diff --git a/frontend/src/app/dashboard/admin/audit-log/page.tsx b/frontend/src/app/dashboard/admin/audit-log/page.tsx
index 3dc6d09..9a3c331 100644
--- a/frontend/src/app/dashboard/admin/audit-log/page.tsx
+++ b/frontend/src/app/dashboard/admin/audit-log/page.tsx
@@ -8,6 +8,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { History } from "lucide-react";
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "@/components/ui/table";
import { errorMessage } from "@/lib/utils";
+import { BackLink } from "@/components/shared/BackLink";
const ACTIONS = [
"refund_created",
@@ -192,7 +193,7 @@ export default function AdminAuditLogPage() {
-
+
Admin Audit Log
{total} action{total !== 1 ? "s" : ""} recorded
diff --git a/frontend/src/app/dashboard/admin/cashup/page.tsx b/frontend/src/app/dashboard/admin/cashup/page.tsx
index 036f769..8b932e1 100644
--- a/frontend/src/app/dashboard/admin/cashup/page.tsx
+++ b/frontend/src/app/dashboard/admin/cashup/page.tsx
@@ -8,6 +8,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { Wallet } from "lucide-react";
import { errorMessage } from "@/lib/utils";
import type { Event } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
export default function CashupLandingPage() {
const { token } = useAuth();
@@ -55,15 +56,11 @@ export default function CashupLandingPage() {
-
Post-event Cashup
+
+
Post-event Cashup
Set costs, reconcile takings, and close out an event. Admin only.
-
{error &&
{error}
}
diff --git a/frontend/src/app/dashboard/admin/registrations/page.tsx b/frontend/src/app/dashboard/admin/registrations/page.tsx
index 9bd901f..39eade3 100644
--- a/frontend/src/app/dashboard/admin/registrations/page.tsx
+++ b/frontend/src/app/dashboard/admin/registrations/page.tsx
@@ -8,6 +8,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { ClipboardList } from "lucide-react";
import { errorMessage } from "@/lib/utils";
import type { Event, FormResponse, Registration } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
const STATUS_OPTIONS = ["pending", "confirmed", "partial_paid", "paid", "cancelled"] as const;
@@ -197,11 +198,11 @@ export default function AdminRegistrationsPage() {
-
Manage Registrations
+
+
Manage Registrations
{registrations.length} registration{registrations.length !== 1 ? "s" : ""} total
-
{!isAdmin && (
diff --git a/frontend/src/app/dashboard/admin/settings/page.tsx b/frontend/src/app/dashboard/admin/settings/page.tsx
index b738983..a2369c9 100644
--- a/frontend/src/app/dashboard/admin/settings/page.tsx
+++ b/frontend/src/app/dashboard/admin/settings/page.tsx
@@ -2,7 +2,7 @@
import React, { Suspense, useCallback, useEffect, useRef, useState } from "react";
import { useAuth } from "@/hooks/useAuth";
-import { useRouter, useSearchParams } from "next/navigation";
+import { useSearchParams } from "next/navigation";
import { apiFetch, ApiError, API_BASE, resolveToApiOrigin } from "@/lib/api";
import { useSiteSettings } from "@/contexts/SiteSettingsContext";
import { useDismissingState } from "@/hooks/useDismissingState";
@@ -14,6 +14,7 @@ import { YocoTab } from "@/components/admin/YocoTab";
import { extractDominantColors } from "@/lib/extractColors";
import { mapsSearchUrl } from "@/lib/maps";
import { errorMessage } from "@/lib/utils";
+import { BackLink } from "@/components/shared/BackLink";
type TabId = "organisation" | "branding" | "notifications" | "email" | "legal" | "whatsapp" | "yoco" | "backups";
@@ -85,7 +86,6 @@ export default function SiteSettingsPage() {
function SiteSettingsPageInner() {
const { token } = useAuth();
- const router = useRouter();
const searchParams = useSearchParams();
const { reload: reloadSettings } = useSiteSettings();
@@ -366,15 +366,10 @@ function SiteSettingsPageInner() {
{/* Header */}
-
Site Settings
+
+
Site Settings
Configure your organisation, branding, email, and legal pages.
-
{/* Tab bar */}
diff --git a/frontend/src/app/dashboard/admin/users/page.tsx b/frontend/src/app/dashboard/admin/users/page.tsx
index 24322a9..6e08dfd 100644
--- a/frontend/src/app/dashboard/admin/users/page.tsx
+++ b/frontend/src/app/dashboard/admin/users/page.tsx
@@ -10,6 +10,7 @@ import { Users as UsersIcon } from "lucide-react";
import { RoleBadge, type Role as RoleBadgeRole } from "@/components/shared/RoleBadge";
import { errorMessage } from "@/lib/utils";
import type { Paginated } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
interface UserItem {
id: string;
@@ -259,12 +260,12 @@ export default function AdminUsersPage() {
-
User Management
+
+
User Management
{total} user{total !== 1 ? "s" : ""} total
-
diff --git a/frontend/src/app/dashboard/staff/event-tickets/page.tsx b/frontend/src/app/dashboard/staff/event-tickets/page.tsx
index 1050d19..c57d2fc 100644
--- a/frontend/src/app/dashboard/staff/event-tickets/page.tsx
+++ b/frontend/src/app/dashboard/staff/event-tickets/page.tsx
@@ -10,6 +10,7 @@ import { QrImage } from "@/components/shared/QrImage";
import { Ticket } from "lucide-react";
import { errorMessage } from "@/lib/utils";
import type { Event, Ticket as TicketRecord } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
function EventTicketsContent() {
const { token, user } = useAuth();
@@ -239,14 +240,11 @@ function EventTicketsContent() {
-
Event Tickets
+
+
+
Event Tickets
+
-
View and print tickets for an event.
diff --git a/frontend/src/app/dashboard/staff/my-groups/page.tsx b/frontend/src/app/dashboard/staff/my-groups/page.tsx
index 14b04bd..6b08c6f 100644
--- a/frontend/src/app/dashboard/staff/my-groups/page.tsx
+++ b/frontend/src/app/dashboard/staff/my-groups/page.tsx
@@ -2,10 +2,10 @@
import React, { useEffect, useState } from "react";
import { useAuth } from "@/hooks/useAuth";
-import { useRouter } from "next/navigation";
import { apiFetch } from "@/lib/api";
import { formatDate } from "@/lib/date";
import { Users } from "lucide-react";
+import { BackLink } from "@/components/shared/BackLink";
type Member = {
id: string; name: string; gender: string | null; dateOfBirth: string | null; phone: string | null;
@@ -25,7 +25,6 @@ const ageOn = (dob: string | null, on: string) => {
/** Groups the signed-in staff member leads (rooms, small groups, buses) and who's in them. */
export default function MyGroupsPage() {
const { token } = useAuth();
- const router = useRouter();
const [data, setData] = useState<{ medicalShown: boolean; groups: MyGroup[] } | null>(null);
const [error, setError] = useState(null);
@@ -42,7 +41,7 @@ export default function MyGroupsPage() {
-
+
My groups
Rooms, small groups and buses you lead
diff --git a/frontend/src/app/dashboard/staff/ticket-scanning/page.tsx b/frontend/src/app/dashboard/staff/ticket-scanning/page.tsx
index 6c0162b..2700d55 100644
--- a/frontend/src/app/dashboard/staff/ticket-scanning/page.tsx
+++ b/frontend/src/app/dashboard/staff/ticket-scanning/page.tsx
@@ -5,13 +5,13 @@ import { QRScanner, QRScannerHandle } from "@/components/qr/QRScanner";
import { useAuth } from "@/hooks/useAuth";
import { apiFetch } from "@/lib/api";
import { useDismissingState } from "@/hooks/useDismissingState";
-import { useRouter } from "next/navigation";
import { QrCode } from "lucide-react";
import { useOfflineScanning } from "@/components/scanner/useOfflineScanning";
import { OfflineScanPanel } from "@/components/scanner/OfflineScanPanel";
import type { SnapshotTicket } from "@/lib/offlineScan";
import { errorMessage } from "@/lib/utils";
import type { Event, RecentScan, ScanStats, Section } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
// GET /api/tickets/scan-preview/:qr — just the fields the confirm step needs. Offline
// scans build the same shape from the downloaded ticket list.
@@ -33,7 +33,6 @@ type ScanTicket = {
};
export default function TicketScanningPage() {
- const router = useRouter();
const scannerRef = useRef(null);
const [scanInfo, setScanInfo] = useDismissingState(null);
const [error, setError] = useDismissingState(null);
@@ -330,9 +329,11 @@ export default function TicketScanningPage() {
-
Ticket Scanning
+
+
+
Ticket Scanning
+
-
Use the button to start/stop scanning. The back camera will be used when available.
diff --git a/frontend/src/app/dashboard/supervisor/allocations/page.tsx b/frontend/src/app/dashboard/supervisor/allocations/page.tsx
index ec85282..aff84c2 100644
--- a/frontend/src/app/dashboard/supervisor/allocations/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/allocations/page.tsx
@@ -10,6 +10,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { BedDouble, Plus, Wand2, Printer, Trash2, Pencil, Eraser } from "lucide-react";
import { errorMessage } from "@/lib/utils";
import type { Event } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
type Group = { id: string; name: string; capacity: number | null; gender: "male" | "female" | null; leaderUserId: string | null; leader?: { id: string; name: string } | null };
type AllocSet = { id: string; name: string; showOnTicket: boolean; groups: Group[]; assignments: { attendeeId: string; groupId: string }[] };
@@ -207,7 +208,7 @@ export default function AllocationsPage() {
-
+
Rooms & groups
Put attendees into rooms, small groups, teams or buses
diff --git a/frontend/src/app/dashboard/supervisor/consent/page.tsx b/frontend/src/app/dashboard/supervisor/consent/page.tsx
index a774ac0..90ac0b1 100644
--- a/frontend/src/app/dashboard/supervisor/consent/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/consent/page.tsx
@@ -10,6 +10,7 @@ import { ShieldCheck, Send, RefreshCw, HeartPulse, Printer } from "lucide-react"
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "@/components/ui/table";
import { errorMessage } from "@/lib/utils";
import type { Event, ConsentRow, MedicalRow } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
const STATUS_STYLE: Record = {
@@ -134,7 +135,7 @@ export default function ConsentTrackerPage() {
-
+
Parental consent
Youth events: who still needs a parent's consent before check-in
diff --git a/frontend/src/app/dashboard/supervisor/coupons/page.tsx b/frontend/src/app/dashboard/supervisor/coupons/page.tsx
index ad8533e..5cbfa8a 100644
--- a/frontend/src/app/dashboard/supervisor/coupons/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/coupons/page.tsx
@@ -8,6 +8,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { TicketPercent, Plus, X, Search } from "lucide-react";
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "@/components/ui/table";
import { errorMessage } from "@/lib/utils";
+import { BackLink } from "@/components/shared/BackLink";
type CouponType = "percent" | "fixed" | "comp";
type Role = "user" | "staff" | "supervisor" | "admin";
@@ -206,7 +207,7 @@ export default function CouponsPage() {
-
+
Coupon codes
Discounts for staff, leaders, volunteers and promotions
diff --git a/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx b/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx
index 25549e1..ca08500 100644
--- a/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/email-attendees/page.tsx
@@ -9,6 +9,7 @@ import { Mail, Users, Zap, Clock } from "lucide-react";
import { AllocationGroupFilter } from "@/components/shared/AllocationGroupFilter";
import { errorMessage } from "@/lib/utils";
import type { Event, MessageSendResult, Registration, User } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
type Attendee = { id: string; name: string; email: string; pref: string };
type TemplateKey = 'custom'|'payment_reminder'|'event_reminder'|'tickets';
@@ -489,10 +490,10 @@ function EmailAttendeesPageInner() {
-
Email Attendees
-
-
-
+
+
+
Email Attendees
+
diff --git a/frontend/src/app/dashboard/supervisor/event-options/page.tsx b/frontend/src/app/dashboard/supervisor/event-options/page.tsx
index 8b5aaa2..7956187 100644
--- a/frontend/src/app/dashboard/supervisor/event-options/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/event-options/page.tsx
@@ -8,6 +8,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { Ticket } from "lucide-react";
import { errorMessage } from "@/lib/utils";
import type { Event, EventOption } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
// Format a Date (or date-like input) to the value expected by
// This returns local time (browser timezone) as YYYY-MM-DDTHH:mm
@@ -209,9 +210,11 @@ function EventOptionsContent() {
-
Event options
+
+
+
Event options
+
-
{!canView && (
diff --git a/frontend/src/app/dashboard/supervisor/events/page.tsx b/frontend/src/app/dashboard/supervisor/events/page.tsx
index a2b88ec..ba3296f 100644
--- a/frontend/src/app/dashboard/supervisor/events/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/events/page.tsx
@@ -12,6 +12,7 @@ import { Calendar } from "lucide-react";
import { ChoicesEditor } from "@/components/shared/FormFieldExtras";
import { errorMessage } from "@/lib/utils";
import type { Event, EventAttachment, EventFormField, EventOption, Paginated, Section } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
// ─── helpers ────────────────────────────────────────────────────────────────
@@ -1792,13 +1793,13 @@ export default function ManageEventsPage() {
-
Events
+
+
Events
Manage and create events
-
diff --git a/frontend/src/app/dashboard/supervisor/forms/page.tsx b/frontend/src/app/dashboard/supervisor/forms/page.tsx
index f5e067e..07609c9 100644
--- a/frontend/src/app/dashboard/supervisor/forms/page.tsx
+++ b/frontend/src/app/dashboard/supervisor/forms/page.tsx
@@ -9,6 +9,7 @@ import { useDismissingState } from "@/hooks/useDismissingState";
import { FileText } from "lucide-react";
import { errorMessage } from "@/lib/utils";
import type { Event, EventForm, FormResponse, Registration, User } from "@/types";
+import { BackLink } from "@/components/shared/BackLink";
type FormFieldType = 'yes_no' | 'text' | 'date' | 'numeric' | 'statement' | 'paragraph' | 'rating' | 'multiple_choice';
@@ -452,10 +453,12 @@ export default function FormsBrowserPage() {