import { useContext, useMemo, useState } from "react"; import { createHouseholdStore } from "../../api/stores"; import { HouseholdContext } from "../../context/HouseholdContext"; import { StoreContext } from "../../context/StoreContext"; import useActionToast from "../../hooks/useActionToast"; import getApiErrorMessage from "../../lib/getApiErrorMessage"; import StoreAvailableItemsManager from "./StoreAvailableItemsManager"; import StoreLocationManager from "./StoreLocationManager"; import StoreZoneManager from "./StoreZoneManager"; import "../../styles/components/manage/StoreAvailableItemsManager.css"; import "../../styles/components/manage/ManageStores.css"; function groupLocationsByStore(locations) { const grouped = new Map(); for (const location of locations) { const key = location.household_store_id; if (!grouped.has(key)) { grouped.set(key, { household_store_id: location.household_store_id, name: location.name, locations: [], }); } grouped.get(key).locations.push(location); } return Array.from(grouped.values()).sort((a, b) => a.name.localeCompare(b.name)); } function locationLabel(location) { return location.display_name || location.name; } export default function ManageStores() { const { activeHousehold } = useContext(HouseholdContext); const { activeStore, stores: householdStores, refreshStores, refreshZones, } = useContext(StoreContext); const toast = useActionToast(); const [createForm, setCreateForm] = useState({ name: "", location_name: "", address: "", }); const [saving, setSaving] = useState(false); const isAdmin = ["owner", "admin"].includes(activeHousehold?.role); const groupedStores = useMemo( () => groupLocationsByStore(householdStores), [householdStores] ); const refreshAfterStoreChange = async () => { await refreshStores(); await refreshZones(); }; const handleCreateStore = async (event) => { event.preventDefault(); if (!createForm.name.trim()) return; setSaving(true); try { await createHouseholdStore(activeHousehold.id, { name: createForm.name.trim(), location_name: createForm.location_name.trim() || "Default Location", address: createForm.address.trim() || null, }); setCreateForm({ name: "", location_name: "", address: "" }); await refreshAfterStoreChange(); toast.success("Created store", `Created store ${createForm.name.trim()}`); } catch (error) { const message = getApiErrorMessage(error, "Failed to create store"); toast.error("Create store failed", `Create store failed: ${message}`); } finally { setSaving(false); } }; return (

Store Locations ({householdStores.length})

Stores are private to this household. Locations define map-specific zones, item placement, and shopping order.

{householdStores.length === 0 ? (

No store locations added yet.

) : (
{groupedStores.map((storeGroup) => (

{storeGroup.name}

{storeGroup.locations.map((location) => { const label = locationLabel(location); const showLocationName = storeGroup.locations.length > 1 || label !== storeGroup.name; return (
{showLocationName ? {label} : null} {location.address ? (

{location.address}

) : null} {location.is_default ? (

Default location

) : null}
); })}
))}
)}
{isAdmin ? (

Add Store

setCreateForm((current) => ({ ...current, name: event.target.value }))} placeholder="Store name, e.g. Costco" required /> setCreateForm((current) => ({ ...current, location_name: event.target.value })) } placeholder="Location name, e.g. Fontana" /> setCreateForm((current) => ({ ...current, address: event.target.value }))} placeholder="Address or notes" />
) : activeStore ? (

Household members can manage item defaults. Only owners and admins can manage stores, locations, zones, and item deletion.

) : null}
); }