diff --git a/src/components/JobList.tsx b/src/components/JobList.tsx
new file mode 100644
index 0000000..8993573
--- /dev/null
+++ b/src/components/JobList.tsx
@@ -0,0 +1,25 @@
+import { JobListItem, type JobListItemProps } from "@/components/JobListItem"
+import { cn } from "@/lib/utils"
+
+export interface JobListProps {
+ jobs: JobListItemProps[]
+ className?: string
+}
+
+export function JobList({ jobs, className }: JobListProps) {
+ if (jobs.length === 0) {
+ return (
+
+ )
+ }
+
+ return (
+
+ {jobs.map((job, index) => (
+
+ ))}
+
+ )
+}
diff --git a/src/components/JobListItem.tsx b/src/components/JobListItem.tsx
new file mode 100644
index 0000000..bee23dd
--- /dev/null
+++ b/src/components/JobListItem.tsx
@@ -0,0 +1,30 @@
+import { Progress } from "@/components/ui/progress"
+import { cn } from "@/lib/utils"
+import { formatTime } from "@/utils/datetime"
+
+export interface JobListItemProps {
+ title: string
+ runningTime: string
+ progress: number
+ startTime?: string
+ eta?: string
+ className?: string
+}
+
+export function JobListItem({ title, runningTime, progress, startTime, eta, className }: JobListItemProps) {
+ return (
+
+
+ {title}
+ {runningTime}
+
+
+ {(startTime || eta) && (
+
+ {startTime ? formatTime(startTime) : ""} started
+ {eta ? `ETA ${formatTime(eta)}` : ""}
+
+ )}
+
+ )
+}
diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx
new file mode 100644
index 0000000..f162996
--- /dev/null
+++ b/src/components/ui/label.tsx
@@ -0,0 +1,18 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+function Label({ className, ...props }: React.ComponentProps<"label">) {
+ return (
+
+ )
+}
+
+export { Label }
diff --git a/src/components/ui/progress.tsx b/src/components/ui/progress.tsx
new file mode 100644
index 0000000..844e869
--- /dev/null
+++ b/src/components/ui/progress.tsx
@@ -0,0 +1,81 @@
+import { Progress as ProgressPrimitive } from "@base-ui/react/progress"
+
+import { cn } from "@/lib/utils"
+
+function Progress({
+ className,
+ children,
+ value,
+ ...props
+}: ProgressPrimitive.Root.Props) {
+ return (
+
+ {children}
+
+
+
+
+ )
+}
+
+function ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {
+ return (
+
+ )
+}
+
+function ProgressIndicator({
+ className,
+ ...props
+}: ProgressPrimitive.Indicator.Props) {
+ return (
+
+ )
+}
+
+function ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {
+ return (
+
+ )
+}
+
+function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {
+ return (
+
+ )
+}
+
+export {
+ Progress,
+ ProgressTrack,
+ ProgressIndicator,
+ ProgressLabel,
+ ProgressValue,
+}
diff --git a/src/views/JobsView.tsx b/src/views/JobsView.tsx
index 42be260..78a3e16 100644
--- a/src/views/JobsView.tsx
+++ b/src/views/JobsView.tsx
@@ -1,7 +1,10 @@
+import { JobList } from "@/components/JobList"
+import mockJobs from "@/mocks/jobs.json"
+
export function JobsView() {
return (
-
-
Running jobs coming soon.
+
+
)
}