Files
mitwirkung/apps/web/src/pages/NewBillPage.tsx

57 lines
4.7 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 { ArrowLeft, ArrowRight, CheckCircle2, FileText, Lightbulb, Target } from "lucide-react";
import { useEffect, useState, type FormEvent } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useAuth } from "../AuthContext";
import { api } from "../api";
import type { Topic } from "../types";
export function NewBillPage() {
const { user, loading, openAuth } = useAuth();
const [topics, setTopics] = useState<Topic[]>([]);
const [error, setError] = useState("");
const [busy, setBusy] = useState(false);
const navigate = useNavigate();
useEffect(() => { api.get<{ topics: Topic[] }>("/api/topics").then((d) => setTopics(d.topics)); }, []);
useEffect(() => { if (!loading && !user) openAuth(); }, [loading, user, openAuth]);
async function submit(event: FormEvent<HTMLFormElement>) {
event.preventDefault(); setBusy(true); setError("");
const form = new FormData(event.currentTarget);
const data = Object.fromEntries(form);
try {
const result = await api.post<{ id: number }>("/api/bills", { ...data, deadline: new Date(String(data.deadline)).toISOString() });
navigate(`/entwurf/${result.id}`);
} catch (err) { setError(err instanceof Error ? err.message : "Entwurf konnte nicht gespeichert werden."); }
finally { setBusy(false); }
}
const minDate = new Date(Date.now() + 2 * 86400000).toISOString().slice(0, 10);
return (
<main className="create-page">
<div className="create-shell">
<Link to="/" className="back-link"><ArrowLeft size={17} /> Zurück zur Übersicht</Link>
<div className="create-heading"><p className="eyebrow">Dein Vorschlag</p><h1>Eine gute Idee braucht<br /><em>eine klare Form.</em></h1><p>Beschreibe deinen Entwurf so konkret, verständlich und überprüfbar wie möglich.</p></div>
<div className="create-layout">
<form className="bill-form" onSubmit={submit}>
<section><div className="form-section-title"><span>01</span><div><h2>Grundidee</h2><p>Worum geht es in deinem Vorschlag?</p></div></div>
<label>Titel des Entwurfs <small>10–140 Zeichen</small><input name="title" minLength={10} maxLength={140} required placeholder="z. B. Kostenfreie Bibliotheksausweise für alle Jugendlichen" /></label>
<label>Kurzbeschreibung <small>30–300 Zeichen</small><textarea name="summary" minLength={30} maxLength={300} rows={3} required placeholder="Fasse die zentrale Idee in zwei bis drei Sätzen zusammen." /></label>
<div className="form-row"><label>Themenbereich<select name="topicId" required defaultValue=""><option value="" disabled>Bitte wählen</option>{topics.map((t) => <option key={t.id} value={t.id}>{t.name}</option>)}</select></label><label>Abstimmung bis<input name="deadline" type="date" min={minDate} required /></label></div>
</section>
<section><div className="form-section-title"><span>02</span><div><h2>Begründung</h2><p>Was soll sich verändern und warum?</p></div></div>
<label>Ausgangslage und Problem <small>mind. 40 Zeichen</small><textarea name="problem" minLength={40} maxLength={2000} rows={5} required placeholder="Beschreibe nachvollziehbar, welches Problem heute besteht und wen es betrifft." /></label>
<label>Vorgeschlagene Lösung <small>mind. 40 Zeichen</small><textarea name="solution" minLength={40} maxLength={3000} rows={6} required placeholder="Welche konkrete gesetzliche oder politische Änderung schlägst du vor?" /></label>
<label>Erwartete Wirkung <small>mind. 30 Zeichen</small><textarea name="impact" minLength={30} maxLength={2000} rows={4} required placeholder="Welche positiven Effekte, Kosten oder möglichen Zielkonflikte sind zu erwarten?" /></label>
</section>
{error && <p className="form-error">{error}</p>}
<div className="form-submit"><p>Mit dem Einreichen stimmst du unseren Moderationsregeln zu.</p><button className="button button-primary button-large" disabled={busy || !user}>{busy ? "Wird eingereicht …" : "Entwurf veröffentlichen"}<ArrowRight size={18} /></button></div>
</form>
<aside className="writing-guide"><p className="eyebrow">Schreibhilfe</p><h3>Was einen guten Entwurf ausmacht</h3><div><Lightbulb /><p><strong>Verständlich</strong>Vermeide Fachsprache oder erkläre notwendige Begriffe.</p></div><div><Target /><p><strong>Konkret</strong>Formuliere ein klares Ziel und einen umsetzbaren Weg dorthin.</p></div><div><FileText /><p><strong>Nachvollziehbar</strong>Trenne Ausgangslage, Lösung und erwartete Wirkung.</p></div><div><CheckCircle2 /><p><strong>Fair</strong>Benenne auch mögliche Kosten, Nachteile oder Zielkonflikte.</p></div></aside>
</div>
</div>
</main>
);
}