andoncloud-station-assignment-widget 1.0.8 → 1.0.9

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.ts CHANGED
@@ -24,7 +24,7 @@ declare const getDisplayName: (lang: string) => string;
24
24
  declare const getTitle: (data: WidgetData | undefined, _settings: WidgetSettings | undefined, _filters: FilterValues | undefined, lang: string) => string;
25
25
  //#endregion
26
26
  //#region src/version.d.ts
27
- declare const LIBRARY_VERSION = "1.0.8";
27
+ declare const LIBRARY_VERSION = "1.0.9";
28
28
  //#endregion
29
29
  //#region src/index.d.ts
30
30
  declare const thumbnail: string | undefined;
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { registerTranslations } from "andoncloud-sdk";
1
2
  import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
2
3
  import { PresenceStatusEnum, WorkplaceEvent, WorkplaceEventDocument, getCurrentShift, normalizeShifts, useGqlClients } from "andoncloud-dashboard-toolkit";
3
4
  import { BaseWidget } from "andoncloud-widget-base";
@@ -213,7 +214,7 @@ const navigateState = (currentState, shifts, direction) => {
213
214
  };
214
215
  //#endregion
215
216
  //#region src/version.ts
216
- const LIBRARY_VERSION = "1.0.8";
217
+ const LIBRARY_VERSION = "1.0.9";
217
218
  //#endregion
218
219
  //#region src/components/SettingsFormContent/index.tsx
219
220
  const SettingsFormContent = ({ data, formProps }) => {
@@ -1503,6 +1504,7 @@ const getTitle = (data, _settings, _filters, lang) => {
1503
1504
  };
1504
1505
  //#endregion
1505
1506
  //#region src/index.tsx
1507
+ registerTranslations(resources);
1506
1508
  const thumbnail = void 0;
1507
1509
  const requiredFeatures = ["feature.station-assignment-widget"];
1508
1510
  const extraPermissions = [];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["en","pl","presenceColors","styles","styles","styles","styles","styles","styles","styles","styles","styles","styles","styles","styles","locales"],"sources":["../src/locales/en/translation.json","../src/locales/pl/translation.json","../src/locales/index.ts","../src/utils/state.ts","../src/version.ts","../src/components/SettingsFormContent/index.tsx","../src/components/AssignmentBoard/helpers.ts","../src/components/AssignmentBoard/OperatorCard/SidePanel/styles.ts","../src/components/AssignmentBoard/OperatorCard/SidePanel/MainContent.tsx","../src/components/AssignmentBoard/DropZone/styles.ts","../src/components/AssignmentBoard/DropZone/index.tsx","../src/components/AssignmentBoard/OperatorCard/styles.ts","../src/components/AssignmentBoard/OperatorCard/index.tsx","../src/components/AssignmentBoard/PoolColumn/styles.ts","../src/components/AssignmentBoard/PoolColumn/index.tsx","../src/components/AssignmentBoard/WorkplaceColumn/styles.ts","../src/components/AssignmentBoard/WorkplaceColumn/index.tsx","../src/components/AssignmentBoard/styles.ts","../src/components/AssignmentBoard/index.tsx","../src/components/Navigation/styles.ts","../src/components/Navigation/index.tsx","../src/components/WidgetView/styles.ts","../src/components/WidgetView/index.tsx","../src/components/Widget/utils.ts","../src/components/Widget/index.tsx","../src/core/title.ts","../src/index.tsx"],"sourcesContent":["","","import en from './en/translation.json';\nimport pl from './pl/translation.json';\n\nconst resources = {\n en: {\n translation: en,\n },\n pl: {\n translation: pl,\n },\n};\n\nexport default resources;\n","import { getCurrentShift, ListShifts_Shift, normalizeShifts } from 'andoncloud-dashboard-toolkit';\nimport dayjs from 'dayjs';\n\nimport { ViewState } from '@/types';\n\nconst DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';\n\nconst sortShifts = (shifts: ListShifts_Shift[]): ListShifts_Shift[] => [...shifts].sort((a, b) => a.startedAt.localeCompare(b.startedAt));\n\nconst findShiftByName = (shifts: ListShifts_Shift[], name: string) => shifts.find((s) => s.name === name);\n\nexport const makeShiftDateTime = (date: string, shift: ListShifts_Shift): string => {\n const shiftStart = dayjs(shift.startedAt);\n return dayjs(date).hour(shiftStart.hour()).minute(shiftStart.minute()).second(0).format(DATETIME_FORMAT);\n};\n\nexport const extractDate = (dateTime: string): string => dayjs(dateTime).format('YYYY-MM-DD');\n\nconst getMinDate = (shifts: ListShifts_Shift[]): string => {\n const now = dayjs();\n const normalizedShifts = normalizeShifts(shifts, now);\n const currentShift = getCurrentShift(now, normalizedShifts);\n return (currentShift?.startedAt || now).format('YYYY-MM-DD');\n};\n\nexport const getInitialState = (shifts: ListShifts_Shift[]): ViewState | null => {\n const sortedShifts = sortShifts(shifts);\n const now = dayjs();\n const today = now.format('YYYY-MM-DD');\n const normalizedShifts = normalizeShifts(sortedShifts, now);\n\n const currentNormalizedShift = getCurrentShift(now, normalizedShifts);\n\n if (currentNormalizedShift) {\n const shift = findShiftByName(sortedShifts, currentNormalizedShift.name);\n if (shift) {\n return { date: currentNormalizedShift.startedAt.format(DATETIME_FORMAT), shift, isCurrentShift: true };\n }\n }\n\n const nextNormalizedShift = normalizedShifts.find((s) => s.startedAt.isAfter(now));\n\n if (nextNormalizedShift) {\n const shift = findShiftByName(sortedShifts, nextNormalizedShift.name);\n if (shift) {\n return { date: makeShiftDateTime(today, shift), shift, isCurrentShift: false };\n }\n }\n\n const tomorrow = dayjs(now).add(1, 'day').startOf('day');\n const tomorrowNormalizedShifts = normalizeShifts(sortedShifts, tomorrow);\n\n if (tomorrowNormalizedShifts.length > 0) {\n const shift = findShiftByName(sortedShifts, tomorrowNormalizedShifts[0].name);\n if (shift) {\n return { date: makeShiftDateTime(tomorrow.format('YYYY-MM-DD'), shift), shift, isCurrentShift: false };\n }\n }\n\n return null;\n};\n\nconst MAX_DAYS_FORWARD = 14;\n\nexport const canNavigate = (currentState: ViewState, shifts: ListShifts_Shift[], direction: 'prev' | 'next'): boolean => {\n const sortedShifts = sortShifts(shifts);\n const currentDate = extractDate(currentState.date);\n const minDate = getMinDate(sortedShifts);\n const maxDate = dayjs().add(MAX_DAYS_FORWARD, 'day').format('YYYY-MM-DD');\n const currentIndex = sortedShifts.findIndex((s) => s.id === currentState.shift.id);\n\n if (direction === 'next') {\n if (currentIndex < sortedShifts.length - 1) {\n return true;\n }\n const nextDate = dayjs(currentDate).add(1, 'day').format('YYYY-MM-DD');\n return nextDate <= maxDate;\n }\n\n if (currentIndex > 0) {\n return currentDate >= minDate;\n }\n const prevDate = dayjs(currentDate).subtract(1, 'day').format('YYYY-MM-DD');\n return prevDate >= minDate;\n};\n\nexport const navigateState = (currentState: ViewState, shifts: ListShifts_Shift[], direction: 'prev' | 'next'): ViewState => {\n const sortedShifts = sortShifts(shifts);\n if (!canNavigate(currentState, sortedShifts, direction)) {\n return currentState;\n }\n\n const currentDate = extractDate(currentState.date);\n const currentIndex = sortedShifts.findIndex((s) => s.id === currentState.shift.id);\n\n const checkIsCurrent = (date: string, shift: ListShifts_Shift): boolean => {\n const now = dayjs();\n const normalizedShifts = normalizeShifts(sortedShifts, now);\n const currentNormalized = getCurrentShift(now, normalizedShifts);\n if (!currentNormalized || currentNormalized.name !== shift.name) return false;\n return currentNormalized.startedAt.format('YYYY-MM-DD') === dayjs(date).format('YYYY-MM-DD');\n };\n\n if (direction === 'next') {\n if (currentIndex < sortedShifts.length - 1) {\n const shift = sortedShifts[currentIndex + 1];\n const date = makeShiftDateTime(currentDate, shift);\n return { date, shift, isCurrentShift: checkIsCurrent(date, shift) };\n }\n const nextDate = dayjs(currentDate).add(1, 'day').format('YYYY-MM-DD');\n const shift = sortedShifts[0];\n return { date: makeShiftDateTime(nextDate, shift), shift, isCurrentShift: false };\n }\n\n if (currentIndex > 0) {\n const shift = sortedShifts[currentIndex - 1];\n const date = makeShiftDateTime(currentDate, shift);\n return { date, shift, isCurrentShift: checkIsCurrent(date, shift) };\n }\n const prevDate = dayjs(currentDate).subtract(1, 'day').format('YYYY-MM-DD');\n const shift = sortedShifts[sortedShifts.length - 1];\n return { date: makeShiftDateTime(prevDate, shift), shift, isCurrentShift: false };\n};\n","export const LIBRARY_VERSION = '1.0.8';\n","import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { TabContext, TabList, TabPanel } from '@mui/lab';\nimport { FormControl, InputLabel, MenuItem, Select, Tab, TextField } from '@mui/material';\nimport { SettingsFormContentProps } from 'andoncloud-widget-base';\n\nimport { WidgetData, WidgetSettings } from '@/types';\n\nconst SettingsFormContent: React.FC<SettingsFormContentProps<WidgetData, WidgetSettings>> = ({ data, formProps }) => {\n // -- Local state --\n const [selectedTab, setSelectedTab] = useState('filters');\n\n // -- Translation --\n const { t } = useTranslation();\n\n return (\n <TabContext value={selectedTab}>\n <TabList onChange={(_, value) => setSelectedTab(value)} centered>\n <Tab label={t('stationAssignmentWidget.settingsFiltersTab')} value=\"filters\" />\n <Tab label={t('stationAssignmentWidget.advanced')} value=\"advanced\" />\n </TabList>\n\n <TabPanel value=\"filters\">\n <FormControl fullWidth>\n <InputLabel id=\"department-label\">{t('stationAssignmentWidget.department')}</InputLabel>\n <Select\n name=\"departmentId\"\n labelId=\"department-label\"\n variant=\"outlined\"\n value={formProps.values.departmentId ?? ''}\n onChange={formProps.handleChange}\n fullWidth\n >\n <MenuItem value=\"\">{t('stationAssignmentWidget.allDepartments')}</MenuItem>\n {data.departments.map((department) => (\n <MenuItem key={department.id} value={department.id}>\n {department.name}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n <FormControl sx={{ mt: 2 }} fullWidth>\n <InputLabel id=\"refresh-interval-label\">{t('stationAssignmentWidget.refreshInterval')}</InputLabel>\n <Select\n name=\"refreshInterval\"\n labelId=\"refresh-interval-label\"\n variant=\"outlined\"\n value={formProps.values.refreshInterval}\n onChange={formProps.handleChange}\n fullWidth\n >\n <MenuItem value={15}>15s</MenuItem>\n <MenuItem value={30}>30s</MenuItem>\n <MenuItem value={60}>60s</MenuItem>\n </Select>\n </FormControl>\n </TabPanel>\n\n <TabPanel value=\"advanced\">\n <TextField\n name=\"customTitle\"\n label={t('stationAssignmentWidget.customTitle')}\n value={formProps.values.customTitle}\n onChange={formProps.handleChange}\n fullWidth\n />\n </TabPanel>\n </TabContext>\n );\n};\n\nexport default SettingsFormContent;\n","import { DropResult } from '@hello-pangea/dnd';\nimport { ListWorkplaceAssignments_WorkplaceWithAssignment, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nimport { WidgetData } from '@/types';\n\nexport const presenceLabelKeys: Record<PresenceStatusEnum, string> = {\n [PresenceStatusEnum.Present]: 'stationAssignmentWidget.presenceStatusPresent',\n [PresenceStatusEnum.NotPresent]: 'stationAssignmentWidget.presenceStatusNotPresent',\n [PresenceStatusEnum.PresentElsewhere]: 'stationAssignmentWidget.presenceStatusPresentElsewhere',\n};\n\ntype QueryWorkplace = ListWorkplaceAssignments_WorkplaceWithAssignment['workplace'];\n\nexport interface OperatorContext {\n presenceStatus?: PresenceStatusEnum;\n assignedWorkplaceName?: string;\n isUnplanned?: boolean;\n checkedInWorkplace?: QueryWorkplace;\n}\n\nexport const findOperatorContext = (data: WidgetData, userId: string): OperatorContext => {\n for (const wp of data.workplaces) {\n const assigned = wp.assignedOperators.find((op) => op.user.id === userId);\n if (assigned) {\n return {\n presenceStatus: assigned.presenceStatus,\n assignedWorkplaceName: wp.workplace.name,\n };\n }\n }\n\n for (const wp of data.workplaces) {\n const unplanned = wp.unplannedOperators.find((op) => op.user.id === userId && !op.plannedWorkplace);\n if (unplanned) {\n return {\n isUnplanned: true,\n checkedInWorkplace: wp.workplace,\n };\n }\n }\n\n return {};\n};\n\nconst UNPLANNED_PREFIX = 'unplanned:';\n\nexport const isUnplannedDraggableId = (draggableId: string): boolean => draggableId.startsWith(UNPLANNED_PREFIX);\n\nexport const extractUserId = (draggableId: string): string =>\n isUnplannedDraggableId(draggableId) ? draggableId.slice(UNPLANNED_PREFIX.length) : draggableId;\n\nexport const makeUnplannedDraggableId = (userId: string): string => `${UNPLANNED_PREFIX}${userId}`;\n\nexport const getUpdatedData = (\n data: WidgetData,\n result: DropResult,\n): Pick<WidgetData, 'workplaces' | 'unassignedOperators'> | null => {\n const { source, destination, draggableId } = result;\n\n if (!destination) return null;\n if (source.droppableId === destination.droppableId && source.index === destination.index) return null;\n\n const isUnplanned = isUnplannedDraggableId(draggableId);\n const userId = extractUserId(draggableId);\n const fromPool = source.droppableId === 'pool';\n const toPool = destination.droppableId === 'pool';\n\n if (isUnplanned && toPool) return null;\n\n let movedUser: { id: string; name: string } | undefined;\n let movedPresenceStatus = PresenceStatusEnum.NotPresent;\n\n const newUnassignedOperators = [...data.unassignedOperators];\n const newWorkplaces = data.workplaces.map((wp) => ({\n ...wp,\n assignedOperators: [...wp.assignedOperators],\n unplannedOperators: [...wp.unplannedOperators],\n }));\n\n if (isUnplanned) {\n const sourceWp = newWorkplaces.find((wp) => wp.workplace.id === source.droppableId);\n if (sourceWp) {\n const idx = sourceWp.unplannedOperators.findIndex((op) => op.user.id === userId);\n if (idx !== -1) {\n movedUser = sourceWp.unplannedOperators[idx].user;\n movedPresenceStatus = PresenceStatusEnum.PresentElsewhere;\n sourceWp.unplannedOperators.splice(idx, 1);\n }\n }\n const poolIdx = newUnassignedOperators.findIndex((op) => op.id === userId);\n if (poolIdx !== -1) {\n newUnassignedOperators.splice(poolIdx, 1);\n }\n } else if (fromPool) {\n const idx = newUnassignedOperators.findIndex((op) => op.id === userId);\n if (idx !== -1) {\n movedUser = newUnassignedOperators[idx];\n newUnassignedOperators.splice(idx, 1);\n }\n } else {\n const sourceWp = newWorkplaces.find((wp) => wp.workplace.id === source.droppableId);\n if (sourceWp) {\n const idx = sourceWp.assignedOperators.findIndex((op) => op.user.id === userId);\n if (idx !== -1) {\n movedUser = sourceWp.assignedOperators[idx].user;\n movedPresenceStatus = sourceWp.assignedOperators[idx].presenceStatus;\n sourceWp.assignedOperators.splice(idx, 1);\n sourceWp.assignedCount -= 1;\n }\n }\n }\n\n if (!movedUser) return null;\n\n if (toPool) {\n newUnassignedOperators.splice(destination.index, 0, movedUser);\n } else {\n const destWp = newWorkplaces.find((wp) => wp.workplace.id === destination.droppableId);\n if (destWp) {\n destWp.assignedOperators.splice(destination.index, 0, {\n user: movedUser,\n presenceStatus: movedPresenceStatus,\n });\n destWp.assignedCount += 1;\n }\n }\n\n return { workplaces: newWorkplaces, unassignedOperators: newUnassignedOperators };\n};\n","import { SxProps, Theme } from '@mui/material/styles';\nimport { PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nconst presenceColors: Record<PresenceStatusEnum, string> = {\n [PresenceStatusEnum.Present]: 'success.main',\n [PresenceStatusEnum.NotPresent]: 'error.main',\n [PresenceStatusEnum.PresentElsewhere]: 'warning.main',\n};\n\nexport const makePresenceIndicatorStyles = (status: PresenceStatusEnum): SxProps<Theme> => ({\n flexShrink: 0,\n width: 12,\n height: 12,\n borderRadius: '50%',\n backgroundColor: presenceColors[status],\n});\n\nconst styles: Record<string, SxProps<Theme>> = {\n properties: {\n gap: (theme) => theme.spacing(0.5),\n },\n property: {\n marginLeft: (theme) => theme.spacing(2),\n },\n propertyLabel: {\n marginBottom: (theme) => theme.spacing(0.5),\n fontWeight: 'bold',\n },\n propertyValue: {\n fontSize: (theme) => theme.typography.pxToRem(14),\n color: 'text.primary',\n },\n checkedInValue: {\n fontSize: (theme) => theme.typography.pxToRem(14),\n fontWeight: 600,\n color: 'warning.main',\n },\n unplannedIndicator: {\n flexShrink: 0,\n width: 12,\n height: 12,\n borderRadius: '50%',\n backgroundColor: 'success.main',\n },\n assignButton: {\n marginTop: (theme) => theme.spacing(2),\n },\n separator: {\n width: '100%',\n height: '1px',\n margin: (theme) => theme.spacing(1, 0),\n background: 'linear-gradient(90deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.05) 100%)',\n },\n};\n\nexport default styles;\n","import { Fragment, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Box, Button, CircularProgress, Stack, Typography } from '@mui/material';\nimport { GqlClients, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\nimport dayjs from 'dayjs';\n\nimport { ViewState, WidgetData } from '@/types';\n\nimport { findOperatorContext, presenceLabelKeys } from '../../helpers';\n\nimport styles, { makePresenceIndicatorStyles } from './styles';\n\ninterface MainContentProps {\n userId: string;\n data: WidgetData;\n gqlClients: GqlClients;\n viewState: ViewState;\n onAssignToWorkplace?: (userId: string, workplaceId: string) => void;\n}\n\nconst getPresenceLabel = (t: (key: string) => string, status?: PresenceStatusEnum): string => {\n if (!status) return t('stationAssignmentWidget.unassignedOperator');\n return t(presenceLabelKeys[status]);\n};\n\nconst formatDuration = (startedAt: string): string => {\n const start = dayjs(startedAt);\n const now = dayjs();\n const totalMinutes = now.diff(start, 'minute');\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n\n if (hours > 0) {\n return `${hours}h ${minutes}m`;\n }\n return `${minutes}m`;\n};\n\nconst MainContent: React.FC<MainContentProps> = ({ userId, data, gqlClients, viewState, onAssignToWorkplace }) => {\n const { t } = useTranslation();\n const [checkedInAt, setCheckedInAt] = useState<string | null>(null);\n const [checkedInWorkplaceName, setCheckedInWorkplaceName] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const context = findOperatorContext(data, userId);\n const isPresent =\n context.isUnplanned ||\n context.presenceStatus === PresenceStatusEnum.Present ||\n context.presenceStatus === PresenceStatusEnum.PresentElsewhere;\n\n const handleAssignHere = () => {\n if (!context.checkedInWorkplace || !onAssignToWorkplace) return;\n onAssignToWorkplace(userId, context.checkedInWorkplace.id);\n };\n\n useEffect(() => {\n if (!isPresent || !gqlClients.graphqlSdk) return;\n\n setIsLoading(true);\n void gqlClients.graphqlSdk\n .usersPresences({\n filter: {\n user_id_eq: userId,\n shift_id_eq: viewState.shift.id,\n finished_at_null: 'true',\n },\n })\n .then(({ usersPresences }) => {\n if (usersPresences.length > 0) {\n const latest = usersPresences[usersPresences.length - 1];\n setCheckedInAt(latest.startedAt);\n const wp = data.workplaces.find((w) => w.workplace.id === latest.workplaceId);\n if (wp) {\n setCheckedInWorkplaceName(wp.workplace.name);\n }\n }\n return undefined;\n })\n .catch(() => undefined)\n .finally(() => setIsLoading(false));\n }, [userId, isPresent, gqlClients.graphqlSdk, viewState.shift.id, data.workplaces]);\n\n return (\n <Stack sx={styles.properties}>\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.presenceStatus')}</Typography>\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n {context.isUnplanned && (\n <Box title={t('stationAssignmentWidget.checkedInUnassigned')} sx={styles.unplannedIndicator} />\n )}\n {!context.isUnplanned && context.presenceStatus && (\n <Box\n title={t(presenceLabelKeys[context.presenceStatus])}\n sx={makePresenceIndicatorStyles(context.presenceStatus)}\n />\n )}\n <Typography sx={styles.propertyValue}>\n {context.isUnplanned\n ? t('stationAssignmentWidget.checkedInUnassigned')\n : getPresenceLabel(t, context.presenceStatus)}\n </Typography>\n </Stack>\n </Box>\n\n {context.isUnplanned && context.checkedInWorkplace && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.checkedInLocation')}</Typography>\n <Typography sx={styles.propertyValue}>{context.checkedInWorkplace.name}</Typography>\n </Box>\n </Fragment>\n )}\n\n {context.assignedWorkplaceName && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.assignedWorkplace')}</Typography>\n <Typography sx={styles.propertyValue}>{context.assignedWorkplaceName}</Typography>\n </Box>\n </Fragment>\n )}\n\n {isLoading && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property} display=\"flex\" justifyContent=\"center\" mt={2}>\n <CircularProgress size={16} />\n </Box>\n </Fragment>\n )}\n\n {!isLoading && checkedInAt && (\n <Fragment>\n {context.presenceStatus === PresenceStatusEnum.PresentElsewhere && checkedInWorkplaceName && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.checkedInLocation')}</Typography>\n <Typography sx={styles.checkedInValue}>{checkedInWorkplaceName}</Typography>\n </Box>\n </Fragment>\n )}\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.checkedInTime')}</Typography>\n <Typography sx={styles.propertyValue}>{dayjs(checkedInAt).format('HH:mm')}</Typography>\n </Box>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.workingFor')}</Typography>\n <Typography sx={styles.propertyValue}>{formatDuration(checkedInAt)}</Typography>\n </Box>\n </Fragment>\n )}\n {context.isUnplanned && context.checkedInWorkplace && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property} display=\"flex\" justifyContent=\"flex-end\">\n <Button\n variant=\"contained\"\n size=\"small\"\n color=\"info\"\n sx={styles.assignButton}\n onClick={handleAssignHere}\n data-testid=\"stationAssignment.sidePanel.assignHere\"\n >\n {t('stationAssignmentWidget.assignHere')}\n </Button>\n </Box>\n </Fragment>\n )}\n </Stack>\n );\n};\n\nexport default MainContent;\n","import { SxProps, Theme } from '@mui/material';\n\nexport const makeDropZoneStyles = (isDraggingOver: boolean): SxProps<Theme> => ({\n height: '100%',\n transition: 'background-color 0.2s ease',\n backgroundColor: isDraggingOver ? 'rgba(0,0,0,0.1)' : 'transparent',\n});\n","import { Droppable, DroppableProps, DroppableProvided } from '@hello-pangea/dnd';\nimport { Box } from '@mui/material';\n\nimport { makeDropZoneStyles } from './styles';\n\ninterface DropZoneProps {\n droppableId: string;\n children: (provided: DroppableProvided) => React.ReactNode;\n renderClone?: DroppableProps['renderClone'];\n}\n\nconst DropZone: React.FC<DropZoneProps> = ({ droppableId, children, renderClone }) => (\n <Droppable droppableId={droppableId} renderClone={renderClone}>\n {(provided, snapshot) => (\n <Box ref={provided.innerRef} {...provided.droppableProps} sx={makeDropZoneStyles(snapshot.isDraggingOver)}>\n {children(provided)}\n {provided.placeholder}\n </Box>\n )}\n </Droppable>\n);\n\nexport default DropZone;\n","import { SxProps, Theme } from '@mui/material';\nimport { PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nconst presenceColors: Record<PresenceStatusEnum, string> = {\n [PresenceStatusEnum.Present]: 'success.main',\n [PresenceStatusEnum.NotPresent]: 'error.main',\n [PresenceStatusEnum.PresentElsewhere]: 'warning.main',\n};\n\nexport const makeCardStyles = (dragging?: boolean, clickable = true): SxProps<Theme> => ({\n display: 'flex',\n alignItems: 'center',\n gap: (theme) => theme.spacing(1),\n cursor: clickable ? 'pointer' : 'default',\n padding: (theme) => theme.spacing(1),\n borderBottom: '1px solid rgba(255, 255, 255, 0.15)',\n boxShadow: 'none',\n '&:last-of-type': {\n borderBottom: 'none',\n },\n ...(clickable && {\n '&:hover': {\n backgroundColor: 'rgba(255, 255, 255, 0.05)',\n },\n }),\n ...(dragging && {\n opacity: 0.5,\n }),\n});\n\nexport const makePresenceDotStyles = (status: PresenceStatusEnum): SxProps<Theme> => ({\n flexShrink: 0,\n width: 10,\n height: 10,\n borderRadius: '50%',\n backgroundColor: presenceColors[status],\n});\n\nexport const unplannedDotStyles: SxProps<Theme> = {\n flexShrink: 0,\n width: 10,\n height: 10,\n borderRadius: '50%',\n backgroundColor: 'success.main',\n};\n\nconst styles: Record<string, SxProps<Theme>> = {\n name: {\n flexGrow: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n removeButton: {\n flexShrink: 0,\n opacity: 0.6,\n padding: (theme) => theme.spacing(0.25),\n marginLeft: 'auto',\n '&:hover': {\n opacity: 1,\n },\n },\n};\n\nexport default styles;\n","import { useTranslation } from 'react-i18next';\n\nimport { Draggable, DraggableProvided } from '@hello-pangea/dnd';\nimport CloseIcon from '@mui/icons-material/Close';\nimport { Box, Card, IconButton, Typography } from '@mui/material';\nimport { PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nimport { OperatorUser } from '@/types';\n\nimport { presenceLabelKeys } from '../helpers';\n\nimport styles, { makeCardStyles, makePresenceDotStyles, unplannedDotStyles } from './styles';\n\ninterface OperatorCardProps {\n user: OperatorUser;\n index: number;\n draggableId: string;\n showPresence?: boolean;\n presenceStatus?: PresenceStatusEnum;\n isUnplanned?: boolean;\n onClick?: () => void;\n onRemove?: () => void;\n}\n\ninterface DraggingOperatorCardProps {\n provided: DraggableProvided;\n user: OperatorUser;\n}\n\nexport const DraggingOperatorCard: React.FC<DraggingOperatorCardProps> = ({ provided, user }) => (\n <Card ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} sx={makeCardStyles(true)}>\n <Typography sx={styles.name}>{user.name}</Typography>\n </Card>\n);\n\nconst OperatorCard: React.FC<OperatorCardProps> = ({\n user,\n index,\n draggableId,\n showPresence,\n presenceStatus,\n isUnplanned,\n onClick,\n onRemove,\n}) => {\n const { t } = useTranslation();\n\n return (\n <Draggable draggableId={draggableId} index={index}>\n {(provided, snapshot) => (\n <Card\n ref={provided.innerRef}\n {...provided.draggableProps}\n {...provided.dragHandleProps}\n sx={makeCardStyles(snapshot.isDragging, !!onClick)}\n onClick={() => {\n if (!snapshot.isDragging && onClick) {\n onClick();\n }\n }}\n data-testid=\"stationAssignment.operatorCard\"\n >\n {isUnplanned && <Box title={t('stationAssignmentWidget.checkedInUnassigned')} sx={unplannedDotStyles} />}\n {!isUnplanned && showPresence && presenceStatus && (\n <Box title={t(presenceLabelKeys[presenceStatus])} sx={makePresenceDotStyles(presenceStatus)} />\n )}\n <Typography title={user.name} sx={styles.name}>\n {user.name}\n </Typography>\n {onRemove && (\n <IconButton\n title={t('stationAssignmentWidget.removeOperator')}\n size=\"small\"\n color=\"error\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n sx={styles.removeButton}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Card>\n )}\n </Draggable>\n );\n};\n\nexport default OperatorCard;\n","import { SxProps, Theme } from '@mui/material';\n\nconst styles: Record<string, SxProps<Theme>> = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n flexShrink: 0,\n width: 250,\n height: '100%',\n },\n header: {\n display: 'flex',\n padding: (theme) => theme.spacing(0.5, 1),\n },\n action: {\n display: 'flex',\n alignSelf: 'center',\n margin: (theme) => theme.spacing(0, 0, 0, 1),\n },\n search: {\n margin: (theme) => theme.spacing(0, 1, 1, 1),\n '&.MuiFormControl-root': {\n margin: 0,\n },\n '& .MuiOutlinedInput-notchedOutline': {\n border: 'none',\n },\n '& .MuiInputAdornment-root': {\n color: 'text.primary',\n },\n },\n content: {\n flexGrow: 1,\n padding: (theme) => theme.spacing(0.5),\n overflow: 'auto',\n },\n};\n\nexport default styles;\n","import { Fragment, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport SearchIcon from '@mui/icons-material/Search';\nimport { Card, CardContent, CardHeader, InputAdornment, TextField } from '@mui/material';\n\nimport { OperatorUser } from '@/types';\n\nimport DropZone from '../DropZone';\nimport OperatorCard, { DraggingOperatorCard } from '../OperatorCard';\n\nimport styles from './styles';\n\ninterface PoolColumnProps {\n operators: OperatorUser[];\n unplannedUserIds?: Set<string>;\n onOperatorClick?: (userId: string, userName: string) => void;\n}\n\nconst PoolColumn: React.FC<PoolColumnProps> = ({ operators, unplannedUserIds, onOperatorClick }) => {\n const [searchQuery, setSearchQuery] = useState('');\n const { t } = useTranslation();\n\n const poolOperators = useMemo(\n () => (unplannedUserIds ? operators.filter((user) => !unplannedUserIds.has(user.id)) : operators),\n [operators, unplannedUserIds],\n );\n\n const filteredOperators = useMemo(() => {\n if (!searchQuery.trim()) return poolOperators;\n const query = searchQuery.toLowerCase();\n return poolOperators.filter((user) =>\n user.name\n .toLowerCase()\n .split(' ')\n .some((part) => part.startsWith(query)),\n );\n }, [poolOperators, searchQuery]);\n\n return (\n <Card sx={styles.root} data-testid=\"stationAssignment.pool\">\n <CardHeader\n title={t('stationAssignmentWidget.unassignedPool')}\n action={poolOperators.length}\n slotProps={{ title: { variant: 'subtitle1' }, action: { sx: styles.action } }}\n sx={styles.header}\n />\n <TextField\n size=\"small\"\n label={t('stationAssignmentWidget.searchOperators')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n sx={styles.search}\n data-testid=\"stationAssignment.pool.search\"\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n <CardContent sx={styles.content}>\n <DropZone\n droppableId=\"pool\"\n renderClone={(provided, _, rubric) => (\n <DraggingOperatorCard provided={provided} user={filteredOperators[rubric.source.index]} />\n )}\n >\n {() => (\n <Fragment>\n {filteredOperators.map((user, index) => (\n <OperatorCard\n key={user.id}\n user={user}\n index={index}\n draggableId={user.id}\n onClick={onOperatorClick ? () => onOperatorClick(user.id, user.name) : undefined}\n />\n ))}\n </Fragment>\n )}\n </DropZone>\n </CardContent>\n </Card>\n );\n};\n\nexport default PoolColumn;\n","import { SxProps, Theme } from '@mui/material';\n\ntype BorderStatus = 'normal' | 'overcapacity' | 'unplanned';\n\nconst borderConfig: Record<\n Exclude<BorderStatus, 'normal'>,\n { borderColor: string; labelColor: string; labelBg: string }\n> = {\n overcapacity: { borderColor: 'error.main', labelColor: 'error.contrastText', labelBg: 'error.main' },\n unplanned: { borderColor: 'warning.main', labelColor: 'warning.contrastText', labelBg: 'warning.main' },\n};\n\nexport const makeRootStyles = (\n borderStatus: BorderStatus,\n frozenHeight?: number,\n borderLabel?: string,\n): SxProps<Theme> => ({\n display: 'flex',\n flexDirection: 'column',\n flexShrink: 0,\n position: 'relative',\n width: 250,\n minHeight: 200,\n border: borderStatus !== 'normal' ? 2 : 1,\n borderColor: borderStatus !== 'normal' ? borderConfig[borderStatus].borderColor : 'divider',\n ...(borderStatus !== 'normal' && {\n '&::after': {\n content: `\"${borderLabel}\"`,\n position: 'absolute',\n bottom: -2,\n left: -2,\n padding: (theme: Theme) => theme.spacing(0.25, 0.75),\n fontSize: (theme: Theme) => theme.typography.pxToRem(10),\n color: borderConfig[borderStatus].labelColor,\n backgroundColor: borderConfig[borderStatus].labelBg,\n borderRadius: '0 4px 0 0',\n textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',\n pointerEvents: 'none',\n },\n }),\n ...(frozenHeight !== undefined && {\n overflow: 'hidden',\n maxHeight: frozenHeight,\n }),\n});\n\nconst styles: Record<string, SxProps<Theme>> = {\n header: {\n display: 'flex',\n padding: (theme) => theme.spacing(0.5, 1),\n '& .MuiCardHeader-content': {\n overflowX: 'hidden',\n },\n },\n title: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n action: {\n display: 'flex',\n alignSelf: 'center',\n gap: (theme) => theme.spacing(1),\n margin: (theme) => theme.spacing(0, 0, 0, 1),\n },\n content: {\n flexGrow: 1,\n padding: (theme) => theme.spacing(0.5),\n },\n unplannedLabel: {\n display: 'block',\n margin: (theme) => theme.spacing(1, 0),\n padding: (theme) => theme.spacing(0, 0.5),\n color: 'text.primary',\n opacity: 0.7,\n textAlign: 'center',\n },\n unplannedSeparator: {\n height: '1px',\n backgroundColor: 'text.primary',\n opacity: 0.3,\n },\n};\n\nconst badgeColors: Record<string, { color: string; backgroundColor: string }> = {\n ok: { color: 'success.contrastText', backgroundColor: 'success.main' },\n missing: { color: 'error.contrastText', backgroundColor: 'error.main' },\n overcapacity: { color: 'error.contrastText', backgroundColor: 'error.main' },\n warning: { color: 'warning.contrastText', backgroundColor: 'warning.main' },\n};\n\nexport const makeStatusBadgeStyles = (status: 'missing' | 'overcapacity' | 'ok' | 'warning'): SxProps<Theme> => ({\n padding: (theme) => `${theme.spacing(0.25)} ${theme.spacing(1)}`,\n borderRadius: 1,\n ...badgeColors[status],\n});\n\nexport default styles;\n","import { Fragment, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Box, Card, CardContent, CardHeader, Typography } from '@mui/material';\nimport { ListWorkplaceAssignments_WorkplaceWithAssignment, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nimport { ViewState } from '@/types';\n\nimport DropZone from '../DropZone';\nimport { makeUnplannedDraggableId } from '../helpers';\nimport OperatorCard, { DraggingOperatorCard } from '../OperatorCard';\n\nimport styles, { makeRootStyles, makeStatusBadgeStyles } from './styles';\n\nconst getStatusBadge = (assignment: ListWorkplaceAssignments_WorkplaceWithAssignment, unplannedCount: number) => {\n const presentCount = assignment.assignedOperators.filter(\n (op) => op.presenceStatus === PresenceStatusEnum.Present,\n ).length;\n const checkedInHereCount = presentCount + unplannedCount;\n\n if (checkedInHereCount > assignment.recommendedOperators) {\n const diff = checkedInHereCount - assignment.recommendedOperators;\n return {\n text: `+${diff}`,\n status: 'overcapacity' as const,\n titleKey: 'stationAssignmentWidget.statusOvercapacity',\n checkedInHereCount,\n };\n }\n if (checkedInHereCount < assignment.recommendedOperators) {\n const diff = checkedInHereCount - assignment.recommendedOperators;\n return {\n text: `${diff}`,\n status: 'missing' as const,\n titleKey: 'stationAssignmentWidget.statusMissing',\n checkedInHereCount,\n };\n }\n if (unplannedCount === 0) {\n return { text: 'OK', status: 'ok' as const, titleKey: 'stationAssignmentWidget.statusOk', checkedInHereCount };\n }\n return {\n text: 'OK',\n status: 'warning' as const,\n titleKey: 'stationAssignmentWidget.statusUnplanned',\n checkedInHereCount,\n };\n};\n\nconst getPlanningBadge = (assignment: ListWorkplaceAssignments_WorkplaceWithAssignment) => {\n const diff = assignment.assignedCount - assignment.recommendedOperators;\n if (diff > 0) {\n return {\n text: `+${diff}`,\n status: 'overcapacity' as const,\n titleKey: 'stationAssignmentWidget.statusOvercapacity',\n };\n }\n if (diff < 0) {\n return { text: `${diff}`, status: 'missing' as const, titleKey: 'stationAssignmentWidget.statusMissing' };\n }\n return { text: 'OK', status: 'ok' as const, titleKey: 'stationAssignmentWidget.statusOk' };\n};\n\ninterface WorkplaceColumnProps {\n assignment: ListWorkplaceAssignments_WorkplaceWithAssignment;\n viewState: ViewState;\n registerRef?: (el: HTMLDivElement | null) => void;\n frozenHeight?: number;\n onOperatorClick?: (userId: string, userName: string) => void;\n onRemoveOperator?: (userId: string) => void;\n}\n\nconst WorkplaceColumn: React.FC<WorkplaceColumnProps> = ({\n assignment,\n viewState,\n registerRef,\n frozenHeight,\n onOperatorClick,\n onRemoveOperator,\n}) => {\n const { t } = useTranslation();\n const { isCurrentShift } = viewState;\n\n const sortedOperators = useMemo(\n () =>\n [...assignment.assignedOperators].sort((a, b) =>\n a.user.name.localeCompare(b.user.name, undefined, { numeric: true }),\n ),\n [assignment.assignedOperators],\n );\n\n const sortedUnplanned = useMemo(\n () =>\n isCurrentShift\n ? assignment.unplannedOperators\n .filter((op) => !op.plannedWorkplace)\n .sort((a, b) => a.user.name.localeCompare(b.user.name, undefined, { numeric: true }))\n : [],\n [assignment.unplannedOperators, isCurrentShift],\n );\n\n const { localOperators, elsewhereOperators } = useMemo(() => {\n if (!isCurrentShift) {\n return { localOperators: sortedOperators, elsewhereOperators: [] };\n }\n return {\n localOperators: sortedOperators.filter((op) => op.presenceStatus !== PresenceStatusEnum.PresentElsewhere),\n elsewhereOperators: sortedOperators.filter((op) => op.presenceStatus === PresenceStatusEnum.PresentElsewhere),\n };\n }, [sortedOperators, isCurrentShift]);\n\n const badge = isCurrentShift ? getStatusBadge(assignment, sortedUnplanned.length) : null;\n const planningBadge = !isCurrentShift ? getPlanningBadge(assignment) : null;\n const activeBadge = badge || planningBadge!;\n\n const isOvercapacity = isCurrentShift\n ? assignment.assignedCount > assignment.recommendedOperators ||\n (badge?.checkedInHereCount ?? 0) > assignment.recommendedOperators\n : assignment.assignedCount > assignment.recommendedOperators;\n\n const getBorderStatus = () => {\n if (isOvercapacity) return { status: 'overcapacity' as const, label: t('stationAssignmentWidget.overcapacity') };\n if (isCurrentShift && sortedUnplanned.length > 0)\n return { status: 'unplanned' as const, label: t('stationAssignmentWidget.unplannedStaffing') };\n return { status: 'normal' as const, label: '' };\n };\n const border = getBorderStatus();\n\n const displayCount = badge ? badge.checkedInHereCount : assignment.assignedCount;\n\n return (\n <Card\n ref={registerRef}\n sx={makeRootStyles(border.status, frozenHeight, border.label)}\n data-testid=\"stationAssignment.workplace\"\n >\n <CardHeader\n title={assignment.workplace.name}\n action={\n <Fragment>\n <Typography data-testid=\"stationAssignment.workplace.count\">{`${displayCount}/${assignment.recommendedOperators}`}</Typography>\n <Typography\n title={t(activeBadge.titleKey)}\n variant=\"caption\"\n sx={makeStatusBadgeStyles(activeBadge.status)}\n data-testid=\"stationAssignment.workplace.badge\"\n >\n {activeBadge.text}\n </Typography>\n </Fragment>\n }\n slotProps={{\n title: { variant: 'subtitle1', title: assignment.workplace.name, sx: styles.title },\n action: { sx: styles.action },\n }}\n sx={styles.header}\n />\n <CardContent sx={styles.content}>\n <DropZone\n droppableId={assignment.workplace.id}\n renderClone={(provided, _, rubric) => {\n const idx = rubric.source.index;\n const assignedCount = localOperators.length + elsewhereOperators.length;\n let user;\n if (idx < localOperators.length) {\n user = localOperators[idx]?.user;\n } else if (idx < assignedCount) {\n user = elsewhereOperators[idx - localOperators.length]?.user;\n } else {\n user = sortedUnplanned[idx - assignedCount]?.user;\n }\n if (!user)\n return <Card ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} />;\n return <DraggingOperatorCard provided={provided} user={user} />;\n }}\n >\n {() => {\n const elsewhereOffset = localOperators.length;\n const unplannedOffset = elsewhereOffset + elsewhereOperators.length;\n return (\n <Fragment>\n {localOperators.map((operator, index) => (\n <OperatorCard\n key={operator.user.id}\n user={operator.user}\n index={index}\n draggableId={operator.user.id}\n showPresence={isCurrentShift}\n presenceStatus={operator.presenceStatus}\n onClick={onOperatorClick ? () => onOperatorClick(operator.user.id, operator.user.name) : undefined}\n onRemove={onRemoveOperator ? () => onRemoveOperator(operator.user.id) : undefined}\n />\n ))}\n {elsewhereOperators.length > 0 && (\n <Fragment>\n <Typography\n variant=\"caption\"\n sx={styles.unplannedLabel}\n data-testid=\"stationAssignment.workplace.elsewhereLabel\"\n >\n {t('stationAssignmentWidget.presentElsewhereLabel')}\n </Typography>\n <Box sx={styles.unplannedSeparator} />\n </Fragment>\n )}\n {elsewhereOperators.map((operator, index) => (\n <OperatorCard\n key={operator.user.id}\n user={operator.user}\n index={elsewhereOffset + index}\n draggableId={operator.user.id}\n showPresence\n presenceStatus={operator.presenceStatus}\n onClick={onOperatorClick ? () => onOperatorClick(operator.user.id, operator.user.name) : undefined}\n onRemove={onRemoveOperator ? () => onRemoveOperator(operator.user.id) : undefined}\n />\n ))}\n {sortedUnplanned.length > 0 && (\n <Fragment>\n <Typography\n variant=\"caption\"\n sx={styles.unplannedLabel}\n data-testid=\"stationAssignment.workplace.unplannedLabel\"\n >\n {t('stationAssignmentWidget.unplannedSectionLabel')}\n </Typography>\n <Box sx={styles.unplannedSeparator} />\n </Fragment>\n )}\n {sortedUnplanned.map((unplanned, index) => (\n <OperatorCard\n key={unplanned.user.id}\n user={unplanned.user}\n index={unplannedOffset + index}\n draggableId={makeUnplannedDraggableId(unplanned.user.id)}\n isUnplanned\n onClick={\n onOperatorClick ? () => onOperatorClick(unplanned.user.id, unplanned.user.name) : undefined\n }\n />\n ))}\n </Fragment>\n );\n }}\n </DropZone>\n </CardContent>\n </Card>\n );\n};\n\nexport default WorkplaceColumn;\n","import { Theme } from '@mui/material';\n\nconst styles = {\n grid: (theme: Theme) => ({\n display: 'flex',\n flexDirection: 'column',\n flexWrap: 'wrap',\n alignContent: 'flex-start',\n gap: theme.spacing(1),\n height: '100%',\n overflowX: 'auto',\n }),\n};\n\nexport default styles;\n","import { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { DragDropContext, DragStart, DropResult } from '@hello-pangea/dnd';\nimport { Box } from '@mui/material';\nimport { GqlClients, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\nimport { SidePanelProps } from 'andoncloud-sdk';\n\nimport { ViewState, WidgetData } from '@/types';\nimport { extractDate } from '@/utils/state';\n\nimport MainContent from './OperatorCard/SidePanel/MainContent';\nimport { extractUserId, getUpdatedData } from './helpers';\nimport PoolColumn from './PoolColumn';\nimport WorkplaceColumn from './WorkplaceColumn';\n\nimport styles from './styles';\n\ninterface AssignmentBoardProps {\n data: WidgetData;\n viewState: ViewState;\n gqlClients: GqlClients;\n updateData: (data: Partial<WidgetData>) => void;\n updateSidePanelProps: (props: Partial<SidePanelProps>) => void;\n refetchAssignments: () => void;\n}\n\nconst AssignmentBoard: React.FC<AssignmentBoardProps> = ({\n data,\n viewState,\n gqlClients,\n updateData,\n updateSidePanelProps,\n refetchAssignments,\n}) => {\n const { graphqlSdk } = gqlClients;\n const [frozenHeights, setFrozenHeights] = useState<Record<string, number>>({});\n\n // Refs to workplace column DOM elements for freezing heights during drag\n const columnRefs = useRef<Record<string, HTMLDivElement | null>>({});\n\n // Ref to access latest data in async callbacks (avoids stale closures)\n const dataRef = useRef(data);\n dataRef.current = data;\n\n const unplannedUserIds = useMemo(() => {\n const ids = new Set<string>();\n for (const wp of data.workplaces) {\n for (const op of wp.unplannedOperators) {\n ids.add(op.user.id);\n }\n }\n return ids;\n }, [data.workplaces]);\n\n const registerColumnRef = useCallback((id: string, el: HTMLDivElement | null) => {\n columnRefs.current[id] = el;\n }, []);\n\n const handleDragStart = useCallback((_: DragStart) => {\n const heights: Record<string, number> = {};\n Object.entries(columnRefs.current).forEach(([id, el]) => {\n if (el) {\n heights[id] = el.getBoundingClientRect().height;\n }\n });\n setFrozenHeights(heights);\n }, []);\n\n const handleRemoveOperator = useCallback(\n (userId: string, workplaceId: string) => {\n if (!graphqlSdk) return;\n\n const workplace = data.workplaces.find((w) => w.workplace.id === workplaceId);\n const operator = workplace?.assignedOperators.find((o) => o.user.id === userId);\n if (!workplace || !operator) return;\n\n updateData({\n workplaces: data.workplaces.map((w) =>\n w.workplace.id === workplaceId\n ? {\n ...w,\n assignedOperators: w.assignedOperators.filter((o) => o.user.id !== userId),\n assignedCount: w.assignedCount - 1,\n }\n : w,\n ),\n unassignedOperators: [operator.user, ...data.unassignedOperators],\n });\n\n graphqlSdk\n .unassignOperator({\n input: {\n userId,\n shiftId: viewState.shift.id,\n validFrom: extractDate(viewState.date),\n },\n })\n .catch(() => {});\n },\n [graphqlSdk, data, viewState, updateData],\n );\n\n const handleAssignUnplanned = useCallback(\n (userId: string, workplaceId: string) => {\n if (!graphqlSdk) return;\n\n updateData({\n workplaces: data.workplaces.map((w) => {\n const isTarget = w.workplace.id === workplaceId;\n const unplanned = w.unplannedOperators.find((op) => op.user.id === userId);\n return {\n ...w,\n unplannedOperators: w.unplannedOperators.filter((op) => op.user.id !== userId),\n ...(isTarget && unplanned\n ? {\n assignedOperators: [\n ...w.assignedOperators,\n { user: unplanned.user, presenceStatus: PresenceStatusEnum.Present },\n ].sort((a, b) => a.user.name.localeCompare(b.user.name, undefined, { numeric: true })),\n assignedCount: w.assignedCount + 1,\n }\n : {}),\n };\n }),\n unassignedOperators: data.unassignedOperators.filter((op) => op.id !== userId),\n });\n\n updateSidePanelProps({ open: false });\n\n graphqlSdk\n .assignOperator({\n input: {\n userId,\n workplaceId,\n shiftId: viewState.shift.id,\n validFrom: extractDate(viewState.date),\n },\n })\n .then(refetchAssignments)\n .catch(() => {});\n },\n [graphqlSdk, data, viewState, updateData, updateSidePanelProps, refetchAssignments],\n );\n\n const handleOperatorClick = useCallback(\n (userId: string, userName: string) => {\n updateSidePanelProps({\n open: true,\n title: userName,\n width: '25%',\n mainContent: (\n <MainContent\n userId={userId}\n data={data}\n gqlClients={gqlClients}\n viewState={viewState}\n onAssignToWorkplace={handleAssignUnplanned}\n />\n ),\n });\n },\n [data, gqlClients, viewState, updateSidePanelProps, handleAssignUnplanned],\n );\n\n const handleDragEnd = (result: DropResult) => {\n setFrozenHeights({});\n if (!graphqlSdk) return;\n\n const updatedData = getUpdatedData(data, result);\n if (!updatedData) return;\n\n updateData(updatedData);\n\n const { destination, draggableId } = result;\n const userId = extractUserId(draggableId);\n const toPool = destination!.droppableId === 'pool';\n\n if (toPool) {\n graphqlSdk\n .unassignOperator({\n input: {\n userId,\n shiftId: viewState.shift.id,\n validFrom: extractDate(viewState.date),\n },\n })\n .catch(() => {});\n } else {\n const workplaceId = destination!.droppableId;\n const assignPromise = graphqlSdk.assignOperator({\n input: {\n userId,\n workplaceId,\n shiftId: viewState.shift.id,\n validFrom: viewState.date,\n },\n });\n\n if (viewState.isCurrentShift) {\n assignPromise\n .then(() =>\n graphqlSdk.usersPresences({\n filter: {\n user_id_eq: userId,\n shift_id_eq: viewState.shift.id,\n finished_at_null: 'true',\n },\n }),\n )\n .then(({ usersPresences }) => {\n if (usersPresences.length === 0) return undefined;\n const latest = usersPresences[usersPresences.length - 1];\n const presenceStatus =\n latest.workplaceId === workplaceId ? PresenceStatusEnum.Present : PresenceStatusEnum.PresentElsewhere;\n return updateData({\n workplaces: dataRef.current.workplaces.map((w) =>\n w.workplace.id === workplaceId\n ? {\n ...w,\n assignedOperators: w.assignedOperators.map((op) =>\n op.user.id === userId ? { ...op, presenceStatus } : op,\n ),\n }\n : w,\n ),\n });\n })\n .catch(() => {});\n } else {\n assignPromise.catch(() => {});\n }\n }\n };\n\n return (\n <DragDropContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>\n <Box sx={styles.grid}>\n <PoolColumn\n operators={data.unassignedOperators}\n unplannedUserIds={viewState.isCurrentShift ? unplannedUserIds : undefined}\n onOperatorClick={viewState.isCurrentShift ? handleOperatorClick : undefined}\n />\n {data.workplaces.map((assignment) => (\n <WorkplaceColumn\n key={assignment.workplace.id}\n assignment={assignment}\n viewState={viewState}\n registerRef={(el) => registerColumnRef(assignment.workplace.id, el)}\n frozenHeight={frozenHeights[assignment.workplace.id]}\n onOperatorClick={viewState.isCurrentShift ? handleOperatorClick : undefined}\n onRemoveOperator={(userId) => handleRemoveOperator(userId, assignment.workplace.id)}\n />\n ))}\n </Box>\n </DragDropContext>\n );\n};\n\nexport default AssignmentBoard;\n","import { SxProps, Theme } from '@mui/material';\n\nconst styles: Record<string, SxProps<Theme>> = {\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: (theme) => theme.spacing(2),\n marginBottom: (theme) => theme.spacing(1),\n padding: (theme) => theme.spacing(1),\n borderBottom: '1px solid #717171',\n background: '#525860',\n },\n label: {\n minWidth: 200,\n textAlign: 'center',\n color: 'rgba(255, 255, 255, 0.65)',\n },\n};\n\nexport default styles;\n","import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';\nimport ChevronRightIcon from '@mui/icons-material/ChevronRight';\nimport { Box, IconButton, Typography } from '@mui/material';\nimport dayjs from 'dayjs';\n\nimport { ViewState } from '@/types';\n\nimport styles from './styles';\n\ninterface NavigationProps {\n viewState: ViewState;\n departmentName?: string;\n canPrev?: boolean;\n canNext?: boolean;\n onNavigate: (direction: 'prev' | 'next') => void;\n}\n\nconst isOvernightShift = (shift: ViewState['shift']): boolean => {\n const start = dayjs(shift.startedAt);\n const end = dayjs(shift.finishedAt);\n return start.hour() * 60 + start.minute() > end.hour() * 60 + end.minute();\n};\n\nconst formatLabel = (viewState: ViewState): string => {\n const { shift } = viewState;\n const startDate = dayjs(viewState.date);\n\n if (isOvernightShift(shift)) {\n const endDate = startDate.add(1, 'day');\n const shiftStart = dayjs(shift.startedAt);\n const shiftEnd = dayjs(shift.finishedAt);\n return `${startDate.format('DD.MM')} / ${endDate.format('DD.MM')} (${shiftStart.format(\n 'HH:mm',\n )} - ${shiftEnd.format('HH:mm')})`;\n }\n\n return `${startDate.format('DD.MM')} - ${shift.name}`;\n};\n\nconst Navigation: React.FC<NavigationProps> = ({\n viewState,\n departmentName,\n canPrev = true,\n canNext = true,\n onNavigate,\n}) => (\n <Box sx={styles.root} data-testid=\"stationAssignment.navigation\">\n <IconButton\n color=\"secondary\"\n disabled={!canPrev}\n onClick={() => onNavigate('prev')}\n data-testid=\"stationAssignment.navigation.prev\"\n >\n <ChevronLeftIcon />\n </IconButton>\n <Typography sx={styles.label} data-testid=\"stationAssignment.navigation.label\">\n {formatLabel(viewState)}\n {departmentName && ` - ${departmentName}`}\n </Typography>\n <IconButton\n color=\"secondary\"\n disabled={!canNext}\n onClick={() => onNavigate('next')}\n data-testid=\"stationAssignment.navigation.next\"\n >\n <ChevronRightIcon />\n </IconButton>\n </Box>\n);\n\nexport default Navigation;\n","import { SxProps, Theme } from '@mui/material/styles';\n\nconst styles: Record<string, SxProps<Theme>> = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n },\n loader: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n flexGrow: 1,\n },\n};\n\nexport default styles;\n","import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Box, CircularProgress, Typography } from '@mui/material';\nimport {\n getCurrentShift,\n normalizeShifts,\n ListShifts_Shift,\n WorkplaceEvent,\n WorkplaceEventDocument,\n WorkplaceEventSubscriptionPayload,\n} from 'andoncloud-dashboard-toolkit';\nimport dayjs from 'dayjs';\nimport { print } from 'graphql';\n\nimport { ViewState, WidgetViewProps } from '@/types';\nimport { canNavigate, getInitialState, makeShiftDateTime, navigateState } from '@/utils/state';\n\nimport AssignmentBoard from '../AssignmentBoard';\nimport Navigation from '../Navigation';\n\nimport styles from './styles';\n\nconst WidgetView: React.FC<WidgetViewProps> = ({ data, updateData, gqlClients, settings, updateSidePanelProps }) => {\n const { t } = useTranslation();\n const [viewState, setViewState] = useState<ViewState | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [gqlWsSubscribed, setGqlWsSubscribed] = useState(false);\n\n const departmentName = useMemo(() => {\n if (!settings?.departmentId) return undefined;\n const department = data.departments.find((d) => d.id === settings.departmentId);\n return department?.name;\n }, [settings?.departmentId, data.departments]);\n\n const { graphqlSdk, gqlWsClient } = gqlClients;\n const shiftsRef = useRef(data.shifts);\n shiftsRef.current = data.shifts;\n\n useEffect(() => {\n if (data.shifts.length > 0 && !viewState) {\n const initialState = getInitialState(data.shifts);\n\n if (initialState) {\n setViewState(initialState);\n }\n }\n }, [data.shifts, viewState]);\n\n useEffect(() => {\n if (!gqlWsClient || !data?.workplaces?.length || gqlWsSubscribed) return;\n\n data.workplaces.forEach(({ workplace }) =>\n gqlWsClient.subscribe<WorkplaceEventSubscriptionPayload>(\n print(WorkplaceEventDocument),\n { id: workplace.id },\n ({ event, subject }) => {\n if (event === WorkplaceEvent.CurrentShiftChanged && subject) {\n const newShift = subject as ListShifts_Shift;\n const now = dayjs();\n const sorted = [...shiftsRef.current].sort((a, b) => a.startedAt.localeCompare(b.startedAt));\n const normalized = normalizeShifts(sorted, now);\n const current = getCurrentShift(now, normalized);\n const shiftDateTime = current\n ? current.startedAt.format('YYYY-MM-DDTHH:mm:ssZ')\n : makeShiftDateTime(now.format('YYYY-MM-DD'), newShift);\n\n setViewState((prev) => {\n if (!prev?.isCurrentShift) return prev;\n return { date: shiftDateTime, shift: newShift, isCurrentShift: true };\n });\n }\n },\n ),\n );\n\n setGqlWsSubscribed(true);\n }, [gqlWsClient, data?.workplaces, gqlWsSubscribed]);\n\n const fetchAssignmentsRef = useRef<(showLoading?: boolean) => void>(null!);\n\n fetchAssignmentsRef.current = (showLoading = false) => {\n if (!graphqlSdk || !viewState || !updateData) return;\n\n if (showLoading) setIsLoading(true);\n void graphqlSdk\n .workplaceAssignments({\n input: {\n date: viewState.date,\n shiftId: viewState.shift.id,\n departmentId: settings?.departmentId || undefined,\n },\n })\n .then(({ workplaceAssignments }) => {\n return updateData(workplaceAssignments);\n })\n .catch(() => {})\n .finally(() => {\n if (showLoading) setIsLoading(false);\n });\n };\n\n useEffect(() => {\n if (!viewState || !graphqlSdk) return;\n\n fetchAssignmentsRef.current?.(true);\n\n const refreshInterval = (settings?.refreshInterval || 60) * 1000;\n const intervalId = setInterval(() => fetchAssignmentsRef.current?.(), refreshInterval);\n\n return () => clearInterval(intervalId);\n }, [viewState, graphqlSdk, settings?.departmentId, settings?.refreshInterval]);\n\n const handleNavigate = useCallback(\n (direction: 'prev' | 'next') => {\n if (!viewState) return;\n const newState = navigateState(viewState, data.shifts, direction);\n setViewState(newState);\n },\n [viewState, data.shifts],\n );\n\n const canPrev = viewState ? canNavigate(viewState, data.shifts, 'prev') : false;\n const canNext = viewState ? canNavigate(viewState, data.shifts, 'next') : false;\n\n return (\n <Box sx={styles.root}>\n {viewState ? (\n <Fragment>\n <Navigation\n viewState={viewState}\n departmentName={departmentName}\n canPrev={canPrev}\n canNext={canNext}\n onNavigate={handleNavigate}\n />\n {isLoading ? (\n <Box sx={styles.loader} data-testid=\"stationAssignment.loader\">\n <CircularProgress />\n </Box>\n ) : (\n <AssignmentBoard\n data={data}\n viewState={viewState}\n gqlClients={gqlClients}\n updateData={updateData!}\n updateSidePanelProps={updateSidePanelProps}\n refetchAssignments={() => fetchAssignmentsRef.current?.()}\n />\n )}\n </Fragment>\n ) : (\n <Typography data-testid=\"stationAssignment.noShifts\">\n {t('stationAssignmentWidget.noShiftsAvailable')}\n </Typography>\n )}\n </Box>\n );\n};\n\nexport default WidgetView;\n","import { TFunction } from 'i18next';\nimport * as yup from 'yup';\n\nexport const getSettingsFormProps = (t: TFunction) => {\n yup.setLocale({\n mixed: {\n required: t('stationAssignmentWidget.thisFieldIsRequired'),\n },\n });\n return {\n initialValues: {\n customTitle: '',\n departmentId: undefined,\n refreshInterval: 60,\n },\n validationSchema: yup.object({\n departmentId: yup.string(),\n refreshInterval: yup.number().oneOf([15, 30, 60]).required(),\n }),\n };\n};\n","import { useEffect, useState } from 'react';\n\nimport { useGqlClients, WidgetProps } from 'andoncloud-dashboard-toolkit';\nimport { BaseWidget } from 'andoncloud-widget-base';\n\nimport locales from '@/locales';\nimport { WidgetData, WidgetSettings } from '@/types';\nimport { getInitialState } from '@/utils/state';\nimport { LIBRARY_VERSION } from '@/version';\n\nimport SettingsFormContent from '../SettingsFormContent';\nimport WidgetView from '../WidgetView';\n\nimport { getSettingsFormProps } from './utils';\n\nconst Widget: React.FC<WidgetProps<WidgetData, WidgetSettings>> = ({\n url,\n wsUrl,\n lang,\n data,\n settings,\n ...widgetProps\n}) => {\n const { graphqlSdk, gqlWsClient } = useGqlClients({ url, wsUrl, lang });\n const [widgetData, setWidgetData] = useState<WidgetData | undefined>(data);\n\n useEffect(() => {\n if (!data && graphqlSdk) {\n Promise.all([graphqlSdk.departments(), graphqlSdk.listShifts()])\n .then(([{ departments }, { shifts }]) => {\n const initialState = getInitialState(shifts);\n\n if (!initialState) {\n return;\n }\n const { date, shift } = initialState;\n\n return graphqlSdk\n .workplaceAssignments({\n input: {\n date,\n shiftId: shift.id,\n departmentId: settings?.departmentId || undefined,\n },\n })\n .then(({ workplaceAssignments }) => {\n return setWidgetData({\n ...workplaceAssignments,\n departments,\n shifts,\n });\n });\n })\n .catch(() => {});\n }\n }, [data, graphqlSdk, settings?.departmentId]);\n\n return (\n <BaseWidget\n {...widgetProps}\n lang={lang}\n locales={locales}\n data={widgetData}\n gqlClients={{ graphqlSdk, gqlWsClient }}\n WidgetView={WidgetView}\n getSettingsFormProps={getSettingsFormProps}\n SettingsFormContent={SettingsFormContent}\n version={LIBRARY_VERSION}\n data-testid=\"station-assignment-widget\"\n />\n );\n};\n\nexport default Widget;\n","import type { FilterValues } from 'andoncloud-dashboard-toolkit';\nimport i18n from 'i18next';\n\nimport type { WidgetData, WidgetSettings } from '../types';\n\nconst ns = 'stationAssignmentWidget';\n\nconst t = (key: string, lng: string, options?: Record<string, unknown>) => i18n.t(`${ns}.${key}`, { lng, ...options });\n\nexport const getDisplayName = (lang: string) => t('displayName', lang);\n\nexport const getTitle = (\n data: WidgetData | undefined,\n _settings: WidgetSettings | undefined,\n _filters: FilterValues | undefined,\n lang: string,\n): string => {\n const name = getDisplayName(lang);\n\n const workplaces = data?.workplaces;\n if (!workplaces?.length) return name;\n\n const unassignedCount = data?.unassignedOperators?.length ?? 0;\n const parts = [t('titleWorkplaces', lang, { count: workplaces.length })];\n\n if (unassignedCount > 0) {\n parts.push(t('titleUnassigned', lang, { count: unassignedCount }));\n }\n\n return `${name} — ${parts.join(', ')}`;\n};\n","export { default as Widget } from './components/Widget';\nexport { getDisplayName, getTitle } from './core/title';\n\nexport const thumbnail: string | undefined = undefined;\n\nexport const requiredFeatures: string[] = ['feature.station-assignment-widget'];\nexport const extraPermissions: string[] = [];\n\nexport { LIBRARY_VERSION as version } from './version';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["en","pl","presenceColors","styles","styles","styles","styles","styles","styles","styles","styles","styles","styles","styles","styles","locales","locales"],"sources":["../src/locales/en/translation.json","../src/locales/pl/translation.json","../src/locales/index.ts","../src/utils/state.ts","../src/version.ts","../src/components/SettingsFormContent/index.tsx","../src/components/AssignmentBoard/helpers.ts","../src/components/AssignmentBoard/OperatorCard/SidePanel/styles.ts","../src/components/AssignmentBoard/OperatorCard/SidePanel/MainContent.tsx","../src/components/AssignmentBoard/DropZone/styles.ts","../src/components/AssignmentBoard/DropZone/index.tsx","../src/components/AssignmentBoard/OperatorCard/styles.ts","../src/components/AssignmentBoard/OperatorCard/index.tsx","../src/components/AssignmentBoard/PoolColumn/styles.ts","../src/components/AssignmentBoard/PoolColumn/index.tsx","../src/components/AssignmentBoard/WorkplaceColumn/styles.ts","../src/components/AssignmentBoard/WorkplaceColumn/index.tsx","../src/components/AssignmentBoard/styles.ts","../src/components/AssignmentBoard/index.tsx","../src/components/Navigation/styles.ts","../src/components/Navigation/index.tsx","../src/components/WidgetView/styles.ts","../src/components/WidgetView/index.tsx","../src/components/Widget/utils.ts","../src/components/Widget/index.tsx","../src/core/title.ts","../src/index.tsx"],"sourcesContent":["","","import en from './en/translation.json';\nimport pl from './pl/translation.json';\n\nconst resources = {\n en: {\n translation: en,\n },\n pl: {\n translation: pl,\n },\n};\n\nexport default resources;\n","import { getCurrentShift, ListShifts_Shift, normalizeShifts } from 'andoncloud-dashboard-toolkit';\nimport dayjs from 'dayjs';\n\nimport { ViewState } from '@/types';\n\nconst DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';\n\nconst sortShifts = (shifts: ListShifts_Shift[]): ListShifts_Shift[] => [...shifts].sort((a, b) => a.startedAt.localeCompare(b.startedAt));\n\nconst findShiftByName = (shifts: ListShifts_Shift[], name: string) => shifts.find((s) => s.name === name);\n\nexport const makeShiftDateTime = (date: string, shift: ListShifts_Shift): string => {\n const shiftStart = dayjs(shift.startedAt);\n return dayjs(date).hour(shiftStart.hour()).minute(shiftStart.minute()).second(0).format(DATETIME_FORMAT);\n};\n\nexport const extractDate = (dateTime: string): string => dayjs(dateTime).format('YYYY-MM-DD');\n\nconst getMinDate = (shifts: ListShifts_Shift[]): string => {\n const now = dayjs();\n const normalizedShifts = normalizeShifts(shifts, now);\n const currentShift = getCurrentShift(now, normalizedShifts);\n return (currentShift?.startedAt || now).format('YYYY-MM-DD');\n};\n\nexport const getInitialState = (shifts: ListShifts_Shift[]): ViewState | null => {\n const sortedShifts = sortShifts(shifts);\n const now = dayjs();\n const today = now.format('YYYY-MM-DD');\n const normalizedShifts = normalizeShifts(sortedShifts, now);\n\n const currentNormalizedShift = getCurrentShift(now, normalizedShifts);\n\n if (currentNormalizedShift) {\n const shift = findShiftByName(sortedShifts, currentNormalizedShift.name);\n if (shift) {\n return { date: currentNormalizedShift.startedAt.format(DATETIME_FORMAT), shift, isCurrentShift: true };\n }\n }\n\n const nextNormalizedShift = normalizedShifts.find((s) => s.startedAt.isAfter(now));\n\n if (nextNormalizedShift) {\n const shift = findShiftByName(sortedShifts, nextNormalizedShift.name);\n if (shift) {\n return { date: makeShiftDateTime(today, shift), shift, isCurrentShift: false };\n }\n }\n\n const tomorrow = dayjs(now).add(1, 'day').startOf('day');\n const tomorrowNormalizedShifts = normalizeShifts(sortedShifts, tomorrow);\n\n if (tomorrowNormalizedShifts.length > 0) {\n const shift = findShiftByName(sortedShifts, tomorrowNormalizedShifts[0].name);\n if (shift) {\n return { date: makeShiftDateTime(tomorrow.format('YYYY-MM-DD'), shift), shift, isCurrentShift: false };\n }\n }\n\n return null;\n};\n\nconst MAX_DAYS_FORWARD = 14;\n\nexport const canNavigate = (currentState: ViewState, shifts: ListShifts_Shift[], direction: 'prev' | 'next'): boolean => {\n const sortedShifts = sortShifts(shifts);\n const currentDate = extractDate(currentState.date);\n const minDate = getMinDate(sortedShifts);\n const maxDate = dayjs().add(MAX_DAYS_FORWARD, 'day').format('YYYY-MM-DD');\n const currentIndex = sortedShifts.findIndex((s) => s.id === currentState.shift.id);\n\n if (direction === 'next') {\n if (currentIndex < sortedShifts.length - 1) {\n return true;\n }\n const nextDate = dayjs(currentDate).add(1, 'day').format('YYYY-MM-DD');\n return nextDate <= maxDate;\n }\n\n if (currentIndex > 0) {\n return currentDate >= minDate;\n }\n const prevDate = dayjs(currentDate).subtract(1, 'day').format('YYYY-MM-DD');\n return prevDate >= minDate;\n};\n\nexport const navigateState = (currentState: ViewState, shifts: ListShifts_Shift[], direction: 'prev' | 'next'): ViewState => {\n const sortedShifts = sortShifts(shifts);\n if (!canNavigate(currentState, sortedShifts, direction)) {\n return currentState;\n }\n\n const currentDate = extractDate(currentState.date);\n const currentIndex = sortedShifts.findIndex((s) => s.id === currentState.shift.id);\n\n const checkIsCurrent = (date: string, shift: ListShifts_Shift): boolean => {\n const now = dayjs();\n const normalizedShifts = normalizeShifts(sortedShifts, now);\n const currentNormalized = getCurrentShift(now, normalizedShifts);\n if (!currentNormalized || currentNormalized.name !== shift.name) return false;\n return currentNormalized.startedAt.format('YYYY-MM-DD') === dayjs(date).format('YYYY-MM-DD');\n };\n\n if (direction === 'next') {\n if (currentIndex < sortedShifts.length - 1) {\n const shift = sortedShifts[currentIndex + 1];\n const date = makeShiftDateTime(currentDate, shift);\n return { date, shift, isCurrentShift: checkIsCurrent(date, shift) };\n }\n const nextDate = dayjs(currentDate).add(1, 'day').format('YYYY-MM-DD');\n const shift = sortedShifts[0];\n return { date: makeShiftDateTime(nextDate, shift), shift, isCurrentShift: false };\n }\n\n if (currentIndex > 0) {\n const shift = sortedShifts[currentIndex - 1];\n const date = makeShiftDateTime(currentDate, shift);\n return { date, shift, isCurrentShift: checkIsCurrent(date, shift) };\n }\n const prevDate = dayjs(currentDate).subtract(1, 'day').format('YYYY-MM-DD');\n const shift = sortedShifts[sortedShifts.length - 1];\n return { date: makeShiftDateTime(prevDate, shift), shift, isCurrentShift: false };\n};\n","export const LIBRARY_VERSION = '1.0.9';\n","import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { TabContext, TabList, TabPanel } from '@mui/lab';\nimport { FormControl, InputLabel, MenuItem, Select, Tab, TextField } from '@mui/material';\nimport { SettingsFormContentProps } from 'andoncloud-widget-base';\n\nimport { WidgetData, WidgetSettings } from '@/types';\n\nconst SettingsFormContent: React.FC<SettingsFormContentProps<WidgetData, WidgetSettings>> = ({ data, formProps }) => {\n // -- Local state --\n const [selectedTab, setSelectedTab] = useState('filters');\n\n // -- Translation --\n const { t } = useTranslation();\n\n return (\n <TabContext value={selectedTab}>\n <TabList onChange={(_, value) => setSelectedTab(value)} centered>\n <Tab label={t('stationAssignmentWidget.settingsFiltersTab')} value=\"filters\" />\n <Tab label={t('stationAssignmentWidget.advanced')} value=\"advanced\" />\n </TabList>\n\n <TabPanel value=\"filters\">\n <FormControl fullWidth>\n <InputLabel id=\"department-label\">{t('stationAssignmentWidget.department')}</InputLabel>\n <Select\n name=\"departmentId\"\n labelId=\"department-label\"\n variant=\"outlined\"\n value={formProps.values.departmentId ?? ''}\n onChange={formProps.handleChange}\n fullWidth\n >\n <MenuItem value=\"\">{t('stationAssignmentWidget.allDepartments')}</MenuItem>\n {data.departments.map((department) => (\n <MenuItem key={department.id} value={department.id}>\n {department.name}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n <FormControl sx={{ mt: 2 }} fullWidth>\n <InputLabel id=\"refresh-interval-label\">{t('stationAssignmentWidget.refreshInterval')}</InputLabel>\n <Select\n name=\"refreshInterval\"\n labelId=\"refresh-interval-label\"\n variant=\"outlined\"\n value={formProps.values.refreshInterval}\n onChange={formProps.handleChange}\n fullWidth\n >\n <MenuItem value={15}>15s</MenuItem>\n <MenuItem value={30}>30s</MenuItem>\n <MenuItem value={60}>60s</MenuItem>\n </Select>\n </FormControl>\n </TabPanel>\n\n <TabPanel value=\"advanced\">\n <TextField\n name=\"customTitle\"\n label={t('stationAssignmentWidget.customTitle')}\n value={formProps.values.customTitle}\n onChange={formProps.handleChange}\n fullWidth\n />\n </TabPanel>\n </TabContext>\n );\n};\n\nexport default SettingsFormContent;\n","import { DropResult } from '@hello-pangea/dnd';\nimport { ListWorkplaceAssignments_WorkplaceWithAssignment, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nimport { WidgetData } from '@/types';\n\nexport const presenceLabelKeys: Record<PresenceStatusEnum, string> = {\n [PresenceStatusEnum.Present]: 'stationAssignmentWidget.presenceStatusPresent',\n [PresenceStatusEnum.NotPresent]: 'stationAssignmentWidget.presenceStatusNotPresent',\n [PresenceStatusEnum.PresentElsewhere]: 'stationAssignmentWidget.presenceStatusPresentElsewhere',\n};\n\ntype QueryWorkplace = ListWorkplaceAssignments_WorkplaceWithAssignment['workplace'];\n\nexport interface OperatorContext {\n presenceStatus?: PresenceStatusEnum;\n assignedWorkplaceName?: string;\n isUnplanned?: boolean;\n checkedInWorkplace?: QueryWorkplace;\n}\n\nexport const findOperatorContext = (data: WidgetData, userId: string): OperatorContext => {\n for (const wp of data.workplaces) {\n const assigned = wp.assignedOperators.find((op) => op.user.id === userId);\n if (assigned) {\n return {\n presenceStatus: assigned.presenceStatus,\n assignedWorkplaceName: wp.workplace.name,\n };\n }\n }\n\n for (const wp of data.workplaces) {\n const unplanned = wp.unplannedOperators.find((op) => op.user.id === userId && !op.plannedWorkplace);\n if (unplanned) {\n return {\n isUnplanned: true,\n checkedInWorkplace: wp.workplace,\n };\n }\n }\n\n return {};\n};\n\nconst UNPLANNED_PREFIX = 'unplanned:';\n\nexport const isUnplannedDraggableId = (draggableId: string): boolean => draggableId.startsWith(UNPLANNED_PREFIX);\n\nexport const extractUserId = (draggableId: string): string =>\n isUnplannedDraggableId(draggableId) ? draggableId.slice(UNPLANNED_PREFIX.length) : draggableId;\n\nexport const makeUnplannedDraggableId = (userId: string): string => `${UNPLANNED_PREFIX}${userId}`;\n\nexport const getUpdatedData = (\n data: WidgetData,\n result: DropResult,\n): Pick<WidgetData, 'workplaces' | 'unassignedOperators'> | null => {\n const { source, destination, draggableId } = result;\n\n if (!destination) return null;\n if (source.droppableId === destination.droppableId && source.index === destination.index) return null;\n\n const isUnplanned = isUnplannedDraggableId(draggableId);\n const userId = extractUserId(draggableId);\n const fromPool = source.droppableId === 'pool';\n const toPool = destination.droppableId === 'pool';\n\n if (isUnplanned && toPool) return null;\n\n let movedUser: { id: string; name: string } | undefined;\n let movedPresenceStatus = PresenceStatusEnum.NotPresent;\n\n const newUnassignedOperators = [...data.unassignedOperators];\n const newWorkplaces = data.workplaces.map((wp) => ({\n ...wp,\n assignedOperators: [...wp.assignedOperators],\n unplannedOperators: [...wp.unplannedOperators],\n }));\n\n if (isUnplanned) {\n const sourceWp = newWorkplaces.find((wp) => wp.workplace.id === source.droppableId);\n if (sourceWp) {\n const idx = sourceWp.unplannedOperators.findIndex((op) => op.user.id === userId);\n if (idx !== -1) {\n movedUser = sourceWp.unplannedOperators[idx].user;\n movedPresenceStatus = PresenceStatusEnum.PresentElsewhere;\n sourceWp.unplannedOperators.splice(idx, 1);\n }\n }\n const poolIdx = newUnassignedOperators.findIndex((op) => op.id === userId);\n if (poolIdx !== -1) {\n newUnassignedOperators.splice(poolIdx, 1);\n }\n } else if (fromPool) {\n const idx = newUnassignedOperators.findIndex((op) => op.id === userId);\n if (idx !== -1) {\n movedUser = newUnassignedOperators[idx];\n newUnassignedOperators.splice(idx, 1);\n }\n } else {\n const sourceWp = newWorkplaces.find((wp) => wp.workplace.id === source.droppableId);\n if (sourceWp) {\n const idx = sourceWp.assignedOperators.findIndex((op) => op.user.id === userId);\n if (idx !== -1) {\n movedUser = sourceWp.assignedOperators[idx].user;\n movedPresenceStatus = sourceWp.assignedOperators[idx].presenceStatus;\n sourceWp.assignedOperators.splice(idx, 1);\n sourceWp.assignedCount -= 1;\n }\n }\n }\n\n if (!movedUser) return null;\n\n if (toPool) {\n newUnassignedOperators.splice(destination.index, 0, movedUser);\n } else {\n const destWp = newWorkplaces.find((wp) => wp.workplace.id === destination.droppableId);\n if (destWp) {\n destWp.assignedOperators.splice(destination.index, 0, {\n user: movedUser,\n presenceStatus: movedPresenceStatus,\n });\n destWp.assignedCount += 1;\n }\n }\n\n return { workplaces: newWorkplaces, unassignedOperators: newUnassignedOperators };\n};\n","import { SxProps, Theme } from '@mui/material/styles';\nimport { PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nconst presenceColors: Record<PresenceStatusEnum, string> = {\n [PresenceStatusEnum.Present]: 'success.main',\n [PresenceStatusEnum.NotPresent]: 'error.main',\n [PresenceStatusEnum.PresentElsewhere]: 'warning.main',\n};\n\nexport const makePresenceIndicatorStyles = (status: PresenceStatusEnum): SxProps<Theme> => ({\n flexShrink: 0,\n width: 12,\n height: 12,\n borderRadius: '50%',\n backgroundColor: presenceColors[status],\n});\n\nconst styles: Record<string, SxProps<Theme>> = {\n properties: {\n gap: (theme) => theme.spacing(0.5),\n },\n property: {\n marginLeft: (theme) => theme.spacing(2),\n },\n propertyLabel: {\n marginBottom: (theme) => theme.spacing(0.5),\n fontWeight: 'bold',\n },\n propertyValue: {\n fontSize: (theme) => theme.typography.pxToRem(14),\n color: 'text.primary',\n },\n checkedInValue: {\n fontSize: (theme) => theme.typography.pxToRem(14),\n fontWeight: 600,\n color: 'warning.main',\n },\n unplannedIndicator: {\n flexShrink: 0,\n width: 12,\n height: 12,\n borderRadius: '50%',\n backgroundColor: 'success.main',\n },\n assignButton: {\n marginTop: (theme) => theme.spacing(2),\n },\n separator: {\n width: '100%',\n height: '1px',\n margin: (theme) => theme.spacing(1, 0),\n background: 'linear-gradient(90deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.05) 100%)',\n },\n};\n\nexport default styles;\n","import { Fragment, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Box, Button, CircularProgress, Stack, Typography } from '@mui/material';\nimport { GqlClients, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\nimport dayjs from 'dayjs';\n\nimport { ViewState, WidgetData } from '@/types';\n\nimport { findOperatorContext, presenceLabelKeys } from '../../helpers';\n\nimport styles, { makePresenceIndicatorStyles } from './styles';\n\ninterface MainContentProps {\n userId: string;\n data: WidgetData;\n gqlClients: GqlClients;\n viewState: ViewState;\n onAssignToWorkplace?: (userId: string, workplaceId: string) => void;\n}\n\nconst getPresenceLabel = (t: (key: string) => string, status?: PresenceStatusEnum): string => {\n if (!status) return t('stationAssignmentWidget.unassignedOperator');\n return t(presenceLabelKeys[status]);\n};\n\nconst formatDuration = (startedAt: string): string => {\n const start = dayjs(startedAt);\n const now = dayjs();\n const totalMinutes = now.diff(start, 'minute');\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n\n if (hours > 0) {\n return `${hours}h ${minutes}m`;\n }\n return `${minutes}m`;\n};\n\nconst MainContent: React.FC<MainContentProps> = ({ userId, data, gqlClients, viewState, onAssignToWorkplace }) => {\n const { t } = useTranslation();\n const [checkedInAt, setCheckedInAt] = useState<string | null>(null);\n const [checkedInWorkplaceName, setCheckedInWorkplaceName] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const context = findOperatorContext(data, userId);\n const isPresent =\n context.isUnplanned ||\n context.presenceStatus === PresenceStatusEnum.Present ||\n context.presenceStatus === PresenceStatusEnum.PresentElsewhere;\n\n const handleAssignHere = () => {\n if (!context.checkedInWorkplace || !onAssignToWorkplace) return;\n onAssignToWorkplace(userId, context.checkedInWorkplace.id);\n };\n\n useEffect(() => {\n if (!isPresent || !gqlClients.graphqlSdk) return;\n\n setIsLoading(true);\n void gqlClients.graphqlSdk\n .usersPresences({\n filter: {\n user_id_eq: userId,\n shift_id_eq: viewState.shift.id,\n finished_at_null: 'true',\n },\n })\n .then(({ usersPresences }) => {\n if (usersPresences.length > 0) {\n const latest = usersPresences[usersPresences.length - 1];\n setCheckedInAt(latest.startedAt);\n const wp = data.workplaces.find((w) => w.workplace.id === latest.workplaceId);\n if (wp) {\n setCheckedInWorkplaceName(wp.workplace.name);\n }\n }\n return undefined;\n })\n .catch(() => undefined)\n .finally(() => setIsLoading(false));\n }, [userId, isPresent, gqlClients.graphqlSdk, viewState.shift.id, data.workplaces]);\n\n return (\n <Stack sx={styles.properties}>\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.presenceStatus')}</Typography>\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n {context.isUnplanned && (\n <Box title={t('stationAssignmentWidget.checkedInUnassigned')} sx={styles.unplannedIndicator} />\n )}\n {!context.isUnplanned && context.presenceStatus && (\n <Box\n title={t(presenceLabelKeys[context.presenceStatus])}\n sx={makePresenceIndicatorStyles(context.presenceStatus)}\n />\n )}\n <Typography sx={styles.propertyValue}>\n {context.isUnplanned\n ? t('stationAssignmentWidget.checkedInUnassigned')\n : getPresenceLabel(t, context.presenceStatus)}\n </Typography>\n </Stack>\n </Box>\n\n {context.isUnplanned && context.checkedInWorkplace && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.checkedInLocation')}</Typography>\n <Typography sx={styles.propertyValue}>{context.checkedInWorkplace.name}</Typography>\n </Box>\n </Fragment>\n )}\n\n {context.assignedWorkplaceName && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.assignedWorkplace')}</Typography>\n <Typography sx={styles.propertyValue}>{context.assignedWorkplaceName}</Typography>\n </Box>\n </Fragment>\n )}\n\n {isLoading && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property} display=\"flex\" justifyContent=\"center\" mt={2}>\n <CircularProgress size={16} />\n </Box>\n </Fragment>\n )}\n\n {!isLoading && checkedInAt && (\n <Fragment>\n {context.presenceStatus === PresenceStatusEnum.PresentElsewhere && checkedInWorkplaceName && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.checkedInLocation')}</Typography>\n <Typography sx={styles.checkedInValue}>{checkedInWorkplaceName}</Typography>\n </Box>\n </Fragment>\n )}\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.checkedInTime')}</Typography>\n <Typography sx={styles.propertyValue}>{dayjs(checkedInAt).format('HH:mm')}</Typography>\n </Box>\n <Box sx={styles.separator} />\n <Box sx={styles.property}>\n <Typography sx={styles.propertyLabel}>{t('stationAssignmentWidget.workingFor')}</Typography>\n <Typography sx={styles.propertyValue}>{formatDuration(checkedInAt)}</Typography>\n </Box>\n </Fragment>\n )}\n {context.isUnplanned && context.checkedInWorkplace && (\n <Fragment>\n <Box sx={styles.separator} />\n <Box sx={styles.property} display=\"flex\" justifyContent=\"flex-end\">\n <Button\n variant=\"contained\"\n size=\"small\"\n color=\"info\"\n sx={styles.assignButton}\n onClick={handleAssignHere}\n data-testid=\"stationAssignment.sidePanel.assignHere\"\n >\n {t('stationAssignmentWidget.assignHere')}\n </Button>\n </Box>\n </Fragment>\n )}\n </Stack>\n );\n};\n\nexport default MainContent;\n","import { SxProps, Theme } from '@mui/material';\n\nexport const makeDropZoneStyles = (isDraggingOver: boolean): SxProps<Theme> => ({\n height: '100%',\n transition: 'background-color 0.2s ease',\n backgroundColor: isDraggingOver ? 'rgba(0,0,0,0.1)' : 'transparent',\n});\n","import { Droppable, DroppableProps, DroppableProvided } from '@hello-pangea/dnd';\nimport { Box } from '@mui/material';\n\nimport { makeDropZoneStyles } from './styles';\n\ninterface DropZoneProps {\n droppableId: string;\n children: (provided: DroppableProvided) => React.ReactNode;\n renderClone?: DroppableProps['renderClone'];\n}\n\nconst DropZone: React.FC<DropZoneProps> = ({ droppableId, children, renderClone }) => (\n <Droppable droppableId={droppableId} renderClone={renderClone}>\n {(provided, snapshot) => (\n <Box ref={provided.innerRef} {...provided.droppableProps} sx={makeDropZoneStyles(snapshot.isDraggingOver)}>\n {children(provided)}\n {provided.placeholder}\n </Box>\n )}\n </Droppable>\n);\n\nexport default DropZone;\n","import { SxProps, Theme } from '@mui/material';\nimport { PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nconst presenceColors: Record<PresenceStatusEnum, string> = {\n [PresenceStatusEnum.Present]: 'success.main',\n [PresenceStatusEnum.NotPresent]: 'error.main',\n [PresenceStatusEnum.PresentElsewhere]: 'warning.main',\n};\n\nexport const makeCardStyles = (dragging?: boolean, clickable = true): SxProps<Theme> => ({\n display: 'flex',\n alignItems: 'center',\n gap: (theme) => theme.spacing(1),\n cursor: clickable ? 'pointer' : 'default',\n padding: (theme) => theme.spacing(1),\n borderBottom: '1px solid rgba(255, 255, 255, 0.15)',\n boxShadow: 'none',\n '&:last-of-type': {\n borderBottom: 'none',\n },\n ...(clickable && {\n '&:hover': {\n backgroundColor: 'rgba(255, 255, 255, 0.05)',\n },\n }),\n ...(dragging && {\n opacity: 0.5,\n }),\n});\n\nexport const makePresenceDotStyles = (status: PresenceStatusEnum): SxProps<Theme> => ({\n flexShrink: 0,\n width: 10,\n height: 10,\n borderRadius: '50%',\n backgroundColor: presenceColors[status],\n});\n\nexport const unplannedDotStyles: SxProps<Theme> = {\n flexShrink: 0,\n width: 10,\n height: 10,\n borderRadius: '50%',\n backgroundColor: 'success.main',\n};\n\nconst styles: Record<string, SxProps<Theme>> = {\n name: {\n flexGrow: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n removeButton: {\n flexShrink: 0,\n opacity: 0.6,\n padding: (theme) => theme.spacing(0.25),\n marginLeft: 'auto',\n '&:hover': {\n opacity: 1,\n },\n },\n};\n\nexport default styles;\n","import { useTranslation } from 'react-i18next';\n\nimport { Draggable, DraggableProvided } from '@hello-pangea/dnd';\nimport CloseIcon from '@mui/icons-material/Close';\nimport { Box, Card, IconButton, Typography } from '@mui/material';\nimport { PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nimport { OperatorUser } from '@/types';\n\nimport { presenceLabelKeys } from '../helpers';\n\nimport styles, { makeCardStyles, makePresenceDotStyles, unplannedDotStyles } from './styles';\n\ninterface OperatorCardProps {\n user: OperatorUser;\n index: number;\n draggableId: string;\n showPresence?: boolean;\n presenceStatus?: PresenceStatusEnum;\n isUnplanned?: boolean;\n onClick?: () => void;\n onRemove?: () => void;\n}\n\ninterface DraggingOperatorCardProps {\n provided: DraggableProvided;\n user: OperatorUser;\n}\n\nexport const DraggingOperatorCard: React.FC<DraggingOperatorCardProps> = ({ provided, user }) => (\n <Card ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} sx={makeCardStyles(true)}>\n <Typography sx={styles.name}>{user.name}</Typography>\n </Card>\n);\n\nconst OperatorCard: React.FC<OperatorCardProps> = ({\n user,\n index,\n draggableId,\n showPresence,\n presenceStatus,\n isUnplanned,\n onClick,\n onRemove,\n}) => {\n const { t } = useTranslation();\n\n return (\n <Draggable draggableId={draggableId} index={index}>\n {(provided, snapshot) => (\n <Card\n ref={provided.innerRef}\n {...provided.draggableProps}\n {...provided.dragHandleProps}\n sx={makeCardStyles(snapshot.isDragging, !!onClick)}\n onClick={() => {\n if (!snapshot.isDragging && onClick) {\n onClick();\n }\n }}\n data-testid=\"stationAssignment.operatorCard\"\n >\n {isUnplanned && <Box title={t('stationAssignmentWidget.checkedInUnassigned')} sx={unplannedDotStyles} />}\n {!isUnplanned && showPresence && presenceStatus && (\n <Box title={t(presenceLabelKeys[presenceStatus])} sx={makePresenceDotStyles(presenceStatus)} />\n )}\n <Typography title={user.name} sx={styles.name}>\n {user.name}\n </Typography>\n {onRemove && (\n <IconButton\n title={t('stationAssignmentWidget.removeOperator')}\n size=\"small\"\n color=\"error\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n sx={styles.removeButton}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Card>\n )}\n </Draggable>\n );\n};\n\nexport default OperatorCard;\n","import { SxProps, Theme } from '@mui/material';\n\nconst styles: Record<string, SxProps<Theme>> = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n flexShrink: 0,\n width: 250,\n height: '100%',\n },\n header: {\n display: 'flex',\n padding: (theme) => theme.spacing(0.5, 1),\n },\n action: {\n display: 'flex',\n alignSelf: 'center',\n margin: (theme) => theme.spacing(0, 0, 0, 1),\n },\n search: {\n margin: (theme) => theme.spacing(0, 1, 1, 1),\n '&.MuiFormControl-root': {\n margin: 0,\n },\n '& .MuiOutlinedInput-notchedOutline': {\n border: 'none',\n },\n '& .MuiInputAdornment-root': {\n color: 'text.primary',\n },\n },\n content: {\n flexGrow: 1,\n padding: (theme) => theme.spacing(0.5),\n overflow: 'auto',\n },\n};\n\nexport default styles;\n","import { Fragment, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport SearchIcon from '@mui/icons-material/Search';\nimport { Card, CardContent, CardHeader, InputAdornment, TextField } from '@mui/material';\n\nimport { OperatorUser } from '@/types';\n\nimport DropZone from '../DropZone';\nimport OperatorCard, { DraggingOperatorCard } from '../OperatorCard';\n\nimport styles from './styles';\n\ninterface PoolColumnProps {\n operators: OperatorUser[];\n unplannedUserIds?: Set<string>;\n onOperatorClick?: (userId: string, userName: string) => void;\n}\n\nconst PoolColumn: React.FC<PoolColumnProps> = ({ operators, unplannedUserIds, onOperatorClick }) => {\n const [searchQuery, setSearchQuery] = useState('');\n const { t } = useTranslation();\n\n const poolOperators = useMemo(\n () => (unplannedUserIds ? operators.filter((user) => !unplannedUserIds.has(user.id)) : operators),\n [operators, unplannedUserIds],\n );\n\n const filteredOperators = useMemo(() => {\n if (!searchQuery.trim()) return poolOperators;\n const query = searchQuery.toLowerCase();\n return poolOperators.filter((user) =>\n user.name\n .toLowerCase()\n .split(' ')\n .some((part) => part.startsWith(query)),\n );\n }, [poolOperators, searchQuery]);\n\n return (\n <Card sx={styles.root} data-testid=\"stationAssignment.pool\">\n <CardHeader\n title={t('stationAssignmentWidget.unassignedPool')}\n action={poolOperators.length}\n slotProps={{ title: { variant: 'subtitle1' }, action: { sx: styles.action } }}\n sx={styles.header}\n />\n <TextField\n size=\"small\"\n label={t('stationAssignmentWidget.searchOperators')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n sx={styles.search}\n data-testid=\"stationAssignment.pool.search\"\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n <CardContent sx={styles.content}>\n <DropZone\n droppableId=\"pool\"\n renderClone={(provided, _, rubric) => (\n <DraggingOperatorCard provided={provided} user={filteredOperators[rubric.source.index]} />\n )}\n >\n {() => (\n <Fragment>\n {filteredOperators.map((user, index) => (\n <OperatorCard\n key={user.id}\n user={user}\n index={index}\n draggableId={user.id}\n onClick={onOperatorClick ? () => onOperatorClick(user.id, user.name) : undefined}\n />\n ))}\n </Fragment>\n )}\n </DropZone>\n </CardContent>\n </Card>\n );\n};\n\nexport default PoolColumn;\n","import { SxProps, Theme } from '@mui/material';\n\ntype BorderStatus = 'normal' | 'overcapacity' | 'unplanned';\n\nconst borderConfig: Record<\n Exclude<BorderStatus, 'normal'>,\n { borderColor: string; labelColor: string; labelBg: string }\n> = {\n overcapacity: { borderColor: 'error.main', labelColor: 'error.contrastText', labelBg: 'error.main' },\n unplanned: { borderColor: 'warning.main', labelColor: 'warning.contrastText', labelBg: 'warning.main' },\n};\n\nexport const makeRootStyles = (\n borderStatus: BorderStatus,\n frozenHeight?: number,\n borderLabel?: string,\n): SxProps<Theme> => ({\n display: 'flex',\n flexDirection: 'column',\n flexShrink: 0,\n position: 'relative',\n width: 250,\n minHeight: 200,\n border: borderStatus !== 'normal' ? 2 : 1,\n borderColor: borderStatus !== 'normal' ? borderConfig[borderStatus].borderColor : 'divider',\n ...(borderStatus !== 'normal' && {\n '&::after': {\n content: `\"${borderLabel}\"`,\n position: 'absolute',\n bottom: -2,\n left: -2,\n padding: (theme: Theme) => theme.spacing(0.25, 0.75),\n fontSize: (theme: Theme) => theme.typography.pxToRem(10),\n color: borderConfig[borderStatus].labelColor,\n backgroundColor: borderConfig[borderStatus].labelBg,\n borderRadius: '0 4px 0 0',\n textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',\n pointerEvents: 'none',\n },\n }),\n ...(frozenHeight !== undefined && {\n overflow: 'hidden',\n maxHeight: frozenHeight,\n }),\n});\n\nconst styles: Record<string, SxProps<Theme>> = {\n header: {\n display: 'flex',\n padding: (theme) => theme.spacing(0.5, 1),\n '& .MuiCardHeader-content': {\n overflowX: 'hidden',\n },\n },\n title: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n action: {\n display: 'flex',\n alignSelf: 'center',\n gap: (theme) => theme.spacing(1),\n margin: (theme) => theme.spacing(0, 0, 0, 1),\n },\n content: {\n flexGrow: 1,\n padding: (theme) => theme.spacing(0.5),\n },\n unplannedLabel: {\n display: 'block',\n margin: (theme) => theme.spacing(1, 0),\n padding: (theme) => theme.spacing(0, 0.5),\n color: 'text.primary',\n opacity: 0.7,\n textAlign: 'center',\n },\n unplannedSeparator: {\n height: '1px',\n backgroundColor: 'text.primary',\n opacity: 0.3,\n },\n};\n\nconst badgeColors: Record<string, { color: string; backgroundColor: string }> = {\n ok: { color: 'success.contrastText', backgroundColor: 'success.main' },\n missing: { color: 'error.contrastText', backgroundColor: 'error.main' },\n overcapacity: { color: 'error.contrastText', backgroundColor: 'error.main' },\n warning: { color: 'warning.contrastText', backgroundColor: 'warning.main' },\n};\n\nexport const makeStatusBadgeStyles = (status: 'missing' | 'overcapacity' | 'ok' | 'warning'): SxProps<Theme> => ({\n padding: (theme) => `${theme.spacing(0.25)} ${theme.spacing(1)}`,\n borderRadius: 1,\n ...badgeColors[status],\n});\n\nexport default styles;\n","import { Fragment, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Box, Card, CardContent, CardHeader, Typography } from '@mui/material';\nimport { ListWorkplaceAssignments_WorkplaceWithAssignment, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\n\nimport { ViewState } from '@/types';\n\nimport DropZone from '../DropZone';\nimport { makeUnplannedDraggableId } from '../helpers';\nimport OperatorCard, { DraggingOperatorCard } from '../OperatorCard';\n\nimport styles, { makeRootStyles, makeStatusBadgeStyles } from './styles';\n\nconst getStatusBadge = (assignment: ListWorkplaceAssignments_WorkplaceWithAssignment, unplannedCount: number) => {\n const presentCount = assignment.assignedOperators.filter(\n (op) => op.presenceStatus === PresenceStatusEnum.Present,\n ).length;\n const checkedInHereCount = presentCount + unplannedCount;\n\n if (checkedInHereCount > assignment.recommendedOperators) {\n const diff = checkedInHereCount - assignment.recommendedOperators;\n return {\n text: `+${diff}`,\n status: 'overcapacity' as const,\n titleKey: 'stationAssignmentWidget.statusOvercapacity',\n checkedInHereCount,\n };\n }\n if (checkedInHereCount < assignment.recommendedOperators) {\n const diff = checkedInHereCount - assignment.recommendedOperators;\n return {\n text: `${diff}`,\n status: 'missing' as const,\n titleKey: 'stationAssignmentWidget.statusMissing',\n checkedInHereCount,\n };\n }\n if (unplannedCount === 0) {\n return { text: 'OK', status: 'ok' as const, titleKey: 'stationAssignmentWidget.statusOk', checkedInHereCount };\n }\n return {\n text: 'OK',\n status: 'warning' as const,\n titleKey: 'stationAssignmentWidget.statusUnplanned',\n checkedInHereCount,\n };\n};\n\nconst getPlanningBadge = (assignment: ListWorkplaceAssignments_WorkplaceWithAssignment) => {\n const diff = assignment.assignedCount - assignment.recommendedOperators;\n if (diff > 0) {\n return {\n text: `+${diff}`,\n status: 'overcapacity' as const,\n titleKey: 'stationAssignmentWidget.statusOvercapacity',\n };\n }\n if (diff < 0) {\n return { text: `${diff}`, status: 'missing' as const, titleKey: 'stationAssignmentWidget.statusMissing' };\n }\n return { text: 'OK', status: 'ok' as const, titleKey: 'stationAssignmentWidget.statusOk' };\n};\n\ninterface WorkplaceColumnProps {\n assignment: ListWorkplaceAssignments_WorkplaceWithAssignment;\n viewState: ViewState;\n registerRef?: (el: HTMLDivElement | null) => void;\n frozenHeight?: number;\n onOperatorClick?: (userId: string, userName: string) => void;\n onRemoveOperator?: (userId: string) => void;\n}\n\nconst WorkplaceColumn: React.FC<WorkplaceColumnProps> = ({\n assignment,\n viewState,\n registerRef,\n frozenHeight,\n onOperatorClick,\n onRemoveOperator,\n}) => {\n const { t } = useTranslation();\n const { isCurrentShift } = viewState;\n\n const sortedOperators = useMemo(\n () =>\n [...assignment.assignedOperators].sort((a, b) =>\n a.user.name.localeCompare(b.user.name, undefined, { numeric: true }),\n ),\n [assignment.assignedOperators],\n );\n\n const sortedUnplanned = useMemo(\n () =>\n isCurrentShift\n ? assignment.unplannedOperators\n .filter((op) => !op.plannedWorkplace)\n .sort((a, b) => a.user.name.localeCompare(b.user.name, undefined, { numeric: true }))\n : [],\n [assignment.unplannedOperators, isCurrentShift],\n );\n\n const { localOperators, elsewhereOperators } = useMemo(() => {\n if (!isCurrentShift) {\n return { localOperators: sortedOperators, elsewhereOperators: [] };\n }\n return {\n localOperators: sortedOperators.filter((op) => op.presenceStatus !== PresenceStatusEnum.PresentElsewhere),\n elsewhereOperators: sortedOperators.filter((op) => op.presenceStatus === PresenceStatusEnum.PresentElsewhere),\n };\n }, [sortedOperators, isCurrentShift]);\n\n const badge = isCurrentShift ? getStatusBadge(assignment, sortedUnplanned.length) : null;\n const planningBadge = !isCurrentShift ? getPlanningBadge(assignment) : null;\n const activeBadge = badge || planningBadge!;\n\n const isOvercapacity = isCurrentShift\n ? assignment.assignedCount > assignment.recommendedOperators ||\n (badge?.checkedInHereCount ?? 0) > assignment.recommendedOperators\n : assignment.assignedCount > assignment.recommendedOperators;\n\n const getBorderStatus = () => {\n if (isOvercapacity) return { status: 'overcapacity' as const, label: t('stationAssignmentWidget.overcapacity') };\n if (isCurrentShift && sortedUnplanned.length > 0)\n return { status: 'unplanned' as const, label: t('stationAssignmentWidget.unplannedStaffing') };\n return { status: 'normal' as const, label: '' };\n };\n const border = getBorderStatus();\n\n const displayCount = badge ? badge.checkedInHereCount : assignment.assignedCount;\n\n return (\n <Card\n ref={registerRef}\n sx={makeRootStyles(border.status, frozenHeight, border.label)}\n data-testid=\"stationAssignment.workplace\"\n >\n <CardHeader\n title={assignment.workplace.name}\n action={\n <Fragment>\n <Typography data-testid=\"stationAssignment.workplace.count\">{`${displayCount}/${assignment.recommendedOperators}`}</Typography>\n <Typography\n title={t(activeBadge.titleKey)}\n variant=\"caption\"\n sx={makeStatusBadgeStyles(activeBadge.status)}\n data-testid=\"stationAssignment.workplace.badge\"\n >\n {activeBadge.text}\n </Typography>\n </Fragment>\n }\n slotProps={{\n title: { variant: 'subtitle1', title: assignment.workplace.name, sx: styles.title },\n action: { sx: styles.action },\n }}\n sx={styles.header}\n />\n <CardContent sx={styles.content}>\n <DropZone\n droppableId={assignment.workplace.id}\n renderClone={(provided, _, rubric) => {\n const idx = rubric.source.index;\n const assignedCount = localOperators.length + elsewhereOperators.length;\n let user;\n if (idx < localOperators.length) {\n user = localOperators[idx]?.user;\n } else if (idx < assignedCount) {\n user = elsewhereOperators[idx - localOperators.length]?.user;\n } else {\n user = sortedUnplanned[idx - assignedCount]?.user;\n }\n if (!user)\n return <Card ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} />;\n return <DraggingOperatorCard provided={provided} user={user} />;\n }}\n >\n {() => {\n const elsewhereOffset = localOperators.length;\n const unplannedOffset = elsewhereOffset + elsewhereOperators.length;\n return (\n <Fragment>\n {localOperators.map((operator, index) => (\n <OperatorCard\n key={operator.user.id}\n user={operator.user}\n index={index}\n draggableId={operator.user.id}\n showPresence={isCurrentShift}\n presenceStatus={operator.presenceStatus}\n onClick={onOperatorClick ? () => onOperatorClick(operator.user.id, operator.user.name) : undefined}\n onRemove={onRemoveOperator ? () => onRemoveOperator(operator.user.id) : undefined}\n />\n ))}\n {elsewhereOperators.length > 0 && (\n <Fragment>\n <Typography\n variant=\"caption\"\n sx={styles.unplannedLabel}\n data-testid=\"stationAssignment.workplace.elsewhereLabel\"\n >\n {t('stationAssignmentWidget.presentElsewhereLabel')}\n </Typography>\n <Box sx={styles.unplannedSeparator} />\n </Fragment>\n )}\n {elsewhereOperators.map((operator, index) => (\n <OperatorCard\n key={operator.user.id}\n user={operator.user}\n index={elsewhereOffset + index}\n draggableId={operator.user.id}\n showPresence\n presenceStatus={operator.presenceStatus}\n onClick={onOperatorClick ? () => onOperatorClick(operator.user.id, operator.user.name) : undefined}\n onRemove={onRemoveOperator ? () => onRemoveOperator(operator.user.id) : undefined}\n />\n ))}\n {sortedUnplanned.length > 0 && (\n <Fragment>\n <Typography\n variant=\"caption\"\n sx={styles.unplannedLabel}\n data-testid=\"stationAssignment.workplace.unplannedLabel\"\n >\n {t('stationAssignmentWidget.unplannedSectionLabel')}\n </Typography>\n <Box sx={styles.unplannedSeparator} />\n </Fragment>\n )}\n {sortedUnplanned.map((unplanned, index) => (\n <OperatorCard\n key={unplanned.user.id}\n user={unplanned.user}\n index={unplannedOffset + index}\n draggableId={makeUnplannedDraggableId(unplanned.user.id)}\n isUnplanned\n onClick={\n onOperatorClick ? () => onOperatorClick(unplanned.user.id, unplanned.user.name) : undefined\n }\n />\n ))}\n </Fragment>\n );\n }}\n </DropZone>\n </CardContent>\n </Card>\n );\n};\n\nexport default WorkplaceColumn;\n","import { Theme } from '@mui/material';\n\nconst styles = {\n grid: (theme: Theme) => ({\n display: 'flex',\n flexDirection: 'column',\n flexWrap: 'wrap',\n alignContent: 'flex-start',\n gap: theme.spacing(1),\n height: '100%',\n overflowX: 'auto',\n }),\n};\n\nexport default styles;\n","import { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { DragDropContext, DragStart, DropResult } from '@hello-pangea/dnd';\nimport { Box } from '@mui/material';\nimport { GqlClients, PresenceStatusEnum } from 'andoncloud-dashboard-toolkit';\nimport { SidePanelProps } from 'andoncloud-sdk';\n\nimport { ViewState, WidgetData } from '@/types';\nimport { extractDate } from '@/utils/state';\n\nimport MainContent from './OperatorCard/SidePanel/MainContent';\nimport { extractUserId, getUpdatedData } from './helpers';\nimport PoolColumn from './PoolColumn';\nimport WorkplaceColumn from './WorkplaceColumn';\n\nimport styles from './styles';\n\ninterface AssignmentBoardProps {\n data: WidgetData;\n viewState: ViewState;\n gqlClients: GqlClients;\n updateData: (data: Partial<WidgetData>) => void;\n updateSidePanelProps: (props: Partial<SidePanelProps>) => void;\n refetchAssignments: () => void;\n}\n\nconst AssignmentBoard: React.FC<AssignmentBoardProps> = ({\n data,\n viewState,\n gqlClients,\n updateData,\n updateSidePanelProps,\n refetchAssignments,\n}) => {\n const { graphqlSdk } = gqlClients;\n const [frozenHeights, setFrozenHeights] = useState<Record<string, number>>({});\n\n // Refs to workplace column DOM elements for freezing heights during drag\n const columnRefs = useRef<Record<string, HTMLDivElement | null>>({});\n\n // Ref to access latest data in async callbacks (avoids stale closures)\n const dataRef = useRef(data);\n dataRef.current = data;\n\n const unplannedUserIds = useMemo(() => {\n const ids = new Set<string>();\n for (const wp of data.workplaces) {\n for (const op of wp.unplannedOperators) {\n ids.add(op.user.id);\n }\n }\n return ids;\n }, [data.workplaces]);\n\n const registerColumnRef = useCallback((id: string, el: HTMLDivElement | null) => {\n columnRefs.current[id] = el;\n }, []);\n\n const handleDragStart = useCallback((_: DragStart) => {\n const heights: Record<string, number> = {};\n Object.entries(columnRefs.current).forEach(([id, el]) => {\n if (el) {\n heights[id] = el.getBoundingClientRect().height;\n }\n });\n setFrozenHeights(heights);\n }, []);\n\n const handleRemoveOperator = useCallback(\n (userId: string, workplaceId: string) => {\n if (!graphqlSdk) return;\n\n const workplace = data.workplaces.find((w) => w.workplace.id === workplaceId);\n const operator = workplace?.assignedOperators.find((o) => o.user.id === userId);\n if (!workplace || !operator) return;\n\n updateData({\n workplaces: data.workplaces.map((w) =>\n w.workplace.id === workplaceId\n ? {\n ...w,\n assignedOperators: w.assignedOperators.filter((o) => o.user.id !== userId),\n assignedCount: w.assignedCount - 1,\n }\n : w,\n ),\n unassignedOperators: [operator.user, ...data.unassignedOperators],\n });\n\n graphqlSdk\n .unassignOperator({\n input: {\n userId,\n shiftId: viewState.shift.id,\n validFrom: extractDate(viewState.date),\n },\n })\n .catch(() => {});\n },\n [graphqlSdk, data, viewState, updateData],\n );\n\n const handleAssignUnplanned = useCallback(\n (userId: string, workplaceId: string) => {\n if (!graphqlSdk) return;\n\n updateData({\n workplaces: data.workplaces.map((w) => {\n const isTarget = w.workplace.id === workplaceId;\n const unplanned = w.unplannedOperators.find((op) => op.user.id === userId);\n return {\n ...w,\n unplannedOperators: w.unplannedOperators.filter((op) => op.user.id !== userId),\n ...(isTarget && unplanned\n ? {\n assignedOperators: [\n ...w.assignedOperators,\n { user: unplanned.user, presenceStatus: PresenceStatusEnum.Present },\n ].sort((a, b) => a.user.name.localeCompare(b.user.name, undefined, { numeric: true })),\n assignedCount: w.assignedCount + 1,\n }\n : {}),\n };\n }),\n unassignedOperators: data.unassignedOperators.filter((op) => op.id !== userId),\n });\n\n updateSidePanelProps({ open: false });\n\n graphqlSdk\n .assignOperator({\n input: {\n userId,\n workplaceId,\n shiftId: viewState.shift.id,\n validFrom: extractDate(viewState.date),\n },\n })\n .then(refetchAssignments)\n .catch(() => {});\n },\n [graphqlSdk, data, viewState, updateData, updateSidePanelProps, refetchAssignments],\n );\n\n const handleOperatorClick = useCallback(\n (userId: string, userName: string) => {\n updateSidePanelProps({\n open: true,\n title: userName,\n width: '25%',\n mainContent: (\n <MainContent\n userId={userId}\n data={data}\n gqlClients={gqlClients}\n viewState={viewState}\n onAssignToWorkplace={handleAssignUnplanned}\n />\n ),\n });\n },\n [data, gqlClients, viewState, updateSidePanelProps, handleAssignUnplanned],\n );\n\n const handleDragEnd = (result: DropResult) => {\n setFrozenHeights({});\n if (!graphqlSdk) return;\n\n const updatedData = getUpdatedData(data, result);\n if (!updatedData) return;\n\n updateData(updatedData);\n\n const { destination, draggableId } = result;\n const userId = extractUserId(draggableId);\n const toPool = destination!.droppableId === 'pool';\n\n if (toPool) {\n graphqlSdk\n .unassignOperator({\n input: {\n userId,\n shiftId: viewState.shift.id,\n validFrom: extractDate(viewState.date),\n },\n })\n .catch(() => {});\n } else {\n const workplaceId = destination!.droppableId;\n const assignPromise = graphqlSdk.assignOperator({\n input: {\n userId,\n workplaceId,\n shiftId: viewState.shift.id,\n validFrom: viewState.date,\n },\n });\n\n if (viewState.isCurrentShift) {\n assignPromise\n .then(() =>\n graphqlSdk.usersPresences({\n filter: {\n user_id_eq: userId,\n shift_id_eq: viewState.shift.id,\n finished_at_null: 'true',\n },\n }),\n )\n .then(({ usersPresences }) => {\n if (usersPresences.length === 0) return undefined;\n const latest = usersPresences[usersPresences.length - 1];\n const presenceStatus =\n latest.workplaceId === workplaceId ? PresenceStatusEnum.Present : PresenceStatusEnum.PresentElsewhere;\n return updateData({\n workplaces: dataRef.current.workplaces.map((w) =>\n w.workplace.id === workplaceId\n ? {\n ...w,\n assignedOperators: w.assignedOperators.map((op) =>\n op.user.id === userId ? { ...op, presenceStatus } : op,\n ),\n }\n : w,\n ),\n });\n })\n .catch(() => {});\n } else {\n assignPromise.catch(() => {});\n }\n }\n };\n\n return (\n <DragDropContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>\n <Box sx={styles.grid}>\n <PoolColumn\n operators={data.unassignedOperators}\n unplannedUserIds={viewState.isCurrentShift ? unplannedUserIds : undefined}\n onOperatorClick={viewState.isCurrentShift ? handleOperatorClick : undefined}\n />\n {data.workplaces.map((assignment) => (\n <WorkplaceColumn\n key={assignment.workplace.id}\n assignment={assignment}\n viewState={viewState}\n registerRef={(el) => registerColumnRef(assignment.workplace.id, el)}\n frozenHeight={frozenHeights[assignment.workplace.id]}\n onOperatorClick={viewState.isCurrentShift ? handleOperatorClick : undefined}\n onRemoveOperator={(userId) => handleRemoveOperator(userId, assignment.workplace.id)}\n />\n ))}\n </Box>\n </DragDropContext>\n );\n};\n\nexport default AssignmentBoard;\n","import { SxProps, Theme } from '@mui/material';\n\nconst styles: Record<string, SxProps<Theme>> = {\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: (theme) => theme.spacing(2),\n marginBottom: (theme) => theme.spacing(1),\n padding: (theme) => theme.spacing(1),\n borderBottom: '1px solid #717171',\n background: '#525860',\n },\n label: {\n minWidth: 200,\n textAlign: 'center',\n color: 'rgba(255, 255, 255, 0.65)',\n },\n};\n\nexport default styles;\n","import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';\nimport ChevronRightIcon from '@mui/icons-material/ChevronRight';\nimport { Box, IconButton, Typography } from '@mui/material';\nimport dayjs from 'dayjs';\n\nimport { ViewState } from '@/types';\n\nimport styles from './styles';\n\ninterface NavigationProps {\n viewState: ViewState;\n departmentName?: string;\n canPrev?: boolean;\n canNext?: boolean;\n onNavigate: (direction: 'prev' | 'next') => void;\n}\n\nconst isOvernightShift = (shift: ViewState['shift']): boolean => {\n const start = dayjs(shift.startedAt);\n const end = dayjs(shift.finishedAt);\n return start.hour() * 60 + start.minute() > end.hour() * 60 + end.minute();\n};\n\nconst formatLabel = (viewState: ViewState): string => {\n const { shift } = viewState;\n const startDate = dayjs(viewState.date);\n\n if (isOvernightShift(shift)) {\n const endDate = startDate.add(1, 'day');\n const shiftStart = dayjs(shift.startedAt);\n const shiftEnd = dayjs(shift.finishedAt);\n return `${startDate.format('DD.MM')} / ${endDate.format('DD.MM')} (${shiftStart.format(\n 'HH:mm',\n )} - ${shiftEnd.format('HH:mm')})`;\n }\n\n return `${startDate.format('DD.MM')} - ${shift.name}`;\n};\n\nconst Navigation: React.FC<NavigationProps> = ({\n viewState,\n departmentName,\n canPrev = true,\n canNext = true,\n onNavigate,\n}) => (\n <Box sx={styles.root} data-testid=\"stationAssignment.navigation\">\n <IconButton\n color=\"secondary\"\n disabled={!canPrev}\n onClick={() => onNavigate('prev')}\n data-testid=\"stationAssignment.navigation.prev\"\n >\n <ChevronLeftIcon />\n </IconButton>\n <Typography sx={styles.label} data-testid=\"stationAssignment.navigation.label\">\n {formatLabel(viewState)}\n {departmentName && ` - ${departmentName}`}\n </Typography>\n <IconButton\n color=\"secondary\"\n disabled={!canNext}\n onClick={() => onNavigate('next')}\n data-testid=\"stationAssignment.navigation.next\"\n >\n <ChevronRightIcon />\n </IconButton>\n </Box>\n);\n\nexport default Navigation;\n","import { SxProps, Theme } from '@mui/material/styles';\n\nconst styles: Record<string, SxProps<Theme>> = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n },\n loader: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n flexGrow: 1,\n },\n};\n\nexport default styles;\n","import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Box, CircularProgress, Typography } from '@mui/material';\nimport {\n getCurrentShift,\n normalizeShifts,\n ListShifts_Shift,\n WorkplaceEvent,\n WorkplaceEventDocument,\n WorkplaceEventSubscriptionPayload,\n} from 'andoncloud-dashboard-toolkit';\nimport dayjs from 'dayjs';\nimport { print } from 'graphql';\n\nimport { ViewState, WidgetViewProps } from '@/types';\nimport { canNavigate, getInitialState, makeShiftDateTime, navigateState } from '@/utils/state';\n\nimport AssignmentBoard from '../AssignmentBoard';\nimport Navigation from '../Navigation';\n\nimport styles from './styles';\n\nconst WidgetView: React.FC<WidgetViewProps> = ({ data, updateData, gqlClients, settings, updateSidePanelProps }) => {\n const { t } = useTranslation();\n const [viewState, setViewState] = useState<ViewState | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [gqlWsSubscribed, setGqlWsSubscribed] = useState(false);\n\n const departmentName = useMemo(() => {\n if (!settings?.departmentId) return undefined;\n const department = data.departments.find((d) => d.id === settings.departmentId);\n return department?.name;\n }, [settings?.departmentId, data.departments]);\n\n const { graphqlSdk, gqlWsClient } = gqlClients;\n const shiftsRef = useRef(data.shifts);\n shiftsRef.current = data.shifts;\n\n useEffect(() => {\n if (data.shifts.length > 0 && !viewState) {\n const initialState = getInitialState(data.shifts);\n\n if (initialState) {\n setViewState(initialState);\n }\n }\n }, [data.shifts, viewState]);\n\n useEffect(() => {\n if (!gqlWsClient || !data?.workplaces?.length || gqlWsSubscribed) return;\n\n data.workplaces.forEach(({ workplace }) =>\n gqlWsClient.subscribe<WorkplaceEventSubscriptionPayload>(\n print(WorkplaceEventDocument),\n { id: workplace.id },\n ({ event, subject }) => {\n if (event === WorkplaceEvent.CurrentShiftChanged && subject) {\n const newShift = subject as ListShifts_Shift;\n const now = dayjs();\n const sorted = [...shiftsRef.current].sort((a, b) => a.startedAt.localeCompare(b.startedAt));\n const normalized = normalizeShifts(sorted, now);\n const current = getCurrentShift(now, normalized);\n const shiftDateTime = current\n ? current.startedAt.format('YYYY-MM-DDTHH:mm:ssZ')\n : makeShiftDateTime(now.format('YYYY-MM-DD'), newShift);\n\n setViewState((prev) => {\n if (!prev?.isCurrentShift) return prev;\n return { date: shiftDateTime, shift: newShift, isCurrentShift: true };\n });\n }\n },\n ),\n );\n\n setGqlWsSubscribed(true);\n }, [gqlWsClient, data?.workplaces, gqlWsSubscribed]);\n\n const fetchAssignmentsRef = useRef<(showLoading?: boolean) => void>(null!);\n\n fetchAssignmentsRef.current = (showLoading = false) => {\n if (!graphqlSdk || !viewState || !updateData) return;\n\n if (showLoading) setIsLoading(true);\n void graphqlSdk\n .workplaceAssignments({\n input: {\n date: viewState.date,\n shiftId: viewState.shift.id,\n departmentId: settings?.departmentId || undefined,\n },\n })\n .then(({ workplaceAssignments }) => {\n return updateData(workplaceAssignments);\n })\n .catch(() => {})\n .finally(() => {\n if (showLoading) setIsLoading(false);\n });\n };\n\n useEffect(() => {\n if (!viewState || !graphqlSdk) return;\n\n fetchAssignmentsRef.current?.(true);\n\n const refreshInterval = (settings?.refreshInterval || 60) * 1000;\n const intervalId = setInterval(() => fetchAssignmentsRef.current?.(), refreshInterval);\n\n return () => clearInterval(intervalId);\n }, [viewState, graphqlSdk, settings?.departmentId, settings?.refreshInterval]);\n\n const handleNavigate = useCallback(\n (direction: 'prev' | 'next') => {\n if (!viewState) return;\n const newState = navigateState(viewState, data.shifts, direction);\n setViewState(newState);\n },\n [viewState, data.shifts],\n );\n\n const canPrev = viewState ? canNavigate(viewState, data.shifts, 'prev') : false;\n const canNext = viewState ? canNavigate(viewState, data.shifts, 'next') : false;\n\n return (\n <Box sx={styles.root}>\n {viewState ? (\n <Fragment>\n <Navigation\n viewState={viewState}\n departmentName={departmentName}\n canPrev={canPrev}\n canNext={canNext}\n onNavigate={handleNavigate}\n />\n {isLoading ? (\n <Box sx={styles.loader} data-testid=\"stationAssignment.loader\">\n <CircularProgress />\n </Box>\n ) : (\n <AssignmentBoard\n data={data}\n viewState={viewState}\n gqlClients={gqlClients}\n updateData={updateData!}\n updateSidePanelProps={updateSidePanelProps}\n refetchAssignments={() => fetchAssignmentsRef.current?.()}\n />\n )}\n </Fragment>\n ) : (\n <Typography data-testid=\"stationAssignment.noShifts\">\n {t('stationAssignmentWidget.noShiftsAvailable')}\n </Typography>\n )}\n </Box>\n );\n};\n\nexport default WidgetView;\n","import { TFunction } from 'i18next';\nimport * as yup from 'yup';\n\nexport const getSettingsFormProps = (t: TFunction) => {\n yup.setLocale({\n mixed: {\n required: t('stationAssignmentWidget.thisFieldIsRequired'),\n },\n });\n return {\n initialValues: {\n customTitle: '',\n departmentId: undefined,\n refreshInterval: 60,\n },\n validationSchema: yup.object({\n departmentId: yup.string(),\n refreshInterval: yup.number().oneOf([15, 30, 60]).required(),\n }),\n };\n};\n","import { useEffect, useState } from 'react';\n\nimport { useGqlClients, WidgetProps } from 'andoncloud-dashboard-toolkit';\nimport { BaseWidget } from 'andoncloud-widget-base';\n\nimport locales from '@/locales';\nimport { WidgetData, WidgetSettings } from '@/types';\nimport { getInitialState } from '@/utils/state';\nimport { LIBRARY_VERSION } from '@/version';\n\nimport SettingsFormContent from '../SettingsFormContent';\nimport WidgetView from '../WidgetView';\n\nimport { getSettingsFormProps } from './utils';\n\nconst Widget: React.FC<WidgetProps<WidgetData, WidgetSettings>> = ({\n url,\n wsUrl,\n lang,\n data,\n settings,\n ...widgetProps\n}) => {\n const { graphqlSdk, gqlWsClient } = useGqlClients({ url, wsUrl, lang });\n const [widgetData, setWidgetData] = useState<WidgetData | undefined>(data);\n\n useEffect(() => {\n if (!data && graphqlSdk) {\n Promise.all([graphqlSdk.departments(), graphqlSdk.listShifts()])\n .then(([{ departments }, { shifts }]) => {\n const initialState = getInitialState(shifts);\n\n if (!initialState) {\n return;\n }\n const { date, shift } = initialState;\n\n return graphqlSdk\n .workplaceAssignments({\n input: {\n date,\n shiftId: shift.id,\n departmentId: settings?.departmentId || undefined,\n },\n })\n .then(({ workplaceAssignments }) => {\n return setWidgetData({\n ...workplaceAssignments,\n departments,\n shifts,\n });\n });\n })\n .catch(() => {});\n }\n }, [data, graphqlSdk, settings?.departmentId]);\n\n return (\n <BaseWidget\n {...widgetProps}\n lang={lang}\n locales={locales}\n data={widgetData}\n gqlClients={{ graphqlSdk, gqlWsClient }}\n WidgetView={WidgetView}\n getSettingsFormProps={getSettingsFormProps}\n SettingsFormContent={SettingsFormContent}\n version={LIBRARY_VERSION}\n data-testid=\"station-assignment-widget\"\n />\n );\n};\n\nexport default Widget;\n","import type { FilterValues } from 'andoncloud-dashboard-toolkit';\nimport i18n from 'i18next';\n\nimport type { WidgetData, WidgetSettings } from '../types';\n\nconst ns = 'stationAssignmentWidget';\n\nconst t = (key: string, lng: string, options?: Record<string, unknown>) => i18n.t(`${ns}.${key}`, { lng, ...options });\n\nexport const getDisplayName = (lang: string) => t('displayName', lang);\n\nexport const getTitle = (\n data: WidgetData | undefined,\n _settings: WidgetSettings | undefined,\n _filters: FilterValues | undefined,\n lang: string,\n): string => {\n const name = getDisplayName(lang);\n\n const workplaces = data?.workplaces;\n if (!workplaces?.length) return name;\n\n const unassignedCount = data?.unassignedOperators?.length ?? 0;\n const parts = [t('titleWorkplaces', lang, { count: workplaces.length })];\n\n if (unassignedCount > 0) {\n parts.push(t('titleUnassigned', lang, { count: unassignedCount }));\n }\n\n return `${name} — ${parts.join(', ')}`;\n};\n","import { registerTranslations } from 'andoncloud-sdk';\n\nimport locales from './locales';\n\nregisterTranslations(locales);\n\nexport { default as Widget } from './components/Widget';\nexport { getDisplayName, getTitle } from './core/title';\n\nexport const thumbnail: string | undefined = undefined;\n\nexport const requiredFeatures: string[] = ['feature.station-assignment-widget'];\nexport const extraPermissions: string[] = [];\n\nexport { LIBRARY_VERSION as version } from './version';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "andoncloud-station-assignment-widget",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Made with create-andoncloud-widget",
5
5
  "author": "Adrian Olszewski",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  "andoncloud-dashboard-toolkit": "^1.0.0",
30
30
  "andoncloud-sdk": "^1.0.0",
31
31
  "andoncloud-widget-base": "^1.0.0",
32
+ "dayjs": "^1.11.0",
32
33
  "graphql-request": "^6.0.0",
33
34
  "i18next": "^22.0.0",
34
35
  "react": "^18.0.0",
@@ -46,10 +47,10 @@
46
47
  "@types/react": "^19.2.14",
47
48
  "actioncable": "^5.2.8",
48
49
  "ajv": "^8.18.0",
49
- "andoncloud-dashboard-toolkit": "^1.5.54",
50
+ "andoncloud-dashboard-toolkit": "^1.5.63",
50
51
  "andoncloud-library-scripts": "^2.0.0",
51
52
  "andoncloud-sdk": "^1.7.25",
52
- "andoncloud-widget-base": "^1.2.24",
53
+ "andoncloud-widget-base": "^1.2.25",
53
54
  "cypress": "^15.12.0",
54
55
  "eslint-config-andoncloud": "^1.1.0",
55
56
  "graphql-request": "^6.1.0",
@@ -73,7 +74,6 @@
73
74
  ],
74
75
  "dependencies": {
75
76
  "@hello-pangea/dnd": "^18.0.1",
76
- "dayjs": "^1.11.20",
77
77
  "yup": "^1.7.1"
78
78
  }
79
79
  }