fix(streckkod+kvitto): sparad-bekraftelse, fettvarden, kvitto-antal
Streckkod / produktbidrag: - Tydlig bekraftelse 'Sparad i delade katalogen - tack!' visas nu efter att en fotad produkt lasts av, sa man ser att bidraget gick fram (forut bara 'Skanna igen' utan aterkoppling). - Naringsetiketter laser nu ocksa enkelomattat och fleromattat fett (t.ex. olivolja visar tre fettrader). Nya valfria falt monounsaturatedFatG/ polyunsaturatedFatG i NutritionValues + READ_NUTRITION_LABEL + prompt + produktpanelen. Obligatoriska EU-falt oforandrade. Kvitto: - Rader som ar samma vara (samma normaliserade namn + enhet) slas nu ihop till EN vara med ratt antal - '2 x mjolk' pa kvittot blir en vara a 2 st i stallet for tva rader a 1 st. Priser summeras, rabatter dras som forut. En kvittorad raknas som minst 1 exemplar aven om antal saknas. Verifierat: typecheck hela repot gront, nutrition-engine 19/19, ai-contracts 24/24, worker 23/23, api 104/104, samt repro mot testdatabas (2 mjolk-rader -> 1 vara a 2; olivolja sparar fett/mattat/enkel-/fleromattat).
This commit is contained in:
@@ -29,6 +29,8 @@ type Nutrition = {
|
||||
carbsG: number;
|
||||
fatG: number;
|
||||
saturatedFatG: number;
|
||||
monounsaturatedFatG?: number;
|
||||
polyunsaturatedFatG?: number;
|
||||
fiberG: number;
|
||||
sugarG: number;
|
||||
saltG: number;
|
||||
@@ -87,6 +89,7 @@ export default function BarcodeScreen() {
|
||||
const [product, setProduct] = useState<ProductInfo | null>(null);
|
||||
const [unknown, setUnknown] = useState(false);
|
||||
const [contributing, setContributing] = useState(false);
|
||||
const [justContributed, setJustContributed] = useState(false);
|
||||
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
||||
// Synkron lås: hindrar att kamerans upprepade träffar startar parallella uppslag.
|
||||
const locked = useRef(false);
|
||||
@@ -101,6 +104,7 @@ export default function BarcodeScreen() {
|
||||
lastGtin.current = gtin;
|
||||
setBusy(true);
|
||||
setErrorMsg(null);
|
||||
setJustContributed(false);
|
||||
try {
|
||||
const result = await api<BarcodeScanResponse>("/v1/scans", {
|
||||
method: "POST",
|
||||
@@ -177,6 +181,7 @@ export default function BarcodeScreen() {
|
||||
const found = await pollScan(created.scan.id);
|
||||
if (found) {
|
||||
setUnknown(false);
|
||||
setJustContributed(true);
|
||||
setProduct(found);
|
||||
} else {
|
||||
// Behåll nuvarande vy (okänd/produkt) och visa felet som dialog.
|
||||
@@ -197,6 +202,7 @@ export default function BarcodeScreen() {
|
||||
setProduct(null);
|
||||
setUnknown(false);
|
||||
setErrorMsg(null);
|
||||
setJustContributed(false);
|
||||
locked.current = false;
|
||||
lastGtin.current = null;
|
||||
};
|
||||
@@ -248,6 +254,11 @@ export default function BarcodeScreen() {
|
||||
{product && !contributing && (
|
||||
<View style={styles.panel}>
|
||||
<ScrollView contentContainerStyle={{ padding: spacing.lg, paddingBottom: spacing.md }}>
|
||||
{justContributed && (
|
||||
<View style={styles.savedBanner}>
|
||||
<Small style={styles.savedText}>{t("barcode.contributing.saved")}</Small>
|
||||
</View>
|
||||
)}
|
||||
<Heading>{product.name}</Heading>
|
||||
{(product.brand || product.packageSizeValue) && (
|
||||
<Small style={styles.muted}>
|
||||
@@ -269,6 +280,12 @@ export default function BarcodeScreen() {
|
||||
<NutRow label={t("barcode.info.kcal")} value={`${Math.round(n.kcal)} kcal`} strong />
|
||||
<NutRow label={t("barcode.info.fat")} value={fmtG(n.fatG)} />
|
||||
<NutRow label={t("barcode.info.satfat")} value={fmtG(n.saturatedFatG)} sub />
|
||||
{n.monounsaturatedFatG != null && (
|
||||
<NutRow label={t("barcode.info.monofat")} value={fmtG(n.monounsaturatedFatG)} sub />
|
||||
)}
|
||||
{n.polyunsaturatedFatG != null && (
|
||||
<NutRow label={t("barcode.info.polyfat")} value={fmtG(n.polyunsaturatedFatG)} sub />
|
||||
)}
|
||||
<NutRow label={t("barcode.info.carbs")} value={fmtG(n.carbsG)} />
|
||||
<NutRow label={t("barcode.info.sugar")} value={fmtG(n.sugarG)} sub />
|
||||
<NutRow label={t("barcode.info.fiber")} value={fmtG(n.fiberG)} />
|
||||
@@ -426,4 +443,12 @@ const styles = StyleSheet.create({
|
||||
muted: { color: colors.textMuted },
|
||||
strong: { fontWeight: "700" },
|
||||
source: { color: colors.textMuted, fontStyle: "italic" },
|
||||
savedBanner: {
|
||||
backgroundColor: colors.primarySoft,
|
||||
borderRadius: 10,
|
||||
paddingVertical: spacing.xs,
|
||||
paddingHorizontal: spacing.sm,
|
||||
marginBottom: spacing.sm,
|
||||
},
|
||||
savedText: { color: colors.primary, fontWeight: "700" },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user