diff --git a/frontend/src/api.ts b/frontend/src/api.ts index e240234..39f493d 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -1,7 +1,7 @@ import axios from 'axios' // Central axios instance for new/migrated code. -// Existing archive components still call fetch('/api/...') directly — +// Existing archive components still call fetch('/kitchen/api/...') directly — // see port log B5 for the migration tracker. const api = axios.create({ baseURL: '/kitchen/api', diff --git a/frontend/src/components/AllowancesReport.tsx b/frontend/src/components/AllowancesReport.tsx index fdbbe77..cfee46e 100644 --- a/frontend/src/components/AllowancesReport.tsx +++ b/frontend/src/components/AllowancesReport.tsx @@ -254,7 +254,7 @@ export default function AllowancesReport() { const { data: summary, isLoading, error } = useQuery({ queryKey: ['allowances-summary', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/allowances/summary?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/allowances/summary?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch allowances summary') @@ -268,7 +268,7 @@ export default function AllowancesReport() { const { data: chartData } = useQuery({ queryKey: ['allowances-daily', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/allowances/daily?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/allowances/daily?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch chart data') @@ -282,7 +282,7 @@ export default function AllowancesReport() { const { data: disputes } = useQuery({ queryKey: ['disputes-period-summary', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/disputes/period-summary?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/disputes/period-summary?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch disputes summary') diff --git a/frontend/src/components/Budget.tsx b/frontend/src/components/Budget.tsx index dcbeb94..1830a16 100644 --- a/frontend/src/components/Budget.tsx +++ b/frontend/src/components/Budget.tsx @@ -254,7 +254,7 @@ export default function Budget() { const { data: budgetData, isLoading, error, refetch } = useQuery({ queryKey: ['budget', 'weekly', weekOffset], queryFn: async () => { - const res = await fetch(`/api/budget/weekly?week_offset=${weekOffset}`, { + const res = await fetch(`/kitchen/api/budget/weekly?week_offset=${weekOffset}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch budget data') @@ -267,7 +267,7 @@ export default function Budget() { const { data: prevWeek1 } = useQuery({ queryKey: ['budget', 'weekly', weekOffset - 1], queryFn: async () => { - const res = await fetch(`/api/budget/weekly?week_offset=${weekOffset - 1}`, { + const res = await fetch(`/kitchen/api/budget/weekly?week_offset=${weekOffset - 1}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return null @@ -278,7 +278,7 @@ export default function Budget() { const { data: prevWeek2 } = useQuery({ queryKey: ['budget', 'weekly', weekOffset - 2], queryFn: async () => { - const res = await fetch(`/api/budget/weekly?week_offset=${weekOffset - 2}`, { + const res = await fetch(`/kitchen/api/budget/weekly?week_offset=${weekOffset - 2}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return null @@ -298,7 +298,7 @@ export default function Budget() { const { data: overrideData, refetch: refetchOverrides, isLoading: isOverrideLoading } = useQuery({ queryKey: ['cover-overrides', 'weekly', weekOffset], queryFn: async () => { - const res = await fetch(`/api/cover-overrides/weekly?week_offset=${weekOffset}`, { + const res = await fetch(`/kitchen/api/cover-overrides/weekly?week_offset=${weekOffset}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch override data') @@ -312,7 +312,7 @@ export default function Budget() { queryKey: ['cost-distributions', 'weekly', weekOffset, budgetData?.week_start, budgetData?.week_end], queryFn: async () => { const res = await fetch( - `/api/cost-distributions/weekly?week_start=${budgetData!.week_start}&week_end=${budgetData!.week_end}`, + `/kitchen/api/cost-distributions/weekly?week_start=${budgetData!.week_start}&week_end=${budgetData!.week_end}`, { headers: { Authorization: `Bearer ${token}` } } ) if (!res.ok) throw new Error('Failed to fetch distribution data') @@ -335,7 +335,7 @@ export default function Budget() { queryKey: ['resos', 'resident-covers', budgetData?.week_start, budgetData?.week_end], queryFn: async () => { const res = await fetch( - `/api/resos/resident-covers?start_date=${budgetData!.week_start}&end_date=${budgetData!.week_end}`, + `/kitchen/api/resos/resident-covers?start_date=${budgetData!.week_start}&end_date=${budgetData!.week_end}`, { headers: { Authorization: `Bearer ${token}` } } ) if (!res.ok) return {} @@ -347,7 +347,7 @@ export default function Budget() { const snapshotMutation = useMutation({ mutationFn: async () => { - const res = await fetch('/api/cover-overrides/snapshot', { + const res = await fetch('/kitchen/api/cover-overrides/snapshot', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ week_offset: weekOffset }), @@ -383,7 +383,7 @@ export default function Budget() { try { await Promise.all(Object.entries(pendingOverrides).map(([key, value]) => { const [overrideDate, period] = key.split('|') - return fetch('/api/cover-overrides', { + return fetch('/kitchen/api/cover-overrides', { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ override_date: overrideDate, period, override_covers: value }), @@ -398,7 +398,7 @@ export default function Budget() { } const deleteOverride = async (id: number) => { - await fetch(`/api/cover-overrides/${id}`, { + await fetch(`/kitchen/api/cover-overrides/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -407,7 +407,7 @@ export default function Budget() { } const saveSpendRate = async (period: string, food: number | null, drinks: number | null) => { - await fetch('/api/cover-overrides/spend-rates', { + await fetch('/kitchen/api/cover-overrides/spend-rates', { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ week_offset: weekOffset, period, food_spend: food, drinks_spend: drinks }), diff --git a/frontend/src/components/BulkAllergens.tsx b/frontend/src/components/BulkAllergens.tsx index 234d390..e57cd12 100644 --- a/frontend/src/components/BulkAllergens.tsx +++ b/frontend/src/components/BulkAllergens.tsx @@ -65,7 +65,7 @@ export default function BulkAllergens() { const { data: ingredients } = useQuery({ queryKey: ['ingredients-bulk'], queryFn: async () => { - const res = await fetch('/api/ingredients?limit=9999', { + const res = await fetch('/kitchen/api/ingredients?limit=9999', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch ingredients') @@ -78,7 +78,7 @@ export default function BulkAllergens() { const { data: categories } = useQuery({ queryKey: ['ingredient-categories'], queryFn: async () => { - const res = await fetch('/api/ingredients/categories', { + const res = await fetch('/kitchen/api/ingredients/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -91,7 +91,7 @@ export default function BulkAllergens() { const { data: flagCategories } = useQuery({ queryKey: ['food-flag-categories-full'], queryFn: async () => { - const res = await fetch('/api/food-flags/categories', { + const res = await fetch('/kitchen/api/food-flags/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch flag categories') @@ -104,7 +104,7 @@ export default function BulkAllergens() { const { data: bulkNones } = useQuery>({ queryKey: ['bulk-nones'], queryFn: async () => { - const res = await fetch('/api/ingredients/bulk-nones', { + const res = await fetch('/kitchen/api/ingredients/bulk-nones', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return {} @@ -117,7 +117,7 @@ export default function BulkAllergens() { const { data: allSuggestions } = useQuery>({ queryKey: ['bulk-suggestions'], queryFn: async () => { - const res = await fetch('/api/food-flags/suggest/bulk', { + const res = await fetch('/kitchen/api/food-flags/suggest/bulk', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return {} @@ -140,7 +140,7 @@ export default function BulkAllergens() { newFlagIds = currentFlagIds.filter(id => id !== flagId) } - const res = await fetch(`/api/ingredients/${ingredientId}/flags`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredientId}/flags`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ food_flag_ids: newFlagIds }), @@ -156,7 +156,7 @@ export default function BulkAllergens() { // Toggle None for a category on an ingredient const toggleNoneMutation = useMutation({ mutationFn: async ({ ingredientId, categoryId }: { ingredientId: number; categoryId: number }) => { - const res = await fetch(`/api/ingredients/${ingredientId}/flags/none`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/none`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ category_id: categoryId }), diff --git a/frontend/src/components/BulkPublishModal.tsx b/frontend/src/components/BulkPublishModal.tsx index 0bfaba0..32fb654 100644 --- a/frontend/src/components/BulkPublishModal.tsx +++ b/frontend/src/components/BulkPublishModal.tsx @@ -31,7 +31,7 @@ export default function BulkPublishModal({ menuId, divisionId, divisionName, onC const { data: dishes } = useQuery({ queryKey: ['dishes-for-bulk'], queryFn: async () => { - const res = await fetch('/api/recipes?recipe_type=dish', { + const res = await fetch('/kitchen/api/recipes?recipe_type=dish', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -46,7 +46,7 @@ export default function BulkPublishModal({ menuId, divisionId, divisionName, onC queryFn: async () => { const results: Record }> = {} for (const rid of selected) { - const res = await fetch(`/api/food-flags/recipes/${rid}/flags`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${rid}/flags`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -76,7 +76,7 @@ export default function BulkPublishModal({ menuId, divisionId, divisionName, onC price: editedPrices[id] ? parseFloat(editedPrices[id]) : (dish?.gross_sell_price || null), } }) - const res = await fetch(`/api/menus/${menuId}/items/bulk`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/bulk`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ diff --git a/frontend/src/components/CostDistributionModal.tsx b/frontend/src/components/CostDistributionModal.tsx index 36a3a59..990f217 100644 --- a/frontend/src/components/CostDistributionModal.tsx +++ b/frontend/src/components/CostDistributionModal.tsx @@ -123,7 +123,7 @@ export default function CostDistributionModal({ isOpen, onClose, onSaved, invoic if (distributionId) { // Load existing distribution setLoading(true) - fetch(`/api/cost-distributions/${distributionId}`, { + fetch(`/kitchen/api/cost-distributions/${distributionId}`, { headers: { Authorization: `Bearer ${token}` }, }) .then(r => { if (!r.ok) throw new Error('Failed to load distribution'); return r.json() }) @@ -136,7 +136,7 @@ export default function CostDistributionModal({ isOpen, onClose, onSaved, invoic } else if (invoiceId) { // Load invoice availability setLoading(true) - fetch(`/api/cost-distributions/invoice/${invoiceId}/availability`, { + fetch(`/kitchen/api/cost-distributions/invoice/${invoiceId}/availability`, { headers: { Authorization: `Bearer ${token}` }, }) .then(r => { if (!r.ok) throw new Error('Failed to load invoice data'); return r.json() }) @@ -276,7 +276,7 @@ export default function CostDistributionModal({ isOpen, onClose, onSaved, invoic body.start_date = startDate } - const res = await fetch('/api/cost-distributions/', { + const res = await fetch('/kitchen/api/cost-distributions/', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), @@ -300,7 +300,7 @@ export default function CostDistributionModal({ isOpen, onClose, onSaved, invoic if (!token || !distributionId) return setSaving(true) try { - const res = await fetch(`/api/cost-distributions/${distributionId}`, { + const res = await fetch(`/kitchen/api/cost-distributions/${distributionId}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ notes }), @@ -320,7 +320,7 @@ export default function CostDistributionModal({ isOpen, onClose, onSaved, invoic if (!confirm('Are you sure you want to cancel this distribution? This will remove all scheduled entries.')) return setDeleting(true) try { - const res = await fetch(`/api/cost-distributions/${distributionId}`, { + const res = await fetch(`/kitchen/api/cost-distributions/${distributionId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -343,7 +343,7 @@ export default function CostDistributionModal({ isOpen, onClose, onSaved, invoic try { const body: any = { entry_date: settleDate } if (!settleAll && settleAmount) body.amount = parseFloat(settleAmount) - const res = await fetch(`/api/cost-distributions/${distributionId}/settle-early`, { + const res = await fetch(`/kitchen/api/cost-distributions/${distributionId}/settle-early`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), diff --git a/frontend/src/components/CreateDisputeModal.tsx b/frontend/src/components/CreateDisputeModal.tsx index de8ee75..4d76098 100644 --- a/frontend/src/components/CreateDisputeModal.tsx +++ b/frontend/src/components/CreateDisputeModal.tsx @@ -69,7 +69,7 @@ export default function CreateDisputeModal({ const createMutation = useMutation({ mutationFn: async (data: CreateDisputeRequest) => { - const res = await fetch('/api/disputes', { + const res = await fetch('/kitchen/api/disputes', { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/frontend/src/components/Dashboard.tsx b/frontend/src/components/Dashboard.tsx index ece5a8f..c482b6c 100644 --- a/frontend/src/components/Dashboard.tsx +++ b/frontend/src/components/Dashboard.tsx @@ -136,7 +136,7 @@ export default function Dashboard() { const { data: resosSettings } = useQuery({ queryKey: ['resos-settings'], queryFn: async () => { - const res = await fetch('/api/resos/settings', { + const res = await fetch('/kitchen/api/resos/settings', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch Resos settings') @@ -148,7 +148,7 @@ export default function Dashboard() { const { data, isLoading, error } = useQuery({ queryKey: ['dashboard'], queryFn: async () => { - const res = await fetch('/api/reports/dashboard', { + const res = await fetch('/kitchen/api/reports/dashboard', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch dashboard') @@ -159,7 +159,7 @@ export default function Dashboard() { const { data: resosCovers } = useQuery({ queryKey: ['resos-dashboard-covers'], queryFn: async () => { - const res = await fetch('/api/resos/dashboard/today-tomorrow', { + const res = await fetch('/kitchen/api/resos/dashboard/today-tomorrow', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch Resos covers') @@ -172,7 +172,7 @@ export default function Dashboard() { const { data: arrivalStats } = useQuery({ queryKey: ['newbook-arrival-stats'], queryFn: async () => { - const res = await fetch('/api/newbook/dashboard/arrivals?days=3', { + const res = await fetch('/kitchen/api/newbook/dashboard/arrivals?days=3', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch arrival stats') @@ -193,7 +193,7 @@ export default function Dashboard() { }>({ queryKey: ['upcoming-events'], queryFn: async () => { - const res = await fetch('/api/calendar-events/dashboard/upcoming', { + const res = await fetch('/kitchen/api/calendar-events/dashboard/upcoming', { headers: { Authorization: `Bearer ${token}` } }) if (!res.ok) throw new Error('Failed to fetch upcoming events') @@ -217,7 +217,7 @@ export default function Dashboard() { }>({ queryKey: ['recipe-dashboard-stats'], queryFn: async () => { - const res = await fetch('/api/recipes/dashboard-stats', { + const res = await fetch('/kitchen/api/recipes/dashboard-stats', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch recipe stats') @@ -230,7 +230,7 @@ export default function Dashboard() { const { data: disputeStats } = useQuery({ queryKey: ['dispute-stats'], queryFn: async () => { - const res = await fetch('/api/disputes/stats/summary', { + const res = await fetch('/kitchen/api/disputes/stats/summary', { headers: { Authorization: `Bearer ${token}` } }) if (!res.ok) throw new Error('Failed to fetch dispute stats') diff --git a/frontend/src/components/DishEditor.tsx b/frontend/src/components/DishEditor.tsx index 76ece2f..c93d529 100644 --- a/frontend/src/components/DishEditor.tsx +++ b/frontend/src/components/DishEditor.tsx @@ -288,7 +288,7 @@ export default function DishEditor() { const { data: recipe } = useQuery({ queryKey: ['recipe', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Not found') @@ -301,7 +301,7 @@ export default function DishEditor() { const { data: sections } = useQuery({ queryKey: ['dish-courses'], queryFn: async () => { - const res = await fetch('/api/recipes/menu-sections?section_type=dish', { + const res = await fetch('/kitchen/api/recipes/menu-sections?section_type=dish', { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -313,7 +313,7 @@ export default function DishEditor() { const { data: costData } = useQuery({ queryKey: ['recipe-cost', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/costing`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/costing`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -325,7 +325,7 @@ export default function DishEditor() { const { data: scaledCostData } = useQuery({ queryKey: ['recipe-cost-scaled', recipeId, scalePortions], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/costing?scale_to=${scalePortions}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/costing?scale_to=${scalePortions}`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -337,7 +337,7 @@ export default function DishEditor() { const { data: flagData } = useQuery({ queryKey: ['recipe-flags', recipeId], queryFn: async () => { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/flags`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/flags`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -349,7 +349,7 @@ export default function DishEditor() { const { data: flagCategories } = useQuery>({ queryKey: ['food-flag-categories'], queryFn: async () => { - const res = await fetch('/api/food-flags/categories', { + const res = await fetch('/kitchen/api/food-flags/categories', { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -361,7 +361,7 @@ export default function DishEditor() { const { data: changeLog } = useQuery({ queryKey: ['recipe-changelog', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/change-log`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/change-log`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -373,7 +373,7 @@ export default function DishEditor() { const { data: costTrendRaw } = useQuery({ queryKey: ['recipe-cost-trend', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/cost-trend`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/cost-trend`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch cost trend') @@ -386,7 +386,7 @@ export default function DishEditor() { const { data: dishMenus } = useQuery>({ queryKey: ['dish-menus', recipeId], queryFn: async () => { - const res = await fetch(`/api/menus/dish/${recipeId}/menus`, { + const res = await fetch(`/kitchen/api/menus/dish/${recipeId}/menus`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -399,7 +399,7 @@ export default function DishEditor() { const { data: editIngData } = useQuery({ queryKey: ['ingredient-edit', editIngId], queryFn: async () => { - const res = await fetch(`/api/ingredients/${editIngId}`, { + const res = await fetch(`/kitchen/api/ingredients/${editIngId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Not found') @@ -425,7 +425,7 @@ export default function DishEditor() { const { data: availableRecipes } = useQuery>({ queryKey: ['recipes-list-for-sub'], queryFn: async () => { - const res = await fetch('/api/recipes?recipe_type=component', { + const res = await fetch('/kitchen/api/recipes?recipe_type=component', { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -438,7 +438,7 @@ export default function DishEditor() { const { data: sambaposItems } = useQuery({ queryKey: ['sambapos-menu-items-portions'], queryFn: async () => { - const res = await fetch('/api/sambapos/menu-items-with-portions', { + const res = await fetch('/kitchen/api/sambapos/menu-items-with-portions', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -467,7 +467,7 @@ export default function DishEditor() { if (!ingSearch || ingSearch.length < 2 || !token) return const timer = setTimeout(async () => { try { - const res = await fetch(`/api/ingredients/suggest?description=${encodeURIComponent(ingSearch)}`, { + const res = await fetch(`/kitchen/api/ingredients/suggest?description=${encodeURIComponent(ingSearch)}`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -484,7 +484,7 @@ export default function DishEditor() { // Mutations const updateMutation = useMutation({ mutationFn: async (data: Record) => { - const res = await fetch(`/api/recipes/${recipeId}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -502,7 +502,7 @@ export default function DishEditor() { const addIngMutation = useMutation({ mutationFn: async (data: { ingredient_id: number; quantity: number; unit?: string; notes?: string }) => { - const res = await fetch(`/api/recipes/${recipeId}/ingredients`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/ingredients`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -527,7 +527,7 @@ export default function DishEditor() { const updateIngMutation = useMutation({ mutationFn: async ({ riId, quantity, unit, yield_percent, notes }: { riId: number; quantity?: number; unit?: string; yield_percent?: number; notes?: string }) => { - const res = await fetch(`/api/recipes/recipe-ingredients/${riId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-ingredients/${riId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ quantity, unit, yield_percent, notes }), @@ -545,7 +545,7 @@ export default function DishEditor() { const removeIngMutation = useMutation({ mutationFn: async (riId: number) => { - const res = await fetch(`/api/recipes/recipe-ingredients/${riId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-ingredients/${riId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -562,7 +562,7 @@ export default function DishEditor() { const addSubMutation = useMutation({ mutationFn: async (data: { child_recipe_id: number; portions_needed: number; portions_needed_unit?: string }) => { - const res = await fetch(`/api/recipes/${recipeId}/sub-recipes`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/sub-recipes`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -583,7 +583,7 @@ export default function DishEditor() { const removeSubMutation = useMutation({ mutationFn: async (srId: number) => { - const res = await fetch(`/api/recipes/recipe-sub-recipes/${srId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-sub-recipes/${srId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -599,7 +599,7 @@ export default function DishEditor() { const addStepMutation = useMutation({ mutationFn: async (data: { title?: string; instruction: string; step_number: number; duration_minutes?: number }) => { - const res = await fetch(`/api/recipes/${recipeId}/steps`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/steps`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -617,7 +617,7 @@ export default function DishEditor() { const updateStepMutation = useMutation({ mutationFn: async ({ stepId, data }: { stepId: number; data: { title?: string; instruction?: string; duration_minutes?: number } }) => { - const res = await fetch(`/api/recipes/recipe-steps/${stepId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-steps/${stepId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -636,7 +636,7 @@ export default function DishEditor() { const removeStepMutation = useMutation({ mutationFn: async (stepId: number) => { - const res = await fetch(`/api/recipes/recipe-steps/${stepId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-steps/${stepId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -652,7 +652,7 @@ export default function DishEditor() { formData.append('file', file) formData.append('caption', caption) formData.append('image_type', image_type) - const res = await fetch(`/api/recipes/${recipeId}/images`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/images`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: formData, @@ -670,7 +670,7 @@ export default function DishEditor() { // Delete image mutation const deleteImageMutation = useMutation({ mutationFn: async (imageId: number) => { - const res = await fetch(`/api/recipes/${recipeId}/images/${imageId}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/images/${imageId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -684,7 +684,7 @@ export default function DishEditor() { // Batch reorder ingredients const reorderIngMutation = useMutation({ mutationFn: async (ingredientIds: number[]) => { - const res = await fetch(`/api/recipes/${recipeId}/ingredients/reorder`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/ingredients/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ingredient_ids: ingredientIds }), @@ -699,7 +699,7 @@ export default function DishEditor() { // Batch reorder sub-recipes const reorderSubMutation = useMutation({ mutationFn: async (subRecipeIds: number[]) => { - const res = await fetch(`/api/recipes/${recipeId}/sub-recipes/reorder`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/sub-recipes/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ sub_recipe_ids: subRecipeIds }), @@ -714,7 +714,7 @@ export default function DishEditor() { // Reorder steps mutation const reorderStepsMutation = useMutation({ mutationFn: async (stepIds: number[]) => { - const res = await fetch(`/api/recipes/${recipeId}/steps/reorder`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/steps/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ step_ids: stepIds }), @@ -799,7 +799,7 @@ export default function DishEditor() { } const handlePrint = (format: string) => { - window.open(`/api/recipes/${recipeId}/print?format=${format}&token=${token}`, '_blank') + window.open(`/kitchen/api/recipes/${recipeId}/print?format=${format}&token=${token}`, '_blank') } if (!recipe) return
Loading dish...
@@ -929,7 +929,7 @@ export default function DishEditor() { style={{ marginLeft: 'auto', background: 'none', border: '1px solid #b4530955', borderRadius: '4px', color: '#b45309', cursor: 'pointer', padding: '0.15rem 0.5rem', fontSize: '0.8rem', whiteSpace: 'nowrap' }} onClick={async () => { try { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/text-dismissals`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/text-dismissals`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ @@ -1345,10 +1345,10 @@ export default function DishEditor() { {recipe.images.map(img => (
{img.caption setLightboxImg(`/api/recipes/${recipeId}/images/${img.id}?token=${token}`)} + onClick={() => setLightboxImg(`/kitchen/api/recipes/${recipeId}/images/${img.id}?token=${token}`)} />
{img.caption &&
{img.caption}
} diff --git a/frontend/src/components/DishList.tsx b/frontend/src/components/DishList.tsx index 2d9f0e3..6cd2d0d 100644 --- a/frontend/src/components/DishList.tsx +++ b/frontend/src/components/DishList.tsx @@ -120,7 +120,7 @@ export default function DishList() { const { data: sections } = useQuery({ queryKey: ['dish-courses'], queryFn: async () => { - const res = await fetch('/api/recipes/menu-sections?section_type=dish', { + const res = await fetch('/kitchen/api/recipes/menu-sections?section_type=dish', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch sections') @@ -137,7 +137,7 @@ export default function DishList() { params.set('recipe_type', 'dish') if (sectionFilter) params.set('menu_section_id', sectionFilter) if (showArchived) params.set('archived', 'true') - const res = await fetch(`/api/recipes?${params}`, { + const res = await fetch(`/kitchen/api/recipes?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch dishes') @@ -150,7 +150,7 @@ export default function DishList() { const { data: impactData } = useQuery<{ days: number; recipes: ImpactItem[] }>({ queryKey: ['price-impact-dishes', costChangeDays], queryFn: async () => { - const res = await fetch(`/api/recipes/price-impact?days=${costChangeDays}`, { + const res = await fetch(`/kitchen/api/recipes/price-impact?days=${costChangeDays}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch price impact') @@ -167,7 +167,7 @@ export default function DishList() { const { data: costTrendRaw } = useQuery<{ snapshots: CostTrendSnapshot[] }>({ queryKey: ['cost-trend', expandedCostId], queryFn: async () => { - const res = await fetch(`/api/recipes/${expandedCostId}/cost-trend`, { + const res = await fetch(`/kitchen/api/recipes/${expandedCostId}/cost-trend`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch cost trend') @@ -178,7 +178,7 @@ export default function DishList() { const createMutation = useMutation({ mutationFn: async (data: Record) => { - const res = await fetch('/api/recipes', { + const res = await fetch('/kitchen/api/recipes', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -195,7 +195,7 @@ export default function DishList() { const duplicateMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/${id}/duplicate`, { + const res = await fetch(`/kitchen/api/recipes/${id}/duplicate`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -210,7 +210,7 @@ export default function DishList() { const archiveMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/${id}`, { + const res = await fetch(`/kitchen/api/recipes/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -221,7 +221,7 @@ export default function DishList() { const unarchiveMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/${id}`, { + const res = await fetch(`/kitchen/api/recipes/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ is_archived: false }), @@ -233,7 +233,7 @@ export default function DishList() { const createSectionMutation = useMutation({ mutationFn: async (name: string) => { - const res = await fetch('/api/recipes/menu-sections', { + const res = await fetch('/kitchen/api/recipes/menu-sections', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name, section_type: 'dish' }), @@ -250,7 +250,7 @@ export default function DishList() { const updateSectionMutation = useMutation({ mutationFn: async ({ id, name }: { id: number; name: string }) => { - const res = await fetch(`/api/recipes/menu-sections/${id}`, { + const res = await fetch(`/kitchen/api/recipes/menu-sections/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name }), @@ -268,7 +268,7 @@ export default function DishList() { const deleteSectionMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/menu-sections/${id}`, { + const res = await fetch(`/kitchen/api/recipes/menu-sections/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -284,7 +284,7 @@ export default function DishList() { const { data: flagCategories } = useQuery }>>({ queryKey: ['food-flag-categories'], queryFn: async () => { - const res = await fetch('/api/food-flags/categories', { + const res = await fetch('/kitchen/api/food-flags/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch flag categories') diff --git a/frontend/src/components/DisputeDetailModal.tsx b/frontend/src/components/DisputeDetailModal.tsx index ba81c78..6dc5a3b 100644 --- a/frontend/src/components/DisputeDetailModal.tsx +++ b/frontend/src/components/DisputeDetailModal.tsx @@ -125,7 +125,7 @@ export default function DisputeDetailModal({ disputeId, onClose, onUpdate }: Dis const { data: settings } = useQuery<{ llm_enabled?: boolean; anthropic_api_key_set?: boolean }>({ queryKey: ['settings'], queryFn: async () => { - const res = await fetch('/api/settings', { headers: { Authorization: `Bearer ${token}` } }) + const res = await fetch('/kitchen/api/settings', { headers: { Authorization: `Bearer ${token}` } }) if (!res.ok) return {} return res.json() }, @@ -136,7 +136,7 @@ export default function DisputeDetailModal({ disputeId, onClose, onUpdate }: Dis const { data: dispute, isLoading, error } = useQuery({ queryKey: ['dispute', disputeId], queryFn: async () => { - const res = await fetch(`/api/disputes/${disputeId}`, { + const res = await fetch(`/kitchen/api/disputes/${disputeId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch dispute') @@ -147,7 +147,7 @@ export default function DisputeDetailModal({ disputeId, onClose, onUpdate }: Dis const updateMutation = useMutation({ mutationFn: async (data: { status?: string; priority?: string; supplier_response?: string; supplier_contact_name?: string; title?: string; description?: string }) => { - const res = await fetch(`/api/disputes/${disputeId}`, { + const res = await fetch(`/kitchen/api/disputes/${disputeId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', @@ -172,7 +172,7 @@ export default function DisputeDetailModal({ disputeId, onClose, onUpdate }: Dis const deleteMutation = useMutation({ mutationFn: async () => { - const res = await fetch(`/api/disputes/${disputeId}`, { + const res = await fetch(`/kitchen/api/disputes/${disputeId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}`, @@ -251,7 +251,7 @@ export default function DisputeDetailModal({ disputeId, onClose, onUpdate }: Dis setAiEmailSubject('') setAiEmailBody('') try { - const res = await fetch(`/api/disputes/${disputeId}/draft-email`, { + const res = await fetch(`/kitchen/api/disputes/${disputeId}/draft-email`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -290,7 +290,7 @@ export default function DisputeDetailModal({ disputeId, onClose, onUpdate }: Dis params.append('description', uploadDescription.trim()) } - const res = await fetch(`/api/disputes/${disputeId}/attachments?${params}`, { + const res = await fetch(`/kitchen/api/disputes/${disputeId}/attachments?${params}`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, diff --git a/frontend/src/components/Disputes.tsx b/frontend/src/components/Disputes.tsx index 8c2bad8..31e6a76 100644 --- a/frontend/src/components/Disputes.tsx +++ b/frontend/src/components/Disputes.tsx @@ -59,7 +59,7 @@ export default function Disputes() { const { data: suppliersData } = useQuery<{ suppliers: Array<{ id: number; name: string }> }>({ queryKey: ['suppliers'], queryFn: async () => { - const res = await fetch('/api/suppliers/', { + const res = await fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch suppliers') @@ -83,7 +83,7 @@ export default function Disputes() { const { data, isLoading, error } = useQuery({ queryKey: ['disputes', statusFilter, priorityFilter, supplierFilter, dateFilter], queryFn: async () => { - const url = queryString ? `/api/disputes?${queryString}` : '/api/disputes' + const url = queryString ? `/kitchen/api/disputes?${queryString}` : '/kitchen/api/disputes' const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` }, }) diff --git a/frontend/src/components/EventOrderEditor.tsx b/frontend/src/components/EventOrderEditor.tsx index 273f4f2..26c613a 100644 --- a/frontend/src/components/EventOrderEditor.tsx +++ b/frontend/src/components/EventOrderEditor.tsx @@ -128,7 +128,7 @@ export default function EventOrderEditor() { const { data: order } = useQuery({ queryKey: ['event-order', orderId], queryFn: async () => { - const res = await fetch(`/api/event-orders/${orderId}`, { + const res = await fetch(`/kitchen/api/event-orders/${orderId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Not found') @@ -142,7 +142,7 @@ export default function EventOrderEditor() { const { data: recipes } = useQuery({ queryKey: ['recipes-for-event', recipeType], queryFn: async () => { - const res = await fetch(`/api/recipes?recipe_type=${recipeType}`, { + const res = await fetch(`/kitchen/api/recipes?recipe_type=${recipeType}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -155,7 +155,7 @@ export default function EventOrderEditor() { const { data: menus } = useQuery({ queryKey: ['menus-for-event'], queryFn: async () => { - const res = await fetch('/api/menus', { + const res = await fetch('/kitchen/api/menus', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -168,7 +168,7 @@ export default function EventOrderEditor() { const { data: menuDetail } = useQuery({ queryKey: ['menu-detail-for-event', selectedMenuId], queryFn: async () => { - const res = await fetch(`/api/menus/${selectedMenuId}`, { + const res = await fetch(`/kitchen/api/menus/${selectedMenuId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -181,7 +181,7 @@ export default function EventOrderEditor() { queryKey: ['event-shopping-list', orderId, groupBySupplier], queryFn: async () => { const params = groupBySupplier ? '?group_by_supplier=true' : '' - const res = await fetch(`/api/event-orders/${orderId}/shopping-list${params}`, { + const res = await fetch(`/kitchen/api/event-orders/${orderId}/shopping-list${params}`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -191,7 +191,7 @@ export default function EventOrderEditor() { const addItemMutation = useMutation({ mutationFn: async (data: { recipe_id: number; quantity: number }) => { - const res = await fetch(`/api/event-orders/${orderId}/items`, { + const res = await fetch(`/kitchen/api/event-orders/${orderId}/items`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -207,7 +207,7 @@ export default function EventOrderEditor() { const bulkAddMutation = useMutation({ mutationFn: async (items: Array<{ recipe_id: number; quantity: number; notes?: string }>) => { - const res = await fetch(`/api/event-orders/${orderId}/items/bulk`, { + const res = await fetch(`/kitchen/api/event-orders/${orderId}/items/bulk`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ items }), @@ -224,7 +224,7 @@ export default function EventOrderEditor() { const removeItemMutation = useMutation({ mutationFn: async (itemId: number) => { - const res = await fetch(`/api/event-orders/items/${itemId}`, { + const res = await fetch(`/kitchen/api/event-orders/items/${itemId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -238,7 +238,7 @@ export default function EventOrderEditor() { const updateStatusMutation = useMutation({ mutationFn: async (status: string) => { - const res = await fetch(`/api/event-orders/${orderId}`, { + const res = await fetch(`/kitchen/api/event-orders/${orderId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status }), diff --git a/frontend/src/components/EventOrders.tsx b/frontend/src/components/EventOrders.tsx index e8e0145..db47aa2 100644 --- a/frontend/src/components/EventOrders.tsx +++ b/frontend/src/components/EventOrders.tsx @@ -28,7 +28,7 @@ export default function EventOrders() { const { data: orders, isLoading } = useQuery({ queryKey: ['event-orders'], queryFn: async () => { - const res = await fetch('/api/event-orders', { + const res = await fetch('/kitchen/api/event-orders', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -39,7 +39,7 @@ export default function EventOrders() { const createMutation = useMutation({ mutationFn: async (data: { name: string; event_date?: string; notes?: string }) => { - const res = await fetch('/api/event-orders', { + const res = await fetch('/kitchen/api/event-orders', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -56,7 +56,7 @@ export default function EventOrders() { const deleteMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/event-orders/${id}`, { + const res = await fetch(`/kitchen/api/event-orders/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) diff --git a/frontend/src/components/GPReport.tsx b/frontend/src/components/GPReport.tsx index 7f0649b..556be7f 100644 --- a/frontend/src/components/GPReport.tsx +++ b/frontend/src/components/GPReport.tsx @@ -317,7 +317,7 @@ export default function GPReport() { const { data, isLoading, error } = useQuery({ queryKey: ['gp-range', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/gp/range?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/gp/range?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch GP data') @@ -331,7 +331,7 @@ export default function GPReport() { const { data: chartData } = useQuery({ queryKey: ['gp-daily', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/gp/daily?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/gp/daily?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch chart data') @@ -345,7 +345,7 @@ export default function GPReport() { const { data: topSellers, isLoading: topSellersLoading } = useQuery({ queryKey: ['gp-top-sellers', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/gp/top-sellers?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/gp/top-sellers?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) { diff --git a/frontend/src/components/IngredientFlagEditor.tsx b/frontend/src/components/IngredientFlagEditor.tsx index 3e8158b..3664e4c 100644 --- a/frontend/src/components/IngredientFlagEditor.tsx +++ b/frontend/src/components/IngredientFlagEditor.tsx @@ -83,7 +83,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on const { data: categories } = useQuery({ queryKey: ['food-flag-categories'], queryFn: async () => { - const res = await fetch('/api/food-flags/categories', { + const res = await fetch('/kitchen/api/food-flags/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -96,7 +96,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on const { data: currentFlags } = useQuery({ queryKey: ['ingredient-flags', ingredientId], queryFn: async () => { - const res = await fetch(`/api/ingredients/${ingredientId}/flags`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredientId}/flags`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -109,7 +109,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on const { data: currentNones } = useQuery<{ none_category_ids: number[] }>({ queryKey: ['ingredient-flag-nones', ingredientId], queryFn: async () => { - const res = await fetch(`/api/ingredients/${ingredientId}/flags/nones`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/nones`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return { none_category_ids: [] } @@ -122,7 +122,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on const { data: currentDismissals } = useQuery({ queryKey: ['ingredient-flag-dismissals', ingredientId], queryFn: async () => { - const res = await fetch(`/api/ingredients/${ingredientId}/flags/dismissals`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/dismissals`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -139,7 +139,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on if (debouncedName) params.set('name', debouncedName) if (debouncedLineItem) params.set('line_item', debouncedLineItem) if (debouncedText) params.set('text', debouncedText) - const res = await fetch(`/api/food-flags/suggest?${params}`, { + const res = await fetch(`/kitchen/api/food-flags/suggest?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -216,7 +216,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on // For edit mode, persist to API if (ingredientId) { - fetch(`/api/ingredients/${ingredientId}/flags`, { + fetch(`/kitchen/api/ingredients/${ingredientId}/flags`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ food_flag_ids: [...newFlags] }), @@ -253,7 +253,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on const catFlags = categories.find(c => c.id === catId)?.flags || [] const hasActiveFlags = catFlags.some(f => newFlags.has(f.id)) if (!hasActiveFlags) { - fetch(`/api/ingredients/${ingredientId}/flags/none`, { + fetch(`/kitchen/api/ingredients/${ingredientId}/flags/none`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ category_id: catId }), @@ -325,7 +325,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on if (ingredientId) { setSaving(true) try { - await fetch(`/api/ingredients/${ingredientId}/flags`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ food_flag_ids: [...newFlags] }), @@ -356,7 +356,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on if (ingredientId) { setSaving(true) try { - await fetch(`/api/ingredients/${ingredientId}/flags/none`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/none`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ category_id: categoryId }), @@ -393,7 +393,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on // Edit mode: persist immediately if (ingredientId) { try { - const res = await fetch(`/api/ingredients/${ingredientId}/flags/dismissals`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/dismissals`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(dismissal), @@ -421,7 +421,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on // Edit mode: delete from API if (ingredientId && dismissal.id) { try { - await fetch(`/api/ingredients/${ingredientId}/flags/dismissals/${dismissal.id}`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/dismissals/${dismissal.id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -452,7 +452,7 @@ export default function IngredientFlagEditor({ ingredientId, token, onChange, on if (ingredientId) { setSaving(true) try { - await fetch(`/api/ingredients/${ingredientId}/flags`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ food_flag_ids: [...newFlags] }), diff --git a/frontend/src/components/IngredientModal.tsx b/frontend/src/components/IngredientModal.tsx index 1d4ae8f..cc94305 100644 --- a/frontend/src/components/IngredientModal.tsx +++ b/frontend/src/components/IngredientModal.tsx @@ -30,11 +30,11 @@ const SUPPLIER_LOOKUPS: SupplierLookup[] = [ namePattern: /brakes/i, label: 'Fetch Brakes', color: '#f59e0b', - endpoint: '/api/food-flags/brakes-lookup', + endpoint: '/kitchen/api/food-flags/brakes-lookup', paramName: 'product_code', }, // To add another supplier, add an entry here: - // { key: 'bidfood', namePattern: /bidfood/i, label: 'Fetch Bidfood', color: '#3b82f6', endpoint: '/api/food-flags/bidfood-lookup', paramName: 'product_code' }, + // { key: 'bidfood', namePattern: /bidfood/i, label: 'Fetch Bidfood', color: '#3b82f6', endpoint: '/kitchen/api/food-flags/bidfood-lookup', paramName: 'product_code' }, ] function getSupplierLookup(supplierName: string | null | undefined): SupplierLookup | null { @@ -165,7 +165,7 @@ export default function IngredientModal({ const { data: categories } = useQuery({ queryKey: ['ingredient-categories'], queryFn: async () => { - const res = await fetch('/api/ingredients/categories', { + const res = await fetch('/kitchen/api/ingredients/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch categories') @@ -177,7 +177,7 @@ export default function IngredientModal({ const { data: liSuppliers } = useQuery>({ queryKey: ['suppliers'], queryFn: async () => { - const res = await fetch('/api/suppliers/', { headers: { Authorization: `Bearer ${token}` } }) + const res = await fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` } }) if (!res.ok) return [] const data = await res.json() return data.suppliers || data || [] @@ -199,7 +199,7 @@ export default function IngredientModal({ }>>({ queryKey: ['ingredient-sources', editingIngredient?.id], queryFn: async () => { - const res = await fetch(`/api/ingredients/${editingIngredient!.id}/sources`, { + const res = await fetch(`/kitchen/api/ingredients/${editingIngredient!.id}/sources`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -216,7 +216,7 @@ export default function IngredientModal({ if (debouncedLiSearch) params.set('q', debouncedLiSearch) if (liSupplierId) params.set('supplier_id', liSupplierId) params.set('limit', '100') - const res = await fetch(`/api/search/line-items?${params}`, { + const res = await fetch(`/kitchen/api/search/line-items?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return { items: [], total_count: 0 } @@ -230,7 +230,7 @@ export default function IngredientModal({ const { data: settingsData } = useQuery<{ llm_enabled: boolean }>({ queryKey: ['settings-llm-check'], queryFn: async () => { - const res = await fetch('/api/settings/', { + const res = await fetch('/kitchen/api/settings/', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return { llm_enabled: false } @@ -252,7 +252,7 @@ export default function IngredientModal({ const runAnalysis = async () => { setLlmAnalysing(true) try { - const res = await fetch('/api/food-flags/analyse-label', { + const res = await fetch('/kitchen/api/food-flags/analyse-label', { method: 'POST', headers: { Authorization: `Bearer ${token}`, @@ -294,7 +294,7 @@ export default function IngredientModal({ const fetchYield = async () => { setYieldHintLoading(true) try { - const res = await fetch(`/api/ingredients/ai-estimate-yield?name=${encodeURIComponent(debouncedFormName.trim())}`, { + const res = await fetch(`/kitchen/api/ingredients/ai-estimate-yield?name=${encodeURIComponent(debouncedFormName.trim())}`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok && !cancelled) { @@ -434,8 +434,8 @@ export default function IngredientModal({ reader.onload = (e) => setLabelPreview(e.target?.result as string) reader.readAsDataURL(file) const url = editingIngredient - ? `/api/food-flags/scan-label/${editingIngredient.id}` - : '/api/food-flags/scan-label' + ? `/kitchen/api/food-flags/scan-label/${editingIngredient.id}` + : '/kitchen/api/food-flags/scan-label' const res = await fetch(url, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, @@ -467,7 +467,7 @@ export default function IngredientModal({ } if (selectedLi.most_recent_price) sourceData.latest_unit_price = selectedLi.most_recent_price if (selectedLi.most_recent_invoice_id) sourceData.invoice_id = selectedLi.most_recent_invoice_id - const srcRes = await fetch(`/api/ingredients/${ingredientId}/sources`, { + const srcRes = await fetch(`/kitchen/api/ingredients/${ingredientId}/sources`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(sourceData), @@ -484,7 +484,7 @@ export default function IngredientModal({ const applyPendingFlags = async (ingredientId: number) => { if (pendingFlagIds.length > 0) { try { - await fetch(`/api/ingredients/${ingredientId}/flags`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ food_flag_ids: pendingFlagIds }), @@ -493,7 +493,7 @@ export default function IngredientModal({ } for (const catId of pendingNoneCatIds) { try { - await fetch(`/api/ingredients/${ingredientId}/flags/none`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/none`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ category_id: catId }), @@ -503,7 +503,7 @@ export default function IngredientModal({ // Batch persist dismissals from create mode if (pendingDismissals.length > 0) { try { - await fetch(`/api/ingredients/${ingredientId}/flags/dismissals/batch`, { + await fetch(`/kitchen/api/ingredients/${ingredientId}/flags/dismissals/batch`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ dismissals: pendingDismissals }), @@ -529,7 +529,7 @@ export default function IngredientModal({ setFormFree(editingIngredient.is_free || false) setFormPrepackaged(editingIngredient.is_prepackaged || false) setFormProductIngredients(editingIngredient.product_ingredients || '') - setLabelPreview(editingIngredient.has_label_image ? `/api/ingredients/${editingIngredient.id}/label-image?token=${encodeURIComponent(token || '')}` : null) + setLabelPreview(editingIngredient.has_label_image ? `/kitchen/api/ingredients/${editingIngredient.id}/label-image?token=${encodeURIComponent(token || '')}` : null) setLiSearch(editingIngredient.name) } else { const name = prePopulateName || '' @@ -550,7 +550,7 @@ export default function IngredientModal({ } else if (preSelectLineItem.description) { // LLM FEATURE — AI pack size deduction when regex can't parse setAiPackLoading(true) - fetch(`/api/ingredients/ai-pack-size?description=${encodeURIComponent(preSelectLineItem.description)}`, { + fetch(`/kitchen/api/ingredients/ai-pack-size?description=${encodeURIComponent(preSelectLineItem.description)}`, { headers: { Authorization: `Bearer ${token}` }, }).then(res => res.ok ? res.json() : null).then(data => { if (data?.pack_quantity && data?.unit_size) { @@ -589,7 +589,7 @@ export default function IngredientModal({ } const timer = setTimeout(async () => { try { - const res = await fetch(`/api/ingredients/check-duplicate?name=${encodeURIComponent(formName)}`, { + const res = await fetch(`/kitchen/api/ingredients/check-duplicate?name=${encodeURIComponent(formName)}`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -605,7 +605,7 @@ export default function IngredientModal({ const createMutation = useMutation({ mutationFn: async (data: Record) => { - const res = await fetch('/api/ingredients', { + const res = await fetch('/kitchen/api/ingredients', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -628,7 +628,7 @@ export default function IngredientModal({ const updateMutation = useMutation({ mutationFn: async ({ id, data }: { id: number; data: Record }) => { - const res = await fetch(`/api/ingredients/${id}`, { + const res = await fetch(`/kitchen/api/ingredients/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -988,7 +988,7 @@ export default function IngredientModal({ title="Click to enlarge" > Invoice line item { (e.target as HTMLImageElement).parentElement!.style.display = 'none' }} @@ -1058,7 +1058,7 @@ export default function IngredientModal({ {selectedLi.most_recent_line_number != null && (
Product code from invoice { (e.target as HTMLImageElement).parentElement!.style.display = 'none' }} @@ -1246,7 +1246,7 @@ export default function IngredientModal({ {'\u2715'} Invoice line item diff --git a/frontend/src/components/Ingredients.tsx b/frontend/src/components/Ingredients.tsx index 49623b7..8cf5a5f 100644 --- a/frontend/src/components/Ingredients.tsx +++ b/frontend/src/components/Ingredients.tsx @@ -66,7 +66,7 @@ export default function Ingredients() { const { data: categories } = useQuery({ queryKey: ['ingredient-categories'], queryFn: async () => { - const res = await fetch('/api/ingredients/categories', { + const res = await fetch('/kitchen/api/ingredients/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch categories') @@ -84,7 +84,7 @@ export default function Ingredients() { if (categoryFilter) params.set('category_id', categoryFilter) if (showUnmapped) params.set('unmapped', 'true') if (showArchived) params.set('archived', 'true') - const res = await fetch(`/api/ingredients?${params}`, { + const res = await fetch(`/kitchen/api/ingredients?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch ingredients') @@ -97,7 +97,7 @@ export default function Ingredients() { const { data: sources } = useQuery({ queryKey: ['ingredient-sources', expandedId], queryFn: async () => { - const res = await fetch(`/api/ingredients/${expandedId}/sources`, { + const res = await fetch(`/kitchen/api/ingredients/${expandedId}/sources`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch sources') @@ -108,7 +108,7 @@ export default function Ingredients() { const archiveMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/ingredients/${id}`, { + const res = await fetch(`/kitchen/api/ingredients/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -119,7 +119,7 @@ export default function Ingredients() { const unarchiveMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/ingredients/${id}`, { + const res = await fetch(`/kitchen/api/ingredients/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ is_archived: false }), diff --git a/frontend/src/components/InvoiceList.tsx b/frontend/src/components/InvoiceList.tsx index 4341b87..cae64ab 100644 --- a/frontend/src/components/InvoiceList.tsx +++ b/frontend/src/components/InvoiceList.tsx @@ -100,7 +100,7 @@ export default function InvoiceList() { const { data: suppliers } = useQuery({ queryKey: ['suppliers'], queryFn: async () => { - const res = await fetch('/api/suppliers/', { + const res = await fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -119,7 +119,7 @@ export default function InvoiceList() { const { data, isLoading, error } = useQuery({ queryKey: ['invoices', statusFilter, supplierFilter, dateFrom, dateTo], queryFn: async () => { - const url = queryString ? `/api/invoices/?${queryString}` : '/api/invoices/' + const url = queryString ? `/kitchen/api/invoices/?${queryString}` : '/kitchen/api/invoices/' const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` }, }) @@ -137,7 +137,7 @@ export default function InvoiceList() { params.set('status', 'confirmed') params.set('limit', '20') params.set('sort', 'recent') - const res = await fetch(`/api/invoices/?${params}`, { + const res = await fetch(`/kitchen/api/invoices/?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch completed invoices') diff --git a/frontend/src/components/LineItemHistoryModal.tsx b/frontend/src/components/LineItemHistoryModal.tsx index cf5ed8e..06fee31 100644 --- a/frontend/src/components/LineItemHistoryModal.tsx +++ b/frontend/src/components/LineItemHistoryModal.tsx @@ -87,7 +87,7 @@ export default function LineItemHistoryModal({ if (dateFrom) params.set('date_from', dateFrom) if (dateTo) params.set('date_to', dateTo) - const res = await fetch(`/api/search/line-items/history?${params}`, { + const res = await fetch(`/kitchen/api/search/line-items/history?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch history') @@ -99,7 +99,7 @@ export default function LineItemHistoryModal({ // Acknowledge price mutation const acknowledgeMutation = useMutation({ mutationFn: async () => { - const res = await fetch('/api/search/line-items/acknowledge-price', { + const res = await fetch('/kitchen/api/search/line-items/acknowledge-price', { method: 'POST', headers: { Authorization: `Bearer ${token}`, diff --git a/frontend/src/components/LinkDisputeModal.tsx b/frontend/src/components/LinkDisputeModal.tsx index abd3c3f..4c1a64e 100644 --- a/frontend/src/components/LinkDisputeModal.tsx +++ b/frontend/src/components/LinkDisputeModal.tsx @@ -64,7 +64,7 @@ export default function LinkDisputeModal({ const { data: disputes, isLoading } = useQuery({ queryKey: ['open-disputes', supplierId], queryFn: async () => { - const res = await fetch(`/api/disputes/supplier/${supplierId}/open`, { + const res = await fetch(`/kitchen/api/disputes/supplier/${supplierId}/open`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch disputes') @@ -78,7 +78,7 @@ export default function LinkDisputeModal({ mutationFn: async () => { if (!selectedDisputeId) throw new Error('No dispute selected') - const res = await fetch(`/api/disputes/${selectedDisputeId}/link-credit-note`, { + const res = await fetch(`/kitchen/api/disputes/${selectedDisputeId}/link-credit-note`, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/frontend/src/components/MapLineItemsModal.tsx b/frontend/src/components/MapLineItemsModal.tsx index e348b1c..9d93d0a 100644 --- a/frontend/src/components/MapLineItemsModal.tsx +++ b/frontend/src/components/MapLineItemsModal.tsx @@ -95,7 +95,7 @@ export default function MapLineItemsModal({ ingredient, onClose, onSaved }: MapL const { data: suppliers } = useQuery({ queryKey: ['suppliers'], queryFn: async () => { - const res = await fetch('/api/suppliers/', { headers: { Authorization: `Bearer ${token}` } }) + const res = await fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` } }) if (!res.ok) return [] const data = await res.json() return data.suppliers || data || [] @@ -112,7 +112,7 @@ export default function MapLineItemsModal({ ingredient, onClose, onSaved }: MapL params.set('date_from', dateFrom) params.set('date_to', dateTo) params.set('limit', '50') - const res = await fetch(`/api/search/line-items?${params}`, { + const res = await fetch(`/kitchen/api/search/line-items?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return { items: [], total_count: 0 } @@ -206,7 +206,7 @@ export default function MapLineItemsModal({ ingredient, onClose, onSaved }: MapL sourceData.invoice_id = selectedItem.most_recent_invoice_id } - const res = await fetch(`/api/ingredients/${ingredient.id}/sources`, { + const res = await fetch(`/kitchen/api/ingredients/${ingredient.id}/sources`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(sourceData), @@ -233,7 +233,7 @@ export default function MapLineItemsModal({ ingredient, onClose, onSaved }: MapL // Preview URL for the selected line item const previewUrl = selectedItem?.most_recent_invoice_id && selectedItem?.most_recent_line_number != null - ? `/api/invoices/${selectedItem.most_recent_invoice_id}/line-items/${selectedItem.most_recent_line_number}/preview?token=${token}` + ? `/kitchen/api/invoices/${selectedItem.most_recent_invoice_id}/line-items/${selectedItem.most_recent_line_number}/preview?token=${token}` : null return ( diff --git a/frontend/src/components/MenuEditor.tsx b/frontend/src/components/MenuEditor.tsx index d736c13..21ac72d 100644 --- a/frontend/src/components/MenuEditor.tsx +++ b/frontend/src/components/MenuEditor.tsx @@ -84,7 +84,7 @@ export default function MenuEditor() { const { data: menu, isLoading } = useQuery({ queryKey: ['menu', menuId], queryFn: async () => { - const res = await fetch(`/api/menus/${menuId}`, { + const res = await fetch(`/kitchen/api/menus/${menuId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch menu') @@ -97,7 +97,7 @@ export default function MenuEditor() { // Mutations const updateMenuMutation = useMutation({ mutationFn: async (data: Record) => { - const res = await fetch(`/api/menus/${menuId}`, { + const res = await fetch(`/kitchen/api/menus/${menuId}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -109,7 +109,7 @@ export default function MenuEditor() { const addDivMutation = useMutation({ mutationFn: async (name: string) => { - const res = await fetch(`/api/menus/${menuId}/divisions`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/divisions`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name }), @@ -125,7 +125,7 @@ export default function MenuEditor() { const updateDivMutation = useMutation({ mutationFn: async ({ divId, name }: { divId: number; name: string }) => { - const res = await fetch(`/api/menus/${menuId}/divisions/${divId}`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/divisions/${divId}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name }), @@ -140,7 +140,7 @@ export default function MenuEditor() { const deleteDivMutation = useMutation({ mutationFn: async (divId: number) => { - const res = await fetch(`/api/menus/${menuId}/divisions/${divId}`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/divisions/${divId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -151,7 +151,7 @@ export default function MenuEditor() { const reorderDivsMutation = useMutation({ mutationFn: async (ids: number[]) => { - const res = await fetch(`/api/menus/${menuId}/divisions/reorder`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/divisions/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ids }), @@ -163,7 +163,7 @@ export default function MenuEditor() { const updateItemMutation = useMutation({ mutationFn: async ({ itemId, data }: { itemId: number; data: Record }) => { - const res = await fetch(`/api/menus/${menuId}/items/${itemId}`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/${itemId}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -178,7 +178,7 @@ export default function MenuEditor() { const deleteItemMutation = useMutation({ mutationFn: async (itemId: number) => { - const res = await fetch(`/api/menus/${menuId}/items/${itemId}`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/${itemId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -189,7 +189,7 @@ export default function MenuEditor() { const republishMutation = useMutation({ mutationFn: async ({ itemId, confirmed_by_name }: { itemId: number; confirmed_by_name: string }) => { - const res = await fetch(`/api/menus/${menuId}/items/${itemId}/republish`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/${itemId}/republish`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ confirmed_by_name }), @@ -201,7 +201,7 @@ export default function MenuEditor() { const reorderItemsMutation = useMutation({ mutationFn: async (ids: number[]) => { - const res = await fetch(`/api/menus/${menuId}/items/reorder`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ids }), @@ -213,7 +213,7 @@ export default function MenuEditor() { const batchRepublishMutation = useMutation({ mutationFn: async (body: { confirmed_by_name: string; items: Array<{ id: number; confirmed: boolean }> }) => { - const res = await fetch(`/api/menus/${menuId}/republish-stale`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/republish-stale`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), @@ -231,7 +231,7 @@ export default function MenuEditor() { mutationFn: async ({ itemId, file }: { itemId: number; file: File }) => { const formData = new FormData() formData.append('file', file) - const res = await fetch(`/api/menus/${menuId}/items/${itemId}/image`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/${itemId}/image`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: formData, @@ -243,7 +243,7 @@ export default function MenuEditor() { const deleteImageMutation = useMutation({ mutationFn: async (itemId: number) => { - const res = await fetch(`/api/menus/${menuId}/items/${itemId}/image`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/items/${itemId}/image`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -471,7 +471,7 @@ export default function MenuEditor() { {/* Image thumbnail */} {item.has_image ? ( diff --git a/frontend/src/components/MenuFlagMatrix.tsx b/frontend/src/components/MenuFlagMatrix.tsx index 629de23..75e56a9 100644 --- a/frontend/src/components/MenuFlagMatrix.tsx +++ b/frontend/src/components/MenuFlagMatrix.tsx @@ -39,7 +39,7 @@ export default function MenuFlagMatrix({ menuId, menuName, onClose }: Props) { const { data, isLoading } = useQuery({ queryKey: ['menu-flag-matrix', menuId], queryFn: async () => { - const res = await fetch(`/api/menus/${menuId}/flags`, { + const res = await fetch(`/kitchen/api/menus/${menuId}/flags`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') diff --git a/frontend/src/components/MenuList.tsx b/frontend/src/components/MenuList.tsx index b05e4d6..c360445 100644 --- a/frontend/src/components/MenuList.tsx +++ b/frontend/src/components/MenuList.tsx @@ -37,7 +37,7 @@ export default function MenuList() { const { data: menus, isLoading } = useQuery({ queryKey: ['menus'], queryFn: async () => { - const res = await fetch('/api/menus', { + const res = await fetch('/kitchen/api/menus', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch menus') @@ -49,7 +49,7 @@ export default function MenuList() { const createMutation = useMutation({ mutationFn: async (data: { name: string; description: string | null; notes: string | null; preset_divisions: boolean }) => { - const res = await fetch('/api/menus', { + const res = await fetch('/kitchen/api/menus', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -72,7 +72,7 @@ export default function MenuList() { const toggleActiveMutation = useMutation({ mutationFn: async ({ id, is_active }: { id: number; is_active: boolean }) => { - const res = await fetch(`/api/menus/${id}`, { + const res = await fetch(`/kitchen/api/menus/${id}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ is_active }), @@ -84,7 +84,7 @@ export default function MenuList() { const deleteMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/menus/${id}`, { + const res = await fetch(`/kitchen/api/menus/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -95,7 +95,7 @@ export default function MenuList() { const duplicateMutation = useMutation({ mutationFn: async ({ id, name }: { id: number; name: string }) => { - const res = await fetch(`/api/menus/${id}/duplicate`, { + const res = await fetch(`/kitchen/api/menus/${id}/duplicate`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name }), @@ -116,7 +116,7 @@ export default function MenuList() { const reorderMutation = useMutation({ mutationFn: async (ids: number[]) => { - const res = await fetch('/api/menus/reorder', { + const res = await fetch('/kitchen/api/menus/reorder', { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ids }), diff --git a/frontend/src/components/PriceImpact.tsx b/frontend/src/components/PriceImpact.tsx index 38087e1..389961f 100644 --- a/frontend/src/components/PriceImpact.tsx +++ b/frontend/src/components/PriceImpact.tsx @@ -48,7 +48,7 @@ export default function PriceImpact() { const { data, isLoading } = useQuery({ queryKey: ['price-impact', days], queryFn: async () => { - const res = await fetch(`/api/recipes/price-impact?days=${days}`, { + const res = await fetch(`/kitchen/api/recipes/price-impact?days=${days}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch price impact') diff --git a/frontend/src/components/PublishToMenuModal.tsx b/frontend/src/components/PublishToMenuModal.tsx index 382f10f..94d6950 100644 --- a/frontend/src/components/PublishToMenuModal.tsx +++ b/frontend/src/components/PublishToMenuModal.tsx @@ -58,7 +58,7 @@ export default function PublishToMenuModal({ const { data: llmSettings } = useQuery<{ llm_enabled: boolean; anthropic_api_key_set: boolean }>({ queryKey: ['settings'], queryFn: async () => { - const res = await fetch('/api/settings/', { headers: { Authorization: `Bearer ${token}` } }) + const res = await fetch('/kitchen/api/settings/', { headers: { Authorization: `Bearer ${token}` } }) if (!res.ok) return { llm_enabled: false, anthropic_api_key_set: false } return res.json() }, @@ -70,7 +70,7 @@ export default function PublishToMenuModal({ if (!recipeIdToUse) return setAiDescLoading(true) try { - const res = await fetch('/api/menus/generate-description', { + const res = await fetch('/kitchen/api/menus/generate-description', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ recipe_id: recipeIdToUse, recipe_name: displayName || recipeName || '', ingredients: [], allergen_flags: [] }), @@ -87,7 +87,7 @@ export default function PublishToMenuModal({ const { data: dishes } = useQuery>({ queryKey: ['dishes-for-menu'], queryFn: async () => { - const res = await fetch('/api/recipes?recipe_type=dish', { + const res = await fetch('/kitchen/api/recipes?recipe_type=dish', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch dishes') @@ -100,7 +100,7 @@ export default function PublishToMenuModal({ const { data: menus } = useQuery>({ queryKey: ['menus-for-publish'], queryFn: async () => { - const res = await fetch('/api/menus', { + const res = await fetch('/kitchen/api/menus', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch menus') @@ -113,7 +113,7 @@ export default function PublishToMenuModal({ const { data: menuDetail } = useQuery<{ divisions: Division[] }>({ queryKey: ['menu-divisions', selectedMenuId], queryFn: async () => { - const res = await fetch(`/api/menus/${selectedMenuId}`, { + const res = await fetch(`/kitchen/api/menus/${selectedMenuId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -129,7 +129,7 @@ export default function PublishToMenuModal({ }>({ queryKey: ['recipe-flags-for-publish', selectedRecipeId], queryFn: async () => { - const res = await fetch(`/api/food-flags/recipes/${selectedRecipeId}/flags`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${selectedRecipeId}/flags`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed') @@ -158,7 +158,7 @@ export default function PublishToMenuModal({ const publishMutation = useMutation({ mutationFn: async () => { - const res = await fetch(`/api/menus/${selectedMenuId}/items`, { + const res = await fetch(`/kitchen/api/menus/${selectedMenuId}/items`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ diff --git a/frontend/src/components/PurchaseOrderList.tsx b/frontend/src/components/PurchaseOrderList.tsx index 12cfcd4..1d892ef 100644 --- a/frontend/src/components/PurchaseOrderList.tsx +++ b/frontend/src/components/PurchaseOrderList.tsx @@ -35,7 +35,7 @@ export default function PurchaseOrderList() { const { data: suppliersData } = useQuery<{ suppliers: Array<{ id: number; name: string }> }>({ queryKey: ['suppliers'], queryFn: async () => { - const res = await fetch('/api/suppliers/', { + const res = await fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch suppliers') @@ -52,7 +52,7 @@ export default function PurchaseOrderList() { const { data: poList, refetch } = useQuery({ queryKey: ['purchase-orders', statusFilter, supplierFilter], queryFn: async () => { - const res = await fetch(`/api/purchase-orders/?${params}`, { + const res = await fetch(`/kitchen/api/purchase-orders/?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch purchase orders') diff --git a/frontend/src/components/PurchaseOrderModal.tsx b/frontend/src/components/PurchaseOrderModal.tsx index aa17787..fdc0e73 100644 --- a/frontend/src/components/PurchaseOrderModal.tsx +++ b/frontend/src/components/PurchaseOrderModal.tsx @@ -64,7 +64,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def // Load suppliers (including order_email for email button visibility) useEffect(() => { if (!token) return - fetch('/api/suppliers/', { headers: { Authorization: `Bearer ${token}` } }) + fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` } }) .then(r => r.json()) .then(data => setSuppliers(data.suppliers || data || [])) .catch(() => {}) @@ -73,7 +73,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def // Check if SMTP is configured (for email button visibility) useEffect(() => { if (!token) return - fetch('/api/settings/', { headers: { Authorization: `Bearer ${token}` } }) + fetch('/kitchen/api/settings/', { headers: { Authorization: `Bearer ${token}` } }) .then(r => r.json()) .then(data => setSmtpConfigured(!!(data.smtp_host && data.smtp_from_email))) .catch(() => setSmtpConfigured(false)) @@ -83,7 +83,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def useEffect(() => { if (!poId || !token) return setLoading(true) - fetch(`/api/purchase-orders/${poId}`, { headers: { Authorization: `Bearer ${token}` } }) + fetch(`/kitchen/api/purchase-orders/${poId}`, { headers: { Authorization: `Bearer ${token}` } }) .then(r => { if (!r.ok) throw new Error('Failed to load') return r.json() @@ -144,7 +144,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def searchTimeout.current = setTimeout(() => { const params = new URLSearchParams({ query: searchQuery }) if (supplierId) params.append('supplier_id', String(supplierId)) - fetch(`/api/purchase-orders/products/search?${params}`, { + fetch(`/kitchen/api/purchase-orders/products/search?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) .then(r => r.json()) @@ -243,7 +243,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def } try { - const url = poId ? `/api/purchase-orders/${poId}` : '/api/purchase-orders/' + const url = poId ? `/kitchen/api/purchase-orders/${poId}` : '/kitchen/api/purchase-orders/' const method = poId ? 'PUT' : 'POST' const res = await fetch(url, { method, @@ -269,7 +269,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def const form = new FormData() form.append('file', file) try { - const res = await fetch(`/api/purchase-orders/${poId}/attachment`, { + const res = await fetch(`/kitchen/api/purchase-orders/${poId}/attachment`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: form, @@ -285,7 +285,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def const handleRemoveAttachment = async () => { if (!poId || !token) return try { - await fetch(`/api/purchase-orders/${poId}/attachment`, { + await fetch(`/kitchen/api/purchase-orders/${poId}/attachment`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -299,7 +299,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def if (!poId || !token) return if (!confirm('Delete this purchase order?')) return try { - const res = await fetch(`/api/purchase-orders/${poId}`, { + const res = await fetch(`/kitchen/api/purchase-orders/${poId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -346,14 +346,14 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def ...(orderType === 'single_value' ? { total_amount: totalAmount } : {}), } try { - const res = await fetch('/api/purchase-orders/', { + const res = await fetch('/kitchen/api/purchase-orders/', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), }) if (!res.ok) throw new Error('Failed to save') const data = await res.json() - window.open(`/api/purchase-orders/${data.id}/preview?token=${encodeURIComponent(token || '')}`, '_blank') + window.open(`/kitchen/api/purchase-orders/${data.id}/preview?token=${encodeURIComponent(token || '')}`, '_blank') onSaved() onClose() } catch (e: any) { @@ -364,7 +364,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def } else { // Existing PO — save current state then preview await handleSave() - window.open(`/api/purchase-orders/${poId}/preview?token=${encodeURIComponent(token || '')}`, '_blank') + window.open(`/kitchen/api/purchase-orders/${poId}/preview?token=${encodeURIComponent(token || '')}`, '_blank') } } @@ -400,7 +400,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def } try { - const url = poId ? `/api/purchase-orders/${poId}` : '/api/purchase-orders/' + const url = poId ? `/kitchen/api/purchase-orders/${poId}` : '/kitchen/api/purchase-orders/' const method = poId ? 'PUT' : 'POST' const saveRes = await fetch(url, { method, @@ -411,7 +411,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def const savedPo = await saveRes.json() // Now send the email - const emailRes = await fetch(`/api/purchase-orders/${savedPo.id}/send-email`, { + const emailRes = await fetch(`/kitchen/api/purchase-orders/${savedPo.id}/send-email`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -712,7 +712,7 @@ export default function PurchaseOrderModal({ isOpen, onClose, onSaved, poId, def )} {!isEditable && poId && ( - )} diff --git a/frontend/src/components/Purchases.tsx b/frontend/src/components/Purchases.tsx index 862933d..06e392f 100644 --- a/frontend/src/components/Purchases.tsx +++ b/frontend/src/components/Purchases.tsx @@ -281,7 +281,7 @@ export default function Purchases() { const { data, isLoading, error } = useQuery({ queryKey: ['purchases-range', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/purchases/range?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/purchases/range?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch purchases') @@ -293,7 +293,7 @@ export default function Purchases() { const { data: disputeStats } = useQuery({ queryKey: ['daily-dispute-stats', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/disputes/stats/daily?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/disputes/stats/daily?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch dispute stats') @@ -305,7 +305,7 @@ export default function Purchases() { const { data: allowanceStats } = useQuery({ queryKey: ['daily-allowance-stats', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/logbook/daily-stats?date_from=${submittedFromDate}&date_to=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/logbook/daily-stats?date_from=${submittedFromDate}&date_to=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch allowance stats') @@ -379,7 +379,7 @@ export default function Purchases() { const { data: weeklyChartData, isLoading: weeklyChartLoading, error: weeklyChartError } = useQuery({ queryKey: ['weekly-chart-data', weeklyChartDateRange.from, weeklyChartDateRange.to], queryFn: async () => { - const res = await fetch(`/api/reports/gp/daily?from_date=${weeklyChartDateRange.from}&to_date=${weeklyChartDateRange.to}`, { + const res = await fetch(`/kitchen/api/reports/gp/daily?from_date=${weeklyChartDateRange.from}&to_date=${weeklyChartDateRange.to}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch weekly chart data') diff --git a/frontend/src/components/PurchasesReport.tsx b/frontend/src/components/PurchasesReport.tsx index 58a875f..a30ad27 100644 --- a/frontend/src/components/PurchasesReport.tsx +++ b/frontend/src/components/PurchasesReport.tsx @@ -270,7 +270,7 @@ export default function PurchasesReport() { const { data: summary, isLoading, error } = useQuery({ queryKey: ['purchases-summary', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/purchases/summary?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/purchases/summary?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch purchases summary') @@ -284,7 +284,7 @@ export default function PurchasesReport() { const { data: chartData } = useQuery({ queryKey: ['purchases-daily-supplier', submittedFromDate, submittedToDate], queryFn: async () => { - const res = await fetch(`/api/reports/purchases/daily-by-supplier?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { + const res = await fetch(`/kitchen/api/reports/purchases/daily-by-supplier?from_date=${submittedFromDate}&to_date=${submittedToDate}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch chart data') @@ -298,7 +298,7 @@ export default function PurchasesReport() { const { data: topItems } = useQuery({ queryKey: ['purchases-top-items', submittedFromDate, submittedToDate, topItemsSupplierFilter], queryFn: async () => { - let url = `/api/reports/purchases/top-items?from_date=${submittedFromDate}&to_date=${submittedToDate}` + let url = `/kitchen/api/reports/purchases/top-items?from_date=${submittedFromDate}&to_date=${submittedToDate}` if (topItemsSupplierFilter !== null) { url += `&supplier_id=${topItemsSupplierFilter}` } diff --git a/frontend/src/components/RecipeEditor.tsx b/frontend/src/components/RecipeEditor.tsx index 372aa4b..260edab 100644 --- a/frontend/src/components/RecipeEditor.tsx +++ b/frontend/src/components/RecipeEditor.tsx @@ -284,7 +284,7 @@ export default function RecipeEditor() { const { data: recipe } = useQuery({ queryKey: ['recipe', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Not found') @@ -297,7 +297,7 @@ export default function RecipeEditor() { const { data: sections } = useQuery({ queryKey: ['recipe-sections'], queryFn: async () => { - const res = await fetch('/api/recipes/menu-sections?section_type=recipe', { + const res = await fetch('/kitchen/api/recipes/menu-sections?section_type=recipe', { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -309,7 +309,7 @@ export default function RecipeEditor() { const { data: costData } = useQuery({ queryKey: ['recipe-cost', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/costing`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/costing`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -321,7 +321,7 @@ export default function RecipeEditor() { const { data: scaledCostData } = useQuery({ queryKey: ['recipe-cost-scaled', recipeId, scalePortions], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/costing?scale_to=${scalePortions}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/costing?scale_to=${scalePortions}`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -333,7 +333,7 @@ export default function RecipeEditor() { const { data: flagData } = useQuery({ queryKey: ['recipe-flags', recipeId], queryFn: async () => { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/flags`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/flags`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -345,7 +345,7 @@ export default function RecipeEditor() { const { data: flagCategories } = useQuery>({ queryKey: ['food-flag-categories'], queryFn: async () => { - const res = await fetch('/api/food-flags/categories', { + const res = await fetch('/kitchen/api/food-flags/categories', { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -357,7 +357,7 @@ export default function RecipeEditor() { const { data: changeLog } = useQuery({ queryKey: ['recipe-changelog', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/change-log`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/change-log`, { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -369,7 +369,7 @@ export default function RecipeEditor() { const { data: costTrendRaw } = useQuery({ queryKey: ['recipe-cost-trend', recipeId], queryFn: async () => { - const res = await fetch(`/api/recipes/${recipeId}/cost-trend`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/cost-trend`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch cost trend') @@ -382,7 +382,7 @@ export default function RecipeEditor() { const { data: editIngData } = useQuery({ queryKey: ['ingredient-edit', editIngId], queryFn: async () => { - const res = await fetch(`/api/ingredients/${editIngId}`, { + const res = await fetch(`/kitchen/api/ingredients/${editIngId}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Not found') @@ -408,7 +408,7 @@ export default function RecipeEditor() { const { data: availableRecipes } = useQuery>({ queryKey: ['recipes-list-for-sub'], queryFn: async () => { - const res = await fetch('/api/recipes?recipe_type=component', { + const res = await fetch('/kitchen/api/recipes?recipe_type=component', { headers: { Authorization: `Bearer ${token}` }, }) return res.json() @@ -438,7 +438,7 @@ export default function RecipeEditor() { if (!ingSearch || ingSearch.length < 2 || !token) return const timer = setTimeout(async () => { try { - const res = await fetch(`/api/ingredients/suggest?description=${encodeURIComponent(ingSearch)}`, { + const res = await fetch(`/kitchen/api/ingredients/suggest?description=${encodeURIComponent(ingSearch)}`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -455,7 +455,7 @@ export default function RecipeEditor() { // Mutations const updateMutation = useMutation({ mutationFn: async (data: Record) => { - const res = await fetch(`/api/recipes/${recipeId}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -473,7 +473,7 @@ export default function RecipeEditor() { const addIngMutation = useMutation({ mutationFn: async (data: { ingredient_id: number; quantity: number; unit?: string; notes?: string }) => { - const res = await fetch(`/api/recipes/${recipeId}/ingredients`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/ingredients`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -498,7 +498,7 @@ export default function RecipeEditor() { const updateIngMutation = useMutation({ mutationFn: async ({ riId, quantity, unit, yield_percent, notes }: { riId: number; quantity?: number; unit?: string; yield_percent?: number; notes?: string }) => { - const res = await fetch(`/api/recipes/recipe-ingredients/${riId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-ingredients/${riId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ quantity, unit, yield_percent, notes }), @@ -516,7 +516,7 @@ export default function RecipeEditor() { const removeIngMutation = useMutation({ mutationFn: async (riId: number) => { - const res = await fetch(`/api/recipes/recipe-ingredients/${riId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-ingredients/${riId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -533,7 +533,7 @@ export default function RecipeEditor() { const addSubMutation = useMutation({ mutationFn: async (data: { child_recipe_id: number; portions_needed: number; portions_needed_unit?: string }) => { - const res = await fetch(`/api/recipes/${recipeId}/sub-recipes`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/sub-recipes`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -554,7 +554,7 @@ export default function RecipeEditor() { const removeSubMutation = useMutation({ mutationFn: async (srId: number) => { - const res = await fetch(`/api/recipes/recipe-sub-recipes/${srId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-sub-recipes/${srId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -570,7 +570,7 @@ export default function RecipeEditor() { const addStepMutation = useMutation({ mutationFn: async (data: { title?: string; instruction: string; step_number: number; duration_minutes?: number }) => { - const res = await fetch(`/api/recipes/${recipeId}/steps`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/steps`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -588,7 +588,7 @@ export default function RecipeEditor() { const updateStepMutation = useMutation({ mutationFn: async ({ stepId, data }: { stepId: number; data: { title?: string; instruction?: string; duration_minutes?: number } }) => { - const res = await fetch(`/api/recipes/recipe-steps/${stepId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-steps/${stepId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -607,7 +607,7 @@ export default function RecipeEditor() { const removeStepMutation = useMutation({ mutationFn: async (stepId: number) => { - const res = await fetch(`/api/recipes/recipe-steps/${stepId}`, { + const res = await fetch(`/kitchen/api/recipes/recipe-steps/${stepId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -623,7 +623,7 @@ export default function RecipeEditor() { formData.append('file', file) formData.append('caption', caption) formData.append('image_type', image_type) - const res = await fetch(`/api/recipes/${recipeId}/images`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/images`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: formData, @@ -641,7 +641,7 @@ export default function RecipeEditor() { // Delete image mutation const deleteImageMutation = useMutation({ mutationFn: async (imageId: number) => { - const res = await fetch(`/api/recipes/${recipeId}/images/${imageId}`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/images/${imageId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -655,7 +655,7 @@ export default function RecipeEditor() { // Batch reorder ingredients const reorderIngMutation = useMutation({ mutationFn: async (ingredientIds: number[]) => { - const res = await fetch(`/api/recipes/${recipeId}/ingredients/reorder`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/ingredients/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ingredient_ids: ingredientIds }), @@ -670,7 +670,7 @@ export default function RecipeEditor() { // Batch reorder sub-recipes const reorderSubMutation = useMutation({ mutationFn: async (subRecipeIds: number[]) => { - const res = await fetch(`/api/recipes/${recipeId}/sub-recipes/reorder`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/sub-recipes/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ sub_recipe_ids: subRecipeIds }), @@ -685,7 +685,7 @@ export default function RecipeEditor() { // Reorder steps mutation const reorderStepsMutation = useMutation({ mutationFn: async (stepIds: number[]) => { - const res = await fetch(`/api/recipes/${recipeId}/steps/reorder`, { + const res = await fetch(`/kitchen/api/recipes/${recipeId}/steps/reorder`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ step_ids: stepIds }), @@ -769,7 +769,7 @@ export default function RecipeEditor() { } const handlePrint = (format: string) => { - window.open(`/api/recipes/${recipeId}/print?format=${format}&token=${token}`, '_blank') + window.open(`/kitchen/api/recipes/${recipeId}/print?format=${format}&token=${token}`, '_blank') } if (!recipe) return
Loading recipe...
@@ -893,7 +893,7 @@ export default function RecipeEditor() { style={{ marginLeft: 'auto', background: 'none', border: '1px solid #b4530955', borderRadius: '4px', color: '#b45309', cursor: 'pointer', padding: '0.15rem 0.5rem', fontSize: '0.8rem', whiteSpace: 'nowrap' }} onClick={async () => { try { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/text-dismissals`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/text-dismissals`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ @@ -1309,10 +1309,10 @@ export default function RecipeEditor() { {recipe.images.map(img => (
{img.caption setLightboxImg(`/api/recipes/${recipeId}/images/${img.id}?token=${token}`)} + onClick={() => setLightboxImg(`/kitchen/api/recipes/${recipeId}/images/${img.id}?token=${token}`)} />
{img.caption &&
{img.caption}
} diff --git a/frontend/src/components/RecipeFlagMatrix.tsx b/frontend/src/components/RecipeFlagMatrix.tsx index f95faac..3304ce6 100644 --- a/frontend/src/components/RecipeFlagMatrix.tsx +++ b/frontend/src/components/RecipeFlagMatrix.tsx @@ -45,7 +45,7 @@ export default function RecipeFlagMatrix({ recipeId, categoryId }: Props) { const { data: rawData, isLoading } = useQuery({ queryKey: ['recipe-flag-matrix', recipeId], queryFn: async () => { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/flags/matrix`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/flags/matrix`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch matrix') @@ -62,7 +62,7 @@ export default function RecipeFlagMatrix({ recipeId, categoryId }: Props) { const toggleMutation = useMutation({ mutationFn: async ({ ingredientId, flagId, hasFlag }: { ingredientId: number; flagId: number; hasFlag: boolean }) => { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/flags/matrix`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/flags/matrix`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ updates: [{ ingredient_id: ingredientId, food_flag_id: flagId, has_flag: hasFlag }] }), @@ -86,7 +86,7 @@ export default function RecipeFlagMatrix({ recipeId, categoryId }: Props) { const toggleNoneMutation = useMutation({ mutationFn: async ({ ingredientId, catId }: { ingredientId: number; catId: number }) => { - const res = await fetch(`/api/food-flags/recipes/${recipeId}/flags/matrix/none`, { + const res = await fetch(`/kitchen/api/food-flags/recipes/${recipeId}/flags/matrix/none`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ingredient_id: ingredientId, category_id: catId }), diff --git a/frontend/src/components/RecipeList.tsx b/frontend/src/components/RecipeList.tsx index 87921e6..bf9bf10 100644 --- a/frontend/src/components/RecipeList.tsx +++ b/frontend/src/components/RecipeList.tsx @@ -81,7 +81,7 @@ export default function RecipeList() { const { data: sections } = useQuery({ queryKey: ['recipe-sections'], queryFn: async () => { - const res = await fetch('/api/recipes/menu-sections?section_type=recipe', { + const res = await fetch('/kitchen/api/recipes/menu-sections?section_type=recipe', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch sections') @@ -98,7 +98,7 @@ export default function RecipeList() { if (search) params.set('search', search) if (sectionFilter) params.set('menu_section_id', sectionFilter) if (showArchived) params.set('archived', 'true') - const res = await fetch(`/api/recipes?${params}`, { + const res = await fetch(`/kitchen/api/recipes?${params}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch recipes') @@ -109,7 +109,7 @@ export default function RecipeList() { const createMutation = useMutation({ mutationFn: async (data: Record) => { - const res = await fetch('/api/recipes', { + const res = await fetch('/kitchen/api/recipes', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(data), @@ -126,7 +126,7 @@ export default function RecipeList() { const duplicateMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/${id}/duplicate`, { + const res = await fetch(`/kitchen/api/recipes/${id}/duplicate`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -141,7 +141,7 @@ export default function RecipeList() { const archiveMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/${id}`, { + const res = await fetch(`/kitchen/api/recipes/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -152,7 +152,7 @@ export default function RecipeList() { const unarchiveMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/${id}`, { + const res = await fetch(`/kitchen/api/recipes/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ is_archived: false }), @@ -164,7 +164,7 @@ export default function RecipeList() { const createSectionMutation = useMutation({ mutationFn: async (name: string) => { - const res = await fetch('/api/recipes/menu-sections', { + const res = await fetch('/kitchen/api/recipes/menu-sections', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name, section_type: 'recipe' }), @@ -181,7 +181,7 @@ export default function RecipeList() { const updateSectionMutation = useMutation({ mutationFn: async ({ id, name }: { id: number; name: string }) => { - const res = await fetch(`/api/recipes/menu-sections/${id}`, { + const res = await fetch(`/kitchen/api/recipes/menu-sections/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name }), @@ -199,7 +199,7 @@ export default function RecipeList() { const deleteSectionMutation = useMutation({ mutationFn: async (id: number) => { - const res = await fetch(`/api/recipes/menu-sections/${id}`, { + const res = await fetch(`/kitchen/api/recipes/menu-sections/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -215,7 +215,7 @@ export default function RecipeList() { const { data: flagCategories } = useQuery }>>({ queryKey: ['food-flag-categories'], queryFn: async () => { - const res = await fetch('/api/food-flags/categories', { + const res = await fetch('/kitchen/api/food-flags/categories', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch flag categories') diff --git a/frontend/src/components/ReconcilePurchases.tsx b/frontend/src/components/ReconcilePurchases.tsx index c76d6d2..e61b3d0 100644 --- a/frontend/src/components/ReconcilePurchases.tsx +++ b/frontend/src/components/ReconcilePurchases.tsx @@ -83,7 +83,7 @@ export default function ReconcilePurchases() { mutationFn: async (file: File) => { const formData = new FormData() formData.append('file', file) - const res = await fetch('/api/reports/purchases/reconcile', { + const res = await fetch('/kitchen/api/reports/purchases/reconcile', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: formData, diff --git a/frontend/src/components/Review.tsx b/frontend/src/components/Review.tsx index 519f1e3..33ee4e1 100644 --- a/frontend/src/components/Review.tsx +++ b/frontend/src/components/Review.tsx @@ -541,7 +541,7 @@ export default function Review() { const { data: invoice, isLoading, refetch: refetchInvoice } = useQuery({ queryKey: ['invoice', id], queryFn: async () => { - const res = await fetch(`/api/invoices/${id}`, { + const res = await fetch(`/kitchen/api/invoices/${id}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch invoice') @@ -553,13 +553,13 @@ export default function Review() { // Direct URL with token - simpler approach const imageUrl = invoice - ? `/api/invoices/${id}/file?token=${encodeURIComponent(token || '')}#toolbar=0&navpanes=0&view=FitH` + ? `/kitchen/api/invoices/${id}/file?token=${encodeURIComponent(token || '')}#toolbar=0&navpanes=0&view=FitH` : null const { data: lineItems, refetch: refetchLineItems } = useQuery({ queryKey: ['invoice-line-items', id], queryFn: async () => { - const res = await fetch(`/api/invoices/${id}/line-items`, { + const res = await fetch(`/kitchen/api/invoices/${id}/line-items`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch line items') @@ -576,7 +576,7 @@ export default function Review() { }>>({ queryKey: ['invoice-stock-history', id], queryFn: async () => { - const res = await fetch(`/api/invoices/${id}/stock-history`, { + const res = await fetch(`/kitchen/api/invoices/${id}/stock-history`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch stock history') @@ -588,7 +588,7 @@ export default function Review() { const { data: duplicateInfo } = useQuery({ queryKey: ['invoice-duplicates', id], queryFn: async () => { - const res = await fetch(`/api/invoices/${id}/duplicates`, { + const res = await fetch(`/kitchen/api/invoices/${id}/duplicates`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch duplicates') @@ -600,7 +600,7 @@ export default function Review() { const { data: rawOcrData } = useQuery<{ raw_json: any; raw_text: string }>({ queryKey: ['invoice-ocr-data', id], queryFn: async () => { - const res = await fetch(`/api/invoices/${id}/ocr-data`, { + const res = await fetch(`/kitchen/api/invoices/${id}/ocr-data`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch OCR data') @@ -612,7 +612,7 @@ export default function Review() { const { data: settings } = useQuery({ queryKey: ['settings'], queryFn: async () => { - const res = await fetch('/api/settings/', { + const res = await fetch('/kitchen/api/settings/', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to fetch settings') @@ -637,7 +637,7 @@ export default function Review() { const uniqueItems = Array.from(new Map(items.map(i => [i.description.toLowerCase(), i])).values()) if (uniqueItems.length === 0) return - fetch('/api/ingredients/sources/alias-suggestions', { + fetch('/kitchen/api/ingredients/sources/alias-suggestions', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ supplier_id: parseInt(supplierId), items: uniqueItems }), @@ -885,7 +885,7 @@ export default function Review() { const { data: suppliers } = useQuery({ queryKey: ['suppliers'], queryFn: async () => { - const res = await fetch('/api/suppliers/', { + const res = await fetch('/kitchen/api/suppliers/', { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return [] @@ -915,7 +915,7 @@ export default function Review() { }>({ queryKey: ['po-match', id], queryFn: async () => { - const res = await fetch(`/api/purchase-orders/matching/for-invoice?invoice_id=${id}`, { + const res = await fetch(`/kitchen/api/purchase-orders/matching/for-invoice?invoice_id=${id}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) return { matches: [], linked_po: null } @@ -944,7 +944,7 @@ export default function Review() { const pollInterval = setInterval(async () => { try { - const checkRes = await fetch(`/api/invoices/${id}`, { + const checkRes = await fetch(`/kitchen/api/invoices/${id}`, { headers: { Authorization: `Bearer ${token}` }, }) if (checkRes.ok) { @@ -971,7 +971,7 @@ export default function Review() { try { // Fetch the PDF - const pdfUrl = `/api/invoices/${id}/file?token=${encodeURIComponent(token)}` + const pdfUrl = `/kitchen/api/invoices/${id}/file?token=${encodeURIComponent(token)}` const response = await fetch(pdfUrl) const arrayBuffer = await response.arrayBuffer() @@ -1041,7 +1041,7 @@ export default function Review() { const updateMutation = useMutation({ mutationFn: async (data: Partial) => { - const res = await fetch(`/api/invoices/${id}`, { + const res = await fetch(`/kitchen/api/invoices/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, @@ -1067,7 +1067,7 @@ export default function Review() { const deleteMutation = useMutation({ mutationFn: async () => { - const res = await fetch(`/api/invoices/${id}`, { + const res = await fetch(`/kitchen/api/invoices/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) @@ -1082,7 +1082,7 @@ export default function Review() { const updateLineItemMutation = useMutation({ mutationFn: async ({ itemId, data }: { itemId: number; data: Partial }) => { - const res = await fetch(`/api/invoices/${id}/line-items/${itemId}`, { + const res = await fetch(`/kitchen/api/invoices/${id}/line-items/${itemId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, @@ -1104,7 +1104,7 @@ export default function Review() { const createLineItemMutation = useMutation({ mutationFn: async (data: Partial) => { - const res = await fetch(`/api/invoices/${id}/line-items`, { + const res = await fetch(`/kitchen/api/invoices/${id}/line-items`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, @@ -1125,7 +1125,7 @@ export default function Review() { const deleteLineItemMutation = useMutation({ mutationFn: async (itemId: number) => { - const res = await fetch(`/api/invoices/${id}/line-items/${itemId}`, { + const res = await fetch(`/kitchen/api/invoices/${id}/line-items/${itemId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}`, @@ -1143,7 +1143,7 @@ export default function Review() { const saveDefinitionMutation = useMutation({ mutationFn: async ({ itemId, portionDesc }: { itemId: number; portionDesc?: string }) => { - const res = await fetch(`/api/invoices/${id}/line-items/${itemId}/save-definition`, { + const res = await fetch(`/kitchen/api/invoices/${id}/line-items/${itemId}/save-definition`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, @@ -1161,7 +1161,7 @@ export default function Review() { const createSupplierMutation = useMutation({ mutationFn: async (name: string) => { - const res = await fetch('/api/suppliers/', { + const res = await fetch('/kitchen/api/suppliers/', { method: 'POST', headers: { Authorization: `Bearer ${token}`, @@ -1182,7 +1182,7 @@ export default function Review() { const addAliasMutation = useMutation({ mutationFn: async ({ supplierId, alias, invoiceId }: { supplierId: number; alias: string; invoiceId?: number }) => { - const res = await fetch(`/api/suppliers/${supplierId}/aliases`, { + const res = await fetch(`/kitchen/api/suppliers/${supplierId}/aliases`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, @@ -1201,7 +1201,7 @@ export default function Review() { const addDescriptionAliasMutation = useMutation({ mutationFn: async ({ sourceId, alias }: { sourceId: number; alias: string }) => { - const res = await fetch(`/api/ingredients/sources/${sourceId}/aliases`, { + const res = await fetch(`/kitchen/api/ingredients/sources/${sourceId}/aliases`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, @@ -1228,7 +1228,7 @@ export default function Review() { // PO link/unlink handlers const handleLinkPo = async (poId: number) => { try { - const res = await fetch(`/api/purchase-orders/${poId}/link`, { + const res = await fetch(`/kitchen/api/purchase-orders/${poId}/link`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ invoice_id: parseInt(id!) }), @@ -1242,7 +1242,7 @@ export default function Review() { const handleUnlinkPo = async (poId: number) => { try { - const res = await fetch(`/api/purchase-orders/${poId}/unlink`, { + const res = await fetch(`/kitchen/api/purchase-orders/${poId}/unlink`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -1386,7 +1386,7 @@ export default function Review() { setAdminOperationResult(null) try { - const res = await fetch(`/api/invoices/${id}/mark-dext-sent`, { + const res = await fetch(`/kitchen/api/invoices/${id}/mark-dext-sent`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -1423,7 +1423,7 @@ export default function Review() { setAdminOperationResult(null) try { - const res = await fetch(`/api/invoices/${id}/reprocess`, { + const res = await fetch(`/kitchen/api/invoices/${id}/reprocess`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -1457,7 +1457,7 @@ export default function Review() { setShowDatePickerModal(true) try { - const res = await fetch(`/api/invoices/${id}/parse-dates`, { + const res = await fetch(`/kitchen/api/invoices/${id}/parse-dates`, { headers: { Authorization: `Bearer ${token}` }, }) @@ -1485,7 +1485,7 @@ export default function Review() { setInvoiceNumberExamples([]) setShowInvoiceNumberModal(true) try { - const res = await fetch(`/api/invoices/${id}/parse-invoice-number`, { + const res = await fetch(`/kitchen/api/invoices/${id}/parse-invoice-number`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) throw new Error('Failed to search for invoice number') @@ -1513,7 +1513,7 @@ export default function Review() { setAdminOperationResult(null) try { - const res = await fetch(`/api/invoices/${id}/resend-to-azure`, { + const res = await fetch(`/kitchen/api/invoices/${id}/resend-to-azure`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -1532,7 +1532,7 @@ export default function Review() { // Poll for completion const pollInterval = setInterval(async () => { try { - const checkRes = await fetch(`/api/invoices/${id}`, { + const checkRes = await fetch(`/kitchen/api/invoices/${id}`, { headers: { Authorization: `Bearer ${token}` }, }) if (checkRes.ok) { @@ -1565,7 +1565,7 @@ export default function Review() { setAdminOperationResult(null) try { - const res = await fetch(`/api/invoices/${id}/regenerate-highlights`, { + const res = await fetch(`/kitchen/api/invoices/${id}/regenerate-highlights`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -1756,7 +1756,7 @@ export default function Review() { if (!query || query.length < 2) return setSearchLoading(true) try { - const res = await fetch('/api/invoices/line-items/search', { + const res = await fetch('/kitchen/api/invoices/line-items/search', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -1781,7 +1781,7 @@ export default function Review() { try { // Update all line items const promises = lineItems.map(item => - fetch(`/api/invoices/${id}/line-items/${item.id}`, { + fetch(`/kitchen/api/invoices/${id}/line-items/${item.id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, @@ -1805,7 +1805,7 @@ export default function Review() { setAiMatchLoading(true) setAiMatchResults([]) try { - const res = await fetch(`/api/ingredients/ai-match?description=${encodeURIComponent(description)}`, { + const res = await fetch(`/kitchen/api/ingredients/ai-match?description=${encodeURIComponent(description)}`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -1827,7 +1827,7 @@ export default function Review() { setAiDismissedCorrections(new Set()) try { - const res = await fetch(`/api/invoices/${id}/ai-assist`, { + const res = await fetch(`/kitchen/api/invoices/${id}/ai-assist`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) @@ -1906,7 +1906,7 @@ export default function Review() { // Fetch saved definition setDefinitionLoading(true) try { - const res = await fetch(`/api/invoices/${id}/line-items/${item.id}/definition`, { + const res = await fetch(`/kitchen/api/invoices/${id}/line-items/${item.id}/definition`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -1927,7 +1927,7 @@ export default function Review() { if (!item.pack_quantity && !item.unit_size) { setAiPackSizeLoading(true) try { - const packRes = await fetch(`/api/invoices/${id}/line-items/${item.id}/ai-pack-size`, { + const packRes = await fetch(`/kitchen/api/invoices/${id}/line-items/${item.id}/ai-pack-size`, { headers: { Authorization: `Bearer ${token}` }, }) if (packRes.ok) { @@ -1961,7 +1961,7 @@ export default function Review() { } setIngredientSearchLoading(true) try { - const res = await fetch(`/api/ingredients/suggest?description=${encodeURIComponent(query)}`, { + const res = await fetch(`/kitchen/api/ingredients/suggest?description=${encodeURIComponent(query)}`, { headers: { Authorization: `Bearer ${token}` }, }) if (res.ok) { @@ -2053,7 +2053,7 @@ export default function Review() { if (selectedIngredientId) { try { // Set ingredient_id on line item - await fetch(`/api/invoices/${id}/line-items/${itemId}`, { + await fetch(`/kitchen/api/invoices/${id}/line-items/${itemId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ingredient_id: selectedIngredientId }), @@ -2081,7 +2081,7 @@ export default function Review() { if (id) { sourceData.invoice_id = parseInt(id as string) } - const srcRes = await fetch(`/api/ingredients/${selectedIngredientId}/sources`, { + const srcRes = await fetch(`/kitchen/api/ingredients/${selectedIngredientId}/sources`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(sourceData), @@ -2610,7 +2610,7 @@ export default function Review() { )} {isPDF && imageUrl && ( setInvoiceNotes(e.target.value)} onBlur={async () => { try { - await fetch(`/api/invoices/${id}`, { + await fetch(`/kitchen/api/invoices/${id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', @@ -4673,7 +4673,7 @@ export default function Review() {