@optifye/dashboard-core 6.12.14 → 6.12.15

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 CHANGED
@@ -136,6 +136,7 @@ interface LineDetailedMetrics {
136
136
  output_array: number[];
137
137
  output_hourly?: Record<string, number[]>;
138
138
  hourly_target_output?: Array<number | null> | null;
139
+ hourly_target_output_by_sku?: Record<string, Array<number | null> | null>;
139
140
  line_threshold: number;
140
141
  /** Summed real-SKU `performance_metrics.total_day_output_recalculated`. */
141
142
  output_target_recalculated?: number | null;
@@ -1098,6 +1099,7 @@ interface WorkspaceMonthlyMetric {
1098
1099
  ideal_cycle_time?: number;
1099
1100
  ideal_output: number;
1100
1101
  total_day_output: number;
1102
+ target_output?: number;
1101
1103
  avg_pph: number;
1102
1104
  pph_threshold: number;
1103
1105
  workspace_rank: number;
@@ -1118,6 +1120,7 @@ interface LineMonthlyMetric {
1118
1120
  current_output?: number;
1119
1121
  ideal_output?: number;
1120
1122
  line_threshold?: number;
1123
+ target_output?: number;
1121
1124
  idle_time_hourly?: Record<string, any> | null;
1122
1125
  active_time_seconds?: number;
1123
1126
  idle_time_seconds?: number;
package/dist/index.d.ts CHANGED
@@ -136,6 +136,7 @@ interface LineDetailedMetrics {
136
136
  output_array: number[];
137
137
  output_hourly?: Record<string, number[]>;
138
138
  hourly_target_output?: Array<number | null> | null;
139
+ hourly_target_output_by_sku?: Record<string, Array<number | null> | null>;
139
140
  line_threshold: number;
140
141
  /** Summed real-SKU `performance_metrics.total_day_output_recalculated`. */
141
142
  output_target_recalculated?: number | null;
@@ -1098,6 +1099,7 @@ interface WorkspaceMonthlyMetric {
1098
1099
  ideal_cycle_time?: number;
1099
1100
  ideal_output: number;
1100
1101
  total_day_output: number;
1102
+ target_output?: number;
1101
1103
  avg_pph: number;
1102
1104
  pph_threshold: number;
1103
1105
  workspace_rank: number;
@@ -1118,6 +1120,7 @@ interface LineMonthlyMetric {
1118
1120
  current_output?: number;
1119
1121
  ideal_output?: number;
1120
1122
  line_threshold?: number;
1123
+ target_output?: number;
1121
1124
  idle_time_hourly?: Record<string, any> | null;
1122
1125
  active_time_seconds?: number;
1123
1126
  idle_time_seconds?: number;
package/dist/index.js CHANGED
@@ -5596,8 +5596,9 @@ var dashboardService = {
5596
5596
  total_output: item.total_output || 0,
5597
5597
  avg_cycle_time: item.avg_cycle_time || 0,
5598
5598
  ideal_cycle_time: item.ideal_cycle_time ?? 0,
5599
- ideal_output: item.ideal_output || 0,
5600
- total_day_output: item.total_day_output ?? item.ideal_output ?? 0,
5599
+ ideal_output: item.target_output ?? item.ideal_output ?? 0,
5600
+ total_day_output: item.target_output ?? item.total_day_output ?? item.ideal_output ?? 0,
5601
+ target_output: item.target_output ?? item.total_day_output ?? item.ideal_output ?? 0,
5601
5602
  avg_pph: item.avg_pph || 0,
5602
5603
  pph_threshold: item.pph_threshold || 0,
5603
5604
  workspace_rank: item.workspace_rank || 0,
@@ -13996,7 +13997,7 @@ var useLineWorkspaceMetrics = (lineId, options) => {
13996
13997
  trend: item.trend_score === 1 ? 2 : 0,
13997
13998
  predicted_output: item.ideal_output || 0,
13998
13999
  efficiency: item.efficiency || 0,
13999
- action_threshold: item.total_day_output || 0,
14000
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0,
14000
14001
  idle_time: item.idle_time ?? void 0,
14001
14002
  idle_time_hourly: item.idle_time_hourly || null,
14002
14003
  shift_start: item.shift_start || void 0,
@@ -14677,7 +14678,7 @@ var transformMonitorWorkspaceMetrics = ({
14677
14678
  trend: item.trend_score === 1 ? 2 : 0,
14678
14679
  predicted_output: item.ideal_output || 0,
14679
14680
  efficiency: item.efficiency || 0,
14680
- action_threshold: item.total_day_output || 0,
14681
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0,
14681
14682
  monitoring_mode: item.monitoring_mode ?? void 0,
14682
14683
  idle_time: idleTimeSeconds,
14683
14684
  idle_time_hourly: item.idle_time_hourly ?? null,
@@ -18858,6 +18859,7 @@ var useAllWorkspaceMetrics = (options) => {
18858
18859
  trend_score,
18859
18860
  line_id,
18860
18861
  total_day_output,
18862
+ total_day_output_recalculated,
18861
18863
  workspace_display_name
18862
18864
  `).eq("date", fallbackQueryDate).eq("shift_id", fallbackQueryShiftId).in("workspace_id", allEnabledWorkspaceIds).order("efficiency", { ascending: false });
18863
18865
  if (fetchError) throw fetchError;
@@ -18876,7 +18878,7 @@ var useAllWorkspaceMetrics = (options) => {
18876
18878
  trend: item.trend_score === 1 ? 2 : 0,
18877
18879
  predicted_output: 0,
18878
18880
  efficiency: item.efficiency || 0,
18879
- action_threshold: item.total_day_output || 0
18881
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0
18880
18882
  }));
18881
18883
  } else if (shiftGroups.length > 0) {
18882
18884
  console.log(`[useAllWorkspaceMetrics] \u{1F3ED} Fetching per-shift: ${shiftGroups.length} group(s)`);
@@ -18903,6 +18905,7 @@ var useAllWorkspaceMetrics = (options) => {
18903
18905
  trend_score,
18904
18906
  line_id,
18905
18907
  total_day_output,
18908
+ total_day_output_recalculated,
18906
18909
  workspace_display_name
18907
18910
  `).eq("date", group.date).eq("shift_id", group.shiftId).in("workspace_id", groupWorkspaceIds);
18908
18911
  if (fetchError) throw fetchError;
@@ -18921,7 +18924,7 @@ var useAllWorkspaceMetrics = (options) => {
18921
18924
  trend: item.trend_score === 1 ? 2 : 0,
18922
18925
  predicted_output: 0,
18923
18926
  efficiency: item.efficiency || 0,
18924
- action_threshold: item.total_day_output || 0
18927
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0
18925
18928
  }));
18926
18929
  });
18927
18930
  const results = await Promise.all(queryPromises);
@@ -51735,12 +51738,15 @@ var LinePdfGenerator = ({
51735
51738
  doc.setTextColor(0, 0, 0);
51736
51739
  const kpiStartY = 80;
51737
51740
  const kpiSpacing = 10;
51741
+ const dayTargetOutput = Math.round(Number(
51742
+ lineInfo.metrics.output_target_recalculated ?? lineInfo.metrics.line_threshold ?? 0
51743
+ ));
51738
51744
  createKPIBox(kpiStartY);
51739
51745
  doc.setFontSize(11);
51740
51746
  doc.setFont("helvetica", "normal");
51741
51747
  doc.text("Output:", 25, kpiStartY);
51742
51748
  doc.setFont("helvetica", "bold");
51743
- doc.text(`${lineInfo.metrics.current_output} / ${lineInfo.metrics.line_threshold}`, 120, kpiStartY);
51749
+ doc.text(`${lineInfo.metrics.current_output} / ${dayTargetOutput}`, 120, kpiStartY);
51744
51750
  createKPIBox(kpiStartY + kpiSpacing);
51745
51751
  doc.setFont("helvetica", "normal");
51746
51752
  doc.text("Average Efficiency:", 25, kpiStartY + kpiSpacing);
@@ -51775,6 +51781,18 @@ var LinePdfGenerator = ({
51775
51781
  fallbackHours: Math.max(hourlyTimeRanges.length, 1),
51776
51782
  rounding: "floor"
51777
51783
  });
51784
+ const backendHourlyTargetOutput = lineInfo.metrics.hourly_target_output;
51785
+ const shouldUseBackendHourlyTargets = backendHourlyTargetOutput !== void 0;
51786
+ const resolveTargetForRange = (index) => {
51787
+ if (shouldUseBackendHourlyTargets) {
51788
+ if (!Array.isArray(backendHourlyTargetOutput)) return null;
51789
+ const targetValue = backendHourlyTargetOutput[index];
51790
+ if (targetValue === null || targetValue === void 0) return null;
51791
+ const numericTarget = Number(targetValue);
51792
+ return Number.isFinite(numericTarget) ? numericTarget : null;
51793
+ }
51794
+ return targetPlan.targets[index] ?? 0;
51795
+ };
51778
51796
  const skuRemarksByIndex = {};
51779
51797
  if (lineInfo.metrics.sku_segments && lineInfo.metrics.sku_segments.length > 0) {
51780
51798
  lineInfo.metrics.sku_segments.forEach((segment, segmentIndex) => {
@@ -52004,8 +52022,9 @@ var LinePdfGenerator = ({
52004
52022
  doc.setDrawColor(200, 200, 200);
52005
52023
  doc.line(20, rowBottomY, 190, rowBottomY);
52006
52024
  }
52007
- const targetForRange = targetPlan.targets[index] ?? 0;
52008
- const targetStr = targetForRange.toString();
52025
+ const targetForRange = resolveTargetForRange(index);
52026
+ const roundedTargetForRange = targetForRange === null ? null : Math.round(targetForRange);
52027
+ const targetStr = roundedTargetForRange === null ? "-" : roundedTargetForRange.toString();
52009
52028
  let remarkText = targetPlan.breakRemarks[index] || "";
52010
52029
  if (skuRemarksByIndex[index] && skuRemarksByIndex[index].length > 0) {
52011
52030
  const skuRemarks = skuRemarksByIndex[index];
@@ -52027,7 +52046,10 @@ var LinePdfGenerator = ({
52027
52046
  if (!dataCollected) {
52028
52047
  doc.setTextColor(100, 100, 100);
52029
52048
  doc.text("-", 135, yPos);
52030
- } else if (actualOutput >= targetForRange) {
52049
+ } else if (roundedTargetForRange === null) {
52050
+ doc.setTextColor(100, 100, 100);
52051
+ doc.text("-", 135, yPos);
52052
+ } else if (actualOutput >= roundedTargetForRange) {
52031
52053
  doc.setTextColor(0, 171, 69);
52032
52054
  doc.setFont("ZapfDingbats", "normal");
52033
52055
  doc.text("4", 135, yPos);
@@ -53789,6 +53811,19 @@ var WorkspacePdfGenerator = ({
53789
53811
  fallbackHours: Math.max(hourlyData.length, 1),
53790
53812
  rounding: "floor"
53791
53813
  }) : null;
53814
+ const backendHourlyTargetOutput = workspace.hourly_target_output;
53815
+ const shouldUseBackendHourlyTargets = backendHourlyTargetOutput !== void 0;
53816
+ const resolveTargetForRange = (index) => {
53817
+ if (!outputTargetPlan) return null;
53818
+ if (shouldUseBackendHourlyTargets) {
53819
+ if (!Array.isArray(backendHourlyTargetOutput)) return null;
53820
+ const targetValue = backendHourlyTargetOutput[index];
53821
+ if (targetValue === null || targetValue === void 0) return null;
53822
+ const numericTarget = Number(targetValue);
53823
+ return Number.isFinite(numericTarget) ? numericTarget : null;
53824
+ }
53825
+ return outputTargetPlan.targets[index] ?? hourlyTarget;
53826
+ };
53792
53827
  const skuRemarksByIndex = {};
53793
53828
  if (workspace.sku_segments && workspace.sku_segments.length > 0) {
53794
53829
  workspace.sku_segments.forEach((segment, segmentIndex) => {
@@ -53915,7 +53950,7 @@ var WorkspacePdfGenerator = ({
53915
53950
  const idleValue = isUptimeMode ? entry.idleMinutes ?? 0 : 0;
53916
53951
  const uptimePercent = isUptimeMode ? entry.uptimePercent ?? 0 : 0;
53917
53952
  const outputStr = dataCollected ? outputValue.toString() : "TBD";
53918
- const effectiveTarget = outputTargetPlan?.targets[index] ?? hourlyTarget;
53953
+ const effectiveTarget = resolveTargetForRange(index);
53919
53954
  let remarkText = outputTargetPlan?.breakRemarks[index] || "";
53920
53955
  if (skuRemarksByIndex[index] && skuRemarksByIndex[index].length > 0) {
53921
53956
  const skuRemarks = skuRemarksByIndex[index];
@@ -53923,7 +53958,8 @@ var WorkspacePdfGenerator = ({
53923
53958
  const compactSkuRemark = skuRemarks.length === 1 ? `${latestSku} started` : `${latestSku} started, +${skuRemarks.length - 1}`;
53924
53959
  remarkText = remarkText ? `${remarkText}, ${compactSkuRemark}` : compactSkuRemark;
53925
53960
  }
53926
- const targetStr = isUptimeMode ? dataCollected ? idleValue.toString() : "TBD" : effectiveTarget.toString();
53961
+ const roundedEffectiveTarget = effectiveTarget === null ? null : Math.round(effectiveTarget);
53962
+ const targetStr = isUptimeMode ? dataCollected ? idleValue.toString() : "TBD" : roundedEffectiveTarget === null ? "-" : roundedEffectiveTarget.toString();
53927
53963
  if (index < totalRows - 1) {
53928
53964
  const rowBottomY = headerBottomY + (index + 1) * rowHeight;
53929
53965
  doc.setDrawColor(200, 200, 200);
@@ -53966,7 +54002,10 @@ var WorkspacePdfGenerator = ({
53966
54002
  if (!dataCollected) {
53967
54003
  doc.setTextColor(100, 100, 100);
53968
54004
  doc.text("-", 135, yPos);
53969
- } else if (outputValue >= effectiveTarget) {
54005
+ } else if (roundedEffectiveTarget === null) {
54006
+ doc.setTextColor(100, 100, 100);
54007
+ doc.text("-", 135, yPos);
54008
+ } else if (outputValue >= roundedEffectiveTarget) {
53970
54009
  doc.setTextColor(0, 171, 69);
53971
54010
  doc.setFont("ZapfDingbats", "normal");
53972
54011
  doc.text("4", 135, yPos);
@@ -65535,6 +65574,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
65535
65574
  output_array: metrics2.output_array || [],
65536
65575
  output_hourly: metrics2.output_hourly,
65537
65576
  hourly_target_output: metrics2.hourly_target_output,
65577
+ hourly_target_output_by_sku: metrics2.hourly_target_output_by_sku,
65538
65578
  line_threshold: metrics2.line_threshold ?? 0,
65539
65579
  output_target_recalculated: metrics2.output_target_recalculated ?? null,
65540
65580
  threshold_pph: metrics2.threshold_pph ?? 0,
@@ -65568,7 +65608,7 @@ var transformWorkspaceMetrics = (workspaceData, lineId, companyId, queryDate, qu
65568
65608
  trend: item.trend_score === 1 ? 2 : 0,
65569
65609
  predicted_output: item.ideal_output || 0,
65570
65610
  efficiency: item.efficiency || 0,
65571
- action_threshold: item.total_day_output || 0,
65611
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0,
65572
65612
  idle_time: item.idle_time ?? void 0,
65573
65613
  idle_time_hourly: item.idle_time_hourly || null,
65574
65614
  shift_start: item.shift_start || void 0,
@@ -67363,9 +67403,9 @@ var KPIDetailView = ({
67363
67403
  output: metric.current_output || 0,
67364
67404
  // LineMonthlyHistory expects `idealOutput` for the red dotted target ReferenceLine.
67365
67405
  // `line_threshold` comes from `line_metrics` (numeric -> string via PostgREST), so coerce.
67366
- idealOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67406
+ idealOutput: Number(metric.target_output ?? metric.line_threshold ?? metric.ideal_output ?? 0),
67367
67407
  // Keep legacy field in case any downstream code still reads it.
67368
- targetOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67408
+ targetOutput: Number(metric.target_output ?? metric.line_threshold ?? metric.ideal_output ?? 0),
67369
67409
  compliance_percentage: 95 + Math.random() * 5,
67370
67410
  // Mock data: random value between 95-100%
67371
67411
  hasData: isUptimeMode ? hasUptimeMetricData : true,
@@ -67452,6 +67492,7 @@ var KPIDetailView = ({
67452
67492
  output_array: metrics2.output_array || [],
67453
67493
  output_hourly: metrics2.output_hourly,
67454
67494
  hourly_target_output: metrics2.hourly_target_output,
67495
+ hourly_target_output_by_sku: metrics2.hourly_target_output_by_sku,
67455
67496
  line_threshold: metrics2.line_threshold ?? 0,
67456
67497
  output_target_recalculated: metrics2.output_target_recalculated ?? null,
67457
67498
  threshold_pph: metrics2.threshold_pph ?? 0,
@@ -67579,6 +67620,19 @@ var KPIDetailView = ({
67579
67620
  if (selectedSkuId === "all") return null;
67580
67621
  return realSkuOptions.find((item) => item.sku_id === selectedSkuId) ?? null;
67581
67622
  }, [realSkuOptions, selectedSkuId]);
67623
+ const selectedHourlyTargetOutput = React144.useMemo(() => {
67624
+ const aggregateTarget = chartMetrics?.hourly_target_output;
67625
+ if (!normalizedSelectedSkuId) return aggregateTarget;
67626
+ const targetBySku = chartMetrics?.hourly_target_output_by_sku;
67627
+ if (targetBySku && Object.prototype.hasOwnProperty.call(targetBySku, normalizedSelectedSkuId)) {
67628
+ return targetBySku[normalizedSelectedSkuId];
67629
+ }
67630
+ return aggregateTarget;
67631
+ }, [
67632
+ chartMetrics?.hourly_target_output,
67633
+ chartMetrics?.hourly_target_output_by_sku,
67634
+ normalizedSelectedSkuId
67635
+ ]);
67582
67636
  const displayLineInfo = React144.useMemo(() => {
67583
67637
  if (!resolvedLineInfo) return null;
67584
67638
  if (!selectedSkuRow) return resolvedLineInfo;
@@ -68420,7 +68474,7 @@ var KPIDetailView = ({
68420
68474
  workspaceDisplayNames,
68421
68475
  hourlyOutputData,
68422
68476
  hourlyThreshold,
68423
- hourlyTargetOutput: chartMetrics?.hourly_target_output,
68477
+ hourlyTargetOutput: selectedHourlyTargetOutput,
68424
68478
  shiftBreaks: shiftConfig?.shifts?.find((shift) => shift.shiftId === resolvedLineInfo.shift_id)?.breaks || [],
68425
68479
  idleTimeHourly: chartMetrics?.idle_time_hourly,
68426
68480
  timezone: lineTimezone,
@@ -75822,8 +75876,8 @@ var WorkspaceDetailView = ({
75822
75876
  idealCycleTime: Number(metric.ideal_cycle_time || 0),
75823
75877
  pph: metric.avg_pph || 0,
75824
75878
  pphThreshold: metric.pph_threshold || 0,
75825
- idealOutput: Number(metric.ideal_output || 0),
75826
- targetOutput: Number(metric.total_day_output || 0),
75879
+ idealOutput: Number(metric.target_output ?? metric.ideal_output ?? 0),
75880
+ targetOutput: Number(metric.target_output ?? metric.total_day_output ?? 0),
75827
75881
  rank: metric.workspace_rank || 0,
75828
75882
  idleTime: idleTimeSeconds || 0,
75829
75883
  activeTimeSeconds,
package/dist/index.mjs CHANGED
@@ -5567,8 +5567,9 @@ var dashboardService = {
5567
5567
  total_output: item.total_output || 0,
5568
5568
  avg_cycle_time: item.avg_cycle_time || 0,
5569
5569
  ideal_cycle_time: item.ideal_cycle_time ?? 0,
5570
- ideal_output: item.ideal_output || 0,
5571
- total_day_output: item.total_day_output ?? item.ideal_output ?? 0,
5570
+ ideal_output: item.target_output ?? item.ideal_output ?? 0,
5571
+ total_day_output: item.target_output ?? item.total_day_output ?? item.ideal_output ?? 0,
5572
+ target_output: item.target_output ?? item.total_day_output ?? item.ideal_output ?? 0,
5572
5573
  avg_pph: item.avg_pph || 0,
5573
5574
  pph_threshold: item.pph_threshold || 0,
5574
5575
  workspace_rank: item.workspace_rank || 0,
@@ -13967,7 +13968,7 @@ var useLineWorkspaceMetrics = (lineId, options) => {
13967
13968
  trend: item.trend_score === 1 ? 2 : 0,
13968
13969
  predicted_output: item.ideal_output || 0,
13969
13970
  efficiency: item.efficiency || 0,
13970
- action_threshold: item.total_day_output || 0,
13971
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0,
13971
13972
  idle_time: item.idle_time ?? void 0,
13972
13973
  idle_time_hourly: item.idle_time_hourly || null,
13973
13974
  shift_start: item.shift_start || void 0,
@@ -14648,7 +14649,7 @@ var transformMonitorWorkspaceMetrics = ({
14648
14649
  trend: item.trend_score === 1 ? 2 : 0,
14649
14650
  predicted_output: item.ideal_output || 0,
14650
14651
  efficiency: item.efficiency || 0,
14651
- action_threshold: item.total_day_output || 0,
14652
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0,
14652
14653
  monitoring_mode: item.monitoring_mode ?? void 0,
14653
14654
  idle_time: idleTimeSeconds,
14654
14655
  idle_time_hourly: item.idle_time_hourly ?? null,
@@ -18829,6 +18830,7 @@ var useAllWorkspaceMetrics = (options) => {
18829
18830
  trend_score,
18830
18831
  line_id,
18831
18832
  total_day_output,
18833
+ total_day_output_recalculated,
18832
18834
  workspace_display_name
18833
18835
  `).eq("date", fallbackQueryDate).eq("shift_id", fallbackQueryShiftId).in("workspace_id", allEnabledWorkspaceIds).order("efficiency", { ascending: false });
18834
18836
  if (fetchError) throw fetchError;
@@ -18847,7 +18849,7 @@ var useAllWorkspaceMetrics = (options) => {
18847
18849
  trend: item.trend_score === 1 ? 2 : 0,
18848
18850
  predicted_output: 0,
18849
18851
  efficiency: item.efficiency || 0,
18850
- action_threshold: item.total_day_output || 0
18852
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0
18851
18853
  }));
18852
18854
  } else if (shiftGroups.length > 0) {
18853
18855
  console.log(`[useAllWorkspaceMetrics] \u{1F3ED} Fetching per-shift: ${shiftGroups.length} group(s)`);
@@ -18874,6 +18876,7 @@ var useAllWorkspaceMetrics = (options) => {
18874
18876
  trend_score,
18875
18877
  line_id,
18876
18878
  total_day_output,
18879
+ total_day_output_recalculated,
18877
18880
  workspace_display_name
18878
18881
  `).eq("date", group.date).eq("shift_id", group.shiftId).in("workspace_id", groupWorkspaceIds);
18879
18882
  if (fetchError) throw fetchError;
@@ -18892,7 +18895,7 @@ var useAllWorkspaceMetrics = (options) => {
18892
18895
  trend: item.trend_score === 1 ? 2 : 0,
18893
18896
  predicted_output: 0,
18894
18897
  efficiency: item.efficiency || 0,
18895
- action_threshold: item.total_day_output || 0
18898
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0
18896
18899
  }));
18897
18900
  });
18898
18901
  const results = await Promise.all(queryPromises);
@@ -51706,12 +51709,15 @@ var LinePdfGenerator = ({
51706
51709
  doc.setTextColor(0, 0, 0);
51707
51710
  const kpiStartY = 80;
51708
51711
  const kpiSpacing = 10;
51712
+ const dayTargetOutput = Math.round(Number(
51713
+ lineInfo.metrics.output_target_recalculated ?? lineInfo.metrics.line_threshold ?? 0
51714
+ ));
51709
51715
  createKPIBox(kpiStartY);
51710
51716
  doc.setFontSize(11);
51711
51717
  doc.setFont("helvetica", "normal");
51712
51718
  doc.text("Output:", 25, kpiStartY);
51713
51719
  doc.setFont("helvetica", "bold");
51714
- doc.text(`${lineInfo.metrics.current_output} / ${lineInfo.metrics.line_threshold}`, 120, kpiStartY);
51720
+ doc.text(`${lineInfo.metrics.current_output} / ${dayTargetOutput}`, 120, kpiStartY);
51715
51721
  createKPIBox(kpiStartY + kpiSpacing);
51716
51722
  doc.setFont("helvetica", "normal");
51717
51723
  doc.text("Average Efficiency:", 25, kpiStartY + kpiSpacing);
@@ -51746,6 +51752,18 @@ var LinePdfGenerator = ({
51746
51752
  fallbackHours: Math.max(hourlyTimeRanges.length, 1),
51747
51753
  rounding: "floor"
51748
51754
  });
51755
+ const backendHourlyTargetOutput = lineInfo.metrics.hourly_target_output;
51756
+ const shouldUseBackendHourlyTargets = backendHourlyTargetOutput !== void 0;
51757
+ const resolveTargetForRange = (index) => {
51758
+ if (shouldUseBackendHourlyTargets) {
51759
+ if (!Array.isArray(backendHourlyTargetOutput)) return null;
51760
+ const targetValue = backendHourlyTargetOutput[index];
51761
+ if (targetValue === null || targetValue === void 0) return null;
51762
+ const numericTarget = Number(targetValue);
51763
+ return Number.isFinite(numericTarget) ? numericTarget : null;
51764
+ }
51765
+ return targetPlan.targets[index] ?? 0;
51766
+ };
51749
51767
  const skuRemarksByIndex = {};
51750
51768
  if (lineInfo.metrics.sku_segments && lineInfo.metrics.sku_segments.length > 0) {
51751
51769
  lineInfo.metrics.sku_segments.forEach((segment, segmentIndex) => {
@@ -51975,8 +51993,9 @@ var LinePdfGenerator = ({
51975
51993
  doc.setDrawColor(200, 200, 200);
51976
51994
  doc.line(20, rowBottomY, 190, rowBottomY);
51977
51995
  }
51978
- const targetForRange = targetPlan.targets[index] ?? 0;
51979
- const targetStr = targetForRange.toString();
51996
+ const targetForRange = resolveTargetForRange(index);
51997
+ const roundedTargetForRange = targetForRange === null ? null : Math.round(targetForRange);
51998
+ const targetStr = roundedTargetForRange === null ? "-" : roundedTargetForRange.toString();
51980
51999
  let remarkText = targetPlan.breakRemarks[index] || "";
51981
52000
  if (skuRemarksByIndex[index] && skuRemarksByIndex[index].length > 0) {
51982
52001
  const skuRemarks = skuRemarksByIndex[index];
@@ -51998,7 +52017,10 @@ var LinePdfGenerator = ({
51998
52017
  if (!dataCollected) {
51999
52018
  doc.setTextColor(100, 100, 100);
52000
52019
  doc.text("-", 135, yPos);
52001
- } else if (actualOutput >= targetForRange) {
52020
+ } else if (roundedTargetForRange === null) {
52021
+ doc.setTextColor(100, 100, 100);
52022
+ doc.text("-", 135, yPos);
52023
+ } else if (actualOutput >= roundedTargetForRange) {
52002
52024
  doc.setTextColor(0, 171, 69);
52003
52025
  doc.setFont("ZapfDingbats", "normal");
52004
52026
  doc.text("4", 135, yPos);
@@ -53760,6 +53782,19 @@ var WorkspacePdfGenerator = ({
53760
53782
  fallbackHours: Math.max(hourlyData.length, 1),
53761
53783
  rounding: "floor"
53762
53784
  }) : null;
53785
+ const backendHourlyTargetOutput = workspace.hourly_target_output;
53786
+ const shouldUseBackendHourlyTargets = backendHourlyTargetOutput !== void 0;
53787
+ const resolveTargetForRange = (index) => {
53788
+ if (!outputTargetPlan) return null;
53789
+ if (shouldUseBackendHourlyTargets) {
53790
+ if (!Array.isArray(backendHourlyTargetOutput)) return null;
53791
+ const targetValue = backendHourlyTargetOutput[index];
53792
+ if (targetValue === null || targetValue === void 0) return null;
53793
+ const numericTarget = Number(targetValue);
53794
+ return Number.isFinite(numericTarget) ? numericTarget : null;
53795
+ }
53796
+ return outputTargetPlan.targets[index] ?? hourlyTarget;
53797
+ };
53763
53798
  const skuRemarksByIndex = {};
53764
53799
  if (workspace.sku_segments && workspace.sku_segments.length > 0) {
53765
53800
  workspace.sku_segments.forEach((segment, segmentIndex) => {
@@ -53886,7 +53921,7 @@ var WorkspacePdfGenerator = ({
53886
53921
  const idleValue = isUptimeMode ? entry.idleMinutes ?? 0 : 0;
53887
53922
  const uptimePercent = isUptimeMode ? entry.uptimePercent ?? 0 : 0;
53888
53923
  const outputStr = dataCollected ? outputValue.toString() : "TBD";
53889
- const effectiveTarget = outputTargetPlan?.targets[index] ?? hourlyTarget;
53924
+ const effectiveTarget = resolveTargetForRange(index);
53890
53925
  let remarkText = outputTargetPlan?.breakRemarks[index] || "";
53891
53926
  if (skuRemarksByIndex[index] && skuRemarksByIndex[index].length > 0) {
53892
53927
  const skuRemarks = skuRemarksByIndex[index];
@@ -53894,7 +53929,8 @@ var WorkspacePdfGenerator = ({
53894
53929
  const compactSkuRemark = skuRemarks.length === 1 ? `${latestSku} started` : `${latestSku} started, +${skuRemarks.length - 1}`;
53895
53930
  remarkText = remarkText ? `${remarkText}, ${compactSkuRemark}` : compactSkuRemark;
53896
53931
  }
53897
- const targetStr = isUptimeMode ? dataCollected ? idleValue.toString() : "TBD" : effectiveTarget.toString();
53932
+ const roundedEffectiveTarget = effectiveTarget === null ? null : Math.round(effectiveTarget);
53933
+ const targetStr = isUptimeMode ? dataCollected ? idleValue.toString() : "TBD" : roundedEffectiveTarget === null ? "-" : roundedEffectiveTarget.toString();
53898
53934
  if (index < totalRows - 1) {
53899
53935
  const rowBottomY = headerBottomY + (index + 1) * rowHeight;
53900
53936
  doc.setDrawColor(200, 200, 200);
@@ -53937,7 +53973,10 @@ var WorkspacePdfGenerator = ({
53937
53973
  if (!dataCollected) {
53938
53974
  doc.setTextColor(100, 100, 100);
53939
53975
  doc.text("-", 135, yPos);
53940
- } else if (outputValue >= effectiveTarget) {
53976
+ } else if (roundedEffectiveTarget === null) {
53977
+ doc.setTextColor(100, 100, 100);
53978
+ doc.text("-", 135, yPos);
53979
+ } else if (outputValue >= roundedEffectiveTarget) {
53941
53980
  doc.setTextColor(0, 171, 69);
53942
53981
  doc.setFont("ZapfDingbats", "normal");
53943
53982
  doc.text("4", 135, yPos);
@@ -65506,6 +65545,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
65506
65545
  output_array: metrics2.output_array || [],
65507
65546
  output_hourly: metrics2.output_hourly,
65508
65547
  hourly_target_output: metrics2.hourly_target_output,
65548
+ hourly_target_output_by_sku: metrics2.hourly_target_output_by_sku,
65509
65549
  line_threshold: metrics2.line_threshold ?? 0,
65510
65550
  output_target_recalculated: metrics2.output_target_recalculated ?? null,
65511
65551
  threshold_pph: metrics2.threshold_pph ?? 0,
@@ -65539,7 +65579,7 @@ var transformWorkspaceMetrics = (workspaceData, lineId, companyId, queryDate, qu
65539
65579
  trend: item.trend_score === 1 ? 2 : 0,
65540
65580
  predicted_output: item.ideal_output || 0,
65541
65581
  efficiency: item.efficiency || 0,
65542
- action_threshold: item.total_day_output || 0,
65582
+ action_threshold: item.target_output ?? item.total_day_output_recalculated ?? item.total_day_output ?? 0,
65543
65583
  idle_time: item.idle_time ?? void 0,
65544
65584
  idle_time_hourly: item.idle_time_hourly || null,
65545
65585
  shift_start: item.shift_start || void 0,
@@ -67334,9 +67374,9 @@ var KPIDetailView = ({
67334
67374
  output: metric.current_output || 0,
67335
67375
  // LineMonthlyHistory expects `idealOutput` for the red dotted target ReferenceLine.
67336
67376
  // `line_threshold` comes from `line_metrics` (numeric -> string via PostgREST), so coerce.
67337
- idealOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67377
+ idealOutput: Number(metric.target_output ?? metric.line_threshold ?? metric.ideal_output ?? 0),
67338
67378
  // Keep legacy field in case any downstream code still reads it.
67339
- targetOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67379
+ targetOutput: Number(metric.target_output ?? metric.line_threshold ?? metric.ideal_output ?? 0),
67340
67380
  compliance_percentage: 95 + Math.random() * 5,
67341
67381
  // Mock data: random value between 95-100%
67342
67382
  hasData: isUptimeMode ? hasUptimeMetricData : true,
@@ -67423,6 +67463,7 @@ var KPIDetailView = ({
67423
67463
  output_array: metrics2.output_array || [],
67424
67464
  output_hourly: metrics2.output_hourly,
67425
67465
  hourly_target_output: metrics2.hourly_target_output,
67466
+ hourly_target_output_by_sku: metrics2.hourly_target_output_by_sku,
67426
67467
  line_threshold: metrics2.line_threshold ?? 0,
67427
67468
  output_target_recalculated: metrics2.output_target_recalculated ?? null,
67428
67469
  threshold_pph: metrics2.threshold_pph ?? 0,
@@ -67550,6 +67591,19 @@ var KPIDetailView = ({
67550
67591
  if (selectedSkuId === "all") return null;
67551
67592
  return realSkuOptions.find((item) => item.sku_id === selectedSkuId) ?? null;
67552
67593
  }, [realSkuOptions, selectedSkuId]);
67594
+ const selectedHourlyTargetOutput = useMemo(() => {
67595
+ const aggregateTarget = chartMetrics?.hourly_target_output;
67596
+ if (!normalizedSelectedSkuId) return aggregateTarget;
67597
+ const targetBySku = chartMetrics?.hourly_target_output_by_sku;
67598
+ if (targetBySku && Object.prototype.hasOwnProperty.call(targetBySku, normalizedSelectedSkuId)) {
67599
+ return targetBySku[normalizedSelectedSkuId];
67600
+ }
67601
+ return aggregateTarget;
67602
+ }, [
67603
+ chartMetrics?.hourly_target_output,
67604
+ chartMetrics?.hourly_target_output_by_sku,
67605
+ normalizedSelectedSkuId
67606
+ ]);
67553
67607
  const displayLineInfo = useMemo(() => {
67554
67608
  if (!resolvedLineInfo) return null;
67555
67609
  if (!selectedSkuRow) return resolvedLineInfo;
@@ -68391,7 +68445,7 @@ var KPIDetailView = ({
68391
68445
  workspaceDisplayNames,
68392
68446
  hourlyOutputData,
68393
68447
  hourlyThreshold,
68394
- hourlyTargetOutput: chartMetrics?.hourly_target_output,
68448
+ hourlyTargetOutput: selectedHourlyTargetOutput,
68395
68449
  shiftBreaks: shiftConfig?.shifts?.find((shift) => shift.shiftId === resolvedLineInfo.shift_id)?.breaks || [],
68396
68450
  idleTimeHourly: chartMetrics?.idle_time_hourly,
68397
68451
  timezone: lineTimezone,
@@ -75793,8 +75847,8 @@ var WorkspaceDetailView = ({
75793
75847
  idealCycleTime: Number(metric.ideal_cycle_time || 0),
75794
75848
  pph: metric.avg_pph || 0,
75795
75849
  pphThreshold: metric.pph_threshold || 0,
75796
- idealOutput: Number(metric.ideal_output || 0),
75797
- targetOutput: Number(metric.total_day_output || 0),
75850
+ idealOutput: Number(metric.target_output ?? metric.ideal_output ?? 0),
75851
+ targetOutput: Number(metric.target_output ?? metric.total_day_output ?? 0),
75798
75852
  rank: metric.workspace_rank || 0,
75799
75853
  idleTime: idleTimeSeconds || 0,
75800
75854
  activeTimeSeconds,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optifye/dashboard-core",
3
- "version": "6.12.14",
3
+ "version": "6.12.15",
4
4
  "description": "Reusable UI & logic for Optifye dashboard",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",