102 lines
4.8 KiB
TypeScript
102 lines
4.8 KiB
TypeScript
import { useState } from "react";
|
|
import "./App.css";
|
|
|
|
function App() {
|
|
const [institution, setInstitution] = useState("");
|
|
const [dateInfo, setDateInfo] = useState("");
|
|
const [listType, setListType] = useState("k");
|
|
const [studentsFile, setStudentsFile] = useState<File | null>(null);
|
|
const [familiesFile, setFamiliesFile] = useState<File | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const handleGenerate = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
if (!studentsFile) return alert("Bitte Namensliste (CSV) hochladen!");
|
|
setIsLoading(true);
|
|
|
|
const formData = new FormData();
|
|
formData.append("institution", institution);
|
|
formData.append("date_info", dateInfo);
|
|
formData.append("list_type", listType);
|
|
formData.append("students_file", studentsFile);
|
|
if (familiesFile) formData.append("families_file", familiesFile);
|
|
|
|
try {
|
|
const API_URL = "";
|
|
const response = await fetch(`${API_URL}/api/generate-list`, {
|
|
method: "POST",
|
|
body: formData,
|
|
});
|
|
|
|
if (!response.ok) throw new Error("Fehler bei der Generierung");
|
|
|
|
const blob = await response.blob();
|
|
const url = window.URL.createObjectURL(blob);
|
|
const a = document.createElement("a");
|
|
a.href = url;
|
|
a.download = `Listen_${institution.replace(/\s+/g, "_")}_${listType}.pdf`;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
a.remove();
|
|
} catch (err) {
|
|
alert("Es gab einen Fehler: " + err);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
|
<div className="max-w-xl mx-auto">
|
|
<div className="bg-white py-8 px-6 shadow rounded-lg sm:px-10">
|
|
<div className="mb-6">
|
|
<h1 className="text-2xl font-bold text-gray-900">Listentool</h1>
|
|
<p className="mt-1 text-sm text-gray-500">Generiere Fotoauftragslisten aus CSV Dateien.</p>
|
|
</div>
|
|
|
|
<form className="space-y-6" onSubmit={handleGenerate}>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Einrichtung / Event</label>
|
|
<input type="text" required value={institution} onChange={(e) => setInstitution(e.target.value)} placeholder="Grundschule Klettham, Erding" className="mt-1 block w-full border-gray-300 rounded-md shadow-sm border p-2 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" />
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Datum (Anzeige auf PDF)</label>
|
|
<input type="text" required value={dateInfo} onChange={(e) => setDateInfo(e.target.value)} placeholder="07.+09.07.2025" className="mt-1 block w-full border-gray-300 border p-2 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" />
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Listen-Typ</label>
|
|
<select
|
|
value={listType}
|
|
onChange={(e) => setListType(e.target.value)}
|
|
className="mt-1 block w-full border-gray-300 border p-2 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
|
>
|
|
<option value="k">Kindergarten</option>
|
|
<option value="s">Schule</option>
|
|
<option value="e">Event / Veranstaltung</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Namensliste (CSV)</label>
|
|
<input type="file" required accept=".csv" onChange={(e) => setStudentsFile(e.target.files?.[0] || null)} className="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100" />
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Familienliste (Optional, CSV)</label>
|
|
<input type="file" accept=".csv" onChange={(e) => setFamiliesFile(e.target.files?.[0] || null)} className="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100" />
|
|
</div>
|
|
|
|
<button type="submit" disabled={isLoading} className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50">
|
|
{isLoading ? "Generiere..." : "PDF Generieren & Herunterladen"}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default App;
|