@optifye/dashboard-core 6.11.35 → 6.11.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +505 -209
- package/dist/index.mjs +505 -209
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1667,6 +1667,7 @@ var DEFAULT_SHIFT_DATA = {
|
|
|
1667
1667
|
efficiency: 0,
|
|
1668
1668
|
output: 0,
|
|
1669
1669
|
cycleTime: 0,
|
|
1670
|
+
idealCycleTime: 0,
|
|
1670
1671
|
pph: 0,
|
|
1671
1672
|
pphThreshold: 0,
|
|
1672
1673
|
idealOutput: 0,
|
|
@@ -4513,6 +4514,7 @@ var dashboardService = {
|
|
|
4513
4514
|
avg_efficiency: item.avg_efficiency || 0,
|
|
4514
4515
|
total_output: item.total_output || 0,
|
|
4515
4516
|
avg_cycle_time: item.avg_cycle_time || 0,
|
|
4517
|
+
ideal_cycle_time: item.ideal_cycle_time ?? 0,
|
|
4516
4518
|
ideal_output: item.ideal_output || 0,
|
|
4517
4519
|
total_day_output: item.total_day_output ?? item.ideal_output ?? 0,
|
|
4518
4520
|
avg_pph: item.avg_pph || 0,
|
|
@@ -17309,7 +17311,7 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17309
17311
|
const [isLoading, setIsLoading] = React143.useState(true);
|
|
17310
17312
|
const [error, setError] = React143.useState(null);
|
|
17311
17313
|
const supabase = useSupabase();
|
|
17312
|
-
const
|
|
17314
|
+
const parseTimeToMinutes5 = (timeStr) => {
|
|
17313
17315
|
const [hours, minutes] = timeStr.split(":").map(Number);
|
|
17314
17316
|
return hours * 60 + minutes;
|
|
17315
17317
|
};
|
|
@@ -17318,8 +17320,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17318
17320
|
return now4.getHours() * 60 + now4.getMinutes();
|
|
17319
17321
|
};
|
|
17320
17322
|
const isTimeInBreak = (breakStart, breakEnd, currentMinutes) => {
|
|
17321
|
-
const startMinutes =
|
|
17322
|
-
const endMinutes =
|
|
17323
|
+
const startMinutes = parseTimeToMinutes5(breakStart);
|
|
17324
|
+
const endMinutes = parseTimeToMinutes5(breakEnd);
|
|
17323
17325
|
if (endMinutes < startMinutes) {
|
|
17324
17326
|
return currentMinutes >= startMinutes || currentMinutes < endMinutes;
|
|
17325
17327
|
} else {
|
|
@@ -17327,8 +17329,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17327
17329
|
}
|
|
17328
17330
|
};
|
|
17329
17331
|
const calculateBreakProgress = (breakStart, breakEnd, currentMinutes) => {
|
|
17330
|
-
const startMinutes =
|
|
17331
|
-
const endMinutes =
|
|
17332
|
+
const startMinutes = parseTimeToMinutes5(breakStart);
|
|
17333
|
+
const endMinutes = parseTimeToMinutes5(breakEnd);
|
|
17332
17334
|
let elapsedMinutes = 0;
|
|
17333
17335
|
let remainingMinutes = 0;
|
|
17334
17336
|
if (endMinutes < startMinutes) {
|
|
@@ -17346,8 +17348,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17346
17348
|
return { elapsedMinutes, remainingMinutes };
|
|
17347
17349
|
};
|
|
17348
17350
|
const isTimeInShift = (startTime, endTime, currentMinutes) => {
|
|
17349
|
-
const startMinutes =
|
|
17350
|
-
const endMinutes =
|
|
17351
|
+
const startMinutes = parseTimeToMinutes5(startTime);
|
|
17352
|
+
const endMinutes = parseTimeToMinutes5(endTime);
|
|
17351
17353
|
if (endMinutes < startMinutes) {
|
|
17352
17354
|
return currentMinutes >= startMinutes || currentMinutes < endMinutes;
|
|
17353
17355
|
} else {
|
|
@@ -17407,8 +17409,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17407
17409
|
const endTime = breakItem.end || breakItem.endTime || "00:00";
|
|
17408
17410
|
let duration = breakItem.duration || 0;
|
|
17409
17411
|
if (!duration || duration === 0) {
|
|
17410
|
-
const startMinutes =
|
|
17411
|
-
const endMinutes =
|
|
17412
|
+
const startMinutes = parseTimeToMinutes5(startTime);
|
|
17413
|
+
const endMinutes = parseTimeToMinutes5(endTime);
|
|
17412
17414
|
duration = endMinutes < startMinutes ? endMinutes + 24 * 60 - startMinutes : endMinutes - startMinutes;
|
|
17413
17415
|
}
|
|
17414
17416
|
return {
|
|
@@ -17424,8 +17426,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17424
17426
|
const endTime = breakItem.end || breakItem.endTime || "00:00";
|
|
17425
17427
|
let duration = breakItem.duration || 0;
|
|
17426
17428
|
if (!duration || duration === 0) {
|
|
17427
|
-
const startMinutes =
|
|
17428
|
-
const endMinutes =
|
|
17429
|
+
const startMinutes = parseTimeToMinutes5(startTime);
|
|
17430
|
+
const endMinutes = parseTimeToMinutes5(endTime);
|
|
17429
17431
|
duration = endMinutes < startMinutes ? endMinutes + 24 * 60 - startMinutes : endMinutes - startMinutes;
|
|
17430
17432
|
}
|
|
17431
17433
|
return {
|
|
@@ -33440,13 +33442,13 @@ var CycleTimeOverTimeChart = ({
|
|
|
33440
33442
|
observer.observe(containerRef.current);
|
|
33441
33443
|
return () => observer.disconnect();
|
|
33442
33444
|
}, []);
|
|
33443
|
-
const
|
|
33445
|
+
const parseTimeToMinutes5 = (value) => {
|
|
33444
33446
|
const [hours, minutes] = value.split(":").map(Number);
|
|
33445
33447
|
if (!Number.isFinite(hours) || !Number.isFinite(minutes)) return 0;
|
|
33446
33448
|
return hours * 60 + minutes;
|
|
33447
33449
|
};
|
|
33448
33450
|
const formatHourLabel = (slotIndex) => {
|
|
33449
|
-
const baseMinutes =
|
|
33451
|
+
const baseMinutes = parseTimeToMinutes5(shiftStart);
|
|
33450
33452
|
const absoluteMinutes = baseMinutes + slotIndex * 60;
|
|
33451
33453
|
const hour24 = Math.floor(absoluteMinutes % (24 * 60) / 60);
|
|
33452
33454
|
const ampm = hour24 >= 12 ? "PM" : "AM";
|
|
@@ -47903,6 +47905,7 @@ var LineMonthlyPdfGenerator = ({
|
|
|
47903
47905
|
rangeEnd,
|
|
47904
47906
|
selectedShiftId,
|
|
47905
47907
|
availableShifts,
|
|
47908
|
+
lineAssembly = false,
|
|
47906
47909
|
compact = false,
|
|
47907
47910
|
className
|
|
47908
47911
|
}) => {
|
|
@@ -48186,8 +48189,8 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48186
48189
|
timeZone: "Asia/Kolkata"
|
|
48187
48190
|
});
|
|
48188
48191
|
doc.text(dateStr, 25, yPos);
|
|
48189
|
-
doc.text(`${shift.
|
|
48190
|
-
doc.text(`${shift.
|
|
48192
|
+
doc.text(`${Math.round(shift.output || 0)}`, 60, yPos);
|
|
48193
|
+
doc.text(`${Math.round(shift.idealOutput || 0)}`, 95, yPos);
|
|
48191
48194
|
doc.text(`${shift.avg_efficiency.toFixed(1)}%`, 135, yPos);
|
|
48192
48195
|
const statusColor = getEfficiencyColor(shift.avg_efficiency, effectiveLegend);
|
|
48193
48196
|
if (statusColor === "green") {
|
|
@@ -48217,6 +48220,8 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48217
48220
|
doc.setTextColor(0, 0, 0);
|
|
48218
48221
|
}
|
|
48219
48222
|
const poorestWorkspaces = underperformingWorkspaces[selectedShiftId] || [];
|
|
48223
|
+
const isCycleTimeWorkspace = (workspace) => workspace.metric_mode === "cycle_time" || lineAssembly && (workspace.avg_cycle_time !== void 0 || workspace.ideal_cycle_time !== void 0 || workspace.cycle_ratio !== void 0);
|
|
48224
|
+
const showCycleTimePoorestPerformers = !isUptimeMode && poorestWorkspaces.some(isCycleTimeWorkspace);
|
|
48220
48225
|
if (poorestWorkspaces && poorestWorkspaces.length > 0) {
|
|
48221
48226
|
doc.addPage();
|
|
48222
48227
|
doc.setFontSize(14);
|
|
@@ -48242,7 +48247,11 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48242
48247
|
doc.setFillColor(245, 245, 245);
|
|
48243
48248
|
doc.roundedRect(20, 45, 170, 8, 1, 1, "F");
|
|
48244
48249
|
doc.text("Workspace", 25, 50);
|
|
48245
|
-
doc.text(
|
|
48250
|
+
doc.text(
|
|
48251
|
+
isUptimeMode ? "Avg Utilization" : showCycleTimePoorestPerformers ? "Cycle Time" : "Avg Efficiency",
|
|
48252
|
+
120,
|
|
48253
|
+
50
|
|
48254
|
+
);
|
|
48246
48255
|
doc.text("Last 5 Days", 160, 50);
|
|
48247
48256
|
doc.setLineWidth(0.2);
|
|
48248
48257
|
doc.setDrawColor(220, 220, 220);
|
|
@@ -48261,7 +48270,16 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48261
48270
|
);
|
|
48262
48271
|
const workspaceName = rawWorkspaceName.length > 30 ? `${rawWorkspaceName.substring(0, 27)}...` : rawWorkspaceName;
|
|
48263
48272
|
doc.text(workspaceName, 25, yPos2);
|
|
48264
|
-
|
|
48273
|
+
if (isUptimeMode) {
|
|
48274
|
+
doc.text(`${(workspace.avg_efficiency || 0).toFixed(1)}%`, 120, yPos2);
|
|
48275
|
+
} else if (isCycleTimeWorkspace(workspace)) {
|
|
48276
|
+
const actualCycleTime = Number.isFinite(workspace.avg_cycle_time) ? Number(workspace.avg_cycle_time) : null;
|
|
48277
|
+
const targetCycleTime = Number.isFinite(workspace.ideal_cycle_time) ? Number(workspace.ideal_cycle_time) : null;
|
|
48278
|
+
const cycleTimeText = actualCycleTime !== null ? `${actualCycleTime.toFixed(1)}s${targetCycleTime !== null ? ` / ${targetCycleTime.toFixed(1)}s` : ""}` : "-";
|
|
48279
|
+
doc.text(cycleTimeText, 120, yPos2);
|
|
48280
|
+
} else {
|
|
48281
|
+
doc.text(`${(workspace.avg_efficiency || 0).toFixed(1)}%`, 120, yPos2);
|
|
48282
|
+
}
|
|
48265
48283
|
const squareSize = 3;
|
|
48266
48284
|
const squareSpacing = 1;
|
|
48267
48285
|
let squareX = 160;
|
|
@@ -48356,12 +48374,279 @@ Underperforming Workspaces: ${lineInfo.metrics.underperforming_workspaces} / ${l
|
|
|
48356
48374
|
}
|
|
48357
48375
|
);
|
|
48358
48376
|
};
|
|
48377
|
+
|
|
48378
|
+
// src/lib/utils/hourlyTargets.ts
|
|
48379
|
+
var stripSeconds2 = (timeStr) => timeStr ? timeStr.slice(0, 5) : timeStr;
|
|
48380
|
+
var MINUTES_PER_DAY = 24 * 60;
|
|
48381
|
+
var parseTimeToMinutes2 = (timeString) => {
|
|
48382
|
+
const normalized = stripSeconds2(timeString || "");
|
|
48383
|
+
if (!normalized || !/^[0-2]\d:[0-5]\d$/.test(normalized)) return Number.NaN;
|
|
48384
|
+
const [hours, minutes] = normalized.split(":").map(Number);
|
|
48385
|
+
return hours * 60 + minutes;
|
|
48386
|
+
};
|
|
48387
|
+
var normalizeBreaksOnShiftTimeline = (shiftStart, breaks) => {
|
|
48388
|
+
const shiftStartMinutes = parseTimeToMinutes2(shiftStart);
|
|
48389
|
+
if (!Number.isFinite(shiftStartMinutes)) return [];
|
|
48390
|
+
const normalizedBreaks = [];
|
|
48391
|
+
for (const entry of breaks) {
|
|
48392
|
+
const startRaw = parseTimeToMinutes2(entry.startTime);
|
|
48393
|
+
const endRaw = parseTimeToMinutes2(entry.endTime);
|
|
48394
|
+
if (!Number.isFinite(startRaw) || !Number.isFinite(endRaw)) continue;
|
|
48395
|
+
let start = startRaw;
|
|
48396
|
+
let end = endRaw;
|
|
48397
|
+
if (end <= start) {
|
|
48398
|
+
end += 24 * 60;
|
|
48399
|
+
}
|
|
48400
|
+
if (start < shiftStartMinutes) {
|
|
48401
|
+
start += 24 * 60;
|
|
48402
|
+
end += 24 * 60;
|
|
48403
|
+
}
|
|
48404
|
+
const label = entry.remarks?.trim() || "Break";
|
|
48405
|
+
normalizedBreaks.push({ start, end, label });
|
|
48406
|
+
}
|
|
48407
|
+
return normalizedBreaks;
|
|
48408
|
+
};
|
|
48409
|
+
var roundTarget = (value, mode) => {
|
|
48410
|
+
if (!Number.isFinite(value)) return 0;
|
|
48411
|
+
switch (mode) {
|
|
48412
|
+
case "floor":
|
|
48413
|
+
return Math.floor(value);
|
|
48414
|
+
case "ceil":
|
|
48415
|
+
return Math.ceil(value);
|
|
48416
|
+
case "round":
|
|
48417
|
+
default:
|
|
48418
|
+
return Math.round(value);
|
|
48419
|
+
}
|
|
48420
|
+
};
|
|
48421
|
+
var formatDateKey = (date) => {
|
|
48422
|
+
const year = date.getUTCFullYear();
|
|
48423
|
+
const month = `${date.getUTCMonth() + 1}`.padStart(2, "0");
|
|
48424
|
+
const day = `${date.getUTCDate()}`.padStart(2, "0");
|
|
48425
|
+
return `${year}-${month}-${day}`;
|
|
48426
|
+
};
|
|
48427
|
+
var shiftDateKey = (dateKey, deltaDays) => {
|
|
48428
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
48429
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
48430
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
48431
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
48432
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
48433
|
+
date.setUTCDate(date.getUTCDate() + deltaDays);
|
|
48434
|
+
return formatDateKey(date);
|
|
48435
|
+
};
|
|
48436
|
+
var getZonedNowSnapshot = (timeZone, now4) => {
|
|
48437
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
48438
|
+
timeZone,
|
|
48439
|
+
year: "numeric",
|
|
48440
|
+
month: "2-digit",
|
|
48441
|
+
day: "2-digit",
|
|
48442
|
+
hour: "2-digit",
|
|
48443
|
+
minute: "2-digit",
|
|
48444
|
+
hourCycle: "h23"
|
|
48445
|
+
});
|
|
48446
|
+
const parts = formatter.formatToParts(now4).reduce((acc, part) => {
|
|
48447
|
+
if (part.type !== "literal") {
|
|
48448
|
+
acc[part.type] = part.value;
|
|
48449
|
+
}
|
|
48450
|
+
return acc;
|
|
48451
|
+
}, {});
|
|
48452
|
+
const year = Number(parts.year);
|
|
48453
|
+
const month = Number(parts.month);
|
|
48454
|
+
const day = Number(parts.day);
|
|
48455
|
+
const hour = Number(parts.hour);
|
|
48456
|
+
const minute = Number(parts.minute);
|
|
48457
|
+
return {
|
|
48458
|
+
dateKey: `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`,
|
|
48459
|
+
minutesOfDay: (Number.isFinite(hour) ? hour : 0) * 60 + (Number.isFinite(minute) ? minute : 0)
|
|
48460
|
+
};
|
|
48461
|
+
};
|
|
48462
|
+
var getDateKeyInTimeZone = (timeZone, now4 = /* @__PURE__ */ new Date()) => getZonedNowSnapshot(timeZone, now4).dateKey;
|
|
48463
|
+
var buildHourlyIntervals = ({
|
|
48464
|
+
shiftStart,
|
|
48465
|
+
shiftEnd,
|
|
48466
|
+
bucketMinutes = 60,
|
|
48467
|
+
fallbackHours = 11
|
|
48468
|
+
}) => {
|
|
48469
|
+
const startMinutes = parseTimeToMinutes2(shiftStart);
|
|
48470
|
+
if (!Number.isFinite(startMinutes)) return [];
|
|
48471
|
+
const bucket = Number.isFinite(bucketMinutes) && bucketMinutes > 0 ? Math.floor(bucketMinutes) : 60;
|
|
48472
|
+
let totalMinutes;
|
|
48473
|
+
const endRaw = shiftEnd ? parseTimeToMinutes2(shiftEnd) : Number.NaN;
|
|
48474
|
+
if (!Number.isFinite(endRaw)) {
|
|
48475
|
+
totalMinutes = Math.max(0, Math.round(fallbackHours * 60));
|
|
48476
|
+
} else {
|
|
48477
|
+
let endMinutes = endRaw;
|
|
48478
|
+
if (endMinutes <= startMinutes) {
|
|
48479
|
+
endMinutes += 24 * 60;
|
|
48480
|
+
}
|
|
48481
|
+
totalMinutes = endMinutes - startMinutes;
|
|
48482
|
+
}
|
|
48483
|
+
if (!Number.isFinite(totalMinutes) || totalMinutes <= 0) return [];
|
|
48484
|
+
const count = Math.ceil(totalMinutes / bucket);
|
|
48485
|
+
const shiftEndMinutes = startMinutes + totalMinutes;
|
|
48486
|
+
const intervals = [];
|
|
48487
|
+
for (let i = 0; i < count; i += 1) {
|
|
48488
|
+
const start = startMinutes + i * bucket;
|
|
48489
|
+
const end = Math.min(start + bucket, shiftEndMinutes);
|
|
48490
|
+
const minutes = Math.max(0, end - start);
|
|
48491
|
+
if (minutes <= 0) continue;
|
|
48492
|
+
intervals.push({ start, end, minutes });
|
|
48493
|
+
}
|
|
48494
|
+
return intervals;
|
|
48495
|
+
};
|
|
48496
|
+
var computeBreakMinutesByInterval = ({
|
|
48497
|
+
intervals,
|
|
48498
|
+
shiftStart,
|
|
48499
|
+
breaks
|
|
48500
|
+
}) => {
|
|
48501
|
+
if (!intervals.length || !breaks.length) return intervals.map(() => 0);
|
|
48502
|
+
const normalizedBreaks = normalizeBreaksOnShiftTimeline(shiftStart, breaks);
|
|
48503
|
+
return intervals.map((interval) => {
|
|
48504
|
+
if (!normalizedBreaks.length) return 0;
|
|
48505
|
+
let total = 0;
|
|
48506
|
+
for (const brk of normalizedBreaks) {
|
|
48507
|
+
const overlap = Math.max(0, Math.min(interval.end, brk.end) - Math.max(interval.start, brk.start));
|
|
48508
|
+
total += overlap;
|
|
48509
|
+
if (total >= interval.minutes) return interval.minutes;
|
|
48510
|
+
}
|
|
48511
|
+
return Math.min(interval.minutes, total);
|
|
48512
|
+
});
|
|
48513
|
+
};
|
|
48514
|
+
var computeBreakRemarksByInterval = ({
|
|
48515
|
+
intervals,
|
|
48516
|
+
shiftStart,
|
|
48517
|
+
breaks
|
|
48518
|
+
}) => {
|
|
48519
|
+
if (!intervals.length || !breaks.length) return intervals.map(() => "");
|
|
48520
|
+
const normalizedBreaks = normalizeBreaksOnShiftTimeline(shiftStart, breaks);
|
|
48521
|
+
return intervals.map((interval) => {
|
|
48522
|
+
const labels = normalizedBreaks.filter((brk) => Math.max(0, Math.min(interval.end, brk.end) - Math.max(interval.start, brk.start)) > 0).map((brk) => brk.label).filter((label, index, values) => label && values.indexOf(label) === index);
|
|
48523
|
+
return labels.join(", ");
|
|
48524
|
+
});
|
|
48525
|
+
};
|
|
48526
|
+
var computeEffectiveTargets = ({
|
|
48527
|
+
intervals,
|
|
48528
|
+
breakMinutes,
|
|
48529
|
+
pphThreshold,
|
|
48530
|
+
rounding = "round"
|
|
48531
|
+
}) => {
|
|
48532
|
+
return intervals.map((interval, idx) => {
|
|
48533
|
+
const intervalMinutes = Number(interval?.minutes) || 0;
|
|
48534
|
+
const breakMins = Number(breakMinutes?.[idx]) || 0;
|
|
48535
|
+
const plannedWorkMinutes = Math.max(0, intervalMinutes - breakMins);
|
|
48536
|
+
if (!Number.isFinite(pphThreshold) || pphThreshold <= 0) return 0;
|
|
48537
|
+
if (plannedWorkMinutes <= 0) return 0;
|
|
48538
|
+
return roundTarget(pphThreshold * plannedWorkMinutes / 60, rounding);
|
|
48539
|
+
});
|
|
48540
|
+
};
|
|
48541
|
+
var buildHourlyTargetPlan = ({
|
|
48542
|
+
shiftStart,
|
|
48543
|
+
shiftEnd,
|
|
48544
|
+
breaks = [],
|
|
48545
|
+
pphThreshold,
|
|
48546
|
+
bucketMinutes = 60,
|
|
48547
|
+
fallbackHours = 11,
|
|
48548
|
+
rounding = "round"
|
|
48549
|
+
}) => {
|
|
48550
|
+
const intervals = buildHourlyIntervals({
|
|
48551
|
+
shiftStart,
|
|
48552
|
+
shiftEnd,
|
|
48553
|
+
bucketMinutes,
|
|
48554
|
+
fallbackHours
|
|
48555
|
+
});
|
|
48556
|
+
const breakMinutes = computeBreakMinutesByInterval({
|
|
48557
|
+
intervals,
|
|
48558
|
+
shiftStart,
|
|
48559
|
+
breaks
|
|
48560
|
+
});
|
|
48561
|
+
const breakRemarks = computeBreakRemarksByInterval({
|
|
48562
|
+
intervals,
|
|
48563
|
+
shiftStart,
|
|
48564
|
+
breaks
|
|
48565
|
+
});
|
|
48566
|
+
const productiveMinutes = intervals.map((interval, idx) => Math.max(0, (Number(interval?.minutes) || 0) - (Number(breakMinutes[idx]) || 0)));
|
|
48567
|
+
const targets = computeEffectiveTargets({
|
|
48568
|
+
intervals,
|
|
48569
|
+
breakMinutes,
|
|
48570
|
+
pphThreshold,
|
|
48571
|
+
rounding
|
|
48572
|
+
});
|
|
48573
|
+
return {
|
|
48574
|
+
intervals,
|
|
48575
|
+
breakMinutes,
|
|
48576
|
+
breakRemarks,
|
|
48577
|
+
productiveMinutes,
|
|
48578
|
+
targets
|
|
48579
|
+
};
|
|
48580
|
+
};
|
|
48581
|
+
var isHourlyIntervalComplete = ({
|
|
48582
|
+
reportDate,
|
|
48583
|
+
shiftStart,
|
|
48584
|
+
shiftEnd,
|
|
48585
|
+
interval,
|
|
48586
|
+
timeZone = "Asia/Kolkata",
|
|
48587
|
+
now: now4 = /* @__PURE__ */ new Date()
|
|
48588
|
+
}) => {
|
|
48589
|
+
if (!reportDate) return true;
|
|
48590
|
+
const snapshot = getZonedNowSnapshot(timeZone, now4);
|
|
48591
|
+
const shiftStartMinutes = parseTimeToMinutes2(shiftStart);
|
|
48592
|
+
const shiftEndMinutes = shiftEnd ? parseTimeToMinutes2(shiftEnd) : Number.NaN;
|
|
48593
|
+
const wrapsMidnight = Number.isFinite(shiftStartMinutes) && Number.isFinite(shiftEndMinutes) && shiftEndMinutes <= shiftStartMinutes;
|
|
48594
|
+
if (reportDate === snapshot.dateKey) {
|
|
48595
|
+
return interval.end <= snapshot.minutesOfDay;
|
|
48596
|
+
}
|
|
48597
|
+
if (wrapsMidnight && reportDate === shiftDateKey(snapshot.dateKey, -1)) {
|
|
48598
|
+
return interval.end <= snapshot.minutesOfDay + MINUTES_PER_DAY;
|
|
48599
|
+
}
|
|
48600
|
+
return reportDate < snapshot.dateKey;
|
|
48601
|
+
};
|
|
48602
|
+
var isShiftInProgressForReportDate = ({
|
|
48603
|
+
reportDate,
|
|
48604
|
+
shiftStart,
|
|
48605
|
+
shiftEnd,
|
|
48606
|
+
timeZone = "Asia/Kolkata",
|
|
48607
|
+
now: now4 = /* @__PURE__ */ new Date()
|
|
48608
|
+
}) => {
|
|
48609
|
+
if (!reportDate || !shiftStart || !shiftEnd) return false;
|
|
48610
|
+
const shiftStartMinutes = parseTimeToMinutes2(shiftStart);
|
|
48611
|
+
const shiftEndMinutesRaw = parseTimeToMinutes2(shiftEnd);
|
|
48612
|
+
if (!Number.isFinite(shiftStartMinutes) || !Number.isFinite(shiftEndMinutesRaw)) {
|
|
48613
|
+
return false;
|
|
48614
|
+
}
|
|
48615
|
+
let shiftEndMinutes = shiftEndMinutesRaw;
|
|
48616
|
+
const wrapsMidnight = shiftEndMinutes <= shiftStartMinutes;
|
|
48617
|
+
if (wrapsMidnight) {
|
|
48618
|
+
shiftEndMinutes += MINUTES_PER_DAY;
|
|
48619
|
+
}
|
|
48620
|
+
const snapshot = getZonedNowSnapshot(timeZone, now4);
|
|
48621
|
+
let currentMinutes = null;
|
|
48622
|
+
if (reportDate === snapshot.dateKey) {
|
|
48623
|
+
currentMinutes = snapshot.minutesOfDay;
|
|
48624
|
+
} else if (wrapsMidnight && reportDate === shiftDateKey(snapshot.dateKey, -1)) {
|
|
48625
|
+
currentMinutes = snapshot.minutesOfDay + MINUTES_PER_DAY;
|
|
48626
|
+
}
|
|
48627
|
+
if (currentMinutes === null) {
|
|
48628
|
+
return false;
|
|
48629
|
+
}
|
|
48630
|
+
return shiftStartMinutes <= currentMinutes && currentMinutes < shiftEndMinutes;
|
|
48631
|
+
};
|
|
48632
|
+
var formatOperationalDateKey = (dateKey, options) => {
|
|
48633
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
48634
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
48635
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
48636
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
48637
|
+
return new Date(Date.UTC(year, month - 1, day, 12)).toLocaleDateString("en-IN", {
|
|
48638
|
+
...options,
|
|
48639
|
+
timeZone: "UTC"
|
|
48640
|
+
});
|
|
48641
|
+
};
|
|
48359
48642
|
var LinePdfGenerator = ({
|
|
48360
48643
|
lineInfo,
|
|
48361
48644
|
workspaceData,
|
|
48362
48645
|
issueResolutionSummary,
|
|
48363
48646
|
shiftName,
|
|
48364
|
-
className
|
|
48647
|
+
className,
|
|
48648
|
+
shiftBreaks = [],
|
|
48649
|
+
reportTimezone = "Asia/Kolkata"
|
|
48365
48650
|
}) => {
|
|
48366
48651
|
const [isGenerating, setIsGenerating] = React143.useState(false);
|
|
48367
48652
|
const formatResolutionDuration2 = (seconds) => {
|
|
@@ -48388,7 +48673,7 @@ var LinePdfGenerator = ({
|
|
|
48388
48673
|
doc.setFontSize(9);
|
|
48389
48674
|
doc.setFont("helvetica", "normal");
|
|
48390
48675
|
doc.setTextColor(100, 100, 100);
|
|
48391
|
-
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone:
|
|
48676
|
+
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone: reportTimezone })}`;
|
|
48392
48677
|
const generatedTextWidth = doc.getStringUnitWidth(generatedText) * 9 / doc.internal.scaleFactor;
|
|
48393
48678
|
doc.text(generatedText, doc.internal.pageSize.width - 20 - generatedTextWidth, 15);
|
|
48394
48679
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -48406,11 +48691,10 @@ var LinePdfGenerator = ({
|
|
|
48406
48691
|
const isUptimeMode = lineInfo.monitoring_mode === "uptime";
|
|
48407
48692
|
const rawShiftType = shiftName || (lineInfo.shift_id === 0 ? "Day" : lineInfo.shift_id === 1 ? "Night" : `Shift ${lineInfo.shift_id}`);
|
|
48408
48693
|
const shiftType = rawShiftType.toLowerCase().includes("shift") ? rawShiftType : `${rawShiftType} Shift`;
|
|
48409
|
-
const date =
|
|
48694
|
+
const date = formatOperationalDateKey(lineInfo.date, {
|
|
48410
48695
|
weekday: "long",
|
|
48411
48696
|
day: "numeric",
|
|
48412
|
-
month: "long"
|
|
48413
|
-
timeZone: "Asia/Kolkata"
|
|
48697
|
+
month: "long"
|
|
48414
48698
|
});
|
|
48415
48699
|
const shiftStartTime = lineInfo.metrics.shift_start ? (/* @__PURE__ */ new Date(`2000-01-01 ${lineInfo.metrics.shift_start}`)).toLocaleTimeString("en-IN", {
|
|
48416
48700
|
hour: "2-digit",
|
|
@@ -48418,24 +48702,25 @@ var LinePdfGenerator = ({
|
|
|
48418
48702
|
hour12: true,
|
|
48419
48703
|
timeZone: "Asia/Kolkata"
|
|
48420
48704
|
}) : "N/A";
|
|
48421
|
-
const
|
|
48422
|
-
|
|
48423
|
-
|
|
48424
|
-
|
|
48425
|
-
|
|
48426
|
-
|
|
48427
|
-
|
|
48428
|
-
|
|
48429
|
-
|
|
48430
|
-
|
|
48431
|
-
|
|
48432
|
-
|
|
48433
|
-
|
|
48434
|
-
|
|
48435
|
-
|
|
48436
|
-
}
|
|
48705
|
+
const currentTime = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-IN", {
|
|
48706
|
+
hour: "2-digit",
|
|
48707
|
+
minute: "2-digit",
|
|
48708
|
+
timeZone: reportTimezone
|
|
48709
|
+
});
|
|
48710
|
+
const reportEndTime = isShiftInProgressForReportDate({
|
|
48711
|
+
reportDate: lineInfo.date,
|
|
48712
|
+
shiftStart: lineInfo.metrics.shift_start || "",
|
|
48713
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
48714
|
+
timeZone: reportTimezone
|
|
48715
|
+
}) ? currentTime : lineInfo.metrics.shift_end ? (/* @__PURE__ */ new Date(`2000-01-01 ${lineInfo.metrics.shift_end}`)).toLocaleTimeString("en-IN", {
|
|
48716
|
+
hour: "2-digit",
|
|
48717
|
+
minute: "2-digit",
|
|
48718
|
+
hour12: true,
|
|
48719
|
+
timeZone: "Asia/Kolkata"
|
|
48720
|
+
}) : "N/A";
|
|
48437
48721
|
if (isUptimeMode) {
|
|
48438
48722
|
const configuredTimezone = "Asia/Kolkata";
|
|
48723
|
+
const effectiveUptimeTimezone = reportTimezone || configuredTimezone;
|
|
48439
48724
|
const lineShiftStart = lineInfo.metrics.shift_start || "06:00";
|
|
48440
48725
|
const lineShiftEnd = lineInfo.metrics.shift_end || "14:00";
|
|
48441
48726
|
const shiftMinutes = getShiftDurationMinutes(lineShiftStart, lineShiftEnd) || 0;
|
|
@@ -48449,7 +48734,7 @@ var LinePdfGenerator = ({
|
|
|
48449
48734
|
shiftStart,
|
|
48450
48735
|
shiftEnd,
|
|
48451
48736
|
shiftDate,
|
|
48452
|
-
timezone:
|
|
48737
|
+
timezone: effectiveUptimeTimezone
|
|
48453
48738
|
});
|
|
48454
48739
|
let activeMinutes = uptimeSeries.activeMinutes;
|
|
48455
48740
|
let idleMinutes = uptimeSeries.idleMinutes;
|
|
@@ -48530,7 +48815,7 @@ var LinePdfGenerator = ({
|
|
|
48530
48815
|
shiftStart: lineShiftStart,
|
|
48531
48816
|
shiftEnd: lineShiftEnd,
|
|
48532
48817
|
shiftDate: lineInfo.date,
|
|
48533
|
-
timezone:
|
|
48818
|
+
timezone: effectiveUptimeTimezone
|
|
48534
48819
|
});
|
|
48535
48820
|
hourlyData = buildHourlyFromSeries(lineUptimeSeries);
|
|
48536
48821
|
}
|
|
@@ -48638,13 +48923,13 @@ var LinePdfGenerator = ({
|
|
|
48638
48923
|
doc.setFontSize(contentFontSize);
|
|
48639
48924
|
doc.setFont("helvetica", "normal");
|
|
48640
48925
|
let yPos2 = headerBottomY2 + 5.5;
|
|
48641
|
-
const
|
|
48642
|
-
const
|
|
48643
|
-
const [
|
|
48644
|
-
const [
|
|
48645
|
-
const
|
|
48926
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
48927
|
+
const currentTimeIST = new Date(now4.toLocaleString("en-US", { timeZone: configuredTimezone }));
|
|
48928
|
+
const [sYear, sMonth, sDay] = lineInfo.date.split("-").map(Number);
|
|
48929
|
+
const [sStartH, sStartM] = (lineShiftStart || "06:00").split(":").map(Number);
|
|
48930
|
+
const shiftStartBase = new Date(sYear, sMonth - 1, sDay, sStartH, sStartM || 0);
|
|
48646
48931
|
hourlyData.forEach((entry, index) => {
|
|
48647
|
-
const bucketStartTime = new Date(
|
|
48932
|
+
const bucketStartTime = new Date(shiftStartBase);
|
|
48648
48933
|
bucketStartTime.setHours(bucketStartTime.getHours() + index);
|
|
48649
48934
|
const bucketEndTime = new Date(bucketStartTime);
|
|
48650
48935
|
bucketEndTime.setHours(bucketEndTime.getHours() + 1);
|
|
@@ -48655,7 +48940,7 @@ var LinePdfGenerator = ({
|
|
|
48655
48940
|
hour: "numeric",
|
|
48656
48941
|
hour12: true
|
|
48657
48942
|
})}`;
|
|
48658
|
-
const dataCollected = bucketEndTime.getTime() <=
|
|
48943
|
+
const dataCollected = bucketEndTime.getTime() <= currentTimeIST.getTime();
|
|
48659
48944
|
if (index < totalRows2 - 1) {
|
|
48660
48945
|
const rowBottomY = headerBottomY2 + (index + 1) * rowHeight;
|
|
48661
48946
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -48666,11 +48951,10 @@ var LinePdfGenerator = ({
|
|
|
48666
48951
|
doc.text(utilizationStr, 147, yPos2);
|
|
48667
48952
|
yPos2 += rowHeight;
|
|
48668
48953
|
});
|
|
48669
|
-
const fileDate2 =
|
|
48954
|
+
const fileDate2 = formatOperationalDateKey(lineInfo.date, {
|
|
48670
48955
|
day: "2-digit",
|
|
48671
48956
|
month: "short",
|
|
48672
|
-
year: "numeric"
|
|
48673
|
-
timeZone: "Asia/Kolkata"
|
|
48957
|
+
year: "numeric"
|
|
48674
48958
|
}).replace(/ /g, "_");
|
|
48675
48959
|
const fileShift2 = shiftType.replace(/ /g, "_");
|
|
48676
48960
|
const fileName2 = `${lineInfo.line_name}_${fileDate2}_${fileShift2}.pdf`;
|
|
@@ -48723,66 +49007,32 @@ var LinePdfGenerator = ({
|
|
|
48723
49007
|
doc.setLineWidth(0.8);
|
|
48724
49008
|
doc.line(20, 123, 190, 123);
|
|
48725
49009
|
const hourlyOverviewStartY = 128;
|
|
48726
|
-
const parseTimeToMinutes4 = (timeStr) => {
|
|
48727
|
-
const [hours, minutes] = timeStr.split(":");
|
|
48728
|
-
const hour = parseInt(hours, 10);
|
|
48729
|
-
const minute = parseInt(minutes || "0", 10);
|
|
48730
|
-
if (Number.isNaN(hour) || Number.isNaN(minute)) {
|
|
48731
|
-
return NaN;
|
|
48732
|
-
}
|
|
48733
|
-
return (hour * 60 + minute) % (24 * 60);
|
|
48734
|
-
};
|
|
48735
49010
|
const formatMinutesLabel = (totalMinutes) => {
|
|
48736
49011
|
const normalized = (totalMinutes % (24 * 60) + 24 * 60) % (24 * 60);
|
|
48737
49012
|
const hour = Math.floor(normalized / 60);
|
|
48738
49013
|
const minute = normalized % 60;
|
|
48739
|
-
const time2 =
|
|
48740
|
-
time2.setHours(hour);
|
|
48741
|
-
time2.setMinutes(minute);
|
|
48742
|
-
time2.setSeconds(0);
|
|
48743
|
-
time2.setMilliseconds(0);
|
|
49014
|
+
const time2 = new Date(Date.UTC(2e3, 0, 1, hour, minute));
|
|
48744
49015
|
return time2.toLocaleTimeString("en-IN", {
|
|
48745
49016
|
hour: "2-digit",
|
|
48746
49017
|
minute: "2-digit",
|
|
48747
49018
|
hour12: true,
|
|
48748
|
-
timeZone: "
|
|
48749
|
-
});
|
|
48750
|
-
};
|
|
48751
|
-
const buildRange = (startMinutes, minutes) => {
|
|
48752
|
-
const endMinutes = startMinutes + minutes;
|
|
48753
|
-
return {
|
|
48754
|
-
label: `${formatMinutesLabel(startMinutes)} - ${formatMinutesLabel(endMinutes)}`,
|
|
48755
|
-
minutes
|
|
48756
|
-
};
|
|
48757
|
-
};
|
|
48758
|
-
const getHourlyTimeRanges = (startTimeStr, endTimeStr) => {
|
|
48759
|
-
const startMinutes = parseTimeToMinutes4(startTimeStr);
|
|
48760
|
-
if (Number.isNaN(startMinutes)) {
|
|
48761
|
-
return [];
|
|
48762
|
-
}
|
|
48763
|
-
if (!endTimeStr) {
|
|
48764
|
-
const defaultHours = 11;
|
|
48765
|
-
return Array.from({ length: defaultHours }, (_, i) => buildRange(startMinutes + i * 60, 60));
|
|
48766
|
-
}
|
|
48767
|
-
const endMinutes = parseTimeToMinutes4(endTimeStr);
|
|
48768
|
-
if (Number.isNaN(endMinutes)) {
|
|
48769
|
-
const fallbackHours = 11;
|
|
48770
|
-
return Array.from({ length: fallbackHours }, (_, i) => buildRange(startMinutes + i * 60, 60));
|
|
48771
|
-
}
|
|
48772
|
-
let durationMinutes = endMinutes - startMinutes;
|
|
48773
|
-
if (durationMinutes <= 0) {
|
|
48774
|
-
durationMinutes += 24 * 60;
|
|
48775
|
-
}
|
|
48776
|
-
const rangeCount = Math.max(1, Math.ceil(durationMinutes / 60));
|
|
48777
|
-
return Array.from({ length: rangeCount }, (_, i) => {
|
|
48778
|
-
const remainingMinutes = durationMinutes - i * 60;
|
|
48779
|
-
const rangeMinutes = remainingMinutes >= 60 ? 60 : remainingMinutes;
|
|
48780
|
-
return buildRange(startMinutes + i * 60, rangeMinutes);
|
|
49019
|
+
timeZone: "UTC"
|
|
48781
49020
|
});
|
|
48782
49021
|
};
|
|
48783
|
-
const hourlyTimeRanges =
|
|
49022
|
+
const hourlyTimeRanges = buildHourlyIntervals({
|
|
49023
|
+
shiftStart: lineInfo.metrics.shift_start || "06:00",
|
|
49024
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
49025
|
+
fallbackHours: 11
|
|
49026
|
+
});
|
|
49027
|
+
const targetPlan = buildHourlyTargetPlan({
|
|
49028
|
+
shiftStart: lineInfo.metrics.shift_start || "06:00",
|
|
49029
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
49030
|
+
breaks: shiftBreaks,
|
|
49031
|
+
pphThreshold: Number(lineInfo.metrics.threshold_pph ?? 0),
|
|
49032
|
+
fallbackHours: Math.max(hourlyTimeRanges.length, 1),
|
|
49033
|
+
rounding: "floor"
|
|
49034
|
+
});
|
|
48784
49035
|
const shiftDuration = hourlyTimeRanges.length || 11;
|
|
48785
|
-
const targetOutputPerHour = Math.round(lineInfo.metrics.threshold_pph ?? 0);
|
|
48786
49036
|
let hourlyActualOutput = [];
|
|
48787
49037
|
if (lineInfo.metrics.output_hourly && Object.keys(lineInfo.metrics.output_hourly).length > 0) {
|
|
48788
49038
|
const [startHourStr, startMinuteStr] = (lineInfo.metrics.shift_start || "6:00").split(":");
|
|
@@ -48968,29 +49218,29 @@ var LinePdfGenerator = ({
|
|
|
48968
49218
|
doc.text("Remarks", 160, tableHeaderY);
|
|
48969
49219
|
doc.setFont("helvetica", "normal");
|
|
48970
49220
|
let yPos = tableStartY;
|
|
48971
|
-
const now4 = /* @__PURE__ */ new Date();
|
|
48972
|
-
const currentTimeIST = new Date(now4.toLocaleString("en-US", { timeZone: "Asia/Kolkata" }));
|
|
48973
|
-
const [sYear, sMonth, sDay] = lineInfo.date.split("-").map(Number);
|
|
48974
|
-
const [sStartH, sStartM] = (lineInfo.metrics.shift_start || "06:00").split(":").map(Number);
|
|
48975
|
-
const shiftStartBase = new Date(sYear, sMonth - 1, sDay, sStartH, sStartM || 0);
|
|
48976
49221
|
hourlyTimeRanges.forEach((timeRange, index) => {
|
|
48977
49222
|
const actualOutput = hourlyActualOutput[index] || 0;
|
|
48978
|
-
const
|
|
48979
|
-
|
|
48980
|
-
|
|
48981
|
-
|
|
49223
|
+
const dataCollected = isHourlyIntervalComplete({
|
|
49224
|
+
reportDate: lineInfo.date,
|
|
49225
|
+
shiftStart: lineInfo.metrics.shift_start || "06:00",
|
|
49226
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
49227
|
+
interval: timeRange,
|
|
49228
|
+
timeZone: reportTimezone
|
|
49229
|
+
});
|
|
48982
49230
|
const outputStr = dataCollected ? actualOutput.toString() : "TBD";
|
|
48983
49231
|
if (index < totalRows - 1) {
|
|
48984
49232
|
const rowBottomY = headerBottomY + (index + 1) * rowSpacing;
|
|
48985
49233
|
doc.setDrawColor(200, 200, 200);
|
|
48986
49234
|
doc.line(20, rowBottomY, 190, rowBottomY);
|
|
48987
49235
|
}
|
|
48988
|
-
const
|
|
48989
|
-
const
|
|
48990
|
-
const
|
|
48991
|
-
doc.text(timeRange.
|
|
49236
|
+
const targetForRange = targetPlan.targets[index] ?? 0;
|
|
49237
|
+
const targetStr = targetForRange.toString();
|
|
49238
|
+
const remarkText = targetPlan.breakRemarks[index] || "";
|
|
49239
|
+
doc.text(`${formatMinutesLabel(timeRange.start)} - ${formatMinutesLabel(timeRange.end)}`, 25, yPos);
|
|
48992
49240
|
doc.text(outputStr, 75, yPos);
|
|
48993
49241
|
doc.text(targetStr, 105, yPos);
|
|
49242
|
+
const remarkDisplay = remarkText ? doc.splitTextToSize(remarkText, 26)[0] : "";
|
|
49243
|
+
doc.text(remarkDisplay, 160, yPos);
|
|
48994
49244
|
if (!dataCollected) {
|
|
48995
49245
|
doc.setTextColor(100, 100, 100);
|
|
48996
49246
|
doc.text("-", 135, yPos);
|
|
@@ -49006,11 +49256,10 @@ var LinePdfGenerator = ({
|
|
|
49006
49256
|
doc.setTextColor(0, 0, 0);
|
|
49007
49257
|
yPos += rowSpacing;
|
|
49008
49258
|
});
|
|
49009
|
-
const fileDate =
|
|
49259
|
+
const fileDate = formatOperationalDateKey(lineInfo.date, {
|
|
49010
49260
|
day: "2-digit",
|
|
49011
49261
|
month: "short",
|
|
49012
|
-
year: "numeric"
|
|
49013
|
-
timeZone: "Asia/Kolkata"
|
|
49262
|
+
year: "numeric"
|
|
49014
49263
|
}).replace(/ /g, "_");
|
|
49015
49264
|
const fileShift = shiftType.replace(/ /g, "_");
|
|
49016
49265
|
const fileName = `${lineInfo.line_name}_${fileDate}_${fileShift}.pdf`;
|
|
@@ -49938,6 +50187,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
49938
50187
|
}, [analysisMonthlyData, selectedShiftId, isUptimeMode, shiftWorkSeconds]);
|
|
49939
50188
|
const efficiencyDelta = trendSummary?.avg_efficiency?.delta_pp ?? 0;
|
|
49940
50189
|
const efficiencyImproved = efficiencyDelta >= 0;
|
|
50190
|
+
const assemblyRangeCycleTime = React143.useMemo(() => {
|
|
50191
|
+
const trendCycleTime = Number(trendSummary?.avg_cycle_time?.current);
|
|
50192
|
+
if (Number.isFinite(trendCycleTime) && trendCycleTime > 0) {
|
|
50193
|
+
return Math.round(trendCycleTime);
|
|
50194
|
+
}
|
|
50195
|
+
return metrics2?.avgCycleTime ?? 0;
|
|
50196
|
+
}, [trendSummary?.avg_cycle_time?.current, metrics2?.avgCycleTime]);
|
|
49941
50197
|
const cycleDeltaRaw = trendSummary?.avg_cycle_time?.delta_seconds ?? 0;
|
|
49942
50198
|
const cyclePrev = trendSummary?.avg_cycle_time?.previous ?? 0;
|
|
49943
50199
|
const cycleDelta = cyclePrev ? cycleDeltaRaw / cyclePrev * 100 : 0;
|
|
@@ -50123,7 +50379,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
50123
50379
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: "Avg Cycle Time" }),
|
|
50124
50380
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
50125
50381
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-2xl font-bold text-gray-900", children: [
|
|
50126
|
-
|
|
50382
|
+
assemblyRangeCycleTime,
|
|
50127
50383
|
"s"
|
|
50128
50384
|
] }),
|
|
50129
50385
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1 ${cycleWorsened ? "bg-red-50 text-red-600" : "bg-emerald-50 text-emerald-600"} px-2 py-0.5 rounded-full text-[10px] font-medium whitespace-nowrap flex-shrink-0`, children: [
|
|
@@ -50459,7 +50715,25 @@ var WorkspaceWhatsAppShareButton = ({
|
|
|
50459
50715
|
}
|
|
50460
50716
|
);
|
|
50461
50717
|
};
|
|
50462
|
-
var
|
|
50718
|
+
var formatOperationalDateKey2 = (dateKey, options) => {
|
|
50719
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
50720
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
50721
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
50722
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
50723
|
+
return new Date(Date.UTC(year, month - 1, day, 12)).toLocaleDateString("en-IN", {
|
|
50724
|
+
...options,
|
|
50725
|
+
timeZone: "UTC"
|
|
50726
|
+
});
|
|
50727
|
+
};
|
|
50728
|
+
var WorkspacePdfGenerator = ({
|
|
50729
|
+
workspace,
|
|
50730
|
+
className,
|
|
50731
|
+
idleTimeReasons,
|
|
50732
|
+
efficiencyLegend,
|
|
50733
|
+
hourlyCycleTimes,
|
|
50734
|
+
shiftBreaks = [],
|
|
50735
|
+
reportTimezone = "Asia/Kolkata"
|
|
50736
|
+
}) => {
|
|
50463
50737
|
const [isGenerating, setIsGenerating] = React143.useState(false);
|
|
50464
50738
|
const entityConfig = useEntityConfig();
|
|
50465
50739
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
@@ -50489,7 +50763,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50489
50763
|
doc.setFontSize(9);
|
|
50490
50764
|
doc.setFont("helvetica", "normal");
|
|
50491
50765
|
doc.setTextColor(100, 100, 100);
|
|
50492
|
-
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone:
|
|
50766
|
+
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone: reportTimezone })}`;
|
|
50493
50767
|
const generatedTextWidth = doc.getStringUnitWidth(generatedText) * 9 / doc.internal.scaleFactor;
|
|
50494
50768
|
doc.text(generatedText, doc.internal.pageSize.width - 20 - generatedTextWidth, 15);
|
|
50495
50769
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -50508,11 +50782,10 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50508
50782
|
doc.setFontSize(13);
|
|
50509
50783
|
doc.setFont("helvetica", "normal");
|
|
50510
50784
|
doc.setTextColor(60, 60, 60);
|
|
50511
|
-
const date =
|
|
50785
|
+
const date = formatOperationalDateKey2(workspace.date, {
|
|
50512
50786
|
weekday: "long",
|
|
50513
50787
|
day: "numeric",
|
|
50514
|
-
month: "long"
|
|
50515
|
-
timeZone: "Asia/Kolkata"
|
|
50788
|
+
month: "long"
|
|
50516
50789
|
});
|
|
50517
50790
|
const rawShiftType = workspace.shift_type || (workspace.shift_id === 0 ? "Day" : workspace.shift_id === 1 ? "Night" : `Shift ${workspace.shift_id}`);
|
|
50518
50791
|
const shiftType = rawShiftType.toLowerCase().includes("shift") ? rawShiftType : `${rawShiftType} Shift`;
|
|
@@ -50521,7 +50794,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50521
50794
|
const currentTime = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-IN", {
|
|
50522
50795
|
hour: "2-digit",
|
|
50523
50796
|
minute: "2-digit",
|
|
50524
|
-
timeZone:
|
|
50797
|
+
timeZone: reportTimezone
|
|
50525
50798
|
});
|
|
50526
50799
|
const shiftStartTime = (/* @__PURE__ */ new Date(`2000-01-01 ${workspace.shift_start}`)).toLocaleTimeString("en-IN", {
|
|
50527
50800
|
hour: "2-digit",
|
|
@@ -50533,29 +50806,12 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50533
50806
|
minute: "2-digit",
|
|
50534
50807
|
hour12: true
|
|
50535
50808
|
});
|
|
50536
|
-
const
|
|
50537
|
-
|
|
50538
|
-
|
|
50539
|
-
|
|
50540
|
-
|
|
50541
|
-
};
|
|
50542
|
-
const toShiftUtcMs = (dateKey, timeValue) => {
|
|
50543
|
-
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
50544
|
-
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
50545
|
-
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
50546
|
-
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
50547
|
-
const [hourPart, minutePart] = timeValue.split(":").map(Number);
|
|
50548
|
-
const hour = Number.isFinite(hourPart) ? hourPart : 0;
|
|
50549
|
-
const minute = Number.isFinite(minutePart) ? minutePart : 0;
|
|
50550
|
-
const IST_OFFSET_MINUTES = 330;
|
|
50551
|
-
return Date.UTC(year, month - 1, day, hour, minute) - IST_OFFSET_MINUTES * 60 * 1e3;
|
|
50552
|
-
};
|
|
50553
|
-
const shiftStartMinutes = parseTimeToMinutes4(workspace.shift_start);
|
|
50554
|
-
const shiftEndMinutes = parseTimeToMinutes4(workspace.shift_end);
|
|
50555
|
-
const wrapsMidnight = shiftEndMinutes <= shiftStartMinutes;
|
|
50556
|
-
const shiftStartUtcMs = toShiftUtcMs(workspace.date, workspace.shift_start);
|
|
50557
|
-
const shiftEndUtcMs = toShiftUtcMs(workspace.date, workspace.shift_end) + (wrapsMidnight ? 24 * 60 * 60 * 1e3 : 0);
|
|
50558
|
-
const isShiftInProgress = Date.now() >= shiftStartUtcMs && Date.now() < shiftEndUtcMs;
|
|
50809
|
+
const isShiftInProgress = isShiftInProgressForReportDate({
|
|
50810
|
+
reportDate: workspace.date,
|
|
50811
|
+
shiftStart: workspace.shift_start,
|
|
50812
|
+
shiftEnd: workspace.shift_end,
|
|
50813
|
+
timeZone: reportTimezone
|
|
50814
|
+
});
|
|
50559
50815
|
const reportPeriodEndTime = isShiftInProgress ? currentTime : shiftEndTime;
|
|
50560
50816
|
doc.setFontSize(12);
|
|
50561
50817
|
doc.setTextColor(80, 80, 80);
|
|
@@ -50661,7 +50917,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50661
50917
|
shiftStart: workspace.shift_start,
|
|
50662
50918
|
shiftEnd: workspace.shift_end,
|
|
50663
50919
|
shiftDate: workspace.date,
|
|
50664
|
-
timezone:
|
|
50920
|
+
timezone: reportTimezone
|
|
50665
50921
|
}) : null;
|
|
50666
50922
|
const hourlyUptime = uptimeSeries?.points?.length ? Array.from({ length: Math.ceil(uptimeSeries.shiftMinutes / 60) }, (_, index) => {
|
|
50667
50923
|
const start = index * 60;
|
|
@@ -50676,6 +50932,31 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50676
50932
|
const hourlyData = isUptimeMode ? hourlyUptime : isAssemblyCycleMode ? hourlyCycleTimes && hourlyCycleTimes.length > 0 ? hourlyCycleTimes : workspace.hourly_action_counts || [] : workspace.hourly_action_counts || [];
|
|
50677
50933
|
const hourlyTarget = workspace.pph_threshold;
|
|
50678
50934
|
const cycleTarget = workspace.ideal_cycle_time || 0;
|
|
50935
|
+
const hourlyIntervals = buildHourlyIntervals({
|
|
50936
|
+
shiftStart: workspace.shift_start,
|
|
50937
|
+
shiftEnd: workspace.shift_end,
|
|
50938
|
+
fallbackHours: Math.max(hourlyData.length, 1)
|
|
50939
|
+
});
|
|
50940
|
+
const outputTargetPlan = !isUptimeMode && !isAssemblyCycleMode ? buildHourlyTargetPlan({
|
|
50941
|
+
shiftStart: workspace.shift_start,
|
|
50942
|
+
shiftEnd: workspace.shift_end,
|
|
50943
|
+
breaks: shiftBreaks,
|
|
50944
|
+
pphThreshold: workspace.pph_threshold,
|
|
50945
|
+
fallbackHours: Math.max(hourlyData.length, 1),
|
|
50946
|
+
rounding: "floor"
|
|
50947
|
+
}) : null;
|
|
50948
|
+
const formatIntervalLabel = (totalMinutes) => {
|
|
50949
|
+
const normalized = (totalMinutes % (24 * 60) + 24 * 60) % (24 * 60);
|
|
50950
|
+
const hour = Math.floor(normalized / 60);
|
|
50951
|
+
const minute = normalized % 60;
|
|
50952
|
+
const time2 = new Date(Date.UTC(2e3, 0, 1, hour, minute));
|
|
50953
|
+
return time2.toLocaleTimeString("en-IN", {
|
|
50954
|
+
hour: "numeric",
|
|
50955
|
+
...minute > 0 ? { minute: "2-digit" } : {},
|
|
50956
|
+
hour12: true,
|
|
50957
|
+
timeZone: "UTC"
|
|
50958
|
+
});
|
|
50959
|
+
};
|
|
50679
50960
|
const pageHeight = doc.internal.pageSize.height;
|
|
50680
50961
|
const maxContentY = pageHeight - 15;
|
|
50681
50962
|
const baseTableStartY = hourlyPerfStartY + 31;
|
|
@@ -50743,36 +51024,30 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50743
51024
|
doc.setFontSize(contentFontSize);
|
|
50744
51025
|
doc.setFont("helvetica", "normal");
|
|
50745
51026
|
let yPos = headerBottomY + 5.5;
|
|
50746
|
-
const
|
|
50747
|
-
const today = /* @__PURE__ */ new Date();
|
|
50748
|
-
today.setHours(0, 0, 0, 0);
|
|
50749
|
-
workspaceDate.setHours(0, 0, 0, 0);
|
|
50750
|
-
const isToday2 = workspaceDate.getTime() === today.getTime();
|
|
51027
|
+
const isToday2 = getDateKeyInTimeZone(reportTimezone) === workspace.date;
|
|
50751
51028
|
let currentHour = 24;
|
|
50752
51029
|
if (isToday2) {
|
|
50753
51030
|
const now4 = /* @__PURE__ */ new Date();
|
|
50754
|
-
const
|
|
50755
|
-
currentHour =
|
|
51031
|
+
const currentTimeInReportTimezone = new Date(now4.toLocaleString("en-US", { timeZone: reportTimezone }));
|
|
51032
|
+
currentHour = currentTimeInReportTimezone.getHours();
|
|
50756
51033
|
}
|
|
50757
51034
|
hourlyData.forEach((entry, index) => {
|
|
50758
|
-
const
|
|
50759
|
-
|
|
50760
|
-
const
|
|
50761
|
-
|
|
50762
|
-
|
|
50763
|
-
|
|
50764
|
-
|
|
50765
|
-
|
|
50766
|
-
|
|
50767
|
-
hour12: true
|
|
50768
|
-
})}`;
|
|
50769
|
-
const hourNumber = startTime.getHours();
|
|
50770
|
-
const dataCollected = !isToday2 || hourNumber < currentHour;
|
|
51035
|
+
const interval = hourlyIntervals[index];
|
|
51036
|
+
const timeRange = interval ? `${formatIntervalLabel(interval.start)} - ${formatIntervalLabel(interval.end)}` : `${index + 1}`;
|
|
51037
|
+
const dataCollected = interval ? isHourlyIntervalComplete({
|
|
51038
|
+
reportDate: workspace.date,
|
|
51039
|
+
shiftStart: workspace.shift_start,
|
|
51040
|
+
shiftEnd: workspace.shift_end,
|
|
51041
|
+
interval,
|
|
51042
|
+
timeZone: reportTimezone
|
|
51043
|
+
}) : !isToday2 || currentHour >= 24;
|
|
50771
51044
|
const outputValue = isUptimeMode ? entry.activeMinutes ?? 0 : entry;
|
|
50772
51045
|
const idleValue = isUptimeMode ? entry.idleMinutes ?? 0 : 0;
|
|
50773
51046
|
const uptimePercent = isUptimeMode ? entry.uptimePercent ?? 0 : 0;
|
|
50774
51047
|
const outputStr = dataCollected ? outputValue.toString() : "TBD";
|
|
50775
|
-
const
|
|
51048
|
+
const effectiveTarget = outputTargetPlan?.targets[index] ?? hourlyTarget;
|
|
51049
|
+
const remarkText = outputTargetPlan?.breakRemarks[index] || "";
|
|
51050
|
+
const targetStr = isUptimeMode ? dataCollected ? idleValue.toString() : "TBD" : effectiveTarget.toString();
|
|
50776
51051
|
if (index < totalRows - 1) {
|
|
50777
51052
|
const rowBottomY = headerBottomY + (index + 1) * rowHeight;
|
|
50778
51053
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -50804,10 +51079,12 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50804
51079
|
} else {
|
|
50805
51080
|
doc.text(outputStr, 75, yPos);
|
|
50806
51081
|
doc.text(targetStr, 105, yPos);
|
|
51082
|
+
const remarkDisplay = remarkText ? doc.splitTextToSize(remarkText, 26)[0] : "";
|
|
51083
|
+
doc.text(remarkDisplay, 160, yPos);
|
|
50807
51084
|
if (!dataCollected) {
|
|
50808
51085
|
doc.setTextColor(100, 100, 100);
|
|
50809
51086
|
doc.text("-", 135, yPos);
|
|
50810
|
-
} else if (outputValue >=
|
|
51087
|
+
} else if (outputValue >= effectiveTarget) {
|
|
50811
51088
|
doc.setTextColor(0, 171, 69);
|
|
50812
51089
|
doc.setFont("ZapfDingbats", "normal");
|
|
50813
51090
|
doc.text("4", 135, yPos);
|
|
@@ -50821,11 +51098,10 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50821
51098
|
yPos += rowHeight;
|
|
50822
51099
|
});
|
|
50823
51100
|
const workspaceDisplayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
50824
|
-
const fileDate =
|
|
51101
|
+
const fileDate = formatOperationalDateKey2(workspace.date, {
|
|
50825
51102
|
day: "2-digit",
|
|
50826
51103
|
month: "short",
|
|
50827
|
-
year: "numeric"
|
|
50828
|
-
timeZone: "Asia/Kolkata"
|
|
51104
|
+
year: "numeric"
|
|
50829
51105
|
}).replace(/ /g, "_");
|
|
50830
51106
|
const fileShift = shiftType.replace(/ /g, "_");
|
|
50831
51107
|
const fileName = `${workspaceDisplayName}_${fileDate}_${fileShift}.pdf`;
|
|
@@ -50871,12 +51147,25 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
50871
51147
|
availableShifts,
|
|
50872
51148
|
shiftConfig,
|
|
50873
51149
|
efficiencyLegend,
|
|
51150
|
+
trendSummary,
|
|
50874
51151
|
className,
|
|
50875
51152
|
compact = false,
|
|
50876
51153
|
isAssemblyWorkspace = false
|
|
50877
51154
|
}) => {
|
|
50878
51155
|
const [isGenerating, setIsGenerating] = React143.useState(false);
|
|
50879
51156
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
51157
|
+
const drawStatusMark = (doc, x, y, met) => {
|
|
51158
|
+
doc.setLineWidth(0.8);
|
|
51159
|
+
if (met) {
|
|
51160
|
+
doc.setDrawColor(0, 171, 69);
|
|
51161
|
+
doc.line(x - 1.8, y - 0.2, x - 0.5, y + 1.2);
|
|
51162
|
+
doc.line(x - 0.5, y + 1.2, x + 2.1, y - 1.6);
|
|
51163
|
+
return;
|
|
51164
|
+
}
|
|
51165
|
+
doc.setDrawColor(227, 67, 41);
|
|
51166
|
+
doc.line(x - 1.8, y - 1.6, x + 1.8, y + 1.6);
|
|
51167
|
+
doc.line(x - 1.8, y + 1.6, x + 1.8, y - 1.6);
|
|
51168
|
+
};
|
|
50880
51169
|
const generatePDF = async () => {
|
|
50881
51170
|
setIsGenerating(true);
|
|
50882
51171
|
try {
|
|
@@ -51071,12 +51360,13 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
51071
51360
|
doc.setFont("helvetica", "bold");
|
|
51072
51361
|
doc.text(`${outputMetrics.underperformingDays} of ${outputMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 3);
|
|
51073
51362
|
} else {
|
|
51363
|
+
const medianCycleTime = Number.isFinite(trendSummary?.avg_cycle_time?.current) ? Number(trendSummary?.avg_cycle_time?.current) : outputMetrics.avgCycleTime;
|
|
51074
51364
|
createKPIBox(kpiStartY);
|
|
51075
51365
|
doc.setFontSize(11);
|
|
51076
51366
|
doc.setFont("helvetica", "normal");
|
|
51077
51367
|
doc.text("Average Cycle Time:", 25, kpiStartY);
|
|
51078
51368
|
doc.setFont("helvetica", "bold");
|
|
51079
|
-
doc.text(`${
|
|
51369
|
+
doc.text(`${medianCycleTime.toFixed(1)}s`, 120, kpiStartY);
|
|
51080
51370
|
createKPIBox(kpiStartY + kpiSpacing);
|
|
51081
51371
|
doc.setFont("helvetica", "normal");
|
|
51082
51372
|
doc.text("Average Idle Time:", 25, kpiStartY + kpiSpacing);
|
|
@@ -51111,8 +51401,8 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
51111
51401
|
doc.roundedRect(20, tableHeaderY, 170, 7, 1, 1, "F");
|
|
51112
51402
|
const textY = tableHeaderY + 5;
|
|
51113
51403
|
doc.text("Date", 25, textY);
|
|
51114
|
-
doc.text(isUptimeMode ? "Productive" : isAssemblyWorkspace ? "Cycle Time" : "Actual", 60, textY);
|
|
51115
|
-
doc.text(isUptimeMode ? "Idle" : isAssemblyWorkspace ? "
|
|
51404
|
+
doc.text(isUptimeMode ? "Productive" : isAssemblyWorkspace ? "Actual Cycle Time" : "Actual", 60, textY);
|
|
51405
|
+
doc.text(isUptimeMode ? "Idle" : isAssemblyWorkspace ? "Standard Cycle Time" : "Standard", 95, textY);
|
|
51116
51406
|
doc.text(isUptimeMode ? "Utilization" : "Efficiency", 135, textY);
|
|
51117
51407
|
doc.text("Status", 170, textY);
|
|
51118
51408
|
doc.setLineWidth(0.2);
|
|
@@ -51144,31 +51434,18 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
51144
51434
|
doc.text(formatIdleTime(productiveSeconds), 60, yPos);
|
|
51145
51435
|
doc.text(formatIdleTime(clampedIdleSeconds), 95, yPos);
|
|
51146
51436
|
doc.text(`${utilization}%`, 135, yPos);
|
|
51147
|
-
|
|
51148
|
-
doc.setTextColor(0, 171, 69);
|
|
51149
|
-
doc.text("\u2713", 170, yPos);
|
|
51150
|
-
} else {
|
|
51151
|
-
doc.setTextColor(227, 67, 41);
|
|
51152
|
-
doc.text("\xD7", 170, yPos);
|
|
51153
|
-
}
|
|
51154
|
-
doc.setTextColor(0, 0, 0);
|
|
51437
|
+
drawStatusMark(doc, 171, yPos - 0.3, utilization >= effectiveLegend.green_min);
|
|
51155
51438
|
} else {
|
|
51156
51439
|
if (isAssemblyWorkspace) {
|
|
51440
|
+
const targetCycleTime = Number.isFinite(shift.idealCycleTime) && Number(shift.idealCycleTime) > 0 ? Number(shift.idealCycleTime) : shift.pphThreshold > 0 ? 3600 / shift.pphThreshold : null;
|
|
51157
51441
|
doc.text(`${shift.cycleTime.toFixed(1)}`, 60, yPos);
|
|
51158
|
-
doc.text(
|
|
51442
|
+
doc.text(targetCycleTime !== null ? `${targetCycleTime.toFixed(1)}` : "-", 95, yPos);
|
|
51159
51443
|
} else {
|
|
51160
51444
|
doc.text(`${shift.output}`, 60, yPos);
|
|
51161
51445
|
doc.text(`${shift.targetOutput}`, 95, yPos);
|
|
51162
51446
|
}
|
|
51163
51447
|
doc.text(`${shift.efficiency.toFixed(1)}%`, 135, yPos);
|
|
51164
|
-
|
|
51165
|
-
doc.setTextColor(0, 171, 69);
|
|
51166
|
-
doc.text("\u2713", 170, yPos);
|
|
51167
|
-
} else {
|
|
51168
|
-
doc.setTextColor(227, 67, 41);
|
|
51169
|
-
doc.text("\xD7", 170, yPos);
|
|
51170
|
-
}
|
|
51171
|
-
doc.setTextColor(0, 0, 0);
|
|
51448
|
+
drawStatusMark(doc, 171, yPos - 0.3, shift.efficiency >= effectiveLegend.green_min);
|
|
51172
51449
|
}
|
|
51173
51450
|
yPos += 8;
|
|
51174
51451
|
});
|
|
@@ -64334,7 +64611,17 @@ var KPIDetailView = ({
|
|
|
64334
64611
|
)
|
|
64335
64612
|
] }),
|
|
64336
64613
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 ml-auto", children: [
|
|
64337
|
-
resolvedLineInfo && activeTab === "overview" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
64614
|
+
resolvedLineInfo && activeTab === "overview" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
64615
|
+
LinePdfGenerator,
|
|
64616
|
+
{
|
|
64617
|
+
lineInfo: resolvedLineInfo,
|
|
64618
|
+
workspaceData: resolvedWorkspaces || [],
|
|
64619
|
+
issueResolutionSummary,
|
|
64620
|
+
shiftName: getShiftName(resolvedLineInfo.shift_id),
|
|
64621
|
+
shiftBreaks: shiftConfig?.shifts?.find((shift) => shift.shiftId === resolvedLineInfo.shift_id)?.breaks || [],
|
|
64622
|
+
reportTimezone: shiftConfig?.timezone || configuredTimezone
|
|
64623
|
+
}
|
|
64624
|
+
),
|
|
64338
64625
|
activeTab === "monthly_history" && !urlDate && !urlShift && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
64339
64626
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
64340
64627
|
MonthlyRangeFilter_default,
|
|
@@ -64363,6 +64650,8 @@ var KPIDetailView = ({
|
|
|
64363
64650
|
rangeStart,
|
|
64364
64651
|
rangeEnd,
|
|
64365
64652
|
selectedShiftId,
|
|
64653
|
+
availableShifts: shiftConfig?.shifts?.map((shift) => ({ id: shift.shiftId, name: shift.shiftName })),
|
|
64654
|
+
lineAssembly: resolvedLineInfo?.assembly === true,
|
|
64366
64655
|
compact: true
|
|
64367
64656
|
}
|
|
64368
64657
|
)
|
|
@@ -64541,7 +64830,7 @@ var KPIDetailViewWithDisplayNames = withSelectedLineDisplayNames(KPIDetailView);
|
|
|
64541
64830
|
var KPIDetailView_default = KPIDetailViewWithDisplayNames;
|
|
64542
64831
|
var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
64543
64832
|
var resolveCompanyId = (...candidates) => candidates.find(isNonEmptyString);
|
|
64544
|
-
var
|
|
64833
|
+
var parseTimeToMinutes3 = (value) => {
|
|
64545
64834
|
if (!value) return null;
|
|
64546
64835
|
const [hourStr, minuteStr] = value.split(":");
|
|
64547
64836
|
const hour = Number.parseInt(hourStr ?? "", 10);
|
|
@@ -64553,8 +64842,8 @@ var getShiftEndDate = (shift, timezone) => {
|
|
|
64553
64842
|
if (!shift?.date) return null;
|
|
64554
64843
|
const startTime = shift.startTime || "06:00";
|
|
64555
64844
|
const endTime = shift.endTime || "18:00";
|
|
64556
|
-
const startMinutes =
|
|
64557
|
-
const endMinutes =
|
|
64845
|
+
const startMinutes = parseTimeToMinutes3(startTime);
|
|
64846
|
+
const endMinutes = parseTimeToMinutes3(endTime);
|
|
64558
64847
|
if (startMinutes === null || endMinutes === null) return null;
|
|
64559
64848
|
const shiftStartDate = dateFnsTz.fromZonedTime(`${shift.date}T${startTime}:00`, timezone);
|
|
64560
64849
|
let durationMinutes = endMinutes - startMinutes;
|
|
@@ -64592,7 +64881,7 @@ var createKpisOverviewUrl = ({
|
|
|
64592
64881
|
return queryString ? `/kpis?${queryString}` : "/kpis";
|
|
64593
64882
|
};
|
|
64594
64883
|
var getZonedDateAtMidday = (dateKey, timezone) => dateFnsTz.fromZonedTime(`${dateKey}T12:00:00`, timezone);
|
|
64595
|
-
var
|
|
64884
|
+
var formatDateKey2 = (dateKey, timezone, options) => {
|
|
64596
64885
|
try {
|
|
64597
64886
|
return new Intl.DateTimeFormat("en-US", {
|
|
64598
64887
|
...options,
|
|
@@ -65660,7 +65949,7 @@ var KPIsOverviewView = ({
|
|
|
65660
65949
|
setActiveTab(newTab);
|
|
65661
65950
|
}, [activeTab, leaderboardLines.length, lines.length]);
|
|
65662
65951
|
const formatLocalDate2 = React143.useCallback((dateKey) => {
|
|
65663
|
-
return
|
|
65952
|
+
return formatDateKey2(dateKey, configuredTimezone, {
|
|
65664
65953
|
year: "numeric",
|
|
65665
65954
|
month: "long",
|
|
65666
65955
|
day: "numeric"
|
|
@@ -65674,8 +65963,8 @@ var KPIsOverviewView = ({
|
|
|
65674
65963
|
zonedNow.getMonth(),
|
|
65675
65964
|
new Date(zonedNow.getFullYear(), zonedNow.getMonth() + 1, 0).getDate()
|
|
65676
65965
|
);
|
|
65677
|
-
const startLabel =
|
|
65678
|
-
const endLabel =
|
|
65966
|
+
const startLabel = formatDateKey2(startOfMonthKey, configuredTimezone, { month: "short", day: "numeric" });
|
|
65967
|
+
const endLabel = formatDateKey2(endOfMonthKey, configuredTimezone, { month: "short", day: "numeric" });
|
|
65679
65968
|
return `${startLabel} - ${endLabel}, ${zonedNow.getFullYear()}`;
|
|
65680
65969
|
};
|
|
65681
65970
|
const isMonthlyMode = activeTab === "leaderboard" && timeRange === "monthly";
|
|
@@ -71310,6 +71599,7 @@ var WorkspaceDetailView = ({
|
|
|
71310
71599
|
efficiency: monitoringMode === "uptime" ? Number.isFinite(metric.avg_efficiency) ? Number(metric.avg_efficiency) : computedUptimeEfficiency : Number.isFinite(metric.avg_efficiency) ? Number(metric.avg_efficiency) : 0,
|
|
71311
71600
|
output: metric.total_output || 0,
|
|
71312
71601
|
cycleTime: metric.avg_cycle_time || 0,
|
|
71602
|
+
idealCycleTime: Number(metric.ideal_cycle_time || 0),
|
|
71313
71603
|
pph: metric.avg_pph || 0,
|
|
71314
71604
|
pphThreshold: metric.pph_threshold || 0,
|
|
71315
71605
|
idealOutput: Number(metric.ideal_output || 0),
|
|
@@ -71865,7 +72155,9 @@ var WorkspaceDetailView = ({
|
|
|
71865
72155
|
workspace,
|
|
71866
72156
|
idleTimeReasons: idleTimeChartData,
|
|
71867
72157
|
efficiencyLegend,
|
|
71868
|
-
hourlyCycleTimes: cycleTimeChartData
|
|
72158
|
+
hourlyCycleTimes: cycleTimeChartData,
|
|
72159
|
+
shiftBreaks: shiftConfig?.shifts?.find((shift2) => shift2.shiftId === workspace.shift_id)?.breaks || [],
|
|
72160
|
+
reportTimezone: shiftConfig?.timezone || timezone
|
|
71869
72161
|
}
|
|
71870
72162
|
) }),
|
|
71871
72163
|
activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -71900,6 +72192,7 @@ var WorkspaceDetailView = ({
|
|
|
71900
72192
|
workspaceId,
|
|
71901
72193
|
workspaceName: formattedWorkspaceName,
|
|
71902
72194
|
monthlyData,
|
|
72195
|
+
analysisData: analysisMonthlyData,
|
|
71903
72196
|
selectedMonth,
|
|
71904
72197
|
selectedYear,
|
|
71905
72198
|
monitoringMode: workspace?.monitoring_mode,
|
|
@@ -71908,7 +72201,10 @@ var WorkspaceDetailView = ({
|
|
|
71908
72201
|
selectedShiftId: selectedShift,
|
|
71909
72202
|
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
71910
72203
|
shiftConfig,
|
|
71911
|
-
|
|
72204
|
+
efficiencyLegend,
|
|
72205
|
+
trendSummary: workspaceMonthlyTrend,
|
|
72206
|
+
compact: true,
|
|
72207
|
+
isAssemblyWorkspace
|
|
71912
72208
|
}
|
|
71913
72209
|
)
|
|
71914
72210
|
] })
|
|
@@ -80123,7 +80419,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
80123
80419
|
};
|
|
80124
80420
|
}, [companyId, enabled, getIsPageActive, isLiveScope, lineIds.length, refreshFromResume, startPolling, stopPolling, supabase]);
|
|
80125
80421
|
};
|
|
80126
|
-
var
|
|
80422
|
+
var parseTimeToMinutes4 = (value) => {
|
|
80127
80423
|
if (!value) return null;
|
|
80128
80424
|
const parts = value.split(":");
|
|
80129
80425
|
if (parts.length < 2) return null;
|
|
@@ -80158,8 +80454,8 @@ var classifyShiftBucket = ({
|
|
|
80158
80454
|
return "day";
|
|
80159
80455
|
}
|
|
80160
80456
|
}
|
|
80161
|
-
const startMinutes =
|
|
80162
|
-
const endMinutes =
|
|
80457
|
+
const startMinutes = parseTimeToMinutes4(startTime);
|
|
80458
|
+
const endMinutes = parseTimeToMinutes4(endTime);
|
|
80163
80459
|
if (startMinutes !== null) {
|
|
80164
80460
|
if (startMinutes >= 4 * 60 && startMinutes < 18 * 60) return "day";
|
|
80165
80461
|
return "night";
|
|
@@ -80218,8 +80514,8 @@ var getShiftWindowsForConfig = (shiftConfig, timezone) => {
|
|
|
80218
80514
|
];
|
|
80219
80515
|
};
|
|
80220
80516
|
var normalizeShiftWindowMinutes = (startTime, endTime) => {
|
|
80221
|
-
const startMinutes =
|
|
80222
|
-
const endMinutesRaw =
|
|
80517
|
+
const startMinutes = parseTimeToMinutes4(startTime);
|
|
80518
|
+
const endMinutesRaw = parseTimeToMinutes4(endTime);
|
|
80223
80519
|
if (startMinutes === null || endMinutesRaw === null) {
|
|
80224
80520
|
return null;
|
|
80225
80521
|
}
|
|
@@ -80385,7 +80681,7 @@ var PlantHeadView = () => {
|
|
|
80385
80681
|
startTime: shift.startTime,
|
|
80386
80682
|
endTime: shift.endTime
|
|
80387
80683
|
});
|
|
80388
|
-
const startMinutes =
|
|
80684
|
+
const startMinutes = parseTimeToMinutes4(shift.startTime);
|
|
80389
80685
|
if (bucket === "day" && startMinutes !== null) {
|
|
80390
80686
|
candidateStarts.push(startMinutes);
|
|
80391
80687
|
}
|
|
@@ -80395,7 +80691,7 @@ var PlantHeadView = () => {
|
|
|
80395
80691
|
scopedLineIds.forEach((lineId) => {
|
|
80396
80692
|
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
80397
80693
|
getShiftWindowsForConfig(shiftConfig).forEach((shift) => {
|
|
80398
|
-
const startMinutes =
|
|
80694
|
+
const startMinutes = parseTimeToMinutes4(shift.startTime);
|
|
80399
80695
|
if (startMinutes !== null) {
|
|
80400
80696
|
candidateStarts.push(startMinutes);
|
|
80401
80697
|
}
|
|
@@ -80486,7 +80782,7 @@ var PlantHeadView = () => {
|
|
|
80486
80782
|
startTime: shift.startTime,
|
|
80487
80783
|
endTime: shift.endTime
|
|
80488
80784
|
});
|
|
80489
|
-
return bucket === "day" ?
|
|
80785
|
+
return bucket === "day" ? parseTimeToMinutes4(shift.startTime) : null;
|
|
80490
80786
|
}).filter((value) => value !== null);
|
|
80491
80787
|
}) : [];
|
|
80492
80788
|
if (dayStartCandidates.length > 0) {
|