feat: Phase 4 — WebApp-Frontend für Bühnenrecht (AIIA-27)

Complete frontend implementation with Next.js App Router:

- Dashboard with case/analysis/proceeding stats and quick actions
- Normen-Browser with Quellenrang hierarchy and instrument detail
- Entscheidungssuche with full-text search and detail view
- Analysemodus with streaming AI analysis (4 modes: Gutachten, Entscheidung, Vergleich, Risiko)
- Vertragsanalyse with file upload (PDF/DOCX)
- Verfahren overview (BSchGO/ArbGG)
- Auth pages (Login/Register)
- Mandantenfähigkeit: tenant switcher, RBAC-based settings
- Responsive sidebar navigation with Tailwind CSS
- Dashboard layout with session-based auth guard
- Installed missing runtime deps (pdf-parse, mammoth, devDependencies)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO (LegalAI)
2026-04-09 00:23:09 +00:00
parent 3c16fdc30f
commit 78ccf64948
64 changed files with 9541 additions and 100 deletions

View File

@@ -0,0 +1,148 @@
CREATE TYPE "public"."clause_rating" AS ENUM('standard', 'abweichend', 'kritisch', 'unbekannt');--> statement-breakpoint
CREATE TYPE "public"."contract_doc_status" AS ENUM('uploaded', 'extracting', 'extracted', 'analyzing', 'completed', 'failed');--> statement-breakpoint
CREATE TYPE "public"."deadline_type" AS ENUM('frist', 'termin', 'vorfrist');--> statement-breakpoint
CREATE TYPE "public"."proceeding_status" AS ENUM('vorbereitung', 'eingereicht', 'laufend', 'verhandlung', 'entschieden', 'abgeschlossen', 'ruht');--> statement-breakpoint
CREATE TYPE "public"."proceeding_step_status" AS ENUM('ausstehend', 'aktiv', 'abgeschlossen', 'uebersprungen');--> statement-breakpoint
CREATE TYPE "public"."proceeding_type" AS ENUM('bschgo_bezirk', 'bschgo_bund', 'arbgg_erste_instanz', 'arbgg_berufung', 'arbgg_revision');--> statement-breakpoint
CREATE TABLE "contract_clauses" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"document_id" uuid NOT NULL,
"category" varchar(200) NOT NULL,
"extracted_text" text NOT NULL,
"position_start" integer,
"position_end" integer,
"standard_clause_id" uuid,
"rating" "clause_rating" DEFAULT 'unbekannt' NOT NULL,
"analysis" text,
"deviations" jsonb,
"risk_score" integer,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "contract_documents" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"tenant_id" uuid NOT NULL,
"case_id" uuid,
"user_id" uuid NOT NULL,
"filename" varchar(500) NOT NULL,
"mime_type" varchar(100) NOT NULL,
"file_size_bytes" integer NOT NULL,
"storage_path" text NOT NULL,
"extracted_text" text,
"status" "contract_doc_status" DEFAULT 'uploaded' NOT NULL,
"error_message" text,
"fachgruppe_id" uuid,
"metadata" jsonb,
"delete_after" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "proceeding_deadlines" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"proceeding_id" uuid NOT NULL,
"step_id" uuid,
"type" "deadline_type" DEFAULT 'frist' NOT NULL,
"label" varchar(255) NOT NULL,
"description" text,
"due_date" date NOT NULL,
"due_time" varchar(10),
"warning_date" date,
"warning_days_before" integer,
"is_completed" boolean DEFAULT false,
"completed_at" timestamp with time zone,
"is_calculated" boolean DEFAULT false,
"calculation_basis" text,
"legal_basis" varchar(255),
"notes" text,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "proceeding_steps" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"proceeding_id" uuid NOT NULL,
"step_key" varchar(100) NOT NULL,
"label" varchar(255) NOT NULL,
"description" text,
"sort_order" integer DEFAULT 0 NOT NULL,
"status" "proceeding_step_status" DEFAULT 'ausstehend' NOT NULL,
"legal_basis" varchar(255),
"responsible_party" varchar(255),
"completed_at" timestamp with time zone,
"notes" text,
"metadata" jsonb,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "proceedings" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"tenant_id" uuid NOT NULL,
"case_id" uuid,
"type" "proceeding_type" NOT NULL,
"status" "proceeding_status" DEFAULT 'vorbereitung' NOT NULL,
"filing_date" date,
"internal_ref" varchar(100),
"external_ref" varchar(100),
"tribunal_id" uuid,
"court_name" varchar(255),
"chamber" varchar(100),
"presiding_judge" varchar(255),
"applicant" varchar(255),
"respondent" varchar(255),
"subject" text,
"amount_in_dispute_cents" integer,
"fachgruppe_id" uuid,
"current_step_key" varchar(100),
"notes" text,
"metadata" jsonb,
"closed_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "standard_clauses" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"instrument_id" uuid NOT NULL,
"category" varchar(200) NOT NULL,
"label" varchar(500) NOT NULL,
"body" text NOT NULL,
"fachgruppe_ids" jsonb,
"norm_id" uuid,
"sort_order" integer DEFAULT 0,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "contract_clauses" ADD CONSTRAINT "contract_clauses_document_id_contract_documents_id_fk" FOREIGN KEY ("document_id") REFERENCES "public"."contract_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contract_clauses" ADD CONSTRAINT "contract_clauses_standard_clause_id_standard_clauses_id_fk" FOREIGN KEY ("standard_clause_id") REFERENCES "public"."standard_clauses"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contract_documents" ADD CONSTRAINT "contract_documents_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contract_documents" ADD CONSTRAINT "contract_documents_case_id_cases_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."cases"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contract_documents" ADD CONSTRAINT "contract_documents_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contract_documents" ADD CONSTRAINT "contract_documents_fachgruppe_id_nv_buehne_fachgruppen_id_fk" FOREIGN KEY ("fachgruppe_id") REFERENCES "public"."nv_buehne_fachgruppen"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceeding_deadlines" ADD CONSTRAINT "proceeding_deadlines_proceeding_id_proceedings_id_fk" FOREIGN KEY ("proceeding_id") REFERENCES "public"."proceedings"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceeding_deadlines" ADD CONSTRAINT "proceeding_deadlines_step_id_proceeding_steps_id_fk" FOREIGN KEY ("step_id") REFERENCES "public"."proceeding_steps"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceeding_steps" ADD CONSTRAINT "proceeding_steps_proceeding_id_proceedings_id_fk" FOREIGN KEY ("proceeding_id") REFERENCES "public"."proceedings"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceedings" ADD CONSTRAINT "proceedings_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceedings" ADD CONSTRAINT "proceedings_case_id_cases_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."cases"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceedings" ADD CONSTRAINT "proceedings_tribunal_id_arbitration_tribunals_id_fk" FOREIGN KEY ("tribunal_id") REFERENCES "public"."arbitration_tribunals"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "proceedings" ADD CONSTRAINT "proceedings_fachgruppe_id_nv_buehne_fachgruppen_id_fk" FOREIGN KEY ("fachgruppe_id") REFERENCES "public"."nv_buehne_fachgruppen"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "standard_clauses" ADD CONSTRAINT "standard_clauses_instrument_id_norm_instruments_id_fk" FOREIGN KEY ("instrument_id") REFERENCES "public"."norm_instruments"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "standard_clauses" ADD CONSTRAINT "standard_clauses_norm_id_norms_id_fk" FOREIGN KEY ("norm_id") REFERENCES "public"."norms"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "contract_clauses_doc_idx" ON "contract_clauses" USING btree ("document_id");--> statement-breakpoint
CREATE INDEX "contract_clauses_category_idx" ON "contract_clauses" USING btree ("category");--> statement-breakpoint
CREATE INDEX "contract_clauses_rating_idx" ON "contract_clauses" USING btree ("rating");--> statement-breakpoint
CREATE INDEX "contract_docs_tenant_idx" ON "contract_documents" USING btree ("tenant_id");--> statement-breakpoint
CREATE INDEX "contract_docs_case_idx" ON "contract_documents" USING btree ("case_id");--> statement-breakpoint
CREATE INDEX "contract_docs_status_idx" ON "contract_documents" USING btree ("status");--> statement-breakpoint
CREATE INDEX "contract_docs_delete_after_idx" ON "contract_documents" USING btree ("delete_after");--> statement-breakpoint
CREATE INDEX "proceeding_deadlines_proceeding_idx" ON "proceeding_deadlines" USING btree ("proceeding_id");--> statement-breakpoint
CREATE INDEX "proceeding_deadlines_step_idx" ON "proceeding_deadlines" USING btree ("step_id");--> statement-breakpoint
CREATE INDEX "proceeding_deadlines_due_date_idx" ON "proceeding_deadlines" USING btree ("due_date");--> statement-breakpoint
CREATE INDEX "proceeding_deadlines_warning_idx" ON "proceeding_deadlines" USING btree ("warning_date");--> statement-breakpoint
CREATE INDEX "proceeding_steps_proceeding_idx" ON "proceeding_steps" USING btree ("proceeding_id");--> statement-breakpoint
CREATE UNIQUE INDEX "proceeding_steps_key_idx" ON "proceeding_steps" USING btree ("proceeding_id","step_key");--> statement-breakpoint
CREATE INDEX "proceedings_tenant_idx" ON "proceedings" USING btree ("tenant_id");--> statement-breakpoint
CREATE INDEX "proceedings_case_idx" ON "proceedings" USING btree ("case_id");--> statement-breakpoint
CREATE INDEX "proceedings_type_idx" ON "proceedings" USING btree ("type");--> statement-breakpoint
CREATE INDEX "proceedings_status_idx" ON "proceedings" USING btree ("status");--> statement-breakpoint
CREATE INDEX "standard_clauses_instrument_idx" ON "standard_clauses" USING btree ("instrument_id");--> statement-breakpoint
CREATE INDEX "standard_clauses_category_idx" ON "standard_clauses" USING btree ("category");

View File

@@ -0,0 +1,87 @@
-- Phase 3.3: Contract Analysis Module (Vertragsanalyse)
-- Adds contract document upload, clause extraction, and standard clause comparison
-- Enums
CREATE TYPE contract_doc_status AS ENUM ('uploaded', 'extracting', 'extracted', 'analyzing', 'completed', 'failed');
CREATE TYPE clause_rating AS ENUM ('standard', 'abweichend', 'kritisch', 'unbekannt');
-- Contract documents table
CREATE TABLE contract_documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
case_id UUID REFERENCES cases(id) ON DELETE SET NULL,
user_id UUID NOT NULL REFERENCES users(id),
filename VARCHAR(500) NOT NULL,
mime_type VARCHAR(100) NOT NULL,
file_size_bytes INTEGER NOT NULL,
storage_path TEXT NOT NULL,
extracted_text TEXT,
status contract_doc_status NOT NULL DEFAULT 'uploaded',
error_message TEXT,
fachgruppe_id UUID REFERENCES nv_buehne_fachgruppen(id),
metadata JSONB,
delete_after TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX contract_docs_tenant_idx ON contract_documents(tenant_id);
CREATE INDEX contract_docs_case_idx ON contract_documents(case_id);
CREATE INDEX contract_docs_status_idx ON contract_documents(status);
CREATE INDEX contract_docs_delete_after_idx ON contract_documents(delete_after);
-- Standard clauses (reference data from NV Bühne etc.)
CREATE TABLE standard_clauses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
instrument_id UUID NOT NULL REFERENCES norm_instruments(id) ON DELETE CASCADE,
category VARCHAR(200) NOT NULL,
label VARCHAR(500) NOT NULL,
body TEXT NOT NULL,
fachgruppe_ids JSONB,
norm_id UUID REFERENCES norms(id),
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX standard_clauses_instrument_idx ON standard_clauses(instrument_id);
CREATE INDEX standard_clauses_category_idx ON standard_clauses(category);
-- Contract clauses (extracted from uploaded documents)
CREATE TABLE contract_clauses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
document_id UUID NOT NULL REFERENCES contract_documents(id) ON DELETE CASCADE,
category VARCHAR(200) NOT NULL,
extracted_text TEXT NOT NULL,
position_start INTEGER,
position_end INTEGER,
standard_clause_id UUID REFERENCES standard_clauses(id),
rating clause_rating NOT NULL DEFAULT 'unbekannt',
analysis TEXT,
deviations JSONB,
risk_score INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX contract_clauses_doc_idx ON contract_clauses(document_id);
CREATE INDEX contract_clauses_category_idx ON contract_clauses(category);
CREATE INDEX contract_clauses_rating_idx ON contract_clauses(rating);
-- RLS policies for contract_documents
ALTER TABLE contract_documents ENABLE ROW LEVEL SECURITY;
CREATE POLICY contract_documents_tenant_isolation ON contract_documents
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY contract_documents_tenant_insert ON contract_documents
FOR INSERT WITH CHECK (tenant_id = current_setting('app.tenant_id')::uuid);
-- RLS policies for contract_clauses (via document join)
ALTER TABLE contract_clauses ENABLE ROW LEVEL SECURITY;
CREATE POLICY contract_clauses_tenant_isolation ON contract_clauses
USING (document_id IN (
SELECT id FROM contract_documents
WHERE tenant_id = current_setting('app.tenant_id')::uuid
));
-- Standard clauses are shared reference data (no RLS needed)

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,13 @@
"when": 1775682934077,
"tag": "0000_peaceful_amazoness",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1775690117252,
"tag": "0001_curved_fabian_cortez",
"breakpoints": true
}
]
}