Adds the full Next.js app (app/, components/, lib/, scripts/, assets/, docs/, Dockerfile, compose, configs) to version control. Security: - CIPC BizPortal customer-code logins (Login 1 + Login 3) now read CIPC_LOGIN1_CODE / CIPC_LOGIN1_PASSWORD / CIPC_LOGIN3_CODE / CIPC_LOGIN3_PASSWORD from .env.local instead of source. - BizPortal personal login in apply-bizportal route reads BIZPORTAL_ID_NO / BIZPORTAL_PASSWORD. - Added .env.example as the committed template. .gitignore excludes .env*, node_modules, .next, logs, sqlite, Playwright storage_state.json (live CIPC cookies), scratch dirs, client PDFs and debug screenshots.
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
// app/api/tasks/[id]/complete/route.ts
|
|
// POST /api/tasks/[id]/complete
|
|
// Atomic state transition: in_progress → done. Body: { result, log, duration_ms }.
|
|
|
|
import { NextRequest, NextResponse } from "next/server";
|
|
import { BASE_URL, PBRecord } from "@/lib/pb";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const COLLECTION = "tasks";
|
|
|
|
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
|
|
let body: any = {};
|
|
try {
|
|
body = await req.json();
|
|
} catch {
|
|
return NextResponse.json({ error: "invalid JSON body" }, { status: 400 });
|
|
}
|
|
|
|
const update: Record<string, unknown> = {
|
|
status: "done",
|
|
completed_at: new Date().toISOString().replace("T", " ").replace("Z", ""),
|
|
result: body.result ?? null,
|
|
log: body.log ?? null,
|
|
};
|
|
if (typeof body.duration_ms === "number") update.duration_ms = body.duration_ms;
|
|
|
|
// Atomic PATCH: only succeeds if status is currently "in_progress".
|
|
const url = `${BASE_URL}/api/collections/${COLLECTION}/records/${encodeURIComponent(params.id)}?filter=status="in_progress"`;
|
|
const res = await fetch(url, {
|
|
method: "PATCH",
|
|
headers: {
|
|
Authorization: process.env.PB_TOKEN as string,
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(update),
|
|
cache: "no-store",
|
|
});
|
|
|
|
if (res.status === 404) {
|
|
return NextResponse.json(
|
|
{ ok: false, error: "task not found or not in progress" },
|
|
{ status: 409 },
|
|
);
|
|
}
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
return NextResponse.json({ ok: false, error: `PB ${res.status}: ${text.slice(0, 200)}` }, { status: 500 });
|
|
}
|
|
const data: PBRecord = await res.json();
|
|
return NextResponse.json({ ok: true, task: data });
|
|
}
|