Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ The output format is a Markdown file to faciliate the display of the recipe on t

- **Challenge**: Present the application in multiple languages

- **Solution**: The same prompt is utilized, but the LLM is instructed to generate the output in a specific language, catering to the user's language preference (English/French).
- **Solution**: The same prompt is utilized, but the LLM is instructed to generate the output in a specific language, catering to the user's language preference (English, French, Spanish, Italian, Arabic). The UI includes comprehensive translations for all features including allergen warnings, ingredient descriptions, and nutritional information.

**Direct Allergen Detection and Nutritional Analysis**

Expand Down
147 changes: 97 additions & 50 deletions lambda/barcode_product_summary/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lambda/recipe_step_by_step/index.js

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions resources/ui/src/assets/i18n/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ const customTranslations: Record<string, Record<string, string>> = {
ingredients_desc_additive:
"Click on each additive to view AI-generated detailed descriptions",
ingredients_no_additive: "The product does not have additives",
tab_ai_summary: "AI Summary",
tab_ingredients: "Ingredients",
tab_additives: "Additives",
allergen_warning_title: "Allergen Warning",
allergen_warning_message: "This product contains allergens you're sensitive to:",
summary_title: "Summary of ingredients generated by AI",
summary_benefits_title: "Benefits",
summary_disadvantages_title: "Disadvantages",
Expand Down Expand Up @@ -128,6 +133,11 @@ const customTranslations: Record<string, Record<string, string>> = {
ingredients_desc_additive:
"Cliquez sur chaque additif pour voir les descriptions détaillées générées par l'IA",
ingredients_no_additive: "Le produit ne contient pas d'additifs",
tab_ai_summary: "Résumé IA",
tab_ingredients: "Ingrédients",
tab_additives: "Additifs",
allergen_warning_title: "Avertissement Allergène",
allergen_warning_message: "Ce produit contient des allergènes auxquels vous êtes sensible :",
summary_title: "Résumé des ingrédients généré par IA",
summary_benefits_title: "Avantages",
summary_disadvantages_title: "Inconvénients",
Expand Down Expand Up @@ -218,8 +228,13 @@ const customTranslations: Record<string, Record<string, string>> = {
ingredients_desc_ingredient:
"Fai clic su ogni ingrediente per visualizzare le descrizioni dettagliate generate dall’AI",
ingredients_no_additive: "Il prodotto non contiene additivi",
tab_ai_summary: "Riepilogo IA",
tab_ingredients: "Ingredienti",
tab_additives: "Additivi",
ingredients_desc_additive:
"Fai clic su ogni additivo per visualizzare le descrizioni dettagliate generate dall’AI",
allergen_warning_title: "Avviso Allergeni",
allergen_warning_message: "Questo prodotto contiene allergeni a cui sei sensibile:",
summary_title: "Riepilogo degli ingredienti generato dall’AI",
summary_benefits_title: "Benefici",
summary_disadvantages_title: "Svantaggi",
Expand Down Expand Up @@ -311,8 +326,13 @@ const customTranslations: Record<string, Record<string, string>> = {
ingredients_desc_ingredient:
"Haz clic en cada ingrediente para ver descripciones detalladas generadas por IA",
ingredients_no_additive: "El producto no contiene aditivos",
tab_ai_summary: "Resumen IA",
tab_ingredients: "Ingredientes",
tab_additives: "Aditivos",
ingredients_desc_additive:
"Haz clic en cada aditivo para ver descripciones detalladas generadas por IA",
allergen_warning_title: "Advertencia de Alérgenos",
allergen_warning_message: "Este producto contiene alérgenos a los que eres sensible:",
summary_title: "Resumen de ingredientes generados por IA",
summary_benefits_title: "Beneficios",
summary_disadvantages_title: "Desventajas",
Expand Down Expand Up @@ -398,6 +418,11 @@ arabic:{
"ingredients_desc_ingredient": "انقر على كل مكون لعرض الوصف التفصيلي الناتج عن الذكاء الاصطناعي",
"ingredients_desc_additive": "انقر على كل إضافة لعرض الوصف التفصيلي الناتج عن الذكاء الاصطناعي",
"ingredients_no_additive": "المنتج لا يحتوي على إضافات",
"tab_ai_summary": "ملخص الذكاء الاصطناعي",
"tab_ingredients": "المكونات",
"tab_additives": "الإضافات",
"allergen_warning_title": "تحذير من مسببات الحساسية",
"allergen_warning_message": "يحتوي هذا المنتج على مسببات حساسية تؤثر عليك:",
"summary_title": "ملخص المكونات الناتجة عن الذكاء الاصطناعي",
"summary_benefits_title": "الفوائد",
"summary_disadvantages_title": "العيوب",
Expand Down
131 changes: 111 additions & 20 deletions resources/ui/src/pages/components/barcode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Button from "@cloudscape-design/components/button";
import Ingredients from "./barcode_ingredients";
import Badge from "@cloudscape-design/components/badge";
import Link from "@cloudscape-design/components/link";
import Alert from "@cloudscape-design/components/alert";
import {
Box,
Container,
Expand Down Expand Up @@ -43,10 +44,17 @@ const Barcode: React.FC = () => {
const [productCode, setProductCode] = useState("");
const [showScanner, setShowScanner] = useState(false);
const [tempProductCode, setTempProductCode] = useState("");
const [hasPreferences, setHasPreferences] = useState(false);
const currentTranslations = customTranslations[language]; // Get translations for the current language or fallback to English

let html5QrcodeScanner: any;

// Check if user has set preferences
useEffect(() => {
const stored = localStorage.getItem("userPreferences");
setHasPreferences(!!stored);
}, []);

function onScanFailure(error: unknown) {
console.warn(`Code scan error = ${error}`);
}
Expand Down Expand Up @@ -122,7 +130,11 @@ const Barcode: React.FC = () => {
>
<div style={{ textAlign: "center" }}>
{!showScanner && (
<Button variant="primary" onClick={handleButtonClick}>
<Button
variant="primary"
onClick={handleButtonClick}
iconName="search"
>
{currentTranslations["scan_button_label"]}
</Button>
)}
Expand Down Expand Up @@ -153,27 +165,106 @@ const Barcode: React.FC = () => {
</div>

{!showScanner && (
<Box>
<div style={{ textAlign: "left" }}>
<h4>{currentTranslations["scan_main_title"]}</h4>

<SpaceBetween direction="vertical" size="m">
<div>
<p>
<Badge color="green">1</Badge>{" "}
{currentTranslations["scan_label_1"]}{" "}
<Link href="/preference">
{currentTranslations["scan_label_2"]}
</Link>
</p>
<p>
<Badge color="green">2</Badge>{" "}
{currentTranslations["scan_label_3"]}
</p>
<div style={{
background: "white",
borderRadius: "8px",
padding: "20px",
border: "1px solid #e5e7eb",
boxShadow: "0 1px 3px rgba(0,0,0,0.1)"
}}>
{!hasPreferences && (
<Alert
type="warning"
header="Set your preferences first"
>
To get personalized nutritional information, please{" "}
<Link href="/preference">set your preferences</Link> before scanning.
</Alert>
)}

<div style={{
textAlign: "center",
margin: hasPreferences ? "0 0 24px 0" : "16px 0 24px 0"
}}>
<div style={{
fontSize: "48px",
marginBottom: "8px",
opacity: 0.8
}}>
📱
</div>
<h3 style={{
margin: "0 0 8px 0",
fontSize: "18px",
fontWeight: "600",
color: "#1f2937"
}}>
{currentTranslations["scan_main_title"]}
</h3>
<p style={{
margin: 0,
fontSize: "14px",
color: "#6b7280"
}}>
Point your camera at a product barcode
</p>
</div>

<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
<div style={{
display: "flex",
alignItems: "center",
gap: "12px"
}}>
<div style={{
background: "#3b82f6",
color: "white",
width: "24px",
height: "24px",
borderRadius: "50%",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontWeight: "600",
fontSize: "14px",
flexShrink: 0
}}>
1
</div>
<span style={{ fontSize: "15px", lineHeight: "1.5", color: "#374151" }}>
{currentTranslations["scan_label_1"]}{" "}
<Link href="/preference">
{currentTranslations["scan_label_2"]}
</Link>
</span>
</div>

<div style={{
display: "flex",
alignItems: "center",
gap: "12px"
}}>
<div style={{
background: "#3b82f6",
color: "white",
width: "24px",
height: "24px",
borderRadius: "50%",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontWeight: "600",
fontSize: "14px",
flexShrink: 0
}}>
2
</div>
</SpaceBetween>
<span style={{ fontSize: "15px", lineHeight: "1.5", color: "#374151" }}>
{currentTranslations["scan_label_3"]}
</span>
</div>
</div>
</Box>
</div>
)}
<div id="reader"></div>

Expand Down
Loading