@arquimedes.co/eureka-forms 3.0.49-new-steps → 3.0.50-test

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.
Files changed (145) hide show
  1. package/dist/@Types/Condition.d.ts +6 -4
  2. package/dist/@Types/ErkValue.d.ts +16 -0
  3. package/dist/@Types/ErkValue.js +1 -0
  4. package/dist/@Types/Form.d.ts +1 -0
  5. package/dist/@Types/FormStep.d.ts +10 -8
  6. package/dist/@Types/FormStep.js +1 -2
  7. package/dist/@Types/User.d.ts +13 -0
  8. package/dist/@Types/User.js +1 -0
  9. package/dist/App/App.js +1 -1
  10. package/dist/App/AppFunctions.js +8 -3
  11. package/dist/App/AppHooks.js +20 -1
  12. package/dist/Form/Form.js +6 -2
  13. package/dist/Form/Form.module.css +48 -39
  14. package/dist/FormSteps/ApiSelectorStep/MaterialApiSelectorStep/MaterialApiSelectorStep.js +8 -4
  15. package/dist/FormSteps/CBRStepMapper.js +1 -1
  16. package/dist/FormSteps/ClassifierSelectorStep/MaterialClassifierSelectorStep/MaterialClassifierSelectorStep.js +2 -2
  17. package/dist/FormSteps/DatePickerRangeStep/MaterialDatePickerRangeStep/MaterialDatePickerRangeStep.js +1 -1
  18. package/dist/FormSteps/EntityValueStep/MaterialEntityValuePickerStep/MaterialEntityValuePickerStep.js +52 -4
  19. package/dist/FormSteps/FileUploadStep/MaterialFileUploadStep/FileComponent/FileComponent.js +1 -1
  20. package/dist/FormSteps/FileUploadStep/MaterialFileUploadStep/FileComponent/FileComponent.module.css +1 -1
  21. package/dist/FormSteps/FileUploadStep/MaterialFileUploadStep/MaterialFileUploadStep.js +48 -17
  22. package/dist/FormSteps/FileUploadStep/MaterialFileUploadStep/MaterialFileUploadStep.module.css +16 -0
  23. package/dist/FormSteps/Step.js +0 -16
  24. package/dist/FormSteps/StepFunctions.js +6 -23
  25. package/dist/FormSteps/StepFunctions.test.js +3 -57
  26. package/dist/FormSteps/TitleStep/MaterialTitleStep/MaterialTitleStep.js +2 -1
  27. package/dist/Icons/@ErkIcon.d.ts +2 -2
  28. package/dist/Icons/@ErkIcon.js +2 -2
  29. package/dist/Icons/EmailIcon.d.ts +3 -0
  30. package/dist/Icons/{EditIcon.js → EmailIcon.js} +3 -3
  31. package/dist/Icons/Entities/SchoolIcon.d.ts +3 -0
  32. package/dist/Icons/Entities/SchoolIcon.js +7 -0
  33. package/dist/Icons/GroupIcon.d.ts +3 -0
  34. package/dist/Icons/GroupIcon.js +7 -0
  35. package/dist/Icons/LockedIcon.d.ts +3 -0
  36. package/dist/Icons/LockedIcon.js +7 -0
  37. package/dist/Login/Login.module.css +135 -0
  38. package/dist/Login/LoginLayout.module.css +68 -0
  39. package/dist/Login/LoginPage.d.ts +10 -0
  40. package/dist/Login/LoginPage.js +101 -0
  41. package/dist/Login/LoginTextField.d.ts +14 -0
  42. package/dist/Login/LoginTextField.js +29 -0
  43. package/dist/Services/ApiSelectorService.d.ts +366 -0
  44. package/dist/Services/ApiSelectorService.js +173 -0
  45. package/dist/Services/ApiSelectorService.test.d.ts +1 -0
  46. package/dist/Services/ApiSelectorService.test.js +87 -0
  47. package/dist/Services/DraftService.js +4 -1
  48. package/dist/Services/IntegrationService.d.ts +21 -0
  49. package/dist/Services/IntegrationService.js +22 -0
  50. package/dist/Services/UserService.d.ts +10 -0
  51. package/dist/Services/UserService.js +21 -0
  52. package/dist/Shared/ErkDatePicker/ErkDatePicker.js +11 -4
  53. package/dist/Shared/ErkDateRangePicker/ErkDateRangePicker.d.ts +3 -2
  54. package/dist/Shared/ErkDateRangePicker/ErkDateRangePicker.js +10 -4
  55. package/dist/Shared/ErkSelect/ErkSelect.d.ts +2 -2
  56. package/dist/Shared/InputIcon/InputIcon.js +6 -0
  57. package/dist/Shared/Navbar/Navbar.d.ts +2 -1
  58. package/dist/Shared/Navbar/Navbar.js +22 -3
  59. package/dist/Shared/Navbar/Navbar.module.css +22 -8
  60. package/dist/Shared/SmartDraftRenderer/LinkDecorator.d.ts +14 -0
  61. package/dist/Shared/SmartDraftRenderer/LinkDecorator.js +48 -0
  62. package/dist/Shared/SmartDraftRenderer/SmartDraftRenderer.js +10 -3
  63. package/dist/States/GlobalSlice.d.ts +4 -1
  64. package/dist/States/GlobalSlice.js +8 -1
  65. package/dist/constants/ErkIconTypes.d.ts +3 -1
  66. package/dist/constants/ErkIconTypes.js +2 -0
  67. package/dist/constants/ErkValueTypes.d.ts +6 -0
  68. package/dist/constants/ErkValueTypes.js +7 -0
  69. package/dist/constants/FormStepTypes.d.ts +3 -6
  70. package/dist/constants/FormStepTypes.js +1 -4
  71. package/dist/hooks.d.ts +3 -0
  72. package/dist/hooks.js +17 -1
  73. package/package.json +9 -3
  74. package/dist/@Types/AvailabilityFormStep.d.ts +0 -48
  75. package/dist/@Types/AvailabilityFormStep.js +0 -24
  76. package/dist/@Types/BankAccountFormStep.d.ts +0 -67
  77. package/dist/@Types/BankAccountFormStep.js +0 -14
  78. package/dist/@Types/BookingFormStep.d.ts +0 -156
  79. package/dist/@Types/BookingFormStep.js +0 -44
  80. package/dist/@Types/CalendarFormStep.d.ts +0 -192
  81. package/dist/@Types/CalendarFormStep.js +0 -48
  82. package/dist/@Types/CommunicationChannelFormStep.d.ts +0 -51
  83. package/dist/@Types/CommunicationChannelFormStep.js +0 -15
  84. package/dist/@Types/ConsentFormStep.d.ts +0 -36
  85. package/dist/@Types/ConsentFormStep.js +0 -8
  86. package/dist/@Types/EntityFormFormStep.d.ts +0 -66
  87. package/dist/@Types/EntityFormFormStep.js +0 -20
  88. package/dist/@Types/EventFormStep.d.ts +0 -52
  89. package/dist/@Types/EventFormStep.js +0 -13
  90. package/dist/@Types/ExternalReferenceFormStep.d.ts +0 -74
  91. package/dist/@Types/ExternalReferenceFormStep.js +0 -20
  92. package/dist/@Types/LocationFormStep.d.ts +0 -159
  93. package/dist/@Types/LocationFormStep.js +0 -46
  94. package/dist/@Types/NumericFormSteps.d.ts +0 -108
  95. package/dist/@Types/NumericFormSteps.js +0 -20
  96. package/dist/@Types/PredefinedSelectorFormStep.d.ts +0 -51
  97. package/dist/@Types/PredefinedSelectorFormStep.js +0 -39
  98. package/dist/@Types/StepRef.d.ts +0 -135
  99. package/dist/@Types/StepRef.js +0 -49
  100. package/dist/FormSteps/BookingStep/BookingStep.d.ts +0 -17
  101. package/dist/FormSteps/BookingStep/BookingStep.js +0 -14
  102. package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.d.ts +0 -3
  103. package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.js +0 -362
  104. package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.module.css +0 -174
  105. package/dist/FormSteps/CalendarStep/CalendarStep.d.ts +0 -7
  106. package/dist/FormSteps/CalendarStep/CalendarStep.js +0 -14
  107. package/dist/FormSteps/CalendarStep/MaterialCalendarStep/MaterialCalendarStep.d.ts +0 -3
  108. package/dist/FormSteps/CalendarStep/MaterialCalendarStep/MaterialCalendarStep.js +0 -269
  109. package/dist/FormSteps/CalendarStep/MaterialCalendarStep/MaterialCalendarStep.module.css +0 -531
  110. package/dist/FormSteps/LocationStep/LocationStep.d.ts +0 -10
  111. package/dist/FormSteps/LocationStep/LocationStep.js +0 -14
  112. package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.d.ts +0 -3
  113. package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.js +0 -47
  114. package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.module.css +0 -18
  115. package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.d.ts +0 -3
  116. package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.js +0 -168
  117. package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.module.css +0 -94
  118. package/dist/FormSteps/NumberStep/NumberStep.d.ts +0 -10
  119. package/dist/FormSteps/NumberStep/NumberStep.js +0 -14
  120. package/dist/Icons/AddIcon.d.ts +0 -3
  121. package/dist/Icons/AddIcon.js +0 -7
  122. package/dist/Icons/EditIcon.d.ts +0 -3
  123. package/dist/Icons/RemoveIcon.d.ts +0 -3
  124. package/dist/Icons/RemoveIcon.js +0 -7
  125. package/dist/Icons/ViewDayIcon.d.ts +0 -3
  126. package/dist/Icons/ViewDayIcon.js +0 -7
  127. package/dist/Icons/ViewWeekIcon.d.ts +0 -3
  128. package/dist/Icons/ViewWeekIcon.js +0 -7
  129. package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.d.ts +0 -19
  130. package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.js +0 -80
  131. package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.module.css +0 -82
  132. package/dist/Shared/ErkAddressAutocomplete/googlePlaces.d.ts +0 -29
  133. package/dist/Shared/ErkAddressAutocomplete/googlePlaces.js +0 -139
  134. package/dist/Shared/ErkLocationField/ErkLocationField.d.ts +0 -23
  135. package/dist/Shared/ErkLocationField/ErkLocationField.js +0 -73
  136. package/dist/Shared/ErkLocationField/ErkLocationField.module.css +0 -29
  137. package/dist/Shared/ErkLocationField/addressFields.d.ts +0 -12
  138. package/dist/Shared/ErkLocationField/addressFields.js +0 -34
  139. package/dist/Shared/ErkLocationField/locationRestrictions.d.ts +0 -6
  140. package/dist/Shared/ErkLocationField/locationRestrictions.js +0 -51
  141. package/dist/Shared/ErkLocationInput/ErkLocationInput.d.ts +0 -15
  142. package/dist/Shared/ErkLocationInput/ErkLocationInput.js +0 -499
  143. package/dist/Shared/ErkLocationInput/ErkLocationInput.module.css +0 -115
  144. package/dist/Shared/ErkNumberField/ErkNumberField.d.ts +0 -42
  145. package/dist/Shared/ErkNumberField/ErkNumberField.js +0 -170
@@ -1,174 +0,0 @@
1
- /* =========================================================================
2
- MaterialBookingStep — layout & typography only.
3
- All colors use MUI theme via styled() in the .tsx file.
4
- ========================================================================= */
5
-
6
- .container {
7
- display: flex;
8
- flex-direction: column;
9
- padding: 10px;
10
- padding-bottom: 0;
11
- padding-top: 5px;
12
- box-sizing: border-box;
13
- max-width: 100%;
14
- }
15
-
16
- /* =========================================================================
17
- Read-only summary
18
- ========================================================================= */
19
-
20
- .summaryDetails {
21
- display: flex;
22
- flex-direction: column;
23
- gap: 2px;
24
- }
25
-
26
- .summaryLabel {
27
- font-size: 11px;
28
- text-transform: uppercase;
29
- letter-spacing: 0.5px;
30
- opacity: 0.5;
31
- font-weight: 600;
32
- }
33
-
34
- .summaryMain {
35
- font-size: 14px;
36
- font-weight: 500;
37
- }
38
-
39
- /* =========================================================================
40
- Dialog header
41
- ========================================================================= */
42
-
43
- .dialogTitleInner {
44
- display: flex;
45
- align-items: center;
46
- gap: 8px;
47
- }
48
-
49
- .dialogTitleText {
50
- flex: 1;
51
- font-weight: 600;
52
- font-size: 17px;
53
- }
54
-
55
- /* =========================================================================
56
- Person phase
57
- ========================================================================= */
58
-
59
- .personList {
60
- display: flex;
61
- flex-direction: column;
62
- padding: 8px 0;
63
- flex: 1;
64
- overflow-y: auto;
65
- min-height: 0;
66
- }
67
-
68
- .personInfo {
69
- display: flex;
70
- flex-direction: column;
71
- gap: 2px;
72
- flex: 1;
73
- min-width: 0;
74
- }
75
-
76
- .personName {
77
- font-weight: 600;
78
- font-size: 14px;
79
- }
80
-
81
- .personRole {
82
- font-size: 12px;
83
- opacity: 0.55;
84
- }
85
-
86
- .personDesc {
87
- font-size: 12px;
88
- opacity: 0.45;
89
- overflow: hidden;
90
- text-overflow: ellipsis;
91
- white-space: nowrap;
92
- }
93
-
94
- /* =========================================================================
95
- Datetime phase
96
- ========================================================================= */
97
-
98
- .datetimePhase {
99
- display: flex;
100
- flex-direction: column;
101
- flex: 1;
102
- overflow: hidden;
103
- min-height: 0;
104
- }
105
-
106
- .dateSectionTitle {
107
- padding: 14px 20px 8px;
108
- font-weight: 600;
109
- font-size: 14px;
110
- }
111
-
112
- .dateStrip {
113
- display: flex;
114
- align-items: center;
115
- padding: 0 8px 8px;
116
- gap: 4px;
117
- }
118
-
119
- .dateChips {
120
- display: flex;
121
- flex: 1;
122
- gap: 4px;
123
- overflow-x: auto;
124
- scrollbar-width: none;
125
- }
126
-
127
- .dateChips::-webkit-scrollbar {
128
- display: none;
129
- }
130
-
131
- .chipDow {
132
- font-size: 11px;
133
- text-transform: lowercase;
134
- opacity: 0.75;
135
- }
136
-
137
- .chipNum {
138
- font-size: 16px;
139
- font-weight: 700;
140
- line-height: 1.1;
141
- }
142
-
143
- .chipMonth {
144
- font-size: 10px;
145
- opacity: 0.65;
146
- text-transform: lowercase;
147
- }
148
-
149
- /* =========================================================================
150
- Slot list
151
- ========================================================================= */
152
-
153
- .slotList {
154
- display: flex;
155
- flex-direction: column;
156
- gap: 6px;
157
- padding: 0 16px 20px;
158
- flex: 1;
159
- overflow-y: auto;
160
- min-height: 0;
161
- }
162
-
163
- .slotsLoading {
164
- display: flex;
165
- justify-content: center;
166
- padding: 24px 0;
167
- }
168
-
169
- .slotsEmpty {
170
- padding: 20px 4px;
171
- font-size: 13px;
172
- opacity: 0.5;
173
- text-align: center;
174
- }
@@ -1,7 +0,0 @@
1
- import { CalendarStep } from '../../@Types/CalendarFormStep';
2
- import { StepProps } from '../Step';
3
- export interface CalendarStepProps extends StepProps {
4
- step: CalendarStep;
5
- }
6
- declare function CalendarStepComponent(props: CalendarStepProps): JSX.Element;
7
- export default CalendarStepComponent;
@@ -1,14 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { FormStyleTypes } from '../../constants/FormStepTypes';
3
- import MaterialCalendarStep from './MaterialCalendarStep/MaterialCalendarStep';
4
- import { useAppSelector } from '../../hooks';
5
- function CalendarStepComponent(props) {
6
- const { formStyle } = useAppSelector((state) => state.global);
7
- switch (formStyle.type) {
8
- case FormStyleTypes.MATERIAL:
9
- default: {
10
- return _jsx(MaterialCalendarStep, { ...props });
11
- }
12
- }
13
- }
14
- export default CalendarStepComponent;
@@ -1,3 +0,0 @@
1
- import { CalendarStepProps } from '../CalendarStep';
2
- declare function MaterialCalendarStep({ step, editable }: CalendarStepProps): JSX.Element;
3
- export default MaterialCalendarStep;
@@ -1,269 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useContext, useState, useCallback, useRef, useMemo } from 'react';
3
- import { startOfWeek, endOfWeek, addWeeks, addDays, addMonths, startOfMonth, endOfMonth, isSameMonth, isSameDay, isToday, format, parse, startOfDay, } from 'date-fns';
4
- import { es } from 'date-fns/locale';
5
- import { Popover } from '@mui/material';
6
- import ArrowLeftIcon from '../../../Icons/ArrowLeftIcon';
7
- import ArrowRightIcon from '../../../Icons/ArrowRightIcon';
8
- import ViewWeekIcon from '../../../Icons/ViewWeekIcon';
9
- import ViewDayIcon from '../../../Icons/ViewDayIcon';
10
- import CalendarIcon from '../../../Icons/CalendarIcon';
11
- import AddIcon from '../../../Icons/AddIcon';
12
- import CloseIcon from '../../../Icons/CloseIcon';
13
- import DeleteIcon from '../../../Icons/DeleteIcon';
14
- import { CalendarEventCategory, CalendarDefaultView, } from '../../../@Types/CalendarFormStep';
15
- import { useFormStep } from '../../StepHooks';
16
- import FormContext from '../../../Contexts/FormContext';
17
- import { selectBreakPoint, useAppSelector } from '../../../hooks';
18
- import { calcStepWidth } from '../../StepFunctions';
19
- import styles from './MaterialCalendarStep.module.css';
20
- // ---------------------------------------------------------------------------
21
- // Constants
22
- // ---------------------------------------------------------------------------
23
- const CELL_HEIGHT = 48; // px per hour
24
- const WEEK_START = 1; // Monday
25
- const CATEGORY_COLORS = {
26
- [CalendarEventCategory.WORKING]: '#4CAF50',
27
- [CalendarEventCategory.PHYSICAL]: '#2196F3',
28
- [CalendarEventCategory.VIRTUAL]: '#9C27B0',
29
- [CalendarEventCategory.SPECIFIC]: '#FF9800',
30
- [CalendarEventCategory.MEETING]: '#E91E63',
31
- [CalendarEventCategory.BUSY]: '#607D8B',
32
- [CalendarEventCategory.CUSTOM]: '#795548',
33
- };
34
- const CATEGORY_LABELS = {
35
- [CalendarEventCategory.WORKING]: 'Trabajo',
36
- [CalendarEventCategory.PHYSICAL]: 'Presencial',
37
- [CalendarEventCategory.VIRTUAL]: 'Virtual',
38
- [CalendarEventCategory.SPECIFIC]: 'Específico',
39
- [CalendarEventCategory.MEETING]: 'Reunión',
40
- [CalendarEventCategory.BUSY]: 'Ocupado',
41
- [CalendarEventCategory.CUSTOM]: 'Personalizado',
42
- };
43
- // ---------------------------------------------------------------------------
44
- // Helpers
45
- // ---------------------------------------------------------------------------
46
- function parseTime(hhmm) {
47
- const [h, m] = hhmm.split(':').map(Number);
48
- return { h: h ?? 0, m: m ?? 0 };
49
- }
50
- function toMinutes(hhmm) {
51
- const { h, m } = parseTime(hhmm);
52
- return h * 60 + m;
53
- }
54
- function minutesToHHMM(mins) {
55
- const h = Math.floor(mins / 60);
56
- const m = mins % 60;
57
- return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
58
- }
59
- function isoToHHMM(iso) {
60
- // "2024-06-19T09:30:00" → "09:30"
61
- return iso.slice(11, 16);
62
- }
63
- function dateAndTimeToISO(date, hhmm) {
64
- const { h, m } = parseTime(hhmm);
65
- const d = new Date(date);
66
- d.setHours(h, m, 0, 0);
67
- return d.toISOString().slice(0, 19);
68
- }
69
- function isoToDate(iso) {
70
- // Treat as local time (no timezone shift)
71
- return parse(iso.slice(0, 19), 'yyyy-MM-dd\'T\'HH:mm:ss', new Date());
72
- }
73
- function newEventId() {
74
- return `evt-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
75
- }
76
- function EventBlock({ event, minHour, template, onDelete, readOnly }) {
77
- const startMins = toMinutes(isoToHHMM(event.start));
78
- const endMins = toMinutes(isoToHHMM(event.end));
79
- const top = (startMins - minHour * 60) * (CELL_HEIGHT / 60);
80
- const height = Math.max((endMins - startMins) * (CELL_HEIGHT / 60), 18);
81
- const color = template?.color ?? CATEGORY_COLORS[event.category] ?? '#607D8B';
82
- const label = event.title ?? template?.name ?? CATEGORY_LABELS[event.category];
83
- return (_jsxs("div", { className: styles.eventBlock, style: { top, height, backgroundColor: color }, title: `${label} ${isoToHHMM(event.start)}–${isoToHHMM(event.end)}`, children: [_jsx("span", { className: styles.eventLabel, children: label }), _jsxs("span", { className: styles.eventTime, children: [isoToHHMM(event.start), "\u2013", isoToHHMM(event.end)] }), !readOnly && (_jsx("button", { type: "button", className: styles.eventDeleteBtn, onClick: (e) => { e.stopPropagation(); onDelete(event.id); }, "aria-label": "Eliminar", children: _jsx(DeleteIcon, { size: 13 }) }))] }));
84
- }
85
- // ---------------------------------------------------------------------------
86
- // Main component
87
- // ---------------------------------------------------------------------------
88
- function MaterialCalendarStep({ step, editable }) {
89
- const currentBreakPoint = useAppSelector(selectBreakPoint);
90
- const { postview } = useAppSelector((state) => state.global);
91
- const form = useContext(FormContext);
92
- const isReadOnly = !editable || postview;
93
- const widthStyle = currentBreakPoint <= step.size ? '100%' : calcStepWidth(step.size, form.size);
94
- // ------------------------------------------------------------------
95
- // Resolve config
96
- // ------------------------------------------------------------------
97
- const minTimeStr = step.minTime ?? '00:00';
98
- const maxTimeStr = step.maxTime ?? '23:00';
99
- const minHour = parseTime(minTimeStr).h;
100
- const maxHour = parseTime(maxTimeStr).h + 1;
101
- const totalHours = maxHour - minHour;
102
- const showWeekends = step.showWeekends ?? true;
103
- const allowedCategories = (step.allowedCategories?.length ? step.allowedCategories : Object.values(CalendarEventCategory));
104
- const defaultViewMode = (step.defaultView ?? CalendarDefaultView.WEEK);
105
- // ------------------------------------------------------------------
106
- // Form value
107
- // ------------------------------------------------------------------
108
- const { value, onChange } = useFormStep(step, {
109
- defaultValue: null,
110
- rules: {
111
- required: step.required ? 'Este campo es obligatorio' : undefined,
112
- },
113
- });
114
- const events = useMemo(() => value?.events ?? [], [value?.events]);
115
- const setEvents = useCallback((updater) => {
116
- onChange({
117
- type: 'CALENDAR_VALUE',
118
- events: updater(events),
119
- timezone: value?.timezone,
120
- });
121
- }, [events, value?.timezone, onChange]);
122
- const deleteEvent = useCallback((id) => setEvents((prev) => prev.filter((e) => e.id !== id)), [setEvents]);
123
- // ------------------------------------------------------------------
124
- // Navigation state
125
- // ------------------------------------------------------------------
126
- const [viewMode, setViewMode] = useState(defaultViewMode);
127
- const [current, setCurrent] = useState(() => startOfDay(new Date()));
128
- const [createState, setCreate] = useState(null);
129
- // Create form
130
- const [newCategory, setNewCategory] = useState(allowedCategories[0] ?? CalendarEventCategory.WORKING);
131
- const [newTitle, setNewTitle] = useState('');
132
- const [newStart, setNewStart] = useState('09:00');
133
- const [newEnd, setNewEnd] = useState('10:00');
134
- const gridRef = useRef(null);
135
- // ------------------------------------------------------------------
136
- // Derived view dates
137
- // ------------------------------------------------------------------
138
- const weekStart = startOfWeek(current, { weekStartsOn: WEEK_START });
139
- const weekEnd = endOfWeek(current, { weekStartsOn: WEEK_START });
140
- const visibleDays = (() => {
141
- if (viewMode === 'day')
142
- return [current];
143
- const days = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
144
- return showWeekends ? days : days.filter((d) => d.getDay() !== 0 && d.getDay() !== 6);
145
- })();
146
- // ------------------------------------------------------------------
147
- // Navigate
148
- // ------------------------------------------------------------------
149
- const prev = () => {
150
- if (viewMode === 'month')
151
- setCurrent((d) => addMonths(d, -1));
152
- else if (viewMode === 'week')
153
- setCurrent((d) => addWeeks(d, -1));
154
- else
155
- setCurrent((d) => addDays(d, -1));
156
- };
157
- const next = () => {
158
- if (viewMode === 'month')
159
- setCurrent((d) => addMonths(d, 1));
160
- else if (viewMode === 'week')
161
- setCurrent((d) => addWeeks(d, 1));
162
- else
163
- setCurrent((d) => addDays(d, 1));
164
- };
165
- const navLabel = () => {
166
- if (viewMode === 'month')
167
- return format(current, 'MMMM yyyy', { locale: es });
168
- if (viewMode === 'week') {
169
- const s = format(weekStart, 'd MMM', { locale: es });
170
- const e = format(weekEnd, 'd MMM yyyy', { locale: es });
171
- return `${s} – ${e}`;
172
- }
173
- return format(current, 'EEEE d \'de\' MMMM yyyy', { locale: es });
174
- };
175
- // ------------------------------------------------------------------
176
- // Events per day (for time-grid views)
177
- // ------------------------------------------------------------------
178
- const eventsForDay = (day) => events.filter((e) => isSameDay(isoToDate(e.start), day));
179
- // ------------------------------------------------------------------
180
- // Create flow
181
- // ------------------------------------------------------------------
182
- const handleGridClick = (e, day) => {
183
- if (isReadOnly)
184
- return;
185
- const rect = (e.currentTarget).getBoundingClientRect();
186
- const relY = e.clientY - rect.top;
187
- const clickedMins = Math.round((relY / CELL_HEIGHT) * 60) * 30; // snap to 30min
188
- const startMins = minHour * 60 + clickedMins;
189
- const startHHMM = minutesToHHMM(Math.min(startMins, (maxHour - 1) * 60));
190
- const endHHMM = minutesToHHMM(Math.min(startMins + 60, maxHour * 60));
191
- setNewStart(startHHMM);
192
- setNewEnd(endHHMM);
193
- setNewCategory(allowedCategories[0] ?? CalendarEventCategory.WORKING);
194
- setNewTitle('');
195
- setCreate({ anchorEl: e.currentTarget, date: day, startMins });
196
- };
197
- const handleMonthDayClick = (day) => {
198
- setCurrent(day);
199
- setViewMode('day');
200
- };
201
- const handleCreate = () => {
202
- if (!createState)
203
- return;
204
- const startISO = dateAndTimeToISO(createState.date, newStart);
205
- const endISO = dateAndTimeToISO(createState.date, newEnd);
206
- const template = step.eventTemplates?.find((t) => t.category === newCategory);
207
- const evt = {
208
- id: newEventId(),
209
- category: newCategory,
210
- start: startISO,
211
- end: endISO,
212
- title: newTitle || undefined,
213
- eventTemplateId: template?.id,
214
- };
215
- setEvents((prev) => [...prev, evt]);
216
- setCreate(null);
217
- };
218
- // ------------------------------------------------------------------
219
- // Hour labels column
220
- // ------------------------------------------------------------------
221
- const hourLabels = Array.from({ length: totalHours }, (_, i) => minHour + i);
222
- // ------------------------------------------------------------------
223
- // Time-grid view (week / day)
224
- // ------------------------------------------------------------------
225
- const renderTimeGrid = () => (_jsxs("div", { className: styles.gridWrapper, children: [_jsxs("div", { className: styles.gridHeader, style: { gridTemplateColumns: `48px repeat(${visibleDays.length}, 1fr)` }, children: [_jsx("div", { className: styles.cornerCell }), visibleDays.map((day) => (_jsxs("div", { className: `${styles.dayHeader} ${isToday(day) ? styles.dayHeaderToday : ''}`, onClick: () => { setCurrent(day); setViewMode('day'); }, children: [_jsx("span", { className: styles.dayHeaderDow, children: format(day, 'EEE', { locale: es }) }), _jsx("span", { className: `${styles.dayHeaderNum} ${isToday(day) ? styles.todayCircle : ''}`, children: format(day, 'd') })] }, day.toISOString())))] }), _jsx("div", { className: styles.gridBody, ref: gridRef, children: _jsxs("div", { className: styles.gridInner, style: { gridTemplateColumns: `48px repeat(${visibleDays.length}, 1fr)` }, children: [_jsx("div", { className: styles.hourLabels, children: hourLabels.map((h) => (_jsx("div", { className: styles.hourLabel, style: { height: CELL_HEIGHT }, children: h > 0 && `${String(h).padStart(2, '0')}:00` }, h))) }), visibleDays.map((day) => (_jsxs("div", { className: styles.dayColumn, style: { height: totalHours * CELL_HEIGHT }, onClick: (e) => handleGridClick(e, day), children: [hourLabels.map((h) => (_jsx("div", { className: styles.hourLine, style: { top: (h - minHour) * CELL_HEIGHT } }, h))), eventsForDay(day).map((evt) => (_jsx(EventBlock, { event: evt, minHour: minHour, template: step.eventTemplates?.find((t) => t.category === evt.category), onDelete: deleteEvent, readOnly: isReadOnly }, evt.id)))] }, day.toISOString())))] }) })] }));
226
- // ------------------------------------------------------------------
227
- // Month view
228
- // ------------------------------------------------------------------
229
- const renderMonth = () => {
230
- const mStart = startOfMonth(current);
231
- const mEnd = endOfMonth(current);
232
- const gridStart = startOfWeek(mStart, { weekStartsOn: WEEK_START });
233
- const gridEnd = endOfWeek(mEnd, { weekStartsOn: WEEK_START });
234
- const days = [];
235
- let d = gridStart;
236
- while (d <= gridEnd) {
237
- days.push(d);
238
- d = addDays(d, 1);
239
- }
240
- const DOW_LABELS = ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
241
- return (_jsxs("div", { className: styles.monthGrid, children: [DOW_LABELS.map((lbl) => (_jsx("div", { className: styles.monthDowHeader, children: lbl }, lbl))), days.map((day) => {
242
- const dayEvts = eventsForDay(day);
243
- const outside = !isSameMonth(day, current);
244
- return (_jsxs("div", { className: [
245
- styles.monthCell,
246
- outside ? styles.monthCellOutside : '',
247
- isToday(day) ? styles.monthCellToday : '',
248
- ].filter(Boolean).join(' '), onClick: () => handleMonthDayClick(day), children: [_jsx("span", { className: `${styles.monthCellNum} ${isToday(day) ? styles.todayCircle : ''}`, children: format(day, 'd') }), dayEvts.slice(0, 3).map((evt) => {
249
- const color = CATEGORY_COLORS[evt.category] ?? '#607D8B';
250
- return (_jsx("div", { className: styles.monthEventDot, style: { backgroundColor: color }, children: evt.title ?? CATEGORY_LABELS[evt.category] }, evt.id));
251
- }), dayEvts.length > 3 && (_jsxs("div", { className: styles.monthMoreLabel, children: ["+", dayEvts.length - 3, " m\u00E1s"] }))] }, day.toISOString()));
252
- })] }));
253
- };
254
- // ------------------------------------------------------------------
255
- // Create popover
256
- // ------------------------------------------------------------------
257
- const needsTitle = newCategory === CalendarEventCategory.MEETING ||
258
- newCategory === CalendarEventCategory.CUSTOM;
259
- const renderCreatePopover = () => {
260
- if (!createState)
261
- return null;
262
- return (_jsxs(Popover, { open: true, anchorEl: createState.anchorEl, onClose: () => setCreate(null), anchorOrigin: { vertical: 'top', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'left' }, slotProps: { paper: { className: styles.popoverPaper } }, children: [_jsxs("div", { className: styles.popoverHeader, children: [_jsx("span", { className: styles.popoverTitle, children: "Nuevo evento" }), _jsx("button", { type: "button", className: styles.popoverClose, onClick: () => setCreate(null), children: _jsx(CloseIcon, { size: 16 }) })] }), _jsxs("div", { className: styles.popoverBody, children: [_jsx("div", { className: styles.popoverLabel, children: "Tipo" }), _jsx("div", { className: styles.categoryGrid, children: allowedCategories.map((cat) => (_jsxs("button", { type: "button", className: `${styles.categoryChip} ${newCategory === cat ? styles.categoryChipActive : ''}`, style: newCategory === cat ? { backgroundColor: CATEGORY_COLORS[cat], color: '#fff' } : {}, onClick: () => setNewCategory(cat), children: [_jsx("span", { className: styles.categoryDot, style: { backgroundColor: CATEGORY_COLORS[cat] } }), CATEGORY_LABELS[cat]] }, cat))) }), needsTitle && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.popoverLabel, children: "Nombre" }), _jsx("input", { className: styles.popoverInput, value: newTitle, onChange: (e) => setNewTitle(e.target.value), placeholder: "Ej: Standup, Visita cliente\u2026", autoFocus: true })] })), _jsxs("div", { className: styles.timeRow, children: [_jsxs("div", { children: [_jsx("div", { className: styles.popoverLabel, children: "Inicio" }), _jsx("input", { type: "time", className: styles.popoverInput, value: newStart, onChange: (e) => setNewStart(e.target.value) })] }), _jsx("span", { className: styles.timeDash, children: "\u2013" }), _jsxs("div", { children: [_jsx("div", { className: styles.popoverLabel, children: "Fin" }), _jsx("input", { type: "time", className: styles.popoverInput, value: newEnd, onChange: (e) => setNewEnd(e.target.value) })] })] }), _jsxs("button", { type: "button", className: styles.createBtn, style: { backgroundColor: CATEGORY_COLORS[newCategory] }, onClick: handleCreate, children: [_jsx(AddIcon, { size: 16 }), "Agregar bloque"] })] })] }));
263
- };
264
- // ------------------------------------------------------------------
265
- // Render
266
- // ------------------------------------------------------------------
267
- return (_jsxs("div", { className: styles.container, style: { width: widthStyle }, children: [_jsxs("div", { className: styles.toolbar, children: [_jsxs("div", { className: styles.viewSwitcher, children: [_jsx("button", { type: "button", className: `${styles.viewBtn} ${viewMode === 'day' ? styles.viewBtnActive : ''}`, onClick: () => setViewMode('day'), title: "D\u00EDa", children: _jsx(ViewDayIcon, { size: 18 }) }), _jsx("button", { type: "button", className: `${styles.viewBtn} ${viewMode === 'week' ? styles.viewBtnActive : ''}`, onClick: () => setViewMode('week'), title: "Semana", children: _jsx(ViewWeekIcon, { size: 18 }) }), _jsx("button", { type: "button", className: `${styles.viewBtn} ${viewMode === 'month' ? styles.viewBtnActive : ''}`, onClick: () => setViewMode('month'), title: "Mes", children: _jsx(CalendarIcon, { size: 18 }) })] }), _jsxs("div", { className: styles.navGroup, children: [_jsx("button", { type: "button", className: styles.navBtn, onClick: prev, children: _jsx(ArrowLeftIcon, { size: 20 }) }), _jsx("span", { className: styles.navLabel, children: navLabel() }), _jsx("button", { type: "button", className: styles.navBtn, onClick: next, children: _jsx(ArrowRightIcon, { size: 20 }) })] }), events.length > 0 && (_jsxs("span", { className: styles.eventBadge, children: [events.length, " evento", events.length !== 1 ? 's' : ''] })), !isReadOnly && viewMode !== 'month' && (_jsx("span", { className: styles.hintText, children: "Clic en el grid para agregar" }))] }), _jsx("div", { className: styles.calendarCard, children: viewMode === 'month' ? renderMonth() : renderTimeGrid() }), !isReadOnly && renderCreatePopover()] }));
268
- }
269
- export default MaterialCalendarStep;