96 lines
2.3 KiB
TypeScript
96 lines
2.3 KiB
TypeScript
|
|
const BASE = 'http://localhost:8420/api'
|
||
|
|
|
||
|
|
async function get<T>(path: string): Promise<T> {
|
||
|
|
const res = await fetch(`${BASE}${path}`)
|
||
|
|
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`)
|
||
|
|
return res.json()
|
||
|
|
}
|
||
|
|
|
||
|
|
async function post<T>(path: string, body: unknown): Promise<T> {
|
||
|
|
const res = await fetch(`${BASE}${path}`, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify(body),
|
||
|
|
})
|
||
|
|
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`)
|
||
|
|
return res.json()
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Project {
|
||
|
|
id: string
|
||
|
|
name: string
|
||
|
|
path: string
|
||
|
|
status: string
|
||
|
|
priority: number
|
||
|
|
tech_stack: string[] | null
|
||
|
|
created_at: string
|
||
|
|
total_tasks: number
|
||
|
|
done_tasks: number
|
||
|
|
active_tasks: number
|
||
|
|
blocked_tasks: number
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ProjectDetail extends Project {
|
||
|
|
tasks: Task[]
|
||
|
|
modules: Module[]
|
||
|
|
decisions: Decision[]
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Task {
|
||
|
|
id: string
|
||
|
|
project_id: string
|
||
|
|
title: string
|
||
|
|
status: string
|
||
|
|
priority: number
|
||
|
|
assigned_role: string | null
|
||
|
|
parent_task_id: string | null
|
||
|
|
brief: Record<string, unknown> | null
|
||
|
|
spec: Record<string, unknown> | null
|
||
|
|
created_at: string
|
||
|
|
updated_at: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Decision {
|
||
|
|
id: number
|
||
|
|
project_id: string
|
||
|
|
task_id: string | null
|
||
|
|
type: string
|
||
|
|
category: string | null
|
||
|
|
title: string
|
||
|
|
description: string
|
||
|
|
tags: string[] | null
|
||
|
|
created_at: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Module {
|
||
|
|
id: number
|
||
|
|
project_id: string
|
||
|
|
name: string
|
||
|
|
type: string
|
||
|
|
path: string
|
||
|
|
description: string | null
|
||
|
|
owner_role: string | null
|
||
|
|
dependencies: string[] | null
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface CostEntry {
|
||
|
|
project_id: string
|
||
|
|
project_name: string
|
||
|
|
runs: number
|
||
|
|
total_tokens: number
|
||
|
|
total_cost_usd: number
|
||
|
|
total_duration_seconds: number
|
||
|
|
}
|
||
|
|
|
||
|
|
export const api = {
|
||
|
|
projects: () => get<Project[]>('/projects'),
|
||
|
|
project: (id: string) => get<ProjectDetail>(`/projects/${id}`),
|
||
|
|
cost: (days = 7) => get<CostEntry[]>(`/cost?days=${days}`),
|
||
|
|
createProject: (data: { id: string; name: string; path: string; tech_stack?: string[]; priority?: number }) =>
|
||
|
|
post<Project>('/projects', data),
|
||
|
|
createTask: (data: { project_id: string; title: string; priority?: number; route_type?: string }) =>
|
||
|
|
post<Task>('/tasks', data),
|
||
|
|
bootstrap: (data: { path: string; id: string; name: string }) =>
|
||
|
|
post<{ project: Project }>('/bootstrap', data),
|
||
|
|
}
|