- Backend: Elysia + Bun + Drizzle ORM + PostgreSQL - Frontend: React + Vite + TypeScript + Tailwind CSS - Task CRUD API with bearer token auth for writes - Public read-only dashboard with auto-refresh - Task states: active, queued, blocked, completed, cancelled - Reorder support for queue management - Progress notes per task - Docker Compose for local dev and Dokploy deployment
56 lines
1.3 KiB
TypeScript
56 lines
1.3 KiB
TypeScript
import {
|
|
pgTable,
|
|
uuid,
|
|
text,
|
|
integer,
|
|
timestamp,
|
|
jsonb,
|
|
pgEnum,
|
|
} from "drizzle-orm/pg-core";
|
|
|
|
export const taskStatusEnum = pgEnum("task_status", [
|
|
"active",
|
|
"queued",
|
|
"blocked",
|
|
"completed",
|
|
"cancelled",
|
|
]);
|
|
|
|
export const taskPriorityEnum = pgEnum("task_priority", [
|
|
"critical",
|
|
"high",
|
|
"medium",
|
|
"low",
|
|
]);
|
|
|
|
export const taskSourceEnum = pgEnum("task_source", [
|
|
"donovan",
|
|
"david",
|
|
"hammer",
|
|
"heartbeat",
|
|
"cron",
|
|
"other",
|
|
]);
|
|
|
|
export interface ProgressNote {
|
|
timestamp: string;
|
|
note: string;
|
|
}
|
|
|
|
export const tasks = pgTable("tasks", {
|
|
id: uuid("id").defaultRandom().primaryKey(),
|
|
title: text("title").notNull(),
|
|
description: text("description"),
|
|
source: taskSourceEnum("source").notNull().default("donovan"),
|
|
status: taskStatusEnum("status").notNull().default("queued"),
|
|
priority: taskPriorityEnum("priority").notNull().default("medium"),
|
|
position: integer("position").notNull().default(0),
|
|
progressNotes: jsonb("progress_notes").$type<ProgressNote[]>().default([]),
|
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
|
|
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
});
|
|
|
|
export type Task = typeof tasks.$inferSelect;
|
|
export type NewTask = typeof tasks.$inferInsert;
|