@optifye/dashboard-core 6.10.0 → 6.10.1
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 +73 -1
- package/dist/index.d.ts +73 -1
- package/dist/index.js +789 -347
- package/dist/index.mjs +786 -348
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8867,27 +8867,208 @@ var useLeaderboardMetrics = (date, shiftId, limit = 10, filter2 = "all") => {
|
|
|
8867
8867
|
refetch: fetchLeaderboard
|
|
8868
8868
|
};
|
|
8869
8869
|
};
|
|
8870
|
+
var useMultiLineShiftConfigs = (lineIds, fallbackConfig) => {
|
|
8871
|
+
const [shiftConfigMap, setShiftConfigMap] = React24.useState(/* @__PURE__ */ new Map());
|
|
8872
|
+
const [isLoading, setIsLoading] = React24.useState(true);
|
|
8873
|
+
const [error, setError] = React24.useState(null);
|
|
8874
|
+
const supabase = useSupabase();
|
|
8875
|
+
const lineIdsKey = React24.useMemo(() => lineIds.sort().join(","), [lineIds]);
|
|
8876
|
+
React24.useEffect(() => {
|
|
8877
|
+
if (!lineIds || lineIds.length === 0) {
|
|
8878
|
+
setShiftConfigMap(/* @__PURE__ */ new Map());
|
|
8879
|
+
setIsLoading(false);
|
|
8880
|
+
return;
|
|
8881
|
+
}
|
|
8882
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8883
|
+
const validLineIds = lineIds.filter((id3) => uuidRegex.test(id3));
|
|
8884
|
+
if (validLineIds.length === 0) {
|
|
8885
|
+
console.warn("[useMultiLineShiftConfigs] No valid line IDs provided");
|
|
8886
|
+
setShiftConfigMap(/* @__PURE__ */ new Map());
|
|
8887
|
+
setIsLoading(false);
|
|
8888
|
+
return;
|
|
8889
|
+
}
|
|
8890
|
+
let mounted = true;
|
|
8891
|
+
const calculateBreakDuration2 = (startTime, endTime) => {
|
|
8892
|
+
const [sh, sm] = startTime.split(":").map(Number);
|
|
8893
|
+
const [eh, em] = endTime.split(":").map(Number);
|
|
8894
|
+
let startMinutes = sh * 60 + sm;
|
|
8895
|
+
let endMinutes = eh * 60 + em;
|
|
8896
|
+
if (endMinutes < startMinutes) {
|
|
8897
|
+
endMinutes += 24 * 60;
|
|
8898
|
+
}
|
|
8899
|
+
return endMinutes - startMinutes;
|
|
8900
|
+
};
|
|
8901
|
+
const stripSeconds = (timeStr) => {
|
|
8902
|
+
if (!timeStr) return timeStr;
|
|
8903
|
+
return timeStr.substring(0, 5);
|
|
8904
|
+
};
|
|
8905
|
+
const buildShiftConfigFromRows = (shifts, fallback) => {
|
|
8906
|
+
const mapped = shifts.map((shift) => ({
|
|
8907
|
+
shiftId: shift.shift_id,
|
|
8908
|
+
shiftName: shift.shift_name || `Shift ${shift.shift_id}`,
|
|
8909
|
+
startTime: stripSeconds(shift.start_time),
|
|
8910
|
+
endTime: stripSeconds(shift.end_time),
|
|
8911
|
+
breaks: Array.isArray(shift.breaks) ? shift.breaks.map((b) => ({
|
|
8912
|
+
startTime: b.start || b.startTime || "00:00",
|
|
8913
|
+
endTime: b.end || b.endTime || "00:00",
|
|
8914
|
+
duration: calculateBreakDuration2(
|
|
8915
|
+
b.start || b.startTime || "00:00",
|
|
8916
|
+
b.end || b.endTime || "00:00"
|
|
8917
|
+
),
|
|
8918
|
+
remarks: b.remarks || b.name || ""
|
|
8919
|
+
})) : [],
|
|
8920
|
+
timezone: shift.timezone
|
|
8921
|
+
}));
|
|
8922
|
+
const day = mapped.find((s) => s.shiftId === 0);
|
|
8923
|
+
const night = mapped.find((s) => s.shiftId === 1);
|
|
8924
|
+
return {
|
|
8925
|
+
shifts: mapped,
|
|
8926
|
+
timezone: mapped[0]?.timezone,
|
|
8927
|
+
dayShift: day ? { id: day.shiftId, startTime: day.startTime, endTime: day.endTime, name: day.shiftName } : fallback?.dayShift,
|
|
8928
|
+
nightShift: night ? { id: night.shiftId, startTime: night.startTime, endTime: night.endTime, name: night.shiftName } : fallback?.nightShift,
|
|
8929
|
+
transitionPeriodMinutes: fallback?.transitionPeriodMinutes || 0
|
|
8930
|
+
};
|
|
8931
|
+
};
|
|
8932
|
+
const fetchAllConfigs = async () => {
|
|
8933
|
+
try {
|
|
8934
|
+
setIsLoading(true);
|
|
8935
|
+
setError(null);
|
|
8936
|
+
console.log(`[useMultiLineShiftConfigs] Fetching shift configs for ${validLineIds.length} lines`);
|
|
8937
|
+
const { data, error: fetchError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks, timezone").in("line_id", validLineIds);
|
|
8938
|
+
if (fetchError) {
|
|
8939
|
+
console.error("[useMultiLineShiftConfigs] Error fetching shift configs:", fetchError);
|
|
8940
|
+
throw new Error(`Failed to fetch shift configs: ${fetchError.message}`);
|
|
8941
|
+
}
|
|
8942
|
+
const lineShiftsMap = /* @__PURE__ */ new Map();
|
|
8943
|
+
data?.forEach((row) => {
|
|
8944
|
+
if (!lineShiftsMap.has(row.line_id)) {
|
|
8945
|
+
lineShiftsMap.set(row.line_id, []);
|
|
8946
|
+
}
|
|
8947
|
+
lineShiftsMap.get(row.line_id).push(row);
|
|
8948
|
+
});
|
|
8949
|
+
const configMap = /* @__PURE__ */ new Map();
|
|
8950
|
+
lineShiftsMap.forEach((shifts, lineId) => {
|
|
8951
|
+
const config = buildShiftConfigFromRows(shifts, fallbackConfig);
|
|
8952
|
+
configMap.set(lineId, config);
|
|
8953
|
+
});
|
|
8954
|
+
validLineIds.forEach((lineId) => {
|
|
8955
|
+
if (!configMap.has(lineId) && fallbackConfig) {
|
|
8956
|
+
console.warn(`[useMultiLineShiftConfigs] No config found for line ${lineId}, using fallback`);
|
|
8957
|
+
configMap.set(lineId, fallbackConfig);
|
|
8958
|
+
}
|
|
8959
|
+
});
|
|
8960
|
+
console.log(`[useMultiLineShiftConfigs] Built configs for ${configMap.size} lines`);
|
|
8961
|
+
if (mounted) {
|
|
8962
|
+
setShiftConfigMap(configMap);
|
|
8963
|
+
setIsLoading(false);
|
|
8964
|
+
}
|
|
8965
|
+
} catch (err) {
|
|
8966
|
+
console.error("[useMultiLineShiftConfigs] Error:", err);
|
|
8967
|
+
if (mounted) {
|
|
8968
|
+
setError(err instanceof Error ? err.message : "Failed to fetch shift configs");
|
|
8969
|
+
if (fallbackConfig) {
|
|
8970
|
+
const fallbackMap = /* @__PURE__ */ new Map();
|
|
8971
|
+
validLineIds.forEach((lineId) => {
|
|
8972
|
+
fallbackMap.set(lineId, fallbackConfig);
|
|
8973
|
+
});
|
|
8974
|
+
setShiftConfigMap(fallbackMap);
|
|
8975
|
+
}
|
|
8976
|
+
setIsLoading(false);
|
|
8977
|
+
}
|
|
8978
|
+
}
|
|
8979
|
+
};
|
|
8980
|
+
fetchAllConfigs();
|
|
8981
|
+
return () => {
|
|
8982
|
+
mounted = false;
|
|
8983
|
+
};
|
|
8984
|
+
}, [lineIdsKey, supabase]);
|
|
8985
|
+
return {
|
|
8986
|
+
shiftConfigMap,
|
|
8987
|
+
isLoading,
|
|
8988
|
+
error
|
|
8989
|
+
};
|
|
8990
|
+
};
|
|
8991
|
+
|
|
8992
|
+
// src/lib/utils/shiftGrouping.ts
|
|
8993
|
+
var getCurrentShiftForLine = (lineId, shiftConfig, timezone, now2 = /* @__PURE__ */ new Date()) => {
|
|
8994
|
+
const currentShift = getCurrentShift(timezone, shiftConfig, now2);
|
|
8995
|
+
return {
|
|
8996
|
+
lineId,
|
|
8997
|
+
shiftId: currentShift.shiftId,
|
|
8998
|
+
date: currentShift.date,
|
|
8999
|
+
shiftName: currentShift.shiftName || `Shift ${currentShift.shiftId}`
|
|
9000
|
+
};
|
|
9001
|
+
};
|
|
9002
|
+
var groupLinesByShift = (shiftConfigMap, timezone, now2 = /* @__PURE__ */ new Date()) => {
|
|
9003
|
+
const lineShiftInfos = [];
|
|
9004
|
+
shiftConfigMap.forEach((shiftConfig, lineId) => {
|
|
9005
|
+
const info = getCurrentShiftForLine(lineId, shiftConfig, timezone, now2);
|
|
9006
|
+
lineShiftInfos.push(info);
|
|
9007
|
+
});
|
|
9008
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
9009
|
+
lineShiftInfos.forEach((info) => {
|
|
9010
|
+
const key = `${info.shiftId}-${info.date}`;
|
|
9011
|
+
if (!groupMap.has(key)) {
|
|
9012
|
+
groupMap.set(key, {
|
|
9013
|
+
shiftId: info.shiftId,
|
|
9014
|
+
date: info.date,
|
|
9015
|
+
shiftName: info.shiftName,
|
|
9016
|
+
lineIds: []
|
|
9017
|
+
});
|
|
9018
|
+
}
|
|
9019
|
+
groupMap.get(key).lineIds.push(info.lineId);
|
|
9020
|
+
});
|
|
9021
|
+
return Array.from(groupMap.values()).sort((a, b) => a.shiftId - b.shiftId);
|
|
9022
|
+
};
|
|
9023
|
+
var areAllLinesOnSameShift = (shiftConfigMap, timezone, now2 = /* @__PURE__ */ new Date()) => {
|
|
9024
|
+
if (shiftConfigMap.size <= 1) return true;
|
|
9025
|
+
const groups = groupLinesByShift(shiftConfigMap, timezone, now2);
|
|
9026
|
+
return groups.length === 1;
|
|
9027
|
+
};
|
|
9028
|
+
var getUniformShiftGroup = (shiftConfigMap, timezone, now2 = /* @__PURE__ */ new Date()) => {
|
|
9029
|
+
const groups = groupLinesByShift(shiftConfigMap, timezone, now2);
|
|
9030
|
+
return groups.length === 1 ? groups[0] : null;
|
|
9031
|
+
};
|
|
9032
|
+
|
|
9033
|
+
// src/lib/hooks/useDashboardMetrics.ts
|
|
8870
9034
|
var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds }) => {
|
|
8871
9035
|
const { supabaseUrl, supabaseKey } = useDashboardConfig();
|
|
8872
9036
|
const entityConfig = useEntityConfig();
|
|
8873
9037
|
const databaseConfig = useDatabaseConfig();
|
|
8874
9038
|
const dateTimeConfig = useDateTimeConfig();
|
|
8875
9039
|
const isFactoryView = lineId === (entityConfig.factoryViewId || "factory");
|
|
8876
|
-
const
|
|
8877
|
-
|
|
8878
|
-
|
|
9040
|
+
const appTimezone = useAppTimezone();
|
|
9041
|
+
const defaultTimezone = appTimezone || dateTimeConfig?.defaultTimezone || "UTC";
|
|
9042
|
+
const configuredLineIds = React24.useMemo(() => {
|
|
9043
|
+
return getConfiguredLineIds(entityConfig);
|
|
8879
9044
|
}, [entityConfig]);
|
|
8880
|
-
const
|
|
8881
|
-
const {
|
|
9045
|
+
const { shiftConfig: staticShiftConfig } = useDashboardConfig();
|
|
9046
|
+
const {
|
|
9047
|
+
shiftConfigMap: multiLineShiftConfigMap,
|
|
9048
|
+
isLoading: isMultiLineShiftConfigLoading
|
|
9049
|
+
} = useMultiLineShiftConfigs(
|
|
9050
|
+
isFactoryView ? configuredLineIds : [],
|
|
9051
|
+
staticShiftConfig
|
|
9052
|
+
);
|
|
9053
|
+
const {
|
|
9054
|
+
shiftConfig: singleLineShiftConfig,
|
|
9055
|
+
isLoading: isSingleLineShiftConfigLoading,
|
|
9056
|
+
isFromDatabase
|
|
9057
|
+
} = useDynamicShiftConfig(isFactoryView ? void 0 : lineId);
|
|
9058
|
+
const shiftLoading = isFactoryView ? isMultiLineShiftConfigLoading : isSingleLineShiftConfigLoading;
|
|
9059
|
+
const shiftGroups = React24.useMemo(() => {
|
|
9060
|
+
if (!isFactoryView) return [];
|
|
9061
|
+
if (isMultiLineShiftConfigLoading || multiLineShiftConfigMap.size === 0) return [];
|
|
9062
|
+
return groupLinesByShift(multiLineShiftConfigMap, defaultTimezone);
|
|
9063
|
+
}, [isFactoryView, isMultiLineShiftConfigLoading, multiLineShiftConfigMap, defaultTimezone]);
|
|
9064
|
+
const shiftConfig = isFactoryView ? null : singleLineShiftConfig;
|
|
8882
9065
|
console.log(`[useDashboardMetrics] \u{1F3AF} Shift config for line ${lineId}:`, {
|
|
8883
9066
|
isFactoryView,
|
|
8884
|
-
lineIdForShiftConfig,
|
|
8885
|
-
firstLineId,
|
|
8886
9067
|
isFromDatabase,
|
|
8887
|
-
shiftConfig: shiftConfig ? { shifts: shiftConfig.shifts?.length, timezone: shiftConfig.timezone } : null
|
|
9068
|
+
shiftConfig: shiftConfig ? { shifts: shiftConfig.shifts?.length, timezone: shiftConfig.timezone } : null,
|
|
9069
|
+
shiftGroupsCount: shiftGroups.length,
|
|
9070
|
+
shiftGroups: shiftGroups.map((g) => ({ shiftId: g.shiftId, date: g.date, lineCount: g.lineIds.length }))
|
|
8888
9071
|
});
|
|
8889
|
-
const appTimezone = useAppTimezone();
|
|
8890
|
-
const defaultTimezone = appTimezone || dateTimeConfig?.defaultTimezone || "UTC";
|
|
8891
9072
|
const configuredLineMetricsTable = databaseConfig?.tables?.lineMetrics ?? "line_metrics";
|
|
8892
9073
|
const schema = databaseConfig?.schema ?? "public";
|
|
8893
9074
|
const supabase = useSupabase();
|
|
@@ -8924,16 +9105,6 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
8924
9105
|
setIsLoading(true);
|
|
8925
9106
|
setError(null);
|
|
8926
9107
|
try {
|
|
8927
|
-
const currentShiftDetails = getCurrentShift(defaultTimezone, shiftConfig);
|
|
8928
|
-
const operationalDate = getOperationalDate(defaultTimezone);
|
|
8929
|
-
const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? userAccessibleLineIds || getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
|
|
8930
|
-
if (targetLineIds.length === 0 && currentLineIdToUse === (entityConfig.factoryViewId || "factory")) {
|
|
8931
|
-
throw new Error("Factory view selected, but no lines are configured in entityConfig.");
|
|
8932
|
-
}
|
|
8933
|
-
if (targetLineIds.length === 0) {
|
|
8934
|
-
throw new Error("No target line IDs available for fetching metrics.");
|
|
8935
|
-
}
|
|
8936
|
-
const isFactoryView2 = currentLineIdToUse === (entityConfig.factoryViewId || "factory");
|
|
8937
9108
|
const { data: { session } } = await supabase.auth.getSession();
|
|
8938
9109
|
console.log("[useDashboardMetrics] Session check:", {
|
|
8939
9110
|
hasSession: !!session,
|
|
@@ -8947,42 +9118,98 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
8947
9118
|
if (!apiUrl) {
|
|
8948
9119
|
throw new Error("Backend URL is not configured. Please set NEXT_PUBLIC_BACKEND_URL in your environment.");
|
|
8949
9120
|
}
|
|
8950
|
-
const
|
|
8951
|
-
const
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
lineIdsParam,
|
|
8956
|
-
operationalDate,
|
|
8957
|
-
shiftId: currentShiftDetails.shiftId,
|
|
8958
|
-
companyId: entityConfig.companyId
|
|
8959
|
-
});
|
|
8960
|
-
const response = await fetch(url, {
|
|
8961
|
-
method: "GET",
|
|
8962
|
-
headers: {
|
|
8963
|
-
"Authorization": `Bearer ${session.access_token}`,
|
|
8964
|
-
"Content-Type": "application/json"
|
|
8965
|
-
}
|
|
8966
|
-
});
|
|
8967
|
-
console.log("[useDashboardMetrics] Response status:", response.status, response.statusText);
|
|
8968
|
-
if (!response.ok) {
|
|
8969
|
-
const errorText = await response.text();
|
|
8970
|
-
console.error("[useDashboardMetrics] Backend API error response:", errorText);
|
|
8971
|
-
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
9121
|
+
const factoryViewIdentifier = entityConfig.factoryViewId || "factory";
|
|
9122
|
+
const isFactory = currentLineIdToUse === factoryViewIdentifier;
|
|
9123
|
+
const targetLineIds = isFactory ? userAccessibleLineIds || configuredLineIds : [currentLineIdToUse];
|
|
9124
|
+
if (targetLineIds.length === 0) {
|
|
9125
|
+
throw new Error("No target line IDs available for fetching metrics.");
|
|
8972
9126
|
}
|
|
8973
|
-
|
|
8974
|
-
let
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
9127
|
+
let allWorkspaceMetrics = [];
|
|
9128
|
+
let allLineMetrics = [];
|
|
9129
|
+
if (isFactory && shiftGroups.length > 0) {
|
|
9130
|
+
console.log(`[useDashboardMetrics] \u{1F3ED} Factory view: Fetching for ${shiftGroups.length} shift group(s)`);
|
|
9131
|
+
const metricsPromises = shiftGroups.map(async (group) => {
|
|
9132
|
+
const lineIdsParam = `line_ids=${group.lineIds.join(",")}`;
|
|
9133
|
+
const url = `${apiUrl}/api/dashboard/metrics?${lineIdsParam}&date=${group.date}&shift_id=${group.shiftId}&company_id=${entityConfig.companyId}`;
|
|
9134
|
+
console.log(`[useDashboardMetrics] \u{1F4CA} Fetching for shift ${group.shiftId} (${group.shiftName}):`, {
|
|
9135
|
+
lineIds: group.lineIds,
|
|
9136
|
+
date: group.date
|
|
9137
|
+
});
|
|
9138
|
+
const response = await fetch(url, {
|
|
9139
|
+
method: "GET",
|
|
9140
|
+
headers: {
|
|
9141
|
+
"Authorization": `Bearer ${session.access_token}`,
|
|
9142
|
+
"Content-Type": "application/json"
|
|
9143
|
+
}
|
|
9144
|
+
});
|
|
9145
|
+
if (!response.ok) {
|
|
9146
|
+
const errorText = await response.text();
|
|
9147
|
+
console.error(`[useDashboardMetrics] Backend API error for shift ${group.shiftId}:`, errorText);
|
|
9148
|
+
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
9149
|
+
}
|
|
9150
|
+
const responseText = await response.text();
|
|
9151
|
+
try {
|
|
9152
|
+
return JSON.parse(responseText);
|
|
9153
|
+
} catch (parseError) {
|
|
9154
|
+
console.error("[useDashboardMetrics] Failed to parse response:", responseText.substring(0, 500));
|
|
9155
|
+
throw new Error(`Invalid JSON response from backend`);
|
|
9156
|
+
}
|
|
9157
|
+
});
|
|
9158
|
+
const results = await Promise.all(metricsPromises);
|
|
9159
|
+
results.forEach((result) => {
|
|
9160
|
+
if (result.workspace_metrics) {
|
|
9161
|
+
allWorkspaceMetrics.push(...result.workspace_metrics);
|
|
9162
|
+
}
|
|
9163
|
+
if (result.line_metrics) {
|
|
9164
|
+
allLineMetrics.push(...result.line_metrics);
|
|
9165
|
+
}
|
|
9166
|
+
});
|
|
9167
|
+
console.log(`[useDashboardMetrics] \u{1F4CA} Merged metrics from ${results.length} shift groups:`, {
|
|
9168
|
+
workspaceCount: allWorkspaceMetrics.length,
|
|
9169
|
+
lineMetricsCount: allLineMetrics.length
|
|
9170
|
+
});
|
|
9171
|
+
} else {
|
|
9172
|
+
const currentShiftDetails = shiftConfig ? getCurrentShift(defaultTimezone, shiftConfig) : shiftGroups.length === 1 ? { date: shiftGroups[0].date, shiftId: shiftGroups[0].shiftId } : getCurrentShift(defaultTimezone, staticShiftConfig);
|
|
9173
|
+
const operationalDate = currentShiftDetails.date;
|
|
9174
|
+
const lineIdsParam = isFactory ? `line_ids=${targetLineIds.join(",")}` : `line_id=${targetLineIds[0]}`;
|
|
9175
|
+
const url = `${apiUrl}/api/dashboard/metrics?${lineIdsParam}&date=${operationalDate}&shift_id=${currentShiftDetails.shiftId}&company_id=${entityConfig.companyId}`;
|
|
9176
|
+
console.log("[useDashboardMetrics] Calling backend API:", {
|
|
9177
|
+
url,
|
|
9178
|
+
apiUrl,
|
|
9179
|
+
lineIdsParam,
|
|
9180
|
+
operationalDate,
|
|
9181
|
+
shiftId: currentShiftDetails.shiftId,
|
|
9182
|
+
companyId: entityConfig.companyId
|
|
9183
|
+
});
|
|
9184
|
+
const response = await fetch(url, {
|
|
9185
|
+
method: "GET",
|
|
9186
|
+
headers: {
|
|
9187
|
+
"Authorization": `Bearer ${session.access_token}`,
|
|
9188
|
+
"Content-Type": "application/json"
|
|
9189
|
+
}
|
|
9190
|
+
});
|
|
9191
|
+
console.log("[useDashboardMetrics] Response status:", response.status, response.statusText);
|
|
9192
|
+
if (!response.ok) {
|
|
9193
|
+
const errorText = await response.text();
|
|
9194
|
+
console.error("[useDashboardMetrics] Backend API error response:", errorText);
|
|
9195
|
+
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
9196
|
+
}
|
|
9197
|
+
const responseText = await response.text();
|
|
9198
|
+
let backendData;
|
|
9199
|
+
try {
|
|
9200
|
+
backendData = JSON.parse(responseText);
|
|
9201
|
+
} catch (parseError) {
|
|
9202
|
+
console.error("[useDashboardMetrics] Failed to parse response as JSON. Response text:", responseText.substring(0, 500));
|
|
9203
|
+
throw new Error(`Invalid JSON response from backend. Received: ${responseText.substring(0, 100)}...`);
|
|
9204
|
+
}
|
|
9205
|
+
console.log("[useDashboardMetrics] Backend response:", {
|
|
9206
|
+
workspaceCount: backendData.workspace_metrics?.length || 0,
|
|
9207
|
+
lineCount: backendData.line_metrics?.length || 0
|
|
9208
|
+
});
|
|
9209
|
+
allWorkspaceMetrics = backendData.workspace_metrics || [];
|
|
9210
|
+
allLineMetrics = backendData.line_metrics || [];
|
|
8980
9211
|
}
|
|
8981
|
-
|
|
8982
|
-
workspaceCount: backendData.workspace_metrics?.length || 0,
|
|
8983
|
-
lineCount: backendData.line_metrics?.length || 0
|
|
8984
|
-
});
|
|
8985
|
-
const transformedWorkspaceData = (backendData.workspace_metrics || []).map((item) => ({
|
|
9212
|
+
const transformedWorkspaceData = allWorkspaceMetrics.map((item) => ({
|
|
8986
9213
|
company_id: item.company_id || entityConfig.companyId,
|
|
8987
9214
|
line_id: item.line_id,
|
|
8988
9215
|
shift_id: item.shift_id,
|
|
@@ -9005,7 +9232,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
9005
9232
|
});
|
|
9006
9233
|
const newMetricsState = {
|
|
9007
9234
|
workspaceMetrics: transformedWorkspaceData,
|
|
9008
|
-
lineMetrics:
|
|
9235
|
+
lineMetrics: allLineMetrics || []
|
|
9009
9236
|
};
|
|
9010
9237
|
console.log("[useDashboardMetrics] Setting metrics state:", {
|
|
9011
9238
|
workspaceMetrics: newMetricsState.workspaceMetrics.length,
|
|
@@ -9026,9 +9253,12 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
9026
9253
|
metrics2?.lineMetrics?.length || 0,
|
|
9027
9254
|
companySpecificMetricsTable,
|
|
9028
9255
|
entityConfig,
|
|
9029
|
-
appTimezone,
|
|
9030
9256
|
defaultTimezone,
|
|
9031
9257
|
shiftConfig,
|
|
9258
|
+
shiftGroups,
|
|
9259
|
+
configuredLineIds,
|
|
9260
|
+
staticShiftConfig,
|
|
9261
|
+
userAccessibleLineIds,
|
|
9032
9262
|
shiftLoading
|
|
9033
9263
|
]);
|
|
9034
9264
|
const fetchAllMetricsRef = React24.useRef(fetchAllMetrics);
|
|
@@ -9052,32 +9282,68 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
9052
9282
|
if (!currentLineIdToUse || !supabase || companySpecificMetricsTable.includes("unknown_company") || !entityConfig.companyId) {
|
|
9053
9283
|
return;
|
|
9054
9284
|
}
|
|
9055
|
-
const
|
|
9056
|
-
const
|
|
9057
|
-
const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? userAccessibleLineIds || getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
|
|
9058
|
-
if (targetLineIds.length === 0) return;
|
|
9059
|
-
const wsMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
9060
|
-
const lineMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
9285
|
+
const factoryViewIdentifier = entityConfig.factoryViewId || "factory";
|
|
9286
|
+
const isFactory = currentLineIdToUse === factoryViewIdentifier;
|
|
9061
9287
|
const channels = [];
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
{
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9288
|
+
if (isFactory && shiftGroups.length > 0) {
|
|
9289
|
+
console.log(`[useDashboardMetrics] \u{1F4E1} Setting up subscriptions for ${shiftGroups.length} shift group(s)`);
|
|
9290
|
+
shiftGroups.forEach((group, index) => {
|
|
9291
|
+
const baseFilterParts = `date=eq.${group.date},shift_id=eq.${group.shiftId}`;
|
|
9292
|
+
const lineIdFilterPart = `line_id=in.(${group.lineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
9293
|
+
const filter2 = `${baseFilterParts},${lineIdFilterPart}`;
|
|
9294
|
+
const wsChannelName = `dashboard-ws-g${index}-${group.date}-${group.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9295
|
+
const wsChannel = supabase.channel(wsChannelName).on(
|
|
9296
|
+
"postgres_changes",
|
|
9297
|
+
{ event: "*", schema, table: companySpecificMetricsTable, filter: filter2 },
|
|
9298
|
+
(payload) => {
|
|
9299
|
+
const payloadData = payload.new || payload.old;
|
|
9300
|
+
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
9301
|
+
queueUpdate();
|
|
9302
|
+
}
|
|
9071
9303
|
}
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9304
|
+
).subscribe();
|
|
9305
|
+
channels.push(wsChannel);
|
|
9306
|
+
const lmChannelName = `dashboard-lm-g${index}-${group.date}-${group.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9307
|
+
const lmChannel = supabase.channel(lmChannelName).on(
|
|
9308
|
+
"postgres_changes",
|
|
9309
|
+
{ event: "*", schema, table: configuredLineMetricsTable, filter: filter2 },
|
|
9310
|
+
(payload) => {
|
|
9311
|
+
const payloadData = payload.new || payload.old;
|
|
9312
|
+
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
9313
|
+
queueUpdate();
|
|
9314
|
+
onLineMetricsUpdateRef.current?.();
|
|
9315
|
+
}
|
|
9316
|
+
}
|
|
9317
|
+
).subscribe();
|
|
9318
|
+
channels.push(lmChannel);
|
|
9319
|
+
});
|
|
9320
|
+
} else {
|
|
9321
|
+
const currentShiftDetails = shiftConfig ? getCurrentShift(defaultTimezone, shiftConfig) : getCurrentShift(defaultTimezone, staticShiftConfig);
|
|
9322
|
+
const operationalDateForSubscription = currentShiftDetails.date;
|
|
9323
|
+
const targetLineIds = [currentLineIdToUse];
|
|
9324
|
+
if (targetLineIds.length === 0) return;
|
|
9325
|
+
const wsMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
9326
|
+
const lineMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
9327
|
+
const createSubscription = (table, filter2, channelNameBase, callback) => {
|
|
9328
|
+
const channelName = `${channelNameBase}-${Date.now()}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9329
|
+
const channel = supabase.channel(channelName).on(
|
|
9330
|
+
"postgres_changes",
|
|
9331
|
+
{ event: "*", schema, table, filter: filter2 },
|
|
9332
|
+
(payload) => {
|
|
9333
|
+
const payloadData = payload.new;
|
|
9334
|
+
if (payloadData?.date === operationalDateForSubscription && payloadData?.shift_id === currentShiftDetails.shiftId) {
|
|
9335
|
+
callback();
|
|
9336
|
+
}
|
|
9337
|
+
}
|
|
9338
|
+
).subscribe();
|
|
9339
|
+
channels.push(channel);
|
|
9340
|
+
};
|
|
9341
|
+
createSubscription(companySpecificMetricsTable, wsMetricsFilter, "dashboard-ws-metrics", queueUpdate);
|
|
9342
|
+
createSubscription(configuredLineMetricsTable, lineMetricsFilter, "dashboard-line-metrics", () => {
|
|
9343
|
+
queueUpdate();
|
|
9344
|
+
onLineMetricsUpdateRef.current?.();
|
|
9345
|
+
});
|
|
9346
|
+
}
|
|
9081
9347
|
return () => {
|
|
9082
9348
|
channels.forEach((channel) => {
|
|
9083
9349
|
supabase?.removeChannel(channel);
|
|
@@ -9091,9 +9357,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
9091
9357
|
schema,
|
|
9092
9358
|
entityConfig?.companyId,
|
|
9093
9359
|
entityConfig?.factoryViewId,
|
|
9094
|
-
appTimezone,
|
|
9095
9360
|
defaultTimezone,
|
|
9096
9361
|
shiftConfig,
|
|
9362
|
+
staticShiftConfig,
|
|
9363
|
+
shiftGroups,
|
|
9097
9364
|
lineId,
|
|
9098
9365
|
userAccessibleLineIds
|
|
9099
9366
|
]);
|
|
@@ -9111,20 +9378,37 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9111
9378
|
const isFactoryView = lineId === (entityConfig.factoryViewId || "factory");
|
|
9112
9379
|
const databaseConfig = useDatabaseConfig();
|
|
9113
9380
|
const dateTimeConfig = useDateTimeConfig();
|
|
9114
|
-
useShiftConfig();
|
|
9115
|
-
const
|
|
9116
|
-
|
|
9117
|
-
|
|
9381
|
+
const staticShiftConfig = useShiftConfig();
|
|
9382
|
+
const appTimezone = useAppTimezone();
|
|
9383
|
+
const timezone = appTimezone || dateTimeConfig.defaultTimezone || "UTC";
|
|
9384
|
+
const configuredLineIds = React24.useMemo(() => {
|
|
9385
|
+
return getConfiguredLineIds(entityConfig);
|
|
9118
9386
|
}, [entityConfig]);
|
|
9119
|
-
const
|
|
9120
|
-
|
|
9121
|
-
|
|
9387
|
+
const {
|
|
9388
|
+
shiftConfigMap: multiLineShiftConfigMap,
|
|
9389
|
+
isLoading: isMultiLineShiftConfigLoading
|
|
9390
|
+
} = useMultiLineShiftConfigs(
|
|
9391
|
+
isFactoryView ? configuredLineIds : [],
|
|
9392
|
+
staticShiftConfig
|
|
9393
|
+
);
|
|
9394
|
+
const {
|
|
9395
|
+
shiftConfig: singleLineShiftConfig,
|
|
9396
|
+
isFromDatabase,
|
|
9397
|
+
isLoading: isSingleLineShiftConfigLoading
|
|
9398
|
+
} = useDynamicShiftConfig(isFactoryView ? void 0 : lineId);
|
|
9399
|
+
const isShiftConfigLoading = isFactoryView ? isMultiLineShiftConfigLoading : isSingleLineShiftConfigLoading;
|
|
9400
|
+
const shiftGroups = React24.useMemo(() => {
|
|
9401
|
+
if (!isFactoryView) return [];
|
|
9402
|
+
if (isMultiLineShiftConfigLoading || multiLineShiftConfigMap.size === 0) return [];
|
|
9403
|
+
return groupLinesByShift(multiLineShiftConfigMap, timezone);
|
|
9404
|
+
}, [isFactoryView, isMultiLineShiftConfigLoading, multiLineShiftConfigMap, timezone]);
|
|
9405
|
+
const shiftConfig = isFactoryView ? null : singleLineShiftConfig;
|
|
9122
9406
|
console.log(`[useLineKPIs] \u{1F3AF} Shift config for line ${lineId}:`, {
|
|
9123
9407
|
isFactoryView,
|
|
9124
|
-
lineIdForShiftConfig,
|
|
9125
|
-
firstLineId,
|
|
9126
9408
|
isFromDatabase,
|
|
9127
|
-
shiftConfig
|
|
9409
|
+
shiftConfig,
|
|
9410
|
+
shiftGroupsCount: shiftGroups.length,
|
|
9411
|
+
shiftGroups: shiftGroups.map((g) => ({ shiftId: g.shiftId, date: g.date, lineCount: g.lineIds.length }))
|
|
9128
9412
|
});
|
|
9129
9413
|
const supabase = useSupabase();
|
|
9130
9414
|
React24.useMemo(() => {
|
|
@@ -9138,8 +9422,6 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9138
9422
|
const updateQueueRef = React24.useRef(false);
|
|
9139
9423
|
const updateTimeoutRef = React24.useRef(null);
|
|
9140
9424
|
const queueUpdateRef = React24.useRef(void 0);
|
|
9141
|
-
const appTimezone = useAppTimezone();
|
|
9142
|
-
const timezone = appTimezone || dateTimeConfig.defaultTimezone || "UTC";
|
|
9143
9425
|
const schema = databaseConfig.schema ?? "public";
|
|
9144
9426
|
const lineMetricsTable = databaseConfig.tables?.lineMetrics ?? "line_metrics";
|
|
9145
9427
|
const companySpecificMetricsTable = React24.useMemo(
|
|
@@ -9158,8 +9440,6 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9158
9440
|
setIsLoading(true);
|
|
9159
9441
|
setError(null);
|
|
9160
9442
|
try {
|
|
9161
|
-
const currentShiftDetails = getCurrentShift(timezone, shiftConfig ?? void 0);
|
|
9162
|
-
const operationalDate = currentShiftDetails.date;
|
|
9163
9443
|
const { data: { session } } = await supabase.auth.getSession();
|
|
9164
9444
|
if (!session?.access_token) {
|
|
9165
9445
|
throw new Error("No authentication token available");
|
|
@@ -9170,33 +9450,68 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9170
9450
|
}
|
|
9171
9451
|
const factoryViewIdentifier = entityConfig.factoryViewId || "factory";
|
|
9172
9452
|
const isFactory = currentLineId === factoryViewIdentifier;
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9453
|
+
if (isFactory && shiftGroups.length > 0) {
|
|
9454
|
+
console.log(`[useLineKPIs] \u{1F3ED} Factory view: Fetching KPIs for ${shiftGroups.length} shift group(s)`);
|
|
9455
|
+
const kpiPromises = shiftGroups.map(async (group) => {
|
|
9456
|
+
const lineIdsParam = `line_ids=${group.lineIds.join(",")}`;
|
|
9457
|
+
const url = `${apiUrl}/api/dashboard/line-kpis?${lineIdsParam}&date=${group.date}&shift_id=${group.shiftId}&company_id=${entityConfig.companyId}`;
|
|
9458
|
+
console.log(`[useLineKPIs] \u{1F4CA} Fetching for shift ${group.shiftId} (${group.shiftName}):`, {
|
|
9459
|
+
lineIds: group.lineIds,
|
|
9460
|
+
date: group.date
|
|
9461
|
+
});
|
|
9462
|
+
const response = await fetch(url, {
|
|
9463
|
+
headers: {
|
|
9464
|
+
"Authorization": `Bearer ${session.access_token}`,
|
|
9465
|
+
"Content-Type": "application/json"
|
|
9466
|
+
}
|
|
9467
|
+
});
|
|
9468
|
+
if (!response.ok) {
|
|
9469
|
+
const errorText = await response.text();
|
|
9470
|
+
console.error(`[useLineKPIs] Backend API error for shift ${group.shiftId}:`, errorText);
|
|
9471
|
+
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
9180
9472
|
}
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
} catch (parseError) {
|
|
9193
|
-
console.error("[useLineKPIs] Failed to parse response as JSON. Response text:", responseText.substring(0, 500));
|
|
9194
|
-
throw new Error(`Invalid JSON response from backend. Received: ${responseText.substring(0, 100)}...`);
|
|
9195
|
-
}
|
|
9196
|
-
if (backendData.kpis) {
|
|
9197
|
-
setKPIs(backendData.kpis);
|
|
9473
|
+
const responseText = await response.text();
|
|
9474
|
+
try {
|
|
9475
|
+
return JSON.parse(responseText);
|
|
9476
|
+
} catch (parseError) {
|
|
9477
|
+
console.error("[useLineKPIs] Failed to parse response as JSON:", responseText.substring(0, 500));
|
|
9478
|
+
throw new Error(`Invalid JSON response from backend`);
|
|
9479
|
+
}
|
|
9480
|
+
});
|
|
9481
|
+
const results = await Promise.all(kpiPromises);
|
|
9482
|
+
const aggregatedKPIs = aggregateKPIResults(results);
|
|
9483
|
+
setKPIs(aggregatedKPIs);
|
|
9198
9484
|
} else {
|
|
9199
|
-
|
|
9485
|
+
const currentShiftDetails = shiftConfig ? getCurrentShift(timezone, shiftConfig) : shiftGroups.length === 1 ? { date: shiftGroups[0].date, shiftId: shiftGroups[0].shiftId } : getCurrentShift(timezone, staticShiftConfig);
|
|
9486
|
+
const operationalDate = currentShiftDetails.date;
|
|
9487
|
+
const lineParam = isFactory ? `line_ids=${configuredLineIds.join(",")}` : `line_id=${currentLineId}`;
|
|
9488
|
+
const response = await fetch(
|
|
9489
|
+
`${apiUrl}/api/dashboard/line-kpis?${lineParam}&date=${operationalDate}&shift_id=${currentShiftDetails.shiftId}&company_id=${entityConfig.companyId}`,
|
|
9490
|
+
{
|
|
9491
|
+
headers: {
|
|
9492
|
+
"Authorization": `Bearer ${session.access_token}`,
|
|
9493
|
+
"Content-Type": "application/json"
|
|
9494
|
+
}
|
|
9495
|
+
}
|
|
9496
|
+
);
|
|
9497
|
+
if (!response.ok) {
|
|
9498
|
+
const errorText = await response.text();
|
|
9499
|
+
console.error("[useLineKPIs] Backend API error response:", errorText);
|
|
9500
|
+
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
9501
|
+
}
|
|
9502
|
+
const responseText = await response.text();
|
|
9503
|
+
let backendData;
|
|
9504
|
+
try {
|
|
9505
|
+
backendData = JSON.parse(responseText);
|
|
9506
|
+
} catch (parseError) {
|
|
9507
|
+
console.error("[useLineKPIs] Failed to parse response as JSON. Response text:", responseText.substring(0, 500));
|
|
9508
|
+
throw new Error(`Invalid JSON response from backend. Received: ${responseText.substring(0, 100)}...`);
|
|
9509
|
+
}
|
|
9510
|
+
if (backendData.kpis) {
|
|
9511
|
+
setKPIs(backendData.kpis);
|
|
9512
|
+
} else {
|
|
9513
|
+
setKPIs(null);
|
|
9514
|
+
}
|
|
9200
9515
|
}
|
|
9201
9516
|
} catch (err) {
|
|
9202
9517
|
console.error("[useLineKPIs] Error fetching KPIs:", err);
|
|
@@ -9207,7 +9522,80 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9207
9522
|
isFetchingRef.current = false;
|
|
9208
9523
|
updateQueueRef.current = false;
|
|
9209
9524
|
}
|
|
9210
|
-
}, [timezone, shiftConfig, entityConfig, supabase, enabled, isShiftConfigLoading]);
|
|
9525
|
+
}, [timezone, shiftConfig, shiftGroups, configuredLineIds, staticShiftConfig, entityConfig, supabase, enabled, isShiftConfigLoading]);
|
|
9526
|
+
const aggregateKPIResults = (results) => {
|
|
9527
|
+
const validResults = results.filter((r2) => r2?.kpis);
|
|
9528
|
+
if (validResults.length === 0) return null;
|
|
9529
|
+
if (validResults.length === 1) return validResults[0].kpis;
|
|
9530
|
+
let totalEfficiency = 0;
|
|
9531
|
+
let totalEfficiencyWeight = 0;
|
|
9532
|
+
let totalOutputCurrent = 0;
|
|
9533
|
+
let totalOutputTarget = 0;
|
|
9534
|
+
let totalIdealOutput = 0;
|
|
9535
|
+
let totalUnderperformingCurrent = 0;
|
|
9536
|
+
let totalUnderperformingTotal = 0;
|
|
9537
|
+
let totalCycleTimeSum = 0;
|
|
9538
|
+
let totalCycleTimeCount = 0;
|
|
9539
|
+
let totalQualitySum = 0;
|
|
9540
|
+
let totalQualityCount = 0;
|
|
9541
|
+
validResults.forEach((result) => {
|
|
9542
|
+
const kpis2 = result.kpis;
|
|
9543
|
+
if (kpis2.efficiency?.value !== void 0) {
|
|
9544
|
+
const weight = kpis2.outputProgress?.current || 1;
|
|
9545
|
+
totalEfficiency += kpis2.efficiency.value * weight;
|
|
9546
|
+
totalEfficiencyWeight += weight;
|
|
9547
|
+
}
|
|
9548
|
+
if (kpis2.outputProgress) {
|
|
9549
|
+
totalOutputCurrent += kpis2.outputProgress.current || 0;
|
|
9550
|
+
totalOutputTarget += kpis2.outputProgress.target || 0;
|
|
9551
|
+
totalIdealOutput += kpis2.outputProgress.idealOutput || 0;
|
|
9552
|
+
}
|
|
9553
|
+
if (kpis2.underperformingWorkers) {
|
|
9554
|
+
totalUnderperformingCurrent += kpis2.underperformingWorkers.current || 0;
|
|
9555
|
+
totalUnderperformingTotal += kpis2.underperformingWorkers.total || 0;
|
|
9556
|
+
}
|
|
9557
|
+
if (kpis2.avgCycleTime?.value !== void 0) {
|
|
9558
|
+
totalCycleTimeSum += kpis2.avgCycleTime.value;
|
|
9559
|
+
totalCycleTimeCount++;
|
|
9560
|
+
}
|
|
9561
|
+
if (kpis2.qualityCompliance?.value !== void 0) {
|
|
9562
|
+
totalQualitySum += kpis2.qualityCompliance.value;
|
|
9563
|
+
totalQualityCount++;
|
|
9564
|
+
}
|
|
9565
|
+
});
|
|
9566
|
+
const aggregated = {
|
|
9567
|
+
efficiency: {
|
|
9568
|
+
value: totalEfficiencyWeight > 0 ? totalEfficiency / totalEfficiencyWeight : 0,
|
|
9569
|
+
change: 0
|
|
9570
|
+
// Change not meaningful when aggregating across shifts
|
|
9571
|
+
},
|
|
9572
|
+
outputProgress: {
|
|
9573
|
+
current: totalOutputCurrent,
|
|
9574
|
+
target: totalOutputTarget,
|
|
9575
|
+
change: 0,
|
|
9576
|
+
// Change not meaningful when aggregating across shifts
|
|
9577
|
+
idealOutput: totalIdealOutput
|
|
9578
|
+
},
|
|
9579
|
+
underperformingWorkers: {
|
|
9580
|
+
current: totalUnderperformingCurrent,
|
|
9581
|
+
total: totalUnderperformingTotal,
|
|
9582
|
+
change: 0
|
|
9583
|
+
// Change not meaningful when aggregating across shifts
|
|
9584
|
+
},
|
|
9585
|
+
avgCycleTime: {
|
|
9586
|
+
value: totalCycleTimeCount > 0 ? totalCycleTimeSum / totalCycleTimeCount : 0,
|
|
9587
|
+
change: 0
|
|
9588
|
+
// Change not meaningful when aggregating across shifts
|
|
9589
|
+
},
|
|
9590
|
+
qualityCompliance: {
|
|
9591
|
+
value: totalQualityCount > 0 ? totalQualitySum / totalQualityCount : 0,
|
|
9592
|
+
change: 0
|
|
9593
|
+
// Change not meaningful when aggregating across shifts
|
|
9594
|
+
}
|
|
9595
|
+
};
|
|
9596
|
+
console.log("[useLineKPIs] \u{1F4CA} Aggregated KPIs from", validResults.length, "shift groups:", aggregated);
|
|
9597
|
+
return aggregated;
|
|
9598
|
+
};
|
|
9211
9599
|
const queueUpdate = React24.useCallback(() => {
|
|
9212
9600
|
if (updateTimeoutRef.current) {
|
|
9213
9601
|
clearTimeout(updateTimeoutRef.current);
|
|
@@ -9227,40 +9615,66 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9227
9615
|
return;
|
|
9228
9616
|
}
|
|
9229
9617
|
fetchKPIs();
|
|
9230
|
-
const currentShiftDetails = getCurrentShift(timezone, shiftConfig ?? void 0);
|
|
9231
|
-
const operationalDate = currentShiftDetails.date;
|
|
9232
9618
|
const factoryViewIdentifier = entityConfig.factoryViewId || "factory";
|
|
9233
|
-
const
|
|
9234
|
-
if (targetLineIds.length === 0) {
|
|
9235
|
-
console.warn("[useLineKPIs] No target line IDs for subscription. LineId:", currentLineId);
|
|
9236
|
-
return;
|
|
9237
|
-
}
|
|
9238
|
-
const baseFilterParts = `date=eq.${operationalDate},shift_id=eq.${currentShiftDetails.shiftId}`;
|
|
9239
|
-
const lineIdFilterPart = `line_id=in.(${targetLineIds.join(",")})`;
|
|
9240
|
-
const lineMetricsFilter = `${baseFilterParts},${lineIdFilterPart}`;
|
|
9241
|
-
const companyTableFilter = `${baseFilterParts},${lineIdFilterPart}`;
|
|
9619
|
+
const isFactory = currentLineId === factoryViewIdentifier;
|
|
9242
9620
|
const activeChannels = [];
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
const
|
|
9249
|
-
|
|
9250
|
-
|
|
9621
|
+
if (isFactory && shiftGroups.length > 0) {
|
|
9622
|
+
console.log(`[useLineKPIs] \u{1F4E1} Setting up subscriptions for ${shiftGroups.length} shift group(s)`);
|
|
9623
|
+
shiftGroups.forEach((group, index) => {
|
|
9624
|
+
const baseFilterParts = `date=eq.${group.date},shift_id=eq.${group.shiftId}`;
|
|
9625
|
+
const lineIdFilterPart = `line_id=in.(${group.lineIds.join(",")})`;
|
|
9626
|
+
const filter2 = `${baseFilterParts},${lineIdFilterPart}`;
|
|
9627
|
+
const lmChannelName = `kpi-lm-factory-g${index}-${group.date}-${group.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9628
|
+
const lmChannel = supabase.channel(lmChannelName).on(
|
|
9629
|
+
"postgres_changes",
|
|
9630
|
+
{ event: "*", schema, table: lineMetricsTable, filter: filter2 },
|
|
9631
|
+
(payload) => {
|
|
9632
|
+
const payloadData = payload.new || payload.old;
|
|
9633
|
+
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
9634
|
+
queueUpdateRef.current?.();
|
|
9635
|
+
}
|
|
9636
|
+
}
|
|
9637
|
+
).subscribe((status, err) => {
|
|
9638
|
+
if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR || status === supabaseJs.REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
|
|
9639
|
+
console.error(`[useLineKPIs] Subscription to ${lineMetricsTable} (group ${index}) FAILED:`, status, err);
|
|
9640
|
+
}
|
|
9641
|
+
});
|
|
9642
|
+
activeChannels.push(lmChannel);
|
|
9643
|
+
if (companySpecificMetricsTable && !companySpecificMetricsTable.includes("unknown_company")) {
|
|
9644
|
+
const csChannelName = `kpi-cs-factory-g${index}-${group.date}-${group.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9645
|
+
const csChannel = supabase.channel(csChannelName).on(
|
|
9646
|
+
"postgres_changes",
|
|
9647
|
+
{ event: "*", schema, table: companySpecificMetricsTable, filter: filter2 },
|
|
9648
|
+
(payload) => {
|
|
9649
|
+
const payloadData = payload.new || payload.old;
|
|
9650
|
+
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
9651
|
+
queueUpdateRef.current?.();
|
|
9652
|
+
}
|
|
9653
|
+
}
|
|
9654
|
+
).subscribe((status, err) => {
|
|
9655
|
+
if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR || status === supabaseJs.REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
|
|
9656
|
+
console.error(`[useLineKPIs] Subscription to ${companySpecificMetricsTable} (group ${index}) FAILED:`, status, err);
|
|
9657
|
+
}
|
|
9658
|
+
});
|
|
9659
|
+
activeChannels.push(csChannel);
|
|
9251
9660
|
}
|
|
9661
|
+
});
|
|
9662
|
+
} else {
|
|
9663
|
+
const currentShiftDetails = shiftConfig ? getCurrentShift(timezone, shiftConfig) : getCurrentShift(timezone, staticShiftConfig);
|
|
9664
|
+
const operationalDate = currentShiftDetails.date;
|
|
9665
|
+
const targetLineIds = [currentLineId];
|
|
9666
|
+
if (targetLineIds.length === 0) {
|
|
9667
|
+
console.warn("[useLineKPIs] No target line IDs for subscription. LineId:", currentLineId);
|
|
9668
|
+
return;
|
|
9252
9669
|
}
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
}
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
if (companySpecificMetricsTable && !companySpecificMetricsTable.includes("unknown_company")) {
|
|
9260
|
-
const csChannelName = `kpi-cs-${currentLineId}-${operationalDate}-${currentShiftDetails.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9261
|
-
const csChannel = supabase.channel(csChannelName).on(
|
|
9670
|
+
const baseFilterParts = `date=eq.${operationalDate},shift_id=eq.${currentShiftDetails.shiftId}`;
|
|
9671
|
+
const lineIdFilterPart = `line_id=in.(${targetLineIds.join(",")})`;
|
|
9672
|
+
const lineMetricsFilter = `${baseFilterParts},${lineIdFilterPart}`;
|
|
9673
|
+
const companyTableFilter = `${baseFilterParts},${lineIdFilterPart}`;
|
|
9674
|
+
const lmChannelName = `kpi-lm-${currentLineId}-${operationalDate}-${currentShiftDetails.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9675
|
+
const lmChannel = supabase.channel(lmChannelName).on(
|
|
9262
9676
|
"postgres_changes",
|
|
9263
|
-
{ event: "*", schema, table:
|
|
9677
|
+
{ event: "*", schema, table: lineMetricsTable, filter: lineMetricsFilter },
|
|
9264
9678
|
(payload) => {
|
|
9265
9679
|
const payloadData = payload.new || payload.old;
|
|
9266
9680
|
if (payloadData?.date === operationalDate && payloadData?.shift_id === currentShiftDetails.shiftId) {
|
|
@@ -9269,10 +9683,28 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9269
9683
|
}
|
|
9270
9684
|
).subscribe((status, err) => {
|
|
9271
9685
|
if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR || status === supabaseJs.REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
|
|
9272
|
-
console.error(`[useLineKPIs] Subscription to ${
|
|
9686
|
+
console.error(`[useLineKPIs] Subscription to ${lineMetricsTable} FAILED: ${status}`, err || "");
|
|
9273
9687
|
}
|
|
9274
9688
|
});
|
|
9275
|
-
activeChannels.push(
|
|
9689
|
+
activeChannels.push(lmChannel);
|
|
9690
|
+
if (companySpecificMetricsTable && !companySpecificMetricsTable.includes("unknown_company")) {
|
|
9691
|
+
const csChannelName = `kpi-cs-${currentLineId}-${operationalDate}-${currentShiftDetails.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
9692
|
+
const csChannel = supabase.channel(csChannelName).on(
|
|
9693
|
+
"postgres_changes",
|
|
9694
|
+
{ event: "*", schema, table: companySpecificMetricsTable, filter: companyTableFilter },
|
|
9695
|
+
(payload) => {
|
|
9696
|
+
const payloadData = payload.new || payload.old;
|
|
9697
|
+
if (payloadData?.date === operationalDate && payloadData?.shift_id === currentShiftDetails.shiftId) {
|
|
9698
|
+
queueUpdateRef.current?.();
|
|
9699
|
+
}
|
|
9700
|
+
}
|
|
9701
|
+
).subscribe((status, err) => {
|
|
9702
|
+
if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR || status === supabaseJs.REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
|
|
9703
|
+
console.error(`[useLineKPIs] Subscription to ${companySpecificMetricsTable} FAILED: ${status}`, err || "");
|
|
9704
|
+
}
|
|
9705
|
+
});
|
|
9706
|
+
activeChannels.push(csChannel);
|
|
9707
|
+
}
|
|
9276
9708
|
}
|
|
9277
9709
|
return () => {
|
|
9278
9710
|
activeChannels.forEach((ch) => supabase.removeChannel(ch).catch((err) => console.error("[useLineKPIs] Error removing KPI channel:", err)));
|
|
@@ -9280,7 +9712,7 @@ var useLineKPIs = ({ lineId, enabled }) => {
|
|
|
9280
9712
|
clearTimeout(updateTimeoutRef.current);
|
|
9281
9713
|
}
|
|
9282
9714
|
};
|
|
9283
|
-
}, [lineId, supabase, entityConfig, schema, lineMetricsTable, companySpecificMetricsTable, timezone, shiftConfig, isShiftConfigLoading]);
|
|
9715
|
+
}, [lineId, supabase, entityConfig, schema, lineMetricsTable, companySpecificMetricsTable, timezone, shiftConfig, staticShiftConfig, shiftGroups, isShiftConfigLoading]);
|
|
9284
9716
|
return {
|
|
9285
9717
|
kpis,
|
|
9286
9718
|
isLoading,
|
|
@@ -10953,10 +11385,26 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
10953
11385
|
const dateTimeConfig = useDateTimeConfig();
|
|
10954
11386
|
const staticShiftConfig = useShiftConfig();
|
|
10955
11387
|
const timezone = useAppTimezone();
|
|
10956
|
-
const configuredLineIds = React24.useMemo(() =>
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
11388
|
+
const configuredLineIds = React24.useMemo(() => {
|
|
11389
|
+
const allLineIds = getConfiguredLineIds(entityConfig);
|
|
11390
|
+
if (options?.allowedLineIds) {
|
|
11391
|
+
return allLineIds.filter((id3) => options.allowedLineIds.includes(id3));
|
|
11392
|
+
}
|
|
11393
|
+
return allLineIds;
|
|
11394
|
+
}, [entityConfig, options?.allowedLineIds]);
|
|
11395
|
+
const {
|
|
11396
|
+
shiftConfigMap: multiLineShiftConfigMap,
|
|
11397
|
+
isLoading: isShiftConfigLoading
|
|
11398
|
+
} = useMultiLineShiftConfigs(configuredLineIds, staticShiftConfig);
|
|
11399
|
+
const shiftGroups = React24.useMemo(() => {
|
|
11400
|
+
if (isShiftConfigLoading || multiLineShiftConfigMap.size === 0) return [];
|
|
11401
|
+
return groupLinesByShift(multiLineShiftConfigMap, timezone || dateTimeConfig.defaultTimezone || "Asia/Kolkata");
|
|
11402
|
+
}, [isShiftConfigLoading, multiLineShiftConfigMap, timezone, dateTimeConfig.defaultTimezone]);
|
|
11403
|
+
console.log(`[useAllWorkspaceMetrics] \u{1F4CA} Shift groups:`, shiftGroups.map((g) => ({
|
|
11404
|
+
shiftId: g.shiftId,
|
|
11405
|
+
date: g.date,
|
|
11406
|
+
lineIds: g.lineIds
|
|
11407
|
+
})));
|
|
10960
11408
|
const supabase = useSupabase();
|
|
10961
11409
|
const [workspaces, setWorkspaces] = React24.useState([]);
|
|
10962
11410
|
const [loading, setLoading] = React24.useState(true);
|
|
@@ -10964,19 +11412,29 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
10964
11412
|
const [initialized, setInitialized] = React24.useState(false);
|
|
10965
11413
|
const fetchTimeoutRef = React24.useRef(null);
|
|
10966
11414
|
const isFetchingRef = React24.useRef(false);
|
|
10967
|
-
const
|
|
11415
|
+
const hasSpecificDateShift = options?.initialDate !== void 0 || options?.initialShiftId !== void 0;
|
|
11416
|
+
const fallbackQueryShiftId = React24.useMemo(() => {
|
|
10968
11417
|
if (options?.initialShiftId !== void 0) {
|
|
10969
11418
|
return options.initialShiftId;
|
|
10970
11419
|
}
|
|
11420
|
+
if (shiftGroups.length > 0) {
|
|
11421
|
+
return shiftGroups[0].shiftId;
|
|
11422
|
+
}
|
|
10971
11423
|
const currentShift = getCurrentShift(
|
|
10972
11424
|
timezone || dateTimeConfig.defaultTimezone || "Asia/Kolkata",
|
|
10973
|
-
|
|
11425
|
+
staticShiftConfig
|
|
10974
11426
|
);
|
|
10975
11427
|
return currentShift.shiftId;
|
|
10976
|
-
}, [options?.initialShiftId, timezone, dateTimeConfig.defaultTimezone,
|
|
10977
|
-
const
|
|
10978
|
-
|
|
10979
|
-
|
|
11428
|
+
}, [options?.initialShiftId, shiftGroups, timezone, dateTimeConfig.defaultTimezone, staticShiftConfig]);
|
|
11429
|
+
const fallbackQueryDate = React24.useMemo(() => {
|
|
11430
|
+
if (options?.initialDate) {
|
|
11431
|
+
return options.initialDate;
|
|
11432
|
+
}
|
|
11433
|
+
if (shiftGroups.length > 0) {
|
|
11434
|
+
return shiftGroups[0].date;
|
|
11435
|
+
}
|
|
11436
|
+
return getOperationalDate(timezone || dateTimeConfig.defaultTimezone || "UTC");
|
|
11437
|
+
}, [options?.initialDate, shiftGroups, timezone, dateTimeConfig.defaultTimezone]);
|
|
10980
11438
|
const metricsTable = React24.useMemo(() => {
|
|
10981
11439
|
const companyId = entityConfig.companyId;
|
|
10982
11440
|
if (!companyId) return "";
|
|
@@ -10994,49 +11452,99 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
10994
11452
|
}
|
|
10995
11453
|
setError(null);
|
|
10996
11454
|
try {
|
|
10997
|
-
const
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
const
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
}
|
|
11005
|
-
if (
|
|
11455
|
+
const lineWorkspaceMap = /* @__PURE__ */ new Map();
|
|
11456
|
+
let allEnabledWorkspaceIds = [];
|
|
11457
|
+
for (const lineId of configuredLineIds) {
|
|
11458
|
+
const lineWorkspaces = await workspaceService.getWorkspaces(lineId);
|
|
11459
|
+
const enabledIds = lineWorkspaces.filter((ws) => ws.enable === true).map((ws) => ws.id);
|
|
11460
|
+
lineWorkspaceMap.set(lineId, enabledIds);
|
|
11461
|
+
allEnabledWorkspaceIds.push(...enabledIds);
|
|
11462
|
+
}
|
|
11463
|
+
if (allEnabledWorkspaceIds.length === 0) {
|
|
11006
11464
|
setWorkspaces([]);
|
|
11007
11465
|
setInitialized(true);
|
|
11008
11466
|
setLoading(false);
|
|
11009
11467
|
return;
|
|
11010
11468
|
}
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11469
|
+
let transformedData = [];
|
|
11470
|
+
if (hasSpecificDateShift) {
|
|
11471
|
+
console.log(`[useAllWorkspaceMetrics] \u{1F4CA} Using specific date/shift: ${fallbackQueryDate} / ${fallbackQueryShiftId}`);
|
|
11472
|
+
const { data, error: fetchError } = await supabase.from(metricsTable).select(`
|
|
11473
|
+
workspace_name,
|
|
11474
|
+
total_output,
|
|
11475
|
+
avg_pph,
|
|
11476
|
+
efficiency,
|
|
11477
|
+
workspace_id,
|
|
11478
|
+
avg_cycle_time,
|
|
11479
|
+
performance_score,
|
|
11480
|
+
trend_score,
|
|
11481
|
+
line_id,
|
|
11482
|
+
total_day_output
|
|
11483
|
+
`).eq("date", fallbackQueryDate).eq("shift_id", fallbackQueryShiftId).in("workspace_id", allEnabledWorkspaceIds).order("efficiency", { ascending: false });
|
|
11484
|
+
if (fetchError) throw fetchError;
|
|
11485
|
+
transformedData = (data || []).map((item) => ({
|
|
11486
|
+
company_id: entityConfig.companyId || "unknown",
|
|
11487
|
+
line_id: item.line_id,
|
|
11488
|
+
shift_id: fallbackQueryShiftId,
|
|
11489
|
+
date: fallbackQueryDate,
|
|
11490
|
+
workspace_uuid: item.workspace_id,
|
|
11491
|
+
workspace_name: item.workspace_name,
|
|
11492
|
+
action_count: item.total_output || 0,
|
|
11493
|
+
pph: item.avg_pph || 0,
|
|
11494
|
+
performance_score: item.performance_score || 0,
|
|
11495
|
+
avg_cycle_time: item.avg_cycle_time || 0,
|
|
11496
|
+
trend: item.trend_score === 1 ? 2 : 0,
|
|
11497
|
+
predicted_output: 0,
|
|
11498
|
+
efficiency: item.efficiency || 0,
|
|
11499
|
+
action_threshold: item.total_day_output || 0
|
|
11500
|
+
}));
|
|
11501
|
+
} else if (shiftGroups.length > 0) {
|
|
11502
|
+
console.log(`[useAllWorkspaceMetrics] \u{1F3ED} Fetching per-shift: ${shiftGroups.length} group(s)`);
|
|
11503
|
+
const queryPromises = shiftGroups.map(async (group) => {
|
|
11504
|
+
const groupWorkspaceIds = group.lineIds.flatMap(
|
|
11505
|
+
(lineId) => lineWorkspaceMap.get(lineId) || []
|
|
11506
|
+
);
|
|
11507
|
+
if (groupWorkspaceIds.length === 0) {
|
|
11508
|
+
return [];
|
|
11509
|
+
}
|
|
11510
|
+
console.log(`[useAllWorkspaceMetrics] \u{1F4CA} Fetching shift ${group.shiftId} (${group.shiftName}):`, {
|
|
11511
|
+
lineIds: group.lineIds,
|
|
11512
|
+
date: group.date,
|
|
11513
|
+
workspaceCount: groupWorkspaceIds.length
|
|
11514
|
+
});
|
|
11515
|
+
const { data, error: fetchError } = await supabase.from(metricsTable).select(`
|
|
11516
|
+
workspace_name,
|
|
11517
|
+
total_output,
|
|
11518
|
+
avg_pph,
|
|
11519
|
+
efficiency,
|
|
11520
|
+
workspace_id,
|
|
11521
|
+
avg_cycle_time,
|
|
11522
|
+
performance_score,
|
|
11523
|
+
trend_score,
|
|
11524
|
+
line_id,
|
|
11525
|
+
total_day_output
|
|
11526
|
+
`).eq("date", group.date).eq("shift_id", group.shiftId).in("workspace_id", groupWorkspaceIds);
|
|
11527
|
+
if (fetchError) throw fetchError;
|
|
11528
|
+
return (data || []).map((item) => ({
|
|
11529
|
+
company_id: entityConfig.companyId || "unknown",
|
|
11530
|
+
line_id: item.line_id,
|
|
11531
|
+
shift_id: group.shiftId,
|
|
11532
|
+
date: group.date,
|
|
11533
|
+
workspace_uuid: item.workspace_id,
|
|
11534
|
+
workspace_name: item.workspace_name,
|
|
11535
|
+
action_count: item.total_output || 0,
|
|
11536
|
+
pph: item.avg_pph || 0,
|
|
11537
|
+
performance_score: item.performance_score || 0,
|
|
11538
|
+
avg_cycle_time: item.avg_cycle_time || 0,
|
|
11539
|
+
trend: item.trend_score === 1 ? 2 : 0,
|
|
11540
|
+
predicted_output: 0,
|
|
11541
|
+
efficiency: item.efficiency || 0,
|
|
11542
|
+
action_threshold: item.total_day_output || 0
|
|
11543
|
+
}));
|
|
11544
|
+
});
|
|
11545
|
+
const results = await Promise.all(queryPromises);
|
|
11546
|
+
transformedData = results.flat().sort((a, b) => (b.efficiency || 0) - (a.efficiency || 0));
|
|
11547
|
+
}
|
|
11040
11548
|
setWorkspaces((prevWorkspaces) => {
|
|
11041
11549
|
if (prevWorkspaces.length !== transformedData.length) {
|
|
11042
11550
|
return transformedData;
|
|
@@ -11058,11 +11566,19 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
11058
11566
|
setLoading(false);
|
|
11059
11567
|
isFetchingRef.current = false;
|
|
11060
11568
|
}
|
|
11061
|
-
}, [
|
|
11569
|
+
}, [fallbackQueryDate, fallbackQueryShiftId, hasSpecificDateShift, shiftGroups, metricsTable, supabase, entityConfig.companyId, configuredLineIds, options?.enabled, isShiftConfigLoading]);
|
|
11062
11570
|
React24.useEffect(() => {
|
|
11063
11571
|
if (!initialized) {
|
|
11064
11572
|
fetchWorkspaceMetrics();
|
|
11065
11573
|
}
|
|
11574
|
+
const validDateShiftCombos = /* @__PURE__ */ new Set();
|
|
11575
|
+
if (hasSpecificDateShift) {
|
|
11576
|
+
validDateShiftCombos.add(`${fallbackQueryDate}-${fallbackQueryShiftId}`);
|
|
11577
|
+
} else {
|
|
11578
|
+
shiftGroups.forEach((group) => {
|
|
11579
|
+
validDateShiftCombos.add(`${group.date}-${group.shiftId}`);
|
|
11580
|
+
});
|
|
11581
|
+
}
|
|
11066
11582
|
const setupSubscription = () => {
|
|
11067
11583
|
const channel2 = supabase.channel(`all-workspace-metrics-${Date.now()}`).on(
|
|
11068
11584
|
"postgres_changes",
|
|
@@ -11073,7 +11589,8 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
11073
11589
|
},
|
|
11074
11590
|
async (payload) => {
|
|
11075
11591
|
const data = payload.new || payload.old;
|
|
11076
|
-
|
|
11592
|
+
const dataKey = `${data?.date}-${data?.shift_id}`;
|
|
11593
|
+
if (!validDateShiftCombos.has(dataKey)) {
|
|
11077
11594
|
return;
|
|
11078
11595
|
}
|
|
11079
11596
|
if (fetchTimeoutRef.current) {
|
|
@@ -11099,10 +11616,10 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
11099
11616
|
supabase.removeChannel(channel);
|
|
11100
11617
|
}
|
|
11101
11618
|
};
|
|
11102
|
-
}, [
|
|
11619
|
+
}, [fallbackQueryDate, fallbackQueryShiftId, hasSpecificDateShift, shiftGroups, metricsTable, fetchWorkspaceMetrics, initialized, supabase, schema, entityConfig.companyId]);
|
|
11103
11620
|
React24.useEffect(() => {
|
|
11104
11621
|
setInitialized(false);
|
|
11105
|
-
}, [
|
|
11622
|
+
}, [fallbackQueryDate, fallbackQueryShiftId, shiftGroups]);
|
|
11106
11623
|
const refreshWorkspaces = React24.useCallback(() => fetchWorkspaceMetrics(), [fetchWorkspaceMetrics]);
|
|
11107
11624
|
return React24.useMemo(
|
|
11108
11625
|
() => ({ workspaces, loading, error, refreshWorkspaces }),
|
|
@@ -11591,127 +12108,6 @@ function useClipTypesWithCounts(workspaceId, date, shiftId, totalOutput, options
|
|
|
11591
12108
|
counts
|
|
11592
12109
|
};
|
|
11593
12110
|
}
|
|
11594
|
-
var useMultiLineShiftConfigs = (lineIds, fallbackConfig) => {
|
|
11595
|
-
const [shiftConfigMap, setShiftConfigMap] = React24.useState(/* @__PURE__ */ new Map());
|
|
11596
|
-
const [isLoading, setIsLoading] = React24.useState(true);
|
|
11597
|
-
const [error, setError] = React24.useState(null);
|
|
11598
|
-
const supabase = useSupabase();
|
|
11599
|
-
const lineIdsKey = React24.useMemo(() => lineIds.sort().join(","), [lineIds]);
|
|
11600
|
-
React24.useEffect(() => {
|
|
11601
|
-
if (!lineIds || lineIds.length === 0) {
|
|
11602
|
-
setShiftConfigMap(/* @__PURE__ */ new Map());
|
|
11603
|
-
setIsLoading(false);
|
|
11604
|
-
return;
|
|
11605
|
-
}
|
|
11606
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11607
|
-
const validLineIds = lineIds.filter((id3) => uuidRegex.test(id3));
|
|
11608
|
-
if (validLineIds.length === 0) {
|
|
11609
|
-
console.warn("[useMultiLineShiftConfigs] No valid line IDs provided");
|
|
11610
|
-
setShiftConfigMap(/* @__PURE__ */ new Map());
|
|
11611
|
-
setIsLoading(false);
|
|
11612
|
-
return;
|
|
11613
|
-
}
|
|
11614
|
-
let mounted = true;
|
|
11615
|
-
const calculateBreakDuration2 = (startTime, endTime) => {
|
|
11616
|
-
const [sh, sm] = startTime.split(":").map(Number);
|
|
11617
|
-
const [eh, em] = endTime.split(":").map(Number);
|
|
11618
|
-
let startMinutes = sh * 60 + sm;
|
|
11619
|
-
let endMinutes = eh * 60 + em;
|
|
11620
|
-
if (endMinutes < startMinutes) {
|
|
11621
|
-
endMinutes += 24 * 60;
|
|
11622
|
-
}
|
|
11623
|
-
return endMinutes - startMinutes;
|
|
11624
|
-
};
|
|
11625
|
-
const stripSeconds = (timeStr) => {
|
|
11626
|
-
if (!timeStr) return timeStr;
|
|
11627
|
-
return timeStr.substring(0, 5);
|
|
11628
|
-
};
|
|
11629
|
-
const buildShiftConfigFromRows = (shifts, fallback) => {
|
|
11630
|
-
const mapped = shifts.map((shift) => ({
|
|
11631
|
-
shiftId: shift.shift_id,
|
|
11632
|
-
shiftName: shift.shift_name || `Shift ${shift.shift_id}`,
|
|
11633
|
-
startTime: stripSeconds(shift.start_time),
|
|
11634
|
-
endTime: stripSeconds(shift.end_time),
|
|
11635
|
-
breaks: Array.isArray(shift.breaks) ? shift.breaks.map((b) => ({
|
|
11636
|
-
startTime: b.start || b.startTime || "00:00",
|
|
11637
|
-
endTime: b.end || b.endTime || "00:00",
|
|
11638
|
-
duration: calculateBreakDuration2(
|
|
11639
|
-
b.start || b.startTime || "00:00",
|
|
11640
|
-
b.end || b.endTime || "00:00"
|
|
11641
|
-
),
|
|
11642
|
-
remarks: b.remarks || b.name || ""
|
|
11643
|
-
})) : [],
|
|
11644
|
-
timezone: shift.timezone
|
|
11645
|
-
}));
|
|
11646
|
-
const day = mapped.find((s) => s.shiftId === 0);
|
|
11647
|
-
const night = mapped.find((s) => s.shiftId === 1);
|
|
11648
|
-
return {
|
|
11649
|
-
shifts: mapped,
|
|
11650
|
-
timezone: mapped[0]?.timezone,
|
|
11651
|
-
dayShift: day ? { id: day.shiftId, startTime: day.startTime, endTime: day.endTime, name: day.shiftName } : fallback?.dayShift,
|
|
11652
|
-
nightShift: night ? { id: night.shiftId, startTime: night.startTime, endTime: night.endTime, name: night.shiftName } : fallback?.nightShift,
|
|
11653
|
-
transitionPeriodMinutes: fallback?.transitionPeriodMinutes || 0
|
|
11654
|
-
};
|
|
11655
|
-
};
|
|
11656
|
-
const fetchAllConfigs = async () => {
|
|
11657
|
-
try {
|
|
11658
|
-
setIsLoading(true);
|
|
11659
|
-
setError(null);
|
|
11660
|
-
console.log(`[useMultiLineShiftConfigs] Fetching shift configs for ${validLineIds.length} lines`);
|
|
11661
|
-
const { data, error: fetchError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks, timezone").in("line_id", validLineIds);
|
|
11662
|
-
if (fetchError) {
|
|
11663
|
-
console.error("[useMultiLineShiftConfigs] Error fetching shift configs:", fetchError);
|
|
11664
|
-
throw new Error(`Failed to fetch shift configs: ${fetchError.message}`);
|
|
11665
|
-
}
|
|
11666
|
-
const lineShiftsMap = /* @__PURE__ */ new Map();
|
|
11667
|
-
data?.forEach((row) => {
|
|
11668
|
-
if (!lineShiftsMap.has(row.line_id)) {
|
|
11669
|
-
lineShiftsMap.set(row.line_id, []);
|
|
11670
|
-
}
|
|
11671
|
-
lineShiftsMap.get(row.line_id).push(row);
|
|
11672
|
-
});
|
|
11673
|
-
const configMap = /* @__PURE__ */ new Map();
|
|
11674
|
-
lineShiftsMap.forEach((shifts, lineId) => {
|
|
11675
|
-
const config = buildShiftConfigFromRows(shifts, fallbackConfig);
|
|
11676
|
-
configMap.set(lineId, config);
|
|
11677
|
-
});
|
|
11678
|
-
validLineIds.forEach((lineId) => {
|
|
11679
|
-
if (!configMap.has(lineId) && fallbackConfig) {
|
|
11680
|
-
console.warn(`[useMultiLineShiftConfigs] No config found for line ${lineId}, using fallback`);
|
|
11681
|
-
configMap.set(lineId, fallbackConfig);
|
|
11682
|
-
}
|
|
11683
|
-
});
|
|
11684
|
-
console.log(`[useMultiLineShiftConfigs] Built configs for ${configMap.size} lines`);
|
|
11685
|
-
if (mounted) {
|
|
11686
|
-
setShiftConfigMap(configMap);
|
|
11687
|
-
setIsLoading(false);
|
|
11688
|
-
}
|
|
11689
|
-
} catch (err) {
|
|
11690
|
-
console.error("[useMultiLineShiftConfigs] Error:", err);
|
|
11691
|
-
if (mounted) {
|
|
11692
|
-
setError(err instanceof Error ? err.message : "Failed to fetch shift configs");
|
|
11693
|
-
if (fallbackConfig) {
|
|
11694
|
-
const fallbackMap = /* @__PURE__ */ new Map();
|
|
11695
|
-
validLineIds.forEach((lineId) => {
|
|
11696
|
-
fallbackMap.set(lineId, fallbackConfig);
|
|
11697
|
-
});
|
|
11698
|
-
setShiftConfigMap(fallbackMap);
|
|
11699
|
-
}
|
|
11700
|
-
setIsLoading(false);
|
|
11701
|
-
}
|
|
11702
|
-
}
|
|
11703
|
-
};
|
|
11704
|
-
fetchAllConfigs();
|
|
11705
|
-
return () => {
|
|
11706
|
-
mounted = false;
|
|
11707
|
-
};
|
|
11708
|
-
}, [lineIdsKey, supabase]);
|
|
11709
|
-
return {
|
|
11710
|
-
shiftConfigMap,
|
|
11711
|
-
isLoading,
|
|
11712
|
-
error
|
|
11713
|
-
};
|
|
11714
|
-
};
|
|
11715
12111
|
var MAX_RETRIES = 10;
|
|
11716
12112
|
var RETRY_DELAY = 500;
|
|
11717
12113
|
function useNavigation(customNavigate) {
|
|
@@ -45266,6 +45662,10 @@ function HomeView({
|
|
|
45266
45662
|
const [diagnosisModalOpen, setDiagnosisModalOpen] = React24.useState(false);
|
|
45267
45663
|
const [diagnoses, setDiagnoses] = React24.useState([]);
|
|
45268
45664
|
const timezone = useAppTimezone();
|
|
45665
|
+
const { shiftConfigMap: lineShiftConfigs } = useMultiLineShiftConfigs(
|
|
45666
|
+
allLineIds,
|
|
45667
|
+
dashboardConfig?.shiftConfig
|
|
45668
|
+
);
|
|
45269
45669
|
React24.useEffect(() => {
|
|
45270
45670
|
const initDisplayNames = async () => {
|
|
45271
45671
|
try {
|
|
@@ -45363,12 +45763,18 @@ function HomeView({
|
|
|
45363
45763
|
label: "Diagnose",
|
|
45364
45764
|
onClick: async () => {
|
|
45365
45765
|
console.log("\u{1F50D} Investigating bottleneck:", bottleneck.log_number);
|
|
45366
|
-
const operationalDate = getOperationalDate(
|
|
45367
|
-
timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC"
|
|
45368
|
-
);
|
|
45369
45766
|
const tz = timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC";
|
|
45370
|
-
const
|
|
45767
|
+
const lineShiftConfig = bottleneck.line_id && lineShiftConfigs.get(bottleneck.line_id);
|
|
45768
|
+
const effectiveShiftConfig = lineShiftConfig || dashboardConfig?.shiftConfig;
|
|
45769
|
+
const shiftResult = getCurrentShift(tz, effectiveShiftConfig);
|
|
45371
45770
|
const currentShift = shiftResult.shiftId;
|
|
45771
|
+
const operationalDate = shiftResult.date;
|
|
45772
|
+
console.log("\u{1F550} Using shift config for line:", {
|
|
45773
|
+
lineId: bottleneck.line_id,
|
|
45774
|
+
hasLineConfig: !!lineShiftConfig,
|
|
45775
|
+
shiftId: currentShift,
|
|
45776
|
+
date: operationalDate
|
|
45777
|
+
});
|
|
45372
45778
|
console.log("\u{1F3AC} [Investigate] Opening clips modal with data:", {
|
|
45373
45779
|
workspaceId: bottleneck.workspace_id,
|
|
45374
45780
|
ticketId: bottleneck.id,
|
|
@@ -45438,12 +45844,18 @@ function HomeView({
|
|
|
45438
45844
|
state,
|
|
45439
45845
|
priority: bottleneck.priority
|
|
45440
45846
|
});
|
|
45441
|
-
const operationalDate = getOperationalDate(
|
|
45442
|
-
timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC"
|
|
45443
|
-
);
|
|
45444
45847
|
const tz = timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC";
|
|
45445
|
-
const
|
|
45848
|
+
const lineShiftConfig = bottleneck.line_id && lineShiftConfigs.get(bottleneck.line_id);
|
|
45849
|
+
const effectiveShiftConfig = lineShiftConfig || dashboardConfig?.shiftConfig;
|
|
45850
|
+
const shiftResult = getCurrentShift(tz, effectiveShiftConfig);
|
|
45446
45851
|
const currentShift = shiftResult.shiftId;
|
|
45852
|
+
const operationalDate = shiftResult.date;
|
|
45853
|
+
console.log("\u{1F550} Using shift config for line:", {
|
|
45854
|
+
lineId: bottleneck.line_id,
|
|
45855
|
+
hasLineConfig: !!lineShiftConfig,
|
|
45856
|
+
shiftId: currentShift,
|
|
45857
|
+
date: operationalDate
|
|
45858
|
+
});
|
|
45447
45859
|
setBottleneckModalData({
|
|
45448
45860
|
workspaceId: bottleneck.workspace_id,
|
|
45449
45861
|
workspaceName: bottleneck_workspace.workspace_name || "Unknown Workspace",
|
|
@@ -45500,7 +45912,7 @@ function HomeView({
|
|
|
45500
45912
|
};
|
|
45501
45913
|
setBottleneckNotification(errorNotification);
|
|
45502
45914
|
}
|
|
45503
|
-
}, [notificationService, timezone, dashboardConfig]);
|
|
45915
|
+
}, [notificationService, timezone, dashboardConfig, lineShiftConfigs]);
|
|
45504
45916
|
React24.useEffect(() => {
|
|
45505
45917
|
const ticketsEnabled = dashboardConfig?.ticketsConfig?.enabled ?? true;
|
|
45506
45918
|
if (!ticketsEnabled) {
|
|
@@ -47443,6 +47855,7 @@ var LeaderboardDetailView = React24.memo(({
|
|
|
47443
47855
|
const entityConfig = useEntityConfig();
|
|
47444
47856
|
const [sortAscending, setSortAscending] = React24.useState(false);
|
|
47445
47857
|
const timezone = useAppTimezone();
|
|
47858
|
+
const staticShiftConfig = useShiftConfig();
|
|
47446
47859
|
const [isMobile, setIsMobile] = React24.useState(false);
|
|
47447
47860
|
React24__namespace.default.useEffect(() => {
|
|
47448
47861
|
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
@@ -47471,9 +47884,27 @@ var LeaderboardDetailView = React24.memo(({
|
|
|
47471
47884
|
() => typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
|
|
47472
47885
|
[shift]
|
|
47473
47886
|
);
|
|
47474
|
-
const
|
|
47475
|
-
|
|
47476
|
-
|
|
47887
|
+
const configuredLineIds = React24.useMemo(() => {
|
|
47888
|
+
const allLineIds = getConfiguredLineIds(entityConfig);
|
|
47889
|
+
if (userAccessibleLineIds) {
|
|
47890
|
+
return allLineIds.filter((id3) => userAccessibleLineIds.includes(id3));
|
|
47891
|
+
}
|
|
47892
|
+
return allLineIds;
|
|
47893
|
+
}, [entityConfig, userAccessibleLineIds]);
|
|
47894
|
+
const shouldFetchShiftConfigs = !date && shiftId === void 0;
|
|
47895
|
+
const {
|
|
47896
|
+
shiftConfigMap: multiLineShiftConfigMap,
|
|
47897
|
+
isLoading: isShiftConfigLoading
|
|
47898
|
+
} = useMultiLineShiftConfigs(
|
|
47899
|
+
shouldFetchShiftConfigs ? configuredLineIds : [],
|
|
47900
|
+
staticShiftConfig
|
|
47901
|
+
);
|
|
47902
|
+
const shiftGroups = React24.useMemo(() => {
|
|
47903
|
+
if (!shouldFetchShiftConfigs || isShiftConfigLoading || multiLineShiftConfigMap.size === 0) {
|
|
47904
|
+
return [];
|
|
47905
|
+
}
|
|
47906
|
+
return groupLinesByShift(multiLineShiftConfigMap, timezone || "Asia/Kolkata");
|
|
47907
|
+
}, [shouldFetchShiftConfigs, isShiftConfigLoading, multiLineShiftConfigMap, timezone]);
|
|
47477
47908
|
const {
|
|
47478
47909
|
workspaces,
|
|
47479
47910
|
loading: workspacesLoading,
|
|
@@ -47481,21 +47912,28 @@ var LeaderboardDetailView = React24.memo(({
|
|
|
47481
47912
|
refreshWorkspaces
|
|
47482
47913
|
} = useAllWorkspaceMetrics({
|
|
47483
47914
|
initialDate: date,
|
|
47484
|
-
initialShiftId:
|
|
47915
|
+
initialShiftId: shiftId,
|
|
47485
47916
|
allowedLineIds: userAccessibleLineIds,
|
|
47486
|
-
// Filter to user's accessible lines only
|
|
47487
47917
|
enabled: !isShiftConfigLoading
|
|
47488
|
-
// Pass enabled flag
|
|
47489
47918
|
});
|
|
47490
47919
|
const getShiftName = React24.useCallback((shiftId2) => {
|
|
47491
47920
|
if (shiftId2 !== void 0) {
|
|
47492
|
-
return getShiftNameById(shiftId2, timezone || "Asia/Kolkata",
|
|
47921
|
+
return getShiftNameById(shiftId2, timezone || "Asia/Kolkata", staticShiftConfig);
|
|
47493
47922
|
}
|
|
47494
|
-
|
|
47495
|
-
|
|
47496
|
-
|
|
47923
|
+
if (shiftGroups.length > 1) {
|
|
47924
|
+
const shiftNames = shiftGroups.map((g) => g.shiftName).join(" & ");
|
|
47925
|
+
return shiftNames;
|
|
47926
|
+
} else if (shiftGroups.length === 1) {
|
|
47927
|
+
return shiftGroups[0].shiftName;
|
|
47928
|
+
}
|
|
47929
|
+
const currentShift = getCurrentShift(timezone || "Asia/Kolkata", staticShiftConfig);
|
|
47930
|
+
return currentShift.shiftName || getShiftNameById(currentShift.shiftId, timezone || "Asia/Kolkata", staticShiftConfig);
|
|
47931
|
+
}, [timezone, staticShiftConfig, shiftGroups]);
|
|
47497
47932
|
const getShiftIcon = React24.useCallback((shiftId2) => {
|
|
47498
|
-
|
|
47933
|
+
if (shiftId2 === void 0 && shiftGroups.length > 1) {
|
|
47934
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
47935
|
+
}
|
|
47936
|
+
const effectiveShiftId = shiftId2 !== void 0 ? shiftId2 : shiftGroups.length === 1 ? shiftGroups[0].shiftId : getCurrentShift(timezone || "Asia/Kolkata", staticShiftConfig).shiftId;
|
|
47499
47937
|
const shiftNameLower = getShiftName(effectiveShiftId).toLowerCase();
|
|
47500
47938
|
if (shiftNameLower.includes("day") || shiftNameLower.includes("morning")) {
|
|
47501
47939
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" }) });
|
|
@@ -47507,7 +47945,7 @@ var LeaderboardDetailView = React24.memo(({
|
|
|
47507
47945
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" }) });
|
|
47508
47946
|
}
|
|
47509
47947
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
47510
|
-
}, [getShiftName]);
|
|
47948
|
+
}, [getShiftName, shiftGroups, timezone, staticShiftConfig]);
|
|
47511
47949
|
const formatDate2 = React24.useCallback((date2) => {
|
|
47512
47950
|
return new Intl.DateTimeFormat("en-US", {
|
|
47513
47951
|
weekday: "long",
|
|
@@ -56845,6 +57283,7 @@ exports.WorkspacePdfGenerator = WorkspacePdfGenerator;
|
|
|
56845
57283
|
exports.WorkspaceWhatsAppShareButton = WorkspaceWhatsAppShareButton;
|
|
56846
57284
|
exports.actionService = actionService;
|
|
56847
57285
|
exports.apiUtils = apiUtils;
|
|
57286
|
+
exports.areAllLinesOnSameShift = areAllLinesOnSameShift;
|
|
56848
57287
|
exports.authCoreService = authCoreService;
|
|
56849
57288
|
exports.authOTPService = authOTPService;
|
|
56850
57289
|
exports.authRateLimitService = authRateLimitService;
|
|
@@ -56890,6 +57329,7 @@ exports.getConfiguredLineIds = getConfiguredLineIds;
|
|
|
56890
57329
|
exports.getCoreSessionRecordingProperties = getCoreSessionRecordingProperties;
|
|
56891
57330
|
exports.getCoreSessionReplayUrl = getCoreSessionReplayUrl;
|
|
56892
57331
|
exports.getCurrentShift = getCurrentShift;
|
|
57332
|
+
exports.getCurrentShiftForLine = getCurrentShiftForLine;
|
|
56893
57333
|
exports.getCurrentTimeInZone = getCurrentTimeInZone;
|
|
56894
57334
|
exports.getDashboardHeaderTimeInZone = getDashboardHeaderTimeInZone;
|
|
56895
57335
|
exports.getDaysDifferenceInZone = getDaysDifferenceInZone;
|
|
@@ -56912,6 +57352,7 @@ exports.getShortWorkspaceDisplayNameAsync = getShortWorkspaceDisplayNameAsync;
|
|
|
56912
57352
|
exports.getStoredWorkspaceMappings = getStoredWorkspaceMappings;
|
|
56913
57353
|
exports.getSubscriptionManager = getSubscriptionManager;
|
|
56914
57354
|
exports.getThreadMessages = getThreadMessages;
|
|
57355
|
+
exports.getUniformShiftGroup = getUniformShiftGroup;
|
|
56915
57356
|
exports.getUserThreads = getUserThreads;
|
|
56916
57357
|
exports.getUserThreadsPaginated = getUserThreadsPaginated;
|
|
56917
57358
|
exports.getWorkspaceDisplayName = getWorkspaceDisplayName;
|
|
@@ -56919,6 +57360,7 @@ exports.getWorkspaceDisplayNameAsync = getWorkspaceDisplayNameAsync;
|
|
|
56919
57360
|
exports.getWorkspaceDisplayNamesMap = getWorkspaceDisplayNamesMap;
|
|
56920
57361
|
exports.getWorkspaceFromUrl = getWorkspaceFromUrl;
|
|
56921
57362
|
exports.getWorkspaceNavigationParams = getWorkspaceNavigationParams;
|
|
57363
|
+
exports.groupLinesByShift = groupLinesByShift;
|
|
56922
57364
|
exports.hasAnyShiftData = hasAnyShiftData;
|
|
56923
57365
|
exports.identifyCoreUser = identifyCoreUser;
|
|
56924
57366
|
exports.initializeCoreMixpanel = initializeCoreMixpanel;
|