diff --git a/apps/desktop/src/renderer/components/tasks/task-card-skeleton.tsx b/apps/desktop/src/renderer/components/tasks/task-card-skeleton.tsx
new file mode 100644
index 00000000..4d278e8e
--- /dev/null
+++ b/apps/desktop/src/renderer/components/tasks/task-card-skeleton.tsx
@@ -0,0 +1,24 @@
+import { Skeleton } from '@/renderer/components/ui/skeleton';
+
+export const TaskCardSkeleton = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/desktop/src/renderer/components/tasks/task-container.tsx b/apps/desktop/src/renderer/components/tasks/task-container.tsx
index 76f11b69..b99b7b6f 100644
--- a/apps/desktop/src/renderer/components/tasks/task-container.tsx
+++ b/apps/desktop/src/renderer/components/tasks/task-container.tsx
@@ -1,18 +1,9 @@
-import {
- formatDuration,
- formatTaskStatus,
- formatTaskType,
- timeAgo,
-} from '@colanode/core';
-import { Clock, Calendar } from 'lucide-react';
-
import { Container, ContainerBody } from '@/renderer/components/ui/container';
import { useWorkspace } from '@/renderer/contexts/workspace';
import { useQuery } from '@/renderer/hooks/use-query';
-import { TaskLogs } from '@/renderer/components/tasks/task-logs';
-import { TaskArtifacts } from '@/renderer/components/tasks/task-artifacts';
import { TaskNotFound } from '@/renderer/components/tasks/task-not-found';
-import { TaskStatusBadge } from '@/renderer/components/tasks/task-status-badge';
+import { TaskDetails } from '@/renderer/components/tasks/task-details';
+import { TaskSkeleton } from '@/renderer/components/tasks/task-skeleton';
interface TaskContainerProps {
taskId: string;
@@ -28,89 +19,20 @@ export const TaskContainer = ({ taskId }: TaskContainerProps) => {
taskId: taskId,
});
- if (isPending) {
- return Loading...
;
- }
-
- if (!data) {
- return ;
- }
-
- const duration = formatDuration(data.task.createdAt, data.task.completedAt);
- const createdAtAgo = timeAgo(data.task.createdAt);
-
return (
-
-
-
-
-
-
-
{data.task.name}
-
- {data.task.description}
-
-
-
-
-
-
- Type
-
- {formatTaskType(data.task.attributes.type)}
-
-
-
-
- Status
-
-
- {formatTaskStatus(data.task.status)}
-
-
-
-
- Started
-
-
-
- {createdAtAgo}
-
-
-
-
- Duration
-
-
-
- {duration}
-
-
-
-
- Artifacts
-
-
- {data.artifacts.length}
-
-
-
-
-
-
-
Logs
-
-
-
-
-
+ {isPending ? (
+
+ ) : data ? (
+
+ ) : (
+
+ )}
);
diff --git a/apps/desktop/src/renderer/components/tasks/task-details.tsx b/apps/desktop/src/renderer/components/tasks/task-details.tsx
new file mode 100644
index 00000000..f0b78a92
--- /dev/null
+++ b/apps/desktop/src/renderer/components/tasks/task-details.tsx
@@ -0,0 +1,87 @@
+import {
+ formatDuration,
+ formatTaskStatus,
+ formatTaskType,
+ TaskArtifactOutput,
+ TaskLogOutput,
+ TaskOutput,
+ timeAgo,
+} from '@colanode/core';
+import { Clock, Calendar } from 'lucide-react';
+
+import { TaskLogs } from '@/renderer/components/tasks/task-logs';
+import { TaskArtifacts } from '@/renderer/components/tasks/task-artifacts';
+import { TaskStatusBadge } from '@/renderer/components/tasks/task-status-badge';
+
+interface TaskDetailsProps {
+ task: TaskOutput;
+ logs: TaskLogOutput[];
+ artifacts: TaskArtifactOutput[];
+}
+
+export const TaskDetails = ({ task, logs, artifacts }: TaskDetailsProps) => {
+ const duration = formatDuration(task.createdAt, task.completedAt);
+ const createdAtAgo = timeAgo(task.createdAt);
+
+ return (
+
+
+
+
+
+
+
{task.name}
+
+ {task.description}
+
+
+
+
+
+
+ Type
+
+ {formatTaskType(task.attributes.type)}
+
+
+
+ Status
+
+ {formatTaskStatus(task.status)}
+
+
+
+
Started
+
+
+ {createdAtAgo}
+
+
+
+
Duration
+
+
+ {duration}
+
+
+
+ Artifacts
+ {artifacts.length}
+
+
+
+
+
+
Logs
+
+
+
+
+
+ );
+};
diff --git a/apps/desktop/src/renderer/components/tasks/task-list.tsx b/apps/desktop/src/renderer/components/tasks/task-list.tsx
index 78a6236a..106245a0 100644
--- a/apps/desktop/src/renderer/components/tasks/task-list.tsx
+++ b/apps/desktop/src/renderer/components/tasks/task-list.tsx
@@ -4,8 +4,8 @@ import { useQuery } from '@/renderer/hooks/use-query';
import { useWorkspace } from '@/renderer/contexts/workspace';
import { Button } from '@/renderer/components/ui/button';
import { TaskCreateDialog } from '@/renderer/components/tasks/task-create-dialog';
-import { Spinner } from '@/renderer/components/ui/spinner';
import { TaskCard } from '@/renderer/components/tasks/task-card';
+import { TaskCardSkeleton } from '@/renderer/components/tasks/task-card-skeleton';
export const TaskList = () => {
const workspace = useWorkspace();
@@ -30,10 +30,14 @@ export const TaskList = () => {
- {isPending && }
- {tasks.map((t) => (
-
- ))}
+ {isPending && (
+ <>
+
+
+
+ >
+ )}
+ {!isPending && tasks.map((t) => )}
{
+ return (
+
+
+
+
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ );
+};