import React, { useEffect, useState } from "react"; import { Container, Paper, Typography, Box, Button, Grid, Card, CardContent, Chip, Divider, Dialog, DialogTitle, DialogContent, DialogActions, TextField, MenuItem, IconButton, Tooltip, Alert, } from "@mui/material"; import { Download, Delete, Refresh, ArrowBack, Edit, Save, VpnKey, ContentCopy, SwapVert, } from "@mui/icons-material"; import { useParams, useNavigate } from "react-router-dom"; import dayjs from "dayjs"; // Store import { useApplicationStore } from "../store/applicationStore"; // Types import { VSM_FINANCING_LABELS, QSM_FINANCING_LABELS } from "../types/api"; // Components import LoadingSpinner from "../components/LoadingSpinner/LoadingSpinner"; // Utils import { translateStatus, getStatusColor } from "../utils/statusTranslations"; const AdminApplicationView: React.FC = () => { const navigate = useNavigate(); const { paId } = useParams<{ paId: string }>(); // Store const { currentApplication, formData, isLoading, error, successMessage, loadApplicationAdmin, updateApplicationStatusAdmin, deleteApplicationAdmin, downloadApplicationPdfAdmin, resetApplicationCredentials, isAdmin, } = useApplicationStore(); // Local state const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [editingStatus, setEditingStatus] = useState(false); const [newStatus, setNewStatus] = useState(""); const [showResetDialog, setShowResetDialog] = useState(false); const [newCredentials, setNewCredentials] = useState<{ pa_id: string; pa_key: string; } | null>(null); const [copiedField, setCopiedField] = useState(null); // Redirect if not admin useEffect(() => { if (!isAdmin) { navigate("/"); return; } }, [isAdmin, navigate]); // Load application on mount useEffect(() => { if (paId && isAdmin) { loadApplicationAdmin(paId); } }, [paId, isAdmin, loadApplicationAdmin]); // Update status when application loads useEffect(() => { if (currentApplication) { setNewStatus(currentApplication.status); } }, [currentApplication]); // Handle status change const handleStatusChange = async () => { if (paId && newStatus !== currentApplication?.status) { const success = await updateApplicationStatusAdmin(paId, newStatus); if (success) { setEditingStatus(false); } } else { setEditingStatus(false); } }; // Handle delete const handleDelete = async () => { if (paId) { const success = await deleteApplicationAdmin(paId); if (success) { navigate("/admin"); } } }; // Handle refresh const handleRefresh = () => { if (paId) { loadApplicationAdmin(paId); } }; // Handle reset credentials const handleResetCredentials = async () => { if (paId) { const result = await resetApplicationCredentials(paId); if (result) { setNewCredentials(result); } } }; // Copy to clipboard function const copyToClipboard = (text: string, field: string) => { navigator.clipboard.writeText(text); setCopiedField(field); setTimeout(() => setCopiedField(null), 2000); }; // Handle download PDF const handleDownloadPdf = async () => { if (paId) { await downloadApplicationPdfAdmin(paId); } }; if (!isAdmin) { return null; // Will redirect } if (!paId) { return ( Keine Antrags-ID angegeben. ); } if (isLoading) { return ; } if (error) { return ( } > {error} ); } if (!currentApplication) { return ( Antrag nicht gefunden. ); } return ( {/* Header */} Antrag {currentApplication.pa_id} {editingStatus ? ( setNewStatus(e.target.value)} sx={{ minWidth: 100 }} > Neu In Prüfung Genehmigt Abgelehnt ) : ( setEditingStatus(true)} sx={{ cursor: "pointer" }} /> )} {/* Action Buttons */} navigate(`/admin/applications/${paId}/edit`)} > setShowResetDialog(true)}> setShowDeleteDialog(true)} > {/* Success/Error Messages */} {successMessage && ( {successMessage} )} {error && ( {error} )} {/* Main Content */} {/* Application Details */} Antragsinformationen Antragssteller {formData.firstName} {formData.lastName} E-Mail {formData.email ? ( {formData.email} ) : ( "-" )} Telefon {formData.phone ? ( {formData.phone} ) : ( "-" )} Rolle {formData.role || "-"} Institution {formData.institutionName || "-"} Fakultät {formData.course || "-"} Projektname {formData.projectName} Projektbeschreibung {formData.description} Startdatum {formData.startDate ? dayjs(formData.startDate).format("DD.MM.YYYY") : "-"} Enddatum {formData.endDate ? dayjs(formData.endDate).format("DD.MM.YYYY") : "-"} Teilnehmerzahl {formData.participants || "-"} Beantragte Summe {formData.requestedAmountEur?.toLocaleString("de-DE", { style: "currency", currency: "EUR", }) || "0,00 €"} {/* Financing Information */} {(formData.vsmFinancing || formData.qsmFinancing) && ( {currentApplication.variant === "QSM" ? "Erfüllte Aufgabe der QSM" : "Erfüllte Aufgabe der VS nach §65 des Landeshochschulgesetzes"} {currentApplication.variant === "QSM" && (formData.financingCode || formData.qsmFinancing) ? QSM_FINANCING_LABELS[ (formData.financingCode || formData.qsmFinancing) as keyof typeof QSM_FINANCING_LABELS ] || formData.financingCode || formData.qsmFinancing : currentApplication.variant === "VSM" && (formData.financingCode || formData.vsmFinancing) ? VSM_FINANCING_LABELS[ (formData.financingCode || formData.vsmFinancing) as keyof typeof VSM_FINANCING_LABELS ] || formData.financingCode || formData.vsmFinancing : "-"} {/* Display flags */} {formData.vsmFlags && currentApplication.variant === "VSM" && ( Zusätzliche Angaben: • Die Maßnahme erfüllt Aufgaben der verfassten Studierendenschaft:{" "} {formData.vsmFlags.aufgaben ? "Ja" : "Nein"} • Es werden keine Einzelpersonen von der Maßnahme gefördert:{" "} {formData.vsmFlags.individuell ? "Ja" : "Nein"} )} {formData.qsmFlags && currentApplication.variant === "QSM" && ( Zusätzliche Angaben: • Es handelt sich um Stellenfinanzierungen:{" "} {formData.qsmFlags.stellenfinanzierungen ? "Ja" : "Nein"} • Die Studierenden werden an der Planung und Durchführung der Maßnahme beteiligt:{" "} {formData.qsmFlags.studierende ? "Ja" : "Nein"} • Es werden keine Einzelpersonen von der Maßnahme gefördert:{" "} {formData.qsmFlags.individuell ? "Ja" : "Nein"} {formData.qsmFlags.exkursionGenehmigt !== undefined && ( • Die beantragte Exkursion wurde von den zuständigen Stellen genehmigt:{" "} {formData.qsmFlags.exkursionGenehmigt ? "Ja" : "Nein"} )} {formData.qsmFlags.exkursionBezuschusst !== undefined && ( • Die Exkursion wird bereits aus anderen Mitteln bezuschusst:{" "} {formData.qsmFlags.exkursionBezuschusst ? "Ja" : "Nein"} )} )} {/* Attachments */} Anhänge: • Vergleichsangebote liegen bei:{" "} {formData.comparativeOffers ? "Ja" : "Nein"} {currentApplication.variant === "QSM" && ( • Die Fakultät ist über den Antrag informiert:{" "} {formData.fakultaet ? "Ja" : "Nein"} )} )} {/* Costs Breakdown */} {formData.costs && formData.costs.length > 0 && ( Kostenpositionen {formData.costs .filter((cost) => cost.amountEur && cost.amountEur > 0) .map((cost, index) => ( {cost.name} {cost.amountEur?.toLocaleString("de-DE", { style: "currency", currency: "EUR", }) || "0,00 €"} ))} Gesamt: {formData.requestedAmountEur?.toLocaleString("de-DE", { style: "currency", currency: "EUR", }) || "0,00 €"} )} {/* Sidebar */} {/* Status Card */} Status & Zeitstempel {editingStatus ? ( setNewStatus(e.target.value)} size="small" > Neu In Prüfung Genehmigt Abgelehnt ) : ( setEditingStatus(true)} sx={{ cursor: "pointer" }} /> )} Erstellt:{" "} {dayjs(currentApplication.created_at).format( "DD.MM.YYYY HH:mm", )} Zuletzt geändert:{" "} {dayjs(currentApplication.updated_at).format( "DD.MM.YYYY HH:mm", )} {/* Participating Faculties */} {formData.participatingFaculties && ( Teilnehmende Fakultäten {Object.entries(formData.participatingFaculties).map( ([faculty, participating]) => participating ? ( ) : null, )} )} {/* Admin Actions */} Admin-Aktionen {/* Delete Confirmation Dialog */} setShowDeleteDialog(false)} > Antrag löschen Sind Sie sicher, dass Sie den Antrag {paId} unwiderruflich löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden. {/* Reset Credentials Dialog */} { setShowResetDialog(false); setNewCredentials(null); setCopiedField(null); }} > Zugangsdaten zurücksetzen {!newCredentials ? ( Möchten Sie neue Zugangsdaten für den Antrag {paId} generieren? Die alten Zugangsdaten werden ungültig. ) : ( Neue Zugangsdaten wurden generiert! theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50], mb: 2, }} > Antrags-ID: {newCredentials.pa_id} copyToClipboard(newCredentials.pa_id, "id")} > {copiedField === "id" && ( Kopiert! )} Neuer Zugangsschlüssel: {newCredentials.pa_key} copyToClipboard(newCredentials.pa_key, "key") } > {copiedField === "key" && ( Kopiert! )} Bitte speichern Sie diese Zugangsdaten sicher ab und teilen Sie sie dem Antragsteller mit. )} {!newCredentials && ( )} ); }; export default AdminApplicationView;