since3-portal/modules/admin/ui/views/internal-accounts-view.tsx
2026-10-11 18:22:32 +02:00

44 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { monthlyCost } from "@/modules/admin/lib/internal-costs"
import { getInternalCredentials } from "@/modules/admin/queries/internal-credentials"
import { InternalCredentialDialog } from "@/modules/admin/ui/components/internal-credential-dialog"
import { InternalCredentialsTable } from "@/modules/admin/ui/components/internal-credentials-table"
import { formatCurrency } from "@/modules/shared/lib/invoice-math"
function Stat({ label, value, detail }: { label: string; value: string; detail?: string }) {
return (
<div className="flex min-w-0 flex-col gap-1 rounded-lg border border-border p-4">
<span className="text-small text-muted-foreground">{label}</span>
<span className="text-xl font-semibold tabular-nums break-words sm:text-2xl">{value}</span>
{detail && <span className="text-small text-muted-foreground">{detail}</span>}
</div>
)
}
export default async function InternalAccountsView() {
const credentials = await getInternalCredentials()
const perMonth = monthlyCost(credentials)
const paid = credentials.filter((credential) => credential.plan === "paid").length
return (
<div className="flex w-full flex-col gap-6 md:gap-8">
<div className="flex w-full flex-wrap items-start justify-between gap-3">
<div className="flex flex-col gap-2">
<h1 className="text-2xl font-semibold md:text-3xl">Internal Accounts</h1>
<p className="max-w-2xl text-sm text-muted-foreground">
Zugänge von Since3 selbst – verschlüsselt im Supabase Vault und nur für Admins sichtbar.
Jedes Anzeigen oder Kopieren eines Passworts wird protokolliert.
</p>
</div>
<InternalCredentialDialog />
</div>
<div className="grid gap-3 sm:grid-cols-3">
<Stat label="Laufende Kosten" value={`${formatCurrency(perMonth)} / Monat`} detail={`≈ ${formatCurrency(perMonth * 12)} im Jahr`} />
<Stat label="Bezahlte Dienste" value={String(paid)} detail={`von ${credentials.length} Zugängen`} />
<Stat label="Kostenlose Dienste" value={String(credentials.length - paid)} />
</div>
<InternalCredentialsTable credentials={credentials} />
</div>
)
}