import { createApiClient } from "../lib/apiClient"; import type { LabelCreateInput, LabelBatchCreateInput, LabelBatchCreateResult, LabelDto, LabelGetListInput, LabelUpdateInput, PagedResultDto, } from "../types/label"; const api = createApiClient({ getToken: () => { try { return localStorage.getItem("access_token") ?? localStorage.getItem("token") ?? null; } catch { return null; } }, }); const PATH = "/label"; function parseIdList(v: unknown): string[] | undefined { if (!Array.isArray(v)) return undefined; return [...new Set(v.map((x) => String(x).trim()).filter(Boolean))]; } export function normalizeLabelDto(raw: unknown): LabelDto { const r = (raw && typeof raw === "object" ? raw : {}) as Record; const regionIds = parseIdList(r.regionIds ?? r.RegionIds); const groupIds = parseIdList(r.groupIds ?? r.GroupIds); const mergedRegionIds = [...new Set([...(regionIds ?? []), ...(groupIds ?? [])])]; const appliedRaw = r.appliedRegionType ?? r.AppliedRegionType; const appliedRegionType = typeof appliedRaw === "string" && appliedRaw.trim() ? appliedRaw.trim().toUpperCase() : mergedRegionIds.length > 0 ? "SPECIFIED" : null; const regionRaw = r.region ?? r.Region; const locationIds = parseIdList(r.locationIds ?? r.LocationIds) ?? []; const locationIdRaw = r.locationId ?? r.LocationId; const locationId = locationIdRaw != null && String(locationIdRaw).trim() ? String(locationIdRaw).trim() : locationIds[0] ?? null; const mergedLocationIds = [ ...new Set([ ...(locationId ? [locationId] : []), ...locationIds, ]), ]; return { ...(r as object), id: String(r.id ?? r.Id ?? r.labelCode ?? r.LabelCode ?? ""), locationId, locationIds: mergedLocationIds.length ? mergedLocationIds : locationIds, regionIds: mergedRegionIds.length ? mergedRegionIds : regionIds, groupIds: mergedRegionIds.length ? mergedRegionIds : groupIds, appliedRegionType: appliedRegionType as LabelDto["appliedRegionType"], region: typeof regionRaw === "string" ? regionRaw : null, } as LabelDto; } function locationBodyFromInput(input: LabelCreateInput | LabelUpdateInput): Record { const locationIds = [ ...new Set((input.locationIds ?? []).map((x) => String(x).trim()).filter(Boolean)), ]; const body: Record = {}; if (locationIds.length) { body.locationIds = locationIds; body.locationId = locationIds[0]; } return body; } function scopeBodyFromInput(input: LabelCreateInput | LabelUpdateInput): Record { const regionIds = [ ...new Set( [...(input.regionIds ?? []), ...(input.groupIds ?? [])] .map((x) => String(x).trim()) .filter(Boolean), ), ]; const applied = String(input.appliedRegionType ?? "").trim().toUpperCase() || (regionIds.length > 0 ? "SPECIFIED" : ""); const body: Record = {}; if (applied === "ALL" || applied === "SPECIFIED") { body.appliedRegionType = applied; } if (regionIds.length) { body.regionIds = regionIds; body.groupIds = regionIds; } else if (applied === "ALL") { body.regionIds = []; body.groupIds = []; } return body; } export async function getLabels(input: LabelGetListInput, signal?: AbortSignal): Promise> { const res = await api.requestJson & { items?: unknown[]; Items?: unknown[] }>({ path: PATH, method: "GET", query: { SkipCount: input.skipCount, MaxResultCount: input.maxResultCount, Sorting: input.sorting, Keyword: input.keyword, PartnerId: input.partnerId, GroupId: input.groupId, LocationId: input.locationId, ProductId: input.productId, LabelCategoryId: input.labelCategoryId, LabelTypeId: input.labelTypeId, TemplateCode: input.templateCode, State: input.state, }, signal, }); const itemsRaw = res.items ?? res.Items ?? []; const items = (Array.isArray(itemsRaw) ? itemsRaw : []).map((x) => normalizeLabelDto(x)); return { ...res, items, totalCount: res.totalCount ?? (res as { TotalCount?: number }).TotalCount ?? items.length, }; } export async function getLabel(labelCode: string, signal?: AbortSignal): Promise { const raw = await api.requestJson({ path: `${PATH}/${encodeURIComponent(labelCode)}`, method: "GET", signal, }); return normalizeLabelDto(raw); } export async function createLabel(input: LabelCreateInput): Promise { const raw = await api.requestJson({ path: PATH, method: "POST", body: { labelCode: String(input.labelCode ?? "").trim() || null, labelName: input.labelName, templateCode: input.templateCode, ...locationBodyFromInput(input), labelCategoryId: input.labelCategoryId, labelTypeId: String(input.labelTypeId ?? "").trim() || null, productIds: input.productIds, labelInfoJson: input.labelInfoJson, state: input.state ?? true, ...scopeBodyFromInput(input), }, }); return normalizeLabelDto(raw); } function normalizeBatchCreateResult(raw: unknown): LabelBatchCreateResult { const r = (raw && typeof raw === "object" ? raw : {}) as Record; const successItemsRaw = r.successItems ?? r.SuccessItems; const errorsRaw = r.errors ?? r.Errors; const successItems = Array.isArray(successItemsRaw) ? successItemsRaw.map((x) => { const it = (x && typeof x === "object" ? x : {}) as Record; return { rowNumber: typeof (it.rowNumber ?? it.RowNumber) === "number" ? (it.rowNumber ?? it.RowNumber) as number : null, labelCode: it.labelCode != null || it.LabelCode != null ? String(it.labelCode ?? it.LabelCode) : null, labelName: it.labelName != null || it.LabelName != null ? String(it.labelName ?? it.LabelName) : null, }; }) : []; const errors = Array.isArray(errorsRaw) ? errorsRaw.map((x) => { const it = (x && typeof x === "object" ? x : {}) as Record; return { rowNumber: typeof (it.rowNumber ?? it.RowNumber) === "number" ? (it.rowNumber ?? it.RowNumber) as number : null, labelName: it.labelName != null || it.LabelName != null ? String(it.labelName ?? it.LabelName) : null, message: it.message != null || it.Message != null ? String(it.message ?? it.Message) : null, }; }) : []; return { successCount: Number(r.successCount ?? r.SuccessCount ?? successItems.length) || 0, failCount: Number(r.failCount ?? r.FailCount ?? errors.length) || 0, successItems, errors, }; } export async function batchCreateLabels(input: LabelBatchCreateInput): Promise { const raw = await api.requestJson({ path: `${PATH}/batch-create`, method: "POST", body: { templateCode: input.templateCode, saveTemplateProductDefaults: input.saveTemplateProductDefaults ?? true, items: input.items.map((item) => { const locationIds = [ ...new Set((item.locationIds ?? []).map((x) => String(x).trim()).filter(Boolean)), ]; const regionIds = [ ...new Set( [...(item.regionIds ?? []), ...(item.groupIds ?? [])] .map((x) => String(x).trim()) .filter(Boolean), ), ]; const partnerIds = [ ...new Set( [ ...(item.partnerId ? [item.partnerId] : []), ...(item.partnerIds ?? []), ] .map((x) => String(x).trim()) .filter(Boolean), ), ]; return { labelCode: String(item.labelCode ?? "").trim() || null, labelName: item.labelName, labelCategoryId: item.labelCategoryId, labelTypeId: String(item.labelTypeId ?? "").trim() || null, productIds: item.productIds, locationIds, locationId: item.locationId ?? locationIds[0] ?? null, appliedRegionType: item.appliedRegionType, regionIds, groupIds: regionIds, partnerId: item.partnerId ?? partnerIds[0] ?? null, partnerIds, labelInfoJson: item.labelInfoJson ?? null, state: item.state ?? true, templateDefaultValues: item.templateDefaultValues ?? {}, templateDataValues: item.templateDataValues ?? {}, templateDateOffsets: item.templateDateOffsets ?? {}, nutritionByElementId: item.nutritionByElementId ?? {}, }; }), }, }); return normalizeBatchCreateResult(raw); } export async function updateLabel(labelCode: string, input: LabelUpdateInput): Promise { const raw = await api.requestJson({ path: `${PATH}/${encodeURIComponent(labelCode)}`, method: "PUT", body: { labelName: input.labelName, templateCode: input.templateCode, ...locationBodyFromInput(input), labelCategoryId: input.labelCategoryId, labelTypeId: input.labelTypeId, productIds: input.productIds, labelInfoJson: input.labelInfoJson, state: input.state ?? true, ...scopeBodyFromInput(input), }, }); return normalizeLabelDto(raw); } export async function deleteLabel(labelCode: string): Promise { await api.requestJson({ path: `${PATH}/${encodeURIComponent(labelCode)}`, method: "DELETE", }); }