Files
shokuninmarche/client/src/pages/DashboardPage.tsx
airewit-developer c8909befb1 feat: Foundation — auth system, 9 migrations, React frontend
Backend:
- Express server with JWT httpOnly cookie auth
- POST /api/auth/register, /api/auth/login, /api/auth/logout, GET /api/auth/me
- bcrypt 12 rounds, generic 401 errors (no email/password field disclosure)
- Auth middleware protects all /api/* routes except register/login
- pg Pool database connection

Frontend (React + Vite + TailwindCSS + shadcn/ui):
- AuthContext with session restore on page load via /api/auth/me
- ProtectedRoute redirects unauthenticated users to /login
- LoginPage, RegisterPage — Hebrew RTL layout (dir=rtl), inline validation
- DashboardPage placeholder
- shadcn/ui components: Button, Input, Label, Card

Database:
- 9 migrations (001-009): extensions, users, events, vendors, guests,
  bookings, invitations, vendor_ratings, organizer_preferences
- pg_trgm for fuzzy Hebrew search, GIN indexes on style_tags
- Phase 2+3 fields included: source, payment_status, contract_value,
  vendor ratings 6-dimension, organizer preferences
- Idempotent migration runner with schema_migrations tracking table

Infrastructure:
- Dockerfile (multi-stage: build React → production node:20-alpine)
- docker-compose.yml with PostgreSQL healthcheck, expose not ports
- Migrations run automatically on container start

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 18:22:42 +00:00

39 lines
1.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useAuth } from '@/contexts/AuthContext';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
export function DashboardPage() {
const { user, logout } = useAuth();
async function handleLogout() {
await logout();
}
return (
<div className="min-h-screen bg-muted/40 p-6" dir="rtl">
<div className="max-w-4xl mx-auto space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-3xl font-bold">אירועית</h1>
<Button variant="outline" onClick={handleLogout}>
התנתקות
</Button>
</div>
<Card>
<CardHeader>
<CardTitle>ברוך הבא, {user?.display_name}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">
{user?.role === 'organizer' ? 'מארגן אירועים' : 'ספק שירותים'} {user?.email}
</p>
<p className="mt-4 text-sm text-muted-foreground">
הלוח הראשי של {user?.role === 'organizer' ? 'האירועים' : 'הפרופיל'} שלך יוצג כאן בקרוב.
</p>
</CardContent>
</Card>
</div>
</div>
);
}