@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.mjs
CHANGED
|
@@ -1638,6 +1638,7 @@ var DEFAULT_SHIFT_DATA = {
|
|
|
1638
1638
|
efficiency: 0,
|
|
1639
1639
|
output: 0,
|
|
1640
1640
|
cycleTime: 0,
|
|
1641
|
+
idealCycleTime: 0,
|
|
1641
1642
|
pph: 0,
|
|
1642
1643
|
pphThreshold: 0,
|
|
1643
1644
|
idealOutput: 0,
|
|
@@ -4484,6 +4485,7 @@ var dashboardService = {
|
|
|
4484
4485
|
avg_efficiency: item.avg_efficiency || 0,
|
|
4485
4486
|
total_output: item.total_output || 0,
|
|
4486
4487
|
avg_cycle_time: item.avg_cycle_time || 0,
|
|
4488
|
+
ideal_cycle_time: item.ideal_cycle_time ?? 0,
|
|
4487
4489
|
ideal_output: item.ideal_output || 0,
|
|
4488
4490
|
total_day_output: item.total_day_output ?? item.ideal_output ?? 0,
|
|
4489
4491
|
avg_pph: item.avg_pph || 0,
|
|
@@ -17280,7 +17282,7 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17280
17282
|
const [isLoading, setIsLoading] = useState(true);
|
|
17281
17283
|
const [error, setError] = useState(null);
|
|
17282
17284
|
const supabase = useSupabase();
|
|
17283
|
-
const
|
|
17285
|
+
const parseTimeToMinutes5 = (timeStr) => {
|
|
17284
17286
|
const [hours, minutes] = timeStr.split(":").map(Number);
|
|
17285
17287
|
return hours * 60 + minutes;
|
|
17286
17288
|
};
|
|
@@ -17289,8 +17291,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17289
17291
|
return now4.getHours() * 60 + now4.getMinutes();
|
|
17290
17292
|
};
|
|
17291
17293
|
const isTimeInBreak = (breakStart, breakEnd, currentMinutes) => {
|
|
17292
|
-
const startMinutes =
|
|
17293
|
-
const endMinutes =
|
|
17294
|
+
const startMinutes = parseTimeToMinutes5(breakStart);
|
|
17295
|
+
const endMinutes = parseTimeToMinutes5(breakEnd);
|
|
17294
17296
|
if (endMinutes < startMinutes) {
|
|
17295
17297
|
return currentMinutes >= startMinutes || currentMinutes < endMinutes;
|
|
17296
17298
|
} else {
|
|
@@ -17298,8 +17300,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17298
17300
|
}
|
|
17299
17301
|
};
|
|
17300
17302
|
const calculateBreakProgress = (breakStart, breakEnd, currentMinutes) => {
|
|
17301
|
-
const startMinutes =
|
|
17302
|
-
const endMinutes =
|
|
17303
|
+
const startMinutes = parseTimeToMinutes5(breakStart);
|
|
17304
|
+
const endMinutes = parseTimeToMinutes5(breakEnd);
|
|
17303
17305
|
let elapsedMinutes = 0;
|
|
17304
17306
|
let remainingMinutes = 0;
|
|
17305
17307
|
if (endMinutes < startMinutes) {
|
|
@@ -17317,8 +17319,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17317
17319
|
return { elapsedMinutes, remainingMinutes };
|
|
17318
17320
|
};
|
|
17319
17321
|
const isTimeInShift = (startTime, endTime, currentMinutes) => {
|
|
17320
|
-
const startMinutes =
|
|
17321
|
-
const endMinutes =
|
|
17322
|
+
const startMinutes = parseTimeToMinutes5(startTime);
|
|
17323
|
+
const endMinutes = parseTimeToMinutes5(endTime);
|
|
17322
17324
|
if (endMinutes < startMinutes) {
|
|
17323
17325
|
return currentMinutes >= startMinutes || currentMinutes < endMinutes;
|
|
17324
17326
|
} else {
|
|
@@ -17378,8 +17380,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17378
17380
|
const endTime = breakItem.end || breakItem.endTime || "00:00";
|
|
17379
17381
|
let duration = breakItem.duration || 0;
|
|
17380
17382
|
if (!duration || duration === 0) {
|
|
17381
|
-
const startMinutes =
|
|
17382
|
-
const endMinutes =
|
|
17383
|
+
const startMinutes = parseTimeToMinutes5(startTime);
|
|
17384
|
+
const endMinutes = parseTimeToMinutes5(endTime);
|
|
17383
17385
|
duration = endMinutes < startMinutes ? endMinutes + 24 * 60 - startMinutes : endMinutes - startMinutes;
|
|
17384
17386
|
}
|
|
17385
17387
|
return {
|
|
@@ -17395,8 +17397,8 @@ var useActiveBreaks = (lineIds) => {
|
|
|
17395
17397
|
const endTime = breakItem.end || breakItem.endTime || "00:00";
|
|
17396
17398
|
let duration = breakItem.duration || 0;
|
|
17397
17399
|
if (!duration || duration === 0) {
|
|
17398
|
-
const startMinutes =
|
|
17399
|
-
const endMinutes =
|
|
17400
|
+
const startMinutes = parseTimeToMinutes5(startTime);
|
|
17401
|
+
const endMinutes = parseTimeToMinutes5(endTime);
|
|
17400
17402
|
duration = endMinutes < startMinutes ? endMinutes + 24 * 60 - startMinutes : endMinutes - startMinutes;
|
|
17401
17403
|
}
|
|
17402
17404
|
return {
|
|
@@ -33411,13 +33413,13 @@ var CycleTimeOverTimeChart = ({
|
|
|
33411
33413
|
observer.observe(containerRef.current);
|
|
33412
33414
|
return () => observer.disconnect();
|
|
33413
33415
|
}, []);
|
|
33414
|
-
const
|
|
33416
|
+
const parseTimeToMinutes5 = (value) => {
|
|
33415
33417
|
const [hours, minutes] = value.split(":").map(Number);
|
|
33416
33418
|
if (!Number.isFinite(hours) || !Number.isFinite(minutes)) return 0;
|
|
33417
33419
|
return hours * 60 + minutes;
|
|
33418
33420
|
};
|
|
33419
33421
|
const formatHourLabel = (slotIndex) => {
|
|
33420
|
-
const baseMinutes =
|
|
33422
|
+
const baseMinutes = parseTimeToMinutes5(shiftStart);
|
|
33421
33423
|
const absoluteMinutes = baseMinutes + slotIndex * 60;
|
|
33422
33424
|
const hour24 = Math.floor(absoluteMinutes % (24 * 60) / 60);
|
|
33423
33425
|
const ampm = hour24 >= 12 ? "PM" : "AM";
|
|
@@ -47874,6 +47876,7 @@ var LineMonthlyPdfGenerator = ({
|
|
|
47874
47876
|
rangeEnd,
|
|
47875
47877
|
selectedShiftId,
|
|
47876
47878
|
availableShifts,
|
|
47879
|
+
lineAssembly = false,
|
|
47877
47880
|
compact = false,
|
|
47878
47881
|
className
|
|
47879
47882
|
}) => {
|
|
@@ -48157,8 +48160,8 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48157
48160
|
timeZone: "Asia/Kolkata"
|
|
48158
48161
|
});
|
|
48159
48162
|
doc.text(dateStr, 25, yPos);
|
|
48160
|
-
doc.text(`${shift.
|
|
48161
|
-
doc.text(`${shift.
|
|
48163
|
+
doc.text(`${Math.round(shift.output || 0)}`, 60, yPos);
|
|
48164
|
+
doc.text(`${Math.round(shift.idealOutput || 0)}`, 95, yPos);
|
|
48162
48165
|
doc.text(`${shift.avg_efficiency.toFixed(1)}%`, 135, yPos);
|
|
48163
48166
|
const statusColor = getEfficiencyColor(shift.avg_efficiency, effectiveLegend);
|
|
48164
48167
|
if (statusColor === "green") {
|
|
@@ -48188,6 +48191,8 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48188
48191
|
doc.setTextColor(0, 0, 0);
|
|
48189
48192
|
}
|
|
48190
48193
|
const poorestWorkspaces = underperformingWorkspaces[selectedShiftId] || [];
|
|
48194
|
+
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);
|
|
48195
|
+
const showCycleTimePoorestPerformers = !isUptimeMode && poorestWorkspaces.some(isCycleTimeWorkspace);
|
|
48191
48196
|
if (poorestWorkspaces && poorestWorkspaces.length > 0) {
|
|
48192
48197
|
doc.addPage();
|
|
48193
48198
|
doc.setFontSize(14);
|
|
@@ -48213,7 +48218,11 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48213
48218
|
doc.setFillColor(245, 245, 245);
|
|
48214
48219
|
doc.roundedRect(20, 45, 170, 8, 1, 1, "F");
|
|
48215
48220
|
doc.text("Workspace", 25, 50);
|
|
48216
|
-
doc.text(
|
|
48221
|
+
doc.text(
|
|
48222
|
+
isUptimeMode ? "Avg Utilization" : showCycleTimePoorestPerformers ? "Cycle Time" : "Avg Efficiency",
|
|
48223
|
+
120,
|
|
48224
|
+
50
|
|
48225
|
+
);
|
|
48217
48226
|
doc.text("Last 5 Days", 160, 50);
|
|
48218
48227
|
doc.setLineWidth(0.2);
|
|
48219
48228
|
doc.setDrawColor(220, 220, 220);
|
|
@@ -48232,7 +48241,16 @@ var LineMonthlyPdfGenerator = ({
|
|
|
48232
48241
|
);
|
|
48233
48242
|
const workspaceName = rawWorkspaceName.length > 30 ? `${rawWorkspaceName.substring(0, 27)}...` : rawWorkspaceName;
|
|
48234
48243
|
doc.text(workspaceName, 25, yPos2);
|
|
48235
|
-
|
|
48244
|
+
if (isUptimeMode) {
|
|
48245
|
+
doc.text(`${(workspace.avg_efficiency || 0).toFixed(1)}%`, 120, yPos2);
|
|
48246
|
+
} else if (isCycleTimeWorkspace(workspace)) {
|
|
48247
|
+
const actualCycleTime = Number.isFinite(workspace.avg_cycle_time) ? Number(workspace.avg_cycle_time) : null;
|
|
48248
|
+
const targetCycleTime = Number.isFinite(workspace.ideal_cycle_time) ? Number(workspace.ideal_cycle_time) : null;
|
|
48249
|
+
const cycleTimeText = actualCycleTime !== null ? `${actualCycleTime.toFixed(1)}s${targetCycleTime !== null ? ` / ${targetCycleTime.toFixed(1)}s` : ""}` : "-";
|
|
48250
|
+
doc.text(cycleTimeText, 120, yPos2);
|
|
48251
|
+
} else {
|
|
48252
|
+
doc.text(`${(workspace.avg_efficiency || 0).toFixed(1)}%`, 120, yPos2);
|
|
48253
|
+
}
|
|
48236
48254
|
const squareSize = 3;
|
|
48237
48255
|
const squareSpacing = 1;
|
|
48238
48256
|
let squareX = 160;
|
|
@@ -48327,12 +48345,279 @@ Underperforming Workspaces: ${lineInfo.metrics.underperforming_workspaces} / ${l
|
|
|
48327
48345
|
}
|
|
48328
48346
|
);
|
|
48329
48347
|
};
|
|
48348
|
+
|
|
48349
|
+
// src/lib/utils/hourlyTargets.ts
|
|
48350
|
+
var stripSeconds2 = (timeStr) => timeStr ? timeStr.slice(0, 5) : timeStr;
|
|
48351
|
+
var MINUTES_PER_DAY = 24 * 60;
|
|
48352
|
+
var parseTimeToMinutes2 = (timeString) => {
|
|
48353
|
+
const normalized = stripSeconds2(timeString || "");
|
|
48354
|
+
if (!normalized || !/^[0-2]\d:[0-5]\d$/.test(normalized)) return Number.NaN;
|
|
48355
|
+
const [hours, minutes] = normalized.split(":").map(Number);
|
|
48356
|
+
return hours * 60 + minutes;
|
|
48357
|
+
};
|
|
48358
|
+
var normalizeBreaksOnShiftTimeline = (shiftStart, breaks) => {
|
|
48359
|
+
const shiftStartMinutes = parseTimeToMinutes2(shiftStart);
|
|
48360
|
+
if (!Number.isFinite(shiftStartMinutes)) return [];
|
|
48361
|
+
const normalizedBreaks = [];
|
|
48362
|
+
for (const entry of breaks) {
|
|
48363
|
+
const startRaw = parseTimeToMinutes2(entry.startTime);
|
|
48364
|
+
const endRaw = parseTimeToMinutes2(entry.endTime);
|
|
48365
|
+
if (!Number.isFinite(startRaw) || !Number.isFinite(endRaw)) continue;
|
|
48366
|
+
let start = startRaw;
|
|
48367
|
+
let end = endRaw;
|
|
48368
|
+
if (end <= start) {
|
|
48369
|
+
end += 24 * 60;
|
|
48370
|
+
}
|
|
48371
|
+
if (start < shiftStartMinutes) {
|
|
48372
|
+
start += 24 * 60;
|
|
48373
|
+
end += 24 * 60;
|
|
48374
|
+
}
|
|
48375
|
+
const label = entry.remarks?.trim() || "Break";
|
|
48376
|
+
normalizedBreaks.push({ start, end, label });
|
|
48377
|
+
}
|
|
48378
|
+
return normalizedBreaks;
|
|
48379
|
+
};
|
|
48380
|
+
var roundTarget = (value, mode) => {
|
|
48381
|
+
if (!Number.isFinite(value)) return 0;
|
|
48382
|
+
switch (mode) {
|
|
48383
|
+
case "floor":
|
|
48384
|
+
return Math.floor(value);
|
|
48385
|
+
case "ceil":
|
|
48386
|
+
return Math.ceil(value);
|
|
48387
|
+
case "round":
|
|
48388
|
+
default:
|
|
48389
|
+
return Math.round(value);
|
|
48390
|
+
}
|
|
48391
|
+
};
|
|
48392
|
+
var formatDateKey = (date) => {
|
|
48393
|
+
const year = date.getUTCFullYear();
|
|
48394
|
+
const month = `${date.getUTCMonth() + 1}`.padStart(2, "0");
|
|
48395
|
+
const day = `${date.getUTCDate()}`.padStart(2, "0");
|
|
48396
|
+
return `${year}-${month}-${day}`;
|
|
48397
|
+
};
|
|
48398
|
+
var shiftDateKey = (dateKey, deltaDays) => {
|
|
48399
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
48400
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
48401
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
48402
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
48403
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
48404
|
+
date.setUTCDate(date.getUTCDate() + deltaDays);
|
|
48405
|
+
return formatDateKey(date);
|
|
48406
|
+
};
|
|
48407
|
+
var getZonedNowSnapshot = (timeZone, now4) => {
|
|
48408
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
48409
|
+
timeZone,
|
|
48410
|
+
year: "numeric",
|
|
48411
|
+
month: "2-digit",
|
|
48412
|
+
day: "2-digit",
|
|
48413
|
+
hour: "2-digit",
|
|
48414
|
+
minute: "2-digit",
|
|
48415
|
+
hourCycle: "h23"
|
|
48416
|
+
});
|
|
48417
|
+
const parts = formatter.formatToParts(now4).reduce((acc, part) => {
|
|
48418
|
+
if (part.type !== "literal") {
|
|
48419
|
+
acc[part.type] = part.value;
|
|
48420
|
+
}
|
|
48421
|
+
return acc;
|
|
48422
|
+
}, {});
|
|
48423
|
+
const year = Number(parts.year);
|
|
48424
|
+
const month = Number(parts.month);
|
|
48425
|
+
const day = Number(parts.day);
|
|
48426
|
+
const hour = Number(parts.hour);
|
|
48427
|
+
const minute = Number(parts.minute);
|
|
48428
|
+
return {
|
|
48429
|
+
dateKey: `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`,
|
|
48430
|
+
minutesOfDay: (Number.isFinite(hour) ? hour : 0) * 60 + (Number.isFinite(minute) ? minute : 0)
|
|
48431
|
+
};
|
|
48432
|
+
};
|
|
48433
|
+
var getDateKeyInTimeZone = (timeZone, now4 = /* @__PURE__ */ new Date()) => getZonedNowSnapshot(timeZone, now4).dateKey;
|
|
48434
|
+
var buildHourlyIntervals = ({
|
|
48435
|
+
shiftStart,
|
|
48436
|
+
shiftEnd,
|
|
48437
|
+
bucketMinutes = 60,
|
|
48438
|
+
fallbackHours = 11
|
|
48439
|
+
}) => {
|
|
48440
|
+
const startMinutes = parseTimeToMinutes2(shiftStart);
|
|
48441
|
+
if (!Number.isFinite(startMinutes)) return [];
|
|
48442
|
+
const bucket = Number.isFinite(bucketMinutes) && bucketMinutes > 0 ? Math.floor(bucketMinutes) : 60;
|
|
48443
|
+
let totalMinutes;
|
|
48444
|
+
const endRaw = shiftEnd ? parseTimeToMinutes2(shiftEnd) : Number.NaN;
|
|
48445
|
+
if (!Number.isFinite(endRaw)) {
|
|
48446
|
+
totalMinutes = Math.max(0, Math.round(fallbackHours * 60));
|
|
48447
|
+
} else {
|
|
48448
|
+
let endMinutes = endRaw;
|
|
48449
|
+
if (endMinutes <= startMinutes) {
|
|
48450
|
+
endMinutes += 24 * 60;
|
|
48451
|
+
}
|
|
48452
|
+
totalMinutes = endMinutes - startMinutes;
|
|
48453
|
+
}
|
|
48454
|
+
if (!Number.isFinite(totalMinutes) || totalMinutes <= 0) return [];
|
|
48455
|
+
const count = Math.ceil(totalMinutes / bucket);
|
|
48456
|
+
const shiftEndMinutes = startMinutes + totalMinutes;
|
|
48457
|
+
const intervals = [];
|
|
48458
|
+
for (let i = 0; i < count; i += 1) {
|
|
48459
|
+
const start = startMinutes + i * bucket;
|
|
48460
|
+
const end = Math.min(start + bucket, shiftEndMinutes);
|
|
48461
|
+
const minutes = Math.max(0, end - start);
|
|
48462
|
+
if (minutes <= 0) continue;
|
|
48463
|
+
intervals.push({ start, end, minutes });
|
|
48464
|
+
}
|
|
48465
|
+
return intervals;
|
|
48466
|
+
};
|
|
48467
|
+
var computeBreakMinutesByInterval = ({
|
|
48468
|
+
intervals,
|
|
48469
|
+
shiftStart,
|
|
48470
|
+
breaks
|
|
48471
|
+
}) => {
|
|
48472
|
+
if (!intervals.length || !breaks.length) return intervals.map(() => 0);
|
|
48473
|
+
const normalizedBreaks = normalizeBreaksOnShiftTimeline(shiftStart, breaks);
|
|
48474
|
+
return intervals.map((interval) => {
|
|
48475
|
+
if (!normalizedBreaks.length) return 0;
|
|
48476
|
+
let total = 0;
|
|
48477
|
+
for (const brk of normalizedBreaks) {
|
|
48478
|
+
const overlap = Math.max(0, Math.min(interval.end, brk.end) - Math.max(interval.start, brk.start));
|
|
48479
|
+
total += overlap;
|
|
48480
|
+
if (total >= interval.minutes) return interval.minutes;
|
|
48481
|
+
}
|
|
48482
|
+
return Math.min(interval.minutes, total);
|
|
48483
|
+
});
|
|
48484
|
+
};
|
|
48485
|
+
var computeBreakRemarksByInterval = ({
|
|
48486
|
+
intervals,
|
|
48487
|
+
shiftStart,
|
|
48488
|
+
breaks
|
|
48489
|
+
}) => {
|
|
48490
|
+
if (!intervals.length || !breaks.length) return intervals.map(() => "");
|
|
48491
|
+
const normalizedBreaks = normalizeBreaksOnShiftTimeline(shiftStart, breaks);
|
|
48492
|
+
return intervals.map((interval) => {
|
|
48493
|
+
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);
|
|
48494
|
+
return labels.join(", ");
|
|
48495
|
+
});
|
|
48496
|
+
};
|
|
48497
|
+
var computeEffectiveTargets = ({
|
|
48498
|
+
intervals,
|
|
48499
|
+
breakMinutes,
|
|
48500
|
+
pphThreshold,
|
|
48501
|
+
rounding = "round"
|
|
48502
|
+
}) => {
|
|
48503
|
+
return intervals.map((interval, idx) => {
|
|
48504
|
+
const intervalMinutes = Number(interval?.minutes) || 0;
|
|
48505
|
+
const breakMins = Number(breakMinutes?.[idx]) || 0;
|
|
48506
|
+
const plannedWorkMinutes = Math.max(0, intervalMinutes - breakMins);
|
|
48507
|
+
if (!Number.isFinite(pphThreshold) || pphThreshold <= 0) return 0;
|
|
48508
|
+
if (plannedWorkMinutes <= 0) return 0;
|
|
48509
|
+
return roundTarget(pphThreshold * plannedWorkMinutes / 60, rounding);
|
|
48510
|
+
});
|
|
48511
|
+
};
|
|
48512
|
+
var buildHourlyTargetPlan = ({
|
|
48513
|
+
shiftStart,
|
|
48514
|
+
shiftEnd,
|
|
48515
|
+
breaks = [],
|
|
48516
|
+
pphThreshold,
|
|
48517
|
+
bucketMinutes = 60,
|
|
48518
|
+
fallbackHours = 11,
|
|
48519
|
+
rounding = "round"
|
|
48520
|
+
}) => {
|
|
48521
|
+
const intervals = buildHourlyIntervals({
|
|
48522
|
+
shiftStart,
|
|
48523
|
+
shiftEnd,
|
|
48524
|
+
bucketMinutes,
|
|
48525
|
+
fallbackHours
|
|
48526
|
+
});
|
|
48527
|
+
const breakMinutes = computeBreakMinutesByInterval({
|
|
48528
|
+
intervals,
|
|
48529
|
+
shiftStart,
|
|
48530
|
+
breaks
|
|
48531
|
+
});
|
|
48532
|
+
const breakRemarks = computeBreakRemarksByInterval({
|
|
48533
|
+
intervals,
|
|
48534
|
+
shiftStart,
|
|
48535
|
+
breaks
|
|
48536
|
+
});
|
|
48537
|
+
const productiveMinutes = intervals.map((interval, idx) => Math.max(0, (Number(interval?.minutes) || 0) - (Number(breakMinutes[idx]) || 0)));
|
|
48538
|
+
const targets = computeEffectiveTargets({
|
|
48539
|
+
intervals,
|
|
48540
|
+
breakMinutes,
|
|
48541
|
+
pphThreshold,
|
|
48542
|
+
rounding
|
|
48543
|
+
});
|
|
48544
|
+
return {
|
|
48545
|
+
intervals,
|
|
48546
|
+
breakMinutes,
|
|
48547
|
+
breakRemarks,
|
|
48548
|
+
productiveMinutes,
|
|
48549
|
+
targets
|
|
48550
|
+
};
|
|
48551
|
+
};
|
|
48552
|
+
var isHourlyIntervalComplete = ({
|
|
48553
|
+
reportDate,
|
|
48554
|
+
shiftStart,
|
|
48555
|
+
shiftEnd,
|
|
48556
|
+
interval,
|
|
48557
|
+
timeZone = "Asia/Kolkata",
|
|
48558
|
+
now: now4 = /* @__PURE__ */ new Date()
|
|
48559
|
+
}) => {
|
|
48560
|
+
if (!reportDate) return true;
|
|
48561
|
+
const snapshot = getZonedNowSnapshot(timeZone, now4);
|
|
48562
|
+
const shiftStartMinutes = parseTimeToMinutes2(shiftStart);
|
|
48563
|
+
const shiftEndMinutes = shiftEnd ? parseTimeToMinutes2(shiftEnd) : Number.NaN;
|
|
48564
|
+
const wrapsMidnight = Number.isFinite(shiftStartMinutes) && Number.isFinite(shiftEndMinutes) && shiftEndMinutes <= shiftStartMinutes;
|
|
48565
|
+
if (reportDate === snapshot.dateKey) {
|
|
48566
|
+
return interval.end <= snapshot.minutesOfDay;
|
|
48567
|
+
}
|
|
48568
|
+
if (wrapsMidnight && reportDate === shiftDateKey(snapshot.dateKey, -1)) {
|
|
48569
|
+
return interval.end <= snapshot.minutesOfDay + MINUTES_PER_DAY;
|
|
48570
|
+
}
|
|
48571
|
+
return reportDate < snapshot.dateKey;
|
|
48572
|
+
};
|
|
48573
|
+
var isShiftInProgressForReportDate = ({
|
|
48574
|
+
reportDate,
|
|
48575
|
+
shiftStart,
|
|
48576
|
+
shiftEnd,
|
|
48577
|
+
timeZone = "Asia/Kolkata",
|
|
48578
|
+
now: now4 = /* @__PURE__ */ new Date()
|
|
48579
|
+
}) => {
|
|
48580
|
+
if (!reportDate || !shiftStart || !shiftEnd) return false;
|
|
48581
|
+
const shiftStartMinutes = parseTimeToMinutes2(shiftStart);
|
|
48582
|
+
const shiftEndMinutesRaw = parseTimeToMinutes2(shiftEnd);
|
|
48583
|
+
if (!Number.isFinite(shiftStartMinutes) || !Number.isFinite(shiftEndMinutesRaw)) {
|
|
48584
|
+
return false;
|
|
48585
|
+
}
|
|
48586
|
+
let shiftEndMinutes = shiftEndMinutesRaw;
|
|
48587
|
+
const wrapsMidnight = shiftEndMinutes <= shiftStartMinutes;
|
|
48588
|
+
if (wrapsMidnight) {
|
|
48589
|
+
shiftEndMinutes += MINUTES_PER_DAY;
|
|
48590
|
+
}
|
|
48591
|
+
const snapshot = getZonedNowSnapshot(timeZone, now4);
|
|
48592
|
+
let currentMinutes = null;
|
|
48593
|
+
if (reportDate === snapshot.dateKey) {
|
|
48594
|
+
currentMinutes = snapshot.minutesOfDay;
|
|
48595
|
+
} else if (wrapsMidnight && reportDate === shiftDateKey(snapshot.dateKey, -1)) {
|
|
48596
|
+
currentMinutes = snapshot.minutesOfDay + MINUTES_PER_DAY;
|
|
48597
|
+
}
|
|
48598
|
+
if (currentMinutes === null) {
|
|
48599
|
+
return false;
|
|
48600
|
+
}
|
|
48601
|
+
return shiftStartMinutes <= currentMinutes && currentMinutes < shiftEndMinutes;
|
|
48602
|
+
};
|
|
48603
|
+
var formatOperationalDateKey = (dateKey, options) => {
|
|
48604
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
48605
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
48606
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
48607
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
48608
|
+
return new Date(Date.UTC(year, month - 1, day, 12)).toLocaleDateString("en-IN", {
|
|
48609
|
+
...options,
|
|
48610
|
+
timeZone: "UTC"
|
|
48611
|
+
});
|
|
48612
|
+
};
|
|
48330
48613
|
var LinePdfGenerator = ({
|
|
48331
48614
|
lineInfo,
|
|
48332
48615
|
workspaceData,
|
|
48333
48616
|
issueResolutionSummary,
|
|
48334
48617
|
shiftName,
|
|
48335
|
-
className
|
|
48618
|
+
className,
|
|
48619
|
+
shiftBreaks = [],
|
|
48620
|
+
reportTimezone = "Asia/Kolkata"
|
|
48336
48621
|
}) => {
|
|
48337
48622
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
48338
48623
|
const formatResolutionDuration2 = (seconds) => {
|
|
@@ -48359,7 +48644,7 @@ var LinePdfGenerator = ({
|
|
|
48359
48644
|
doc.setFontSize(9);
|
|
48360
48645
|
doc.setFont("helvetica", "normal");
|
|
48361
48646
|
doc.setTextColor(100, 100, 100);
|
|
48362
|
-
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone:
|
|
48647
|
+
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone: reportTimezone })}`;
|
|
48363
48648
|
const generatedTextWidth = doc.getStringUnitWidth(generatedText) * 9 / doc.internal.scaleFactor;
|
|
48364
48649
|
doc.text(generatedText, doc.internal.pageSize.width - 20 - generatedTextWidth, 15);
|
|
48365
48650
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -48377,11 +48662,10 @@ var LinePdfGenerator = ({
|
|
|
48377
48662
|
const isUptimeMode = lineInfo.monitoring_mode === "uptime";
|
|
48378
48663
|
const rawShiftType = shiftName || (lineInfo.shift_id === 0 ? "Day" : lineInfo.shift_id === 1 ? "Night" : `Shift ${lineInfo.shift_id}`);
|
|
48379
48664
|
const shiftType = rawShiftType.toLowerCase().includes("shift") ? rawShiftType : `${rawShiftType} Shift`;
|
|
48380
|
-
const date =
|
|
48665
|
+
const date = formatOperationalDateKey(lineInfo.date, {
|
|
48381
48666
|
weekday: "long",
|
|
48382
48667
|
day: "numeric",
|
|
48383
|
-
month: "long"
|
|
48384
|
-
timeZone: "Asia/Kolkata"
|
|
48668
|
+
month: "long"
|
|
48385
48669
|
});
|
|
48386
48670
|
const shiftStartTime = lineInfo.metrics.shift_start ? (/* @__PURE__ */ new Date(`2000-01-01 ${lineInfo.metrics.shift_start}`)).toLocaleTimeString("en-IN", {
|
|
48387
48671
|
hour: "2-digit",
|
|
@@ -48389,24 +48673,25 @@ var LinePdfGenerator = ({
|
|
|
48389
48673
|
hour12: true,
|
|
48390
48674
|
timeZone: "Asia/Kolkata"
|
|
48391
48675
|
}) : "N/A";
|
|
48392
|
-
const
|
|
48393
|
-
|
|
48394
|
-
|
|
48395
|
-
|
|
48396
|
-
|
|
48397
|
-
|
|
48398
|
-
|
|
48399
|
-
|
|
48400
|
-
|
|
48401
|
-
|
|
48402
|
-
|
|
48403
|
-
|
|
48404
|
-
|
|
48405
|
-
|
|
48406
|
-
|
|
48407
|
-
}
|
|
48676
|
+
const currentTime = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-IN", {
|
|
48677
|
+
hour: "2-digit",
|
|
48678
|
+
minute: "2-digit",
|
|
48679
|
+
timeZone: reportTimezone
|
|
48680
|
+
});
|
|
48681
|
+
const reportEndTime = isShiftInProgressForReportDate({
|
|
48682
|
+
reportDate: lineInfo.date,
|
|
48683
|
+
shiftStart: lineInfo.metrics.shift_start || "",
|
|
48684
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
48685
|
+
timeZone: reportTimezone
|
|
48686
|
+
}) ? currentTime : lineInfo.metrics.shift_end ? (/* @__PURE__ */ new Date(`2000-01-01 ${lineInfo.metrics.shift_end}`)).toLocaleTimeString("en-IN", {
|
|
48687
|
+
hour: "2-digit",
|
|
48688
|
+
minute: "2-digit",
|
|
48689
|
+
hour12: true,
|
|
48690
|
+
timeZone: "Asia/Kolkata"
|
|
48691
|
+
}) : "N/A";
|
|
48408
48692
|
if (isUptimeMode) {
|
|
48409
48693
|
const configuredTimezone = "Asia/Kolkata";
|
|
48694
|
+
const effectiveUptimeTimezone = reportTimezone || configuredTimezone;
|
|
48410
48695
|
const lineShiftStart = lineInfo.metrics.shift_start || "06:00";
|
|
48411
48696
|
const lineShiftEnd = lineInfo.metrics.shift_end || "14:00";
|
|
48412
48697
|
const shiftMinutes = getShiftDurationMinutes(lineShiftStart, lineShiftEnd) || 0;
|
|
@@ -48420,7 +48705,7 @@ var LinePdfGenerator = ({
|
|
|
48420
48705
|
shiftStart,
|
|
48421
48706
|
shiftEnd,
|
|
48422
48707
|
shiftDate,
|
|
48423
|
-
timezone:
|
|
48708
|
+
timezone: effectiveUptimeTimezone
|
|
48424
48709
|
});
|
|
48425
48710
|
let activeMinutes = uptimeSeries.activeMinutes;
|
|
48426
48711
|
let idleMinutes = uptimeSeries.idleMinutes;
|
|
@@ -48501,7 +48786,7 @@ var LinePdfGenerator = ({
|
|
|
48501
48786
|
shiftStart: lineShiftStart,
|
|
48502
48787
|
shiftEnd: lineShiftEnd,
|
|
48503
48788
|
shiftDate: lineInfo.date,
|
|
48504
|
-
timezone:
|
|
48789
|
+
timezone: effectiveUptimeTimezone
|
|
48505
48790
|
});
|
|
48506
48791
|
hourlyData = buildHourlyFromSeries(lineUptimeSeries);
|
|
48507
48792
|
}
|
|
@@ -48609,13 +48894,13 @@ var LinePdfGenerator = ({
|
|
|
48609
48894
|
doc.setFontSize(contentFontSize);
|
|
48610
48895
|
doc.setFont("helvetica", "normal");
|
|
48611
48896
|
let yPos2 = headerBottomY2 + 5.5;
|
|
48612
|
-
const
|
|
48613
|
-
const
|
|
48614
|
-
const [
|
|
48615
|
-
const [
|
|
48616
|
-
const
|
|
48897
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
48898
|
+
const currentTimeIST = new Date(now4.toLocaleString("en-US", { timeZone: configuredTimezone }));
|
|
48899
|
+
const [sYear, sMonth, sDay] = lineInfo.date.split("-").map(Number);
|
|
48900
|
+
const [sStartH, sStartM] = (lineShiftStart || "06:00").split(":").map(Number);
|
|
48901
|
+
const shiftStartBase = new Date(sYear, sMonth - 1, sDay, sStartH, sStartM || 0);
|
|
48617
48902
|
hourlyData.forEach((entry, index) => {
|
|
48618
|
-
const bucketStartTime = new Date(
|
|
48903
|
+
const bucketStartTime = new Date(shiftStartBase);
|
|
48619
48904
|
bucketStartTime.setHours(bucketStartTime.getHours() + index);
|
|
48620
48905
|
const bucketEndTime = new Date(bucketStartTime);
|
|
48621
48906
|
bucketEndTime.setHours(bucketEndTime.getHours() + 1);
|
|
@@ -48626,7 +48911,7 @@ var LinePdfGenerator = ({
|
|
|
48626
48911
|
hour: "numeric",
|
|
48627
48912
|
hour12: true
|
|
48628
48913
|
})}`;
|
|
48629
|
-
const dataCollected = bucketEndTime.getTime() <=
|
|
48914
|
+
const dataCollected = bucketEndTime.getTime() <= currentTimeIST.getTime();
|
|
48630
48915
|
if (index < totalRows2 - 1) {
|
|
48631
48916
|
const rowBottomY = headerBottomY2 + (index + 1) * rowHeight;
|
|
48632
48917
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -48637,11 +48922,10 @@ var LinePdfGenerator = ({
|
|
|
48637
48922
|
doc.text(utilizationStr, 147, yPos2);
|
|
48638
48923
|
yPos2 += rowHeight;
|
|
48639
48924
|
});
|
|
48640
|
-
const fileDate2 =
|
|
48925
|
+
const fileDate2 = formatOperationalDateKey(lineInfo.date, {
|
|
48641
48926
|
day: "2-digit",
|
|
48642
48927
|
month: "short",
|
|
48643
|
-
year: "numeric"
|
|
48644
|
-
timeZone: "Asia/Kolkata"
|
|
48928
|
+
year: "numeric"
|
|
48645
48929
|
}).replace(/ /g, "_");
|
|
48646
48930
|
const fileShift2 = shiftType.replace(/ /g, "_");
|
|
48647
48931
|
const fileName2 = `${lineInfo.line_name}_${fileDate2}_${fileShift2}.pdf`;
|
|
@@ -48694,66 +48978,32 @@ var LinePdfGenerator = ({
|
|
|
48694
48978
|
doc.setLineWidth(0.8);
|
|
48695
48979
|
doc.line(20, 123, 190, 123);
|
|
48696
48980
|
const hourlyOverviewStartY = 128;
|
|
48697
|
-
const parseTimeToMinutes4 = (timeStr) => {
|
|
48698
|
-
const [hours, minutes] = timeStr.split(":");
|
|
48699
|
-
const hour = parseInt(hours, 10);
|
|
48700
|
-
const minute = parseInt(minutes || "0", 10);
|
|
48701
|
-
if (Number.isNaN(hour) || Number.isNaN(minute)) {
|
|
48702
|
-
return NaN;
|
|
48703
|
-
}
|
|
48704
|
-
return (hour * 60 + minute) % (24 * 60);
|
|
48705
|
-
};
|
|
48706
48981
|
const formatMinutesLabel = (totalMinutes) => {
|
|
48707
48982
|
const normalized = (totalMinutes % (24 * 60) + 24 * 60) % (24 * 60);
|
|
48708
48983
|
const hour = Math.floor(normalized / 60);
|
|
48709
48984
|
const minute = normalized % 60;
|
|
48710
|
-
const time2 =
|
|
48711
|
-
time2.setHours(hour);
|
|
48712
|
-
time2.setMinutes(minute);
|
|
48713
|
-
time2.setSeconds(0);
|
|
48714
|
-
time2.setMilliseconds(0);
|
|
48985
|
+
const time2 = new Date(Date.UTC(2e3, 0, 1, hour, minute));
|
|
48715
48986
|
return time2.toLocaleTimeString("en-IN", {
|
|
48716
48987
|
hour: "2-digit",
|
|
48717
48988
|
minute: "2-digit",
|
|
48718
48989
|
hour12: true,
|
|
48719
|
-
timeZone: "
|
|
48720
|
-
});
|
|
48721
|
-
};
|
|
48722
|
-
const buildRange = (startMinutes, minutes) => {
|
|
48723
|
-
const endMinutes = startMinutes + minutes;
|
|
48724
|
-
return {
|
|
48725
|
-
label: `${formatMinutesLabel(startMinutes)} - ${formatMinutesLabel(endMinutes)}`,
|
|
48726
|
-
minutes
|
|
48727
|
-
};
|
|
48728
|
-
};
|
|
48729
|
-
const getHourlyTimeRanges = (startTimeStr, endTimeStr) => {
|
|
48730
|
-
const startMinutes = parseTimeToMinutes4(startTimeStr);
|
|
48731
|
-
if (Number.isNaN(startMinutes)) {
|
|
48732
|
-
return [];
|
|
48733
|
-
}
|
|
48734
|
-
if (!endTimeStr) {
|
|
48735
|
-
const defaultHours = 11;
|
|
48736
|
-
return Array.from({ length: defaultHours }, (_, i) => buildRange(startMinutes + i * 60, 60));
|
|
48737
|
-
}
|
|
48738
|
-
const endMinutes = parseTimeToMinutes4(endTimeStr);
|
|
48739
|
-
if (Number.isNaN(endMinutes)) {
|
|
48740
|
-
const fallbackHours = 11;
|
|
48741
|
-
return Array.from({ length: fallbackHours }, (_, i) => buildRange(startMinutes + i * 60, 60));
|
|
48742
|
-
}
|
|
48743
|
-
let durationMinutes = endMinutes - startMinutes;
|
|
48744
|
-
if (durationMinutes <= 0) {
|
|
48745
|
-
durationMinutes += 24 * 60;
|
|
48746
|
-
}
|
|
48747
|
-
const rangeCount = Math.max(1, Math.ceil(durationMinutes / 60));
|
|
48748
|
-
return Array.from({ length: rangeCount }, (_, i) => {
|
|
48749
|
-
const remainingMinutes = durationMinutes - i * 60;
|
|
48750
|
-
const rangeMinutes = remainingMinutes >= 60 ? 60 : remainingMinutes;
|
|
48751
|
-
return buildRange(startMinutes + i * 60, rangeMinutes);
|
|
48990
|
+
timeZone: "UTC"
|
|
48752
48991
|
});
|
|
48753
48992
|
};
|
|
48754
|
-
const hourlyTimeRanges =
|
|
48993
|
+
const hourlyTimeRanges = buildHourlyIntervals({
|
|
48994
|
+
shiftStart: lineInfo.metrics.shift_start || "06:00",
|
|
48995
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
48996
|
+
fallbackHours: 11
|
|
48997
|
+
});
|
|
48998
|
+
const targetPlan = buildHourlyTargetPlan({
|
|
48999
|
+
shiftStart: lineInfo.metrics.shift_start || "06:00",
|
|
49000
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
49001
|
+
breaks: shiftBreaks,
|
|
49002
|
+
pphThreshold: Number(lineInfo.metrics.threshold_pph ?? 0),
|
|
49003
|
+
fallbackHours: Math.max(hourlyTimeRanges.length, 1),
|
|
49004
|
+
rounding: "floor"
|
|
49005
|
+
});
|
|
48755
49006
|
const shiftDuration = hourlyTimeRanges.length || 11;
|
|
48756
|
-
const targetOutputPerHour = Math.round(lineInfo.metrics.threshold_pph ?? 0);
|
|
48757
49007
|
let hourlyActualOutput = [];
|
|
48758
49008
|
if (lineInfo.metrics.output_hourly && Object.keys(lineInfo.metrics.output_hourly).length > 0) {
|
|
48759
49009
|
const [startHourStr, startMinuteStr] = (lineInfo.metrics.shift_start || "6:00").split(":");
|
|
@@ -48939,29 +49189,29 @@ var LinePdfGenerator = ({
|
|
|
48939
49189
|
doc.text("Remarks", 160, tableHeaderY);
|
|
48940
49190
|
doc.setFont("helvetica", "normal");
|
|
48941
49191
|
let yPos = tableStartY;
|
|
48942
|
-
const now4 = /* @__PURE__ */ new Date();
|
|
48943
|
-
const currentTimeIST = new Date(now4.toLocaleString("en-US", { timeZone: "Asia/Kolkata" }));
|
|
48944
|
-
const [sYear, sMonth, sDay] = lineInfo.date.split("-").map(Number);
|
|
48945
|
-
const [sStartH, sStartM] = (lineInfo.metrics.shift_start || "06:00").split(":").map(Number);
|
|
48946
|
-
const shiftStartBase = new Date(sYear, sMonth - 1, sDay, sStartH, sStartM || 0);
|
|
48947
49192
|
hourlyTimeRanges.forEach((timeRange, index) => {
|
|
48948
49193
|
const actualOutput = hourlyActualOutput[index] || 0;
|
|
48949
|
-
const
|
|
48950
|
-
|
|
48951
|
-
|
|
48952
|
-
|
|
49194
|
+
const dataCollected = isHourlyIntervalComplete({
|
|
49195
|
+
reportDate: lineInfo.date,
|
|
49196
|
+
shiftStart: lineInfo.metrics.shift_start || "06:00",
|
|
49197
|
+
shiftEnd: lineInfo.metrics.shift_end,
|
|
49198
|
+
interval: timeRange,
|
|
49199
|
+
timeZone: reportTimezone
|
|
49200
|
+
});
|
|
48953
49201
|
const outputStr = dataCollected ? actualOutput.toString() : "TBD";
|
|
48954
49202
|
if (index < totalRows - 1) {
|
|
48955
49203
|
const rowBottomY = headerBottomY + (index + 1) * rowSpacing;
|
|
48956
49204
|
doc.setDrawColor(200, 200, 200);
|
|
48957
49205
|
doc.line(20, rowBottomY, 190, rowBottomY);
|
|
48958
49206
|
}
|
|
48959
|
-
const
|
|
48960
|
-
const
|
|
48961
|
-
const
|
|
48962
|
-
doc.text(timeRange.
|
|
49207
|
+
const targetForRange = targetPlan.targets[index] ?? 0;
|
|
49208
|
+
const targetStr = targetForRange.toString();
|
|
49209
|
+
const remarkText = targetPlan.breakRemarks[index] || "";
|
|
49210
|
+
doc.text(`${formatMinutesLabel(timeRange.start)} - ${formatMinutesLabel(timeRange.end)}`, 25, yPos);
|
|
48963
49211
|
doc.text(outputStr, 75, yPos);
|
|
48964
49212
|
doc.text(targetStr, 105, yPos);
|
|
49213
|
+
const remarkDisplay = remarkText ? doc.splitTextToSize(remarkText, 26)[0] : "";
|
|
49214
|
+
doc.text(remarkDisplay, 160, yPos);
|
|
48965
49215
|
if (!dataCollected) {
|
|
48966
49216
|
doc.setTextColor(100, 100, 100);
|
|
48967
49217
|
doc.text("-", 135, yPos);
|
|
@@ -48977,11 +49227,10 @@ var LinePdfGenerator = ({
|
|
|
48977
49227
|
doc.setTextColor(0, 0, 0);
|
|
48978
49228
|
yPos += rowSpacing;
|
|
48979
49229
|
});
|
|
48980
|
-
const fileDate =
|
|
49230
|
+
const fileDate = formatOperationalDateKey(lineInfo.date, {
|
|
48981
49231
|
day: "2-digit",
|
|
48982
49232
|
month: "short",
|
|
48983
|
-
year: "numeric"
|
|
48984
|
-
timeZone: "Asia/Kolkata"
|
|
49233
|
+
year: "numeric"
|
|
48985
49234
|
}).replace(/ /g, "_");
|
|
48986
49235
|
const fileShift = shiftType.replace(/ /g, "_");
|
|
48987
49236
|
const fileName = `${lineInfo.line_name}_${fileDate}_${fileShift}.pdf`;
|
|
@@ -49909,6 +50158,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
49909
50158
|
}, [analysisMonthlyData, selectedShiftId, isUptimeMode, shiftWorkSeconds]);
|
|
49910
50159
|
const efficiencyDelta = trendSummary?.avg_efficiency?.delta_pp ?? 0;
|
|
49911
50160
|
const efficiencyImproved = efficiencyDelta >= 0;
|
|
50161
|
+
const assemblyRangeCycleTime = useMemo(() => {
|
|
50162
|
+
const trendCycleTime = Number(trendSummary?.avg_cycle_time?.current);
|
|
50163
|
+
if (Number.isFinite(trendCycleTime) && trendCycleTime > 0) {
|
|
50164
|
+
return Math.round(trendCycleTime);
|
|
50165
|
+
}
|
|
50166
|
+
return metrics2?.avgCycleTime ?? 0;
|
|
50167
|
+
}, [trendSummary?.avg_cycle_time?.current, metrics2?.avgCycleTime]);
|
|
49912
50168
|
const cycleDeltaRaw = trendSummary?.avg_cycle_time?.delta_seconds ?? 0;
|
|
49913
50169
|
const cyclePrev = trendSummary?.avg_cycle_time?.previous ?? 0;
|
|
49914
50170
|
const cycleDelta = cyclePrev ? cycleDeltaRaw / cyclePrev * 100 : 0;
|
|
@@ -50094,7 +50350,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
50094
50350
|
/* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: "Avg Cycle Time" }),
|
|
50095
50351
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
50096
50352
|
/* @__PURE__ */ jsxs("div", { className: "text-2xl font-bold text-gray-900", children: [
|
|
50097
|
-
|
|
50353
|
+
assemblyRangeCycleTime,
|
|
50098
50354
|
"s"
|
|
50099
50355
|
] }),
|
|
50100
50356
|
/* @__PURE__ */ 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: [
|
|
@@ -50430,7 +50686,25 @@ var WorkspaceWhatsAppShareButton = ({
|
|
|
50430
50686
|
}
|
|
50431
50687
|
);
|
|
50432
50688
|
};
|
|
50433
|
-
var
|
|
50689
|
+
var formatOperationalDateKey2 = (dateKey, options) => {
|
|
50690
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
50691
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
50692
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
50693
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
50694
|
+
return new Date(Date.UTC(year, month - 1, day, 12)).toLocaleDateString("en-IN", {
|
|
50695
|
+
...options,
|
|
50696
|
+
timeZone: "UTC"
|
|
50697
|
+
});
|
|
50698
|
+
};
|
|
50699
|
+
var WorkspacePdfGenerator = ({
|
|
50700
|
+
workspace,
|
|
50701
|
+
className,
|
|
50702
|
+
idleTimeReasons,
|
|
50703
|
+
efficiencyLegend,
|
|
50704
|
+
hourlyCycleTimes,
|
|
50705
|
+
shiftBreaks = [],
|
|
50706
|
+
reportTimezone = "Asia/Kolkata"
|
|
50707
|
+
}) => {
|
|
50434
50708
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
50435
50709
|
const entityConfig = useEntityConfig();
|
|
50436
50710
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
@@ -50460,7 +50734,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50460
50734
|
doc.setFontSize(9);
|
|
50461
50735
|
doc.setFont("helvetica", "normal");
|
|
50462
50736
|
doc.setTextColor(100, 100, 100);
|
|
50463
|
-
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone:
|
|
50737
|
+
const generatedText = `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString("en-IN", { timeZone: reportTimezone })}`;
|
|
50464
50738
|
const generatedTextWidth = doc.getStringUnitWidth(generatedText) * 9 / doc.internal.scaleFactor;
|
|
50465
50739
|
doc.text(generatedText, doc.internal.pageSize.width - 20 - generatedTextWidth, 15);
|
|
50466
50740
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -50479,11 +50753,10 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50479
50753
|
doc.setFontSize(13);
|
|
50480
50754
|
doc.setFont("helvetica", "normal");
|
|
50481
50755
|
doc.setTextColor(60, 60, 60);
|
|
50482
|
-
const date =
|
|
50756
|
+
const date = formatOperationalDateKey2(workspace.date, {
|
|
50483
50757
|
weekday: "long",
|
|
50484
50758
|
day: "numeric",
|
|
50485
|
-
month: "long"
|
|
50486
|
-
timeZone: "Asia/Kolkata"
|
|
50759
|
+
month: "long"
|
|
50487
50760
|
});
|
|
50488
50761
|
const rawShiftType = workspace.shift_type || (workspace.shift_id === 0 ? "Day" : workspace.shift_id === 1 ? "Night" : `Shift ${workspace.shift_id}`);
|
|
50489
50762
|
const shiftType = rawShiftType.toLowerCase().includes("shift") ? rawShiftType : `${rawShiftType} Shift`;
|
|
@@ -50492,7 +50765,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50492
50765
|
const currentTime = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-IN", {
|
|
50493
50766
|
hour: "2-digit",
|
|
50494
50767
|
minute: "2-digit",
|
|
50495
|
-
timeZone:
|
|
50768
|
+
timeZone: reportTimezone
|
|
50496
50769
|
});
|
|
50497
50770
|
const shiftStartTime = (/* @__PURE__ */ new Date(`2000-01-01 ${workspace.shift_start}`)).toLocaleTimeString("en-IN", {
|
|
50498
50771
|
hour: "2-digit",
|
|
@@ -50504,29 +50777,12 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50504
50777
|
minute: "2-digit",
|
|
50505
50778
|
hour12: true
|
|
50506
50779
|
});
|
|
50507
|
-
const
|
|
50508
|
-
|
|
50509
|
-
|
|
50510
|
-
|
|
50511
|
-
|
|
50512
|
-
};
|
|
50513
|
-
const toShiftUtcMs = (dateKey, timeValue) => {
|
|
50514
|
-
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
50515
|
-
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
50516
|
-
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
50517
|
-
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
50518
|
-
const [hourPart, minutePart] = timeValue.split(":").map(Number);
|
|
50519
|
-
const hour = Number.isFinite(hourPart) ? hourPart : 0;
|
|
50520
|
-
const minute = Number.isFinite(minutePart) ? minutePart : 0;
|
|
50521
|
-
const IST_OFFSET_MINUTES = 330;
|
|
50522
|
-
return Date.UTC(year, month - 1, day, hour, minute) - IST_OFFSET_MINUTES * 60 * 1e3;
|
|
50523
|
-
};
|
|
50524
|
-
const shiftStartMinutes = parseTimeToMinutes4(workspace.shift_start);
|
|
50525
|
-
const shiftEndMinutes = parseTimeToMinutes4(workspace.shift_end);
|
|
50526
|
-
const wrapsMidnight = shiftEndMinutes <= shiftStartMinutes;
|
|
50527
|
-
const shiftStartUtcMs = toShiftUtcMs(workspace.date, workspace.shift_start);
|
|
50528
|
-
const shiftEndUtcMs = toShiftUtcMs(workspace.date, workspace.shift_end) + (wrapsMidnight ? 24 * 60 * 60 * 1e3 : 0);
|
|
50529
|
-
const isShiftInProgress = Date.now() >= shiftStartUtcMs && Date.now() < shiftEndUtcMs;
|
|
50780
|
+
const isShiftInProgress = isShiftInProgressForReportDate({
|
|
50781
|
+
reportDate: workspace.date,
|
|
50782
|
+
shiftStart: workspace.shift_start,
|
|
50783
|
+
shiftEnd: workspace.shift_end,
|
|
50784
|
+
timeZone: reportTimezone
|
|
50785
|
+
});
|
|
50530
50786
|
const reportPeriodEndTime = isShiftInProgress ? currentTime : shiftEndTime;
|
|
50531
50787
|
doc.setFontSize(12);
|
|
50532
50788
|
doc.setTextColor(80, 80, 80);
|
|
@@ -50632,7 +50888,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50632
50888
|
shiftStart: workspace.shift_start,
|
|
50633
50889
|
shiftEnd: workspace.shift_end,
|
|
50634
50890
|
shiftDate: workspace.date,
|
|
50635
|
-
timezone:
|
|
50891
|
+
timezone: reportTimezone
|
|
50636
50892
|
}) : null;
|
|
50637
50893
|
const hourlyUptime = uptimeSeries?.points?.length ? Array.from({ length: Math.ceil(uptimeSeries.shiftMinutes / 60) }, (_, index) => {
|
|
50638
50894
|
const start = index * 60;
|
|
@@ -50647,6 +50903,31 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50647
50903
|
const hourlyData = isUptimeMode ? hourlyUptime : isAssemblyCycleMode ? hourlyCycleTimes && hourlyCycleTimes.length > 0 ? hourlyCycleTimes : workspace.hourly_action_counts || [] : workspace.hourly_action_counts || [];
|
|
50648
50904
|
const hourlyTarget = workspace.pph_threshold;
|
|
50649
50905
|
const cycleTarget = workspace.ideal_cycle_time || 0;
|
|
50906
|
+
const hourlyIntervals = buildHourlyIntervals({
|
|
50907
|
+
shiftStart: workspace.shift_start,
|
|
50908
|
+
shiftEnd: workspace.shift_end,
|
|
50909
|
+
fallbackHours: Math.max(hourlyData.length, 1)
|
|
50910
|
+
});
|
|
50911
|
+
const outputTargetPlan = !isUptimeMode && !isAssemblyCycleMode ? buildHourlyTargetPlan({
|
|
50912
|
+
shiftStart: workspace.shift_start,
|
|
50913
|
+
shiftEnd: workspace.shift_end,
|
|
50914
|
+
breaks: shiftBreaks,
|
|
50915
|
+
pphThreshold: workspace.pph_threshold,
|
|
50916
|
+
fallbackHours: Math.max(hourlyData.length, 1),
|
|
50917
|
+
rounding: "floor"
|
|
50918
|
+
}) : null;
|
|
50919
|
+
const formatIntervalLabel = (totalMinutes) => {
|
|
50920
|
+
const normalized = (totalMinutes % (24 * 60) + 24 * 60) % (24 * 60);
|
|
50921
|
+
const hour = Math.floor(normalized / 60);
|
|
50922
|
+
const minute = normalized % 60;
|
|
50923
|
+
const time2 = new Date(Date.UTC(2e3, 0, 1, hour, minute));
|
|
50924
|
+
return time2.toLocaleTimeString("en-IN", {
|
|
50925
|
+
hour: "numeric",
|
|
50926
|
+
...minute > 0 ? { minute: "2-digit" } : {},
|
|
50927
|
+
hour12: true,
|
|
50928
|
+
timeZone: "UTC"
|
|
50929
|
+
});
|
|
50930
|
+
};
|
|
50650
50931
|
const pageHeight = doc.internal.pageSize.height;
|
|
50651
50932
|
const maxContentY = pageHeight - 15;
|
|
50652
50933
|
const baseTableStartY = hourlyPerfStartY + 31;
|
|
@@ -50714,36 +50995,30 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50714
50995
|
doc.setFontSize(contentFontSize);
|
|
50715
50996
|
doc.setFont("helvetica", "normal");
|
|
50716
50997
|
let yPos = headerBottomY + 5.5;
|
|
50717
|
-
const
|
|
50718
|
-
const today = /* @__PURE__ */ new Date();
|
|
50719
|
-
today.setHours(0, 0, 0, 0);
|
|
50720
|
-
workspaceDate.setHours(0, 0, 0, 0);
|
|
50721
|
-
const isToday2 = workspaceDate.getTime() === today.getTime();
|
|
50998
|
+
const isToday2 = getDateKeyInTimeZone(reportTimezone) === workspace.date;
|
|
50722
50999
|
let currentHour = 24;
|
|
50723
51000
|
if (isToday2) {
|
|
50724
51001
|
const now4 = /* @__PURE__ */ new Date();
|
|
50725
|
-
const
|
|
50726
|
-
currentHour =
|
|
51002
|
+
const currentTimeInReportTimezone = new Date(now4.toLocaleString("en-US", { timeZone: reportTimezone }));
|
|
51003
|
+
currentHour = currentTimeInReportTimezone.getHours();
|
|
50727
51004
|
}
|
|
50728
51005
|
hourlyData.forEach((entry, index) => {
|
|
50729
|
-
const
|
|
50730
|
-
|
|
50731
|
-
const
|
|
50732
|
-
|
|
50733
|
-
|
|
50734
|
-
|
|
50735
|
-
|
|
50736
|
-
|
|
50737
|
-
|
|
50738
|
-
hour12: true
|
|
50739
|
-
})}`;
|
|
50740
|
-
const hourNumber = startTime.getHours();
|
|
50741
|
-
const dataCollected = !isToday2 || hourNumber < currentHour;
|
|
51006
|
+
const interval = hourlyIntervals[index];
|
|
51007
|
+
const timeRange = interval ? `${formatIntervalLabel(interval.start)} - ${formatIntervalLabel(interval.end)}` : `${index + 1}`;
|
|
51008
|
+
const dataCollected = interval ? isHourlyIntervalComplete({
|
|
51009
|
+
reportDate: workspace.date,
|
|
51010
|
+
shiftStart: workspace.shift_start,
|
|
51011
|
+
shiftEnd: workspace.shift_end,
|
|
51012
|
+
interval,
|
|
51013
|
+
timeZone: reportTimezone
|
|
51014
|
+
}) : !isToday2 || currentHour >= 24;
|
|
50742
51015
|
const outputValue = isUptimeMode ? entry.activeMinutes ?? 0 : entry;
|
|
50743
51016
|
const idleValue = isUptimeMode ? entry.idleMinutes ?? 0 : 0;
|
|
50744
51017
|
const uptimePercent = isUptimeMode ? entry.uptimePercent ?? 0 : 0;
|
|
50745
51018
|
const outputStr = dataCollected ? outputValue.toString() : "TBD";
|
|
50746
|
-
const
|
|
51019
|
+
const effectiveTarget = outputTargetPlan?.targets[index] ?? hourlyTarget;
|
|
51020
|
+
const remarkText = outputTargetPlan?.breakRemarks[index] || "";
|
|
51021
|
+
const targetStr = isUptimeMode ? dataCollected ? idleValue.toString() : "TBD" : effectiveTarget.toString();
|
|
50747
51022
|
if (index < totalRows - 1) {
|
|
50748
51023
|
const rowBottomY = headerBottomY + (index + 1) * rowHeight;
|
|
50749
51024
|
doc.setDrawColor(200, 200, 200);
|
|
@@ -50775,10 +51050,12 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50775
51050
|
} else {
|
|
50776
51051
|
doc.text(outputStr, 75, yPos);
|
|
50777
51052
|
doc.text(targetStr, 105, yPos);
|
|
51053
|
+
const remarkDisplay = remarkText ? doc.splitTextToSize(remarkText, 26)[0] : "";
|
|
51054
|
+
doc.text(remarkDisplay, 160, yPos);
|
|
50778
51055
|
if (!dataCollected) {
|
|
50779
51056
|
doc.setTextColor(100, 100, 100);
|
|
50780
51057
|
doc.text("-", 135, yPos);
|
|
50781
|
-
} else if (outputValue >=
|
|
51058
|
+
} else if (outputValue >= effectiveTarget) {
|
|
50782
51059
|
doc.setTextColor(0, 171, 69);
|
|
50783
51060
|
doc.setFont("ZapfDingbats", "normal");
|
|
50784
51061
|
doc.text("4", 135, yPos);
|
|
@@ -50792,11 +51069,10 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
50792
51069
|
yPos += rowHeight;
|
|
50793
51070
|
});
|
|
50794
51071
|
const workspaceDisplayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
50795
|
-
const fileDate =
|
|
51072
|
+
const fileDate = formatOperationalDateKey2(workspace.date, {
|
|
50796
51073
|
day: "2-digit",
|
|
50797
51074
|
month: "short",
|
|
50798
|
-
year: "numeric"
|
|
50799
|
-
timeZone: "Asia/Kolkata"
|
|
51075
|
+
year: "numeric"
|
|
50800
51076
|
}).replace(/ /g, "_");
|
|
50801
51077
|
const fileShift = shiftType.replace(/ /g, "_");
|
|
50802
51078
|
const fileName = `${workspaceDisplayName}_${fileDate}_${fileShift}.pdf`;
|
|
@@ -50842,12 +51118,25 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
50842
51118
|
availableShifts,
|
|
50843
51119
|
shiftConfig,
|
|
50844
51120
|
efficiencyLegend,
|
|
51121
|
+
trendSummary,
|
|
50845
51122
|
className,
|
|
50846
51123
|
compact = false,
|
|
50847
51124
|
isAssemblyWorkspace = false
|
|
50848
51125
|
}) => {
|
|
50849
51126
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
50850
51127
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
51128
|
+
const drawStatusMark = (doc, x, y, met) => {
|
|
51129
|
+
doc.setLineWidth(0.8);
|
|
51130
|
+
if (met) {
|
|
51131
|
+
doc.setDrawColor(0, 171, 69);
|
|
51132
|
+
doc.line(x - 1.8, y - 0.2, x - 0.5, y + 1.2);
|
|
51133
|
+
doc.line(x - 0.5, y + 1.2, x + 2.1, y - 1.6);
|
|
51134
|
+
return;
|
|
51135
|
+
}
|
|
51136
|
+
doc.setDrawColor(227, 67, 41);
|
|
51137
|
+
doc.line(x - 1.8, y - 1.6, x + 1.8, y + 1.6);
|
|
51138
|
+
doc.line(x - 1.8, y + 1.6, x + 1.8, y - 1.6);
|
|
51139
|
+
};
|
|
50851
51140
|
const generatePDF = async () => {
|
|
50852
51141
|
setIsGenerating(true);
|
|
50853
51142
|
try {
|
|
@@ -51042,12 +51331,13 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
51042
51331
|
doc.setFont("helvetica", "bold");
|
|
51043
51332
|
doc.text(`${outputMetrics.underperformingDays} of ${outputMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 3);
|
|
51044
51333
|
} else {
|
|
51334
|
+
const medianCycleTime = Number.isFinite(trendSummary?.avg_cycle_time?.current) ? Number(trendSummary?.avg_cycle_time?.current) : outputMetrics.avgCycleTime;
|
|
51045
51335
|
createKPIBox(kpiStartY);
|
|
51046
51336
|
doc.setFontSize(11);
|
|
51047
51337
|
doc.setFont("helvetica", "normal");
|
|
51048
51338
|
doc.text("Average Cycle Time:", 25, kpiStartY);
|
|
51049
51339
|
doc.setFont("helvetica", "bold");
|
|
51050
|
-
doc.text(`${
|
|
51340
|
+
doc.text(`${medianCycleTime.toFixed(1)}s`, 120, kpiStartY);
|
|
51051
51341
|
createKPIBox(kpiStartY + kpiSpacing);
|
|
51052
51342
|
doc.setFont("helvetica", "normal");
|
|
51053
51343
|
doc.text("Average Idle Time:", 25, kpiStartY + kpiSpacing);
|
|
@@ -51082,8 +51372,8 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
51082
51372
|
doc.roundedRect(20, tableHeaderY, 170, 7, 1, 1, "F");
|
|
51083
51373
|
const textY = tableHeaderY + 5;
|
|
51084
51374
|
doc.text("Date", 25, textY);
|
|
51085
|
-
doc.text(isUptimeMode ? "Productive" : isAssemblyWorkspace ? "Cycle Time" : "Actual", 60, textY);
|
|
51086
|
-
doc.text(isUptimeMode ? "Idle" : isAssemblyWorkspace ? "
|
|
51375
|
+
doc.text(isUptimeMode ? "Productive" : isAssemblyWorkspace ? "Actual Cycle Time" : "Actual", 60, textY);
|
|
51376
|
+
doc.text(isUptimeMode ? "Idle" : isAssemblyWorkspace ? "Standard Cycle Time" : "Standard", 95, textY);
|
|
51087
51377
|
doc.text(isUptimeMode ? "Utilization" : "Efficiency", 135, textY);
|
|
51088
51378
|
doc.text("Status", 170, textY);
|
|
51089
51379
|
doc.setLineWidth(0.2);
|
|
@@ -51115,31 +51405,18 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
51115
51405
|
doc.text(formatIdleTime(productiveSeconds), 60, yPos);
|
|
51116
51406
|
doc.text(formatIdleTime(clampedIdleSeconds), 95, yPos);
|
|
51117
51407
|
doc.text(`${utilization}%`, 135, yPos);
|
|
51118
|
-
|
|
51119
|
-
doc.setTextColor(0, 171, 69);
|
|
51120
|
-
doc.text("\u2713", 170, yPos);
|
|
51121
|
-
} else {
|
|
51122
|
-
doc.setTextColor(227, 67, 41);
|
|
51123
|
-
doc.text("\xD7", 170, yPos);
|
|
51124
|
-
}
|
|
51125
|
-
doc.setTextColor(0, 0, 0);
|
|
51408
|
+
drawStatusMark(doc, 171, yPos - 0.3, utilization >= effectiveLegend.green_min);
|
|
51126
51409
|
} else {
|
|
51127
51410
|
if (isAssemblyWorkspace) {
|
|
51411
|
+
const targetCycleTime = Number.isFinite(shift.idealCycleTime) && Number(shift.idealCycleTime) > 0 ? Number(shift.idealCycleTime) : shift.pphThreshold > 0 ? 3600 / shift.pphThreshold : null;
|
|
51128
51412
|
doc.text(`${shift.cycleTime.toFixed(1)}`, 60, yPos);
|
|
51129
|
-
doc.text(
|
|
51413
|
+
doc.text(targetCycleTime !== null ? `${targetCycleTime.toFixed(1)}` : "-", 95, yPos);
|
|
51130
51414
|
} else {
|
|
51131
51415
|
doc.text(`${shift.output}`, 60, yPos);
|
|
51132
51416
|
doc.text(`${shift.targetOutput}`, 95, yPos);
|
|
51133
51417
|
}
|
|
51134
51418
|
doc.text(`${shift.efficiency.toFixed(1)}%`, 135, yPos);
|
|
51135
|
-
|
|
51136
|
-
doc.setTextColor(0, 171, 69);
|
|
51137
|
-
doc.text("\u2713", 170, yPos);
|
|
51138
|
-
} else {
|
|
51139
|
-
doc.setTextColor(227, 67, 41);
|
|
51140
|
-
doc.text("\xD7", 170, yPos);
|
|
51141
|
-
}
|
|
51142
|
-
doc.setTextColor(0, 0, 0);
|
|
51419
|
+
drawStatusMark(doc, 171, yPos - 0.3, shift.efficiency >= effectiveLegend.green_min);
|
|
51143
51420
|
}
|
|
51144
51421
|
yPos += 8;
|
|
51145
51422
|
});
|
|
@@ -64305,7 +64582,17 @@ var KPIDetailView = ({
|
|
|
64305
64582
|
)
|
|
64306
64583
|
] }),
|
|
64307
64584
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 ml-auto", children: [
|
|
64308
|
-
resolvedLineInfo && activeTab === "overview" && /* @__PURE__ */ jsx(
|
|
64585
|
+
resolvedLineInfo && activeTab === "overview" && /* @__PURE__ */ jsx(
|
|
64586
|
+
LinePdfGenerator,
|
|
64587
|
+
{
|
|
64588
|
+
lineInfo: resolvedLineInfo,
|
|
64589
|
+
workspaceData: resolvedWorkspaces || [],
|
|
64590
|
+
issueResolutionSummary,
|
|
64591
|
+
shiftName: getShiftName(resolvedLineInfo.shift_id),
|
|
64592
|
+
shiftBreaks: shiftConfig?.shifts?.find((shift) => shift.shiftId === resolvedLineInfo.shift_id)?.breaks || [],
|
|
64593
|
+
reportTimezone: shiftConfig?.timezone || configuredTimezone
|
|
64594
|
+
}
|
|
64595
|
+
),
|
|
64309
64596
|
activeTab === "monthly_history" && !urlDate && !urlShift && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
64310
64597
|
/* @__PURE__ */ jsx(
|
|
64311
64598
|
MonthlyRangeFilter_default,
|
|
@@ -64334,6 +64621,8 @@ var KPIDetailView = ({
|
|
|
64334
64621
|
rangeStart,
|
|
64335
64622
|
rangeEnd,
|
|
64336
64623
|
selectedShiftId,
|
|
64624
|
+
availableShifts: shiftConfig?.shifts?.map((shift) => ({ id: shift.shiftId, name: shift.shiftName })),
|
|
64625
|
+
lineAssembly: resolvedLineInfo?.assembly === true,
|
|
64337
64626
|
compact: true
|
|
64338
64627
|
}
|
|
64339
64628
|
)
|
|
@@ -64512,7 +64801,7 @@ var KPIDetailViewWithDisplayNames = withSelectedLineDisplayNames(KPIDetailView);
|
|
|
64512
64801
|
var KPIDetailView_default = KPIDetailViewWithDisplayNames;
|
|
64513
64802
|
var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
64514
64803
|
var resolveCompanyId = (...candidates) => candidates.find(isNonEmptyString);
|
|
64515
|
-
var
|
|
64804
|
+
var parseTimeToMinutes3 = (value) => {
|
|
64516
64805
|
if (!value) return null;
|
|
64517
64806
|
const [hourStr, minuteStr] = value.split(":");
|
|
64518
64807
|
const hour = Number.parseInt(hourStr ?? "", 10);
|
|
@@ -64524,8 +64813,8 @@ var getShiftEndDate = (shift, timezone) => {
|
|
|
64524
64813
|
if (!shift?.date) return null;
|
|
64525
64814
|
const startTime = shift.startTime || "06:00";
|
|
64526
64815
|
const endTime = shift.endTime || "18:00";
|
|
64527
|
-
const startMinutes =
|
|
64528
|
-
const endMinutes =
|
|
64816
|
+
const startMinutes = parseTimeToMinutes3(startTime);
|
|
64817
|
+
const endMinutes = parseTimeToMinutes3(endTime);
|
|
64529
64818
|
if (startMinutes === null || endMinutes === null) return null;
|
|
64530
64819
|
const shiftStartDate = fromZonedTime(`${shift.date}T${startTime}:00`, timezone);
|
|
64531
64820
|
let durationMinutes = endMinutes - startMinutes;
|
|
@@ -64563,7 +64852,7 @@ var createKpisOverviewUrl = ({
|
|
|
64563
64852
|
return queryString ? `/kpis?${queryString}` : "/kpis";
|
|
64564
64853
|
};
|
|
64565
64854
|
var getZonedDateAtMidday = (dateKey, timezone) => fromZonedTime(`${dateKey}T12:00:00`, timezone);
|
|
64566
|
-
var
|
|
64855
|
+
var formatDateKey2 = (dateKey, timezone, options) => {
|
|
64567
64856
|
try {
|
|
64568
64857
|
return new Intl.DateTimeFormat("en-US", {
|
|
64569
64858
|
...options,
|
|
@@ -65631,7 +65920,7 @@ var KPIsOverviewView = ({
|
|
|
65631
65920
|
setActiveTab(newTab);
|
|
65632
65921
|
}, [activeTab, leaderboardLines.length, lines.length]);
|
|
65633
65922
|
const formatLocalDate2 = useCallback((dateKey) => {
|
|
65634
|
-
return
|
|
65923
|
+
return formatDateKey2(dateKey, configuredTimezone, {
|
|
65635
65924
|
year: "numeric",
|
|
65636
65925
|
month: "long",
|
|
65637
65926
|
day: "numeric"
|
|
@@ -65645,8 +65934,8 @@ var KPIsOverviewView = ({
|
|
|
65645
65934
|
zonedNow.getMonth(),
|
|
65646
65935
|
new Date(zonedNow.getFullYear(), zonedNow.getMonth() + 1, 0).getDate()
|
|
65647
65936
|
);
|
|
65648
|
-
const startLabel =
|
|
65649
|
-
const endLabel =
|
|
65937
|
+
const startLabel = formatDateKey2(startOfMonthKey, configuredTimezone, { month: "short", day: "numeric" });
|
|
65938
|
+
const endLabel = formatDateKey2(endOfMonthKey, configuredTimezone, { month: "short", day: "numeric" });
|
|
65650
65939
|
return `${startLabel} - ${endLabel}, ${zonedNow.getFullYear()}`;
|
|
65651
65940
|
};
|
|
65652
65941
|
const isMonthlyMode = activeTab === "leaderboard" && timeRange === "monthly";
|
|
@@ -71281,6 +71570,7 @@ var WorkspaceDetailView = ({
|
|
|
71281
71570
|
efficiency: monitoringMode === "uptime" ? Number.isFinite(metric.avg_efficiency) ? Number(metric.avg_efficiency) : computedUptimeEfficiency : Number.isFinite(metric.avg_efficiency) ? Number(metric.avg_efficiency) : 0,
|
|
71282
71571
|
output: metric.total_output || 0,
|
|
71283
71572
|
cycleTime: metric.avg_cycle_time || 0,
|
|
71573
|
+
idealCycleTime: Number(metric.ideal_cycle_time || 0),
|
|
71284
71574
|
pph: metric.avg_pph || 0,
|
|
71285
71575
|
pphThreshold: metric.pph_threshold || 0,
|
|
71286
71576
|
idealOutput: Number(metric.ideal_output || 0),
|
|
@@ -71836,7 +72126,9 @@ var WorkspaceDetailView = ({
|
|
|
71836
72126
|
workspace,
|
|
71837
72127
|
idleTimeReasons: idleTimeChartData,
|
|
71838
72128
|
efficiencyLegend,
|
|
71839
|
-
hourlyCycleTimes: cycleTimeChartData
|
|
72129
|
+
hourlyCycleTimes: cycleTimeChartData,
|
|
72130
|
+
shiftBreaks: shiftConfig?.shifts?.find((shift2) => shift2.shiftId === workspace.shift_id)?.breaks || [],
|
|
72131
|
+
reportTimezone: shiftConfig?.timezone || timezone
|
|
71840
72132
|
}
|
|
71841
72133
|
) }),
|
|
71842
72134
|
activeTab === "monthly_history" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -71871,6 +72163,7 @@ var WorkspaceDetailView = ({
|
|
|
71871
72163
|
workspaceId,
|
|
71872
72164
|
workspaceName: formattedWorkspaceName,
|
|
71873
72165
|
monthlyData,
|
|
72166
|
+
analysisData: analysisMonthlyData,
|
|
71874
72167
|
selectedMonth,
|
|
71875
72168
|
selectedYear,
|
|
71876
72169
|
monitoringMode: workspace?.monitoring_mode,
|
|
@@ -71879,7 +72172,10 @@ var WorkspaceDetailView = ({
|
|
|
71879
72172
|
selectedShiftId: selectedShift,
|
|
71880
72173
|
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
71881
72174
|
shiftConfig,
|
|
71882
|
-
|
|
72175
|
+
efficiencyLegend,
|
|
72176
|
+
trendSummary: workspaceMonthlyTrend,
|
|
72177
|
+
compact: true,
|
|
72178
|
+
isAssemblyWorkspace
|
|
71883
72179
|
}
|
|
71884
72180
|
)
|
|
71885
72181
|
] })
|
|
@@ -80094,7 +80390,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
80094
80390
|
};
|
|
80095
80391
|
}, [companyId, enabled, getIsPageActive, isLiveScope, lineIds.length, refreshFromResume, startPolling, stopPolling, supabase]);
|
|
80096
80392
|
};
|
|
80097
|
-
var
|
|
80393
|
+
var parseTimeToMinutes4 = (value) => {
|
|
80098
80394
|
if (!value) return null;
|
|
80099
80395
|
const parts = value.split(":");
|
|
80100
80396
|
if (parts.length < 2) return null;
|
|
@@ -80129,8 +80425,8 @@ var classifyShiftBucket = ({
|
|
|
80129
80425
|
return "day";
|
|
80130
80426
|
}
|
|
80131
80427
|
}
|
|
80132
|
-
const startMinutes =
|
|
80133
|
-
const endMinutes =
|
|
80428
|
+
const startMinutes = parseTimeToMinutes4(startTime);
|
|
80429
|
+
const endMinutes = parseTimeToMinutes4(endTime);
|
|
80134
80430
|
if (startMinutes !== null) {
|
|
80135
80431
|
if (startMinutes >= 4 * 60 && startMinutes < 18 * 60) return "day";
|
|
80136
80432
|
return "night";
|
|
@@ -80189,8 +80485,8 @@ var getShiftWindowsForConfig = (shiftConfig, timezone) => {
|
|
|
80189
80485
|
];
|
|
80190
80486
|
};
|
|
80191
80487
|
var normalizeShiftWindowMinutes = (startTime, endTime) => {
|
|
80192
|
-
const startMinutes =
|
|
80193
|
-
const endMinutesRaw =
|
|
80488
|
+
const startMinutes = parseTimeToMinutes4(startTime);
|
|
80489
|
+
const endMinutesRaw = parseTimeToMinutes4(endTime);
|
|
80194
80490
|
if (startMinutes === null || endMinutesRaw === null) {
|
|
80195
80491
|
return null;
|
|
80196
80492
|
}
|
|
@@ -80356,7 +80652,7 @@ var PlantHeadView = () => {
|
|
|
80356
80652
|
startTime: shift.startTime,
|
|
80357
80653
|
endTime: shift.endTime
|
|
80358
80654
|
});
|
|
80359
|
-
const startMinutes =
|
|
80655
|
+
const startMinutes = parseTimeToMinutes4(shift.startTime);
|
|
80360
80656
|
if (bucket === "day" && startMinutes !== null) {
|
|
80361
80657
|
candidateStarts.push(startMinutes);
|
|
80362
80658
|
}
|
|
@@ -80366,7 +80662,7 @@ var PlantHeadView = () => {
|
|
|
80366
80662
|
scopedLineIds.forEach((lineId) => {
|
|
80367
80663
|
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
80368
80664
|
getShiftWindowsForConfig(shiftConfig).forEach((shift) => {
|
|
80369
|
-
const startMinutes =
|
|
80665
|
+
const startMinutes = parseTimeToMinutes4(shift.startTime);
|
|
80370
80666
|
if (startMinutes !== null) {
|
|
80371
80667
|
candidateStarts.push(startMinutes);
|
|
80372
80668
|
}
|
|
@@ -80457,7 +80753,7 @@ var PlantHeadView = () => {
|
|
|
80457
80753
|
startTime: shift.startTime,
|
|
80458
80754
|
endTime: shift.endTime
|
|
80459
80755
|
});
|
|
80460
|
-
return bucket === "day" ?
|
|
80756
|
+
return bucket === "day" ? parseTimeToMinutes4(shift.startTime) : null;
|
|
80461
80757
|
}).filter((value) => value !== null);
|
|
80462
80758
|
}) : [];
|
|
80463
80759
|
if (dayStartCandidates.length > 0) {
|