diff --git a/src/components/admin/AdminTasksPanel.tsx b/src/components/admin/AdminTasksPanel.tsx index ffcb879..f386feb 100644 --- a/src/components/admin/AdminTasksPanel.tsx +++ b/src/components/admin/AdminTasksPanel.tsx @@ -75,7 +75,7 @@ function formatDuration(ms: number | null): string { export function AdminTasksPanel() { const queryClient = useQueryClient(); - const { data, error } = useQuery({ + const { data, error, isPending: isLoading } = useQuery({ queryKey: TASKS_QUERY_KEY, queryFn: fetchTasks, refetchInterval: 5000, @@ -122,28 +122,60 @@ export function AdminTasksPanel() { Vercel Hobby invokes scheduled tasks once daily. Shorter intervals are unavailable on this deployment.

)} -
- {(data?.tasks ?? []).map((task) => ( - patchTask.mutate({ key: task.key, patch: { enabled } })} - onSaveInterval={(intervalMs) => patchTask.mutate({ key: task.key, patch: { intervalMs } })} - onRun={() => runTask.mutate(task.key)} - /> - ))} - {data && data.tasks.length === 0 && ( -

No tasks registered.

- )} -
+ {isLoading ? ( + + ) : ( +
+ {(data?.tasks ?? []).map((task) => ( + patchTask.mutate({ key: task.key, patch: { enabled } })} + onSaveInterval={(intervalMs) => patchTask.mutate({ key: task.key, patch: { intervalMs } })} + onRun={() => runTask.mutate(task.key)} + /> + ))} + {data && data.tasks.length === 0 && ( +

No tasks registered.

+ )} +
+ )} ); } +function TasksSkeleton() { + const rows = Array.from({ length: 2 }); + return ( +
+ {rows.map((_, index) => ( + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + ))} +
+ ); +} + function TaskRow({ task, schedulerMode,