added requesting option
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
createUploadRequestAction,
|
||||
deleteOwnUploadAction,
|
||||
extendOwnUploadAction,
|
||||
userLogoutAction,
|
||||
@@ -23,11 +24,20 @@ export default async function DashboardPage({ searchParams }) {
|
||||
'SELECT id, original_name, stored_name, size_bytes, uploaded_at, expires_at FROM uploads WHERE owner = ? ORDER BY uploaded_at DESC',
|
||||
[user.username]
|
||||
);
|
||||
const uploadRequests = await all(
|
||||
`SELECT id, note, created_at, expires_at, completed_at, uploaded_original_name
|
||||
FROM upload_requests
|
||||
WHERE owner = ?
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 200`,
|
||||
[user.username]
|
||||
);
|
||||
|
||||
const resolvedSearchParams = await searchParams;
|
||||
const error = readSearchParam(resolvedSearchParams, 'error');
|
||||
const success = readSearchParam(resolvedSearchParams, 'success');
|
||||
const totalBytes = uploads.reduce((total, item) => total + (Number(item.size_bytes) || 0), 0);
|
||||
const nowTs = Date.now();
|
||||
|
||||
return (
|
||||
<main className="page-shell">
|
||||
@@ -76,6 +86,83 @@ export default async function DashboardPage({ searchParams }) {
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<section className="panel">
|
||||
<h2>Upload-Anfragen</h2>
|
||||
<p className="muted">Benachrichtigung erfolgt an deinen Benutzernamen (E-Mail-Adresse).</p>
|
||||
<form className="form-grid" action={createUploadRequestAction}>
|
||||
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||
|
||||
<label className="field">
|
||||
Notiz (optional)
|
||||
<input className="input" name="note" placeholder="z. B. Bitte die Rechnung als PDF senden" />
|
||||
</label>
|
||||
|
||||
<label className="field">
|
||||
Gültig in Stunden
|
||||
<input className="input" name="expiresHours" placeholder="72" />
|
||||
</label>
|
||||
|
||||
<button className="btn" type="submit">
|
||||
Anfrage erstellen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{uploadRequests.length === 0 ? (
|
||||
<p className="muted">Noch keine Upload-Anfragen.</p>
|
||||
) : (
|
||||
<div className="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Anfrage</th>
|
||||
<th>Status</th>
|
||||
<th>Erstellt</th>
|
||||
<th>Gültig bis</th>
|
||||
<th>Ergebnis</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{uploadRequests.map((entry) => {
|
||||
const requestPath = `/_request/${encodeURIComponent(entry.id)}`;
|
||||
const isCompleted = Number(entry.completed_at || 0) > 0;
|
||||
const isExpired = !isCompleted && Number(entry.expires_at || 0) <= nowTs;
|
||||
|
||||
return (
|
||||
<tr key={entry.id}>
|
||||
<td>
|
||||
<strong>{entry.id}</strong>
|
||||
{entry.note ? <div className="muted">{entry.note}</div> : null}
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
className={`badge ${
|
||||
isCompleted ? 'success' : isExpired ? 'danger' : 'primary'
|
||||
}`}
|
||||
>
|
||||
{isCompleted ? 'Abgeschlossen' : isExpired ? 'Abgelaufen' : 'Offen'}
|
||||
</span>
|
||||
</td>
|
||||
<td>{formatTimestamp(entry.created_at)}</td>
|
||||
<td>{formatTimestamp(entry.expires_at)}</td>
|
||||
<td>{entry.uploaded_original_name || '-'}</td>
|
||||
<td>
|
||||
<div className="row-actions">
|
||||
<a className="btn secondary" href={requestPath}>
|
||||
Öffnen
|
||||
</a>
|
||||
<CopyLinkButton path={requestPath} label="Upload-Anfrage" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="panel">
|
||||
<h2>Aktuelle Uploads</h2>
|
||||
{uploads.length === 0 ? (
|
||||
|
||||
Reference in New Issue
Block a user