147 lines
4.4 KiB
JavaScript
147 lines
4.4 KiB
JavaScript
import { get, runCleanupIfNeeded } from '@/src/lib/db.js';
|
|
import { formatTimestamp, readSearchParam } from '@/src/lib/format.js';
|
|
|
|
import { StatusMessage } from '@/app/manage/_components/status-message.js';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
function normalizeRequestId(value) {
|
|
return String(value || '').trim().toUpperCase();
|
|
}
|
|
|
|
function isValidRequestId(value) {
|
|
return /^[A-Z2-7]{6,24}$/.test(value);
|
|
}
|
|
|
|
function requestState(requestEntry, now) {
|
|
if (!requestEntry) {
|
|
return 'missing';
|
|
}
|
|
if (Number(requestEntry.completed_at || 0) > 0) {
|
|
return 'completed';
|
|
}
|
|
if (Number(requestEntry.expires_at || 0) <= now) {
|
|
return 'expired';
|
|
}
|
|
return 'open';
|
|
}
|
|
|
|
export default async function UploadRequestPage({ params, searchParams }) {
|
|
await runCleanupIfNeeded();
|
|
|
|
const resolvedParams = await params;
|
|
const requestId = normalizeRequestId(resolvedParams.id);
|
|
|
|
if (!isValidRequestId(requestId)) {
|
|
return (
|
|
<main className="page-shell narrow">
|
|
<section className="panel centered">
|
|
<h1>Ungültige Anfrage</h1>
|
|
<p className="muted">Die Upload-Anfrage konnte nicht verarbeitet werden.</p>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
const requestEntry = await get(
|
|
`SELECT id, note, created_at, expires_at, completed_at, uploaded_original_name
|
|
FROM upload_requests
|
|
WHERE id = ?`,
|
|
[requestId]
|
|
);
|
|
|
|
const now = Date.now();
|
|
const state = requestState(requestEntry, now);
|
|
|
|
const resolvedSearchParams = await searchParams;
|
|
const error = readSearchParam(resolvedSearchParams, 'error');
|
|
const success = readSearchParam(resolvedSearchParams, 'success');
|
|
|
|
if (state === 'missing') {
|
|
return (
|
|
<main className="page-shell narrow">
|
|
<StatusMessage error={error} success={success} />
|
|
<section className="panel centered">
|
|
<h1>Anfrage nicht gefunden</h1>
|
|
<p className="muted">Diese Upload-Anfrage existiert nicht oder wurde entfernt.</p>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<main className="page-shell narrow">
|
|
<header className="page-header">
|
|
<div className="header-main">
|
|
<h1>Datei-Anfrage</h1>
|
|
<p className="muted">Anfrage-ID: {requestEntry.id}</p>
|
|
</div>
|
|
</header>
|
|
|
|
<StatusMessage error={error} success={success} />
|
|
|
|
<section className="panel">
|
|
<div className="info-stack">
|
|
<div className="info-card">
|
|
<strong>Status</strong>
|
|
<span className="muted">
|
|
{state === 'open' ? 'Offen' : state === 'completed' ? 'Bereits abgeschlossen' : 'Abgelaufen'}
|
|
</span>
|
|
</div>
|
|
<div className="info-card">
|
|
<strong>Erstellt</strong>
|
|
<span className="muted">{formatTimestamp(requestEntry.created_at)}</span>
|
|
</div>
|
|
<div className="info-card">
|
|
<strong>Gültig bis</strong>
|
|
<span className="muted">{formatTimestamp(requestEntry.expires_at)}</span>
|
|
</div>
|
|
{requestEntry.note ? (
|
|
<div className="info-card">
|
|
<strong>Notiz</strong>
|
|
<span className="muted">{requestEntry.note}</span>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
</section>
|
|
|
|
{state === 'open' ? (
|
|
<section className="panel panel-spotlight">
|
|
<h2>Datei hochladen</h2>
|
|
<form
|
|
className="form-grid"
|
|
method="post"
|
|
action={`/_request/${encodeURIComponent(requestEntry.id)}/upload`}
|
|
encType="multipart/form-data"
|
|
>
|
|
<label className="field">
|
|
Datei
|
|
<input className="input" type="file" name="file" required />
|
|
</label>
|
|
|
|
<label className="field">
|
|
Dein Name (optional)
|
|
<input className="input" name="fulfilledBy" placeholder="z. B. Max Mustermann" />
|
|
</label>
|
|
|
|
<button className="btn" type="submit">
|
|
Datei senden
|
|
</button>
|
|
</form>
|
|
</section>
|
|
) : null}
|
|
|
|
{state === 'completed' ? (
|
|
<section className="panel centered">
|
|
<h2>Vielen Dank</h2>
|
|
<p className="muted">
|
|
{requestEntry.uploaded_original_name
|
|
? `Diese Anfrage wurde bereits mit „${requestEntry.uploaded_original_name}“ abgeschlossen.`
|
|
: 'Diese Anfrage wurde bereits abgeschlossen.'}
|
|
</p>
|
|
</section>
|
|
) : null}
|
|
</main>
|
|
);
|
|
}
|