semblance-dev/src/components/admin/FocusGroupsTab.tsx
Vadym Samoilenko 57508e8e55 Add period selector to all cost-bearing admin tabs
- New usePeriod hook (day/week/month/all/custom presets) with from/to ISO string outputs
- New PeriodSelector component (button group + custom date inputs)
- UsersTab, UsageTab, FocusGroupsTab all wired up with period state
- Backend /admin/users and /admin/focus-groups now accept from/to query params
- MTD Cost column header now reflects selected period label (e.g. "Cost (MTD)")
- Logout clears local state only (no account sign-out)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 19:03:16 +01:00

67 lines
2.8 KiB
TypeScript

import { useAdminFocusGroups } from '@/hooks/useAdminFocusGroups';
import { usePeriod } from '@/hooks/usePeriod';
import PeriodSelector from '@/components/admin/PeriodSelector';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Badge } from '@/components/ui/badge';
import { Loader2 } from 'lucide-react';
export default function FocusGroupsTab() {
const { period, setPeriod, customFrom, setCustomFrom, customTo, setCustomTo, from, to } = usePeriod('all');
const { data, isLoading } = useAdminFocusGroups({ from, to });
const fgs = data?.focus_groups ?? [];
return (
<div className="space-y-4">
<PeriodSelector
period={period} setPeriod={setPeriod}
customFrom={customFrom} setCustomFrom={setCustomFrom}
customTo={customTo} setCustomTo={setCustomTo}
/>
{isLoading ? (
<div className="flex justify-center py-12"><Loader2 className="h-8 w-8 animate-spin text-primary" /></div>
) : (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Date</TableHead>
<TableHead>Model</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Cost</TableHead>
<TableHead className="text-right">Calls</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{fgs.length === 0 && (
<TableRow>
<TableCell colSpan={6} className="text-center text-slate-500 py-8">No focus groups</TableCell>
</TableRow>
)}
{fgs.map((fg: any) => (
<TableRow key={fg._id}>
<TableCell className="font-medium">{fg.name}</TableCell>
<TableCell className="text-xs text-slate-500">
{fg.date ? new Date(fg.date).toLocaleDateString() : '—'}
</TableCell>
<TableCell className="font-mono text-xs">{fg.llm_model ?? '—'}</TableCell>
<TableCell>
<Badge
variant={fg.status === 'completed' ? 'secondary' : fg.status === 'paused_quota' ? 'destructive' : 'outline'}
className="text-xs"
>
{fg.status ?? 'active'}
</Badge>
</TableCell>
<TableCell className="text-right font-mono text-xs">${(fg.cost_total ?? 0).toFixed(4)}</TableCell>
<TableCell className="text-right text-xs">{fg.call_count ?? 0}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)}
</div>
);
}