Diet Tracker

import React, { useState, useEffect, useRef } from ‘react’; import { Plus, Trash2, Camera, ShoppingCart, Utensils, History, ChevronRight, Loader2, Scale, Zap, Flame, Search, CheckCircle2, AlertCircle } from ‘lucide-react’; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from ‘recharts’; // — Configuration & API Setup — const apiKey = “”; // Managed by environment const GEMINI_MODEL = “gemini-2.5-flash-preview-09-2025”; // — Utility Functions — const fetchGemini = async (prompt, imageBase64 = null) => { const url = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${apiKey}`; const payload = { contents: [{ parts: [ { text: prompt }, …(imageBase64 ? [{ inlineData: { mimeType: “image/png”, data: imageBase64 } }] : []) ] }] }; let delay = 1000; for (let i = 0; i < 5; i++) { try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) throw new Error('API request failed'); const data = await response.json(); return data.candidates?.[0]?.content?.parts?.[0]?.text; } catch (err) { if (i === 4) throw err; await new Promise(res => setTimeout(res, delay)); delay *= 2; } } }; const App = () => { // — State — const [activeTab, setActiveTab] = useState(‘dashboard’); const [inventory, setInventory] = useState(() => JSON.parse(localStorage.getItem(‘dt_inventory’) || ‘[]’)); const [entries, setEntries] = useState(() => JSON.parse(localStorage.getItem(‘dt_entries’) || ‘[]’)); const [isScanning, setIsScanning] = useState(false); const [aiLoading, setAiLoading] = useState(false); const [error, setError] = useState(null); // Persistence useEffect(() => { localStorage.setItem(‘dt_inventory’, JSON.stringify(inventory)); }, [inventory]); useEffect(() => { localStorage.setItem(‘dt_entries’, JSON.stringify(entries)); }, [entries]); // — Actions — const addInventoryItem = (item) => { setInventory(prev => […prev, { …item, id: Date.now(), dateAdded: new Date().toISOString() }]); }; const removeInventoryItem = (id) => { setInventory(prev => prev.filter(item => item.id !== id)); }; const logMeal = (entry) => { setEntries(prev => […prev, { …entry, id: Date.now() }]); }; const deleteEntry = (id) => { setEntries(prev => prev.filter(e => e.id !== id)); }; // — Receipt Scanning Logic — const handleFileUpload = async (e) => { const file = e.target.files[0]; if (!file) return; setAiLoading(true); setError(null); const reader = new FileReader(); reader.onloadend = async () => { const base64Data = reader.result.split(‘,’)[1]; const prompt = ` Analyze this receipt or grocery list. Return a JSON array of objects representing food items. Focus on Pescatarian, High-Protein, Low-Carb dietary goals. For each item, provide: – “name”: string – “quantity”: string (e.g., “500g”, “1 pack”) – “protein”: number (estimated grams per serving) – “carbs”: number (estimated grams per serving) – “fat”: number (estimated grams per serving) – “calories”: number (estimated total) – “category”: one of [“Fridge”, “Pantry”, “Produce”, “Seafood”] Strict JSON only, no markdown markers. `; try { const result = await fetchGemini(prompt, base64Data); const cleanedResult = result.replace(/“`json|“`/g, “”).trim(); const parsedItems = JSON.parse(cleanedResult); parsedItems.forEach(item => addInventoryItem(item)); setActiveTab(‘inventory’); } catch (err) { setError(“Failed to process image. Please try again with a clearer photo.”); console.error(err); } finally { setAiLoading(false); } }; reader.readAsDataURL(file); }; // — Derived Data for Charts — const chartData = entries.reduce((acc, entry) => { const date = entry.date; const existing = acc.find(d => d.date === date); if (existing) { existing.protein += Number(entry.protein || 0); existing.carbs += Number(entry.carbs || 0); existing.calories += Number(entry.calories || 0); } else { acc.push({ date, protein: Number(entry.protein || 0), carbs: Number(entry.carbs || 0), calories: Number(entry.calories || 0) }); } return acc; }, []).sort((a, b) => new Date(a.date) – new Date(b.date)).slice(-7); // — UI Components — const Navbar = () => (
{[ { id: ‘dashboard’, icon: Zap, label: ‘Dash’ }, { id: ‘inventory’, icon: ShoppingCart, label: ‘Pantry’ }, { id: ‘log’, icon: Utensils, label: ‘Meals’ }, { id: ‘receipt’, icon: Camera, label: ‘Scan’ } ].map(tab => ( ))}
); return (
{/* Header */}

Diet Intelligence

Pescatarian • High Protein • Low Carb

{error && (
{error}
)} {/* Tab Content */} {activeTab === ‘dashboard’ && (
{/* Quick Stats */}

Items

{inventory.length}

Protein Avg

{chartData.length ? (chartData.reduce((a,b) => a+b.protein, 0)/chartData.length).toFixed(0) : 0}g

Today’s Carbs

{entries.filter(e => e.date === new Date().toISOString().split(‘T’)[0]).reduce((a,b) => a+b.carbs, 0).toFixed(0)}g

{/* Chart */}

7-Day Macronutrient Trend

{/* AI Suggestion Section */}

Smart Suggestions

{inventory.length > 0 ? (

Based on your {inventory.length} pantry items, you could make:

    {inventory.slice(0, 2).map((item, i) => (
  • {item.name.includes(‘Salmon’) ? ‘Grilled Salmon with Greens’ : `High-Protein ${item.name} Bowl`}
  • ))}
) : (

Scan a grocery receipt to get personalized meal suggestions!

)}
)} {activeTab === ‘inventory’ && (

Your Pantry

{inventory.length === 0 && (

Inventory is empty

)} {inventory.map((item) => (
{item.name.charAt(0)}

{item.name}

{item.quantity} • {item.category}

Protein

{item.protein || 0}g

))}
)} {activeTab === ‘log’ && (

Log a Meal

{ e.preventDefault(); const formData = new FormData(e.target); logMeal({ date: formData.get(‘date’), food: formData.get(‘food’), protein: formData.get(‘protein’), carbs: formData.get(‘carbs’), calories: formData.get(‘calories’) }); e.target.reset(); }} className=”space-y-4″>

Recent Logs

{[…entries].reverse().map(entry => (

{entry.food}

{entry.date}

P: {entry.protein}g C: {entry.carbs}g
))}
)} {activeTab === ‘receipt’ && (
{aiLoading ? ( ) : ( )} {aiLoading && (
AI SCANNING…
)}

Receipt Scanner

Upload a photo of your receipt to automatically add items and nutrition info to your pantry.

Supports Walmart, Whole Foods, Instacart & More

)}
); }; export default App;