|
- "use client";
-
- import { NEXT_PUBLIC_API_URL } from "@/config/api";
- import { clientAuthFetch } from "@/app/utils/clientAuthFetch";
-
- export interface JobOrderListItem {
- id: number;
- code: string | null;
- planStart: string | null;
- itemCode: string | null;
- itemName: string | null;
- reqQty: number | null;
- stockInLineId: number | null;
- itemId: number | null;
- lotNo: string | null;
- }
-
- export interface PrinterStatusRequest {
- printerType: "dataflex" | "laser";
- printerIp?: string;
- printerPort?: number;
- }
-
- export interface PrinterStatusResponse {
- connected: boolean;
- message: string;
- }
-
- export interface OnPackQrDownloadRequest {
- jobOrders: {
- jobOrderId: number;
- itemCode: string;
- }[];
- }
-
- /** Readable message when ZIP download returns non-OK (plain text, JSON error body, or generic). */
- async function zipDownloadError(res: Response): Promise<Error> {
- const text = await res.text();
- const ct = res.headers.get("content-type") ?? "";
- if (ct.includes("application/json")) {
- try {
- const j = JSON.parse(text) as { message?: string; error?: string };
- if (typeof j.message === "string" && j.message.length > 0) {
- return new Error(j.message);
- }
- if (typeof j.error === "string" && j.error.length > 0) {
- return new Error(j.error);
- }
- } catch {
- /* ignore parse */
- }
- }
- if (text && text.length > 0 && text.length < 800 && !text.trim().startsWith("{")) {
- return new Error(text);
- }
- return new Error(`下載失敗(HTTP ${res.status})。請查看後端日誌或確認資料庫已執行 Liquibase 更新。`);
- }
-
- /**
- * Fetch job orders by plan date from GET /py/job-orders.
- * Client-side only; uses auth token from localStorage.
- */
- export async function fetchJobOrders(planStart: string): Promise<JobOrderListItem[]> {
- const url = `${NEXT_PUBLIC_API_URL}/py/job-orders?planStart=${encodeURIComponent(planStart)}`;
- const res = await clientAuthFetch(url, { method: "GET" });
- if (!res.ok) {
- throw new Error(`Failed to fetch job orders: ${res.status}`);
- }
- return res.json();
- }
-
- export async function checkPrinterStatus(
- request: PrinterStatusRequest,
- ): Promise<PrinterStatusResponse> {
- const url = `${NEXT_PUBLIC_API_URL}/plastic/check-printer`;
- const res = await clientAuthFetch(url, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- });
-
- const data = (await res.json()) as PrinterStatusResponse;
- if (!res.ok) {
- return data;
- }
-
- return data;
- }
-
- export async function downloadOnPackQrZip(
- request: OnPackQrDownloadRequest,
- ): Promise<Blob> {
- const url = `${NEXT_PUBLIC_API_URL}/plastic/download-onpack-qr`;
- const res = await clientAuthFetch(url, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- });
-
- if (!res.ok) {
- throw await zipDownloadError(res);
- }
-
- return res.blob();
- }
-
- /** OnPack2023 檸檬機 — text QR template (`onpack2030_2`), no separate .bmp */
- export async function downloadOnPackTextQrZip(
- request: OnPackQrDownloadRequest,
- ): Promise<Blob> {
- const url = `${NEXT_PUBLIC_API_URL}/plastic/download-onpack-qr-text`;
- const res = await clientAuthFetch(url, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- });
-
- if (!res.ok) {
- throw await zipDownloadError(res);
- }
-
- return res.blob();
- }
|