@optifye/dashboard-core 6.9.2 → 6.9.4

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.js CHANGED
@@ -2088,6 +2088,59 @@ var workspaceService = {
2088
2088
  console.error("Error updating shift configuration:", error);
2089
2089
  throw error;
2090
2090
  }
2091
+ },
2092
+ /**
2093
+ * Fetch bulk targets data for multiple lines and shifts in a single API call
2094
+ * This replaces 120+ individual API calls with 1 optimized call
2095
+ *
2096
+ * @param params - Parameters for the bulk fetch
2097
+ * @returns Promise with complete targets data for all lines and shifts
2098
+ */
2099
+ async fetchBulkTargets(params) {
2100
+ try {
2101
+ const token = await getAuthToken();
2102
+ const apiUrl = getBackendUrl();
2103
+ const {
2104
+ companyId,
2105
+ lineIds,
2106
+ date,
2107
+ shifts = [0, 1],
2108
+ includeSkus = true,
2109
+ includeActions = true
2110
+ } = params;
2111
+ const queryParams = new URLSearchParams({
2112
+ company_id: companyId,
2113
+ line_ids: lineIds.join(","),
2114
+ date,
2115
+ shifts: shifts.join(","),
2116
+ include_skus: includeSkus.toString(),
2117
+ include_actions: includeActions.toString()
2118
+ });
2119
+ const response = await fetch(
2120
+ `${apiUrl}/api/targets/bulk-load?${queryParams}`,
2121
+ {
2122
+ method: "GET",
2123
+ headers: {
2124
+ "Authorization": `Bearer ${token}`,
2125
+ "Content-Type": "application/json"
2126
+ }
2127
+ }
2128
+ );
2129
+ if (!response.ok) {
2130
+ const errorText = await response.text();
2131
+ throw new Error(`Backend API error (${response.status}): ${errorText}`);
2132
+ }
2133
+ const data = await response.json();
2134
+ console.log("[fetchBulkTargets] Success:", {
2135
+ lineCount: data.metadata?.line_count,
2136
+ totalWorkspaces: data.metadata?.total_workspaces,
2137
+ timestamp: data.metadata?.timestamp
2138
+ });
2139
+ return data;
2140
+ } catch (error) {
2141
+ console.error("Error fetching bulk targets:", error);
2142
+ throw error;
2143
+ }
2091
2144
  }
2092
2145
  };
2093
2146
  var WorkspaceHealthService = class _WorkspaceHealthService {
@@ -5822,60 +5875,32 @@ var UserManagementService = class {
5822
5875
  }
5823
5876
  }
5824
5877
  /**
5825
- * Deactivate a user
5826
- * @param input - Deactivation input
5878
+ * Permanently delete a user
5879
+ * @param userId - The ID of the user to delete
5880
+ * @returns Promise with deletion response
5827
5881
  */
5828
- async deactivateUser(input) {
5882
+ async deleteUser(userId) {
5829
5883
  try {
5830
5884
  const token = await this.getAuthToken();
5831
5885
  const backendUrl = this.getBackendUrl();
5832
5886
  const response = await fetch(
5833
- `${backendUrl}/api/users/deactivate`,
5834
- {
5835
- method: "POST",
5836
- headers: {
5837
- "Authorization": `Bearer ${token}`,
5838
- "Content-Type": "application/json"
5839
- },
5840
- body: JSON.stringify(input)
5841
- }
5842
- );
5843
- if (!response.ok) {
5844
- const errorData = await response.json();
5845
- throw new Error(`Failed to deactivate user: ${errorData.detail || response.statusText}`);
5846
- }
5847
- console.log("[UserManagementService] User deactivated successfully");
5848
- } catch (error) {
5849
- console.error("[UserManagementService] Error deactivating user:", error);
5850
- throw error;
5851
- }
5852
- }
5853
- /**
5854
- * Reactivate a user
5855
- * @param input - Reactivation input
5856
- */
5857
- async reactivateUser(input) {
5858
- try {
5859
- const token = await this.getAuthToken();
5860
- const backendUrl = this.getBackendUrl();
5861
- const response = await fetch(
5862
- `${backendUrl}/api/users/reactivate`,
5887
+ `${backendUrl}/api/users/${userId}`,
5863
5888
  {
5864
- method: "POST",
5889
+ method: "DELETE",
5865
5890
  headers: {
5866
- "Authorization": `Bearer ${token}`,
5867
- "Content-Type": "application/json"
5868
- },
5869
- body: JSON.stringify(input)
5891
+ "Authorization": `Bearer ${token}`
5892
+ }
5870
5893
  }
5871
5894
  );
5872
5895
  if (!response.ok) {
5873
5896
  const errorData = await response.json();
5874
- throw new Error(`Failed to reactivate user: ${errorData.detail || response.statusText}`);
5897
+ throw new Error(`Failed to delete user: ${errorData.detail || response.statusText}`);
5875
5898
  }
5876
- console.log("[UserManagementService] User reactivated successfully");
5899
+ const result = await response.json();
5900
+ console.log("[UserManagementService] User permanently deleted:", result);
5901
+ return result;
5877
5902
  } catch (error) {
5878
- console.error("[UserManagementService] Error reactivating user:", error);
5903
+ console.error("[UserManagementService] Error deleting user:", error);
5879
5904
  throw error;
5880
5905
  }
5881
5906
  }
@@ -7688,7 +7713,7 @@ var useLeaderboardMetrics = (date, shiftId, limit = 10, filter2 = "all") => {
7688
7713
  refetch: fetchLeaderboard
7689
7714
  };
7690
7715
  };
7691
- var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
7716
+ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds }) => {
7692
7717
  const { supabaseUrl, supabaseKey } = useDashboardConfig();
7693
7718
  const entityConfig = useEntityConfig();
7694
7719
  const databaseConfig = useDatabaseConfig();
@@ -7733,7 +7758,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
7733
7758
  try {
7734
7759
  const currentShiftDetails = getCurrentShift(defaultTimezone, shiftConfig);
7735
7760
  const operationalDate = getOperationalDate(defaultTimezone);
7736
- const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
7761
+ const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? userAccessibleLineIds || getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
7737
7762
  if (targetLineIds.length === 0 && currentLineIdToUse === (entityConfig.factoryViewId || "factory")) {
7738
7763
  throw new Error("Factory view selected, but no lines are configured in entityConfig.");
7739
7764
  }
@@ -7859,7 +7884,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
7859
7884
  }
7860
7885
  const currentShiftDetails = getCurrentShift(defaultTimezone, shiftConfig);
7861
7886
  const operationalDateForSubscription = getOperationalDate(defaultTimezone);
7862
- const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
7887
+ const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? userAccessibleLineIds || getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
7863
7888
  if (targetLineIds.length === 0) return;
7864
7889
  const wsMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
7865
7890
  const lineMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
@@ -7897,7 +7922,8 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
7897
7922
  entityConfig?.companyId,
7898
7923
  entityConfig?.factoryViewId,
7899
7924
  defaultTimezone,
7900
- lineId
7925
+ lineId,
7926
+ userAccessibleLineIds
7901
7927
  ]);
7902
7928
  return {
7903
7929
  workspaceMetrics: metrics2?.workspaceMetrics || [],
@@ -9887,7 +9913,8 @@ var useAllWorkspaceMetrics = (options) => {
9887
9913
  }
9888
9914
  setError(null);
9889
9915
  try {
9890
- const configuredLineIds = getConfiguredLineIds(entityConfig);
9916
+ const allConfiguredLineIds = getConfiguredLineIds(entityConfig);
9917
+ const configuredLineIds = options?.allowedLineIds ? allConfiguredLineIds.filter((id3) => options.allowedLineIds.includes(id3)) : allConfiguredLineIds;
9891
9918
  let enabledWorkspaceIds = [];
9892
9919
  for (const lineId of configuredLineIds) {
9893
9920
  const workspaces2 = await workspaceService.getWorkspaces(lineId);
@@ -9950,7 +9977,7 @@ var useAllWorkspaceMetrics = (options) => {
9950
9977
  setLoading(false);
9951
9978
  isFetchingRef.current = false;
9952
9979
  }
9953
- }, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId]);
9980
+ }, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId, entityConfig, options?.allowedLineIds]);
9954
9981
  React23.useEffect(() => {
9955
9982
  if (!initialized) {
9956
9983
  fetchWorkspaceMetrics();
@@ -41449,7 +41476,6 @@ function HomeView({
41449
41476
  factoryName = "Simba Beer - Line 1"
41450
41477
  }) {
41451
41478
  const [isHydrated, setIsHydrated] = React23.useState(false);
41452
- const availableLineIds = React23.useMemo(() => [factoryViewId, ...allLineIds], [factoryViewId, allLineIds]);
41453
41479
  const [selectedLineId, setSelectedLineId] = React23.useState(factoryViewId);
41454
41480
  const [isChangingFilter, setIsChangingFilter] = React23.useState(false);
41455
41481
  const [errorMessage, setErrorMessage] = React23.useState(null);
@@ -41459,6 +41485,21 @@ function HomeView({
41459
41485
  const entityConfig = useEntityConfig();
41460
41486
  const supabaseClient = useSupabaseClient();
41461
41487
  const { user } = useAuth();
41488
+ const isSupervisor = user?.role_level === "supervisor";
41489
+ const hasMultipleLines = allLineIds.length > 1;
41490
+ const availableLineIds = React23.useMemo(() => {
41491
+ if (isSupervisor && !hasMultipleLines) {
41492
+ return allLineIds;
41493
+ }
41494
+ return [factoryViewId, ...allLineIds];
41495
+ }, [factoryViewId, allLineIds, isSupervisor, hasMultipleLines]);
41496
+ React23.useEffect(() => {
41497
+ if (user) {
41498
+ if (isSupervisor && allLineIds.length > 0) {
41499
+ setSelectedLineId(allLineIds[0]);
41500
+ }
41501
+ }
41502
+ }, [user, isSupervisor, allLineIds]);
41462
41503
  const userCompanyId = React23.useMemo(() => {
41463
41504
  return user?.properties?.company_id || user?.company_id || entityConfig.companyId;
41464
41505
  }, [user, entityConfig.companyId]);
@@ -41519,7 +41560,9 @@ function HomeView({
41519
41560
  refetch: refetchMetrics
41520
41561
  } = useDashboardMetrics({
41521
41562
  lineId: selectedLineId,
41522
- onLineMetricsUpdate
41563
+ onLineMetricsUpdate,
41564
+ userAccessibleLineIds: allLineIds
41565
+ // Pass user's accessible lines for supervisor filtering
41523
41566
  });
41524
41567
  const {
41525
41568
  activeBreaks: allActiveBreaks,
@@ -43578,7 +43621,8 @@ var LeaderboardDetailView = React23.memo(({
43578
43621
  line1Id = "",
43579
43622
  line2Id = "",
43580
43623
  lineNames = {},
43581
- className = ""
43624
+ className = "",
43625
+ userAccessibleLineIds
43582
43626
  }) => {
43583
43627
  const navigation = useNavigation();
43584
43628
  const entityConfig = useEntityConfig();
@@ -43618,7 +43662,9 @@ var LeaderboardDetailView = React23.memo(({
43618
43662
  refreshWorkspaces
43619
43663
  } = useAllWorkspaceMetrics({
43620
43664
  initialDate: date,
43621
- initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0
43665
+ initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
43666
+ allowedLineIds: userAccessibleLineIds
43667
+ // Filter to user's accessible lines only
43622
43668
  });
43623
43669
  const getShiftName = React23.useCallback((shiftId2) => {
43624
43670
  if (shiftId2 === void 0) return "Day";
@@ -44974,12 +45020,17 @@ var ACTION_NAMES = {
44974
45020
  var calculatePPH = (cycleTime, breaks = [], shiftHours = 0) => {
44975
45021
  if (cycleTime === "" || cycleTime === 0) return "";
44976
45022
  const pph = 3600 / cycleTime;
44977
- return Number(pph.toFixed(1));
45023
+ return Math.round(pph);
44978
45024
  };
44979
45025
  var calculateDayOutput = (pph, shiftHours, breaks = []) => {
44980
45026
  if (pph === "") return "";
44981
45027
  return Math.round(pph * shiftHours);
44982
45028
  };
45029
+ var calculateDayOutputFromCycleTime = (cycleTime, shiftHours) => {
45030
+ if (cycleTime === "" || cycleTime === 0 || shiftHours === 0) return "";
45031
+ const dayOutput = 3600 / cycleTime * shiftHours;
45032
+ return Math.round(dayOutput);
45033
+ };
44983
45034
  var formatWorkspaceName = (name, lineId) => {
44984
45035
  return getWorkspaceDisplayName(name, lineId);
44985
45036
  };
@@ -44991,20 +45042,6 @@ var getStoredLineState2 = (lineId) => {
44991
45042
  return false;
44992
45043
  }
44993
45044
  };
44994
- var calculateShiftHours2 = (startTime, endTime, breaks = []) => {
44995
- if (!startTime || !endTime) return 8;
44996
- const [startHour, startMinute] = startTime.split(":").map(Number);
44997
- const [endHour, endMinute] = endTime.split(":").map(Number);
44998
- let startMinutes = startHour * 60 + startMinute;
44999
- let endMinutes = endHour * 60 + endMinute;
45000
- if (endMinutes < startMinutes) {
45001
- endMinutes += 24 * 60;
45002
- }
45003
- const safeBreaks = Array.isArray(breaks) ? breaks : [];
45004
- const totalBreakMinutes = safeBreaks.reduce((total, breakItem) => total + breakItem.duration, 0);
45005
- const hoursDiff = (endMinutes - startMinutes - totalBreakMinutes) / 60;
45006
- return Number(hoursDiff.toFixed(1));
45007
- };
45008
45045
  var BulkConfigureModal = ({
45009
45046
  isOpen,
45010
45047
  onClose,
@@ -46212,121 +46249,6 @@ var TargetsView = ({
46212
46249
  const dashboardConfig = useDashboardConfig();
46213
46250
  const { skus, isLoading: skusLoading } = useSKUs(companyId);
46214
46251
  const skuEnabled = dashboardConfig?.skuConfig?.enabled || false;
46215
- const loadOperatingHours = React23.useCallback(async (lineId, shiftId) => {
46216
- try {
46217
- const { data: { session } } = await supabase.auth.getSession();
46218
- if (!session?.access_token) {
46219
- console.error("No authentication token available");
46220
- return {
46221
- startTime: "08:00",
46222
- // Default values
46223
- endTime: "19:00",
46224
- breaks: []
46225
- };
46226
- }
46227
- const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
46228
- if (!backendUrl) {
46229
- console.error("Backend URL is not configured");
46230
- return {
46231
- startTime: "08:00",
46232
- // Default values
46233
- endTime: "19:00",
46234
- breaks: []
46235
- };
46236
- }
46237
- const response = await fetch(`${backendUrl}/api/lines/${lineId}/operating-hours?shift_id=${shiftId}`, {
46238
- headers: {
46239
- "Authorization": `Bearer ${session.access_token}`,
46240
- "Content-Type": "application/json"
46241
- }
46242
- });
46243
- if (!response.ok) {
46244
- console.log(`No operating hours found for line ${lineId}, shift ${shiftId} - using defaults`);
46245
- return {
46246
- startTime: "08:00",
46247
- // Default values
46248
- endTime: "19:00",
46249
- breaks: []
46250
- };
46251
- }
46252
- const data = await response.json();
46253
- let breaks = [];
46254
- if (data?.breaks) {
46255
- if (Array.isArray(data.breaks)) {
46256
- breaks = data.breaks.map((breakItem) => {
46257
- const startTime = breakItem.start || breakItem.startTime || "00:00";
46258
- const endTime = breakItem.end || breakItem.endTime || "00:00";
46259
- const calculateDuration = (start, end) => {
46260
- const [startHour, startMinute] = start.split(":").map(Number);
46261
- const [endHour, endMinute] = end.split(":").map(Number);
46262
- let startMinutes = startHour * 60 + startMinute;
46263
- let endMinutes = endHour * 60 + endMinute;
46264
- if (endMinutes < startMinutes) {
46265
- endMinutes += 24 * 60;
46266
- }
46267
- return endMinutes - startMinutes;
46268
- };
46269
- return {
46270
- startTime,
46271
- endTime,
46272
- duration: breakItem.duration || calculateDuration(startTime, endTime)
46273
- };
46274
- });
46275
- } else if (typeof data.breaks === "object" && data.breaks.breaks) {
46276
- breaks = data.breaks.breaks.map((breakItem) => {
46277
- const startTime = breakItem.start || breakItem.startTime || "00:00";
46278
- const endTime = breakItem.end || breakItem.endTime || "00:00";
46279
- const calculateDuration = (start, end) => {
46280
- const [startHour, startMinute] = start.split(":").map(Number);
46281
- const [endHour, endMinute] = end.split(":").map(Number);
46282
- let startMinutes = startHour * 60 + startMinute;
46283
- let endMinutes = endHour * 60 + endMinute;
46284
- if (endMinutes < startMinutes) {
46285
- endMinutes += 24 * 60;
46286
- }
46287
- return endMinutes - startMinutes;
46288
- };
46289
- return {
46290
- startTime,
46291
- endTime,
46292
- duration: breakItem.duration || calculateDuration(startTime, endTime)
46293
- };
46294
- });
46295
- } else if (typeof data.breaks === "string") {
46296
- try {
46297
- const parsedBreaks = JSON.parse(data.breaks);
46298
- if (Array.isArray(parsedBreaks)) {
46299
- breaks = parsedBreaks.map((breakItem) => ({
46300
- startTime: breakItem.start || breakItem.startTime || "00:00",
46301
- endTime: breakItem.end || breakItem.endTime || "00:00",
46302
- duration: breakItem.duration || 0
46303
- }));
46304
- } else if (parsedBreaks.breaks && Array.isArray(parsedBreaks.breaks)) {
46305
- breaks = parsedBreaks.breaks.map((breakItem) => ({
46306
- startTime: breakItem.start || breakItem.startTime || "00:00",
46307
- endTime: breakItem.end || breakItem.endTime || "00:00",
46308
- duration: breakItem.duration || 0
46309
- }));
46310
- }
46311
- } catch (e) {
46312
- console.error("Error parsing breaks data:", e);
46313
- }
46314
- }
46315
- }
46316
- return {
46317
- startTime: data?.start_time || "08:00",
46318
- endTime: data?.end_time || "19:00",
46319
- breaks
46320
- };
46321
- } catch (e) {
46322
- console.error("Exception when loading operating hours:", e);
46323
- return {
46324
- startTime: "08:00",
46325
- endTime: "19:00",
46326
- breaks: []
46327
- };
46328
- }
46329
- }, [supabase]);
46330
46252
  React23.useEffect(() => {
46331
46253
  console.log("[TargetsView] Component mounted/re-rendered", {
46332
46254
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -46338,221 +46260,108 @@ var TargetsView = ({
46338
46260
  };
46339
46261
  }, []);
46340
46262
  React23.useEffect(() => {
46341
- let timeoutId;
46342
- let retryCount = 0;
46343
- const MAX_RETRIES2 = 2;
46344
- const LOADING_TIMEOUT = 15e3;
46345
46263
  const fetchInitialData = async () => {
46346
- if (lineIds.length === 0) return;
46347
- console.log("[TargetsView] Starting fetchInitialData");
46264
+ if (lineIds.length === 0 || !companyId) return;
46265
+ console.log("[TargetsView] Starting optimized fetchInitialData with bulk endpoint");
46348
46266
  setIsLoading(true);
46349
- timeoutId = setTimeout(() => {
46350
- console.error("Loading timeout reached");
46351
- if (retryCount < MAX_RETRIES2) {
46352
- retryCount++;
46353
- console.log(`Retrying... (attempt ${retryCount + 1}/${MAX_RETRIES2 + 1})`);
46354
- sonner.toast.warning("Loading is taking longer than expected. Retrying...");
46355
- fetchInitialData();
46356
- } else {
46357
- setIsLoading(false);
46358
- sonner.toast.error("Failed to load data. Please refresh the page.");
46359
- }
46360
- }, LOADING_TIMEOUT);
46361
46267
  try {
46362
- const { data: { session } } = await supabase.auth.getSession();
46363
- if (!session?.access_token) {
46364
- throw new Error("No authentication token available");
46365
- }
46366
- const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
46367
- if (!backendUrl) {
46368
- throw new Error("Backend URL is not configured");
46268
+ const currentDate = getOperationalDate(timezone);
46269
+ const bulkResponse = await workspaceService.fetchBulkTargets({
46270
+ companyId,
46271
+ lineIds,
46272
+ date: currentDate,
46273
+ shifts: [0, 1],
46274
+ // Fetch both shifts at once
46275
+ includeSkus: skuEnabled,
46276
+ includeActions: true
46277
+ });
46278
+ if (!bulkResponse.success) {
46279
+ throw new Error("Failed to fetch bulk targets data");
46369
46280
  }
46370
- const [linesResponse, actions] = await Promise.all([
46371
- // Fetch lines data (includes factory_id)
46372
- Promise.all(lineIds.map(async (lineId) => {
46373
- try {
46374
- const response = await fetch(`${backendUrl}/api/lines/${lineId}`, {
46375
- headers: {
46376
- "Authorization": `Bearer ${session.access_token}`,
46377
- "Content-Type": "application/json"
46378
- }
46379
- });
46380
- if (!response.ok) {
46381
- console.error(`Error fetching line data for ${lineId}:`, response.statusText);
46382
- return { lineId, factoryId: void 0 };
46383
- }
46384
- const lineData = await response.json();
46385
- return { lineId, factoryId: lineData.factory_id };
46386
- } catch (err) {
46387
- console.error(`Exception fetching line data for ${lineId}:`, err);
46388
- return { lineId, factoryId: void 0 };
46389
- }
46390
- })),
46391
- // Fetch action IDs
46392
- actionService.getActionsByName(
46393
- [ACTION_NAMES.ASSEMBLY, ACTION_NAMES.PACKAGING],
46394
- companyId
46395
- )
46396
- ]);
46397
- const factoryResults = linesResponse;
46398
- const assemblyAction = actions.find((a) => a.action_name === ACTION_NAMES.ASSEMBLY);
46399
- const packagingAction = actions.find((a) => a.action_name === ACTION_NAMES.PACKAGING);
46281
+ const { data } = bulkResponse;
46282
+ const assemblyAction = Object.values(data.actions).find((a) => a.action_name === ACTION_NAMES.ASSEMBLY);
46283
+ const packagingAction = Object.values(data.actions).find((a) => a.action_name === ACTION_NAMES.PACKAGING);
46400
46284
  if (!assemblyAction || !packagingAction) {
46401
- throw new Error("Could not find required actions");
46285
+ throw new Error("Could not find required actions in bulk response");
46402
46286
  }
46403
46287
  const actionIdsData = {
46404
46288
  assembly: assemblyAction.id,
46405
46289
  packaging: packagingAction.id
46406
46290
  };
46407
46291
  setActionIds(actionIdsData);
46408
- const updatedLineWorkspaces = { ...initialLineWorkspaces };
46409
- factoryResults.forEach((result) => {
46410
- if (result.factoryId && updatedLineWorkspaces[result.lineId]) {
46411
- updatedLineWorkspaces[result.lineId].factoryId = result.factoryId;
46412
- }
46413
- });
46414
- const currentDate = getOperationalDate(timezone);
46415
- for (const lineId of lineIds) {
46416
- if (!updatedLineWorkspaces[lineId]?.factoryId) {
46417
- console.warn(`Skipping workspace fetch for line ${lineId} - no factory ID`);
46418
- continue;
46419
- }
46420
- try {
46421
- const workspacesData = await workspaceService.getWorkspaces(lineId);
46422
- const enabledWorkspaces = workspacesData.filter((ws) => ws.enable === true);
46423
- const actionThresholds = await workspaceService.getActionThresholds(
46424
- lineId,
46425
- currentDate,
46426
- 0
46427
- // Always use day shift for initial load
46428
- );
46429
- const operatingHoursData = await loadOperatingHours(lineId, 0);
46430
- if (operatingHoursData) {
46431
- updatedLineWorkspaces[lineId].shiftStartTime = operatingHoursData.startTime;
46432
- updatedLineWorkspaces[lineId].shiftEndTime = operatingHoursData.endTime;
46433
- updatedLineWorkspaces[lineId].breaks = operatingHoursData.breaks;
46434
- updatedLineWorkspaces[lineId].shiftHours = calculateShiftHours2(
46435
- operatingHoursData.startTime,
46436
- operatingHoursData.endTime,
46437
- operatingHoursData.breaks
46438
- );
46292
+ const newAllShiftsData = { 0: {}, 1: {} };
46293
+ const newDbValues = { 0: {}, 1: {} };
46294
+ Object.entries(data.lines).forEach(([lineId, lineData]) => {
46295
+ [0, 1].forEach((shiftId) => {
46296
+ const shiftData = lineData.shifts[shiftId.toString()];
46297
+ if (!shiftData) {
46298
+ console.warn(`No shift ${shiftId} data for line ${lineId}`);
46299
+ return;
46439
46300
  }
46301
+ const operatingHours = shiftData.operating_hours || {
46302
+ start_time: "08:00",
46303
+ end_time: "19:00",
46304
+ breaks: [],
46305
+ total_hours: 11
46306
+ };
46307
+ newAllShiftsData[shiftId][lineId] = {
46308
+ productId: "",
46309
+ shiftStartTime: operatingHours.start_time,
46310
+ shiftEndTime: operatingHours.end_time,
46311
+ breaks: operatingHours.breaks,
46312
+ shiftHours: operatingHours.total_hours,
46313
+ workspaces: [],
46314
+ factoryId: lineData.line_info.factory_id
46315
+ };
46316
+ newDbValues[shiftId][lineId] = {};
46317
+ const enabledWorkspaces = lineData.workspaces.filter((ws) => ws.enable === true);
46440
46318
  const mappedWorkspaces = enabledWorkspaces.map((ws) => {
46441
- const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
46442
- if (!dbValues[0][lineId]) {
46443
- dbValues[0][lineId] = {};
46444
- }
46319
+ const threshold = shiftData.thresholds.find((t) => t.workspace_id === ws.id);
46445
46320
  if (threshold) {
46446
- dbValues[0][lineId][ws.id] = {
46447
- targetPPH: threshold.pph_threshold,
46448
- targetCycleTime: threshold.ideal_cycle_time,
46449
- targetDayOutput: threshold.total_day_output
46321
+ newDbValues[shiftId][lineId][ws.id] = {
46322
+ targetPPH: threshold.pph_threshold ? Math.round(threshold.pph_threshold) : "",
46323
+ targetCycleTime: threshold.ideal_cycle_time ?? "",
46324
+ targetDayOutput: threshold.total_day_output ?? ""
46450
46325
  };
46451
46326
  }
46327
+ let actionType = "assembly";
46328
+ let actionId = actionIdsData.assembly;
46329
+ if (ws.action_id === packagingAction.id || ws.action_type === "packaging") {
46330
+ actionType = "packaging";
46331
+ actionId = packagingAction.id;
46332
+ } else if (ws.action_id === assemblyAction.id || ws.action_type === "assembly") {
46333
+ actionType = "assembly";
46334
+ actionId = assemblyAction.id;
46335
+ }
46452
46336
  return {
46453
46337
  id: ws.id,
46454
46338
  name: ws.workspace_id,
46455
- targetPPH: threshold?.pph_threshold ?? (ws.action_pph_threshold === null ? "" : ws.action_pph_threshold),
46456
- targetCycleTime: threshold?.ideal_cycle_time ?? (ws.action_cycle_time === null ? "" : ws.action_cycle_time),
46457
- targetDayOutput: threshold?.total_day_output ?? (ws.action_total_day_output === null ? "" : ws.action_total_day_output),
46458
- actionType: ws.action_id === actionIdsData.assembly ? "assembly" : ws.action_id === actionIdsData.packaging ? "packaging" : "assembly",
46459
- actionId: ws.action_id === actionIdsData.assembly ? actionIdsData.assembly : ws.action_id === actionIdsData.packaging ? actionIdsData.packaging : actionIdsData.assembly
46339
+ targetPPH: threshold?.pph_threshold ? Math.round(threshold.pph_threshold) : "",
46340
+ targetCycleTime: threshold?.ideal_cycle_time ?? "",
46341
+ targetDayOutput: threshold?.total_day_output ?? "",
46342
+ actionType,
46343
+ actionId
46460
46344
  };
46461
46345
  }).sort((a, b) => a.name.localeCompare(b.name, void 0, { numeric: true }));
46462
- updatedLineWorkspaces[lineId].workspaces = mappedWorkspaces;
46463
- } catch (error) {
46464
- console.error(`Error fetching workspace data for line ${lineId}:`, error);
46465
- }
46466
- }
46467
- setLineWorkspaces(updatedLineWorkspaces);
46468
- await fetchAllShiftsData(updatedLineWorkspaces);
46346
+ newAllShiftsData[shiftId][lineId].workspaces = mappedWorkspaces;
46347
+ });
46348
+ });
46349
+ setAllShiftsData(newAllShiftsData);
46350
+ setDbValues(newDbValues);
46351
+ console.log("[TargetsView] Successfully loaded all data with bulk endpoint:", {
46352
+ lineCount: bulkResponse.metadata.line_count,
46353
+ totalWorkspaces: bulkResponse.metadata.total_workspaces,
46354
+ loadTime: "Fast!"
46355
+ });
46469
46356
  } catch (error) {
46470
- console.error("Error fetching initial data:", error);
46471
- clearTimeout(timeoutId);
46472
- if (retryCount < MAX_RETRIES2) {
46473
- retryCount++;
46474
- console.log(`Error occurred, retrying... (attempt ${retryCount + 1}/${MAX_RETRIES2 + 1})`);
46475
- sonner.toast.warning("Error loading data. Retrying...");
46476
- setTimeout(() => fetchInitialData(), 1e3);
46477
- } else {
46478
- sonner.toast.error("Failed to load initial data");
46479
- setIsLoading(false);
46480
- }
46357
+ console.error("[TargetsView] Error fetching bulk data:", error);
46358
+ sonner.toast.error("Failed to load targets data. Please refresh the page.");
46481
46359
  } finally {
46482
- clearTimeout(timeoutId);
46483
- if (retryCount === 0 || retryCount >= MAX_RETRIES2) {
46484
- setIsLoading(false);
46485
- }
46360
+ setIsLoading(false);
46486
46361
  }
46487
46362
  };
46488
46363
  fetchInitialData();
46489
- return () => {
46490
- clearTimeout(timeoutId);
46491
- };
46492
- }, [lineIds, companyId, loadOperatingHours]);
46493
- const fetchAllShiftsData = React23.useCallback(async (currentWorkspaces) => {
46494
- if (!supabase) return;
46495
- const currentDate = getOperationalDate(timezone);
46496
- const newAllShiftsData = {
46497
- 0: JSON.parse(JSON.stringify(currentWorkspaces)),
46498
- // Deep clone for day shift
46499
- 1: JSON.parse(JSON.stringify(currentWorkspaces))
46500
- // Deep clone for night shift
46501
- };
46502
- const newDbValues = { 0: {}, 1: {} };
46503
- for (const shiftId of [0, 1]) {
46504
- for (const lineId of lineIds) {
46505
- try {
46506
- const operatingHoursData = await loadOperatingHours(lineId, shiftId);
46507
- if (!operatingHoursData) {
46508
- console.warn(`No operating hours for line ${lineId}, shift ${shiftId} - using defaults`);
46509
- continue;
46510
- }
46511
- const { startTime, endTime, breaks } = operatingHoursData;
46512
- const shiftHours = calculateShiftHours2(startTime, endTime, breaks);
46513
- const actionThresholds = await workspaceService.getActionThresholds(
46514
- lineId,
46515
- currentDate,
46516
- shiftId
46517
- );
46518
- if (!newDbValues[shiftId][lineId]) {
46519
- newDbValues[shiftId][lineId] = {};
46520
- }
46521
- const existingLine = newAllShiftsData[shiftId][lineId];
46522
- if (existingLine) {
46523
- newAllShiftsData[shiftId][lineId] = {
46524
- ...existingLine,
46525
- shiftStartTime: startTime,
46526
- shiftEndTime: endTime,
46527
- breaks,
46528
- shiftHours: Number(shiftHours),
46529
- workspaces: existingLine.workspaces.map((ws) => {
46530
- const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
46531
- if (threshold) {
46532
- newDbValues[shiftId][lineId][ws.id] = {
46533
- targetPPH: threshold.pph_threshold,
46534
- targetCycleTime: threshold.ideal_cycle_time,
46535
- targetDayOutput: threshold.total_day_output
46536
- };
46537
- return {
46538
- ...ws,
46539
- targetPPH: threshold.pph_threshold,
46540
- targetCycleTime: threshold.ideal_cycle_time,
46541
- targetDayOutput: threshold.total_day_output
46542
- };
46543
- }
46544
- return ws;
46545
- })
46546
- };
46547
- }
46548
- } catch (error) {
46549
- console.error(`Error fetching data for line ${lineId}, shift ${shiftId}:`, error);
46550
- }
46551
- }
46552
- }
46553
- setAllShiftsData(newAllShiftsData);
46554
- setDbValues(newDbValues);
46555
- }, [supabase, lineIds, loadOperatingHours]);
46364
+ }, [lineIds, companyId, timezone, skuEnabled]);
46556
46365
  const toggleLineDropdown = React23.useCallback((lineId) => {
46557
46366
  setDropdownStates((prev) => {
46558
46367
  const newIsOpen = !prev[lineId];
@@ -46625,7 +46434,7 @@ var TargetsView = ({
46625
46434
  if (value !== "") {
46626
46435
  const pph = calculatePPH(value, prev[lineId].breaks, shiftHours);
46627
46436
  updates.targetPPH = pph;
46628
- updates.targetDayOutput = calculateDayOutput(pph, shiftHours, prev[lineId].breaks);
46437
+ updates.targetDayOutput = calculateDayOutputFromCycleTime(value, shiftHours);
46629
46438
  } else {
46630
46439
  updates.targetPPH = "";
46631
46440
  updates.targetDayOutput = "";
@@ -46743,7 +46552,8 @@ var TargetsView = ({
46743
46552
  action_id: ws.actionId,
46744
46553
  workspace_id: ws.id,
46745
46554
  date: currentDate,
46746
- pph_threshold: Number(ws.targetPPH) || 0,
46555
+ pph_threshold: ws.targetPPH ? Math.round(Number(ws.targetPPH)) : 0,
46556
+ // Round to whole number
46747
46557
  ideal_cycle_time: Number(ws.targetCycleTime) || 0,
46748
46558
  total_day_output: Number(ws.targetDayOutput) || 0,
46749
46559
  action_name: ws.actionType === "assembly" ? ACTION_NAMES.ASSEMBLY : ACTION_NAMES.PACKAGING,
@@ -46762,7 +46572,8 @@ var TargetsView = ({
46762
46572
  shift_id: selectedShift,
46763
46573
  product_code: lineDataToSave.productId,
46764
46574
  threshold_day_output: packagingWorkspaces.reduce((acc, ws) => acc + (Number(ws.targetDayOutput) || 0), 0),
46765
- threshold_pph: packagingWorkspaces.reduce((acc, ws) => acc + (Number(ws.targetPPH) || 0), 0),
46575
+ threshold_pph: packagingWorkspaces.reduce((acc, ws) => acc + (ws.targetPPH ? Math.round(Number(ws.targetPPH)) : 0), 0),
46576
+ // Round each PPH value
46766
46577
  ...skuEnabled && lineDataToSave.selectedSKU ? { sku_id: lineDataToSave.selectedSKU.id } : {}
46767
46578
  };
46768
46579
  console.log(`[handleSaveLine] lineThresholdData for upsert on ${lineId}:`, lineThresholdData);
@@ -48514,94 +48325,14 @@ var SupervisorManagementView = ({
48514
48325
  ] });
48515
48326
  };
48516
48327
  var SupervisorManagementView_default = SupervisorManagementView;
48517
- var roleChangeImpacts = {
48518
- supervisor_to_plant_head: {
48519
- title: "Supervisor \u2192 Plant Head",
48520
- warnings: [
48521
- "Will lose line-specific assignments",
48522
- "Will need factory assignment",
48523
- "Will gain ability to manage supervisors",
48524
- "Will see factory-wide data"
48525
- ],
48526
- colorClass: "text-blue-700 bg-blue-50 border-blue-200"
48527
- },
48528
- supervisor_to_owner: {
48529
- title: "Supervisor \u2192 Owner",
48530
- warnings: [
48531
- "Will gain full company access",
48532
- "Will lose line-specific restrictions",
48533
- "Will be able to manage all users",
48534
- "Will see all company data"
48535
- ],
48536
- colorClass: "text-red-700 bg-red-50 border-red-200"
48537
- },
48538
- plant_head_to_supervisor: {
48539
- title: "Plant Head \u2192 Supervisor",
48540
- warnings: [
48541
- "Will lose factory access",
48542
- "Will lose ability to manage others",
48543
- "Will need line assignment",
48544
- "Will only see assigned line data"
48545
- ],
48546
- colorClass: "text-orange-700 bg-orange-50 border-orange-200"
48547
- },
48548
- plant_head_to_owner: {
48549
- title: "Plant Head \u2192 Owner",
48550
- warnings: [
48551
- "Will gain full company access",
48552
- "Will lose factory-specific restrictions",
48553
- "Will be able to manage all users",
48554
- "Will see all company data"
48555
- ],
48556
- colorClass: "text-blue-700 bg-blue-50 border-blue-200"
48557
- },
48558
- owner_to_plant_head: {
48559
- title: "Owner \u2192 Plant Head",
48560
- warnings: [
48561
- "Will lose company-wide access",
48562
- "Will need factory assignment",
48563
- "Will only manage supervisors",
48564
- "Will only see factory data"
48565
- ],
48566
- colorClass: "text-orange-700 bg-orange-50 border-orange-200"
48567
- },
48568
- owner_to_supervisor: {
48569
- title: "Owner \u2192 Supervisor",
48570
- warnings: [
48571
- "Will lose company-wide access",
48572
- "Will lose ability to manage others",
48573
- "Will need line assignment",
48574
- "Will only see assigned line data"
48575
- ],
48576
- colorClass: "text-red-700 bg-red-50 border-red-200"
48577
- },
48578
- to_optifye: {
48579
- title: "Promoting to Optifye",
48580
- warnings: [
48581
- "Will gain access to ALL companies",
48582
- "Will be able to manage all users globally",
48583
- "Will see all data across the platform",
48584
- "This is the highest privilege level"
48585
- ],
48586
- colorClass: "text-purple-700 bg-purple-50 border-purple-200"
48587
- },
48588
- from_optifye: {
48589
- title: "Demoting from Optifye",
48590
- warnings: [
48591
- "Will lose access to other companies",
48592
- "Will only see assigned company data",
48593
- "Will lose global management capabilities",
48594
- "Will need appropriate assignments"
48595
- ],
48596
- colorClass: "text-red-700 bg-red-50 border-red-200"
48597
- }
48598
- };
48599
- var getRoleChangeKey = (currentRole, newRole) => {
48600
- if (currentRole === newRole) return null;
48601
- if (newRole === "optifye") return "to_optifye";
48602
- if (currentRole === "optifye") return "from_optifye";
48603
- const key = `${currentRole}_to_${newRole}`;
48604
- return roleChangeImpacts[key] ? key : null;
48328
+ var getRoleLabel = (role) => {
48329
+ const labels = {
48330
+ "supervisor": "Supervisor",
48331
+ "plant_head": "Plant Head",
48332
+ "owner": "Owner",
48333
+ "optifye": "Optifye Admin"
48334
+ };
48335
+ return labels[role] || role;
48605
48336
  };
48606
48337
  var ChangeRoleDialog = ({
48607
48338
  user,
@@ -48614,8 +48345,6 @@ var ChangeRoleDialog = ({
48614
48345
  const [confirmed, setConfirmed] = React23.useState(false);
48615
48346
  const [isChanging, setIsChanging] = React23.useState(false);
48616
48347
  const roleChanged = selectedRole !== user.role_level;
48617
- const changeKey = roleChanged ? getRoleChangeKey(user.role_level, selectedRole) : null;
48618
- const impactInfo = changeKey ? roleChangeImpacts[changeKey] : null;
48619
48348
  const handleNext = () => {
48620
48349
  if (roleChanged) {
48621
48350
  setStep("confirm");
@@ -48635,7 +48364,7 @@ var ChangeRoleDialog = ({
48635
48364
  setStep("select");
48636
48365
  setConfirmed(false);
48637
48366
  };
48638
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-xl max-w-md w-full mx-4", children: [
48367
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-xl shadow-2xl max-w-md w-full mx-4 transform transition-all", children: [
48639
48368
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-6 border-b border-gray-200", children: [
48640
48369
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
48641
48370
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 bg-blue-100 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserCog, { className: "w-5 h-5 text-blue-600" }) }),
@@ -48645,20 +48374,14 @@ var ChangeRoleDialog = ({
48645
48374
  "button",
48646
48375
  {
48647
48376
  onClick: onClose,
48648
- className: "text-gray-400 hover:text-gray-600 transition-colors",
48377
+ className: "text-gray-400 hover:text-gray-600 transition-colors p-1 hover:bg-gray-100 rounded-lg",
48649
48378
  disabled: isChanging,
48379
+ "aria-label": "Close dialog",
48650
48380
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-5 h-5" })
48651
48381
  }
48652
48382
  )
48653
48383
  ] }),
48654
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 space-y-6", children: step === "select" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
48655
- roleChanged && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-4 bg-amber-50 border border-amber-200 rounded-lg", children: [
48656
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-5 h-5 text-amber-600 mt-0.5 flex-shrink-0" }),
48657
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
48658
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-amber-900 text-sm", children: "Changing roles affects access" }),
48659
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-amber-700 text-sm mt-1", children: "Review the impact carefully before confirming." })
48660
- ] })
48661
- ] }),
48384
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 space-y-5", children: step === "select" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
48662
48385
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
48663
48386
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: "User" }),
48664
48387
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3 bg-gray-50 rounded-lg", children: [
@@ -48669,7 +48392,7 @@ var ChangeRoleDialog = ({
48669
48392
  ] })
48670
48393
  ] })
48671
48394
  ] }),
48672
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
48395
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
48673
48396
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "Select new role" }),
48674
48397
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: availableRoles.map((role) => /* @__PURE__ */ jsxRuntime.jsxs(
48675
48398
  "label",
@@ -48693,27 +48416,24 @@ var ChangeRoleDialog = ({
48693
48416
  role
48694
48417
  )) })
48695
48418
  ] }),
48696
- impactInfo && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-4 border rounded-lg ${impactInfo.colorClass}`, children: [
48697
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-sm mb-2", children: "\u2139\uFE0F Impact of this change:" }),
48698
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1.5 text-sm", children: impactInfo.warnings.map((warning6, idx) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2", children: [
48699
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5", children: "\u2022" }),
48700
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: warning6 })
48701
- ] }, idx)) })
48702
- ] })
48419
+ roleChanged && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 bg-gray-50 border border-gray-200 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-600", children: [
48420
+ "Changing from ",
48421
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-900", children: getRoleLabel(user.role_level) }),
48422
+ " to ",
48423
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-900", children: getRoleLabel(selectedRole) }),
48424
+ " will modify user permissions."
48425
+ ] }) })
48703
48426
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
48704
48427
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-3 p-4 bg-gray-50 rounded-lg", children: [
48705
48428
  /* @__PURE__ */ jsxRuntime.jsx(RoleBadge, { role: user.role_level }),
48706
48429
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-5 h-5 text-gray-400" }),
48707
48430
  /* @__PURE__ */ jsxRuntime.jsx(RoleBadge, { role: selectedRole })
48708
48431
  ] }),
48709
- impactInfo && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-4 border rounded-lg ${impactInfo.colorClass}`, children: [
48710
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-sm mb-3", children: impactInfo.title }),
48711
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-2 text-sm", children: impactInfo.warnings.map((warning6, idx) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2", children: [
48712
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5", children: "\u2022" }),
48713
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: warning6 })
48714
- ] }, idx)) })
48432
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
48433
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: "User" }),
48434
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900", children: user.email })
48715
48435
  ] }),
48716
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-4 border border-gray-200 rounded-lg", children: [
48436
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-3 border border-gray-200 rounded-lg bg-gray-50", children: [
48717
48437
  /* @__PURE__ */ jsxRuntime.jsx(
48718
48438
  "input",
48719
48439
  {
@@ -48724,7 +48444,7 @@ var ChangeRoleDialog = ({
48724
48444
  className: "mt-0.5 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
48725
48445
  }
48726
48446
  ),
48727
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "confirm-role-change", className: "text-sm text-gray-700 cursor-pointer", children: "I understand this will change the user's access and responsibilities" })
48447
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "confirm-role-change", className: "text-sm text-gray-700 cursor-pointer", children: "I confirm this role change and understand the permissions will be updated" })
48728
48448
  ] })
48729
48449
  ] }) }) }),
48730
48450
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end gap-3 p-6 border-t border-gray-200 bg-gray-50", children: step === "select" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -48767,7 +48487,7 @@ var ChangeRoleDialog = ({
48767
48487
  /* @__PURE__ */ jsxRuntime.jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
48768
48488
  ] }),
48769
48489
  "Changing..."
48770
- ] }) : "Change Role"
48490
+ ] }) : "Confirm Change"
48771
48491
  }
48772
48492
  )
48773
48493
  ] }) })
@@ -48790,32 +48510,34 @@ var ConfirmRemoveUserDialog = ({
48790
48510
  setIsRemoving(false);
48791
48511
  }
48792
48512
  };
48793
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-xl max-w-md w-full mx-4", children: [
48513
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-xl shadow-2xl max-w-md w-full mx-4 transform transition-all", children: [
48794
48514
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-6 border-b border-gray-200", children: [
48795
48515
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
48796
48516
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 bg-red-100 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-5 h-5 text-red-600" }) }),
48797
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Remove User" })
48517
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Permanently Delete User" })
48798
48518
  ] }),
48799
48519
  /* @__PURE__ */ jsxRuntime.jsx(
48800
48520
  "button",
48801
48521
  {
48802
48522
  onClick: onCancel,
48803
- className: "text-gray-400 hover:text-gray-600 transition-colors",
48523
+ className: "text-gray-400 hover:text-gray-600 transition-colors p-1 hover:bg-gray-100 rounded-lg",
48524
+ disabled: isRemoving,
48525
+ "aria-label": "Close dialog",
48804
48526
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-5 h-5" })
48805
48527
  }
48806
48528
  )
48807
48529
  ] }),
48808
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-6", children: [
48809
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-4 bg-red-50 border border-red-200 rounded-lg", children: [
48810
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "w-5 h-5 text-red-600 mt-0.5 flex-shrink-0" }),
48811
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
48812
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-red-900 text-sm", children: "This action cannot be undone" }),
48813
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-red-700 text-sm mt-1", children: "The user will immediately lose all access to the platform." })
48530
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-5", children: [
48531
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-3 bg-red-50 border border-red-200 rounded-lg", children: [
48532
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "w-4 h-4 text-red-600 mt-0.5 flex-shrink-0" }),
48533
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-red-900", children: [
48534
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "This action cannot be undone." }),
48535
+ " This will permanently delete the user and all related data from the system."
48814
48536
  ] })
48815
48537
  ] }),
48816
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
48817
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "You are about to remove:" }),
48818
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 bg-gray-50 rounded-lg space-y-2", children: [
48538
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
48539
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "You are about to permanently delete:" }),
48540
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3 bg-gray-50 rounded-lg space-y-2.5", children: [
48819
48541
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
48820
48542
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-600", children: "Email" }),
48821
48543
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-900", children: user.email })
@@ -48840,28 +48562,7 @@ var ConfirmRemoveUserDialog = ({
48840
48562
  ] })
48841
48563
  ] })
48842
48564
  ] }),
48843
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
48844
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "This will:" }),
48845
- /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "space-y-2 text-sm text-gray-600", children: [
48846
- /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2", children: [
48847
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 mt-0.5", children: "\u2022" }),
48848
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Revoke all access immediately" })
48849
- ] }),
48850
- /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2", children: [
48851
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 mt-0.5", children: "\u2022" }),
48852
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Remove all line and factory assignments" })
48853
- ] }),
48854
- /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2", children: [
48855
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 mt-0.5", children: "\u2022" }),
48856
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Log the user out of all sessions" })
48857
- ] }),
48858
- /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2", children: [
48859
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 mt-0.5", children: "\u2022" }),
48860
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "User will not be able to access the dashboard" })
48861
- ] })
48862
- ] })
48863
- ] }),
48864
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-4 border border-gray-200 rounded-lg", children: [
48565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 p-3 border border-gray-200 rounded-lg bg-gray-50", children: [
48865
48566
  /* @__PURE__ */ jsxRuntime.jsx(
48866
48567
  "input",
48867
48568
  {
@@ -48872,7 +48573,7 @@ var ConfirmRemoveUserDialog = ({
48872
48573
  className: "mt-0.5 h-4 w-4 text-red-600 border-gray-300 rounded focus:ring-red-500"
48873
48574
  }
48874
48575
  ),
48875
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "confirm-remove", className: "text-sm text-gray-700 cursor-pointer", children: "I understand this action is permanent and cannot be undone" })
48576
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "confirm-remove", className: "text-sm text-gray-700 cursor-pointer", children: "I understand this will permanently delete the user and all related data, and this action cannot be undone" })
48876
48577
  ] })
48877
48578
  ] }),
48878
48579
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-3 p-6 border-t border-gray-200 bg-gray-50", children: [
@@ -48896,8 +48597,8 @@ var ConfirmRemoveUserDialog = ({
48896
48597
  /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
48897
48598
  /* @__PURE__ */ jsxRuntime.jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
48898
48599
  ] }),
48899
- "Removing..."
48900
- ] }) : "Remove User"
48600
+ "Deleting..."
48601
+ ] }) : "Delete User"
48901
48602
  }
48902
48603
  )
48903
48604
  ] })
@@ -49320,7 +49021,6 @@ var FactoryAssignmentDropdown = ({
49320
49021
  var UserManagementTable = ({
49321
49022
  users,
49322
49023
  isLoading = false,
49323
- onUserClick,
49324
49024
  onRoleChange,
49325
49025
  onRemoveUser,
49326
49026
  onLineAssignmentUpdate,
@@ -49346,9 +49046,48 @@ var UserManagementTable = ({
49346
49046
  const [sortField, setSortField] = React23.useState("email");
49347
49047
  const [sortDirection, setSortDirection] = React23.useState("asc");
49348
49048
  const [openActionMenuId, setOpenActionMenuId] = React23.useState(null);
49049
+ const [dropdownPosition, setDropdownPosition] = React23.useState(null);
49050
+ const actionButtonRefs = React23.useRef({});
49349
49051
  const [selectedUser, setSelectedUser] = React23.useState(null);
49350
49052
  const [showChangeRoleDialog, setShowChangeRoleDialog] = React23.useState(false);
49351
49053
  const [showRemoveUserDialog, setShowRemoveUserDialog] = React23.useState(false);
49054
+ const handleOpenActionMenu = (userId) => {
49055
+ const buttonRef = actionButtonRefs.current[userId];
49056
+ if (buttonRef) {
49057
+ const rect = buttonRef.getBoundingClientRect();
49058
+ setDropdownPosition({
49059
+ top: rect.bottom + 8,
49060
+ // 8px below the button
49061
+ left: rect.right - 192
49062
+ // 192px is the dropdown width (w-48 = 12rem = 192px)
49063
+ });
49064
+ setOpenActionMenuId(userId);
49065
+ }
49066
+ };
49067
+ const handleCloseActionMenu = () => {
49068
+ setOpenActionMenuId(null);
49069
+ setDropdownPosition(null);
49070
+ };
49071
+ React23.useEffect(() => {
49072
+ if (openActionMenuId && actionButtonRefs.current[openActionMenuId]) {
49073
+ const updatePosition = () => {
49074
+ const buttonRef = actionButtonRefs.current[openActionMenuId];
49075
+ if (buttonRef) {
49076
+ const rect = buttonRef.getBoundingClientRect();
49077
+ setDropdownPosition({
49078
+ top: rect.bottom + 8,
49079
+ left: rect.right - 192
49080
+ });
49081
+ }
49082
+ };
49083
+ window.addEventListener("scroll", updatePosition, true);
49084
+ window.addEventListener("resize", updatePosition);
49085
+ return () => {
49086
+ window.removeEventListener("scroll", updatePosition, true);
49087
+ window.removeEventListener("resize", updatePosition);
49088
+ };
49089
+ }
49090
+ }, [openActionMenuId]);
49352
49091
  const filteredAndSortedUsers = React23.useMemo(() => {
49353
49092
  let filtered = users;
49354
49093
  filtered = filtered.filter((user) => availableRoles.includes(user.role_level));
@@ -49539,7 +49278,7 @@ var UserManagementTable = ({
49539
49278
  LineAssignmentDropdown,
49540
49279
  {
49541
49280
  userId: user.user_id,
49542
- currentLineIds: user.properties?.line_id || [],
49281
+ currentLineIds: user.properties?.line_ids || [],
49543
49282
  availableLines: (
49544
49283
  // Filter lines to only show those from the target user's company
49545
49284
  (() => {
@@ -49577,69 +49316,24 @@ var UserManagementTable = ({
49577
49316
  }
49578
49317
  ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-900", children: formatAssignments(user) }) }),
49579
49318
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: formatDate(user.created_at) }) }),
49580
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right", children: hasActions && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
49581
- /* @__PURE__ */ jsxRuntime.jsx(
49582
- "button",
49583
- {
49584
- onClick: () => setOpenActionMenuId(openActionMenuId === user.user_id ? null : user.user_id),
49585
- className: "p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors",
49586
- "aria-label": "User actions",
49587
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { className: "w-4 h-4" })
49588
- }
49589
- ),
49590
- openActionMenuId === user.user_id && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49591
- /* @__PURE__ */ jsxRuntime.jsx(
49592
- "div",
49593
- {
49594
- className: "fixed inset-0 z-[9998]",
49595
- onClick: () => setOpenActionMenuId(null)
49319
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right", children: hasActions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx(
49320
+ "button",
49321
+ {
49322
+ ref: (el) => {
49323
+ actionButtonRefs.current[user.user_id] = el;
49324
+ },
49325
+ onClick: () => {
49326
+ if (openActionMenuId === user.user_id) {
49327
+ handleCloseActionMenu();
49328
+ } else {
49329
+ handleOpenActionMenu(user.user_id);
49596
49330
  }
49597
- ),
49598
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 z-[9999]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
49599
- /* @__PURE__ */ jsxRuntime.jsxs(
49600
- "button",
49601
- {
49602
- onClick: () => {
49603
- onUserClick?.(user);
49604
- setOpenActionMenuId(null);
49605
- },
49606
- className: "w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100 flex items-center gap-2",
49607
- children: [
49608
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-4 h-4" }),
49609
- "View Details"
49610
- ]
49611
- }
49612
- ),
49613
- canChangeRole && /* @__PURE__ */ jsxRuntime.jsxs(
49614
- "button",
49615
- {
49616
- onClick: () => handleChangeRole(user),
49617
- className: "w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100 flex items-center gap-2",
49618
- disabled: isCurrentUser,
49619
- children: [
49620
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserCog, { className: "w-4 h-4" }),
49621
- "Change Role"
49622
- ]
49623
- }
49624
- ),
49625
- canRemove && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49626
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-200 my-1" }),
49627
- /* @__PURE__ */ jsxRuntime.jsxs(
49628
- "button",
49629
- {
49630
- onClick: () => handleRemoveUser(user),
49631
- className: "w-full px-4 py-2 text-sm text-left text-red-600 hover:bg-red-50 flex items-center gap-2",
49632
- disabled: isCurrentUser,
49633
- children: [
49634
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-4 h-4" }),
49635
- "Remove User"
49636
- ]
49637
- }
49638
- )
49639
- ] })
49640
- ] }) })
49641
- ] })
49642
- ] }) })
49331
+ },
49332
+ className: "p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors",
49333
+ "aria-label": "User actions",
49334
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { className: "w-4 h-4" })
49335
+ }
49336
+ ) }) })
49643
49337
  ]
49644
49338
  },
49645
49339
  user.user_id
@@ -49647,6 +49341,75 @@ var UserManagementTable = ({
49647
49341
  }) })
49648
49342
  ] }) }) })
49649
49343
  ] }),
49344
+ openActionMenuId && dropdownPosition && typeof document !== "undefined" && reactDom.createPortal(
49345
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49346
+ /* @__PURE__ */ jsxRuntime.jsx(
49347
+ "div",
49348
+ {
49349
+ className: "fixed inset-0 z-[9998]",
49350
+ onClick: handleCloseActionMenu
49351
+ }
49352
+ ),
49353
+ /* @__PURE__ */ jsxRuntime.jsx(
49354
+ "div",
49355
+ {
49356
+ className: "fixed w-48 bg-white rounded-lg shadow-lg border border-gray-200 z-[9999]",
49357
+ style: {
49358
+ top: `${dropdownPosition.top}px`,
49359
+ left: `${dropdownPosition.left}px`
49360
+ },
49361
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
49362
+ (() => {
49363
+ const user = users.find((u) => u.user_id === openActionMenuId);
49364
+ const isCurrentUser = user?.user_id === currentUserId;
49365
+ const canChangeRole = user && permissions.canChangeRole(user);
49366
+ return canChangeRole && /* @__PURE__ */ jsxRuntime.jsxs(
49367
+ "button",
49368
+ {
49369
+ onClick: () => {
49370
+ if (user) {
49371
+ handleChangeRole(user);
49372
+ }
49373
+ },
49374
+ className: "w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
49375
+ disabled: isCurrentUser,
49376
+ children: [
49377
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserCog, { className: "w-4 h-4" }),
49378
+ "Change Role"
49379
+ ]
49380
+ }
49381
+ );
49382
+ })(),
49383
+ (() => {
49384
+ const user = users.find((u) => u.user_id === openActionMenuId);
49385
+ const isCurrentUser = user?.user_id === currentUserId;
49386
+ const canRemove = user && permissions.canRemoveUser(user);
49387
+ return canRemove && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49388
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-200 my-1" }),
49389
+ /* @__PURE__ */ jsxRuntime.jsxs(
49390
+ "button",
49391
+ {
49392
+ onClick: () => {
49393
+ if (user) {
49394
+ handleRemoveUser(user);
49395
+ }
49396
+ },
49397
+ className: "w-full px-4 py-2 text-sm text-left text-red-600 hover:bg-red-50 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
49398
+ disabled: isCurrentUser,
49399
+ children: [
49400
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-4 h-4" }),
49401
+ "Delete User"
49402
+ ]
49403
+ }
49404
+ )
49405
+ ] });
49406
+ })()
49407
+ ] })
49408
+ }
49409
+ )
49410
+ ] }),
49411
+ document.body
49412
+ ),
49650
49413
  showChangeRoleDialog && selectedUser && /* @__PURE__ */ jsxRuntime.jsx(
49651
49414
  ChangeRoleDialog,
49652
49415
  {
@@ -50298,15 +50061,12 @@ var TeamManagementView = ({
50298
50061
  if (!supabase || !user) return;
50299
50062
  try {
50300
50063
  const userManagementService = createUserManagementService(supabase);
50301
- await userManagementService.deactivateUser({
50302
- user_id: userId,
50303
- deactivated_by: user.id
50304
- });
50305
- sonner.toast.success("User removed successfully");
50064
+ const result = await userManagementService.deleteUser(userId);
50065
+ sonner.toast.success(`User ${result.deleted_user_email} permanently deleted`);
50306
50066
  loadData();
50307
50067
  } catch (err) {
50308
- console.error("Error removing user:", err);
50309
- sonner.toast.error("Failed to remove user");
50068
+ console.error("Error deleting user:", err);
50069
+ sonner.toast.error("Failed to delete user");
50310
50070
  }
50311
50071
  }, [supabase, user, loadData]);
50312
50072
  const handleLineAssignmentUpdate = React23.useCallback(async (userId, lineIds) => {
@@ -50400,9 +50160,6 @@ var TeamManagementView = ({
50400
50160
  {
50401
50161
  users,
50402
50162
  currentUserId: user?.id,
50403
- onUserClick: (clickedUser) => {
50404
- console.log("View user details:", clickedUser);
50405
- },
50406
50163
  onRoleChange: handleRoleChange,
50407
50164
  onRemoveUser: handleRemoveUser,
50408
50165
  onLineAssignmentUpdate: handleLineAssignmentUpdate,