From 0f2b5afa740bf49d1561d495361fb13623950ae7 Mon Sep 17 00:00:00 2001 From: joshua Date: Thu, 6 Aug 2026 15:17:12 +0200 Subject: [PATCH] Help guide opens on demand only; add At the door to admin quick actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The site-wide help guide no longer auto-opens on first visit to a page — it only opens when the help button is clicked. Removed the now-pointless "Don't show this again" checkbox and the per-page dismissal tracking it drove. - Admin dashboard quick actions was missing "At the door" (walk-in registration, payments, ticket printing), which Supervisor already had. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 3 ++ frontend/src/app/dashboard/admin/page.tsx | 3 +- frontend/src/components/shared/HelpFab.tsx | 4 +- .../src/components/shared/HelpGuideModal.tsx | 17 +++------ frontend/src/content/help/registry.ts | 2 +- frontend/src/hooks/useHelpGuide.ts | 38 +++---------------- 6 files changed, 19 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6614bb9..a421dca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ and this project follows [Semantic Versioning](https://semver.org/). - Admin/Supervisor dashboard "Revenue" figures (today/week/month) were overcounting: they didn't exclude donation-application "legs" (the money was already counted once via the original donation) the way Reports and the admin payments-stats endpoint already did. Both endpoints now use the same exclusion. - Admin/Supervisor dashboard "Revenue" KPI, trend chart, and top-performing-events table were undercounting the other way — donations themselves weren't being counted as revenue at all, only tracked in the separate "Donations" figure. Donations now count toward revenue (donation-application legs are still excluded either way, since that money was already counted once via the original donation). +- Admin/Supervisor dashboard KPIs (revenue, donations, registrations, tickets sold) used a calendar-month-to-date window, which under-counted for most of the month (e.g. only 3 days' worth of data on the 3rd). They now use a rolling trailing-month window instead — today back one calendar month, e.g. 9 May through 8 June if today is 8 June — compared against the equal-length month before that. The "View report" links from those tiles now deep-link into the same trailing-month range. +- Admin dashboard was missing the "At the door" quick action that Supervisor already had (walk-in registration, payments, and ticket printing at the door) — added. ### Changed @@ -41,6 +43,7 @@ and this project follows [Semantic Versioning](https://semver.org/). - Admin/Supervisor dashboard quick actions no longer list "Manage sections" or "Event tickets & printing" (redundant with the Events and At-the-door pages) or "Manage WhatsApp API" (moved into Site Settings). Staff keeps "Event tickets & printing" — their only other tool is ticket scanning, and they can't reach At-the-door. - Admin dashboard no longer shows ticket-scanning stats ("Recent scans") — kept on Supervisor/Staff, where it's actually actionable. - The old hand-rolled `Button` component (`components/shared/Button.tsx`) is gone — its one remaining caller now uses the standard `components/ui/button.tsx`. +- The site-wide help guide no longer opens itself automatically on first visit to a page — it only opens when the help button is clicked. The now-pointless "Don't show this again" checkbox was removed along with the per-page dismissal tracking it drove. ### Removed diff --git a/frontend/src/app/dashboard/admin/page.tsx b/frontend/src/app/dashboard/admin/page.tsx index e74d177..244fde6 100644 --- a/frontend/src/app/dashboard/admin/page.tsx +++ b/frontend/src/app/dashboard/admin/page.tsx @@ -8,7 +8,7 @@ import { useStableState } from "@/hooks/useStableState"; import { useVisiblePolling } from "@/hooks/useVisiblePolling"; import { Calendar, Banknote, Gift, Users, Ticket, QrCode, ClipboardList, - UserPlus, FileText, MessageCircle, BarChart2, Mail, Wallet, + UserPlus, FileText, MessageCircle, BarChart2, Mail, Wallet, DoorOpen, } from "lucide-react"; import { StatCard, StatCardRow } from "@/components/shared/StatCard"; import { QuickActionTile, QuickActionGrid } from "@/components/shared/QuickActionTile"; @@ -25,6 +25,7 @@ const QUICK_ACTIONS = [ { href: "/dashboard/supervisor/events", label: "Manage events", description: "Create, edit, and update ticket types", icon: Calendar }, { href: "/dashboard/admin/registrations", label: "Manage registrations", description: "Cancel, update status, and search registrations", icon: ClipboardList }, { href: "/dashboard/supervisor/manual", label: "Manual registration", description: "Register a guest and issue tickets", icon: UserPlus }, + { href: "/dashboard/supervisor/at-the-door", label: "At the door", description: "Walk-ins, payments, ticket printing", icon: DoorOpen }, { href: "/dashboard/supervisor/payments", label: "Payments & donations", description: "Manual payments and assignment", icon: Wallet }, { href: "/dashboard/staff/ticket-scanning", label: "Open scanner", description: "Use your device camera to validate tickets", icon: QrCode }, { href: "/dashboard/supervisor/reports", label: "Reports", description: "View, export, and email reports", icon: BarChart2 }, diff --git a/frontend/src/components/shared/HelpFab.tsx b/frontend/src/components/shared/HelpFab.tsx index 7eaabd3..051d03d 100644 --- a/frontend/src/components/shared/HelpFab.tsx +++ b/frontend/src/components/shared/HelpFab.tsx @@ -21,8 +21,8 @@ const EXCLUDED_PREFIXES = ["/self-service", "/setup"]; export default function HelpFab() { const pathname = usePathname() || "/"; - const { slug, content } = resolveHelpContent(pathname); - const { open, openGuide, closeGuide } = useHelpGuide(slug); + const { content } = resolveHelpContent(pathname); + const { open, openGuide, closeGuide } = useHelpGuide(); if (EXCLUDED_PREFIXES.some(prefix => pathname.startsWith(prefix))) { return null; diff --git a/frontend/src/components/shared/HelpGuideModal.tsx b/frontend/src/components/shared/HelpGuideModal.tsx index 994cd0a..b2f2f94 100644 --- a/frontend/src/components/shared/HelpGuideModal.tsx +++ b/frontend/src/components/shared/HelpGuideModal.tsx @@ -5,9 +5,8 @@ import Link from "next/link"; import { X, Mail, MessageCircleQuestion } from "lucide-react"; import type { HelpContent } from "@/content/help/types"; -export default function HelpGuideModal({ content, onClose }: { content: HelpContent; onClose: (dontShowAgain: boolean) => void }) { +export default function HelpGuideModal({ content, onClose }: { content: HelpContent; onClose: () => void }) { const [tab, setTab] = useState(content.tabs[0]?.key); - const [dontShowAgain, setDontShowAgain] = useState(false); const activeTab = content.tabs.find(t => t.key === tab) || content.tabs[0]; return ( @@ -15,7 +14,7 @@ export default function HelpGuideModal({ content, onClose }: { content: HelpCont // page-level popup (e.g. the report viewer at z-[60]), since the guide // can be opened from the FAB while another overlay is showing.
-
onClose(dontShowAgain)} /> +
{content.subtitle}

-
@@ -42,7 +41,7 @@ export default function HelpGuideModal({ content, onClose }: { content: HelpCont onClose(dontShowAgain)} + onClick={onClose} className="inline-flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-full border border-brand-200 bg-white text-brand-700 hover:bg-brand-100 hover:border-brand-300 transition-colors" > {link.icon && } @@ -90,12 +89,8 @@ export default function HelpGuideModal({ content, onClose }: { content: HelpCont
)} -
- -
diff --git a/frontend/src/content/help/registry.ts b/frontend/src/content/help/registry.ts index 5df0d74..445cee1 100644 --- a/frontend/src/content/help/registry.ts +++ b/frontend/src/content/help/registry.ts @@ -28,7 +28,7 @@ import { staffTicketScanningHelpContent } from "./staff-ticket-scanning"; import { userFormsHelpContent } from "./user-forms"; type HelpRegistryEntry = { - /** Unique, stable slug — used as the per-page "don't show again" storage key. */ + /** Unique, stable identifier for this guide. */ slug: string; matches: (pathname: string) => boolean; content: HelpContent; diff --git a/frontend/src/hooks/useHelpGuide.ts b/frontend/src/hooks/useHelpGuide.ts index 497a04c..ea73ed5 100644 --- a/frontend/src/hooks/useHelpGuide.ts +++ b/frontend/src/hooks/useHelpGuide.ts @@ -1,42 +1,14 @@ "use client"; -import { useEffect, useState } from "react"; +import { useState } from "react"; /** - * Open/close state for a help guide, with per-page "don't show again" - * persistence. `storageKey` should be a stable slug identifying the guide's - * content (e.g. "reports", "dashboard-user", "general") — each slug gets an - * independent dismissal flag, so dismissing one page's guide doesn't - * suppress another's. + * Open/close state for a help guide — opens only when the user explicitly + * asks for it (e.g. clicking the help FAB), never automatically. */ -export function useHelpGuide(storageKey: string) { +export function useHelpGuide() { const [open, setOpen] = useState(false); - const dismissedKey = `hope_events_help_dismissed_${storageKey}`; - - // Show automatically on first visit to this guide, unless dismissed for good. - useEffect(() => { - try { - if (typeof window !== "undefined" && window.localStorage.getItem(dismissedKey) !== "1") { - setOpen(true); - } - } catch { - // localStorage unavailable (private browsing, etc.) — just don't auto-show. - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [dismissedKey]); - const openGuide = () => setOpen(true); - - const closeGuide = (dontShowAgain: boolean) => { - setOpen(false); - if (dontShowAgain) { - try { - window.localStorage.setItem(dismissedKey, "1"); - } catch { - // ignore - } - } - }; - + const closeGuide = () => setOpen(false); return { open, openGuide, closeGuide }; }