labelService.ts 4.95 KB
import { createApiClient } from "../lib/apiClient";
import type {
  LabelCreateInput,
  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<string, unknown>;
  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;
  return {
    ...(r as object),
    id: String(r.id ?? r.Id ?? r.labelCode ?? r.LabelCode ?? ""),
    regionIds: mergedRegionIds.length ? mergedRegionIds : regionIds,
    groupIds: mergedRegionIds.length ? mergedRegionIds : groupIds,
    appliedRegionType: appliedRegionType as LabelDto["appliedRegionType"],
    region: typeof regionRaw === "string" ? regionRaw : null,
  } as LabelDto;
}

function scopeBodyFromInput(input: LabelCreateInput | LabelUpdateInput): Record<string, unknown> {
  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<string, unknown> = {};
  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<PagedResultDto<LabelDto>> {
  const res = await api.requestJson<PagedResultDto<LabelDto> & { 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<LabelDto> {
  const raw = await api.requestJson<unknown>({
    path: `${PATH}/${encodeURIComponent(labelCode)}`,
    method: "GET",
    signal,
  });
  return normalizeLabelDto(raw);
}

export async function createLabel(input: LabelCreateInput): Promise<LabelDto> {
  const raw = await api.requestJson<unknown>({
    path: PATH,
    method: "POST",
    body: {
      labelCode: String(input.labelCode ?? "").trim() || null,
      labelName: input.labelName,
      templateCode: input.templateCode,
      locationId: input.locationId,
      labelCategoryId: input.labelCategoryId,
      labelTypeId: input.labelTypeId,
      productIds: input.productIds,
      labelInfoJson: input.labelInfoJson,
      state: input.state ?? true,
      ...scopeBodyFromInput(input),
    },
  });
  return normalizeLabelDto(raw);
}

export async function updateLabel(labelCode: string, input: LabelUpdateInput): Promise<LabelDto> {
  const raw = await api.requestJson<unknown>({
    path: `${PATH}/${encodeURIComponent(labelCode)}`,
    method: "PUT",
    body: {
      labelName: input.labelName,
      templateCode: input.templateCode,
      locationId: input.locationId,
      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<void> {
  await api.requestJson<unknown>({
    path: `${PATH}/${encodeURIComponent(labelCode)}`,
    method: "DELETE",
  });
}