Skip to content

Commit

Permalink
Show data from OFF (#1089)
Browse files Browse the repository at this point in the history
* wip

* vite config

* show data
  • Loading branch information
alexfauquette authored Dec 6, 2024
1 parent acbc03a commit c53b81d
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 109 deletions.
52 changes: 37 additions & 15 deletions src/pages/nutrition/NutrimentCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,24 @@ interface NutrimentCellProps {
tabIndex: number;
value?: string;
unit?: string;
productValue?: number;
productUnit?: string;
displayOFFValue: boolean;
setValues: (object) => void;
}

export const NutrimentCell = (props: NutrimentCellProps) => {
const { nutrimentId, nutrimentKey, tabIndex, value, unit, setValues } = props;
const {
nutrimentId,
nutrimentKey,
tabIndex,
value,
unit,
setValues,
productValue,
productUnit,
displayOFFValue,
} = props;

return (
<td
Expand All @@ -34,20 +47,29 @@ export const NutrimentCell = (props: NutrimentCellProps) => {
element.classList.remove("focused");
}}
>
<input
style={{ marginRight: 4, maxWidth: 100 }}
value={value ?? ""}
tabIndex={tabIndex}
onChange={(event) =>
setValues((p) => ({
...p,
[nutrimentKey]: {
...p[nutrimentKey],
value: event.target.value,
},
}))
}
/>
<div style={{ display: "inline-table" }}>
<input
style={{ marginRight: 4, maxWidth: 80 }}
value={value ?? ""}
tabIndex={tabIndex}
onChange={(event) =>
setValues((p) => ({
...p,
[nutrimentKey]: {
...p[nutrimentKey],
value: event.target.value,
},
}))
}
/>
<br />
{displayOFFValue && (
<legend style={{ fontSize: 13, textAlign: "end" }}>
{productValue}
{productUnit}
</legend>
)}
</div>

{isValidUnit(unit) ? (
<select
Expand Down
267 changes: 175 additions & 92 deletions src/pages/nutrition/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import {
TransformComponent,
TransformWrapper,
} from "react-zoom-pan-pinch";
import { Box, Button } from "@mui/material";
import { Box, Button, Checkbox, FormControlLabel } from "@mui/material";
import Stack from "@mui/material/Stack";
import {
deleteRobotoff,
getImageId,
NUTRIMENTS,
postRobotoff,
skipRobotoff,
Expand All @@ -21,7 +22,13 @@ import LinksToProduct from "./LinksToProduct";
import { NutrimentCell } from "./NutrimentCell";

export default function Nutrition() {
const { isLoading, insight, nextItem, count } = useRobotoffPredicitions();
const [partiallyFilled, setPartiallyFilled] = React.useState(false);
const [displayOFFValue, setDisplayOFFValue] = React.useState(false);
const handlePartiallyFilled = (_, checked) => setPartiallyFilled(checked);
const handleDisplayOFFValue = (_, checked) => setDisplayOFFValue(checked);

const { isLoading, insight, nextItem, count, product } =
useRobotoffPredicitions(partiallyFilled);

const [values, setValues] = React.useState<
Record<string, Pick<NutrimentPrediction, "value" | "unit">>
Expand Down Expand Up @@ -67,11 +74,29 @@ export default function Nutrition() {
}

const nutrimentsDetected = structurePredictions(values);

const imageId = getImageId(insight.source_image);

const imageTimestamp = product?.images?.[imageId]?.uploaded_t;

return (
<React.Suspense>
<ErrorBoundary>
<Stack direction="row">
<Box sx={{ width: "50%" }}>
<p>
Photo upload:{" "}
{imageTimestamp
? new Date(imageTimestamp * 1000).toLocaleDateString(
undefined,
{
day: "2-digit",
month: "long",
year: "numeric",
},
)
: "..."}
</p>
<TransformWrapper limitToBounds={false} ref={apiRef}>
<TransformComponent>
<img
Expand All @@ -87,6 +112,27 @@ export default function Nutrition() {
</TransformWrapper>
</Box>
<Stack direction="column" sx={{ width: "50%", p: 2 }}>
<Box>
<FormControlLabel
control={
<Checkbox
checked={partiallyFilled}
onChange={handlePartiallyFilled}
/>
}
label="Tableau partielement rempli"
/>
<FormControlLabel
disabled={!partiallyFilled}
control={
<Checkbox
checked={partiallyFilled ? displayOFFValue : false}
onChange={handleDisplayOFFValue}
/>
}
label="afficher le valeurs OFF"
/>
</Box>
<LinksToProduct
barcode={insight.barcode}
count={count}
Expand All @@ -96,106 +142,143 @@ export default function Nutrition() {
<Box
sx={(theme) => ({
width: "fit-content",
"& tr": { verticalAlign: "top" },
"& .focused": {
backgroundColor: theme.palette.divider,
fontWeight: "bold",
},
})}
>
<table>
<tr>
<td>Nutriments</td>
<td>100g</td>
<td>
serving{" "}
<input
tabIndex={2}
value={insight.data.nutrients?.serving_size?.value ?? ""}
style={{ maxWidth: 100 }}
/>
</td>
</tr>
{nutrimentsDetected.map((nutrimentId) => {
const key100g = `${nutrimentId}_100g`;
const { value: value100g, unit: unit100g } =
values[key100g] ?? {};
<thead>
<tr>
<td>Nutriments</td>
<td>100g</td>
<td>
serving{" "}
<div style={{ display: "inline-table" }}>
<input
tabIndex={2}
value={
insight.data.nutrients?.serving_size?.value ?? ""
}
onChange={(event) =>
setValues((p) => ({
...p,
serving_size: {
...p.serving_size,
value: event.target.value,
},
}))
}
style={{ width: 100 }}
/>
<br />
{displayOFFValue && (
<legend style={{ fontSize: 13, textAlign: "end" }}>
{product?.serving_size}
</legend>
)}
</div>
</td>
</tr>
</thead>
<tbody>
{nutrimentsDetected.map((nutrimentId) => {
const key100g = `${nutrimentId}_100g`;
const { value: value100g, unit: unit100g } =
values[key100g] ?? {};

const keyServing = `${nutrimentId}_serving`;
const { value: valueServing, unit: unitServing } =
values[keyServing] ?? {};

const keyServing = `${nutrimentId}_serving`;
const { value: valueServing, unit: unitServing } =
values[keyServing] ?? {};
const product100g = product?.nutriments?.[key100g];
const productServing = product?.nutriments?.[keyServing];
const productUnit =
product?.nutriments?.[`${nutrimentId}_unit`];

return (
<tr
key={nutrimentId}
// Attributes used to highlight when focusing
data-label-id={nutrimentId}
>
<td style={{ paddingLeft: 10, paddingRight: 4 }}>
{NUTRIMENTS[nutrimentId] ?? nutrimentId}
</td>
<NutrimentCell
return (
<tr
key={nutrimentId}
// Attributes used to highlight when focusing
data-label-id={nutrimentId}
>
<td style={{ paddingLeft: 10, paddingRight: 4 }}>
{NUTRIMENTS[nutrimentId] ?? nutrimentId}
</td>
<NutrimentCell
tabIndex={1}
nutrimentId={nutrimentId}
nutrimentKey={key100g}
value={value100g}
unit={unit100g}
setValues={setValues}
productValue={product100g}
productUnit={productUnit}
displayOFFValue={displayOFFValue}
/>
<NutrimentCell
tabIndex={2}
nutrimentId={nutrimentId}
nutrimentKey={keyServing}
value={valueServing}
unit={unitServing}
setValues={setValues}
productValue={productServing}
productUnit={productUnit}
displayOFFValue={displayOFFValue}
/>
</tr>
);
})}
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<Button
tabIndex={1}
nutrimentId={nutrimentId}
nutrimentKey={key100g}
value={value100g}
unit={unit100g}
setValues={setValues}
/>
<NutrimentCell
variant="contained"
color="success"
sx={{
ml: 1,
mt: 2,
}}
onClick={() => {
postRobotoff({
insightId: insight.id,
data: values,
type: "100g",
});
nextItem();
apiRef.current.resetTransform();
}}
>
Valider (100g)
</Button>
</td>
<td>
<Button
tabIndex={2}
nutrimentId={nutrimentId}
nutrimentKey={keyServing}
value={valueServing}
unit={unitServing}
setValues={setValues}
/>
</tr>
);
})}

<tr>
<td></td>
<td>
<Button
tabIndex={1}
variant="contained"
color="success"
sx={{
ml: 1,
mt: 2,
}}
onClick={() => {
postRobotoff({
insightId: insight.id,
data: values,
type: "100g",
});
nextItem();
apiRef.current.resetTransform();
}}
>
Valider (100g)
</Button>
</td>
<td>
<Button
tabIndex={2}
variant="contained"
color="success"
sx={{ ml: 1, mt: 2 }}
onClick={() => {
postRobotoff({
insightId: insight.id,
data: values,
type: "serving",
});
nextItem();
apiRef.current.resetTransform();
}}
>
Valider (serving)
</Button>
</td>
</tr>
variant="contained"
color="success"
sx={{ ml: 1, mt: 2 }}
onClick={() => {
postRobotoff({
insightId: insight.id,
data: values,
type: "serving",
});
nextItem();
apiRef.current.resetTransform();
}}
>
Valider (serving)
</Button>
</td>
</tr>
</tfoot>
</table>
</Box>

Expand Down
Loading

0 comments on commit c53b81d

Please sign in to comment.