57 lines
4.7 KiB
TypeScript
57 lines
4.7 KiB
TypeScript
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>
|
||
);
|
||
}
|