Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# SmartShooter Roadmap (Execution Snapshot)

Last updated: 2026-02-14

## Current Goal
Ship a portfolio-grade analytics and training workflow with compact UX, stable role-gated dev tools, and clean PR-sized delivery.

## Progress Summary

### Completed
1. Repo excellence baseline (lint/format/test/build conventions + CI scaffolding)
2. Dashboard modularization (split monolithic dashboard into focused sections/components)
3. Session form stepper (guided flow without payload contract regressions)
4. Mobile log cards and responsive analytics refinements
5. Bundle optimization pass (code-splitting heavy frontend chunks)
6. Compact analytics layout pass for single-viewport desktop usage
7. Role-aware dev mode (`admin` vs `user`)
8. Milestone interaction update:
- recent badges visible under milestone area
- click milestone to open achieved milestones list

### In Progress
1. Product hardening around role assignment workflow and admin onboarding clarity
2. Final polish on analytics consistency across light/dark and empty-data states

### Next (Priority Order)
1. Admin lifecycle polish
- Add UI hint for non-admin users when dev mode is unavailable
- Add explicit refresh-token guidance after role claim updates
2. Analytics comparator pass
- Add period-over-period KPI deltas
- Keep current compact layout constraints
3. Achievements UX depth
- Group achievements by category and recency
- Add locked milestone previews
4. Regression safety
- Add targeted tests for attempts-vs-made, milestone modal, and filters
5. Docs closure
- Keep roadmap and ux-spec synchronized after each merged PR

## PR Workflow Rules
1. Keep changes PR-sized and reviewable.
2. For each PR:
- run `npm run lint`
- run `npm run test`
- run `npm run build`
3. Ship with user-visible before/after notes and rollback-safe scope.
46 changes: 46 additions & 0 deletions docs/roles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Roles

SmartShooter supports two roles:

- `admin`: can access Dev tools (seed sessions, onboarding shortcuts, slow mode toggle)
- `user`: regular product access, no Dev tools

## Source of truth

1. **Primary**: Firebase Auth custom claims (`role=admin` or `admin=true`)
2. **Fallback**: `VITE_ADMIN_EMAILS` allowlist in frontend env

## Assign role (recommended: custom claims)

Use Firebase Admin SDK from a secure environment:

```js
// node script (run securely, not in browser)
import admin from "firebase-admin";

admin.initializeApp({
credential: admin.credential.applicationDefault(),
});

const uid = "<FIREBASE_UID>";
await admin.auth().setCustomUserClaims(uid, { role: "admin", admin: true });
console.log("Admin role assigned");
```

After assigning claims, the user must re-authenticate (or refresh token) to receive new claims.

## Assign role (quick fallback via env)

Set in `.env.local`:

```bash
VITE_ADMIN_EMAILS=admin@example.com,second-admin@example.com
```

This is useful for local/dev, but custom claims are preferred for production.

## Dev mode visibility

- Dev tools are shown only when:
- user role resolves to `admin`, and
- dev mode is enabled (auto in local `vite dev`, or toggle with `Ctrl/Cmd + Shift + D`)
34 changes: 34 additions & 0 deletions docs/session-kickoff-prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Session Kickoff Prompt (Copy/Paste)

Use this at the start of a new coding session to re-sync quickly:

```text
Act as my implementation copilot for SmartShooter.

First, do a fast repo state check and summarize:
1) current branch
2) uncommitted changes
3) last 5 commits
4) current roadmap status from docs/roadmap.md
5) current UX targets from docs/ux-spec.md

Then propose:
- top 3 next tasks in priority order
- exact files likely to change
- risks/regressions to watch
- verification commands (lint/test/build + any focused checks)

Constraints:
- keep scope PR-sized
- do not change product behavior unless required
- show a short "change summary before editing files"
- after implementation, provide: changed files, verification results, and a commit message suggestion
```

## Optional Variant (If You Want to Continue Previous PR)

```text
Continue the previous PR track.
Use git history and modified files to infer what was in progress, then suggest the smallest safe next increment.
If context is ambiguous, give two options and recommend one.
```
29 changes: 29 additions & 0 deletions docs/ux-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,32 @@
- No backend/data model rewrites.
- No AI feature introduction.
- No major analytics logic changes without failing tests.

## Current UX Baseline (Implemented)
- Dashboard analytics is now compact-first for desktop (`1920x1080`) with tighter vertical density.
- Header keeps primary actions and milestone context visible at all times.
- Analytics controls are grouped (`Period`, `Drills`, `Metrics`) and optimized for quick scanning.
- Calendar streak is year-to-date and rendered as a primary context block.
- Main analytics body prioritizes:
- Court heatmap
- Zones + insights
- Accuracy trend / Attempts vs Made
- Range filter is constrained to a single default range (`midrange`) to avoid misleading mixed-range percentages.
- Milestone area supports recent-badge visibility and a click-through list of achieved milestones.
- Dev mode visibility is role-gated (`admin` only).

## Next UX Backlog (Post-Compact Pass)
1. Milestones UX polish
- Add clearer badge progression states (locked vs unlocked tiers).
- Add optional quick filter for achievements by category (`accuracy`, `volume`, `streak`).
2. Analytics comparators
- Add compare window (`current period` vs `previous period`) for KPI deltas.
- Keep charts compact without re-introducing vertical overflow.
3. Logs efficiency
- Improve row density and sticky actions for faster editing in large logs.
- Preserve mobile cards behavior and parity with desktop actions.
4. Accessibility hardening
- Run keyboard-only walkthrough for all analytics controls and modal states.
- Add/verify ARIA labels and focus traps for milestone/achievement dialogs.
5. Empty-state quality
- Standardize no-data copy and add one-click “reset filters” action in each analytics tab.
58 changes: 44 additions & 14 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
// src/App.jsx
import { useEffect } from "react";
import { Routes, Route, Navigate, Outlet } from "react-router-dom";
import Login from "./pages/Login";
import Dashboard from "./pages/Dashboard";
import Help from "./pages/Help"; // 👈 add this
import ProtectedRoute from "./components/ProtectedRoute";
import { lazy, Suspense, useEffect } from "react";
import { Navigate, Outlet, Route, Routes } from "react-router-dom";
import { useAuthStore } from "./store/useAuthStore";
import Navbar from "./components/Navbar";

const Login = lazy(() => import("./pages/Login"));
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Help = lazy(() => import("./pages/Help"));
const ProtectedRoute = lazy(() => import("./components/ProtectedRoute"));
const Navbar = lazy(() => import("./components/Navbar"));

function RouteFallback() {
return <div className="p-6 text-sm opacity-70">Loading...</div>;
}

function AppShell() {
return (
<>
<Navbar />
<Suspense fallback={<RouteFallback />}>
<Navbar />
</Suspense>
<main>
<Outlet />
</main>
Expand All @@ -29,17 +36,40 @@ export default function App() {

return (
<Routes>
<Route path="/login" element={<Login />} />
<Route
path="/login"
element={
<Suspense fallback={<RouteFallback />}>
<Login />
</Suspense>
}
/>

<Route
element={
<ProtectedRoute>
<AppShell />
</ProtectedRoute>
<Suspense fallback={<RouteFallback />}>
<ProtectedRoute>
<AppShell />
</ProtectedRoute>
</Suspense>
}
>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/help" element={<Help />} /> {/* 👈 new route */}
<Route
path="/dashboard"
element={
<Suspense fallback={<RouteFallback />}>
<Dashboard />
</Suspense>
}
/>
<Route
path="/help"
element={
<Suspense fallback={<RouteFallback />}>
<Help />
</Suspense>
}
/>
<Route path="/" element={<Navigate to="/dashboard" replace />} />
</Route>

Expand Down
Loading