diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b937d9..b655125 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project follows [Semantic Versioning](https://semver.org/). - Donations are no longer mutated when assigned to a registration — assignment now creates an immutable "leg" record referencing the original donation, so a partially-used donation keeps its original amount and remains assignable for its remaining balance instead of losing its history. - Email Attendees / WhatsApp Attendees now respond immediately after queuing recipients and send in the background, instead of blocking the page until every message has been sent. +- Dashboard: the sidebar (My Events, Profile, Admin, etc.) is now hidden on every sub-page under Staff, Supervisor, and Admin — not just Reports — so those pages get the full width for their own content and navigation. It's still shown on each role's root landing page (`/dashboard/staff`, `/dashboard/supervisor`, `/dashboard/admin`); the top navbar's "Dashboard" link always leads back there. ### Fixed @@ -39,6 +40,7 @@ and this project follows [Semantic Versioning](https://semver.org/). - Reports: Master Orders Breakdown's "Donations made" table (donor, amount, used/unused) is now included in the PDF, Excel, Email, and WhatsApp exports — previously only the Orders table was exported and the donations breakdown was visible on screen only. Also fixed a PDF rendering bug where a table title following another table (e.g. "Donations made" below the Orders table) could render at the page's right edge instead of the left margin. - Reports: "Email" export failed with `connect ECONNREFUSED 127.0.0.1:587` — it built its own mail transporter directly from `EMAIL_HOST`/etc. env vars instead of using the shared, DB-configurable SMTP settings (Admin → Site Settings) that the rest of the app already sends through, so it never picked up a working mail server. Now reuses the same shared mailer as tickets and account emails, with matching branded HTML styling. - Reports: "WhatsApp" export surfaced an unhelpful `Request failed with status code 500` on failure. WhatsApp send errors now report the actual reason from the WhatsApp API, and a disconnected WhatsApp session is now detected and auto-recovered the same way it already is for other WhatsApp actions (previously only ticket/text sends had this handling — PDF sends did not). +- Dashboard mobile: the Reports page's Events filter dropdown and the Email/WhatsApp Attendees recipient-picker dropdown could extend past the right edge of narrow screens instead of staying within the viewport; they now stretch to match their trigger's width like the other dropdowns in the app already do. The Cashup event-costs table on the Admin Cashup detail page now scrolls horizontally on narrow screens instead of squeezing its columns. ## [1.3.2] - 2026-08-03 diff --git a/frontend/src/app/dashboard/admin/cashup/[id]/page.tsx b/frontend/src/app/dashboard/admin/cashup/[id]/page.tsx index 314aac3..56b6c0e 100644 --- a/frontend/src/app/dashboard/admin/cashup/[id]/page.tsx +++ b/frontend/src/app/dashboard/admin/cashup/[id]/page.tsx @@ -175,49 +175,51 @@ function CostsTab({ eventId, token, costs, eventOptions, isClosed, onChanged }: {isClosed &&
This event is closed — costs can't be changed until it's reopened.
} - - - - - - - - - - {!isClosed && } - - - - {costs.map(c => ( - - - - - - - - {!isClosed && ( - - )} +
+
LabelTypeTicket typePaid fromAmountTotal
{c.label}{c.costType === "once_off" ? "Once-off" : "Per item"}{c.eventOption?.name || "—"}{c.paidFromMethod || "—"}{money(c.amount)}{money(c.total ?? c.amount)} - - -
+ + + + + + + + + {!isClosed && } - ))} - {costs.length === 0 && ( - + + + {costs.map(c => ( + + + + + + + + {!isClosed && ( + + )} + + ))} + {costs.length === 0 && ( + + )} + + {costs.length > 0 && ( + + + + + {!isClosed && + )} - - {costs.length > 0 && ( - - - - - {!isClosed && - - )} -
LabelTypeTicket typePaid fromAmountTotal
No costs added yet.
{c.label}{c.costType === "once_off" ? "Once-off" : "Per item"}{c.eventOption?.name || "—"}{c.paidFromMethod || "—"}{money(c.amount)}{money(c.total ?? c.amount)} + + +
No costs added yet.
Total costs{money(totalCosts)}} +
Total costs{money(totalCosts)}} -
+ + {editingId !== null && (
diff --git a/frontend/src/app/dashboard/layout.tsx b/frontend/src/app/dashboard/layout.tsx index ba18e65..6606f64 100644 --- a/frontend/src/app/dashboard/layout.tsx +++ b/frontend/src/app/dashboard/layout.tsx @@ -63,10 +63,14 @@ export default function DashboardLayout({ children }: { children: React.ReactNod ); } - // The Reports page is a full-width, self-contained workspace (its own header, filters, and - // navigation) — the dashboard sidebar's section links (My Events, Profile, Admin, etc.) would - // just crowd it, so it's hidden there specifically, not app-wide. - const hideSidebar = pathname === "/dashboard/supervisor/reports"; + // Sub-pages within staff/supervisor/admin (e.g. /dashboard/supervisor/reports, + // /dashboard/admin/cashup/[id]) are full-width workspaces with their own internal navigation + // and header — the dashboard sidebar's section links (My Events, Profile, Admin, etc.) would + // just crowd them. The sidebar stays visible only on each role's root landing page; every + // deeper sub-page hides it. Navigating back is never a dead end: Navbar's "Dashboard" link is + // always present and /dashboard auto-redirects to the role root. + const SIDEBAR_ROOTS = ["/dashboard/staff", "/dashboard/supervisor", "/dashboard/admin"]; + const hideSidebar = !!pathname && SIDEBAR_ROOTS.some(root => pathname !== root && pathname.startsWith(root + "/")); return (
diff --git a/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx b/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx index e092cf5..33eb714 100644 --- a/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx +++ b/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx @@ -75,7 +75,7 @@ function AttendeesCheckboxDropdown({ )} {open && ( -
+