fix(ui): handle 404 errors in profile settings fetch

- throw on non-OK responses in ProfileEditor queryFn
- add isError state with user-friendly message and retry button
- add defensive null check for data.path before .replace() call
- apply same defensive check to provider-editor.tsx

Fixes blank screen when API profile settings file doesn't exist.
This commit is contained in:
kaitranntt
2025-12-18 05:25:52 -05:00
parent d746ec77ca
commit 60c01c7e60
2 changed files with 22 additions and 4 deletions
@@ -566,7 +566,7 @@ export function ProviderEditor({
<div>
<div className="flex items-center gap-2">
<h2 className="text-lg font-semibold">{displayName}</h2>
{data && (
{data?.path && (
<Badge variant="outline" className="text-xs">
{data.path.replace(/^.*\//, '')}
</Badge>
+21 -3
View File
@@ -46,9 +46,15 @@ export function ProfileEditor({ profileName, onDelete }: ProfileEditorProps) {
const queryClient = useQueryClient();
// Fetch settings for selected profile
const { data, isLoading, refetch } = useQuery<SettingsResponse>({
const { data, isLoading, isError, refetch } = useQuery<SettingsResponse>({
queryKey: ['settings', profileName],
queryFn: () => fetch(`/api/settings/${profileName}/raw`).then((r) => r.json()),
queryFn: async () => {
const res = await fetch(`/api/settings/${profileName}/raw`);
if (!res.ok) {
throw new Error(`Failed to load settings: ${res.status}`);
}
return res.json();
},
});
// Derive raw JSON content
@@ -427,7 +433,7 @@ export function ProfileEditor({ profileName, onDelete }: ProfileEditorProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-lg font-semibold">{profileName}</h2>
{data && (
{data?.path && (
<Badge variant="outline" className="text-xs">
{data.path.replace(/^.*\//, '')}
</Badge>
@@ -473,6 +479,18 @@ export function ProfileEditor({ profileName, onDelete }: ProfileEditorProps) {
<Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
<span className="ml-3 text-muted-foreground">Loading settings...</span>
</div>
) : isError ? (
<div className="flex-1 flex items-center justify-center">
<div className="text-center space-y-3">
<p className="text-sm text-muted-foreground">
Failed to load settings for this profile.
</p>
<Button variant="outline" size="sm" onClick={() => refetch()}>
<RefreshCw className="w-4 h-4 mr-1" />
Retry
</Button>
</div>
</div>
) : (
// Split Layout (40% Left / 60% Right)
<div className="flex-1 grid grid-cols-[40%_60%] divide-x overflow-hidden">