Phase 1: project foundation for Alpenwerk HR

Scaffolds the Next.js 16 / TypeScript strict / Tailwind v3 app per
NEXTJS_REBUILD_SUPERPROMPT.md, and implements the Foundation slice from
the Phase 1 plan:

- Corrected Supabase schema (supabase/schema.sql): org units, employees,
  history, positions, hire drafts, saved reports, audit log, reorg
  scenarios, role-based profiles, salary-masking view, RLS policies,
  auto-derivation triggers, position-number generator.
- Seed script (supabase/seed.ts): ~800 realistic Austrian employees across
  9 divisions / 16 departments / 35 teams, history, 8 open positions, and
  hr_admin/manager test accounts.
- Supabase clients (lib/supabase/*), design tokens (tailwind.config.ts),
  format/color helpers (lib/format.ts, lib/colors.ts).
- Shared UI kit (components/ui): Avatar, StatusChip, Toast, Modal,
  SlideOver, SegmentedControl, Lookup.
- Auth (login page, Server Actions) and proxy.ts (Next 16's replacement
  for middleware) guarding the authenticated route group.
- Shell (Sidebar, Topbar, NewHireButton stub) and the Dashboard page,
  reading live data via employees_directory.

Employees list/detail, hire wizard, action panels, org chart, positions,
reports, and audit log are deferred to later phases per the plan.
This commit is contained in:
2026-07-13 21:44:28 +02:00
parent d3a5a9fa27
commit ef9852b09c
41 changed files with 9579 additions and 0 deletions

59
app/(auth)/login/page.tsx Normal file
View File

@@ -0,0 +1,59 @@
import { login } from "@/actions/auth";
type LoginPageProps = {
searchParams: Promise<{ error?: string }>;
};
export default async function LoginPage({ searchParams }: LoginPageProps) {
const { error } = await searchParams;
return (
<div className="flex min-h-screen items-center justify-center bg-surface px-4">
<div className="w-full max-w-sm rounded border border-border bg-white p-8 shadow-sm">
<h1 className="text-xl font-extrabold text-ink">Alpenwerk HR</h1>
<p className="mt-1 text-sm text-ink-muted">Melden Sie sich mit Ihrem Firmenkonto an.</p>
{error && (
<div role="alert" className="mt-4 rounded bg-danger-bg px-3 py-2 text-sm text-danger-text">
{error}
</div>
)}
<form action={login} className="mt-6 flex flex-col gap-4">
<div>
<label htmlFor="email" className="mb-1 block text-sm font-semibold text-ink">
E-Mail
</label>
<input
id="email"
name="email"
type="email"
required
autoComplete="username"
className="w-full rounded border border-border px-3 py-2 text-sm text-ink outline-none focus:border-brand-500"
/>
</div>
<div>
<label htmlFor="password" className="mb-1 block text-sm font-semibold text-ink">
Passwort
</label>
<input
id="password"
name="password"
type="password"
required
autoComplete="current-password"
className="w-full rounded border border-border px-3 py-2 text-sm text-ink outline-none focus:border-brand-500"
/>
</div>
<button
type="submit"
className="mt-2 rounded bg-brand-500 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-600"
>
Anmelden
</button>
</form>
</div>
</div>
);
}