diff --git a/apps/web/src/apps/main/modules/field/cycles/presentation/components/detail-component/detail-weekdays.tsx b/apps/web/src/apps/main/modules/field/cycles/presentation/components/detail-component/detail-weekdays.tsx index 454b3e9..c0d8f92 100644 --- a/apps/web/src/apps/main/modules/field/cycles/presentation/components/detail-component/detail-weekdays.tsx +++ b/apps/web/src/apps/main/modules/field/cycles/presentation/components/detail-component/detail-weekdays.tsx @@ -1,4 +1,4 @@ -import { Box, Paper, Stack, Text } from '@repo/ui/components'; +import { Box, FieldValue, Paper, SimpleGrid, Tabs, Text } from '@repo/ui/components'; import { RouteMap } from '@repo/ui/map'; import { useDetailPageContext, useEnterpriseModuleTranslationContext } from '@repo/ui/foundations'; import type { CycleEntity } from '../../../domain/entities'; @@ -7,6 +7,7 @@ export function DetailWeekdays() { const { detailData } = useDetailPageContext(); const { t } = useEnterpriseModuleTranslationContext(); const weekdays = detailData?.weekdays ?? []; + const activeWeekday = weekdays[0]?.weekday; if (weekdays.length === 0) { return ( @@ -20,20 +21,38 @@ export function DetailWeekdays() { } return ( - - {weekdays.map((row) => ( - - - {t(`weekday_${row.weekday}`)} - - - {(row.destinations ?? []).map((destination, index) => `${index + 1}. ${destination.customerId}`).join(' | ') || t('empty_route')} - - - - - - ))} - + + + {t('section_weekdays')} + + + + {weekdays.map((row) => ( + + {t(`weekday_${row.weekday}`)} + + ))} + + {weekdays.map((row) => ( + + + + + + `${index + 1}. ${destination.customerId}`) + .join(' | ') || t('empty_route') + } + /> + + + + + ))} + + ); } diff --git a/apps/web/src/apps/main/modules/field/cycles/presentation/components/form-component/form-weekdays.tsx b/apps/web/src/apps/main/modules/field/cycles/presentation/components/form-component/form-weekdays.tsx index 86e91e3..c37ce9e 100644 --- a/apps/web/src/apps/main/modules/field/cycles/presentation/components/form-component/form-weekdays.tsx +++ b/apps/web/src/apps/main/modules/field/cycles/presentation/components/form-component/form-weekdays.tsx @@ -1,4 +1,4 @@ -import { Box, FieldAsyncSelect, FieldSwitch, Paper, SimpleGrid, Stack, Text } from '@repo/ui/components'; +import { Box, FieldAsyncSelect, FieldSwitch, Paper, SimpleGrid, Tabs, Text } from '@repo/ui/components'; import { useEnterpriseModuleTranslationContext, useFormPageContext } from '@repo/ui/foundations'; import { loadBranchOptions } from '../../../../shared/load-branch-options'; import { loadCustomerOptions } from '../../../../shared/load-customer-options'; @@ -14,69 +14,77 @@ export function FormWeekdays() { const weekdayRows = (formControl.watch('weekdayRows') as CycleWeekdayRow[] | undefined) ?? []; return ( - - {t('section_weekdays')} - {WEEKDAYS.map((weekday, index) => { - const row = weekdayRows[index]; - const enabled = Boolean(row?.enabled); - return ( - - + + + {t('section_weekdays')} + + + + {WEEKDAYS.map((weekday) => ( + {t(`weekday_${weekday}`)} - - - {enabled ? ( - - - - control={formControl.control} - name={`weekdayRows.${index}.startBranch`} - label={t('common:fields.startBranch')} - valueKey="id" - labelKey="name" - required - searchable - loadOptions={loadBranchOptions} - defaultOptions={(row?.startBranch ? [row.startBranch] : []) as any} - renderLabel={relationLabel} - /> - - control={formControl.control} - name={`weekdayRows.${index}.endBranch`} - label={t('common:fields.endBranch')} - valueKey="id" - labelKey="name" - required - searchable - loadOptions={loadBranchOptions} - defaultOptions={(row?.endBranch ? [row.endBranch] : []) as any} - renderLabel={relationLabel} - /> - + + ))} + + {WEEKDAYS.map((weekday, index) => { + const row = weekdayRows[index]; + const enabled = Boolean(row?.enabled); + return ( + + + {enabled ? ( - - control={formControl.control} - name={`weekdayRows.${index}.customers`} - label={t('common:fields.customers')} - valueKey="id" - labelKey="name" - required - searchable - multiple - loadOptions={loadCustomerOptions} - defaultOptions={(row?.customers ?? []) as any} - renderLabel={relationLabel} - /> + + + control={formControl.control} + name={`weekdayRows.${index}.startBranch`} + label={t('common:fields.startBranch')} + valueKey="id" + labelKey="name" + required + searchable + loadOptions={loadBranchOptions} + defaultOptions={(row?.startBranch ? [row.startBranch] : []) as any} + renderLabel={relationLabel} + /> + + control={formControl.control} + name={`weekdayRows.${index}.endBranch`} + label={t('common:fields.endBranch')} + valueKey="id" + labelKey="name" + required + searchable + loadOptions={loadBranchOptions} + defaultOptions={(row?.endBranch ? [row.endBranch] : []) as any} + renderLabel={relationLabel} + /> + + + + control={formControl.control} + name={`weekdayRows.${index}.customers`} + label={t('common:fields.customers')} + valueKey="id" + labelKey="name" + required + searchable + multiple + loadOptions={loadCustomerOptions} + defaultOptions={(row?.customers ?? []) as any} + renderLabel={relationLabel} + /> + - - ) : null} - - ); - })} - + ) : null} + + ); + })} + + ); } diff --git a/packages/ui/src/components/map/leaflet-stacking.css b/packages/ui/src/components/map/leaflet-stacking.css new file mode 100644 index 0000000..8064460 --- /dev/null +++ b/packages/ui/src/components/map/leaflet-stacking.css @@ -0,0 +1,12 @@ +/* Leaflet panes/controls use z-index 400–1000 and would cover Mantine modals (200) unless contained. */ +.tg-map-viewport { + position: relative; + z-index: 0; + isolation: isolate; + overflow: hidden; +} + +.leaflet-container { + isolation: isolate; + z-index: 0; +} diff --git a/packages/ui/src/components/map/location-map.test.tsx b/packages/ui/src/components/map/location-map.test.tsx index 05fa327..a10f23f 100644 --- a/packages/ui/src/components/map/location-map.test.tsx +++ b/packages/ui/src/components/map/location-map.test.tsx @@ -112,4 +112,9 @@ describe('LocationMap', () => { expect(setView).not.toHaveBeenCalled(); expect(panTo).not.toHaveBeenCalled(); }); + + it('keeps the map in a local stacking context so Leaflet panes stay below modals', () => { + renderMap(); + expect(screen.getByTestId('osm-map').closest('.tg-map-viewport')).not.toBeNull(); + }); }); diff --git a/packages/ui/src/components/map/location-map.tsx b/packages/ui/src/components/map/location-map.tsx index 8f002f8..ace9562 100644 --- a/packages/ui/src/components/map/location-map.tsx +++ b/packages/ui/src/components/map/location-map.tsx @@ -10,6 +10,7 @@ import { toLocationLatLng, } from './location-point'; import 'leaflet/dist/leaflet.css'; +import './leaflet-stacking.css'; export interface LocationMapProps { latitude?: unknown; @@ -119,7 +120,8 @@ export function LocationMap({ h={height} bdrs="md" bd="1px solid var(--mantine-color-default-border)" - style={{ overflow: 'hidden', cursor: interactive ? 'crosshair' : undefined }} + className="tg-map-viewport" + style={{ cursor: interactive ? 'crosshair' : undefined }} > diff --git a/packages/ui/src/components/map/route-map.tsx b/packages/ui/src/components/map/route-map.tsx index 911f724..cc93570 100644 --- a/packages/ui/src/components/map/route-map.tsx +++ b/packages/ui/src/components/map/route-map.tsx @@ -5,6 +5,7 @@ import type { RouteGeometry } from './route-geometry'; import { toLeafletLatLngs } from './route-geometry'; import { OSM_ATTRIBUTION, OSM_TILE_URL } from './osm'; import 'leaflet/dist/leaflet.css'; +import './leaflet-stacking.css'; function FitRouteBounds({ positions }: { positions: Array<[number, number]> }) { const map = useMap(); @@ -38,7 +39,7 @@ export function RouteMap({ geometry, height = 280 }: RouteMapProps) { } return ( - + diff --git a/packages/ui/src/provider/theme-provider.tsx b/packages/ui/src/provider/theme-provider.tsx index bf3a658..56cbf23 100644 --- a/packages/ui/src/provider/theme-provider.tsx +++ b/packages/ui/src/provider/theme-provider.tsx @@ -52,6 +52,9 @@ export function ThemeProvider({ children, colorScheme = 'light', density = 'comp fontFamilyMonospace: typography.fontFamilyMonospace, headings: typography.headings, radius: radius, + components: { + Drawer: { defaultProps: { zIndex: 1100 } }, + }, }); const selectedDensity = densityMap[density]; @@ -59,7 +62,7 @@ export function ThemeProvider({ children, colorScheme = 'light', density = 'comp return ( - + {children} diff --git a/packages/ui/src/theme/tokens/density.ts b/packages/ui/src/theme/tokens/density.ts index 43abfc1..eb302b2 100644 --- a/packages/ui/src/theme/tokens/density.ts +++ b/packages/ui/src/theme/tokens/density.ts @@ -36,7 +36,7 @@ export const standardDensity: MantineThemeOverride = { Pagination: { defaultProps: { size: 'md' } }, Table: { defaultProps: { verticalSpacing: 'sm', horizontalSpacing: 'md' } }, Card: { defaultProps: { padding: 'md' } }, - Modal: { defaultProps: { padding: 'md' } }, + Modal: { defaultProps: { padding: 'md', zIndex: 1100 } }, }, }; @@ -99,7 +99,7 @@ export const compactDensity: MantineThemeOverride = { }, }, Card: { defaultProps: { padding: 'sm' } }, // Card padding shrinks - Modal: { defaultProps: { padding: 'sm' } }, // Modal padding shrinks + Modal: { defaultProps: { padding: 'sm', zIndex: 1100 } }, // Modal padding shrinks; above Leaflet panes (1000) // 5. Force 13px ('sm') text inside 'sm' physical inputs Input: {