labelCategoryService.ts 6.31 KB
import { createApiClient } from "../lib/apiClient";
import { serializeButtonAppearanceForApi } from "../lib/categoryButtonAppearance";
import type {
  LabelCategoryCreateInput,
  LabelCategoryDto,
  LabelCategoryGetListInput,
  LabelCategoryUpdateInput,
  PagedResultDto,
} from "../types/labelCategory";

const api = createApiClient({
  getToken: () => {
    try {
      return localStorage.getItem("access_token") ?? localStorage.getItem("token") ?? null;
    } catch {
      return null;
    }
  },
});

const PATH = "/label-category";

function normalizeLabelCategoryDto(raw: unknown): LabelCategoryDto {
  const r = (raw && typeof raw === "object" ? raw : {}) as Record<string, unknown>;
  const parseIds = (v: unknown): string[] | undefined => {
    if (!Array.isArray(v)) return undefined;
    return [...new Set(v.map((x) => String(x).trim()).filter(Boolean))];
  };
  const groupIds = parseIds(r.groupIds ?? r.GroupIds ?? r.regionIds ?? r.RegionIds);
  const locationIds = parseIds(r.locationIds ?? r.LocationIds);
  const partnerIds = parseIds(r.partnerIds ?? r.PartnerIds ?? r.companyIds ?? r.CompanyIds);
  const noRaw = r.noOfLabels ?? r.NoOfLabels;
  const noOfLabels =
    typeof noRaw === "number" && Number.isFinite(noRaw)
      ? noRaw
      : typeof noRaw === "string" && noRaw.trim() !== "" && Number.isFinite(Number(noRaw))
        ? Number(noRaw)
        : null;
  const orderRaw = r.orderNum ?? r.OrderNum;
  const orderNum =
    typeof orderRaw === "number" && Number.isFinite(orderRaw)
      ? orderRaw
      : typeof orderRaw === "string" && orderRaw.trim() !== "" && Number.isFinite(Number(orderRaw))
        ? Number(orderRaw)
        : null;
  const companyRaw = r.company ?? r.Company;
  return {
    ...(r as object),
    id: String(r.id ?? r.Id ?? ""),
    appliedPartnerType: String(r.appliedPartnerType ?? r.AppliedPartnerType ?? "").trim() || undefined,
    partnerIds,
    companyIds: partnerIds,
    availabilityType: String(r.availabilityType ?? r.AvailabilityType ?? "").trim() || undefined,
    groupIds,
    regionIds: groupIds,
    locationIds,
    company: typeof companyRaw === "string" ? companyRaw : null,
    noOfLabels,
    orderNum,
  } as LabelCategoryDto;
}

function scopeBodyFromInput(input: LabelCategoryCreateInput): Record<string, unknown> {
  const groupIds = [
    ...new Set(
      [...(input.groupIds ?? []), ...(input.regionIds ?? [])]
        .map((x) => String(x).trim())
        .filter(Boolean),
    ),
  ];
  const locationIds = [
    ...new Set((input.locationIds ?? []).map((x) => String(x).trim()).filter(Boolean)),
  ];
  const partnerIds = [
    ...new Set(
      [...(input.partnerIds ?? []), ...(input.companyIds ?? [])]
        .map((x) => String(x).trim())
        .filter(Boolean),
    ),
  ];
  const body: Record<string, unknown> = {};
  const appliedPartnerType = String(input.appliedPartnerType ?? "").trim().toUpperCase();
  if (appliedPartnerType === "ALL" || appliedPartnerType === "SPECIFIED") {
    body.appliedPartnerType = appliedPartnerType;
  }
  if (partnerIds.length) {
    body.partnerIds = partnerIds;
    body.companyIds = partnerIds;
  }
  const availabilityType = String(input.availabilityType ?? "ALL").trim().toUpperCase() || "ALL";
  body.availabilityType = availabilityType;
  if (groupIds.length) {
    body.groupIds = groupIds;
    body.regionIds = groupIds;
  }
  if (locationIds.length) {
    body.locationIds = locationIds;
  }
  return body;
}

export async function getLabelCategories(input: LabelCategoryGetListInput, signal?: AbortSignal): Promise<PagedResultDto<LabelCategoryDto>> {
  const res = await api.requestJson<PagedResultDto<LabelCategoryDto> & { items?: unknown[]; Items?: unknown[] }>({
    path: PATH,
    method: "GET",
    query: {
      SkipCount: input.skipCount,
      MaxResultCount: input.maxResultCount,
      Sorting: input.sorting,
      Keyword: input.keyword,
      State: input.state,
      GroupId: input.groupId,
      LocationId: input.locationId,
    },
    signal,
  });
  const itemsRaw = res.items ?? res.Items ?? [];
  const items = (Array.isArray(itemsRaw) ? itemsRaw : []).map((x) => normalizeLabelCategoryDto(x));
  return { ...res, items, totalCount: res.totalCount ?? (res as { TotalCount?: number }).TotalCount ?? items.length };
}

export async function getLabelCategory(id: string, signal?: AbortSignal): Promise<LabelCategoryDto> {
  const raw = await api.requestJson<unknown>({
    path: `${PATH}/${encodeURIComponent(id)}`,
    method: "GET",
    signal,
  });
  return normalizeLabelCategoryDto(raw);
}

export async function createLabelCategory(input: LabelCategoryCreateInput): Promise<LabelCategoryDto> {
  return api.requestJson<LabelCategoryDto>({
    path: PATH,
    method: "POST",
    body: {
      categoryCode: String(input.categoryCode ?? "").trim() || null,
      categoryName: input.categoryName,
      categoryPhotoUrl: input.categoryPhotoUrl,
      displayText: (input.displayText ?? "").trim() || null,
      buttonBgColor: (input.buttonBgColor ?? "").trim() || null,
      buttonImageUrl: (input.buttonImageUrl ?? "").trim() || null,
      buttonAppearance: serializeButtonAppearanceForApi(input.buttonAppearance),
      buttonStyleJson: (input.buttonStyleJson ?? "").trim() || null,
      state: input.state ?? true,
      orderNum: input.orderNum,
      ...scopeBodyFromInput(input),
    },
  });
}

export async function updateLabelCategory(id: string, input: LabelCategoryUpdateInput): Promise<LabelCategoryDto> {
  const raw = await api.requestJson<unknown>({
    path: `${PATH}/${encodeURIComponent(id)}`,
    method: "PUT",
    body: {
      categoryCode: String(input.categoryCode ?? "").trim() || null,
      categoryName: input.categoryName,
      categoryPhotoUrl: input.categoryPhotoUrl,
      displayText: (input.displayText ?? "").trim() || null,
      buttonBgColor: (input.buttonBgColor ?? "").trim() || null,
      buttonImageUrl: (input.buttonImageUrl ?? "").trim() || null,
      buttonAppearance: serializeButtonAppearanceForApi(input.buttonAppearance),
      buttonStyleJson: (input.buttonStyleJson ?? "").trim() || null,
      state: input.state ?? true,
      orderNum: input.orderNum,
      ...scopeBodyFromInput(input),
    },
  });
  return normalizeLabelCategoryDto(raw);
}

export async function deleteLabelCategory(id: string): Promise<void> {
  await api.requestJson<unknown>({
    path: `${PATH}/${encodeURIComponent(id)}`,
    method: "DELETE",
  });
}