import { Navigate, createFileRoute } from "@tanstack/react-router"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useEffect, useState } from "react"; import type { ModelOption, Profile, ProfileUpdate, TeamSettings } from "@/lib/api"; import { AppShell, SettingsRow, SettingsSection } from "@/components/AppShell"; import { ProfileForm } from "@/components/ProfileForm"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; import { api } from "@/lib/api"; import { useSession } from "@/lib/session"; export const Route = createFileRoute("/admin")({ component: AdminPage }); function AdminPage() { const session = useSession(); const qc = useQueryClient(); const [selected, setSelected] = useState(null); const [error, setError] = useState(null); const options = useQuery({ queryKey: ["options"], queryFn: api.options, enabled: !!session.data?.is_admin, }); const profiles = useQuery({ queryKey: ["adminProfiles"], queryFn: api.adminListProfiles, enabled: !!session.data?.is_admin, }); const save = useMutation({ mutationFn: ({ login, body }: { login: string; body: ProfileUpdate }) => api.adminSaveProfile(login, body), onSuccess: () => { void qc.invalidateQueries({ queryKey: ["adminProfiles"] }); setError(null); }, onError: (e: Error) => setError(e.message), }); if (session.isLoading) { return (
); } if (!session.data) return ; if (!session.data.is_admin) return ; const activeProfile: Profile | null = (selected && profiles.data?.find((p) => p.login === selected)) || null; return (
{profiles.isLoading ? ( ) : ( profiles.data?.map((p) => ( )) )}
{!activeProfile ? (

Pick a user on the left to edit their profile.

) : options.isLoading ? ( ) : ( save.mutateAsync({ login: activeProfile.login!, body }) } saving={save.isPending} error={error} /> )}
); } function GlobalDefaultsSection({ models }: { models: Array }) { const qc = useQueryClient(); const settings = useQuery({ queryKey: ["teamSettings"], queryFn: api.getTeamSettings, }); const [error, setError] = useState(null); const save = useMutation({ mutationFn: (body: TeamSettings) => api.saveTeamSettings(body), onSuccess: (saved) => { qc.setQueryData(["teamSettings"], saved); setError(null); }, onError: (e: Error) => setError(e.message), }); return (
settings.data && save.mutate({ ...settings.data, default_agent_model: model, default_agent_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_agent_subagent_model: model, default_agent_subagent_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_reviewer_model: model, default_reviewer_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_reviewer_subagent_model: model, default_reviewer_subagent_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} />
{error &&

{error}

}
); } interface RolePickerProps { label: string; description: string; models: Array; model: string | null; effort: string | null; onChange: (model: string, effort: string) => void; disabled: boolean; } function RolePicker({ label, description, models, model, effort, onChange, disabled, }: RolePickerProps) { const [localModel, setLocalModel] = useState(model ?? ""); const [localEffort, setLocalEffort] = useState(effort ?? ""); useEffect(() => { setLocalModel(model ?? ""); setLocalEffort(effort ?? ""); }, [model, effort]); const selectedModel = models.find((m) => m.id === localModel); const availableEfforts = selectedModel?.efforts ?? []; const handleModelChange = (value: string | null) => { if (!value) return; const nextModel = models.find((m) => m.id === value); if (!nextModel) return; const nextEffort = nextModel.efforts.includes(localEffort) ? localEffort : nextModel.default_effort; setLocalModel(value); setLocalEffort(nextEffort); onChange(value, nextEffort); }; const handleEffortChange = (value: string | null) => { if (!value || !localModel) return; setLocalEffort(value); onChange(localModel, value); }; return ( } /> ); }