import { createButton, createTag } from "@ui/ui_template_elements"; import { fetchCompanyAssets, processJoinRequest, setCompanyLogo, type CompanyInfo, type DashboardUser, type JoinRequest, type Member, } from "./B01_Dashboard_Api_Fetch"; import { createAssetField, openAssetPicker } from "./B01_Dashboard_UI_AssetPicker"; import { canChangeRole, canDeleteUser } from "./B01_Dashboard_UI_Helper"; import { openChangeRoleModal, openEditCompanyModal, openCreateCompanyModal, openDeleteUserModal, openEditUserModal, openFindCompanyModal, } from "./B01_Dashboard_UI_Modals"; import type { DashboardState } from "./B01_Dashboard_UI_Page"; import { actionPair, table, text } from "@ui/ui_template_general_blocks"; import { DASHBOARD_VISIBLE_ROWS, formatDate, L, runRequest } from "./B01_Dashboard_UI_Common"; export function buildCompanyPanel(state: DashboardState): HTMLElement { const wrap = document.createElement("div"); wrap.className = "b01-dashboard__actions"; if (!state.company) { wrap.append( createTag(L("B01_Dashboard_NoCompany"), "warning"), createButton({ label: L("B01_Dashboard_CreateCompany"), onClick: () => openCreateCompanyModal(), }), createButton({ label: L("B01_Dashboard_FindCompany"), variant: "ghost", onClick: () => openFindCompanyModal(), }), ); return wrap; } wrap.append( createTag(`${state.company.name} (${state.user.status})`, "success"), text(`${L("B01_Dashboard_Metric_ActiveUsers")}: ${state.company.user_count ?? 0}`), text(`${L("B01_Dashboard_Projects")}: ${state.company.project_count ?? 0}`), // 저장한 주소가 화면에 안 보여 「저장이 안 된다」로 읽혔다 (2026-09-13 사용자 지시). text(`${L("B01_Dashboard_Field_Address")}: ${state.company.business_address ?? "-"}`), ); // 회사 정보 수정 (2026-09-06 사용자 지시) — 관리자만 보인다. if (state.user.role !== "USER" && state.company) { const company = state.company; wrap.append( createButton({ label: "회사 정보 수정", variant: "ghost", onClick: () => openEditCompanyModal(company), }), ); } // 회사 대표 로고 — 등록 단계에서 받은 것을 여기서 바꾼다 (2026-09-02 사용자 확정). // 프로젝트가 따로 고르지 않으면 도면이 이 로고를 쓴다. if (state.user.role !== "USER") { const company = state.company; const slot = document.createElement("div"); void fetchCompanyAssets(company.id).then((assets) => { slot.append( createAssetField( "회사 로고 (도면 표제란)", "LOGO", assets, company.logo_asset_id ?? null, company.id, state.user, { onChange: (assetId) => setCompanyLogo(assetId, company.id).then(() => undefined) }, ).root, ); }); wrap.append(slot); } return wrap; } export function memberTable(members: Member[], currentUser: DashboardUser): HTMLElement { return table( [ L("B01_Dashboard_Table_Email"), L("B01_Dashboard_Table_Name"), L("B01_Dashboard_Table_Position"), L("B01_Dashboard_Table_Department"), L("B01_Dashboard_Table_Role"), L("B01_Dashboard_Table_Action"), ], members.map((member) => { const actionsEl = document.createElement("div"); actionsEl.className = "b01-dashboard__actions"; actionsEl.append( createButton({ label: L("Common_Btn_Edit"), variant: "ghost", onClick: () => openEditUserModal(currentUser, member), }), ); if (canChangeRole(currentUser, member)) { actionsEl.append( createButton({ label: L("B01_Dashboard_ChangeRole"), variant: "ghost", onClick: () => openChangeRoleModal(member), }), ); } if (canDeleteUser(currentUser, member)) { actionsEl.append( createButton({ label: L("B01_Dashboard_RemoveMember"), variant: "danger", onClick: () => openDeleteUserModal(member), }), ); } return [ text(member.email), text(member.name), text(member.position), text(member.department), text(member.role), actionsEl, ]; }), DASHBOARD_VISIBLE_ROWS, ); } export function joinRequestTable(requests: JoinRequest[], systemMode: boolean): HTMLElement { return table( [ L("B01_Dashboard_Table_Email"), ...(systemMode ? [L("B01_Dashboard_Table_Company")] : []), L("B01_Dashboard_Table_Requested"), L("B01_Dashboard_Table_Status"), L("B01_Dashboard_Table_Action"), ], requests.map((request) => [ text(request.user_email), ...(systemMode ? [text(request.company_name)] : []), text(formatDate(request.requested_at)), text(request.status), actionPair( () => onB01_JoinRequest_Process_Click(request.id, "APPROVE", systemMode), () => onB01_JoinRequest_Process_Click(request.id, "REJECT", systemMode), ), ]), DASHBOARD_VISIBLE_ROWS, ); } export function companyTable(companies: CompanyInfo[], user?: DashboardUser): HTMLElement { // 로고는 회사 등록 단계에서 받고 여기서 바꾼다 (2026-09-02 사용자 확정). const logoCell = (company: CompanyInfo): HTMLElement => { if (!user) return text(""); const button = createButton({ label: company.logo_asset_id ? "로고 변경…" : "로고 지정…", variant: "ghost", onClick: () => void openAssetPicker( "LOGO", company.id, user, company.logo_asset_id ?? null, async (id) => { await setCompanyLogo(id, company.id); company.logo_asset_id = id; button.textContent = id ? "로고 변경…" : "로고 지정…"; }, ), }); return button; }; return table( [ L("B01_Dashboard_Table_Company"), L("B01_Dashboard_Field_BusinessNumber"), L("B01_Dashboard_Table_Status"), "로고", L("B01_Dashboard_Table_Action"), ], companies.map((company) => [ text(company.name), text(company.business_registration_number), text(company.business_status), logoCell(company), user ? createButton({ label: L("Common_Btn_Edit"), variant: "ghost", onClick: () => openEditCompanyModal(company), }) : text(""), ]), DASHBOARD_VISIBLE_ROWS, ); } export async function onB01_JoinRequest_Process_Click( requestId: number, action: "APPROVE" | "REJECT", systemMode: boolean, ): Promise { await runRequest(() => systemMode && action === "APPROVE" ? import("./B01_Dashboard_Api_Fetch").then((api) => api.systemApproveJoinRequest(requestId)) : processJoinRequest(requestId, action), ); window.dispatchEvent(new HashChangeEvent("hashchange")); }