チャット送信の即時表示とKanbanのDnD並べ替えを修正。 - chat: 送信成功時に返却メッセージを楽観的にローカルへ先頭追加(SSE到着前でも即表示、idで重複排除)。setSending(false) をレスポンス処理後に移動し二重送信窓を縮小。 - todo: TodoService.reorderItems(projectId, columnId, itemIds[]) を追加(1トランザクションでカラム内を再採番、メンバーシップ+同プロジェクト検証、活動ログ/SSEは1件)。POST /todos/items/reorder を追加。 - KanbanBoard: カード単位のドロップターゲット(ポインタYで前/後挿入)+カラム空き領域は末尾追加。楽観的にorderIndex/columnIdを更新しrenderをorderIndexでソート(即時反映)、失敗時はエラー表示+再取得で巻き戻し。ドラッグ直後の誤クリック(ダイアログ誘起)をdragEndタイムスタンプで抑制。空の並べ替えはSSE/ログを出さない。
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { getCurrentUser } from '@/lib/auth/getCurrentUser';
|
|
import { createTodoService } from '@/lib/api/services';
|
|
import { UnauthorizedError } from '@/lib/errors';
|
|
import { handleApiError, jsonError } from '@/lib/api/handleError';
|
|
|
|
export const runtime = 'nodejs';
|
|
|
|
/**
|
|
* カラム内のアイテム順序を一括再採番する(同一カラムの並べ替え / 他カラムからの移動)。
|
|
* body: { columnId: number, itemIds: number[] } —— itemIds の順序で orderIndex 0..n-1 を割り当てる。
|
|
*/
|
|
export async function POST(
|
|
request: NextRequest,
|
|
{ params }: { params: Promise<{ projectId: string }> }
|
|
) {
|
|
const user = await getCurrentUser();
|
|
if (!user) return handleApiError(new UnauthorizedError());
|
|
const { projectId } = await params;
|
|
let body: Record<string, unknown>;
|
|
try {
|
|
body = (await request.json()) as Record<string, unknown>;
|
|
} catch {
|
|
return jsonError(400, 'リクエスト本文が不正です');
|
|
}
|
|
|
|
const columnId = Number(body.columnId);
|
|
const itemIds = Array.isArray(body.itemIds)
|
|
? body.itemIds
|
|
.map((n) => Number(n))
|
|
.filter((n) => Number.isFinite(n) && n > 0)
|
|
: [];
|
|
|
|
const service = createTodoService();
|
|
try {
|
|
const items = service.reorderItems(
|
|
user.id,
|
|
Number(projectId),
|
|
columnId,
|
|
itemIds
|
|
);
|
|
return NextResponse.json({ items });
|
|
} catch (error) {
|
|
return handleApiError(error);
|
|
}
|
|
}
|