BillTracker/client/components/admin/adminShared.jsx

51 lines
1.9 KiB
React
Raw Normal View History

import React from 'react';
import { Badge } from '@/components/ui/badge';
import { Label } from '@/components/ui/label';
export function SectionHeading({ children }) {
return <h2 className="text-base font-semibold text-foreground">{children}</h2>;
}
export function FieldRow({ label, children }) {
return (
<div className="grid gap-2 lg:grid-cols-[200px_1fr] lg:items-center lg:gap-4">
<Label className="text-muted-foreground lg:text-right">{label}</Label>
{children}
</div>
);
}
export function Toggle({ checked, onChange, label, disabled = false }) {
return (
<button
type="button"
role="switch"
aria-checked={checked}
disabled={disabled}
onClick={() => !disabled && onChange(!checked)}
className={`relative inline-flex h-5 w-9 shrink-0 rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'} ${checked ? 'bg-primary' : 'bg-input'}`}
>
<span className={`pointer-events-none inline-block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform ${checked ? 'translate-x-4' : 'translate-x-0'}`} />
{label && <span className="sr-only">{label}</span>}
</button>
);
}
export function formatDateTime(value) {
if (!value) return '—';
const date = new Date(value);
if (Number.isNaN(date.getTime())) return value;
return date.toLocaleString();
}
export function BackupTypeBadge({ type }) {
const cls = {
manual: 'bg-blue-500/15 text-blue-400 border-blue-500/20',
scheduled: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/20',
imported: 'bg-violet-500/15 text-violet-400 border-violet-500/20',
'pre-restore': 'bg-amber-500/15 text-amber-400 border-amber-500/20',
}[type] || 'bg-muted text-muted-foreground border-border';
return <Badge className={cls}>{type || 'backup'}</Badge>;
}