import { useState } from "react"; import { addLocationToStore, removeLocation, setDefaultLocation, updateLocation, } from "../../api/stores"; import useActionToast from "../../hooks/useActionToast"; import getApiErrorMessage from "../../lib/getApiErrorMessage"; import ConfirmSlideModal from "../modals/ConfirmSlideModal"; function locationLabel(location) { return location.display_name || location.name; } function locationEditName(location) { return location.location_name || location.name || ""; } function LocationSettingsModal({ location, draft, setDraft, canManage, onCancel, onSave, onSetDefault, }) { if (!location) return null; return (
event.stopPropagation()}>

{locationLabel(location)} Settings

Update this location name, notes, or default status.

{canManage ? (
{!location.is_default ? ( ) : null}
) : null}
); } export default function StoreLocationManager({ householdId, storeGroup, allLocationCount, canManage, refreshAfterStoreChange, }) { const toast = useActionToast(); const [isOpen, setIsOpen] = useState(false); const [locationDraft, setLocationDraft] = useState({ name: "", address: "" }); const [deleteMode, setDeleteMode] = useState(false); const [selectedDeleteIds, setSelectedDeleteIds] = useState(() => new Set()); const [pendingDeleteLocations, setPendingDeleteLocations] = useState([]); const [editingLocation, setEditingLocation] = useState(null); const [editingLocationDraft, setEditingLocationDraft] = useState({ name: "", address: "" }); const selectedDeleteLocations = storeGroup.locations.filter((location) => selectedDeleteIds.has(location.id) ); const selectedDeleteCount = selectedDeleteLocations.length; const canConfirmDelete = selectedDeleteCount > 0 && allLocationCount - selectedDeleteCount >= 1; const closeManager = () => { setIsOpen(false); setDeleteMode(false); setSelectedDeleteIds(new Set()); setPendingDeleteLocations([]); setEditingLocation(null); }; const handleAddLocation = async () => { const name = locationDraft.name.trim(); if (!name) return; try { await addLocationToStore(householdId, storeGroup.household_store_id, { name, address: locationDraft.address.trim() || null, }); setLocationDraft({ name: "", address: "" }); await refreshAfterStoreChange(); toast.success("Added location", `Added ${name} to ${storeGroup.name}`); } catch (error) { const message = getApiErrorMessage(error, "Failed to add location"); toast.error("Add location failed", `Add location failed: ${message}`); } }; const openLocationSettings = (location) => { setEditingLocation(location); setEditingLocationDraft({ name: locationEditName(location), address: location.address || "", }); }; const handleSaveLocation = async () => { if (!editingLocation) return; const name = editingLocationDraft.name.trim(); if (!name) return; try { await updateLocation(householdId, editingLocation.id, { name, address: editingLocationDraft.address.trim() || null, }); await refreshAfterStoreChange(); setEditingLocation(null); toast.success("Updated location", `Updated ${name}`); } catch (error) { const message = getApiErrorMessage(error, "Failed to update location"); toast.error("Update location failed", `Update location failed: ${message}`); } }; const handleSetDefault = async () => { if (!editingLocation) return; try { await setDefaultLocation(householdId, editingLocation.id); await refreshAfterStoreChange(); setEditingLocation(null); toast.success("Updated default location", `Default location set to ${locationLabel(editingLocation)}`); } catch (error) { const message = getApiErrorMessage(error, "Failed to set default location"); toast.error("Set default failed", `Set default failed: ${message}`); } }; const toggleLocationSelection = (locationId) => { setSelectedDeleteIds((currentIds) => { const nextIds = new Set(currentIds); if (nextIds.has(locationId)) { nextIds.delete(locationId); } else { nextIds.add(locationId); } return nextIds; }); }; const startDeleteMode = () => { setDeleteMode(true); setSelectedDeleteIds(new Set()); }; const cancelDeleteMode = () => { setDeleteMode(false); setSelectedDeleteIds(new Set()); }; const confirmSelectedDelete = () => { if (!canConfirmDelete) return; setPendingDeleteLocations(selectedDeleteLocations); }; const handleDeleteConfirm = async () => { if (pendingDeleteLocations.length === 0) { return; } try { await Promise.all( pendingDeleteLocations.map((location) => removeLocation(householdId, location.id)) ); const count = pendingDeleteLocations.length; await refreshAfterStoreChange(); setPendingDeleteLocations([]); setDeleteMode(false); setSelectedDeleteIds(new Set()); toast.success( count === 1 ? "Removed location" : "Removed locations", `Removed ${count} ${count === 1 ? "location" : "locations"} from ${storeGroup.name}` ); } catch (error) { const message = getApiErrorMessage(error, "Failed to remove locations"); toast.error("Remove locations failed", `Remove locations failed: ${message}`); } }; return ( <> {isOpen ? (
event.stopPropagation()}>

{storeGroup.name} Locations

Manage locations, defaults, and location notes for this store.

{canManage ? (
setLocationDraft((current) => ({ ...current, name: event.target.value })) } placeholder="Location name" /> setLocationDraft((current) => ({ ...current, address: event.target.value })) } placeholder="Address or notes" />
) : null} {canManage && storeGroup.locations.length > 0 ? (
{deleteMode ? ( ) : null}
) : null}
{storeGroup.locations.map((location) => { const isSelectedForDelete = selectedDeleteIds.has(location.id); return ( ); })}
) : null} setEditingLocation(null)} onSave={handleSaveLocation} onSetDefault={handleSetDefault} /> 0} title={ pendingDeleteLocations.length === 1 ? `Delete ${locationLabel(pendingDeleteLocations[0])}?` : `Delete ${pendingDeleteLocations.length} locations?` } description={ pendingDeleteLocations.length > 0 ? `Slide to confirm. This removes ${pendingDeleteLocations.length === 1 ? locationLabel(pendingDeleteLocations[0]) : `${pendingDeleteLocations.length} locations`} from this household.` : "" } confirmLabel={pendingDeleteLocations.length === 1 ? "Delete Location" : "Delete Locations"} onClose={() => setPendingDeleteLocations([])} onConfirm={handleDeleteConfirm} /> ); }