// app/api/[wsId]/tasks/route.ts
import { createClient } from '@tuturuuu/supabase/next/server';
import { hasPermission } from '@/lib/permissions';
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
// GET /api/[wsId]/tasks
export async function GET(
request: NextRequest,
{ params }: { params: { wsId: string } }
) {
try {
const supabase = createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// Check workspace membership
const isMember = await isWorkspaceMember(user.id, params.wsId);
if (!isMember) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
// Parse query parameters
const searchParams = request.nextUrl.searchParams;
const listId = searchParams.get('listId');
const completed = searchParams.get('completed');
// Build query
let query = supabase
.from('workspace_tasks')
.select('*')
.eq('ws_id', params.wsId);
if (listId) query = query.eq('list_id', listId);
if (completed !== null) query = query.eq('completed', completed === 'true');
const { data: tasks, error } = await query;
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json({ data: tasks });
} catch (error) {
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
// POST /api/[wsId]/tasks
const createTaskSchema = z.object({
name: z.string().min(1).max(255),
description: z.string().optional(),
listId: z.string(),
priority: z.number().int().min(0).max(5).optional(),
dueDate: z.string().datetime().optional(),
});
export async function POST(
request: NextRequest,
{ params }: { params: { wsId: string } }
) {
try {
const supabase = createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// Check permission
const canCreate = await hasPermission(user.id, params.wsId, 'manage_tasks');
if (!canCreate) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
// Validate input
const body = await request.json();
const parsed = createTaskSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json(
{ error: 'Invalid input', details: parsed.error.issues },
{ status: 400 }
);
}
// Create task
const { data: task, error } = await supabase
.from('workspace_tasks')
.insert({
ws_id: params.wsId,
name: parsed.data.name,
description: parsed.data.description,
list_id: parsed.data.listId,
priority: parsed.data.priority,
due_date: parsed.data.dueDate,
created_by: user.id,
})
.select()
.single();
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json({ data: task }, { status: 201 });
} catch (error) {
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
// DELETE /api/[wsId]/tasks/[taskId]
export async function DELETE(
request: NextRequest,
{ params }: { params: { wsId: string; taskId: string } }
) {
try {
const supabase = createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const canDelete = await hasPermission(user.id, params.wsId, 'manage_tasks');
if (!canDelete) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
const { error } = await supabase
.from('workspace_tasks')
.delete()
.eq('id', params.taskId)
.eq('ws_id', params.wsId); // Ensure workspace isolation
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json({ success: true });
} catch (error) {
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}