mirror of
https://github.com/Since-3/since3-portal.git
synced 2026-10-12 19:51:17 +00:00
44 lines
2.3 KiB
TypeScript
44 lines
2.3 KiB
TypeScript
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>
|
||
)
|
||
}
|