Files
flyer-crawler.projectium.com/src/layouts/MainLayout.tsx

163 lines
5.5 KiB
TypeScript

// src/layouts/MainLayout.tsx
import React, { useCallback } from 'react';
import { Outlet } from 'react-router-dom';
import { useAuth } from '../hooks/useAuth';
import { useFlyers } from '../hooks/useFlyers';
import { useShoppingLists } from '../hooks/useShoppingLists';
import { useMasterItems } from '../hooks/useMasterItems';
import { useWatchedItems } from '../hooks/useWatchedItems';
import { useActiveDeals } from '../hooks/useActiveDeals';
import { FlyerList } from '../features/flyer/FlyerList';
import { FlyerUploader } from '../features/flyer/FlyerUploader';
import { ShoppingListComponent } from '../features/shopping/ShoppingList';
import { WatchedItemsList } from '../features/shopping/WatchedItemsList';
import { PriceChart } from '../features/charts/PriceChart';
import { PriceHistoryChart } from '../features/charts/PriceHistoryChart';
import Leaderboard from '../components/Leaderboard';
import { ActivityLog, ActivityLogClickHandler } from '../pages/admin/ActivityLog';
import { AnonymousUserBanner } from '../components/AnonymousUserBanner';
import { ErrorDisplay } from '../components/ErrorDisplay';
export interface MainLayoutProps {
onFlyerSelect: (flyer: import('../types').Flyer) => void;
selectedFlyerId: number | null;
onOpenProfile: () => void;
}
export const MainLayout: React.FC<MainLayoutProps> = ({
onFlyerSelect,
selectedFlyerId,
onOpenProfile,
}) => {
const { userProfile, authStatus } = useAuth();
const user = userProfile?.user ?? null;
const { flyers, refetchFlyers, flyersError } = useFlyers();
const { masterItems, error: masterItemsError } = useMasterItems();
const {
shoppingLists,
activeListId,
setActiveListId,
createList,
deleteList,
addItemToList,
updateItemInList,
removeItemFromList,
error: shoppingListError,
} = useShoppingLists();
const {
watchedItems,
addWatchedItem,
removeWatchedItem,
error: watchedItemsError,
} = useWatchedItems();
const { totalActiveItems, error: activeDealsError } = useActiveDeals();
const handleActivityLogClick: ActivityLogClickHandler = useCallback(
(log) => {
if (log.action === 'list_shared') {
const listId = log.details.shopping_list_id;
if (shoppingLists.some((list) => list.shopping_list_id === listId)) {
setActiveListId(listId);
}
}
},
[shoppingLists, setActiveListId],
);
const handleAddItemToShoppingList = useCallback(
async (item: { masterItemId?: number; customItemName?: string }) => {
if (activeListId) {
await addItemToList(activeListId, item);
}
},
[activeListId, addItemToList],
);
const handleAddItemFromWatchedList = useCallback(
(masterItemId: number) => {
if (activeListId) {
addItemToList(activeListId, { masterItemId });
}
},
[activeListId, addItemToList],
);
// Consolidate error states into a single variable for cleaner display logic.
const combinedError =
flyersError?.message ||
masterItemsError ||
shoppingListError ||
watchedItemsError ||
activeDealsError;
return (
<main className="max-w-screen-2xl mx-auto py-4 px-2.5 sm:py-6 lg:py-8">
{authStatus === 'SIGNED_OUT' && flyers.length > 0 && (
<div className="max-w-5xl mx-auto mb-6 px-4 lg:px-0">
{' '}
{/* This div was missing a closing tag in the original code, but it's outside the diff scope. */}
<AnonymousUserBanner onOpenProfile={onOpenProfile} />
</div>
)}
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8 items-start">
<div className="lg:col-span-1 flex flex-col space-y-6">
<FlyerList
flyers={flyers}
onFlyerSelect={onFlyerSelect}
selectedFlyerId={selectedFlyerId}
profile={userProfile}
/>
<FlyerUploader onProcessingComplete={refetchFlyers} />
</div>
<div className="lg:col-span-2 flex flex-col space-y-6">
{combinedError && <ErrorDisplay message={combinedError} />}
{/* The Outlet will render the specific page content (e.g., FlyerDisplay or Welcome message) */}
<Outlet
context={{
totalActiveItems,
masterItems,
addWatchedItem,
shoppingLists,
activeListId,
addItemToList,
}}
/>
</div>
<div className="lg:col-span-1 flex-col space-y-6">
<>
<ShoppingListComponent
user={user}
lists={shoppingLists}
activeListId={activeListId}
onSelectList={setActiveListId}
onCreateList={createList}
onDeleteList={deleteList}
onAddItem={handleAddItemToShoppingList}
onUpdateItem={updateItemInList}
onRemoveItem={removeItemFromList}
/>
<WatchedItemsList
items={watchedItems}
onAddItem={addWatchedItem}
onRemoveItem={removeWatchedItem}
user={user}
activeListId={activeListId}
onAddItemToList={handleAddItemFromWatchedList}
/>
<PriceChart
unitSystem={'imperial'} // This can be passed down or sourced from a context
user={user}
/>
<PriceHistoryChart />
<Leaderboard />
<ActivityLog userProfile={userProfile} onLogClick={handleActivityLogClick} />
</>
</div>
</div>
</main>
);
};