import dayjs, { ConfigType, Dayjs } from "dayjs"; import { Uom } from "../api/settings/uom"; import { ListIterateeCustom, every, isArray, isNaN, isNull, isUndefined, take, } from "lodash"; import { Box, BoxProps } from "@mui/material"; export const manhourFormatter = new Intl.NumberFormat("en-HK", { minimumFractionDigits: 2, maximumFractionDigits: 2, }); export const moneyFormatter = new Intl.NumberFormat("en-HK", { style: "currency", currency: "HKD", }); export const decimalFormatter = new Intl.NumberFormat("en-HK", { minimumFractionDigits: 2, maximumFractionDigits: 5, }); export const integerFormatter = new Intl.NumberFormat("en-HK", {}); export const INPUT_DATE_FORMAT = "YYYY-MM-DD"; export const OUTPUT_DATE_FORMAT = "YYYY-MM-DD"; export const INPUT_TIME_FORMAT = "HH:mm:ss"; export const OUTPUT_TIME_FORMAT = "HH:mm:ss"; export const arrayToDayjs = (arr: ConfigType | (number | undefined)[], showTime: boolean = false) => { const isValidNumber = ( item: ListIterateeCustom, ): boolean => typeof item === "number" && !isNaN(item) && isFinite(item); let tempArr = arr; if (isArray(arr) && every(arr, isValidNumber) && arr.length >= 3) { // [year, month, day] // tempArr = take(arr, 3); tempArr = `${arr[0]?.toString().padStart(4, "0")}-${arr[1]?.toString().padStart(2, "0")}-${arr[2]?.toString().padStart(2, "0")}`; if (showTime) { // [year, month, day, hour, minute, second] tempArr += ` ${ arr[3]?.toString().padStart(2, "0")}:${ arr[4]?.toString().padStart(2, "0")}:${ (arr[5] ?? 0)?.toString().padStart(2, "0")}`; } } return dayjs(tempArr as ConfigType); }; export const arrayToDateString = (arr: ConfigType | (number | undefined)[], format: "input"|"output" = "output") => { if (format == "output") { return arrayToDayjs(arr).format(OUTPUT_DATE_FORMAT); } else { return arrayToDayjs(arr).format(INPUT_DATE_FORMAT); } }; export const arrayToDateTimeString = (arr: ConfigType | (number | undefined)[]) => { return arrayToDayjs(arr, true).format(`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`); }; export const dateStringToDayjs = (date: string) => { // Format: YYYY/MM/DD return dayjs(date, OUTPUT_DATE_FORMAT); }; export const dateTimeStringToDayjs = (dateTime: string) => { // Format: YYYY/MM/DD HH:mm:ss return dayjs(dateTime, `${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`); }; export const dayjsToDateString = (date: Dayjs, format: "input"|"output" = "output") => { if (format == "output") { return date.format(OUTPUT_DATE_FORMAT); } else { return date.format(INPUT_DATE_FORMAT); } }; export const dayjsToDateTimeString = (date: Dayjs, format: "input"|"output" = "input") => { if (format == "input") { return date.format(`${INPUT_DATE_FORMAT}T${INPUT_TIME_FORMAT}`); } else { return date.format(`${OUTPUT_DATE_FORMAT}T${OUTPUT_TIME_FORMAT}`); } }; export const dayjsToArray = (date: Dayjs) => { return [ date.year(), date.month() + 1, // Months are 0-based in Day.js, so add 1 date.date(), date.hour(), // (24-hour format) date.minute(), date.second(), ]; }; export const outputDateStringToInputDateString = (date: string) => { return dayjsToDateTimeString(dateStringToDayjs(date)) } export const stockInLineStatusMap: { [status: string]: number } = { draft: 0, pending: 1, qc: 2, determine1: 3, determine2: 4, determine3: 5, receiving: 6, received: 7, completed: 8, rejected: 9, }; export const stockOutLineStatusMap: { [status: string]: number } = { draft: 0, pending: 1, // waiting for qc determine1: 2, // waiting for qc "lot-change": 3, // waiting for qc // after qc = completed completed: 4, rejected: 5, }; export const pickOrderStatusMap: { [status: string]: number } = { pending: 1, consolidated: 2, released: 3, completed: 4, }; export const calculateWeight = (qty: number, uom: Uom) => { return qty * (uom.unit2Qty || 1) * (uom.unit3Qty || 1) * (uom.unit4Qty || 1); }; export const returnWeightUnit = (uom: Uom) => { return uom.unit4 || uom.unit3 || uom.unit2 || uom.unit1; }; /** * Formats departure time to HH:mm format * Handles array format [hours, minutes] from API and string formats */ export const formatDepartureTime = (time: string | number[] | String | Number | null | undefined): string => { if (!time) return "-"; // Handle array format [hours, minutes] from API if (Array.isArray(time) && time.length >= 2) { const hours = time[0]; const minutes = time[1]; if (typeof hours === 'number' && typeof minutes === 'number' && hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59) { return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`; } } const timeStr = String(time).trim(); if (!timeStr || timeStr === "-") return "-"; // If already in HH:mm format, return as is if (/^\d{1,2}:\d{2}$/.test(timeStr)) { const [hours, minutes] = timeStr.split(":"); return `${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}`; } return timeStr; }; /** * Normalizes store ID to display format (2F or 4F) */ export const normalizeStoreId = (storeId: string | number | String | Number | null | undefined): string => { if (!storeId) return "-"; const storeIdStr = typeof storeId === 'string' || storeId instanceof String ? String(storeId) : String(storeId); if (storeIdStr === "2" || storeIdStr === "2F") return "2F"; if (storeIdStr === "4" || storeIdStr === "4F") return "4F"; return storeIdStr; };