import { useState, useEffect } from "react"; import AutocompleteInput from "./AutocompleteInput"; import { getGroceryLists, createGroceryList, updateGroceryList, deleteGroceryList, shareGroceryList, getGroceryListShares, unshareGroceryList, searchUsers, togglePinGroceryList, updateSharePermission, } from "../groceryApi"; function GroceryLists({ user, onShowToast, selectedListIdFromNotification, onListSelected }) { const [lists, setLists] = useState([]); const [selectedList, setSelectedList] = useState(null); const [loading, setLoading] = useState(true); const [editingList, setEditingList] = useState(null); const [showShareModal, setShowShareModal] = useState(null); const [shares, setShares] = useState([]); const [userSearch, setUserSearch] = useState(""); const [searchResults, setSearchResults] = useState([]); const [allUsers, setAllUsers] = useState([]); const [sharePermission, setSharePermission] = useState(false); // New list form const [newListName, setNewListName] = useState(""); const [showNewListForm, setShowNewListForm] = useState(false); // Edit form const [editName, setEditName] = useState(""); const [editItems, setEditItems] = useState([]); const [newItem, setNewItem] = useState(""); // Extract unique items from all lists for autocomplete const uniqueItems = Array.from( new Set( lists.flatMap(list => list.items.map(item => item.startsWith("✓ ") ? item.substring(2) : item) ).filter(Boolean) ) ).sort(); useEffect(() => { loadLists(); }, []); // Handle list selection from notification useEffect(() => { if (selectedListIdFromNotification && lists.length > 0) { const listToSelect = lists.find(list => list.id === selectedListIdFromNotification); if (listToSelect) { setSelectedList(listToSelect); onListSelected?.(); } } }, [selectedListIdFromNotification, lists, onListSelected]); // Restore selected list from localStorage after lists are loaded useEffect(() => { if (lists.length > 0 && !selectedListIdFromNotification) { try { const savedListId = localStorage.getItem("selectedGroceryListId"); if (savedListId) { const listToSelect = lists.find(list => list.id === parseInt(savedListId)); if (listToSelect) { setSelectedList(listToSelect); } } } catch (err) { console.error("Failed to restore selected list", err); } } }, [lists, selectedListIdFromNotification]); const loadLists = async () => { try { setLoading(true); const data = await getGroceryLists(); setLists(data); } catch (error) { onShowToast(error.message, "error"); } finally { setLoading(false); } }; const handleCreateList = async (e) => { e.preventDefault(); if (!newListName.trim()) return; try { const newList = await createGroceryList({ name: newListName.trim(), items: [], }); setLists([newList, ...lists]); setNewListName(""); setShowNewListForm(false); onShowToast("רשימת קניות נוצרה בהצלחה", "success"); } catch (error) { onShowToast(error.message, "error"); } }; const handleSelectList = (list) => { setSelectedList(list); setEditingList(null); try { localStorage.setItem("selectedGroceryListId", list.id.toString()); } catch (err) { console.error("Failed to save selected list", err); } }; const handleEditList = (list) => { setEditingList(list); setEditName(list.name); setEditItems([...list.items]); setNewItem(""); }; const handleAddItem = () => { if (!newItem.trim()) return; setEditItems([...editItems, newItem.trim()]); setNewItem(""); }; const handleRemoveItem = (index) => { setEditItems(editItems.filter((_, i) => i !== index)); }; const handleToggleItem = (index) => { const updated = [...editItems]; const item = updated[index]; if (item.startsWith("✓ ")) { updated[index] = item.substring(2); } else { updated[index] = "✓ " + item; } setEditItems(updated); }; const handleToggleItemInView = async (index) => { if (!selectedList || !selectedList.can_edit) return; const updated = [...selectedList.items]; const item = updated[index]; if (item.startsWith("✓ ")) { updated[index] = item.substring(2); } else { updated[index] = "✓ " + item; } try { const updatedList = await updateGroceryList(selectedList.id, { items: updated, }); setLists(lists.map((l) => (l.id === updatedList.id ? updatedList : l))); setSelectedList(updatedList); } catch (error) { onShowToast(error.message, "error"); } }; const handleSaveList = async () => { if (!editName.trim()) { onShowToast("שם הרשימה לא יכול להיות ריק", "error"); return; } try { const updated = await updateGroceryList(editingList.id, { name: editName.trim(), items: editItems, }); setLists(lists.map((l) => (l.id === updated.id ? updated : l))); if (selectedList?.id === updated.id) { setSelectedList(updated); } setEditingList(null); onShowToast("רשימת קניות עודכנה בהצלחה", "success"); } catch (error) { onShowToast(error.message, "error"); } }; const handleDeleteList = async (listId) => { if (!confirm("האם אתה בטוח שברצונך למחוק רשימת קניות זו?")) return; try { await deleteGroceryList(listId); setLists(lists.filter((l) => l.id !== listId)); if (selectedList?.id === listId) { setSelectedList(null); } setEditingList(null); onShowToast("רשימת קניות נמחקה בהצלחה", "success"); } catch (error) { onShowToast(error.message, "error"); } }; const handleTogglePin = async (list) => { try { const updated = await togglePinGroceryList(list.id); setLists(lists.map((l) => (l.id === updated.id ? updated : l))); if (selectedList?.id === updated.id) { setSelectedList(updated); } const message = updated.is_pinned ? "רשימה הוצמדה לדף הבית" : "רשימה הוסרה מדף הבית"; onShowToast(message, "success"); } catch (error) { onShowToast(error.message, "error"); } }; const handleShowShareModal = async (list) => { setShowShareModal(list); setUserSearch(""); setSearchResults([]); setSharePermission(false); try { // Load shares for this list const sharesData = await getGroceryListShares(list.id); setShares(sharesData); // Load all users (use a space to bypass minimum length requirement) const users = await searchUsers(" "); // Sort users: recent shares first (those in sharesData), then others alphabetically const sharedUserIds = new Set(sharesData.map(s => s.shared_with_user_id)); const recentUsers = users.filter(u => sharedUserIds.has(u.id)); const otherUsers = users.filter(u => !sharedUserIds.has(u.id)); const sortedUsers = [ ...recentUsers.sort((a, b) => a.display_name.localeCompare(b.display_name)), ...otherUsers.sort((a, b) => a.display_name.localeCompare(b.display_name)) ]; setAllUsers(sortedUsers); setSearchResults(sortedUsers); } catch (error) { console.error("Failed to load users:", error); onShowToast("לא הצלחנו לטעון את רשימת המשתמשים", "error"); } }; const handleSearchUsers = async (query) => { setUserSearch(query); if (query.trim().length === 0) { // Show all users when search is empty setSearchResults(allUsers); return; } // Filter from all users const filtered = allUsers.filter(user => user.display_name.toLowerCase().includes(query.toLowerCase()) || user.username.toLowerCase().includes(query.toLowerCase()) ); setSearchResults(filtered); }; const handleShareWithUser = async (userId, username) => { try { const share = await shareGroceryList(showShareModal.id, { user_identifier: username, can_edit: sharePermission, }); setShares([...shares, share]); setUserSearch(""); setSearchResults([]); setSharePermission(false); onShowToast(`רשימה שותפה עם ${share.display_name}`, "success"); } catch (error) { onShowToast(error.message, "error"); } }; const handleUnshare = async (userId) => { try { await unshareGroceryList(showShareModal.id, userId); setShares(shares.filter((s) => s.shared_with_user_id !== userId)); onShowToast("שיתוף הוסר בהצלחה", "success"); } catch (error) { onShowToast(error.message, "error"); } }; const handleTogglePermission = async (userId, currentCanEdit) => { try { const updatedShare = await updateSharePermission(showShareModal.id, userId, !currentCanEdit); // Update the shares list with the new permission setShares(shares.map((s) => s.shared_with_user_id === userId ? { ...s, can_edit: updatedShare.can_edit } : s )); const message = updatedShare.can_edit ? "הרשאת עריכה ניתנה" : "הרשאת עריכה הוסרה"; onShowToast(message, "success"); } catch (error) { onShowToast(error.message, "error"); } }; if (loading) { return
אין רשימות קניות עדיין
) : ( lists.map((list) => ({list.is_owner ? "שלי" : `של ${list.owner_display_name}`} {" · "} {list.items.length} פריטים
{selectedList.is_owner ? "רשימה שלי" : `משותפת על ידי ${selectedList.owner_display_name}`}
אין פריטים ברשימה
) : (בחר רשימת קניות כדי להציג את הפרטים
הרשימה לא משותפת עם אף אחד
) : (