From 13c704a2dc6d2cb213433e0ebbbb14cddd0937ee Mon Sep 17 00:00:00 2001 From: Dan Glorioso <125602370+danglorioso@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:16:35 -0400 Subject: [PATCH 1/4] feat: add help button on sidebar --- src/components/HelpSheet.tsx | 192 +++++++++++++++++++++++++++++ src/components/Sidebar.tsx | 226 ++++++++++++++++++++--------------- 2 files changed, 319 insertions(+), 99 deletions(-) create mode 100644 src/components/HelpSheet.tsx diff --git a/src/components/HelpSheet.tsx b/src/components/HelpSheet.tsx new file mode 100644 index 00000000..5729aabe --- /dev/null +++ b/src/components/HelpSheet.tsx @@ -0,0 +1,192 @@ +"use client"; + +import { usePathname } from "next/navigation"; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, + SheetDescription, +} from "@/components/ui/sheet"; +import { + Accordion, + AccordionItem, + AccordionTrigger, + AccordionContent, +} from "@/components/ui/accordion"; +import { + LayoutDashboard, + Map, + BarChart3, + School, + FileUp, + Settings, +} from "lucide-react"; + +interface HelpSheetProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +const pages = [ + { + value: "/", + label: "Dashboard", + icon: LayoutDashboard, + description: + "A high-level summary of MHD program data for a selected year.", + features: [ + "Use the year selector to switch between available data years.", + "View total counts for students, projects, and teachers across all schools.", + "Trend lines show how each metric has changed year over year.", + "Percent change indicators highlight growth or decline from the prior year.", + ], + }, + { + value: "/map", + label: "Map", + icon: Map, + description: + "An interactive heatmap of participating schools across Massachusetts.", + features: [ + "Switch the Counts dropdown between Students, Projects, and Teachers to change what the heatmap visualizes.", + "Use the Year dropdown to select which year's data is displayed.", + "Change Region View to zoom into Western, Central, Boston, Northeast, or Southeast MA.", + "Open Filters to toggle school markers, the heatmap overlay, and region boundaries on or off.", + "Enable Gateway Schools Only to restrict the view to gateway city schools.", + "Click a school cluster or marker to see a popup with that school's data.", + "Export saves the current map as a PDF. Copy link shares the exact view via URL.", + "Add to cart to collect multiple figure (map and chart) configurations into a combined export.", + "Keyboard: ⌘S opens the export dialog, ⌘P downloads a PDF directly.", + ], + }, + { + value: "/chart", + label: "Chart", + icon: BarChart3, + description: + "Bar and line charts for exploring project data with detailed filtering.", + features: [ + "Toggle between Bar and Line chart types using the tabs at the top.", + "Open the Filters panel to narrow data by school, city, project type, or teacher experience.", + "Use Group By to segment the chart by school, city, or project type.", + "Measured As controls whether the y-axis shows raw counts or percentages.", + "Export saves the current chart as a PDF. Copy link shares the current filter state via URL.", + "Add to cart to collect multiple chart configurations for a combined export.", + "Keyboard: ⌘S opens the export dialog.", + ], + }, + { + value: "/schools", + label: "Schools", + icon: School, + description: + "A table of all participating schools and their data for a selected year.", + features: [ + "Use the Year dropdown to select which year to display.", + "Search by school name using the search bar.", + "Columns show year-over-year comparisons — arrows indicate change from the prior year.", + "Click any school row to open that school's detailed profile.", + "Click column headers to sort by that metric.", + ], + }, + { + value: "/upload", + label: "Upload Data", + icon: FileUp, + description: "Import new program data by uploading a spreadsheet.", + features: [ + "Drag and drop a spreadsheet file or click to browse.", + "Preview the parsed data before confirming the upload.", + "Validation errors are highlighted so you can correct the source file and re-upload.", + "Confirm the upload to commit the new data to the database.", + ], + }, + { + value: "/settings", + label: "Settings", + icon: Settings, + description: + "Admin tools for configuring program-wide data and school metadata.", + features: [ + "Gateway Schools: add or remove schools designated as gateway city schools.", + "Years of Data: control which years are available across the app.", + "School Locations: edit the map coordinates for individual schools.", + "Changes are not saved automatically — click Save to apply all edits.", + "Navigating away with unsaved changes will prompt you to save or discard.", + ], + }, +]; + +function pathnameToValue(pathname: string): string { + if (pathname === "/") return "/"; + if (pathname.startsWith("/schools/")) return "/schools"; + const clean = pathname.replace(/\/$/, ""); + const match = pages.find( + (p) => p.value !== "/" && clean.startsWith(p.value), + ); + return match?.value ?? "/"; +} + +export function HelpSheet({ open, onOpenChange }: HelpSheetProps) { + const pathname = usePathname(); + const defaultValue = pathnameToValue(pathname); + + return ( + + + + Help + +
+ + {pages.map( + ({ + value, + label, + icon: Icon, + description, + features, + }) => ( + + + + + {label} + + + +

+ {description} +

+
    + {features.map((feature, i) => ( +
  • + + {feature} +
  • + ))} +
+
+
+ ), + )} +
+
+
+
+ ); +} diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 071b5ea9..e1afbf1a 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -12,6 +12,7 @@ import { Settings as SettingsIcon, LogOut, MoreHorizontal, + MessageCircleQuestion, } from "lucide-react"; import { authClient } from "@/lib/auth-client"; import Image from "next/image"; @@ -23,11 +24,13 @@ import { import { DEV_BYPASS, DEV_BYPASS_COOKIE } from "@/lib/dev-config"; // TO DO - REMOVE: dev auth bypass import { DEV_SESSION_USER } from "@/lib/dev-session"; // TO DO - REMOVE: dev auth bypass import { useUnsavedChanges } from "@/components/UnsavedChangesContext"; +import { HelpSheet } from "@/components/HelpSheet"; export default function Sidebar() { const pathname = usePathname(); const router = useRouter(); const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [isHelpOpen, setIsHelpOpen] = useState(false); const { data: authSession, isPending } = authClient.useSession(); const { onNavigationAttempt } = useUnsavedChanges(); // TO DO - REMOVE: dev auth bypass - show dev user when in dev mode with no real session @@ -160,118 +163,143 @@ export default function Sidebar() { ]; return ( - + + + ); } From 9fc5d0e637a966dcf0bef76aba53852be0e89232 Mon Sep 17 00:00:00 2001 From: Dan Glorioso <125602370+danglorioso@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:26:08 -0400 Subject: [PATCH 2/4] feat: add icons and school profile page --- src/components/HelpSheet.tsx | 125 +++++++++++++++++++++++++++++++---- 1 file changed, 112 insertions(+), 13 deletions(-) diff --git a/src/components/HelpSheet.tsx b/src/components/HelpSheet.tsx index 5729aabe..92494974 100644 --- a/src/components/HelpSheet.tsx +++ b/src/components/HelpSheet.tsx @@ -6,7 +6,6 @@ import { SheetContent, SheetHeader, SheetTitle, - SheetDescription, } from "@/components/ui/sheet"; import { Accordion, @@ -19,16 +18,67 @@ import { Map, BarChart3, School, + BookOpen, FileUp, Settings, + TrendingUp, + TrendingDown, + Minus, + ShoppingBasket, } from "lucide-react"; +import type { ReactNode } from "react"; interface HelpSheetProps { open: boolean; onOpenChange: (open: boolean) => void; } -const pages = [ +// Small reusable inline indicator components +function GreenDot() { + return ( + + ); +} + +function TrendLegend() { + return ( +
+
+ + Increase from prior year +
+
+ + Decrease from prior year +
+
+ + No change or no prior year data +
+
+ ); +} + +function CartBadge() { + return ( + + + + 2 + + + ); +} + +interface Page { + value: string; + label: string; + icon: React.ElementType; + description: string; + features: ReactNode[]; +} + +const pages: Page[] = [ { value: "/", label: "Dashboard", @@ -37,9 +87,13 @@ const pages = [ "A high-level summary of MHD program data for a selected year.", features: [ "Use the year selector to switch between available data years.", - "View total counts for students, projects, and teachers across all schools.", - "Trend lines show how each metric has changed year over year.", - "Percent change indicators highlight growth or decline from the prior year.", + "View total counts for students, projects, teachers, and schools.", + <> + Each stat card shows a percentage change from the prior year: + + , + "Click any stat card to jump to the Chart page filtered to that metric.", + "The two line graphs show total projects and schools over the past 6 years.", ], }, { @@ -50,13 +104,20 @@ const pages = [ "An interactive heatmap of participating schools across Massachusetts.", features: [ "Switch the Counts dropdown between Students, Projects, and Teachers to change what the heatmap visualizes.", - "Use the Year dropdown to select which year's data is displayed.", + <> + In the Year dropdown, a filled green dot next to a + year means data is available for that year. + , "Change Region View to zoom into Western, Central, Boston, Northeast, or Southeast MA.", "Open Filters to toggle school markers, the heatmap overlay, and region boundaries on or off.", "Enable Gateway Schools Only to restrict the view to gateway city schools.", "Click a school cluster or marker to see a popup with that school's data.", "Export saves the current map as a PDF. Copy link shares the exact view via URL.", - "Add to cart to collect multiple figure (map and chart) configurations into a combined export.", + <> + Add to cart to collect maps and charts for a combined export. + The badge on the Cart button shows how many items + you've collected. + , "Keyboard: ⌘S opens the export dialog, ⌘P downloads a PDF directly.", ], }, @@ -72,7 +133,11 @@ const pages = [ "Use Group By to segment the chart by school, city, or project type.", "Measured As controls whether the y-axis shows raw counts or percentages.", "Export saves the current chart as a PDF. Copy link shares the current filter state via URL.", - "Add to cart to collect multiple chart configurations for a combined export.", + <> + Add to cart to collect charts and maps for a combined export. + The badge on the Cart button shows how many items + you've collected. + , "Keyboard: ⌘S opens the export dialog.", ], }, @@ -83,11 +148,43 @@ const pages = [ description: "A table of all participating schools and their data for a selected year.", features: [ - "Use the Year dropdown to select which year to display.", + <> + In the Year dropdown, a filled green dot means data + is available for that year. + , "Search by school name using the search bar.", - "Columns show year-over-year comparisons — arrows indicate change from the prior year.", + <> + The # Students, # Teachers, and # Projects columns show + year-over-year change: + + , "Click any school row to open that school's detailed profile.", - "Click column headers to sort by that metric.", + "Click column headers to sort the table by that metric.", + ], + }, + { + value: "/schools/profile", + label: "School Profile", + icon: BookOpen, + description: + "A detailed view of a single school's data, history, and project records.", + features: [ + <> + In the Year dropdown, a filled green dot means the + school participated that year. Years the school didn't + participate in are grayed out and unselectable. + , + <> + The three stat cards show projects, teachers, and students for + the selected year with year-over-year trend indicators: + + , + "The student count line graph shows enrollment history over the past 5 years. Click it to open the Chart page filtered to this school.", + "The project type distribution pie chart breaks down projects by category for the selected year.", + "School Location shows the school's pin on a map. Drag the pin to update its coordinates.", + "The View and Edit Data table lists all project records for the selected year. Double-click any cell to edit it. Teacher changes apply globally across all of that teacher's projects.", + "Double-click the school name at the top of the page to rename the school.", + "Use the ⋮ menu to access Merge School, which combines this school's records with another school.", ], }, { @@ -120,7 +217,7 @@ const pages = [ function pathnameToValue(pathname: string): string { if (pathname === "/") return "/"; - if (pathname.startsWith("/schools/")) return "/schools"; + if (pathname.startsWith("/schools/")) return "/schools/profile"; const clean = pathname.replace(/\/$/, ""); const match = pages.find( (p) => p.value !== "/" && clean.startsWith(p.value), @@ -176,7 +273,9 @@ export function HelpSheet({ open, onOpenChange }: HelpSheetProps) { className="flex gap-2" > - {feature} + + {feature} + ))} From ba7c815f37b714525c3e2c8ddee0fb38043afb59 Mon Sep 17 00:00:00 2001 From: Dan Glorioso <125602370+danglorioso@users.noreply.github.com> Date: Sun, 19 Apr 2026 20:34:30 -0400 Subject: [PATCH 3/4] feat: add to page descriptions, add icons --- src/components/HelpSheet.tsx | 79 ++++++++++++++++++++------------- src/components/ui/accordion.tsx | 2 +- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/components/HelpSheet.tsx b/src/components/HelpSheet.tsx index 92494974..24b09e88 100644 --- a/src/components/HelpSheet.tsx +++ b/src/components/HelpSheet.tsx @@ -40,6 +40,12 @@ function GreenDot() { ); } +function OutlinedDot() { + return ( + + ); +} + function TrendLegend() { return (
@@ -86,7 +92,11 @@ const pages: Page[] = [ description: "A high-level summary of MHD program data for a selected year.", features: [ - "Use the year selector to switch between available data years.", + <> + Use the year selector to switch between available data years. A{" "} + filled green dot next to a year means data is + available for that year. + , "View total counts for students, projects, teachers, and schools.", <> Each stat card shows a percentage change from the prior year: @@ -108,16 +118,19 @@ const pages: Page[] = [ In the Year dropdown, a filled green dot next to a year means data is available for that year. , - "Change Region View to zoom into Western, Central, Boston, Northeast, or Southeast MA.", + "Change Region View to zoom into pre-set views of competition regions.", "Open Filters to toggle school markers, the heatmap overlay, and region boundaries on or off.", "Enable Gateway Schools Only to restrict the view to gateway city schools.", - "Click a school cluster or marker to see a popup with that school's data.", - "Export saves the current map as a PDF. Copy link shares the exact view via URL.", + "Click a school marker to see a popup with that school's data. Click the View Profile button to redirect to that school's profile page.", + "Export saves the current map as a PDF.", + "Copy link shares the exact view and filter state via URL.", <> Add to cart to collect maps and charts for a combined export. - The badge on the Cart button shows how many items - you've collected. + The Cart button shows how many items you've + collected — click it to open the cart and initiate a bulk + export. , + "Use the ‹ or › arrow keys to switch between available years.", "Keyboard: ⌘S opens the export dialog, ⌘P downloads a PDF directly.", ], }, @@ -129,16 +142,19 @@ const pages: Page[] = [ "Bar and line charts for exploring project data with detailed filtering.", features: [ "Toggle between Bar and Line chart types using the tabs at the top.", - "Open the Filters panel to narrow data by school, city, project type, or teacher experience.", - "Use Group By to segment the chart by school, city, or project type.", - "Measured As controls whether the y-axis shows raw counts or percentages.", - "Export saves the current chart as a PDF. Copy link shares the current filter state via URL.", + "Use the date range picker in the top right to set the timeframe. Choose from the past 3 or 5 years relative to the latest year of data, or set a custom year range.", + "Open the Filters panel to narrow data by school, city, project type, teacher experience, and more. Filters are organized by type — you can select one value per filter type, and multiple filter types can be active at the same time.", + "Measured As controls what the y-axis measures — use the dropdown to select from the available count and rate options.", + "Use Group By to combine data points into common categories such as school, city, or project type.", + "Export saves the current chart as a PDF.", + "Copy link shares the current filter state via URL.", <> Add to cart to collect charts and maps for a combined export. - The badge on the Cart button shows how many items - you've collected. + The Cart button shows how many items you've + collected — click it to open the cart and initiate a bulk + export. , - "Keyboard: ⌘S opens the export dialog.", + "Keyboard: ⌘S opens the export dialog, ⌘P downloads a PDF directly, B switches to bar chart, L switches to line chart.", ], }, { @@ -152,14 +168,15 @@ const pages: Page[] = [ In the Year dropdown, a filled green dot means data is available for that year. , - "Search by school name using the search bar.", + "Search by school name, city, or region using the search bar.", <> The # Students, # Teachers, and # Projects columns show year-over-year change: , - "Click any school row to open that school's detailed profile.", - "Click column headers to sort the table by that metric.", + "Use the ‹ or › arrow keys to switch between available years.", + "Click any school name to open that school's detailed profile page.", + "Click column headers to sort the table by that metric in ascending or descending order.", ], }, { @@ -170,9 +187,9 @@ const pages: Page[] = [ "A detailed view of a single school's data, history, and project records.", features: [ <> - In the Year dropdown, a filled green dot means the - school participated that year. Years the school didn't - participate in are grayed out and unselectable. + In the Year dropdown: a filled dot means the school + participated that year; an outlined dot means + data exists for that year but the school did not participate. , <> The three stat cards show projects, teachers, and students for @@ -181,7 +198,7 @@ const pages: Page[] = [ , "The student count line graph shows enrollment history over the past 5 years. Click it to open the Chart page filtered to this school.", "The project type distribution pie chart breaks down projects by category for the selected year.", - "School Location shows the school's pin on a map. Drag the pin to update its coordinates.", + "School Location shows the school's pin on a map. Drag the pin to update its coordinates. Regions are automatically updated based on the new coordinates.", "The View and Edit Data table lists all project records for the selected year. Double-click any cell to edit it. Teacher changes apply globally across all of that teacher's projects.", "Double-click the school name at the top of the page to rename the school.", "Use the ⋮ menu to access Merge School, which combines this school's records with another school.", @@ -191,12 +208,15 @@ const pages: Page[] = [ value: "/upload", label: "Upload Data", icon: FileUp, - description: "Import new program data by uploading a spreadsheet.", + description: + "A multi-step process for importing new yearly program data, broken into tabs.", features: [ - "Drag and drop a spreadsheet file or click to browse.", - "Preview the parsed data before confirming the upload.", - "Validation errors are highlighted so you can correct the source file and re-upload.", - "Confirm the upload to commit the new data to the database.", + "Step 1 — Enter the year for the data being uploaded (new year or overwrite an existing year) and upload the student spreadsheet. A template is available to download. Drag and drop the file or click to browse.", + "Step 2 — Validation checks the student spreadsheet format and data types. Any errors are highlighted so you can correct the source file and re-upload.", + "Step 3 — Upload the school spreadsheet in the same way. Another template is available for this file as well.", + "Step 4 — Validation checks the school spreadsheet, then schools are matched to their locations on the map based on previously known schools.", + "Step 5 — Any schools whose locations could not be matched must be placed manually. Drag a pin onto the map for each unmatched school.", + "Step 6 — Review a summary and confirm the upload to commit all data to the database.", ], }, { @@ -204,13 +224,12 @@ const pages: Page[] = [ label: "Settings", icon: Settings, description: - "Admin tools for configuring program-wide data and school metadata.", + "Admin tools for configuring application-wide settings and school metadata.", features: [ - "Gateway Schools: add or remove schools designated as gateway city schools.", - "Years of Data: control which years are available across the app.", - "School Locations: edit the map coordinates for individual schools.", + "Gateway Schools: add or remove schools designated as schools representing students from gateway cities.", + "School Locations: edit the map coordinates for individual schools. Regions are automatically updated based on the new coordinates.", + "Years of Data: delete or upload years of participation data across the app.", "Changes are not saved automatically — click Save to apply all edits.", - "Navigating away with unsaved changes will prompt you to save or discard.", ], }, ]; diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx index aa15cfcc..5b06a7cc 100644 --- a/src/components/ui/accordion.tsx +++ b/src/components/ui/accordion.tsx @@ -28,7 +28,7 @@ const AccordionTrigger = React.forwardRef< svg]:rotate-180", + "flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left cursor-pointer [&[data-state=open]>svg]:rotate-180", className, )} {...props} From 3daf217c2b37c36e6a37994bce2cd340d131d5c6 Mon Sep 17 00:00:00 2001 From: shaynesidman <147111519+shaynesidman@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:09:15 -0400 Subject: [PATCH 4/4] fix: minor changes to help sheet --- src/components/HelpSheet.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/HelpSheet.tsx b/src/components/HelpSheet.tsx index 24b09e88..3f99c94b 100644 --- a/src/components/HelpSheet.tsx +++ b/src/components/HelpSheet.tsx @@ -67,7 +67,7 @@ function TrendLegend() { function CartBadge() { return ( - + 2 @@ -155,6 +155,7 @@ const pages: Page[] = [ export. , "Keyboard: ⌘S opens the export dialog, ⌘P downloads a PDF directly, B switches to bar chart, L switches to line chart.", + "Certain combinations of chart customizations do not make sense. For example, measuring total school count grouped by project type is such a combination. Such charts may yield nonsensical data or no data at all.", ], }, { @@ -198,7 +199,7 @@ const pages: Page[] = [ , "The student count line graph shows enrollment history over the past 5 years. Click it to open the Chart page filtered to this school.", "The project type distribution pie chart breaks down projects by category for the selected year.", - "School Location shows the school's pin on a map. Drag the pin to update its coordinates. Regions are automatically updated based on the new coordinates.", + "School Location shows the school's pin on a map. Click anywhere on the map to update its coordinates. Regions are automatically updated based on the new coordinates.", "The View and Edit Data table lists all project records for the selected year. Double-click any cell to edit it. Teacher changes apply globally across all of that teacher's projects.", "Double-click the school name at the top of the page to rename the school.", "Use the ⋮ menu to access Merge School, which combines this school's records with another school.", @@ -215,7 +216,7 @@ const pages: Page[] = [ "Step 2 — Validation checks the student spreadsheet format and data types. Any errors are highlighted so you can correct the source file and re-upload.", "Step 3 — Upload the school spreadsheet in the same way. Another template is available for this file as well.", "Step 4 — Validation checks the school spreadsheet, then schools are matched to their locations on the map based on previously known schools.", - "Step 5 — Any schools whose locations could not be matched must be placed manually. Drag a pin onto the map for each unmatched school.", + "Step 5 — Any schools whose locations could not be matched must be placed manually. Click anywhere on the map to place each unmatched school. Regions are automatically set for both matched and unmatched schools.", "Step 6 — Review a summary and confirm the upload to commit all data to the database.", ], },