From 496d609c5faaffdadcef456de590d1984f0d3aad Mon Sep 17 00:00:00 2001 From: Dominic Wrege Date: Fri, 12 Jul 2024 19:52:49 +0200 Subject: [PATCH] 2.2 build 2, allow multiple price feedbacks --- app.json | 2 +- components/detail/feedbackButton.tsx | 55 +-- components/detail/priceBox.tsx | 19 +- screens/detailView.tsx | 22 +- screens/feedbackView.tsx | 483 +++++++++++++++------------ 5 files changed, 305 insertions(+), 276 deletions(-) diff --git a/app.json b/app.json index f49d5f6..372c400 100755 --- a/app.json +++ b/app.json @@ -14,7 +14,7 @@ }, "assetBundlePatterns": ["**/*"], "ios": { - "buildNumber": "1", + "buildNumber": "2", "supportsTablet": false, "jsEngine": "jsc", "bundleIdentifier": "app.ladefuchs.Ladefuchs", diff --git a/components/detail/feedbackButton.tsx b/components/detail/feedbackButton.tsx index 885fbcf..be3201b 100644 --- a/components/detail/feedbackButton.tsx +++ b/components/detail/feedbackButton.tsx @@ -1,47 +1,17 @@ import React from "react"; -import { SafeAreaView, Text, TouchableOpacity, StyleSheet } from "react-native"; -import { useNavigation } from "@react-navigation/native"; -import { Tariff } from "../../../types/tariff"; -import { TariffCondition } from "../../../types/conditions"; +import { SafeAreaView, Text, TouchableOpacity } from "react-native"; +import { ScaledSheet } from "react-native-size-matters"; +import { colors } from "../../theme"; interface FeedbackButtonProps { - link: string | null | undefined; - tariff: Tariff | null | undefined; - tariffCondition: TariffCondition | null; - operatorName: string; // Füge den Operatornamen hinzu - operatorImageUrl: string; // Füge die OperatorImageUrl hinzu + onPress: () => void; } -export function FeedbackButton({ - link, - tariff, - tariffCondition, - operatorName, - operatorImageUrl, -}: FeedbackButtonProps): JSX.Element { - const navigation = useNavigation(); - - if (!link) { - return <>; - } - - const onPress = () => { - navigation.navigate("Feedback", { - tariff, - tariffCondition, - operatorName, - operatorImageUrl, - }); - }; - +export function FeedbackButton({ onPress }: FeedbackButtonProps): JSX.Element { return ( - - + + {"Preise falsch? Dann sag dem Fuchs Bescheid!"} @@ -49,15 +19,12 @@ export function FeedbackButton({ ); } -const styles = StyleSheet.create({ - button: { - // Add your button styles here - }, +const styles = ScaledSheet.create({ underlinedText: { textDecorationLine: "underline", - color: "grey", + color: colors.ladefuchsGrayTextColor, fontFamily: "Bitter", - fontSize: 15, - lineHeight: 20, + fontSize: "15@s", + lineHeight: "20@s", }, }); diff --git a/components/detail/priceBox.tsx b/components/detail/priceBox.tsx index bd61d84..83b1f85 100644 --- a/components/detail/priceBox.tsx +++ b/components/detail/priceBox.tsx @@ -10,9 +10,11 @@ import { scale } from "react-native-size-matters"; export function PriceBox({ chargeMode, price, + rounded = false, }: { chargeMode: ChargeMode; price: number | null | undefined; + rounded?: boolean; }) { const { formatNumber } = useFormatNumber(); const plugSize = 25; @@ -31,7 +33,12 @@ export function PriceBox({ {plug} - + {formatNumber(price) ?? "—"} @@ -44,12 +51,12 @@ const styles = StyleSheet.create({ priceText: { textAlign: "center", fontWeight: "500", - fontSize: scale(40), + fontSize: scale(38), }, priceContainer: { backgroundColor: colors.ladefuchsLightGrayBackground, - paddingHorizontal: scale(12), - paddingVertical: scale(12), + paddingHorizontal: scale(11), + paddingVertical: scale(11), }, priceHeaderText: { fontSize: scale(24), @@ -57,6 +64,10 @@ const styles = StyleSheet.create({ textAlign: "center", marginRight: scale(4), }, + roundedContainer: { + borderBottomLeftRadius: scale(12), + borderBottomRightRadius: scale(12), + }, priceHeaderContainer: { display: "flex", borderTopLeftRadius: scale(12), diff --git a/screens/detailView.tsx b/screens/detailView.tsx index f124b89..8a0c18e 100644 --- a/screens/detailView.tsx +++ b/screens/detailView.tsx @@ -14,6 +14,7 @@ import { useShallow } from "zustand/react/shallow"; import { ScrollView } from "react-native-gesture-handler"; import { ScaledSheet } from "react-native-size-matters"; import { FeedbackButton } from "../components/detail/feedbackButton"; +import { useNavigation } from "@react-navigation/native"; function findTariffCondition({ tariffConditions, @@ -30,6 +31,8 @@ function findTariffCondition({ } export function DetailScreen({ route }: { route: any }): JSX.Element { + const navigation = useNavigation(); + const [operators, operatorId, tariffConditions] = useAppStore( useShallow((state) => [ state.operators, @@ -89,11 +92,20 @@ export function DetailScreen({ route }: { route: any }): JSX.Element { { + // @ts-ignore + navigation.navigate("Feedback", { + tariff, + acTariffCondition, + dcTariffCondition, + operator, + }); + }} + // link={tariff.affiliateLinkUrl} + // tariff={tariff} + // tariffCondition={dcTariffCondition || acTariffCondition} // Übergebe die relevante Bedingung + // operatorName={operator!.name} // Füge den Operatornamen hinzu + // operatorImageUrl={operator!.imageUrl} // Füge die OperatorImageUrl hinzu /> diff --git a/screens/feedbackView.tsx b/screens/feedbackView.tsx index 2e8159f..f2916c3 100644 --- a/screens/feedbackView.tsx +++ b/screens/feedbackView.tsx @@ -7,253 +7,292 @@ import { colors, styles } from "../theme"; import { DetailLogos } from "../components/detail/detailLogos"; import { LadefuchsButton } from "../components/detail/ladefuchsButton"; import { Tariff } from "../types/tariff"; -import { ChargeMode,TariffCondition } from "../types/conditions"; +import { ChargeMode, TariffCondition } from "../types/conditions"; import { ScaledSheet } from "react-native-size-matters"; import { useFormatNumber } from "../hooks/numberFormat"; import { FeedbackContext, FeedbackRequest } from "../types/feedback"; import { useShallow } from "zustand/react/shallow"; import { useAppStore } from "../state/state"; import { sendFeedback } from "../functions/api"; -import CCS from "@assets/plugs/ccs.svg"; -import Typ2 from "@assets/plugs/typ2.svg"; import { scale } from "react-native-size-matters"; +import { PriceBox } from "../components/detail/priceBox"; +import { Operator } from "../types/operator"; export function FeedbackView(): JSX.Element { - const route = useRoute(); - const navigation = useNavigation(); - const { formatNumber } = useFormatNumber(); + const route = useRoute(); + const navigation = useNavigation(); + const { formatNumber } = useFormatNumber(); - const { tariff, tariffCondition, operatorName, operatorImageUrl, chargeMode } = route.params as { - tariff: Tariff; - tariffCondition: TariffCondition; - operatorName: string; - operatorImageUrl: string | null; - chargeMode: string; - }; + const { tariff, acTariffCondition, dcTariffCondition, operator } = + route.params as { + tariff: Tariff; + acTariffCondition: TariffCondition; + dcTariffCondition: TariffCondition; + operator: Operator; + }; - const { operatorId } = useAppStore(useShallow(state => ({ - operatorId: state.operatorId, - }))); + const { operatorId } = useAppStore( + useShallow((state) => ({ + operatorId: state.operatorId, + })) + ); - const [noteText, setNoteText] = useState(""); - const [currentPrice, setCurrentPrice] = useState(formatNumber(tariffCondition.pricePerKwh)); - const [formInvalid, setFormInvalid] = useState(false); - const [newPrice, setNewPrice] = useState(""); + const [noteText, setNoteText] = useState(""); - useEffect(() => { - setFormInvalid(!currentPrice || !noteText); - }, [currentPrice, newPrice, noteText]); + const [formInvalid, setFormInvalid] = useState(false); + const [acNewPrice, setAcNewPrice] = useState(""); + const [dcNewPrice, setDcNewPrice] = useState(""); - useEffect(() => { - console.log("chargeMode:", chargeMode); // Log chargeMode to check its value -}, [chargeMode]); + useEffect(() => { + setFormInvalid(!noteText); + }, [noteText]); - const createRequestPayload = (): FeedbackRequest => { - const context: FeedbackContext = { - tariffId: tariff.identifier, - operatorId, - }; + const createRequestPayload = (): FeedbackRequest[] => { + const context: FeedbackContext = { + tariffId: tariff.identifier, + operatorId, + }; - if (!newPrice) { - return { - context, - request: { - type: "otherFeedback", - attributes: { notes: noteText }, - }, - }; - } + if (!acNewPrice) { + return [ + { + context, + request: { + type: "otherFeedback", + attributes: { notes: noteText }, + }, + }, + ]; + } + const requests = []; - const displayedPrice = parseFloat(currentPrice) || 0; - const actualPrice = parseFloat(newPrice) || 0; + const actualAcPrice = parseFloat(acNewPrice) || 0; + const actualDcPrice = parseFloat(dcNewPrice) || 0; - return { - context, - request: { - type: "wrongPriceFeedback", - attributes: { - notes: noteText, - displayedPrice, - actualPrice, - }, - }, - }; - }; + const wrongPriceRequest = ({ + displayedPrice, + actualPrice, + }: { + displayedPrice: number; + actualPrice: number; + }) => { + return { + context, + request: { + type: "wrongPriceFeedback", + attributes: { + notes: noteText, + displayedPrice, + actualPrice, + }, + }, + }; + }; - const handleSubmit = async () => { - const request = createRequestPayload(); - await sendFeedback(request); - Alert.alert("Danke für deine Meldung. Wir prüfen unsere Daten.", "", [ - { - text: "OK", - onPress: () => navigation.goBack(), - }, - ]); - }; + if (actualAcPrice) { + requests.push( + wrongPriceRequest({ + displayedPrice: acTariffCondition.pricePerKwh, + actualPrice: actualAcPrice, + }) + ); + } - const maxNoteTextLength = 160; - const remainingCharacters = maxNoteTextLength - noteText.length; + if (actualDcPrice) { + wrongPriceRequest({ + displayedPrice: dcTariffCondition.pricePerKwh, + actualPrice: actualDcPrice, + }); + } + return requests; + }; - const renderPlugIcon = () => { - const plugSize = 25; - const plugOpacity = 0.45; + const handleSubmit = async () => { + for (const request of createRequestPayload()) { + await sendFeedback(request); + } + Alert.alert("Danke für deine Meldung. Wir prüfen unsere Daten.", "", [ + { + text: "OK", + onPress: () => navigation.goBack(), + }, + ]); + }; - return chargeMode === "ac" ? ( - - ) : ( - - ); - }; + const maxNoteTextLength = 160; + const remainingCharacters = maxNoteTextLength - noteText.length; - const renderPriceInput = (label: string, value: string, setValue: (text: string) => void) => ( - - - {label} - {renderPlugIcon()} - - - - - - - - ); + const renderPriceInput = ({ + chargeMode, + currentPrice, + newValue, + setNewValue, + }: { + chargeMode: ChargeMode; + currentPrice: number; + newValue: string; + setNewValue: (text: string) => void; + }) => ( + + + + + + + + ); - return ( - - - - Hast Du Futter für den Fuchs? - - Sag uns was nicht stimmt! - - - - - - {renderPriceInput("AC", currentPrice, setCurrentPrice)} - {renderPriceInput("DC", newPrice, setNewPrice)} - - - - {remainingCharacters} /160 - - - - - - ); + return ( + + + + + Hast Du Futter für den Fuchs? + + + + Sag uns was nicht stimmt! + + + + + + + {renderPriceInput({ + chargeMode: "ac", + currentPrice: acTariffCondition.pricePerKwh, + newValue: acNewPrice, + setNewValue: setAcNewPrice, + })} + {renderPriceInput({ + chargeMode: "dc", + currentPrice: dcTariffCondition.pricePerKwh, + newValue: dcNewPrice, + setNewValue: setDcNewPrice, + })} + + + + + {remainingCharacters} / 160 + + + + + + + ); } const feedbackStyles = ScaledSheet.create({ - noteContainer: { - position: "relative", - }, - noteInput: { - height: "80@s", - borderColor: colors.ladefuchsDarkGrayBackground, - borderWidth: 1, - marginTop: 5, - marginBottom: "10@s", - padding: "10@s", - width: "100%", - alignSelf: "center", - textAlignVertical: "top", - backgroundColor: colors.ladefuchsLightGrayBackground, - borderRadius: "10@s", - }, - charCount: { - position: "absolute", - bottom: 15, - right: 10, - opacity: 0.3, - fontSize: "12@s", - }, - priceBoxesContainer: { - flexDirection: "row", - marginTop: 14, - gap: "16@s", - }, - priceContainer: { - width: "47%", - }, - plugContainer: { - flexDirection: "row", - backgroundColor: colors.ladefuchsDarkGrayBackground, - paddingHorizontal: "60@s", - paddingVertical: "5@s", - borderTopLeftRadius: scale(12), - borderTopRightRadius: scale(12), - paddingLeft: 50, - }, - textInput: { - alignSelf: "center", - fontSize: "17@s", - textAlign: "center", - fontWeight: "800", - }, - priceInput: { - marginBottom: "5@s", - paddingHorizontal: "10@s", - paddingVertical: "8@s", - width: "100%", - alignSelf: "center", - textAlignVertical: "top", - backgroundColor: colors.ladefuchsLightGrayBackground, - borderBottomLeftRadius: scale(12), - borderBottomRightRadius: scale(12), - fontSize: "32@s", - textAlign: "center", - fontWeight: "500", - }, - newpriceInput: { - borderColor: colors.ladefuchsDarkGrayBackground, - borderWidth: 1, - marginBottom: "5@s", - paddingHorizontal: "10@s", - paddingVertical: "8@s", - width: "100%", - alignSelf: "center", - textAlignVertical: "top", - backgroundColor: colors.ladefuchsLightGrayBackground, - borderRadius: scale(12), - fontSize: "32@s", - textAlign: "center", - fontWeight: "500", - }, - arrow: { - justifyContent: "center", - alignItems: "center", - marginBottom: "5@s", - }, + noteContainer: { + position: "relative", + }, + noteInput: { + height: "80@s", + borderColor: colors.ladefuchsDarkGrayBackground, + borderWidth: 1, + marginTop: 5, + marginBottom: "10@s", + padding: "10@s", + width: "100%", + alignSelf: "center", + textAlignVertical: "top", + backgroundColor: colors.ladefuchsLightGrayBackground, + borderRadius: "10@s", + }, + charCount: { + position: "absolute", + bottom: "12@s", + right: "10@s", + opacity: 0.3, + fontSize: "12@s", + }, + priceBoxesContainer: { + flexDirection: "row", + marginTop: "6@s", + gap: "16@s", + }, + priceContainer: { + width: "47%", + }, + priceInput: { + marginBottom: "5@s", + paddingHorizontal: "10@s", + paddingVertical: "8@s", + width: "100%", + alignSelf: "center", + textAlignVertical: "top", + backgroundColor: colors.ladefuchsLightGrayBackground, + borderBottomLeftRadius: scale(12), + borderBottomRightRadius: scale(12), + fontSize: "32@s", + textAlign: "center", + fontWeight: "500", + }, + newPriceInput: { + borderColor: colors.ladefuchsDarkGrayBackground, + borderWidth: 1, + marginBottom: "6@s", + paddingHorizontal: "10@s", + paddingVertical: "6@s", + width: "100%", + alignSelf: "center", + textAlignVertical: "top", + backgroundColor: colors.ladefuchsLightGrayBackground, + borderRadius: scale(12), + fontSize: "34@s", + textAlign: "center", + fontWeight: "500", + }, + arrow: { + justifyContent: "center", + alignItems: "center", + marginTop: "5@s", + marginBottom: "1@s", + }, });