- Added Sprint type and interface - Updated Task to include sprintId - Added sprint actions to task store (addSprint, updateSprint, deleteSprint, selectSprint) - Updated API to handle sprints - Updated all sync calls to include sprints
137 lines
3.5 KiB
TypeScript
137 lines
3.5 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
import { join } from "path";
|
|
|
|
const DATA_FILE = join(process.cwd(), "data", "tasks.json");
|
|
|
|
interface Task {
|
|
id: string;
|
|
title: string;
|
|
description?: string;
|
|
type: 'idea' | 'task' | 'bug' | 'research' | 'plan';
|
|
status: 'backlog' | 'in-progress' | 'review' | 'done' | 'archived';
|
|
priority: 'low' | 'medium' | 'high' | 'urgent';
|
|
projectId: string;
|
|
sprintId?: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
dueDate?: string;
|
|
comments: { id: string; text: string; createdAt: string; author: 'user' | 'assistant' }[];
|
|
tags: string[];
|
|
}
|
|
|
|
interface Project {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
color: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
interface Sprint {
|
|
id: string;
|
|
name: string;
|
|
goal?: string;
|
|
startDate: string;
|
|
endDate: string;
|
|
status: 'planning' | 'active' | 'completed';
|
|
projectId: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
interface DataStore {
|
|
projects: Project[];
|
|
tasks: Task[];
|
|
sprints: Sprint[];
|
|
lastUpdated: number;
|
|
}
|
|
|
|
const defaultData: DataStore = {
|
|
projects: [
|
|
{ id: '1', name: 'OpenClaw iOS', description: 'Main iOS app development', color: '#8b5cf6', createdAt: new Date().toISOString() },
|
|
{ id: '2', name: 'Web Projects', description: 'Web tools and dashboards', color: '#3b82f6', createdAt: new Date().toISOString() },
|
|
{ id: '3', name: 'Research', description: 'Experiments and learning', color: '#10b981', createdAt: new Date().toISOString() },
|
|
],
|
|
tasks: [],
|
|
sprints: [],
|
|
lastUpdated: Date.now(),
|
|
};
|
|
|
|
function getData(): DataStore {
|
|
if (!existsSync(DATA_FILE)) {
|
|
return defaultData;
|
|
}
|
|
try {
|
|
const data = readFileSync(DATA_FILE, "utf-8");
|
|
return JSON.parse(data);
|
|
} catch {
|
|
return defaultData;
|
|
}
|
|
}
|
|
|
|
function saveData(data: DataStore) {
|
|
const dir = join(process.cwd(), "data");
|
|
if (!existsSync(dir)) {
|
|
require("fs").mkdirSync(dir, { recursive: true });
|
|
}
|
|
data.lastUpdated = Date.now();
|
|
writeFileSync(DATA_FILE, JSON.stringify(data, null, 2));
|
|
}
|
|
|
|
// GET - fetch all tasks, projects, and sprints
|
|
export async function GET() {
|
|
const data = getData();
|
|
return NextResponse.json(data);
|
|
}
|
|
|
|
// POST - create or update tasks, projects, or sprints
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const { task, projects, sprints } = await request.json();
|
|
const data = getData();
|
|
|
|
// Update projects if provided
|
|
if (projects) {
|
|
data.projects = projects;
|
|
}
|
|
|
|
// Update sprints if provided
|
|
if (sprints) {
|
|
data.sprints = sprints;
|
|
}
|
|
|
|
// Update or add task
|
|
if (task) {
|
|
const existingIndex = data.tasks.findIndex((t) => t.id === task.id);
|
|
if (existingIndex >= 0) {
|
|
data.tasks[existingIndex] = { ...task, updatedAt: new Date().toISOString() };
|
|
} else {
|
|
data.tasks.push({
|
|
...task,
|
|
id: task.id || Date.now().toString(),
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
});
|
|
}
|
|
}
|
|
|
|
saveData(data);
|
|
return NextResponse.json({ success: true, data });
|
|
} catch (error) {
|
|
return NextResponse.json({ error: "Failed to save" }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// DELETE - remove a task
|
|
export async function DELETE(request: Request) {
|
|
try {
|
|
const { id } = await request.json();
|
|
const data = getData();
|
|
data.tasks = data.tasks.filter((t) => t.id !== id);
|
|
saveData(data);
|
|
return NextResponse.json({ success: true });
|
|
} catch (error) {
|
|
return NextResponse.json({ error: "Failed to delete" }, { status: 500 });
|
|
}
|
|
}
|