Files
Aislo/B01_Dashboard/B01_Dashboard_UI_AssignedPlans.ts
T
eomsangdonandClaude Opus 5.5 22e3797ab8 feat(531-4): 대시보드 받은 예정노선 [연결] 모달 · 새 임도 설계속도 → 단계 2 params · 확정 시각 KST
- B01 받은 예정노선 [연결] = 모달(새 임도 프로젝트로 · 기존 프로젝트에 연결) → link API · 409 확인 → 다시 · 끝나면 B03 이동 · 확정(KST) 열
- 연결 new 때 예정노선 설계속도(20/30/40)를 단계 2 params options.design_speed_kph 에 · existing 은 안 건드림
- B03 자동설계 체인이 단계 2 params 의 설계속도를 이어 넘김(없으면 None = 그대로 · 브레인 허락)
- 받은 예정노선 목록에 confirmed_at · D04 표 확정 시각 KST 표시(서버 UTC 그대로)
- 시험: new 연결 설계속도 기록 · existing · 범위 밖 값 안 넣음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 20:55:45 +09:00

86 lines
3.1 KiB
TypeScript

/* =============================================================================
* B01_Dashboard_UI_AssignedPlans.ts
* 대시보드 「받은 예정노선」 구역(요구서 345 2-2 · PLAN 528-2) — 우리 회사에 지정된 예정노선 연도.
* 열 = 예정노선 · 연도 · 확정(KST) · 연결 상태(연결됨 · 미연결 · 업데이트 있음 배지) · [보기] [연결]
* [보기] = 그 예정노선 첫 단계(D02 · 공유 회사 = GET 만) · [연결] = 모달(`B01_Dashboard_UI_PlanLink`)
* ========================================================================== */
import { API_BASE_URL, ROUTES } from "@config/config_frontend";
import { createButton, createTag } from "@ui/ui_template_elements";
import { table, text } from "@ui/ui_template_general_blocks";
import { goToWorkflowStage } from "../A00_Common/b_workflow_nav";
import { kstText } from "../common_util/common_util_time_kst";
import { DASHBOARD_VISIBLE_ROWS, L } from "./B01_Dashboard_UI_Common";
import { openPlanLinkModal } from "./B01_Dashboard_UI_PlanLink";
export interface AssignedPlan {
assignee_id: number;
project_id: string;
project_name: string;
year: number;
linked_project_id: string | null;
/** 연도 확정 시각 — 서버 UTC */
confirmed_at: string | null;
update_available: boolean;
}
/** 받은 예정노선 — 실패 · 없음 = 빈 목록(구역을 안 그림) */
export async function fetchAssignedPlans(): Promise<AssignedPlan[]> {
const response = await fetch(`${API_BASE_URL}/dashboard/plan-routes/assigned`, {
credentials: "include",
});
if (!response.ok) return [];
return ((await response.json()) as { routes?: AssignedPlan[] }).routes ?? [];
}
function linkState(plan: AssignedPlan): HTMLElement {
const cell = document.createElement("div");
cell.className = "b01-dashboard__actions";
cell.append(
createTag(
L(plan.linked_project_id ? "DE_Assigned_Linked" : "DE_Assigned_Unlinked"),
plan.linked_project_id ? "success" : "neutral",
),
);
if (plan.update_available) cell.append(createTag(L("DE_Assigned_Update"), "warning"));
return cell;
}
export function assignedPlanTable(plans: AssignedPlan[]): HTMLElement {
return table(
[
L("DE_New_Plan"),
L("DE_Assigned_Year"),
L("D04_Col_Confirmed"),
L("DE_Assigned_State"),
L("B01_Dashboard_Table_Action"),
],
plans.map((plan) => {
const actions = document.createElement("div");
actions.className = "b01-dashboard__actions";
const link = createButton({
label: L("DE_Assigned_Link"),
variant: "ghost",
onClick: () =>
void openPlanLinkModal(plan.assignee_id, `${plan.project_name} ${plan.year}`),
});
actions.append(
createButton({
label: L("DE_Assigned_View"),
variant: "ghost",
onClick: () => void goToWorkflowStage(plan.project_id, ROUTES.D02_PLAN_BASE),
}),
link,
);
return [
text(plan.project_name),
text(plan.year),
text(kstText(plan.confirmed_at)),
linkState(plan),
actions,
];
}),
DASHBOARD_VISIBLE_ROWS,
);
}