import React, { useState, useMemo, useCallback } from 'react'; import { Session } from '@supabase/supabase-js'; import type { ShoppingList, ShoppingListItem } from '../types'; import { UserIcon } from './icons/UserIcon'; import { ListBulletIcon } from './icons/ListBulletIcon'; import { LoadingSpinner } from './LoadingSpinner'; import { TrashIcon } from './icons/TrashIcon'; import { SpeakerWaveIcon } from './icons/SpeakerWaveIcon'; import { generateSpeechFromText } from '../services/geminiService'; import { decode, decodeAudioData } from '../utils/audioUtils'; interface ShoppingListComponentProps { session: Session | null; lists: ShoppingList[]; activeListId: number | null; onSelectList: (listId: number) => void; onCreateList: (name: string) => Promise; onDeleteList: (listId: number) => Promise; onAddItem: (item: { customItemName: string }) => Promise; onUpdateItem: (itemId: number, updates: Partial) => Promise; onRemoveItem: (itemId: number) => Promise; } export const ShoppingListComponent: React.FC = ({ session, lists, activeListId, onSelectList, onCreateList, onDeleteList, onAddItem, onUpdateItem, onRemoveItem }) => { const [isCreatingList, setIsCreatingList] = useState(false); const [customItemName, setCustomItemName] = useState(''); const [isAddingCustom, setIsAddingCustom] = useState(false); const [isReadingAloud, setIsReadingAloud] = useState(false); const activeList = useMemo(() => lists.find(list => list.id === activeListId), [lists, activeListId]); const { neededItems, purchasedItems } = useMemo(() => { if (!activeList) return { neededItems: [], purchasedItems: [] }; const neededItems: ShoppingListItem[] = []; const purchasedItems: ShoppingListItem[] = []; activeList.items.forEach(item => { if (item.is_purchased) { purchasedItems.push(item); } else { neededItems.push(item); } }); return { neededItems, purchasedItems }; }, [activeList]); const handleCreateList = async () => { const name = prompt("Enter a name for your new shopping list:"); if (name && name.trim()) { setIsCreatingList(true); await onCreateList(name.trim()); setIsCreatingList(false); } }; const handleDeleteList = async () => { if (activeList && window.confirm(`Are you sure you want to delete the "${activeList.name}" list? This cannot be undone.`)) { await onDeleteList(activeList.id); } }; const handleAddCustomItem = async (e: React.FormEvent) => { e.preventDefault(); if (!customItemName.trim()) return; setIsAddingCustom(true); await onAddItem({ customItemName: customItemName.trim() }); setCustomItemName(''); setIsAddingCustom(false); }; const handleReadAloud = useCallback(async () => { if (!activeList || neededItems.length === 0) return; setIsReadingAloud(true); try { const listText = "Here is your shopping list: " + neededItems.map(item => item.custom_item_name || item.master_item?.name).join(', '); const base64Audio = await generateSpeechFromText(listText); // Play the audio const audioContext = new (window.AudioContext)({ sampleRate: 24000 }); const audioBuffer = await decodeAudioData(decode(base64Audio), audioContext, 24000, 1); const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.connect(audioContext.destination); source.start(); } catch (e: any) { console.error("Failed to read list aloud:", e); alert(`Could not read list aloud: ${e.message}`); } finally { setIsReadingAloud(false); } }, [activeList, neededItems]); if (!session) { return (

Your Shopping Lists

Please log in to manage your shopping lists.

); } return (

Shopping List

{lists.length > 0 && ( )}
{activeList ? ( <>
setCustomItemName(e.target.value)} placeholder="Add a custom item..." className="flex-grow block w-full px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm sm:text-sm" disabled={isAddingCustom} />
{neededItems.length > 0 ? neededItems.map(item => (
onUpdateItem(item.id, { is_purchased: !item.is_purchased })} className="h-4 w-4 rounded border-gray-300 text-brand-primary focus:ring-brand-secondary" /> {item.custom_item_name || item.master_item?.name}
)) : (

This list is empty.

)} {purchasedItems.length > 0 && (

Purchased

{purchasedItems.map(item => (
onUpdateItem(item.id, { is_purchased: !item.is_purchased })} className="h-4 w-4 rounded border-gray-300 text-brand-primary focus:ring-brand-secondary" /> {item.custom_item_name || item.master_item?.name}
))}
)}
) : (

No shopping lists found. Create one to get started!

)}
); };