76 lines
3.4 KiB
TypeScript
76 lines
3.4 KiB
TypeScript
import Link from "next/link";
|
|
import Shell from "../components/shell";
|
|
import { getDb } from "@/lib/db";
|
|
import { DEFAULT_TAGE_VORHER } from "@/lib/settings";
|
|
import { TestButtons } from "./test-buttons";
|
|
import IntegrationsForm from "./integrations-form";
|
|
import MembersSection from "./members";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
function Card({ title, children }: { title: string; children: React.ReactNode }) {
|
|
return (
|
|
<section className="rounded-card border border-line bg-white p-5">
|
|
<h2 className="text-[15px] font-semibold tracking-tight">{title}</h2>
|
|
<div className="mt-2 text-sm text-muted">{children}</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export default async function SettingsPage() {
|
|
const db = getDb();
|
|
const last = await db.notificationLog.findFirst({ orderBy: { sentAt: "desc" } });
|
|
return (
|
|
<Shell>
|
|
<Link href="/" className="text-sm font-medium text-muted hover:text-ink">
|
|
← Zurück
|
|
</Link>
|
|
<h1 className="mt-2 text-2xl font-semibold tracking-tight">Einstellungen</h1>
|
|
<p className="mt-1 text-sm text-muted">Erinnerungen, Benachrichtigungen und Empfänger.</p>
|
|
<div className="mt-5 grid gap-4">
|
|
<section className="rounded-card border border-line bg-white p-5">
|
|
<h2 className="text-[15px] font-semibold tracking-tight">Kontakte</h2>
|
|
<p className="mt-1 text-sm text-muted">Wer soll an eure Gutscheine erinnert werden?</p>
|
|
<Link
|
|
href="/contacts"
|
|
className="mt-3 inline-block rounded-field bg-brand-600 px-4 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-brand-700"
|
|
>
|
|
Kontakte verwalten
|
|
</Link>
|
|
</section>
|
|
<MembersSection />
|
|
<Card title="Standard-Erinnerungstage">
|
|
<p>Neue Gutscheine erhalten diese Erinnerungsregeln: {DEFAULT_TAGE_VORHER.join(", ")} Tage vorher.</p>
|
|
</Card>
|
|
<IntegrationsForm />
|
|
<TestButtons />
|
|
<Card title="Letzter Cron-Lauf">
|
|
{last ? (
|
|
<p>
|
|
{last.sentAt.toLocaleString("de-DE")} · {last.kanal} an {last.empfaenger} · {last.status}
|
|
{last.fehler ? ` · Fehler: ${last.fehler}` : ""}
|
|
</p>
|
|
) : (
|
|
<p>Noch keine Benachrichtigung versendet.</p>
|
|
)}
|
|
</Card>
|
|
<Card title="Backup">
|
|
<p>Gesamte Datenbank als Datei sichern, inklusive Gutscheine, Kontakte, Mitglieder und verschlüsselte Einstellungen.</p>
|
|
<a
|
|
href="/api/settings/backup"
|
|
download
|
|
className="mt-3 inline-block rounded-field bg-brand-600 px-4 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-brand-700"
|
|
>
|
|
Datenbank-Backup herunterladen
|
|
</a>
|
|
<p className="mt-2">Wiederherstellen am Server: Datei als <code>/data/gutscheine.db</code> ablegen. Derselbe <code>SETTINGS_ENCRYPTION_KEY</code> muss erhalten bleiben.</p>
|
|
</Card>
|
|
<Card title="Konfiguration (.env)">
|
|
<p>APP_USER, APP_PASSWORD_HASH, SESSION_SECRET, SETTINGS_ENCRYPTION_KEY, DATABASE_URL, CRON_SECRET, APP_URL. SMTP, Telegram und Logo.dev lassen sich oben in der App verwalten; <code>.env</code> dient als Rückfall.</p>
|
|
<p className="mt-2">Zusätzlich manuell: Volume <code>gutschein-data</code> bzw. Datei <code>/data/gutscheine.db</code> regelmäßig kopieren.</p>
|
|
</Card>
|
|
</div>
|
|
</Shell>
|
|
);
|
|
}
|