From 89b1f10788e1d29ef6db78af746a79ef838bbeb8 Mon Sep 17 00:00:00 2001 From: James Singleton Date: Sun, 15 Mar 2026 20:39:22 -0700 Subject: [PATCH 01/12] feat: setup saas structure --- .eslintrc.js | 10 - apps/admin/.prettierignore | 5 - apps/admin/app/(auth)/layout.tsx | 12 - .../(auth)/sign-in/[[...sign-in]]/page.tsx | 7 - .../(auth)/sign-up/[[...sign-up]]/page.tsx | 7 - .../team/[teamId]/analytics/page.tsx | 0 .../(authenticated)/team/[teamId]/layout.tsx | 21 + .../team/[teamId]/meets/page.tsx | 44 +- .../(authenticated)/team/[teamId]/page.tsx | 382 ++ .../team/[teamId]/roster/import/page.tsx | 0 .../team/[teamId]/roster/page.tsx | 65 +- .../swimmers/[swimmerId]/edit/page.tsx | 0 .../[teamId]/swimmers/[swimmerId]/page.tsx | 78 +- .../team/[teamId]/swimmers/create/page.tsx | 0 .../workouts/[workoutId]/edit/page.tsx | 0 .../[teamId]/workouts/[workoutId]/page.tsx | 0 .../team/[teamId]/workouts/create/page.tsx | 0 .../team/[teamId]/workouts/page.tsx | 0 apps/admin/app/global-error.tsx | 23 + apps/admin/app/layout.tsx | 21 +- apps/admin/app/page.tsx | 113 - .../(.)[teamId]/swimmers/create/modal.tsx | 28 - .../(.)[teamId]/swimmers/create/page.tsx | 176 - apps/admin/app/team/@modal/default.tsx | 3 - apps/admin/app/team/[teamId]/page.tsx | 369 -- apps/admin/app/team/layout.tsx | 64 - apps/admin/components.json | 15 +- apps/admin/components/app-sidebar.tsx | 175 - .../dashboard/recent-drops-table.tsx | 143 + .../components/data-table-column-header.tsx | 76 - .../components/data-table-faceted-filter.tsx | 20 - .../components/data-table-pagination.tsx | 97 - .../components/data-table-view-options.tsx | 59 - apps/admin/components/header.tsx | 43 + apps/admin/components/nav-main.tsx | 73 - apps/admin/components/nav-projects.tsx | 89 - apps/admin/components/nav-user.tsx | 37 +- apps/admin/components/providers.tsx | 19 - apps/admin/components/roster/athlete-info.tsx | 224 - apps/admin/components/roster/columns.tsx | 279 - apps/admin/components/roster/data-table.tsx | 134 - apps/admin/components/search.tsx | 26 + apps/admin/components/sidebar.tsx | 260 + apps/admin/components/team-switcher.tsx | 20 +- apps/admin/components/theme-provider.tsx | 9 - apps/admin/env.ts | 11 + apps/admin/eslint.config.mjs | 4 - apps/admin/hooks/use-mobile.ts | 19 + apps/admin/lib/mock-data.tsx | 186 +- apps/admin/next.config.mjs | 6 - apps/admin/next.config.ts | 12 + apps/admin/package.json | 18 +- apps/admin/postcss.config.mjs | 2 +- apps/admin/tsconfig.json | 12 +- apps/web/.prettierignore | 5 - apps/web/app/layout.tsx | 19 +- apps/web/components.json | 15 +- apps/web/components/cta.tsx | 14 +- apps/web/components/date-picker.tsx | 22 +- apps/web/components/header.tsx | 66 +- apps/web/components/hero.tsx | 27 +- apps/web/components/infinite-moving-cards.tsx | 32 +- apps/web/eslint.config.mjs | 4 - apps/web/next.config.js | 2 +- apps/web/package.json | 3 +- apps/web/postcss.config.mjs | 2 +- apps/web/tsconfig.json | 2 +- biome.json | 26 + package.json | 7 +- packages/design-system/components.json | 23 + .../components/icons.tsx | 49 +- .../design-system/components/mode-toggle.tsx | 44 + .../components/ui/alert-dialog.tsx | 199 + .../components/ui/aspect-ratio.tsx | 11 + .../design-system/components/ui/avatar.tsx | 112 + .../design-system/components/ui/badge.tsx | 49 + .../components/ui}/breadcrumb.tsx | 59 +- .../components/ui/button-group.tsx | 83 + .../design-system/components/ui/button.tsx | 67 + .../design-system/components/ui/calendar.tsx | 222 + packages/design-system/components/ui/card.tsx | 103 + .../design-system/components/ui/carousel.tsx | 242 + .../design-system/components/ui/chart.tsx | 356 ++ .../design-system/components/ui/checkbox.tsx | 33 + .../components/ui}/collapsible.tsx | 12 +- .../design-system/components/ui/command.tsx | 195 + .../components/ui/context-menu.tsx | 263 + .../components/ui}/dialog.tsx | 92 +- .../design-system/components/ui/drawer.tsx | 131 + .../components/ui/dropdown-menu.tsx | 269 + .../design-system/components/ui/empty.tsx | 101 + .../design-system/components/ui/field.tsx | 238 + .../components/ui/hover-card.tsx | 44 + .../components/ui/input-group.tsx | 156 + .../design-system/components/ui/input-otp.tsx | 87 + .../design-system/components/ui/input.tsx | 19 + packages/design-system/components/ui/item.tsx | 196 + packages/design-system/components/ui/kbd.tsx | 26 + .../components/ui}/label.tsx | 14 +- .../design-system/components/ui/menubar.tsx | 280 + .../components/ui/navigation-menu.tsx | 164 + .../components/ui}/pagination.tsx | 92 +- .../design-system/components/ui/popover.tsx | 89 + .../design-system/components/ui/progress.tsx | 31 + .../components/ui/radio-group.tsx | 44 + .../design-system/components/ui/resizable.tsx | 50 + .../components/ui}/scroll-area.tsx | 27 +- .../design-system/components/ui/select.tsx | 192 + .../design-system/components/ui/separator.tsx | 28 + .../design-system/components/ui/sheet.tsx | 144 + .../components/ui}/sidebar.tsx | 360 +- .../design-system/components/ui/skeleton.tsx | 13 + .../design-system/components/ui/slider.tsx | 59 + .../design-system/components/ui/sonner.tsx | 49 + .../design-system/components/ui/spinner.tsx | 10 + .../design-system/components/ui/switch.tsx | 33 + .../components/ui}/table.tsx | 42 +- packages/design-system/components/ui/tabs.tsx | 90 + .../design-system/components/ui/textarea.tsx | 18 + .../components/ui/toggle-group.tsx | 89 + .../design-system/components/ui/toggle.tsx | 46 + .../design-system/components/ui/tooltip.tsx | 57 + .../src => design-system}/hooks/use-mobile.ts | 0 packages/design-system/index.tsx | 25 + packages/design-system/lib/fonts.ts | 9 + .../{ui/src => design-system}/lib/utils.ts | 0 packages/design-system/package.json | 48 + .../{ui => design-system}/postcss.config.mjs | 0 packages/design-system/providers/theme.tsx | 17 + packages/design-system/styles/globals.css | 128 + packages/design-system/tsconfig.json | 17 + packages/email/index.ts | 6 + packages/email/keys.ts | 14 + packages/email/package.json | 24 + packages/email/templates/contact.tsx | 54 + packages/email/tsconfig.json | 8 + packages/emails/package.json | 5 - packages/eslint-config/README.md | 3 - packages/eslint-config/base.js | 32 - packages/eslint-config/next.js | 51 - packages/eslint-config/package.json | 26 - packages/eslint-config/react-internal.js | 41 - packages/next-config/index.ts | 38 + packages/next-config/keys.ts | 38 + packages/next-config/package.json | 19 + packages/next-config/tsconfig.json | 8 + packages/parsers/package.json | 14 + packages/parsers/tsconfig.json | 8 + packages/typescript-config/base.json | 5 +- packages/typescript-config/nextjs.json | 10 +- packages/typescript-config/package.json | 5 +- packages/ui/components.json | 20 - packages/ui/eslint.config.mjs | 4 - packages/ui/package.json | 63 - packages/ui/src/components/avatar.tsx | 53 - packages/ui/src/components/badge.tsx | 46 - packages/ui/src/components/button.tsx | 59 - packages/ui/src/components/calendar.tsx | 210 - packages/ui/src/components/card.tsx | 92 - packages/ui/src/components/checkbox.tsx | 32 - packages/ui/src/components/command.tsx | 184 - packages/ui/src/components/dropdown-menu.tsx | 257 - packages/ui/src/components/input.tsx | 21 - .../ui/src/components/navigation-menu.tsx | 168 - packages/ui/src/components/popover.tsx | 48 - packages/ui/src/components/radio-group.tsx | 45 - packages/ui/src/components/select.tsx | 185 - packages/ui/src/components/separator.tsx | 28 - packages/ui/src/components/sheet.tsx | 139 - packages/ui/src/components/skeleton.tsx | 13 - packages/ui/src/components/switch.tsx | 31 - packages/ui/src/components/tabs.tsx | 66 - packages/ui/src/components/textarea.tsx | 18 - packages/ui/src/components/tooltip.tsx | 61 - packages/ui/src/styles/globals.css | 127 - packages/ui/tsconfig.json | 11 - packages/ui/tsconfig.lint.json | 8 - pnpm-lock.yaml | 5019 ++++++++++++----- turbo/generators/templates/config.ts | 37 + turbo/generators/templates/package.json | 3 + .../templates/templates/package.json.hbs | 9 + .../templates/templates/tsconfig.json.hbs | 12 + 182 files changed, 10539 insertions(+), 6427 deletions(-) delete mode 100644 .eslintrc.js delete mode 100644 apps/admin/.prettierignore delete mode 100644 apps/admin/app/(auth)/layout.tsx delete mode 100644 apps/admin/app/(auth)/sign-in/[[...sign-in]]/page.tsx delete mode 100644 apps/admin/app/(auth)/sign-up/[[...sign-up]]/page.tsx rename apps/admin/app/{ => (authenticated)}/team/[teamId]/analytics/page.tsx (100%) create mode 100644 apps/admin/app/(authenticated)/team/[teamId]/layout.tsx rename apps/admin/app/{ => (authenticated)}/team/[teamId]/meets/page.tsx (86%) create mode 100644 apps/admin/app/(authenticated)/team/[teamId]/page.tsx create mode 100644 apps/admin/app/(authenticated)/team/[teamId]/roster/import/page.tsx rename apps/admin/app/{ => (authenticated)}/team/[teamId]/roster/page.tsx (89%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/swimmers/[swimmerId]/edit/page.tsx (100%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/swimmers/[swimmerId]/page.tsx (84%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/swimmers/create/page.tsx (100%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/workouts/[workoutId]/edit/page.tsx (100%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/workouts/[workoutId]/page.tsx (100%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/workouts/create/page.tsx (100%) rename apps/admin/app/{ => (authenticated)}/team/[teamId]/workouts/page.tsx (100%) create mode 100644 apps/admin/app/global-error.tsx delete mode 100644 apps/admin/app/page.tsx delete mode 100644 apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/modal.tsx delete mode 100644 apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/page.tsx delete mode 100644 apps/admin/app/team/@modal/default.tsx delete mode 100644 apps/admin/app/team/[teamId]/page.tsx delete mode 100644 apps/admin/app/team/layout.tsx delete mode 100644 apps/admin/components/app-sidebar.tsx create mode 100644 apps/admin/components/dashboard/recent-drops-table.tsx delete mode 100644 apps/admin/components/data-table-column-header.tsx delete mode 100644 apps/admin/components/data-table-faceted-filter.tsx delete mode 100644 apps/admin/components/data-table-pagination.tsx delete mode 100644 apps/admin/components/data-table-view-options.tsx create mode 100644 apps/admin/components/header.tsx delete mode 100644 apps/admin/components/nav-main.tsx delete mode 100644 apps/admin/components/nav-projects.tsx delete mode 100644 apps/admin/components/providers.tsx delete mode 100644 apps/admin/components/roster/athlete-info.tsx delete mode 100644 apps/admin/components/roster/columns.tsx delete mode 100644 apps/admin/components/roster/data-table.tsx create mode 100644 apps/admin/components/search.tsx create mode 100644 apps/admin/components/sidebar.tsx delete mode 100644 apps/admin/components/theme-provider.tsx create mode 100644 apps/admin/env.ts delete mode 100644 apps/admin/eslint.config.mjs create mode 100644 apps/admin/hooks/use-mobile.ts delete mode 100644 apps/admin/next.config.mjs create mode 100644 apps/admin/next.config.ts delete mode 100644 apps/web/.prettierignore delete mode 100644 apps/web/eslint.config.mjs create mode 100644 biome.json create mode 100644 packages/design-system/components.json rename packages/{ui/src => design-system}/components/icons.tsx (97%) create mode 100644 packages/design-system/components/mode-toggle.tsx create mode 100644 packages/design-system/components/ui/alert-dialog.tsx create mode 100644 packages/design-system/components/ui/aspect-ratio.tsx create mode 100644 packages/design-system/components/ui/avatar.tsx create mode 100644 packages/design-system/components/ui/badge.tsx rename packages/{ui/src/components => design-system/components/ui}/breadcrumb.tsx (59%) create mode 100644 packages/design-system/components/ui/button-group.tsx create mode 100644 packages/design-system/components/ui/button.tsx create mode 100644 packages/design-system/components/ui/calendar.tsx create mode 100644 packages/design-system/components/ui/card.tsx create mode 100644 packages/design-system/components/ui/carousel.tsx create mode 100644 packages/design-system/components/ui/chart.tsx create mode 100644 packages/design-system/components/ui/checkbox.tsx rename packages/{ui/src/components => design-system/components/ui}/collapsible.tsx (79%) create mode 100644 packages/design-system/components/ui/command.tsx create mode 100644 packages/design-system/components/ui/context-menu.tsx rename packages/{ui/src/components => design-system/components/ui}/dialog.tsx (50%) create mode 100644 packages/design-system/components/ui/drawer.tsx create mode 100644 packages/design-system/components/ui/dropdown-menu.tsx create mode 100644 packages/design-system/components/ui/empty.tsx create mode 100644 packages/design-system/components/ui/field.tsx create mode 100644 packages/design-system/components/ui/hover-card.tsx create mode 100644 packages/design-system/components/ui/input-group.tsx create mode 100644 packages/design-system/components/ui/input-otp.tsx create mode 100644 packages/design-system/components/ui/input.tsx create mode 100644 packages/design-system/components/ui/item.tsx create mode 100644 packages/design-system/components/ui/kbd.tsx rename packages/{ui/src/components => design-system/components/ui}/label.tsx (71%) create mode 100644 packages/design-system/components/ui/menubar.tsx create mode 100644 packages/design-system/components/ui/navigation-menu.tsx rename packages/{ui/src/components => design-system/components/ui}/pagination.tsx (53%) create mode 100644 packages/design-system/components/ui/popover.tsx create mode 100644 packages/design-system/components/ui/progress.tsx create mode 100644 packages/design-system/components/ui/radio-group.tsx create mode 100644 packages/design-system/components/ui/resizable.tsx rename packages/{ui/src/components => design-system/components/ui}/scroll-area.tsx (55%) create mode 100644 packages/design-system/components/ui/select.tsx create mode 100644 packages/design-system/components/ui/separator.tsx create mode 100644 packages/design-system/components/ui/sheet.tsx rename packages/{ui/src/components => design-system/components/ui}/sidebar.tsx (57%) create mode 100644 packages/design-system/components/ui/skeleton.tsx create mode 100644 packages/design-system/components/ui/slider.tsx create mode 100644 packages/design-system/components/ui/sonner.tsx create mode 100644 packages/design-system/components/ui/spinner.tsx create mode 100644 packages/design-system/components/ui/switch.tsx rename packages/{ui/src/components => design-system/components/ui}/table.tsx (74%) create mode 100644 packages/design-system/components/ui/tabs.tsx create mode 100644 packages/design-system/components/ui/textarea.tsx create mode 100644 packages/design-system/components/ui/toggle-group.tsx create mode 100644 packages/design-system/components/ui/toggle.tsx create mode 100644 packages/design-system/components/ui/tooltip.tsx rename packages/{ui/src => design-system}/hooks/use-mobile.ts (100%) create mode 100644 packages/design-system/index.tsx create mode 100644 packages/design-system/lib/fonts.ts rename packages/{ui/src => design-system}/lib/utils.ts (100%) create mode 100644 packages/design-system/package.json rename packages/{ui => design-system}/postcss.config.mjs (100%) create mode 100644 packages/design-system/providers/theme.tsx create mode 100644 packages/design-system/styles/globals.css create mode 100644 packages/design-system/tsconfig.json create mode 100644 packages/email/index.ts create mode 100644 packages/email/keys.ts create mode 100644 packages/email/package.json create mode 100644 packages/email/templates/contact.tsx create mode 100644 packages/email/tsconfig.json delete mode 100644 packages/emails/package.json delete mode 100644 packages/eslint-config/README.md delete mode 100644 packages/eslint-config/base.js delete mode 100644 packages/eslint-config/next.js delete mode 100644 packages/eslint-config/package.json delete mode 100644 packages/eslint-config/react-internal.js create mode 100644 packages/next-config/index.ts create mode 100644 packages/next-config/keys.ts create mode 100644 packages/next-config/package.json create mode 100644 packages/next-config/tsconfig.json create mode 100644 packages/parsers/package.json create mode 100644 packages/parsers/tsconfig.json delete mode 100644 packages/ui/components.json delete mode 100644 packages/ui/eslint.config.mjs delete mode 100644 packages/ui/package.json delete mode 100644 packages/ui/src/components/avatar.tsx delete mode 100644 packages/ui/src/components/badge.tsx delete mode 100644 packages/ui/src/components/button.tsx delete mode 100644 packages/ui/src/components/calendar.tsx delete mode 100644 packages/ui/src/components/card.tsx delete mode 100644 packages/ui/src/components/checkbox.tsx delete mode 100644 packages/ui/src/components/command.tsx delete mode 100644 packages/ui/src/components/dropdown-menu.tsx delete mode 100644 packages/ui/src/components/input.tsx delete mode 100644 packages/ui/src/components/navigation-menu.tsx delete mode 100644 packages/ui/src/components/popover.tsx delete mode 100644 packages/ui/src/components/radio-group.tsx delete mode 100644 packages/ui/src/components/select.tsx delete mode 100644 packages/ui/src/components/separator.tsx delete mode 100644 packages/ui/src/components/sheet.tsx delete mode 100644 packages/ui/src/components/skeleton.tsx delete mode 100644 packages/ui/src/components/switch.tsx delete mode 100644 packages/ui/src/components/tabs.tsx delete mode 100644 packages/ui/src/components/textarea.tsx delete mode 100644 packages/ui/src/components/tooltip.tsx delete mode 100644 packages/ui/src/styles/globals.css delete mode 100644 packages/ui/tsconfig.json delete mode 100644 packages/ui/tsconfig.lint.json create mode 100644 turbo/generators/templates/config.ts create mode 100644 turbo/generators/templates/package.json create mode 100644 turbo/generators/templates/templates/package.json.hbs create mode 100644 turbo/generators/templates/templates/tsconfig.json.hbs diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 867a247..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -// This configuration only applies to the package manager root. -/** @type {import("eslint").Linter.Config} */ -module.exports = { - ignorePatterns: ["apps/**", "packages/**"], - extends: ["@workspace/eslint-config/library.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, -}; diff --git a/apps/admin/.prettierignore b/apps/admin/.prettierignore deleted file mode 100644 index fce80f5..0000000 --- a/apps/admin/.prettierignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -.next -public -pnpm-lock.yaml -supabase \ No newline at end of file diff --git a/apps/admin/app/(auth)/layout.tsx b/apps/admin/app/(auth)/layout.tsx deleted file mode 100644 index aba4f4b..0000000 --- a/apps/admin/app/(auth)/layout.tsx +++ /dev/null @@ -1,12 +0,0 @@ -export default function AuthLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - <> -

Auth Layout

- {children} - - ); -} diff --git a/apps/admin/app/(auth)/sign-in/[[...sign-in]]/page.tsx b/apps/admin/app/(auth)/sign-in/[[...sign-in]]/page.tsx deleted file mode 100644 index 1e80856..0000000 --- a/apps/admin/app/(auth)/sign-in/[[...sign-in]]/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function SignInPage() { - return ( - <> -

Sign In Page

- - ); -} diff --git a/apps/admin/app/(auth)/sign-up/[[...sign-up]]/page.tsx b/apps/admin/app/(auth)/sign-up/[[...sign-up]]/page.tsx deleted file mode 100644 index d22fc75..0000000 --- a/apps/admin/app/(auth)/sign-up/[[...sign-up]]/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function SignUpPage() { - return ( - <> -

Sign Up Page

- - ); -} diff --git a/apps/admin/app/team/[teamId]/analytics/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/analytics/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/analytics/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/analytics/page.tsx diff --git a/apps/admin/app/(authenticated)/team/[teamId]/layout.tsx b/apps/admin/app/(authenticated)/team/[teamId]/layout.tsx new file mode 100644 index 0000000..783fceb --- /dev/null +++ b/apps/admin/app/(authenticated)/team/[teamId]/layout.tsx @@ -0,0 +1,21 @@ +import { SidebarProvider } from '@project-aqua/design-system/components/ui/sidebar' +import type { ReactNode } from "react"; +import { GlobalSidebar } from '@/components/sidebar'; + +interface AdminLayoutProperties { + readonly children: ReactNode; + readonly params: Promise<{ teamId: string }>; +} + +const AdminLayout = async ({ children, params }: AdminLayoutProperties) => { + const { teamId } = await params; + return ( + + + { children} + + + ) +} + +export default AdminLayout diff --git a/apps/admin/app/team/[teamId]/meets/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/meets/page.tsx similarity index 86% rename from apps/admin/app/team/[teamId]/meets/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/meets/page.tsx index 2e3972c..37b5048 100644 --- a/apps/admin/app/team/[teamId]/meets/page.tsx +++ b/apps/admin/app/(authenticated)/team/[teamId]/meets/page.tsx @@ -1,23 +1,23 @@ -import { Button } from "@project-aqua/ui/components/button"; +import { Badge } from "@project-aqua/design-system/components/ui/badge"; +import { Button } from "@project-aqua/design-system/components/ui/button"; import { Card, + CardContent, + CardDescription, CardHeader, CardTitle, - CardDescription, - CardContent, -} from "@project-aqua/ui/components/card"; -import { Input } from "@project-aqua/ui/components/input"; -import { Label } from "@project-aqua/ui/components/label"; -import { Select } from "@project-aqua/ui/components/select"; +} from "@project-aqua/design-system/components/ui/card"; +import { Input } from "@project-aqua/design-system/components/ui/input"; +import { Label } from "@project-aqua/design-system/components/ui/label"; +import { Select } from "@project-aqua/design-system/components/ui/select"; import { - TableHeader, - TableRow, - TableHead, + Table, TableBody, TableCell, - Table, -} from "@project-aqua/ui/components/table"; -import { Badge } from "@project-aqua/ui/components/badge"; + TableHead, + TableHeader, + TableRow, +} from "@project-aqua/design-system/components/ui/table"; export default async function MeetsPage({ params, @@ -32,7 +32,7 @@ export default async function MeetsPage({ Add Meet -
+
@@ -115,10 +115,10 @@ export default async function MeetsPage({
Summer Invitational
Registered -
+
July 20, 2023 - Riverside Swim Club
-
+
Prepare for the big event!
@@ -127,10 +127,10 @@ export default async function MeetsPage({
Winter Classic
Registered
-
+
December 10, 2023 - Northside Swim Center
-
+
Get ready for the winter season!
@@ -149,10 +149,10 @@ export default async function MeetsPage({
Regional Championships
Completed
-
+
June 15, 2023 - Olympia Aquatic Center
-
+
Great performance by the team!
@@ -161,10 +161,10 @@ export default async function MeetsPage({
Fall Championships
Cancelled
-
+
September 5, 2023 - Aquatic Center of Excellence
-
+
Unfortunate cancellation due to weather.
diff --git a/apps/admin/app/(authenticated)/team/[teamId]/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/page.tsx new file mode 100644 index 0000000..f9f4c92 --- /dev/null +++ b/apps/admin/app/(authenticated)/team/[teamId]/page.tsx @@ -0,0 +1,382 @@ +import { Badge } from "@project-aqua/design-system/components/ui/badge"; +import { Button } from "@project-aqua/design-system/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@project-aqua/design-system/components/ui/card"; +import { Progress } from "@project-aqua/design-system/components/ui/progress"; +import { Separator } from "@project-aqua/design-system/components/ui/separator"; +import { + AlertCircleIcon, + CalendarIcon, + CheckCircle2Icon, + ChevronRightIcon, + ClipboardListIcon, + ClockIcon, + TrendingUpIcon, + TrophyIcon, + UploadIcon, + UsersIcon, + WavesIcon, + XCircleIcon, +} from "lucide-react"; +import type { Metadata, ResolvingMetadata } from "next"; +import Link from "next/link"; +import { RecentDropsTable } from "@/components/dashboard/recent-drops-table"; +import { Header } from "@/components/header"; +import { + actionItems, + attendanceThisWeek, + recentDrops, + upcomingMeets, +} from "@/lib/mock-data"; + +interface HomePageProps { + params: Promise<{ teamId: string }>; +} + +const urgencyConfig = { + urgent: { label: "Urgent", variant: "destructive" as const }, + soon: { label: "Soon", variant: "secondary" as const }, + ok: { label: "On track", variant: "outline" as const }, +}; + +const actionUrgencyConfig = { + high: { + icon: XCircleIcon, + className: "text-destructive", + badgeVariant: "destructive" as const, + }, + medium: { + icon: AlertCircleIcon, + className: "text-yellow-500", + badgeVariant: "secondary" as const, + }, + low: { + icon: CheckCircle2Icon, + className: "text-muted-foreground", + badgeVariant: "outline" as const, + }, +}; + +const actionTypeIcon = { + entry_deadline: CalendarIcon, + missing_times: ClockIcon, + import_needed: UploadIcon, + attendance: UsersIcon, +}; + +export async function generateMetadata( + { params }: HomePageProps, + parent: ResolvingMetadata +): Promise { + const { teamId } = await params; + const previousMetadata = (await parent).title; + + return { + ...previousMetadata, + alternates: { + canonical: `/team/${teamId}`, + }, + }; +} + +export default async function AdminHomePage({ + params, +}: { + params: Promise<{ teamId: string }>; +}) { + const { teamId } = await params; + const totalAthletes = 24; + const activeMeets = upcomingMeets.length; + const pbsThisMonth = recentDrops.length; + const avgAttendance = Math.round( + (attendanceThisWeek.reduce((sum, d) => sum + d.present, 0) / + attendanceThisWeek.reduce((sum, d) => sum + d.total, 0)) * + 100 + ); + + return ( + <> +
+
+
+
+

Dashboard

+

+ Sunday, March 15, 2026 +

+
+
+ + +
+
+ {/* Stat cards */} +
+ + + + + Athletes + + + +
+ {totalAthletes} +
+

+ Active on roster +

+
+
+ + + + + + Upcoming meets + + + +
+ {activeMeets} +
+

Next 30 days

+
+
+ + + + + + PBs this month + + + +
+ {pbsThisMonth} +
+

+ Personal bests set +

+
+
+ + + + + + Avg attendance + + + +
+ {avgAttendance}% +
+

This week

+
+
+
+ {/* Action items + Upcoming meets */} +
+ {/* Action items */} + + +
+ Needs attention + + {actionItems.filter((a) => a.urgency === "high").length}{" "} + urgent + +
+
+ +
+ {actionItems.map((item) => { + const { icon: UrgencyIcon, className } = + actionUrgencyConfig[item.urgency]; + const TypeIcon = actionTypeIcon[item.type]; + return ( + + +
+

+ {item.title} +

+

+ {item.description} +

+
+ + + ); + })} +
+
+
+ + {/* Upcoming meets */} + + +
+ Upcoming meets + +
+
+ +
+ {upcomingMeets.map((meet) => { + const { label, variant } = + urgencyConfig[meet.deadlineUrgency]; + const entryPct = Math.round( + (meet.entriesSubmitted / meet.entriesTotal) * 100 + ); + return ( + +
+
+

+ {meet.name} +

+

+ {meet.date} · {meet.location} +

+
+ + {label} + +
+
+
+ + Entries: {meet.entriesSubmitted}/{meet.entriesTotal} + + + Due {meet.entryDeadline} + +
+ +
+ + ); + })} +
+
+
+
+ + {/* Recent PBs + Attendance */} +
+ {/* Recent PBs table — takes 2/3 width */} + + +
+
+ + Recent personal bests + + + Times dropped in the last 7 days + +
+ +
+
+ + + +
+ + {/* Attendance this week — takes 1/3 width */} + + + Attendance this week + + {avgAttendance}% average turnout + + + +
+ {attendanceThisWeek.map((day) => { + const pct = Math.round((day.present / day.total) * 100); + return ( +
+
+ + {day.date} + + + {day.present}/{day.total} + + + {pct}% + +
+ +
+ ); + })} +
+ + +
+
+
+
+ + ); +} diff --git a/apps/admin/app/(authenticated)/team/[teamId]/roster/import/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/roster/import/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/apps/admin/app/team/[teamId]/roster/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/roster/page.tsx similarity index 89% rename from apps/admin/app/team/[teamId]/roster/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/roster/page.tsx index c3c0709..3663928 100644 --- a/apps/admin/app/team/[teamId]/roster/page.tsx +++ b/apps/admin/app/(authenticated)/team/[teamId]/roster/page.tsx @@ -1,35 +1,36 @@ -import Link from "next/link"; -import { FileIcon, UserPlusIcon } from "lucide-react"; +import { + Button, + buttonVariants, +} from "@project-aqua/design-system/components/button"; import { Card, - CardHeader, - CardTitle, - CardDescription, CardContent, + CardDescription, CardFooter, -} from "@project-aqua/ui/components/card"; -import { Button, buttonVariants } from "@project-aqua/ui/components/button"; -import { - Tabs, - TabsList, - TabsTrigger, - TabsContent, -} from "@project-aqua/ui/components/tabs"; + CardHeader, + CardTitle, +} from "@project-aqua/design-system/components/card"; import { Table, - TableHeader, - TableRow, - TableHead, TableBody, TableCell, -} from "@project-aqua/ui/components/table"; -import AthleteInfo from "@/components/roster/athlete-info"; -import { mockAthleteData } from "@/lib/mock-data"; + TableHead, + TableHeader, + TableRow, +} from "@project-aqua/design-system/components/table"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@project-aqua/design-system/components/tabs"; +import { FileIcon, UserPlusIcon } from "lucide-react"; +import type { Metadata, ResolvingMetadata } from "next"; +import Link from "next/link"; import { columns } from "@/components/roster/columns"; import { DataTable } from "@/components/roster/data-table"; - -import { Athlete } from "@/types"; -import type { Metadata, ResolvingMetadata } from "next"; +import { mockAthleteData } from "@/lib/mock-data"; +import type { Athlete } from "@/types"; async function getData({ teamId }: { teamId: string }): Promise { return mockAthleteData; @@ -43,7 +44,7 @@ export async function generateMetadata( params: Promise<{ teamId: string }>; searchParams: Promise<{ [key: string]: string | string[] | undefined }>; }, - parent: ResolvingMetadata, + parent: ResolvingMetadata ): Promise { const { teamId } = await params; @@ -76,22 +77,22 @@ export default async function RosterPage({ const rosterData = await getData({ teamId }); const { athleteId } = await searchParams; const selectedAthlete = rosterData.find( - (athlete) => athlete.id === athleteId, + (athlete) => athlete.id === athleteId ); const maleSwimmers = rosterData.filter( - (athlete) => athlete.gender === "Male", + (athlete) => athlete.gender === "Male" ); const femaleSwimmers = rosterData.filter( - (athlete) => athlete.gender === "Female", + (athlete) => athlete.gender === "Female" ); return ( <>
-

Roster

+

Roster

-
+
@@ -103,8 +104,8 @@ export default async function RosterPage({ Add Swimmer @@ -118,10 +119,10 @@ export default async function RosterPage({
-
+
Male Swimmers: {maleSwimmers.length}
-
+
Female Swimmers: {femaleSwimmers.length}
@@ -134,7 +135,7 @@ export default async function RosterPage({
- +
Swimmers diff --git a/apps/admin/app/team/[teamId]/swimmers/[swimmerId]/edit/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/swimmers/[swimmerId]/edit/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/swimmers/[swimmerId]/edit/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/swimmers/[swimmerId]/edit/page.tsx diff --git a/apps/admin/app/team/[teamId]/swimmers/[swimmerId]/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/swimmers/[swimmerId]/page.tsx similarity index 84% rename from apps/admin/app/team/[teamId]/swimmers/[swimmerId]/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/swimmers/[swimmerId]/page.tsx index 3f2eb10..2f5bf85 100644 --- a/apps/admin/app/team/[teamId]/swimmers/[swimmerId]/page.tsx +++ b/apps/admin/app/(authenticated)/team/[teamId]/swimmers/[swimmerId]/page.tsx @@ -1,69 +1,51 @@ -import Link from "next/link"; -import { - User, - Calendar, - Phone, - Users, - Trophy, - TrendingUp, - Edit, -} from "lucide-react"; import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@project-aqua/ui/components/tabs"; + Avatar, + AvatarFallback, + AvatarImage, +} from "@project-aqua/design-system/components/avatar"; +import { buttonVariants } from "@project-aqua/design-system/components/button"; import { Card, CardContent, CardDescription, - CardFooter, CardHeader, CardTitle, -} from "@project-aqua/ui/components/card"; +} from "@project-aqua/design-system/components/card"; +import { Label } from "@project-aqua/design-system/components/label"; import { - Avatar, - AvatarFallback, - AvatarImage, -} from "@project-aqua/ui/components/avatar"; -import { Button, buttonVariants } from "@project-aqua/ui/components/button"; -import { Input } from "@project-aqua/ui/components/input"; -import { Label } from "@project-aqua/ui/components/label"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@project-aqua/ui/components/table"; + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@project-aqua/design-system/components/tabs"; +import { Edit } from "lucide-react"; +import Link from "next/link"; interface Swimmer { - id: string; - name: string; avatar: string; birthday: string; - joinDate: string; - group: string; emergencyContacts: { name: string; relation: string; phone: string; }[]; + group: string; + id: string; + joinDate: string; + name: string; } interface MeetResult { - id: string; date: string; - meetName: string; event: string; - time: string; + id: string; + meetName: string; place: number; + time: string; } async function getSwimmerData( - swimmerId: string, + swimmerId: string ): Promise<{ swimmer: Swimmer; meetResults: MeetResult[] }> { // In a real application, this would be an API call or database query const swimmer: Swimmer = { @@ -118,10 +100,10 @@ export default async function AthletePage({ const { swimmer, meetResults } = await getSwimmerData(swimmerId); return (
-
+
- + {swimmer.name .split(" ") @@ -130,13 +112,13 @@ export default async function AthletePage({
-

{swimmer.name}

-

{swimmer.group}

+

{swimmer.name}

+

{swimmer.group}

Edit Swimmer @@ -148,7 +130,7 @@ export default async function AthletePage({ Info Meet Results - + Swimmer Info @@ -189,7 +171,7 @@ export default async function AthletePage({
-

Primary Contact

+

Primary Contact

@@ -210,7 +192,7 @@ export default async function AthletePage({
-

Secondary Contact

+

Secondary Contact

diff --git a/apps/admin/app/team/[teamId]/swimmers/create/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/swimmers/create/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/swimmers/create/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/swimmers/create/page.tsx diff --git a/apps/admin/app/team/[teamId]/workouts/[workoutId]/edit/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/workouts/[workoutId]/edit/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/workouts/[workoutId]/edit/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/workouts/[workoutId]/edit/page.tsx diff --git a/apps/admin/app/team/[teamId]/workouts/[workoutId]/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/workouts/[workoutId]/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/workouts/[workoutId]/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/workouts/[workoutId]/page.tsx diff --git a/apps/admin/app/team/[teamId]/workouts/create/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/workouts/create/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/workouts/create/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/workouts/create/page.tsx diff --git a/apps/admin/app/team/[teamId]/workouts/page.tsx b/apps/admin/app/(authenticated)/team/[teamId]/workouts/page.tsx similarity index 100% rename from apps/admin/app/team/[teamId]/workouts/page.tsx rename to apps/admin/app/(authenticated)/team/[teamId]/workouts/page.tsx diff --git a/apps/admin/app/global-error.tsx b/apps/admin/app/global-error.tsx new file mode 100644 index 0000000..5a12477 --- /dev/null +++ b/apps/admin/app/global-error.tsx @@ -0,0 +1,23 @@ +"use client"; + +import { Button } from "@project-aqua/design-system/components/ui/button"; +import { fonts } from "@project-aqua/design-system/lib/fonts"; +import type NextError from "next/error"; + +interface GlobalErrorProperties { + readonly error: NextError & { digest?: string }; + readonly reset: () => void; +} + +const GlobalError = ({ error, reset }: GlobalErrorProperties) => { + return ( + + +

Oops, something went wrong

+ + + + ); +}; + +export default GlobalError; diff --git a/apps/admin/app/layout.tsx b/apps/admin/app/layout.tsx index 9c666bd..8aa2e44 100644 --- a/apps/admin/app/layout.tsx +++ b/apps/admin/app/layout.tsx @@ -1,8 +1,11 @@ -import { GeistSans } from "geist/font/sans"; -import { GeistMono } from "geist/font/mono"; +import { Geist } from "next/font/google"; -import "@project-aqua/ui/globals.css"; -import Providers from "@/components/providers"; +import "@project-aqua/design-system/styles/globals.css"; +import { DesignSystemProvider } from "@project-aqua/design-system"; +import { fonts } from "@project-aqua/design-system/lib/fonts"; +import { cn } from "@project-aqua/design-system/lib/utils"; + +const geist = Geist({subsets:['latin'],variable:'--font-sans'}); export default function RootLayout({ children, @@ -11,14 +14,14 @@ export default function RootLayout({ }>) { return ( - - - <>{children} - + + + {children} + ); diff --git a/apps/admin/app/page.tsx b/apps/admin/app/page.tsx deleted file mode 100644 index dc191aa..0000000 --- a/apps/admin/app/page.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import Image from "next/image"; - -export default function Home() { - return ( -
-
-

- Get started by editing  - app/page.tsx -

- -
- -
- -
- - -
- ); -} diff --git a/apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/modal.tsx b/apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/modal.tsx deleted file mode 100644 index a6fd5bb..0000000 --- a/apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/modal.tsx +++ /dev/null @@ -1,28 +0,0 @@ -"use client"; - -import { type ElementRef, useEffect, useRef } from "react"; -import { Dialog } from "@project-aqua/ui/components/dialog"; -import { useRouter } from "next/navigation"; -import { createPortal } from "react-dom"; - -export function Modal({ children }: { children: React.ReactElement }) { - const router = useRouter(); - const dialogRef = useRef>(null); - - useEffect(() => { - if (!dialogRef.current?.open) { - dialogRef.current?.showModal(); - } - }, []); - - function navigateBack() { - router.back(); - } - - return createPortal( - !open && navigateBack()}> - {children} - , - document.getElementById("modal-root")!, - ); -} diff --git a/apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/page.tsx b/apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/page.tsx deleted file mode 100644 index e1ad938..0000000 --- a/apps/admin/app/team/@modal/(.)[teamId]/swimmers/create/page.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import { UploadIcon, CalendarDaysIcon } from "lucide-react"; -import { - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogFooter, -} from "@project-aqua/ui/components/dialog"; -import { Label } from "@project-aqua/ui/components/label"; -import { Input } from "@project-aqua/ui/components/input"; -import { Button } from "@project-aqua/ui/components/button"; -import { - Avatar, - AvatarImage, - AvatarFallback, -} from "@project-aqua/ui/components/avatar"; -import { - Select, - SelectTrigger, - SelectValue, - SelectContent, - SelectItem, -} from "@project-aqua/ui/components/select"; -import { - Popover, - PopoverTrigger, - PopoverContent, -} from "@project-aqua/ui/components/popover"; -import { Calendar } from "@project-aqua/ui/components/calendar"; - -import { Modal } from "./modal"; - -export default function AthleteModal() { - return ( - - - - Add Swimmer - - Fill out the form to add a new swimmer to the team. - - -
-
-
- - - JD - - -
-
- - -
-
-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
-
-
- - -
-
- - - - - - - - - -
-
-
-
- - - - - - - - - -
-
-
-
-

Primary Contact

-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
-
-
-
- - - -
-
- ); -} diff --git a/apps/admin/app/team/@modal/default.tsx b/apps/admin/app/team/@modal/default.tsx deleted file mode 100644 index 4e8611a..0000000 --- a/apps/admin/app/team/@modal/default.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function DefaultModal() { - return null; -} diff --git a/apps/admin/app/team/[teamId]/page.tsx b/apps/admin/app/team/[teamId]/page.tsx deleted file mode 100644 index 395200a..0000000 --- a/apps/admin/app/team/[teamId]/page.tsx +++ /dev/null @@ -1,369 +0,0 @@ -import Link from "next/link"; -import { - Users, - ArrowUpRight, - CreditCard, - DollarSign, - Activity, - CalendarIcon, - CircleX, - CircleCheck, - Calendar, - Award, - TrendingUp, -} from "lucide-react"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@project-aqua/ui/components/card"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableRow, - TableHeader, -} from "@project-aqua/ui/components/table"; -import { - Avatar, - AvatarFallback, - AvatarImage, -} from "@project-aqua/ui/components/avatar"; -import { Button, buttonVariants } from "@project-aqua/ui/components/button"; -import { Badge } from "@project-aqua/ui/components/badge"; -import { cn } from "@project-aqua/ui/lib/utils"; - -import type { Metadata, ResolvingMetadata } from "next"; - -type Props = { - params: Promise<{ teamId: string }>; - searchParams: Promise<{ [key: string]: string | string[] | undefined }>; -}; - -export async function generateMetadata( - { params, searchParams }: Props, - parent: ResolvingMetadata, -): Promise { - const { teamId } = await params; - const previousMetadata = (await parent).title; - - return { - ...previousMetadata, - alternates: { - canonical: `/team/${teamId}`, - }, - }; -} - -const swimMeets = [ - { - id: 1, - name: "Casteel & Desert Sunrise", - address: "Copper Sky Recreation Complex", - date: "2023-08-31", - paid: true, - }, - { - id: 2, - name: "Corona del Sol", - address: "NOZOMI Park", - date: "2023-09-07", - paid: false, - }, - { - id: 3, - name: "Crosswhite Invitational", - address: "Chandler High School", - date: "2023-09-09", - paid: true, - }, -]; - -export default async function AdminHomePage({ - params, -}: { - params: Promise<{ teamId: string }>; -}) { - const { teamId } = await params; - return ( - <> -

Dashboard

-
-
- - - - Total Swimmers - - - - -
45
-

- +4 from last season -

-
-
- - - - Upcoming Meets - - - - -
3
-

- Next meet in 2 weeks -

-
-
- - - - Team Records - - - - -
12
-

2 new this season

-
-
- - - - Performance Trend - - - - -
+8.2%
-

- Improvement from last meet -

-
-
-
-
- - -
- Upcoming Swim Meets - - A list of all upcoming swim meets for the next 30 days. - -
- - View All - - -
- -
- - - Customer - Type - - Status - - Date - Amount - - - - - -
Liam Johnson
-
- liam@example.com -
-
- - Invitational - - - - Approved - - - - 2023-06-23 - - $250.00 -
- - -
Olivia Smith
-
- olivia@example.com -
-
- - Dual Meet - - - - Declined - - - - 2023-06-24 - - $150.00 -
- - -
Noah Williams
-
- noah@example.com -
-
- - Subscription - - - - Approved - - - - 2023-06-25 - - $350.00 -
- - -
Emma Brown
-
- emma@example.com -
-
- Sale - - - Approved - - - - 2023-06-26 - - $450.00 -
- - -
Liam Johnson
-
- liam@example.com -
-
- Sale - - - Approved - - - - 2023-06-27 - - $550.00 -
-
-
- - - - - Action Items - - -
- - - OM - -
-

- Olivia Martin -

-

- olivia.martin@email.com -

-
-
+$1,999.00
-
-
- - - JL - -
-

- Jackson Lee -

-

- jackson.lee@email.com -

-
-
+$39.00
-
-
- - - IN - -
-

- Isabella Nguyen -

-

- isabella.nguyen@email.com -

-
-
+$299.00
-
-
- - - WK - -
-

- William Kim -

-

- will@email.com -

-
-
+$99.00
-
-
- - - SD - -
-

- Sofia Davis -

-

- sofia.davis@email.com -

-
-
+$39.00
-
-
-
-
-
- - ); -} diff --git a/apps/admin/app/team/layout.tsx b/apps/admin/app/team/layout.tsx deleted file mode 100644 index 8e6570e..0000000 --- a/apps/admin/app/team/layout.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import type { Metadata } from "next"; -import { - SidebarInset, - SidebarProvider, - SidebarTrigger, -} from "@project-aqua/ui/components/sidebar"; -import { AppSidebar } from "@/components/app-sidebar"; -import { Separator } from "@project-aqua/ui/components/separator"; -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@project-aqua/ui/components/breadcrumb"; - -export const metadata: Metadata = { - metadataBase: new URL("http://localhost:3001"), - title: { - template: "%s | Project Aqua", - default: - "Swim Coach Dashboard: Roster, Upcoming Meets, and More | Project Aqua", - }, - description: - "Stay on top of your swim team's activities with Project Aqua's Swim Coach Dashboard. View your roster, track upcoming meets, and access other essential tools for effective team management.", -}; - -export default function AdminLayout({ - children, - modal, -}: Readonly<{ - children: React.ReactNode; - modal: React.ReactNode; -}>) { - return ( - - - -
-
- - - - - - - Building Your Application - - - - - Data Fetching - - - -
-
-
{children}
-
-