diff --git a/backend/src/routes/weekly-actual.js b/backend/src/routes/weekly-actual.js index bb2d1f58..d7609f03 100644 --- a/backend/src/routes/weekly-actual.js +++ b/backend/src/routes/weekly-actual.js @@ -253,6 +253,24 @@ export async function weeklyActualRoutes(fastify) { }) } + // Monthly dept split for last 24 months (indices 12–35) + // — previous 12 months followed by last 12 months + const monthly_split = [] + for (let i = 12; i < 36; i++) { + const tm = trendMonths[i] + const data = trendRevRaw[i]?.data ?? [] + let rooms = 0, dry = 0, wet = 0 + for (const d of data) { + rooms += parseFloat(d.accom?.otb ?? 0) + dry += parseFloat(d.dry?.otb ?? 0) + wet += parseFloat(d.wet?.otb ?? 0) + } + monthly_split.push({ + label: `${MONTH_LABELS[tm.month - 1]}-${String(tm.year).slice(2)}`, + rooms, dry, wet, + }) + } + return { week_ending: toDateStr(weekEndDate), week_start: toDateStr(weekStartDate), @@ -262,6 +280,7 @@ export async function weeklyActualRoutes(fastify) { occupancy, month_progress, monthly_trend, + monthly_split, } }) } diff --git a/frontend/src/pages/WeeklyActual.tsx b/frontend/src/pages/WeeklyActual.tsx index 5cc250b2..b44fe1cb 100644 --- a/frontend/src/pages/WeeklyActual.tsx +++ b/frontend/src/pages/WeeklyActual.tsx @@ -7,9 +7,10 @@ import { PieChart, Pie, Cell, LineChart, Line, CartesianGrid, + ReferenceLine, } from 'recharts' import { getWeeklyActual } from '../api' -import type { WeeklyActualData, WeekSummaryRow } from '../types' +import type { WeeklyActualData, WeekSummaryRow, MonthSplitEntry } from '../types' // ── Formatters ───────────────────────────────────────────────────────────── @@ -255,13 +256,47 @@ function OccupancyTable({ occupancy }: { occupancy: WeeklyActualData['occupancy' ) } +// ── Section: Monthly Dept Split (24 months) ──────────────────────────────── + +function MonthSplitChart({ splits }: { splits: MonthSplitEntry[] }) { + // Mark the boundary between previous-12 and last-12 + const boundaryLabel = splits[11]?.label + + return ( +
+

Monthly Turnover by Dept — Previous 12 & Last 12 Months

+ + + + + `£${(v/1000).toFixed(0)}k`} tick={{ fontSize: 10 }} width={52} /> + + + {boundaryLabel && ( + + )} + + + + + +
+ ) +} + // ── Section: Month Progress ──────────────────────────────────────────────── function MonthProgressSection({ - mp, trend, + mp, trend, splits, }: { mp: WeeklyActualData['month_progress'] trend: WeeklyActualData['monthly_trend'] + splits: WeeklyActualData['monthly_split'] }) { const deptBarData = [ { name: 'Rooms', 'Net Sales': mp.split.rooms.net, 'Budget Net': mp.split.rooms.budget_net, 'Last Year': mp.split.rooms.ly_net }, @@ -366,6 +401,8 @@ function MonthProgressSection({ + + ) } @@ -467,7 +504,7 @@ export default function WeeklyActual() {

{MONTH_NAMES[data.month_progress.month - 1]} {data.month_progress.year} — Month Progress to Date

- + {/* ── Utilities ────────────────────────────────────────────── */} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 5dd696d1..1fa4a502 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -106,6 +106,13 @@ export interface MonthTrend { last_year_avg: number } +export interface MonthSplitEntry { + label: string + rooms: number + dry: number + wet: number +} + export interface WeeklyActualData { week_ending: string week_start: string @@ -116,8 +123,9 @@ export interface WeeklyActualData { daily: OccDay[] totals: OccTotals } - month_progress: MonthProgress - monthly_trend: MonthTrend[] + month_progress: MonthProgress + monthly_trend: MonthTrend[] + monthly_split: MonthSplitEntry[] } // ── Directors Forecast types ────────────────────────────────────────────────