groupService.ts 4.04 KB
import { ApiError, createApiClient } from "../lib/apiClient";
import type {
  GroupCreateInput,
  GroupDetailDto,
  GroupGetListInput,
  GroupListResult,
  GroupUpdateInput,
} from "../types/group";

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

function getBaseUrl(): string {
  return import.meta.env.VITE_API_BASE_URL ?? "http://localhost:19001";
}

function getToken(): string | null {
  try {
    return localStorage.getItem("access_token") ?? localStorage.getItem("token") ?? null;
  } catch {
    return null;
  }
}

function joinUrl(baseUrl: string, path: string): string {
  const b = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
  const p = path.startsWith("/") ? path : `/${path}`;
  return `${b}${p}`;
}

function toQueryString(params: Record<string, unknown>): string {
  const qs = new URLSearchParams();
  for (const [k, v] of Object.entries(params)) {
    if (v === undefined || v === null || v === "") continue;
    if (typeof v === "boolean") {
      qs.set(k, v ? "true" : "false");
      continue;
    }
    qs.set(k, String(v));
  }
  const s = qs.toString();
  return s ? `?${s}` : "";
}

export async function getGroups(input: GroupGetListInput, signal?: AbortSignal): Promise<GroupListResult> {
  return api.requestJson<GroupListResult>({
    path: "/group",
    method: "GET",
    query: {
      SkipCount: input.skipCount,
      MaxResultCount: input.maxResultCount,
      Sorting: input.sorting,
      Keyword: input.keyword,
      PartnerId: input.partnerId,
      State: input.state,
    },
    signal,
  });
}

export async function getGroup(id: string, signal?: AbortSignal): Promise<GroupDetailDto> {
  return api.requestJson<GroupDetailDto>({
    path: `/group/${encodeURIComponent(id)}`,
    method: "GET",
    signal,
  });
}

export async function createGroup(input: GroupCreateInput, signal?: AbortSignal): Promise<GroupDetailDto> {
  return api.requestJson<GroupDetailDto>({
    path: "/group",
    method: "POST",
    body: {
      groupName: input.groupName.trim(),
      partnerId: input.partnerId.trim(),
      state: input.state ?? true,
    },
    signal,
  });
}

export async function updateGroup(id: string, input: GroupUpdateInput, signal?: AbortSignal): Promise<GroupDetailDto> {
  return api.requestJson<GroupDetailDto>({
    path: `/group/${encodeURIComponent(id)}`,
    method: "PUT",
    body: {
      groupName: input.groupName.trim(),
      partnerId: input.partnerId.trim(),
      state: input.state ?? true,
    },
    signal,
  });
}

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

export type GroupExportQuery = {
  keyword?: string;
  partnerId?: string;
  state?: boolean;
  sorting?: string;
};

/** GET /api/app/group/export-pdf */
export async function exportGroupsPdf(input: GroupExportQuery, signal?: AbortSignal): Promise<Blob> {
  const baseUrl = getBaseUrl();
  const token = getToken();
  const url = joinUrl(
    baseUrl,
    `/api/app/group/export-pdf${toQueryString({
      Keyword: input.keyword,
      PartnerId: input.partnerId,
      State: input.state,
      Sorting: input.sorting,
    })}`,
  );
  const headers: Record<string, string> = {};
  if (token) headers.Authorization = `Bearer ${token}`;
  const res = await fetch(url, { method: "GET", headers, signal });
  if (!res.ok) {
    const ct = res.headers.get("content-type") ?? "";
    let msg = "Export failed.";
    if (ct.includes("application/json")) {
      const payload = await res.json().catch(() => null);
      const m =
        (payload as { error?: { message?: string } })?.error?.message?.trim() ||
        (payload as { message?: string })?.message?.trim();
      if (m) msg = m;
    } else {
      const t = await res.text().catch(() => "");
      if (t.trim()) msg = t.trim();
    }
    throw new ApiError(msg, res.status, null);
  }
  return res.blob();
}