Skip to content

initial admin dashboard with orders technicians reports users#138

Merged
MeryAmr merged 4 commits into
mainfrom
my-reverted-branch
May 27, 2026
Merged

initial admin dashboard with orders technicians reports users#138
MeryAmr merged 4 commits into
mainfrom
my-reverted-branch

Conversation

@darkhyper24
Copy link
Copy Markdown
Collaborator

added initial pages frontend for admin dashboard ,orders page, users page ,technician page , reports page with the setup and folder structure for mono repo

@darkhyper24 darkhyper24 requested review from MeryAmr and unminnn May 26, 2026 23:02
@darkhyper24 darkhyper24 self-assigned this May 26, 2026
@darkhyper24 darkhyper24 added the Frontend Improvements or new features to frontend label May 26, 2026
Copilot AI review requested due to automatic review settings May 26, 2026 23:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Scaffolds an apps/admin Vite + React + TanStack Router dashboard inside the existing pnpm/turbo monorepo, with mock-driven Orders / Technicians / Reports / Users pages, a design-token-based Tailwind setup, Zustand auth + theme stores, and a @FixIt/env web entry point. The PR is intentionally UI-first scaffolding — most data is mocked and the login flow stubs a session.

Changes:

  • New apps/admin workspace: Vite/Vitest config, Tailwind + design tokens, TanStack Router tree, AppShell/Sidebar/Topbar layout, dashboard/orders/technicians/reports/homeowners pages, Zustand auth & theme stores, Supabase client placeholder.
  • Adds a ./web export and createWebEnv to @FixIt/env, plus root package.json scripts (dev:admin, dev:web) and a pnpm chokidar override.
  • Introduces mock domain types/data and shared UI primitives (cards, charts, filters) to drive the scaffolded admin views.

Reviewed changes

Copilot reviewed 105 out of 108 changed files in this pull request and generated 21 comments.

Show a summary per file
File Description
package.json Adds admin/web turbo scripts and chokidar pnpm override; dev:web duplicates dev:admin.
packages/env/package.json Exposes new ./web subpath export.
packages/env/src/web.ts Adds createWebEnv with Vite client env validation.
apps/admin/vite.config.ts Vite + TanStack Router + Vitest setup with @ alias.
apps/admin/tsr.config.json TanStack Router generator configuration.
apps/admin/tsconfig*.json App and Node tsconfig extending shared base.
apps/admin/tailwind.config.ts Tailwind theme wired to local design tokens and CSS variables.
apps/admin/src/vite-env.d.ts Types Vite env vars for the admin app.
apps/admin/src/types/domain.ts Mock domain model types for orders/techs/reports/etc.
apps/admin/src/test/setup.ts Vitest + Testing Library setup.
apps/admin/src/styles/globals.css Light/dark CSS variables and Tailwind base layer.
apps/admin/src/stores/theme-store.ts Persisted theme preference store.
apps/admin/src/stores/auth-store.ts Persisted admin auth store (tokens persisted to localStorage).
apps/admin/src/routeTree.gen.ts Generated TanStack route tree.
(other admin files) Layout, dashboard widgets, mock data, login flow, and route screens supporting the scaffolded pages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json
"check-types": "turbo check-types",
"dev:native": "turbo -F native dev",
"dev:admin": "turbo -F admin dev",
"dev:web": "turbo -F admin dev",
const [range, setRange] = useState<Range>("30d");

const sliced: OrderSeries = (() => {
const days = range === "7d" ? 7 : range === "90d" ? 30 : 30;
Comment on lines +43 to +44
const result = loginSchema.safeParse(value);
if (!result.success) return;
Comment on lines +7 to +18
const PAGE_TITLES: Record<string, string> = {
"/dashboard": "Dashboard",
"/orders": "Orders",
"/categories": "Categories",
"/technicians": "Technicians",
"/users": "Homeowners",
"/reviews": "Reviews",
"/reports": "Reports",
"/payouts": "Payouts",
"/settings": "Settings",
"/support": "Help & Support",
};
Comment on lines +9 to +21
const SPECIALTY_TO_CATEGORY_ID: Record<string, string> = {
"Plumbing": "plumb",
"Air Conditioning": "ac",
"Electrician": "elec",
"Electrical": "elec",
"Home Cleaning": "clean",
"Painter": "paint",
"Painting": "paint",
"Carpentry": "carp",
"Oven & Cooker": "oven",
"Fridge / Freezer": "fridge",
"Dish Installation": "ac",
};
Comment on lines +22 to +50
<button
key={r.id}
type="button"
onClick={() => onView(r)}
className="text-left rounded-lg border border-border bg-card p-3 hover:bg-muted/30 transition-colors"
>
<div className="flex items-start gap-3">
<TechAvatar initials={r.reporterInitials} color={r.reporterColor} size="md" />
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 flex-wrap">
<p className="text-sm font-semibold text-foreground truncate">{r.reporterName}</p>
<RoleChip role={r.reporterRole} />
</div>
<p className="text-xs text-muted-foreground mt-0.5">vs {r.against} · {r.filedAt}</p>
<p className="text-sm text-foreground mt-1.5 line-clamp-2">{r.summary}</p>
<div className="flex items-center gap-2 mt-2 flex-wrap">
<span className="text-[11px] font-mono text-muted-foreground">{r.orderId}</span>
<CategoryTag meta={getCategoryMetaById(r.category)} fallbackLabel={r.category} size="sm" hideLabel />
{r.status === "closed" && r.resolution && (
<StatusBadge
variant={r.resolution === "resolved" ? "success" : "muted"}
label={r.resolution}
/>
)}
</div>
</div>
<Button size="sm" variant="outline" onClick={(e) => { e.stopPropagation(); onView(r); }}>View</Button>
</div>
</button>
Comment on lines +21 to +24
const MOCK_ADMIN = {
email: "admin@fixit.com",
password: "admin123",
};
Comment on lines +85 to +118
{field.state.meta.errors.length > 0 && (
<p className="text-xs text-destructive">{String(field.state.meta.errors[0] ?? "")}</p>
)}
</div>
)}
</form.Field>

<form.Field name="password">
{(field) => (
<div className="flex flex-col gap-1.5">
<Label htmlFor="password">Password</Label>
<div className="relative">
<Input
id="password"
type={showPassword ? "text" : "password"}
placeholder="••••••••"
autoComplete="current-password"
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
onBlur={field.handleBlur}
className={field.state.meta.errors.length > 0 ? "border-destructive pr-10" : "pr-10"}
/>
<button
type="button"
onClick={() => setShowPassword((p) => !p)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
{field.state.meta.errors.length > 0 && (
<p className="text-xs text-destructive">{String(field.state.meta.errors[0] ?? "")}</p>
)}
Comment on lines +9 to +21
const SPECIALTY_TO_CATEGORY_ID: Record<string, string> = {
"Plumbing": "plumb",
"Air Conditioning": "ac",
"Electrician": "elec",
"Electrical": "elec",
"Home Cleaning": "clean",
"Painter": "paint",
"Painting": "paint",
"Carpentry": "carp",
"Oven & Cooker": "oven",
"Fridge / Freezer": "fridge",
"Dish Installation": "ac",
};
<CardHeader className="flex-row items-center justify-between gap-4 pb-2 flex-wrap">
<div>
<CardTitle className="text-base">Orders Over Time</CardTitle>
<p className="text-xs text-muted-foreground mt-0.5">Homeowner vs technician order volumes</p>
This was linked to issues May 26, 2026
@MeryAmr MeryAmr merged commit 0344683 into main May 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Frontend Improvements or new features to frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

admins reviewing technicians admin dashboard

3 participants