Spaces:
Sleeping
Sleeping
| import { clsx, type ClassValue } from "clsx"; | |
| import { twMerge } from "tailwind-merge"; | |
| import type { AvailableUseCase } from "@/types"; | |
| // ============================================================ | |
| // Tailwind class merging utility | |
| // ============================================================ | |
| export function cn(...inputs: ClassValue[]) { | |
| return twMerge(clsx(inputs)); | |
| } | |
| // ============================================================ | |
| // promptBuilder — mirrors Python promptBuilder() | |
| // ============================================================ | |
| export function promptBuilder( | |
| slicer_usecase: string, | |
| year: number, | |
| site: string, | |
| slicer_period: string, // e.g. "bulan 3" or "week 12" | |
| slicer_section: string, | |
| slicer_model: string, | |
| slicer_eqm: string | |
| ): string { | |
| const eqm = slicer_eqm.toUpperCase(); | |
| const model = slicer_model.toUpperCase(); | |
| const section = slicer_section.toUpperCase(); | |
| if (eqm !== "ALL") { | |
| return `Berikan report ${slicer_usecase} pada tahun ${year}, site ${site}, ${slicer_period}, equipment ${slicer_eqm}`; | |
| } else if (model !== "ALL") { | |
| return `Berikan report ${slicer_usecase} pada tahun ${year}, site ${site}, ${slicer_period}, section ${slicer_section} dan model ${slicer_model}`; | |
| } else if (section !== "ALL" && model === "ALL") { | |
| return `Berikan report ${slicer_usecase} pada tahun ${year}, site ${site}, ${slicer_period}, section ${slicer_section}, model ALL, dan equipment ALL`; | |
| } else { | |
| return `Berikan report ${slicer_usecase} pada tahun ${year}, site ${site}, ${slicer_period}, section ALL, model ALL, dan equipment ALL`; | |
| } | |
| } | |
| // ============================================================ | |
| // getWeekId — mirrors Python get_week_id() with saturday-friday scheme | |
| // ============================================================ | |
| export function getWeekId(date: Date, scheme: "saturday-friday" | "monday-sunday" | "sunday-saturday" = "saturday-friday"): number { | |
| let startOfWeek: Date; | |
| if (scheme === "monday-sunday") { | |
| const day = date.getDay(); // 0=Sun | |
| const diff = day === 0 ? -6 : 1 - day; | |
| startOfWeek = new Date(date); | |
| startOfWeek.setDate(date.getDate() + diff); | |
| } else if (scheme === "sunday-saturday") { | |
| const day = date.getDay(); | |
| startOfWeek = new Date(date); | |
| startOfWeek.setDate(date.getDate() - day); | |
| } else { | |
| // saturday-friday | |
| const day = date.getDay(); // 0=Sun,6=Sat | |
| const diff = (day + 1) % 7; // days since Saturday | |
| startOfWeek = new Date(date); | |
| startOfWeek.setDate(date.getDate() - diff); | |
| } | |
| const year = startOfWeek.getFullYear(); | |
| const firstDayOfYear = new Date(year, 0, 1); | |
| let firstWeekStart: Date; | |
| if (scheme === "saturday-friday") { | |
| const fd = firstDayOfYear.getDay(); | |
| const diff2 = (fd + 1) % 7; | |
| firstWeekStart = new Date(firstDayOfYear); | |
| firstWeekStart.setDate(firstDayOfYear.getDate() - diff2); | |
| if (firstWeekStart.getFullYear() < year) { | |
| const fd2 = firstDayOfYear.getDay(); | |
| firstWeekStart = new Date(firstDayOfYear); | |
| firstWeekStart.setDate(firstDayOfYear.getDate() + (7 - fd2) % 7); | |
| } | |
| } else { | |
| firstWeekStart = firstDayOfYear; | |
| } | |
| const msPerDay = 86400000; | |
| const weekNumber = Math.floor((startOfWeek.getTime() - firstWeekStart.getTime()) / (7 * msPerDay)) + 2; | |
| return parseInt(`${year}${String(weekNumber).padStart(2, "0")}`); | |
| } | |
| // ============================================================ | |
| // getCurrentWeek — returns current week number (1-52) | |
| // ============================================================ | |
| export function getCurrentWeek(): number { | |
| const now = new Date(); | |
| const weekId = getWeekId(now, "saturday-friday"); | |
| return parseInt(String(weekId).slice(-2)); | |
| } | |
| // ============================================================ | |
| // use_case_mapper_interface — mirrors Python mapper.py | |
| // ============================================================ | |
| export const useCaseMapperInterface: Record<AvailableUseCase, string> = { | |
| "pa performance": "pa performance", | |
| "bad actor": "pa performance", | |
| "pareto by frequency": "pareto", | |
| "pareto by duration": "pareto", | |
| "pareto by total equipment": "pareto", | |
| "inspection": "inspection", | |
| "backlog monitoring": "backlog", | |
| "planning": "planning", | |
| "execution and leadtime": "execution", | |
| }; | |
| export const useCaseOptions: AvailableUseCase[] = [ | |
| "pa performance", | |
| "bad actor", | |
| "pareto by frequency", | |
| "pareto by duration", | |
| "pareto by total equipment", | |
| "inspection", | |
| "backlog monitoring", | |
| "planning", | |
| "execution and leadtime", | |
| ]; | |
| // ============================================================ | |
| // Quick questions for Learning agent | |
| // ============================================================ | |
| export const quickQuestions = [ | |
| "Cara manual handling sparepart dengan berat lebih 18 kg?", | |
| "Cara mengeluarkan spare part dari peti kayu?", | |
| "Bagaimana cara recovery after rain yang efektif?", | |
| "Cara optimalisasi pemuatan hauler hingga vessel penuh?", | |
| "Apa saja daftar risiko bekerja di lapangan?" | |
| ]; | |
| // ============================================================ | |
| // Number of buffer messages to send to AI | |
| // ============================================================ | |
| export const N_BUFFER_MESSAGES = 10; | |
| // ============================================================ | |
| // Format a date string nicely | |
| // ============================================================ | |
| export function formatDate(dateStr: string): string { | |
| const date = new Date(dateStr); | |
| const now = new Date(); | |
| const diffMs = now.getTime() - date.getTime(); | |
| const diffDays = Math.floor(diffMs / 86400000); | |
| if (diffDays === 0) { | |
| return date.toLocaleTimeString("id-ID", { hour: "2-digit", minute: "2-digit" }); | |
| } else if (diffDays === 1) { | |
| return "Kemarin"; | |
| } else if (diffDays < 7) { | |
| return date.toLocaleDateString("id-ID", { weekday: "long" }); | |
| } else { | |
| return date.toLocaleDateString("id-ID", { day: "numeric", month: "short", year: "numeric" }); | |
| } | |
| } | |
| // ============================================================ | |
| // Generate short session title from first user message | |
| // ============================================================ | |
| export function generateSessionTitle(firstMessage: string): string { | |
| if (firstMessage.length <= 50) return firstMessage; | |
| return firstMessage.slice(0, 47) + "..."; | |
| } | |
| // ============================================================ | |
| // Whether this use case should hide Equipment dropdown | |
| // ============================================================ | |
| export function shouldHideEquipment(usecase: string): boolean { | |
| const lower = usecase.toLowerCase(); | |
| return lower === "bad actor" || lower === "pareto by total equipment"; | |
| } | |