- vitest.config.ts: add explicit exclude (e2e/**, playwright-report/**,
test-results/**) spread with configDefaults.exclude to keep
node_modules/dist filtering intact
- app/page.test.tsx: waitFor for async stats resolution, replace
getAllByRole('article') with 'a [data-slot=card]' scoped queries
(Getting Started card has no icon so we scope to the 3 stat cards inside
<Link>), drop console.error assertion (production fetchStats destructures
{ count } from the resolved payload without throwing on
{ count: null, error }, so console.error is never called on that path)
- components/workout-form.test.tsx: mock sonner (toast.error/success with
all methods stubbed) to replace obsolete window.alert assertions, wait for
the custom Select trainer dropdown to mount before clicking, fill the
exercise-name-0 input (default exercises state is [{name:""}] which fails
validation), make insert/update mocks resolve on a macrotask so React can
render the transient 'Saving...' loading state
- app/login/page.test.tsx: replace getByRole('heading') with getByText
(shadcn CardTitle renders a <div>, not a semantic heading), extend sonner
mock with toast.error, fix invalid-credentials mock to return a real
Error instance (production supabase-js returns AuthError extends Error,
so the err instanceof Error branch surfaces the real message)
- components/ui/dialog.test.tsx: skip jsdom-incompatible click-outside test
(Radix Dialog closes via pointerDown on overlay, not reproducible in jsdom;
covered by the Escape test + Playwright E2E), replace aria-modal assertion
with role=dialog + aria-labelledby (modern Radix no longer emits aria-modal)
Scope: tests + config only. No production code change.
TabataFit Admin Dashboard
A web-based admin dashboard for managing TabataFit content, built with Next.js, Tailwind CSS, and shadcn/ui.
Features
- Dashboard: Overview with stats and quick actions
- Workouts: Manage workout library (view, delete)
- Trainers: Manage trainer profiles
- Collections: Organize workouts into collections
- Media: Upload videos, thumbnails, and avatars
Tech Stack
- Framework: Next.js 15 (App Router)
- Styling: Tailwind CSS
- Components: shadcn/ui
- Backend: Supabase
- Icons: Lucide React
Getting Started
1. Install Dependencies
cd admin-web
npm install
2. Configure Environment Variables
Create a .env.local file:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
3. Run Development Server
npm run dev
Open http://localhost:3000 in your browser.
Project Structure
app/
├── login/ # Login page
├── workouts/ # Workouts management
├── trainers/ # Trainers management
├── collections/ # Collections management
├── media/ # Media upload
├── page.tsx # Dashboard
├── layout.tsx # Root layout with sidebar
components/
├── sidebar.tsx # Navigation sidebar
├── ui/ # shadcn/ui components
lib/
├── supabase.ts # Supabase client + types
├── utils.ts # Utility functions
Usage
Login
Navigate to /login and sign in with your admin credentials. The user must exist in both:
- Supabase Auth
admin_userstable
Managing Content
- Dashboard: View stats and access quick actions
- Workouts: View all workouts, delete with confirmation
- Trainers: View trainer cards with color indicators
- Collections: View collections with gradient previews
- Media: Upload files to Supabase Storage buckets
Authentication Flow
- User signs in at
/login - App checks if user exists in
admin_userstable - If authorized, redirects to dashboard
- Sidebar provides navigation to all sections
- Logout clears session and redirects to login
Supabase Schema
The dashboard expects these tables:
workouts- Workout definitionstrainers- Trainer profilescollections- Workout collectionscollection_workouts- Collection-workout linksadmin_users- Admin access control
And storage buckets:
videos- Workout videosthumbnails- Workout thumbnailsavatars- Trainer avatars
See the main project SUPABASE_SETUP.md for full schema details.
Building for Production
npm run build
The build output will be in .next/. You can deploy to Vercel, Netlify, or any Next.js-compatible host.
Customization
Theme
The dashboard uses a dark theme with:
- Background:
neutral-950(#0a0a0a) - Cards:
neutral-900(#171717) - Accent: Orange (#f97316)
Modify app/globals.css and Tailwind config to change colors.
Adding Pages
- Create a new directory in
app/ - Add
page.tsxwith your component - Add link to
components/sidebar.tsx
Adding shadcn Components
npx shadcn add component-name
License
Same as TabataFit project