grocery-app/frontend/src/components/manage/ManageStores.jsx
2026-03-28 22:46:53 -07:00

177 lines
6.4 KiB
JavaScript

import { useContext, useEffect, useState } from "react";
import {
addStoreToHousehold,
getAllStores,
removeStoreFromHousehold,
setDefaultStore
} from "../../api/stores";
import StoreAvailableItemsManager from "./StoreAvailableItemsManager";
import { HouseholdContext } from "../../context/HouseholdContext";
import { StoreContext } from "../../context/StoreContext";
import useActionToast from "../../hooks/useActionToast";
import getApiErrorMessage from "../../lib/getApiErrorMessage";
import "../../styles/components/manage/ManageStores.css";
import "../../styles/components/manage/StoreAvailableItemsManager.css";
export default function ManageStores() {
const { activeHousehold } = useContext(HouseholdContext);
const { stores: householdStores, refreshStores } = useContext(StoreContext);
const toast = useActionToast();
const [allStores, setAllStores] = useState([]);
const [loading, setLoading] = useState(true);
const [showAddStore, setShowAddStore] = useState(false);
const isAdmin = ["owner", "admin"].includes(activeHousehold?.role);
useEffect(() => {
loadAllStores();
}, []);
const loadAllStores = async () => {
setLoading(true);
try {
const response = await getAllStores();
setAllStores(response.data);
} catch (error) {
console.error("Failed to load stores:", error);
} finally {
setLoading(false);
}
};
const handleAddStore = async (storeId) => {
const storeName = allStores.find((store) => store.id === storeId)?.name || `store #${storeId}`;
try {
console.log("Adding store with ID:", storeId);
await addStoreToHousehold(activeHousehold.id, storeId, false);
await refreshStores();
toast.success("Added store", `Added store ${storeName}`);
setShowAddStore(false);
} catch (error) {
console.error("Failed to add store:", error);
const message = getApiErrorMessage(error, "Failed to add store");
toast.error("Add store failed", `Add store failed: ${message}`);
}
};
const handleRemoveStore = async (storeId, storeName) => {
if (!confirm(`Remove ${storeName} from this household?`)) return;
try {
await removeStoreFromHousehold(activeHousehold.id, storeId);
await refreshStores();
toast.success("Removed store", `Removed store ${storeName}`);
} catch (error) {
console.error("Failed to remove store:", error);
const message = getApiErrorMessage(error, "Failed to remove store");
toast.error("Remove store failed", `Remove store failed: ${message}`);
}
};
const handleSetDefault = async (storeId) => {
const storeName =
householdStores.find((store) => store.id === storeId)?.name || `store #${storeId}`;
try {
await setDefaultStore(activeHousehold.id, storeId);
await refreshStores();
toast.success("Updated default store", `Default store set to ${storeName}`);
} catch (error) {
console.error("Failed to set default store:", error);
const message = getApiErrorMessage(error, "Failed to set default store");
toast.error("Set default store failed", `Set default store failed: ${message}`);
}
};
const availableStores = allStores.filter(
store => !householdStores.some(hs => hs.id === store.id)
);
return (
<div className="manage-stores">
{/* Current Stores Section */}
<section className="manage-section">
<h2>Your Stores ({householdStores.length})</h2>
{householdStores.length === 0 ? (
<p className="empty-message">No stores added yet.</p>
) : (
<div className="stores-list">
{householdStores.map((store) => (
<div key={store.id} className="store-card">
<div className="store-info">
<h3>{store.name}</h3>
{store.location && <p className="store-location">{store.location}</p>}
</div>
{isAdmin && (
<div className="store-actions">
{!store.is_default && (
<button
onClick={() => handleSetDefault(store.id)}
className="btn-secondary btn-small"
>
Set as Default
</button>
)}
<button
onClick={() => handleRemoveStore(store.id, store.name)}
className="btn-danger btn-small"
disabled={householdStores.length === 1}
title={householdStores.length === 1 ? "Cannot remove last store" : ""}
>
Remove
</button>
</div>
)}
<StoreAvailableItemsManager
householdId={activeHousehold.id}
store={store}
isAdmin={isAdmin}
/>
</div>
))}
</div>
)}
</section>
{/* Add Store Section */}
{isAdmin && (
<section className="manage-section">
<h2>Add Store</h2>
{!showAddStore ? (
<button onClick={() => setShowAddStore(true)} className="btn-primary">
+ Add Store
</button>
) : (
<div className="add-store-panel">
<button onClick={() => setShowAddStore(false)} className="btn-secondary">
Cancel
</button>
{loading ? (
<p>Loading stores...</p>
) : availableStores.length === 0 ? (
<p className="empty-message">All available stores have been added.</p>
) : (
<div className="available-stores">
{availableStores.map((store) => (
<div key={store.id} className="available-store-card">
<div className="store-info">
<h3>{store.name}</h3>
{store.location && <p className="store-location">{store.location}</p>}
</div>
<button
onClick={() => handleAddStore(store.id)}
className="btn-primary btn-small"
>
Add
</button>
</div>
))}
</div>
)}
</div>
)}
</section>
)}
</div>
);
}