@optifye/dashboard-core 6.5.6 → 6.5.8

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
@@ -32,6 +32,7 @@ interface LineInfo {
32
32
  underperforming_workspace_names: string[];
33
33
  underperforming_workspace_uuids: string[];
34
34
  output_array: number[];
35
+ output_hourly?: Record<string, number[]>;
35
36
  line_threshold: number;
36
37
  threshold_pph?: number;
37
38
  shift_start?: string;
@@ -2281,6 +2282,7 @@ interface LineMetrics {
2281
2282
  underperforming_workspace_names: string[];
2282
2283
  underperforming_workspace_uuids: string[];
2283
2284
  output_array: number[];
2285
+ output_hourly?: Record<string, number[]>;
2284
2286
  line_threshold: number;
2285
2287
  threshold_pph: number;
2286
2288
  shift_start: string;
@@ -4325,6 +4327,7 @@ interface HourlyOutputChartProps {
4325
4327
  data: number[];
4326
4328
  pphThreshold: number;
4327
4329
  shiftStart: string;
4330
+ shiftEnd?: string;
4328
4331
  showIdleTime?: boolean;
4329
4332
  idleTimeHourly?: Record<string, string[]>;
4330
4333
  className?: string;
package/dist/index.d.ts CHANGED
@@ -32,6 +32,7 @@ interface LineInfo {
32
32
  underperforming_workspace_names: string[];
33
33
  underperforming_workspace_uuids: string[];
34
34
  output_array: number[];
35
+ output_hourly?: Record<string, number[]>;
35
36
  line_threshold: number;
36
37
  threshold_pph?: number;
37
38
  shift_start?: string;
@@ -2281,6 +2282,7 @@ interface LineMetrics {
2281
2282
  underperforming_workspace_names: string[];
2282
2283
  underperforming_workspace_uuids: string[];
2283
2284
  output_array: number[];
2285
+ output_hourly?: Record<string, number[]>;
2284
2286
  line_threshold: number;
2285
2287
  threshold_pph: number;
2286
2288
  shift_start: string;
@@ -4325,6 +4327,7 @@ interface HourlyOutputChartProps {
4325
4327
  data: number[];
4326
4328
  pphThreshold: number;
4327
4329
  shiftStart: string;
4330
+ shiftEnd?: string;
4328
4331
  showIdleTime?: boolean;
4329
4332
  idleTimeHourly?: Record<string, string[]>;
4330
4333
  className?: string;
package/dist/index.js CHANGED
@@ -893,15 +893,19 @@ var dashboardService = {
893
893
  const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
894
894
  const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
895
895
  const startHour = parseInt(shiftStart.split(":")[0]);
896
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
897
+ const endHour = parseInt(shiftEnd.split(":")[0]);
898
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
899
+ let shiftDuration = endHour - startHour;
900
+ if (endMinute > startMinute) {
901
+ shiftDuration += 1;
902
+ }
903
+ if (shiftDuration <= 0) {
904
+ shiftDuration += 24;
905
+ }
896
906
  let expectedHours = [];
897
- if (isNightShift) {
898
- for (let i = 0; i < 9; i++) {
899
- expectedHours.push((startHour + i) % 24);
900
- }
901
- } else {
902
- for (let i = 0; i < 9; i++) {
903
- expectedHours.push((startHour + i) % 24);
904
- }
907
+ for (let i = 0; i < shiftDuration; i++) {
908
+ expectedHours.push((startHour + i) % 24);
905
909
  }
906
910
  console.log("Expected shift hours:", expectedHours);
907
911
  console.log("Available data hours:", Object.keys(outputHourly));
@@ -5702,15 +5706,19 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5702
5706
  const shiftStart = recentData.shift_start || (isNightShift ? "22:00" : "06:00");
5703
5707
  const shiftEnd = recentData.shift_end || (isNightShift ? "06:00" : "14:00");
5704
5708
  const startHour = parseInt(shiftStart.split(":")[0]);
5709
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
5710
+ const endHour = parseInt(shiftEnd.split(":")[0]);
5711
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
5712
+ let shiftDuration = endHour - startHour;
5713
+ if (endMinute > startMinute) {
5714
+ shiftDuration += 1;
5715
+ }
5716
+ if (shiftDuration <= 0) {
5717
+ shiftDuration += 24;
5718
+ }
5705
5719
  let expectedHours = [];
5706
- if (isNightShift) {
5707
- for (let i = 0; i < 9; i++) {
5708
- expectedHours.push((startHour + i) % 24);
5709
- }
5710
- } else {
5711
- for (let i = 0; i < 9; i++) {
5712
- expectedHours.push((startHour + i) % 24);
5713
- }
5720
+ for (let i = 0; i < shiftDuration; i++) {
5721
+ expectedHours.push((startHour + i) % 24);
5714
5722
  }
5715
5723
  console.log("Expected shift hours (fallback):", expectedHours);
5716
5724
  console.log("Available data hours (fallback):", Object.keys(outputHourly2));
@@ -5814,15 +5822,19 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5814
5822
  const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
5815
5823
  const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
5816
5824
  const startHour = parseInt(shiftStart.split(":")[0]);
5825
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
5826
+ const endHour = parseInt(shiftEnd.split(":")[0]);
5827
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
5828
+ let shiftDuration = endHour - startHour;
5829
+ if (endMinute > startMinute) {
5830
+ shiftDuration += 1;
5831
+ }
5832
+ if (shiftDuration <= 0) {
5833
+ shiftDuration += 24;
5834
+ }
5817
5835
  let expectedHours = [];
5818
- if (isNightShift) {
5819
- for (let i = 0; i < 9; i++) {
5820
- expectedHours.push((startHour + i) % 24);
5821
- }
5822
- } else {
5823
- for (let i = 0; i < 9; i++) {
5824
- expectedHours.push((startHour + i) % 24);
5825
- }
5836
+ for (let i = 0; i < shiftDuration; i++) {
5837
+ expectedHours.push((startHour + i) % 24);
5826
5838
  }
5827
5839
  console.log("Expected shift hours:", expectedHours);
5828
5840
  console.log("Available data hours:", Object.keys(outputHourly));
@@ -21246,6 +21258,7 @@ var HourlyOutputChartComponent = ({
21246
21258
  data,
21247
21259
  pphThreshold,
21248
21260
  shiftStart,
21261
+ shiftEnd,
21249
21262
  showIdleTime = false,
21250
21263
  idleTimeHourly,
21251
21264
  className = ""
@@ -21260,10 +21273,32 @@ var HourlyOutputChartComponent = ({
21260
21273
  return { hour, minute, decimalHour };
21261
21274
  };
21262
21275
  const shiftStartTime = getTimeFromTimeString(shiftStart);
21263
- const SHIFT_DURATION = 11;
21264
- const [animatedData, setAnimatedData] = React19__namespace.default.useState(Array(SHIFT_DURATION).fill(0));
21276
+ const calculateShiftDuration = React19__namespace.default.useMemo(() => {
21277
+ if (!shiftEnd) {
21278
+ return 11;
21279
+ }
21280
+ const endTime = getTimeFromTimeString(shiftEnd);
21281
+ let duration = endTime.decimalHour - shiftStartTime.decimalHour;
21282
+ if (duration <= 0) {
21283
+ duration += 24;
21284
+ }
21285
+ return Math.round(duration);
21286
+ }, [shiftEnd, shiftStartTime.decimalHour]);
21287
+ const SHIFT_DURATION = calculateShiftDuration;
21288
+ const [animatedData, setAnimatedData] = React19__namespace.default.useState(
21289
+ () => Array(SHIFT_DURATION).fill(0)
21290
+ );
21265
21291
  const prevDataRef = React19__namespace.default.useRef(Array(SHIFT_DURATION).fill(0));
21266
21292
  const animationFrameRef = React19__namespace.default.useRef(null);
21293
+ React19__namespace.default.useEffect(() => {
21294
+ setAnimatedData((prev) => {
21295
+ if (prev.length !== SHIFT_DURATION) {
21296
+ return Array(SHIFT_DURATION).fill(0);
21297
+ }
21298
+ return prev;
21299
+ });
21300
+ prevDataRef.current = Array(SHIFT_DURATION).fill(0);
21301
+ }, [SHIFT_DURATION]);
21267
21302
  const [idleBarState, setIdleBarState] = React19__namespace.default.useState({
21268
21303
  visible: showIdleTime,
21269
21304
  key: 0,
@@ -24904,11 +24939,25 @@ var LinePdfGenerator = ({
24904
24939
  doc.setTextColor(70, 70, 70);
24905
24940
  doc.text("Hourly Output Overview", 20, 135);
24906
24941
  doc.setTextColor(0, 0, 0);
24907
- const getHourlyTimeRanges = (startTimeStr) => {
24942
+ const getHourlyTimeRanges = (startTimeStr, endTimeStr) => {
24908
24943
  const [hours, minutes] = startTimeStr.split(":");
24909
24944
  const startHour = parseInt(hours);
24910
24945
  const startMinute = parseInt(minutes || "0");
24911
- const SHIFT_DURATION = 11;
24946
+ let SHIFT_DURATION = 11;
24947
+ if (endTimeStr) {
24948
+ const [endHours, endMinutes] = endTimeStr.split(":");
24949
+ const endHour = parseInt(endHours);
24950
+ const endMinute = parseInt(endMinutes || "0");
24951
+ let duration = endHour - startHour;
24952
+ if (duration <= 0) {
24953
+ duration += 24;
24954
+ }
24955
+ const minuteDiff = endMinute - startMinute;
24956
+ if (minuteDiff !== 0) {
24957
+ duration += minuteDiff / 60;
24958
+ }
24959
+ SHIFT_DURATION = Math.round(duration);
24960
+ }
24912
24961
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
24913
24962
  const hourStartTime = /* @__PURE__ */ new Date();
24914
24963
  hourStartTime.setHours(startHour);
@@ -24929,12 +24978,35 @@ var LinePdfGenerator = ({
24929
24978
  return `${formatTime3(hourStartTime)} - ${formatTime3(hourEndTime)}`;
24930
24979
  });
24931
24980
  };
24932
- const hourlyTimeRanges = lineInfo.metrics.shift_start ? getHourlyTimeRanges(lineInfo.metrics.shift_start) : [];
24933
- const targetOutputPerHour = Math.round(lineInfo.metrics.line_threshold / 11);
24934
- const hourlyActualOutput = Array.from({ length: 11 }, (_, i) => {
24935
- const proportionalOutput = Math.round(lineInfo.metrics.current_output / 11 * (0.85 + Math.random() * 0.3));
24936
- return Math.max(0, proportionalOutput);
24937
- });
24981
+ const hourlyTimeRanges = lineInfo.metrics.shift_start ? getHourlyTimeRanges(lineInfo.metrics.shift_start, lineInfo.metrics.shift_end) : [];
24982
+ const shiftDuration = hourlyTimeRanges.length || 11;
24983
+ const targetOutputPerHour = Math.round(lineInfo.metrics.line_threshold / shiftDuration);
24984
+ let hourlyActualOutput = [];
24985
+ if (lineInfo.metrics.output_hourly && Object.keys(lineInfo.metrics.output_hourly).length > 0) {
24986
+ const startHour = parseInt(lineInfo.metrics.shift_start?.split(":")[0] || "6");
24987
+ const expectedHours = [];
24988
+ for (let i = 0; i < shiftDuration; i++) {
24989
+ expectedHours.push((startHour + i) % 24);
24990
+ }
24991
+ hourlyActualOutput = expectedHours.map((hour) => {
24992
+ const hourData = lineInfo.metrics.output_hourly[hour.toString()];
24993
+ if (hourData && Array.isArray(hourData)) {
24994
+ return hourData.reduce((sum, val) => sum + (val || 0), 0);
24995
+ }
24996
+ return 0;
24997
+ });
24998
+ } else if (lineInfo.metrics.output_array && lineInfo.metrics.output_array.length > 0) {
24999
+ hourlyActualOutput = lineInfo.metrics.output_array.reduce((acc, val, i) => {
25000
+ const hourIndex = Math.floor(i / 60);
25001
+ if (!acc[hourIndex]) acc[hourIndex] = 0;
25002
+ acc[hourIndex] += val;
25003
+ return acc;
25004
+ }, []);
25005
+ } else {
25006
+ hourlyActualOutput = Array.from({ length: shiftDuration }, () => {
25007
+ return Math.round(lineInfo.metrics.current_output / shiftDuration);
25008
+ });
25009
+ }
24938
25010
  doc.setFontSize(11);
24939
25011
  doc.setFont("helvetica", "bold");
24940
25012
  doc.setFillColor(245, 245, 245);
@@ -29322,10 +29394,11 @@ var HealthStatusGrid = ({
29322
29394
  };
29323
29395
  var ISTTimer2 = ISTTimer_default;
29324
29396
  var DashboardHeader = React19.memo(({ lineTitle, className = "", headerControls }) => {
29397
+ const dashboardConfig = useDashboardConfig();
29325
29398
  const getShiftName = () => {
29326
- const now2 = /* @__PURE__ */ new Date();
29327
- const currentHour = now2.getHours();
29328
- return currentHour >= 6 && currentHour < 18 ? "Day" : "Night";
29399
+ const timezone = dashboardConfig.dateTimeConfig?.defaultTimezone || "Asia/Kolkata";
29400
+ const currentShift = getCurrentShift(timezone, dashboardConfig.shiftConfig);
29401
+ return currentShift.shiftId === 0 ? "Day" : "Night";
29329
29402
  };
29330
29403
  const getShiftIcon = () => {
29331
29404
  const shift = getShiftName();
@@ -33817,7 +33890,8 @@ var BottomSection = React19.memo(({
33817
33890
  {
33818
33891
  data: hourlyOutputData,
33819
33892
  pphThreshold: hourlyThreshold,
33820
- shiftStart: lineInfo.metrics.shift_start || "06:00"
33893
+ shiftStart: lineInfo.metrics.shift_start || "06:00",
33894
+ shiftEnd: lineInfo.metrics.shift_end
33821
33895
  }
33822
33896
  ) })
33823
33897
  ] })
@@ -34057,6 +34131,7 @@ var KPIDetailView = ({
34057
34131
  underperforming_workspace_names: metrics2.underperforming_workspace_names || [],
34058
34132
  underperforming_workspace_uuids: metrics2.underperforming_workspace_uuids || [],
34059
34133
  output_array: metrics2.output_array || [],
34134
+ output_hourly: metrics2.output_hourly,
34060
34135
  line_threshold: metrics2.line_threshold ?? 0,
34061
34136
  threshold_pph: metrics2.threshold_pph ?? 0,
34062
34137
  shift_start: metrics2.shift_start || "06:00",
@@ -34067,14 +34142,40 @@ var KPIDetailView = ({
34067
34142
  };
34068
34143
  }, [metrics2, lineDetails, companyId]);
34069
34144
  const hourlyOutputData = React19.useMemo(() => {
34070
- if (!metrics2 || !metrics2.output_array) return [];
34071
- return metrics2.output_array.reduce((acc, val, i) => {
34072
- const hourIndex = Math.floor(i / 60);
34073
- if (!acc[hourIndex]) acc[hourIndex] = 0;
34074
- acc[hourIndex] += val;
34075
- return acc;
34076
- }, []);
34077
- }, [metrics2?.output_array]);
34145
+ if (!metrics2) return [];
34146
+ if (metrics2.output_hourly && Object.keys(metrics2.output_hourly).length > 0) {
34147
+ console.log("Using new output_hourly format in KPIDetailView");
34148
+ const isNightShift = metrics2.shift_id === 1;
34149
+ const shiftStart = metrics2.shift_start || (isNightShift ? "22:00" : "06:00");
34150
+ const shiftEnd = metrics2.shift_end || (isNightShift ? "06:00" : "14:00");
34151
+ const startHour = parseInt(shiftStart.split(":")[0]);
34152
+ const endHour = parseInt(shiftEnd.split(":")[0]);
34153
+ let shiftDuration = endHour - startHour;
34154
+ if (shiftDuration <= 0) {
34155
+ shiftDuration += 24;
34156
+ }
34157
+ let expectedHours = [];
34158
+ for (let i = 0; i < shiftDuration; i++) {
34159
+ expectedHours.push((startHour + i) % 24);
34160
+ }
34161
+ return expectedHours.map((hour) => {
34162
+ const hourData = metrics2.output_hourly[hour.toString()];
34163
+ if (hourData && Array.isArray(hourData)) {
34164
+ return hourData.reduce((sum, val) => sum + (val || 0), 0);
34165
+ }
34166
+ return 0;
34167
+ });
34168
+ }
34169
+ if (metrics2.output_array) {
34170
+ return metrics2.output_array.reduce((acc, val, i) => {
34171
+ const hourIndex = Math.floor(i / 60);
34172
+ if (!acc[hourIndex]) acc[hourIndex] = 0;
34173
+ acc[hourIndex] += val;
34174
+ return acc;
34175
+ }, []);
34176
+ }
34177
+ return [];
34178
+ }, [metrics2]);
34078
34179
  const hourlyThreshold = React19.useMemo(() => metrics2 ? metrics2.threshold_pph || 0 : 0, [metrics2]);
34079
34180
  const sortedByEfficiency = React19.useMemo(() => {
34080
34181
  if (!workspaces) return [];
@@ -38728,6 +38829,7 @@ var WorkspaceDetailView = ({
38728
38829
  data: workspace.hourly_action_counts || [],
38729
38830
  pphThreshold: workspace.pph_threshold || 0,
38730
38831
  shiftStart: workspace.shift_start || "",
38832
+ shiftEnd: workspace.shift_end,
38731
38833
  showIdleTime,
38732
38834
  idleTimeHourly: workspace.idle_time_hourly
38733
38835
  }
@@ -38846,6 +38948,7 @@ var WorkspaceDetailView = ({
38846
38948
  data: workspace.hourly_action_counts || [],
38847
38949
  pphThreshold: workspace.pph_threshold || 0,
38848
38950
  shiftStart: workspace.shift_start || "",
38951
+ shiftEnd: workspace.shift_end,
38849
38952
  showIdleTime,
38850
38953
  idleTimeHourly: workspace.idle_time_hourly
38851
38954
  }
package/dist/index.mjs CHANGED
@@ -863,15 +863,19 @@ var dashboardService = {
863
863
  const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
864
864
  const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
865
865
  const startHour = parseInt(shiftStart.split(":")[0]);
866
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
867
+ const endHour = parseInt(shiftEnd.split(":")[0]);
868
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
869
+ let shiftDuration = endHour - startHour;
870
+ if (endMinute > startMinute) {
871
+ shiftDuration += 1;
872
+ }
873
+ if (shiftDuration <= 0) {
874
+ shiftDuration += 24;
875
+ }
866
876
  let expectedHours = [];
867
- if (isNightShift) {
868
- for (let i = 0; i < 9; i++) {
869
- expectedHours.push((startHour + i) % 24);
870
- }
871
- } else {
872
- for (let i = 0; i < 9; i++) {
873
- expectedHours.push((startHour + i) % 24);
874
- }
877
+ for (let i = 0; i < shiftDuration; i++) {
878
+ expectedHours.push((startHour + i) % 24);
875
879
  }
876
880
  console.log("Expected shift hours:", expectedHours);
877
881
  console.log("Available data hours:", Object.keys(outputHourly));
@@ -5672,15 +5676,19 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5672
5676
  const shiftStart = recentData.shift_start || (isNightShift ? "22:00" : "06:00");
5673
5677
  const shiftEnd = recentData.shift_end || (isNightShift ? "06:00" : "14:00");
5674
5678
  const startHour = parseInt(shiftStart.split(":")[0]);
5679
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
5680
+ const endHour = parseInt(shiftEnd.split(":")[0]);
5681
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
5682
+ let shiftDuration = endHour - startHour;
5683
+ if (endMinute > startMinute) {
5684
+ shiftDuration += 1;
5685
+ }
5686
+ if (shiftDuration <= 0) {
5687
+ shiftDuration += 24;
5688
+ }
5675
5689
  let expectedHours = [];
5676
- if (isNightShift) {
5677
- for (let i = 0; i < 9; i++) {
5678
- expectedHours.push((startHour + i) % 24);
5679
- }
5680
- } else {
5681
- for (let i = 0; i < 9; i++) {
5682
- expectedHours.push((startHour + i) % 24);
5683
- }
5690
+ for (let i = 0; i < shiftDuration; i++) {
5691
+ expectedHours.push((startHour + i) % 24);
5684
5692
  }
5685
5693
  console.log("Expected shift hours (fallback):", expectedHours);
5686
5694
  console.log("Available data hours (fallback):", Object.keys(outputHourly2));
@@ -5784,15 +5792,19 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5784
5792
  const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
5785
5793
  const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
5786
5794
  const startHour = parseInt(shiftStart.split(":")[0]);
5795
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
5796
+ const endHour = parseInt(shiftEnd.split(":")[0]);
5797
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
5798
+ let shiftDuration = endHour - startHour;
5799
+ if (endMinute > startMinute) {
5800
+ shiftDuration += 1;
5801
+ }
5802
+ if (shiftDuration <= 0) {
5803
+ shiftDuration += 24;
5804
+ }
5787
5805
  let expectedHours = [];
5788
- if (isNightShift) {
5789
- for (let i = 0; i < 9; i++) {
5790
- expectedHours.push((startHour + i) % 24);
5791
- }
5792
- } else {
5793
- for (let i = 0; i < 9; i++) {
5794
- expectedHours.push((startHour + i) % 24);
5795
- }
5806
+ for (let i = 0; i < shiftDuration; i++) {
5807
+ expectedHours.push((startHour + i) % 24);
5796
5808
  }
5797
5809
  console.log("Expected shift hours:", expectedHours);
5798
5810
  console.log("Available data hours:", Object.keys(outputHourly));
@@ -21216,6 +21228,7 @@ var HourlyOutputChartComponent = ({
21216
21228
  data,
21217
21229
  pphThreshold,
21218
21230
  shiftStart,
21231
+ shiftEnd,
21219
21232
  showIdleTime = false,
21220
21233
  idleTimeHourly,
21221
21234
  className = ""
@@ -21230,10 +21243,32 @@ var HourlyOutputChartComponent = ({
21230
21243
  return { hour, minute, decimalHour };
21231
21244
  };
21232
21245
  const shiftStartTime = getTimeFromTimeString(shiftStart);
21233
- const SHIFT_DURATION = 11;
21234
- const [animatedData, setAnimatedData] = React19__default.useState(Array(SHIFT_DURATION).fill(0));
21246
+ const calculateShiftDuration = React19__default.useMemo(() => {
21247
+ if (!shiftEnd) {
21248
+ return 11;
21249
+ }
21250
+ const endTime = getTimeFromTimeString(shiftEnd);
21251
+ let duration = endTime.decimalHour - shiftStartTime.decimalHour;
21252
+ if (duration <= 0) {
21253
+ duration += 24;
21254
+ }
21255
+ return Math.round(duration);
21256
+ }, [shiftEnd, shiftStartTime.decimalHour]);
21257
+ const SHIFT_DURATION = calculateShiftDuration;
21258
+ const [animatedData, setAnimatedData] = React19__default.useState(
21259
+ () => Array(SHIFT_DURATION).fill(0)
21260
+ );
21235
21261
  const prevDataRef = React19__default.useRef(Array(SHIFT_DURATION).fill(0));
21236
21262
  const animationFrameRef = React19__default.useRef(null);
21263
+ React19__default.useEffect(() => {
21264
+ setAnimatedData((prev) => {
21265
+ if (prev.length !== SHIFT_DURATION) {
21266
+ return Array(SHIFT_DURATION).fill(0);
21267
+ }
21268
+ return prev;
21269
+ });
21270
+ prevDataRef.current = Array(SHIFT_DURATION).fill(0);
21271
+ }, [SHIFT_DURATION]);
21237
21272
  const [idleBarState, setIdleBarState] = React19__default.useState({
21238
21273
  visible: showIdleTime,
21239
21274
  key: 0,
@@ -24874,11 +24909,25 @@ var LinePdfGenerator = ({
24874
24909
  doc.setTextColor(70, 70, 70);
24875
24910
  doc.text("Hourly Output Overview", 20, 135);
24876
24911
  doc.setTextColor(0, 0, 0);
24877
- const getHourlyTimeRanges = (startTimeStr) => {
24912
+ const getHourlyTimeRanges = (startTimeStr, endTimeStr) => {
24878
24913
  const [hours, minutes] = startTimeStr.split(":");
24879
24914
  const startHour = parseInt(hours);
24880
24915
  const startMinute = parseInt(minutes || "0");
24881
- const SHIFT_DURATION = 11;
24916
+ let SHIFT_DURATION = 11;
24917
+ if (endTimeStr) {
24918
+ const [endHours, endMinutes] = endTimeStr.split(":");
24919
+ const endHour = parseInt(endHours);
24920
+ const endMinute = parseInt(endMinutes || "0");
24921
+ let duration = endHour - startHour;
24922
+ if (duration <= 0) {
24923
+ duration += 24;
24924
+ }
24925
+ const minuteDiff = endMinute - startMinute;
24926
+ if (minuteDiff !== 0) {
24927
+ duration += minuteDiff / 60;
24928
+ }
24929
+ SHIFT_DURATION = Math.round(duration);
24930
+ }
24882
24931
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
24883
24932
  const hourStartTime = /* @__PURE__ */ new Date();
24884
24933
  hourStartTime.setHours(startHour);
@@ -24899,12 +24948,35 @@ var LinePdfGenerator = ({
24899
24948
  return `${formatTime3(hourStartTime)} - ${formatTime3(hourEndTime)}`;
24900
24949
  });
24901
24950
  };
24902
- const hourlyTimeRanges = lineInfo.metrics.shift_start ? getHourlyTimeRanges(lineInfo.metrics.shift_start) : [];
24903
- const targetOutputPerHour = Math.round(lineInfo.metrics.line_threshold / 11);
24904
- const hourlyActualOutput = Array.from({ length: 11 }, (_, i) => {
24905
- const proportionalOutput = Math.round(lineInfo.metrics.current_output / 11 * (0.85 + Math.random() * 0.3));
24906
- return Math.max(0, proportionalOutput);
24907
- });
24951
+ const hourlyTimeRanges = lineInfo.metrics.shift_start ? getHourlyTimeRanges(lineInfo.metrics.shift_start, lineInfo.metrics.shift_end) : [];
24952
+ const shiftDuration = hourlyTimeRanges.length || 11;
24953
+ const targetOutputPerHour = Math.round(lineInfo.metrics.line_threshold / shiftDuration);
24954
+ let hourlyActualOutput = [];
24955
+ if (lineInfo.metrics.output_hourly && Object.keys(lineInfo.metrics.output_hourly).length > 0) {
24956
+ const startHour = parseInt(lineInfo.metrics.shift_start?.split(":")[0] || "6");
24957
+ const expectedHours = [];
24958
+ for (let i = 0; i < shiftDuration; i++) {
24959
+ expectedHours.push((startHour + i) % 24);
24960
+ }
24961
+ hourlyActualOutput = expectedHours.map((hour) => {
24962
+ const hourData = lineInfo.metrics.output_hourly[hour.toString()];
24963
+ if (hourData && Array.isArray(hourData)) {
24964
+ return hourData.reduce((sum, val) => sum + (val || 0), 0);
24965
+ }
24966
+ return 0;
24967
+ });
24968
+ } else if (lineInfo.metrics.output_array && lineInfo.metrics.output_array.length > 0) {
24969
+ hourlyActualOutput = lineInfo.metrics.output_array.reduce((acc, val, i) => {
24970
+ const hourIndex = Math.floor(i / 60);
24971
+ if (!acc[hourIndex]) acc[hourIndex] = 0;
24972
+ acc[hourIndex] += val;
24973
+ return acc;
24974
+ }, []);
24975
+ } else {
24976
+ hourlyActualOutput = Array.from({ length: shiftDuration }, () => {
24977
+ return Math.round(lineInfo.metrics.current_output / shiftDuration);
24978
+ });
24979
+ }
24908
24980
  doc.setFontSize(11);
24909
24981
  doc.setFont("helvetica", "bold");
24910
24982
  doc.setFillColor(245, 245, 245);
@@ -29292,10 +29364,11 @@ var HealthStatusGrid = ({
29292
29364
  };
29293
29365
  var ISTTimer2 = ISTTimer_default;
29294
29366
  var DashboardHeader = memo(({ lineTitle, className = "", headerControls }) => {
29367
+ const dashboardConfig = useDashboardConfig();
29295
29368
  const getShiftName = () => {
29296
- const now2 = /* @__PURE__ */ new Date();
29297
- const currentHour = now2.getHours();
29298
- return currentHour >= 6 && currentHour < 18 ? "Day" : "Night";
29369
+ const timezone = dashboardConfig.dateTimeConfig?.defaultTimezone || "Asia/Kolkata";
29370
+ const currentShift = getCurrentShift(timezone, dashboardConfig.shiftConfig);
29371
+ return currentShift.shiftId === 0 ? "Day" : "Night";
29299
29372
  };
29300
29373
  const getShiftIcon = () => {
29301
29374
  const shift = getShiftName();
@@ -33787,7 +33860,8 @@ var BottomSection = memo(({
33787
33860
  {
33788
33861
  data: hourlyOutputData,
33789
33862
  pphThreshold: hourlyThreshold,
33790
- shiftStart: lineInfo.metrics.shift_start || "06:00"
33863
+ shiftStart: lineInfo.metrics.shift_start || "06:00",
33864
+ shiftEnd: lineInfo.metrics.shift_end
33791
33865
  }
33792
33866
  ) })
33793
33867
  ] })
@@ -34027,6 +34101,7 @@ var KPIDetailView = ({
34027
34101
  underperforming_workspace_names: metrics2.underperforming_workspace_names || [],
34028
34102
  underperforming_workspace_uuids: metrics2.underperforming_workspace_uuids || [],
34029
34103
  output_array: metrics2.output_array || [],
34104
+ output_hourly: metrics2.output_hourly,
34030
34105
  line_threshold: metrics2.line_threshold ?? 0,
34031
34106
  threshold_pph: metrics2.threshold_pph ?? 0,
34032
34107
  shift_start: metrics2.shift_start || "06:00",
@@ -34037,14 +34112,40 @@ var KPIDetailView = ({
34037
34112
  };
34038
34113
  }, [metrics2, lineDetails, companyId]);
34039
34114
  const hourlyOutputData = useMemo(() => {
34040
- if (!metrics2 || !metrics2.output_array) return [];
34041
- return metrics2.output_array.reduce((acc, val, i) => {
34042
- const hourIndex = Math.floor(i / 60);
34043
- if (!acc[hourIndex]) acc[hourIndex] = 0;
34044
- acc[hourIndex] += val;
34045
- return acc;
34046
- }, []);
34047
- }, [metrics2?.output_array]);
34115
+ if (!metrics2) return [];
34116
+ if (metrics2.output_hourly && Object.keys(metrics2.output_hourly).length > 0) {
34117
+ console.log("Using new output_hourly format in KPIDetailView");
34118
+ const isNightShift = metrics2.shift_id === 1;
34119
+ const shiftStart = metrics2.shift_start || (isNightShift ? "22:00" : "06:00");
34120
+ const shiftEnd = metrics2.shift_end || (isNightShift ? "06:00" : "14:00");
34121
+ const startHour = parseInt(shiftStart.split(":")[0]);
34122
+ const endHour = parseInt(shiftEnd.split(":")[0]);
34123
+ let shiftDuration = endHour - startHour;
34124
+ if (shiftDuration <= 0) {
34125
+ shiftDuration += 24;
34126
+ }
34127
+ let expectedHours = [];
34128
+ for (let i = 0; i < shiftDuration; i++) {
34129
+ expectedHours.push((startHour + i) % 24);
34130
+ }
34131
+ return expectedHours.map((hour) => {
34132
+ const hourData = metrics2.output_hourly[hour.toString()];
34133
+ if (hourData && Array.isArray(hourData)) {
34134
+ return hourData.reduce((sum, val) => sum + (val || 0), 0);
34135
+ }
34136
+ return 0;
34137
+ });
34138
+ }
34139
+ if (metrics2.output_array) {
34140
+ return metrics2.output_array.reduce((acc, val, i) => {
34141
+ const hourIndex = Math.floor(i / 60);
34142
+ if (!acc[hourIndex]) acc[hourIndex] = 0;
34143
+ acc[hourIndex] += val;
34144
+ return acc;
34145
+ }, []);
34146
+ }
34147
+ return [];
34148
+ }, [metrics2]);
34048
34149
  const hourlyThreshold = useMemo(() => metrics2 ? metrics2.threshold_pph || 0 : 0, [metrics2]);
34049
34150
  const sortedByEfficiency = useMemo(() => {
34050
34151
  if (!workspaces) return [];
@@ -38698,6 +38799,7 @@ var WorkspaceDetailView = ({
38698
38799
  data: workspace.hourly_action_counts || [],
38699
38800
  pphThreshold: workspace.pph_threshold || 0,
38700
38801
  shiftStart: workspace.shift_start || "",
38802
+ shiftEnd: workspace.shift_end,
38701
38803
  showIdleTime,
38702
38804
  idleTimeHourly: workspace.idle_time_hourly
38703
38805
  }
@@ -38816,6 +38918,7 @@ var WorkspaceDetailView = ({
38816
38918
  data: workspace.hourly_action_counts || [],
38817
38919
  pphThreshold: workspace.pph_threshold || 0,
38818
38920
  shiftStart: workspace.shift_start || "",
38921
+ shiftEnd: workspace.shift_end,
38819
38922
  showIdleTime,
38820
38923
  idleTimeHourly: workspace.idle_time_hourly
38821
38924
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optifye/dashboard-core",
3
- "version": "6.5.6",
3
+ "version": "6.5.8",
4
4
  "description": "Reusable UI & logic for Optifye dashboard",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",