@trii/components 2.0.64 → 2.0.66

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/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { useCallback, useEffect, useState, useRef, useMemo } from 'react';
3
- import { Button, styled as styled$3, Box, IconButton, Avatar, Typography, CircularProgress, Tooltip, Chip, Popper, ClickAwayListener, CardContent, useTheme as useTheme$2, Dialog, DialogContent, TextField, Autocomplete, FormControl, Select, MenuItem, FormControlLabel, Checkbox, DialogActions } from '@mui/material';
4
- import { Handyman, PhoneEnabled, Email, WhatsApp, Facebook, Instagram, ThreeP, Edit, Delete, ContentCopy, Close, Add, Search, Place, AccessTime, Repeat } from '@mui/icons-material';
3
+ import { Button, styled as styled$3, Box, IconButton, Avatar, Typography, CircularProgress, Tooltip, Chip, Popper, ClickAwayListener, CardContent, TextField, useTheme as useTheme$2, Dialog, DialogContent, Autocomplete, FormControl, Select, MenuItem, FormControlLabel, Checkbox, List, ListItemButton, ListItemIcon, ListItemText, DialogActions } from '@mui/material';
4
+ import { Handyman, PhoneEnabled, Email, WhatsApp, Facebook, Instagram, ThreeP, Search, Edit, Delete, ContentCopy, Close, Add, Person, Place, AccessTime, Repeat } from '@mui/icons-material';
5
5
  import { withEmotionCache, ThemeContext, CacheProvider, Global, css, keyframes } from '@emotion/react';
6
6
  import moment from 'moment';
7
7
  import { LocalizationProvider, DatePicker, TimePicker } from '@mui/x-date-pickers-pro';
@@ -9892,6 +9892,30 @@ class AdapterDayjs {
9892
9892
  }
9893
9893
  }
9894
9894
 
9895
+ // ============================================
9896
+ // COMPONENTES EXTERNOS (evitan re-creación en cada render)
9897
+ // ============================================
9898
+ // Componente: Input Container con label
9899
+ const InputContainer = ({ title, children }) => (jsxRuntimeExports.jsxs(Box, { children: [jsxRuntimeExports.jsx(Box, { sx: { mb: 1, color: 'text.secondary', fontSize: '0.875rem', userSelect: 'none' }, children: title }), children] }));
9900
+ // Componente: Contact Search Input (declarado fuera para evitar pérdida de focus)
9901
+ const ContactSearchInput = React__default.memo(({ onChange, placeholder, isSearching, value }) => {
9902
+ return (jsxRuntimeExports.jsxs(Box, { sx: { position: 'relative' }, children: [jsxRuntimeExports.jsx(TextField, { fullWidth: true, size: "small", placeholder: placeholder, value: value, onChange: (e) => onChange(e.target.value), InputProps: {
9903
+ startAdornment: jsxRuntimeExports.jsx(Search, { fontSize: "small", sx: { mr: 1, color: 'text.secondary' } }),
9904
+ }, autoComplete: "off" }), isSearching && (jsxRuntimeExports.jsx(Box, { sx: {
9905
+ position: 'absolute',
9906
+ bottom: 0,
9907
+ left: 0,
9908
+ right: 0,
9909
+ height: 2,
9910
+ bgcolor: 'primary.main',
9911
+ animation: 'progress 1s infinite',
9912
+ '@keyframes progress': {
9913
+ '0%': { transform: 'translateX(-100%)' },
9914
+ '100%': { transform: 'translateX(100%)' },
9915
+ },
9916
+ } }))] }));
9917
+ });
9918
+ ContactSearchInput.displayName = 'ContactSearchInput';
9895
9919
  /**
9896
9920
  * ModalEvents - Componente reutilizable para crear/editar/visualizar eventos y tareas
9897
9921
  *
@@ -9902,22 +9926,33 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
9902
9926
  const [currentType, setCurrentType] = useState(initialType);
9903
9927
  const [localEventData, setLocalEventData] = useState(eventData || {});
9904
9928
  const [localTaskData, setLocalTaskData] = useState(taskData || {});
9905
- const [contactSearch, setContactSearch] = useState('');
9906
9929
  const [searchResults, setSearchResults] = useState([]);
9907
- useState(false);
9930
+ const [isSearching, setIsSearching] = useState(false);
9931
+ const [contactSearchValue, setContactSearchValue] = useState('');
9932
+ const contactSearchRef = useRef('');
9908
9933
  const debounceTimerRef = useRef(null);
9934
+ const wasOpenRef = useRef(false);
9909
9935
  const theme = useTheme$2();
9910
- // Sincronizar con props cuando cambian
9911
- useEffect(() => setCurrentType(initialType), [initialType]);
9912
- useEffect(() => { if (eventData)
9913
- setLocalEventData(eventData); }, [eventData]);
9914
- useEffect(() => { if (taskData)
9915
- setLocalTaskData(taskData); }, [taskData]);
9936
+ // Sincronizar con props SOLO cuando el modal se abre (no en cada cambio de props)
9937
+ useEffect(() => {
9938
+ if (open && !wasOpenRef.current) {
9939
+ // Modal acaba de abrirse - sincronizar datos
9940
+ setCurrentType(initialType);
9941
+ setLocalEventData(eventData || {});
9942
+ setLocalTaskData(taskData || {});
9943
+ setContactSearchValue('');
9944
+ contactSearchRef.current = '';
9945
+ setSearchResults([]);
9946
+ }
9947
+ wasOpenRef.current = open;
9948
+ }, [open, initialType, eventData, taskData]);
9916
9949
  // Restablecer datos locales al cerrar
9917
9950
  useEffect(() => {
9918
9951
  if (!open) {
9919
- setContactSearch('');
9952
+ setContactSearchValue('');
9953
+ contactSearchRef.current = '';
9920
9954
  setSearchResults([]);
9955
+ setIsSearching(false);
9921
9956
  if (debounceTimerRef.current)
9922
9957
  clearTimeout(debounceTimerRef.current);
9923
9958
  }
@@ -9976,6 +10011,15 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
9976
10011
  edit: 'Editar',
9977
10012
  duplicate: 'Duplicar',
9978
10013
  close: 'Cerrar',
10014
+ // Labels de recurrencia
10015
+ noRepeat: 'No repetir',
10016
+ everyDay: 'Todos los días',
10017
+ everyWeek: 'Cada semana',
10018
+ everyMonth: 'Cada mes',
10019
+ everyYear: 'Cada año',
10020
+ everyTwoDays: 'Cada 2 días',
10021
+ everyTwoWeeks: 'Cada 2 semanas',
10022
+ everyWeekday: 'Días laborables (Lun-Vie)',
9979
10023
  };
9980
10024
  const l = useMemo(() => ({
9981
10025
  ...defaultLabels,
@@ -9986,6 +10030,24 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
9986
10030
  const isViewMode = mode === 'view';
9987
10031
  const isCreateMode = mode === 'create';
9988
10032
  const canDelete = (mode === 'edit' || mode === 'view') && Boolean(currentData?.id);
10033
+ // Opciones de recurrencia
10034
+ const recurrenceOptions = useMemo(() => [
10035
+ { value: '', label: l.noRepeat },
10036
+ { value: 'FREQ=DAILY', label: l.everyDay },
10037
+ { value: 'FREQ=WEEKLY', label: l.everyWeek },
10038
+ { value: 'FREQ=MONTHLY', label: l.everyMonth },
10039
+ { value: 'FREQ=YEARLY', label: l.everyYear },
10040
+ { value: 'FREQ=DAILY;INTERVAL=2', label: l.everyTwoDays },
10041
+ { value: 'FREQ=WEEKLY;INTERVAL=2', label: l.everyTwoWeeks },
10042
+ { value: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR', label: l.everyWeekday },
10043
+ ], [l]);
10044
+ // Helper para obtener label de recurrencia
10045
+ const getRecurrenceLabel = (value) => {
10046
+ if (!value)
10047
+ return l.noRepeat;
10048
+ const option = recurrenceOptions.find(opt => opt.value === value);
10049
+ return option ? option.label : value;
10050
+ };
9989
10051
  // Obtener título del modal
9990
10052
  const dialogTitle = useMemo(() => {
9991
10053
  if (isEvent) {
@@ -10050,13 +10112,20 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10050
10112
  const updated = currentContacts.filter(c => c.id !== contactId);
10051
10113
  handleFieldChange('linkedContacts', updated);
10052
10114
  };
10053
- // Handler para búsqueda de contactos con debounce
10054
- const handleContactSearchChange = useCallback((query) => {
10055
- setContactSearch(query);
10115
+ // Handler para buscar contactos con debounce
10116
+ const handleContactSearchDebounced = useCallback((query) => {
10117
+ setContactSearchValue(query);
10118
+ contactSearchRef.current = query;
10056
10119
  if (debounceTimerRef.current) {
10057
10120
  clearTimeout(debounceTimerRef.current);
10058
10121
  }
10059
- if (onSearchContacts && query.length >= 2) {
10122
+ if (query.length < 2) {
10123
+ setSearchResults([]);
10124
+ setIsSearching(false);
10125
+ return;
10126
+ }
10127
+ if (onSearchContacts) {
10128
+ setIsSearching(true);
10060
10129
  debounceTimerRef.current = setTimeout(async () => {
10061
10130
  try {
10062
10131
  const results = await onSearchContacts(query);
@@ -10066,23 +10135,23 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10066
10135
  console.error('Error searching contacts:', error);
10067
10136
  setSearchResults([]);
10068
10137
  }
10138
+ finally {
10139
+ setIsSearching(false);
10140
+ }
10069
10141
  }, searchDebounceMs);
10070
10142
  }
10071
- else if (query.length < 2) {
10072
- setSearchResults([]);
10073
- }
10074
10143
  }, [onSearchContacts, searchDebounceMs]);
10075
10144
  // Contactos filtrados
10076
10145
  const filteredContacts = useMemo(() => {
10077
10146
  if (onSearchContacts) {
10078
10147
  return searchResults;
10079
10148
  }
10080
- if (!contactSearch)
10149
+ const search = contactSearchValue.toLowerCase();
10150
+ if (!search)
10081
10151
  return [];
10082
- const search = contactSearch.toLowerCase();
10083
10152
  return contacts.filter(contact => contact.name.toLowerCase().includes(search) ||
10084
10153
  contact.email?.toLowerCase().includes(search));
10085
- }, [onSearchContacts, searchResults, contacts, contactSearch]);
10154
+ }, [onSearchContacts, searchResults, contacts, contactSearchValue]);
10086
10155
  // Calcular duración para eventos
10087
10156
  const duration = useMemo(() => {
10088
10157
  if (!isEvent || !localEventData.startDate || !localEventData.endDate)
@@ -10096,12 +10165,19 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10096
10165
  const minutes = diff % 60;
10097
10166
  return minutes > 0 ? `${hours}h ${minutes}min` : `${hours}h`;
10098
10167
  }, [isEvent, localEventData.startDate, localEventData.endDate]);
10168
+ // Helper para renderizar valores en modo view
10169
+ const renderViewValue = (value) => {
10170
+ if (value === null || value === undefined || value === '') {
10171
+ return jsxRuntimeExports.jsx(Typography, { color: "text.secondary", children: "-" });
10172
+ }
10173
+ return jsxRuntimeExports.jsx(Typography, { children: value });
10174
+ };
10099
10175
  // ============================================
10100
10176
  // COMPONENTES INTERNOS
10101
10177
  // ============================================
10102
10178
  // Componente: Type Tabs
10103
10179
  const TypeTabs = () => {
10104
- if (!showTypeTabs || currentData?.title)
10180
+ if (!showTypeTabs)
10105
10181
  return null;
10106
10182
  return (jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [jsxRuntimeExports.jsx(Button, { variant: isEvent ? 'contained' : 'text', color: "secondary", size: "small", disableElevation: true, onClick: () => handleTypeChange('event'), sx: {
10107
10183
  textTransform: 'none',
@@ -10119,8 +10195,6 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10119
10195
  fontWeight: 500,
10120
10196
  }, children: l.taskTab })] }));
10121
10197
  };
10122
- // Componente: Input Container con label
10123
- const InputContainer = ({ title, children }) => (jsxRuntimeExports.jsxs(Box, { children: [jsxRuntimeExports.jsx(Box, { sx: { mb: 1, color: 'text.secondary', fontSize: '0.875rem', userSelect: 'none' }, children: title }), children] }));
10124
10198
  // Componente: Date Time Picker Section
10125
10199
  const DateTimeSection = () => {
10126
10200
  if (!config.showDateTime)
@@ -10129,6 +10203,19 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10129
10203
  const startDateDayjs = localEventData.startDate ? defaultDayjs(moment(localEventData.startDate).toISOString()) : null;
10130
10204
  const endDateDayjs = localEventData.endDate ? defaultDayjs(moment(localEventData.endDate).toISOString()) : null;
10131
10205
  const dueDateDayjs = localTaskData.dueDate ? defaultDayjs(moment(localTaskData.dueDate).toISOString()) : null;
10206
+ // Si estamos en modo view, mostrar solo info formateada
10207
+ if (isViewMode) {
10208
+ return (jsxRuntimeExports.jsx(Box, { sx: {
10209
+ display: 'flex',
10210
+ flexDirection: 'column',
10211
+ gap: 1.5,
10212
+ p: 2,
10213
+ borderRadius: 1,
10214
+ bgcolor: theme.palette.mode === 'dark'
10215
+ ? 'rgba(255, 255, 255, 0.05)'
10216
+ : 'rgba(0, 0, 0, 0.02)',
10217
+ }, children: jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', gap: 1.5, alignItems: 'flex-start' }, children: [jsxRuntimeExports.jsx(AccessTime, { sx: { mt: 0.5, color: 'text.secondary', fontSize: '1.25rem' } }), jsxRuntimeExports.jsxs(Box, { sx: { flex: 1 }, children: [isEvent ? (jsxRuntimeExports.jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 1 }, children: localEventData.startDate ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Typography, { children: moment(localEventData.startDate).format('DD/MM/YYYY') }), !localEventData.allDay && (jsxRuntimeExports.jsxs(Typography, { children: [moment(localEventData.startDate).format('HH:mm'), " \u2013 ", moment(localEventData.endDate).format('HH:mm'), duration && jsxRuntimeExports.jsxs(Typography, { component: "span", variant: "caption", color: "text.secondary", children: [" (", duration, ")"] })] })), localEventData.allDay && (jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: l.allDay }))] })) : (jsxRuntimeExports.jsx(Typography, { color: "text.secondary", children: "-" })) })) : (jsxRuntimeExports.jsx(Box, { children: localTaskData.dueDate ? (jsxRuntimeExports.jsx(Typography, { children: moment(localTaskData.dueDate).format('DD/MM/YYYY HH:mm') })) : (jsxRuntimeExports.jsx(Typography, { color: "text.secondary", children: "-" })) })), isEvent && localEventData.recurrence && config.showRecurrence && (jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, mt: 1 }, children: [jsxRuntimeExports.jsx(Repeat, { fontSize: "small", color: "action" }), jsxRuntimeExports.jsx(Typography, { variant: "body2", children: getRecurrenceLabel(localEventData.recurrence) })] }))] })] }) }));
10218
+ }
10132
10219
  return (jsxRuntimeExports.jsxs(Box, { sx: {
10133
10220
  display: 'flex',
10134
10221
  flexDirection: 'column',
@@ -10147,7 +10234,7 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10147
10234
  handleFieldChange('endDate', moment(newStart).add(1, 'hour'));
10148
10235
  }
10149
10236
  }
10150
- }, disabled: isViewMode, slotProps: {
10237
+ }, slotProps: {
10151
10238
  textField: {
10152
10239
  size: 'small',
10153
10240
  fullWidth: true,
@@ -10160,14 +10247,14 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10160
10247
  },
10161
10248
  },
10162
10249
  },
10163
- } }), jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', gap: 1, alignItems: 'center' }, children: [jsxRuntimeExports.jsx(TimePicker, { label: l.startTime, value: startDateDayjs, onChange: (newTime) => {
10250
+ } }), jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', gap: 1, alignItems: 'baseline', marginTop: '15px' }, children: [jsxRuntimeExports.jsx(TimePicker, { label: l.startTime, value: startDateDayjs, onChange: (newTime) => {
10164
10251
  if (newTime) {
10165
10252
  const newStart = moment(localEventData.startDate)
10166
10253
  .hours(newTime.hour())
10167
10254
  .minutes(newTime.minute());
10168
10255
  handleFieldChange('startDate', newStart);
10169
10256
  }
10170
- }, disabled: isViewMode || localEventData.allDay, ampm: false, slotProps: {
10257
+ }, disabled: localEventData.allDay, ampm: false, slotProps: {
10171
10258
  textField: {
10172
10259
  size: 'small',
10173
10260
  },
@@ -10186,7 +10273,7 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10186
10273
  .minutes(newTime.minute());
10187
10274
  handleFieldChange('endDate', newEnd);
10188
10275
  }
10189
- }, disabled: isViewMode || localEventData.allDay, ampm: false, slotProps: {
10276
+ }, disabled: localEventData.allDay, ampm: false, slotProps: {
10190
10277
  textField: {
10191
10278
  size: 'small',
10192
10279
  fullWidth: true,
@@ -10207,7 +10294,7 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10207
10294
  .date(newDate.date());
10208
10295
  handleFieldChange('dueDate', merged);
10209
10296
  }
10210
- }, disabled: isViewMode, slotProps: {
10297
+ }, slotProps: {
10211
10298
  textField: {
10212
10299
  size: 'small',
10213
10300
  },
@@ -10226,7 +10313,7 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10226
10313
  .minutes(newTime.minute());
10227
10314
  handleFieldChange('dueDate', merged);
10228
10315
  }
10229
- }, disabled: isViewMode, ampm: false, slotProps: {
10316
+ }, ampm: false, slotProps: {
10230
10317
  textField: {
10231
10318
  size: 'small',
10232
10319
  },
@@ -10238,14 +10325,14 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10238
10325
  },
10239
10326
  },
10240
10327
  },
10241
- }, sx: { flex: 1 } })] })) }) })] }), isEvent && (config.showAllDay || config.showRecurrence) && (jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center', pl: 5 }, children: [config.showAllDay && (jsxRuntimeExports.jsx(FormControlLabel, { control: jsxRuntimeExports.jsx(Checkbox, { checked: localEventData.allDay || false, onChange: (e) => handleFieldChange('allDay', e.target.checked), disabled: isViewMode, color: "secondary" }), label: l.allDay })), config.showRecurrence && (jsxRuntimeExports.jsxs(Box, { sx: { flex: 1, display: 'flex', alignItems: 'center', gap: 1 }, children: [jsxRuntimeExports.jsx(Repeat, { fontSize: "small" }), jsxRuntimeExports.jsx(FormControl, { fullWidth: true, size: "small", children: jsxRuntimeExports.jsxs(Select, { value: localEventData.recurrence || '', onChange: (e) => handleFieldChange('recurrence', e.target.value), disabled: isViewMode, displayEmpty: true, MenuProps: {
10328
+ }, sx: { flex: 1 } })] })) }) })] }), isEvent && (config.showAllDay || config.showRecurrence) && (jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center', pl: 5 }, children: [config.showAllDay && (jsxRuntimeExports.jsx(FormControlLabel, { control: jsxRuntimeExports.jsx(Checkbox, { checked: localEventData.allDay || false, onChange: (e) => handleFieldChange('allDay', e.target.checked), color: "secondary" }), label: l.allDay })), config.showRecurrence && (jsxRuntimeExports.jsxs(Box, { sx: { flex: 1, display: 'flex', alignItems: 'center', gap: 1 }, children: [jsxRuntimeExports.jsx(Repeat, { fontSize: "small" }), jsxRuntimeExports.jsx(FormControl, { fullWidth: true, size: "small", children: jsxRuntimeExports.jsx(Select, { value: localEventData.recurrence || '', onChange: (e) => handleFieldChange('recurrence', e.target.value), displayEmpty: true, MenuProps: {
10242
10329
  PaperProps: {
10243
10330
  sx: {
10244
10331
  //@ts-ignore
10245
10332
  backgroundColor: theme.palette.background.panel,
10246
10333
  },
10247
10334
  },
10248
- }, children: [jsxRuntimeExports.jsx(MenuItem, { value: "", children: "No repetir" }), jsxRuntimeExports.jsx(MenuItem, { value: "DAILY", children: "Diario" }), jsxRuntimeExports.jsx(MenuItem, { value: "WEEKLY", children: "Semanal" }), jsxRuntimeExports.jsx(MenuItem, { value: "MONTHLY", children: "Mensual" }), jsxRuntimeExports.jsx(MenuItem, { value: "YEARLY", children: "Anual" })] }) })] }))] }))] }));
10335
+ }, children: recurrenceOptions.map((option) => (jsxRuntimeExports.jsx(MenuItem, { value: option.value, children: option.label }, option.value))) }) })] }))] }))] }));
10249
10336
  };
10250
10337
  return (jsxRuntimeExports.jsxs(Dialog, { sx: {
10251
10338
  '& .MuiDialog-paper': {
@@ -10267,7 +10354,8 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10267
10354
  '& .MuiInput-underline:before': { borderBottomColor: 'divider' },
10268
10355
  '& .MuiInput-underline:hover:before': { borderBottomColor: 'text.secondary' },
10269
10356
  '& .MuiInput-underline:after': { borderBottomWidth: 2 },
10270
- } })), jsxRuntimeExports.jsx(TypeTabs, {})] })), !isCreateMode && config.showTitle && (jsxRuntimeExports.jsx(InputContainer, { title: l.title, children: jsxRuntimeExports.jsx(TextField, { fullWidth: true, size: "small", value: currentData?.title || '', onChange: (e) => handleFieldChange('title', e.target.value), disabled: isViewMode, error: !!validationErrors.title, helperText: validationErrors.title }) })), config.showDescription && (jsxRuntimeExports.jsx(InputContainer, { title: l.description, children: jsxRuntimeExports.jsx(TextField, { fullWidth: true, multiline: true, rows: 3, size: "small", value: currentData?.description || '', onChange: (e) => handleFieldChange('description', e.target.value), disabled: isViewMode }) })), config.showCalendar && (jsxRuntimeExports.jsx(InputContainer, { title: l.calendar, children: jsxRuntimeExports.jsx(Autocomplete, { fullWidth: true, size: "small", options: calendars, getOptionLabel: (option) => option.title || option.name || '', value: calendars.find(cal => cal.id === currentData?.calendarId) || null, onChange: (_, newValue) => {
10357
+ } })), jsxRuntimeExports.jsx(TypeTabs, {})] })), !isCreateMode && config.showTitle && (jsxRuntimeExports.jsx(InputContainer, { title: l.title, children: isViewMode ? (renderViewValue(currentData?.title)) : (jsxRuntimeExports.jsx(TextField, { fullWidth: true, size: "small", value: currentData?.title || '', onChange: (e) => handleFieldChange('title', e.target.value), error: !!validationErrors.title, helperText: validationErrors.title })) })), config.showDescription && (jsxRuntimeExports.jsx(InputContainer, { title: l.description, children: isViewMode ? (renderViewValue(currentData?.description)) : (jsxRuntimeExports.jsx(TextField, { fullWidth: true, multiline: true, rows: 3, size: "small", value: currentData?.description || '', onChange: (e) => handleFieldChange('description', e.target.value) })) })), config.showCalendar && (jsxRuntimeExports.jsx(InputContainer, { title: l.calendar, children: isViewMode ? (renderViewValue(calendars.find(cal => cal.id === currentData?.calendarId)?.title ||
10358
+ calendars.find(cal => cal.id === currentData?.calendarId)?.name)) : (jsxRuntimeExports.jsx(Autocomplete, { fullWidth: true, size: "small", options: calendars, getOptionLabel: (option) => option.title || option.name || '', value: calendars.find(cal => cal.id === currentData?.calendarId) || null, onChange: (_, newValue) => {
10271
10359
  const previousCalendar = calendars.find(cal => cal.id === currentData?.calendarId);
10272
10360
  const currentColor = localEventData.color;
10273
10361
  handleFieldChange('calendarId', newValue?.id);
@@ -10280,20 +10368,26 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10280
10368
  handleFieldChange('color', newValue.color);
10281
10369
  }
10282
10370
  }
10283
- }, disabled: isViewMode, slotProps: {
10371
+ }, slotProps: {
10284
10372
  paper: {
10285
10373
  sx: {
10286
10374
  //@ts-ignore
10287
10375
  backgroundColor: theme.palette.background.panel,
10288
10376
  },
10289
10377
  },
10290
- }, renderInput: (params) => (jsxRuntimeExports.jsx(TextField, { ...params, placeholder: l.calendarPlaceholder })) }) })), jsxRuntimeExports.jsx(DateTimeSection, {}), isEvent && config.showColor && (jsxRuntimeExports.jsx(InputContainer, { title: l.color, children: jsxRuntimeExports.jsx("input", { type: "color", value: localEventData.color || '#1976d2', onChange: (e) => handleFieldChange('color', e.target.value), disabled: isViewMode, style: {
10378
+ }, renderInput: (params) => (jsxRuntimeExports.jsx(TextField, { ...params, placeholder: l.calendarPlaceholder })) })) })), jsxRuntimeExports.jsx(DateTimeSection, {}), isEvent && config.showColor && (jsxRuntimeExports.jsx(InputContainer, { title: l.color, children: isViewMode ? (jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [jsxRuntimeExports.jsx(Box, { sx: {
10379
+ width: '24px',
10380
+ height: '24px',
10381
+ borderRadius: '4px',
10382
+ backgroundColor: localEventData.color || '#1976d2',
10383
+ border: '1px solid rgba(0, 0, 0, 0.23)',
10384
+ } }), jsxRuntimeExports.jsx(Typography, { children: localEventData.color || '#1976d2' })] })) : (jsxRuntimeExports.jsx("input", { type: "color", value: localEventData.color || '#1976d2', onChange: (e) => handleFieldChange('color', e.target.value), style: {
10291
10385
  width: '60px',
10292
10386
  height: '40px',
10293
10387
  border: '1px solid rgba(0, 0, 0, 0.23)',
10294
10388
  borderRadius: '4px',
10295
- cursor: isViewMode ? 'not-allowed' : 'pointer',
10296
- } }) })), config.showNotifications && (jsxRuntimeExports.jsxs(Box, { children: [jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: l.notifications }), !isViewMode && (jsxRuntimeExports.jsx(Button, { size: "small", variant: "outlined", color: "secondary", startIcon: jsxRuntimeExports.jsx(Add, {}), onClick: handleAddNotification, children: l.addNotification }))] }), jsxRuntimeExports.jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 1.5 }, children: (currentData?.notifications || []).map((notification, index) => (jsxRuntimeExports.jsxs(Box, { sx: {
10389
+ cursor: 'pointer',
10390
+ } })) })), config.showNotifications && (jsxRuntimeExports.jsxs(Box, { children: [jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: l.notifications }), !isViewMode && (jsxRuntimeExports.jsx(Button, { size: "small", variant: "outlined", color: "secondary", startIcon: jsxRuntimeExports.jsx(Add, {}), onClick: handleAddNotification, children: l.addNotification }))] }), (currentData?.notifications || []).length === 0 && isViewMode ? (jsxRuntimeExports.jsx(Typography, { color: "text.secondary", children: "-" })) : (jsxRuntimeExports.jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 1.5 }, children: (currentData?.notifications || []).map((notification, index) => (jsxRuntimeExports.jsx(Box, { sx: {
10297
10391
  display: 'flex',
10298
10392
  flexDirection: 'column',
10299
10393
  gap: 1,
@@ -10302,33 +10396,19 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10302
10396
  bgcolor: theme.palette.mode === 'dark'
10303
10397
  ? 'rgba(255, 255, 255, 0.05)'
10304
10398
  : 'rgba(0, 0, 0, 0.02)',
10305
- }, children: [jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", children: "Enviar recordatorio" }), jsxRuntimeExports.jsx(TextField, { type: "number", size: "small", value: notification.value, onChange: (e) => {
10306
- const updated = [...(currentData?.notifications || [])];
10307
- updated[index] = { ...notification, value: parseInt(e.target.value) || 0 };
10308
- handleFieldChange('notifications', updated);
10309
- }, disabled: isViewMode, sx: { width: '70px' }, inputProps: { min: 0 } }), jsxRuntimeExports.jsx(FormControl, { size: "small", sx: { minWidth: '100px' }, children: jsxRuntimeExports.jsxs(Select, { value: notification.type, onChange: (e) => {
10310
- const updated = [...(currentData?.notifications || [])];
10311
- updated[index] = { ...notification, type: e.target.value };
10312
- handleFieldChange('notifications', updated);
10313
- }, disabled: isViewMode, children: [jsxRuntimeExports.jsx(MenuItem, { value: "minutes", children: "minuto/s" }), jsxRuntimeExports.jsx(MenuItem, { value: "hours", children: "hora/s" }), jsxRuntimeExports.jsx(MenuItem, { value: "days", children: "d\u00EDa/s" })] }) }), jsxRuntimeExports.jsx(Typography, { variant: "body2", children: "antes." })] }), jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [jsxRuntimeExports.jsx(FormControlLabel, { control: jsxRuntimeExports.jsx(Checkbox, { checked: notification.sendToContact || false, onChange: (e) => {
10399
+ }, children: isViewMode ? (jsxRuntimeExports.jsxs(Typography, { variant: "body2", children: ["Enviar recordatorio ", notification.value, " ", notification.type === 'minutes' ? 'minuto/s' : notification.type === 'hours' ? 'hora/s' : 'd\u00eda/s', " antes", notification.sendToContact && ' a contacto externo'] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", children: "Enviar recordatorio" }), jsxRuntimeExports.jsx(TextField, { type: "number", size: "small", value: notification.value, onChange: (e) => {
10314
10400
  const updated = [...(currentData?.notifications || [])];
10315
- updated[index] = { ...notification, sendToContact: e.target.checked };
10401
+ updated[index] = { ...notification, value: parseInt(e.target.value) || 0 };
10316
10402
  handleFieldChange('notifications', updated);
10317
- }, disabled: isViewMode, color: "secondary" }), label: "Enviar recordatorio a contacto externo" }), !isViewMode && (jsxRuntimeExports.jsx(IconButton, { size: "small", onClick: () => handleRemoveNotification(index), sx: { color: 'text.disabled' }, children: jsxRuntimeExports.jsx(Delete, {}) }))] })] }, index))) })] })), config.showLinkedContacts && (jsxRuntimeExports.jsxs(InputContainer, { title: l.linkedContacts, children: [!isViewMode && (jsxRuntimeExports.jsxs(Box, { sx: { position: 'relative' }, children: [jsxRuntimeExports.jsx(TextField, { fullWidth: true, size: "small", placeholder: l.searchContacts, value: contactSearch, onChange: (e) => handleContactSearchChange(e.target.value), InputProps: {
10318
- startAdornment: jsxRuntimeExports.jsx(Search, { fontSize: "small", sx: { mr: 1, color: 'text.secondary' } }),
10319
- } }), isSearchingContacts && (jsxRuntimeExports.jsx(Box, { sx: {
10320
- position: 'absolute',
10321
- bottom: 0,
10322
- left: 0,
10323
- right: 0,
10324
- height: 2,
10325
- bgcolor: 'primary.main',
10326
- animation: 'progress 1s infinite',
10327
- '@keyframes progress': {
10328
- '0%': { transform: 'translateX(-100%)' },
10329
- '100%': { transform: 'translateX(100%)' },
10330
- },
10331
- } }))] })), jsxRuntimeExports.jsx(Box, { sx: { mt: 1, display: 'flex', flexWrap: 'wrap', gap: 1 }, children: (currentData?.linkedContacts || []).map((contact) => (jsxRuntimeExports.jsxs(Box, { sx: {
10403
+ }, sx: { width: '70px' }, inputProps: { min: 0 } }), jsxRuntimeExports.jsx(FormControl, { size: "small", sx: { minWidth: '100px' }, children: jsxRuntimeExports.jsxs(Select, { value: notification.type, onChange: (e) => {
10404
+ const updated = [...(currentData?.notifications || [])];
10405
+ updated[index] = { ...notification, type: e.target.value };
10406
+ handleFieldChange('notifications', updated);
10407
+ }, children: [jsxRuntimeExports.jsx(MenuItem, { value: "minutes", children: "minuto/s" }), jsxRuntimeExports.jsx(MenuItem, { value: "hours", children: "hora/s" }), jsxRuntimeExports.jsx(MenuItem, { value: "days", children: "d\\u00eda/s" })] }) }), jsxRuntimeExports.jsx(Typography, { variant: "body2", children: "antes." })] }), jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [jsxRuntimeExports.jsx(FormControlLabel, { control: jsxRuntimeExports.jsx(Checkbox, { checked: notification.sendToContact || false, onChange: (e) => {
10408
+ const updated = [...(currentData?.notifications || [])];
10409
+ updated[index] = { ...notification, sendToContact: e.target.checked };
10410
+ handleFieldChange('notifications', updated);
10411
+ }, color: "secondary" }), label: "Enviar recordatorio a contacto externo" }), jsxRuntimeExports.jsx(IconButton, { size: "small", onClick: () => handleRemoveNotification(index), sx: { color: 'text.disabled' }, children: jsxRuntimeExports.jsx(Delete, {}) })] })] })) }, index))) }))] })), config.showLinkedContacts && (jsxRuntimeExports.jsxs(InputContainer, { title: l.linkedContacts, children: [!isViewMode && (jsxRuntimeExports.jsx(ContactSearchInput, { onChange: handleContactSearchDebounced, placeholder: l.searchContacts, isSearching: isSearching || isSearchingContacts, value: contactSearchValue })), (currentData?.linkedContacts || []).length === 0 && isViewMode ? (jsxRuntimeExports.jsx(Typography, { color: "text.secondary", children: "-" })) : (jsxRuntimeExports.jsx(Box, { sx: { mt: 1, display: 'flex', flexWrap: 'wrap', gap: 1 }, children: (currentData?.linkedContacts || []).map((contact) => (jsxRuntimeExports.jsxs(Box, { sx: {
10332
10412
  display: 'inline-flex',
10333
10413
  alignItems: 'center',
10334
10414
  gap: 0.5,
@@ -10336,24 +10416,32 @@ const ModalEvents = ({ open, onClose, mode, type: initialType, showTypeTabs = fa
10336
10416
  py: 0.5,
10337
10417
  bgcolor: 'action.hover',
10338
10418
  borderRadius: 1,
10339
- }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", children: contact.name }), !isViewMode && (jsxRuntimeExports.jsx(IconButton, { size: "small", onClick: () => handleRemoveContact(contact.id), sx: { ml: 0.5 }, children: jsxRuntimeExports.jsx(Close, { fontSize: "small" }) }))] }, contact.id))) }), !isViewMode && contactSearch.length >= 2 && (jsxRuntimeExports.jsx(Box, { sx: { mt: 1, maxHeight: '200px', overflowY: 'auto', border: '1px solid', borderColor: 'divider', borderRadius: 1 }, children: isSearchingContacts ? (jsxRuntimeExports.jsx(Box, { sx: { p: 2, textAlign: 'center' }, children: jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: "Buscando..." }) })) : filteredContacts.length > 0 ? (filteredContacts.map((contact) => (jsxRuntimeExports.jsxs(Box, { sx: {
10340
- p: 1,
10341
- cursor: 'pointer',
10342
- '&:hover': { bgcolor: 'action.hover' },
10343
- }, onClick: () => {
10419
+ }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", children: contact.name }), !isViewMode && (jsxRuntimeExports.jsx(IconButton, { size: "small", onClick: () => handleRemoveContact(contact.id), sx: { ml: 0.5 }, children: jsxRuntimeExports.jsx(Close, { fontSize: "small" }) }))] }, contact.id))) })), !isViewMode && contactSearchValue.length >= 2 && (jsxRuntimeExports.jsx(List, { sx: {
10420
+ mt: 1,
10421
+ maxHeight: '200px',
10422
+ overflow: 'auto',
10423
+ border: '1px solid',
10424
+ borderColor: 'divider',
10425
+ borderRadius: 1,
10426
+ //@ts-ignore
10427
+ backgroundColor: theme.palette.background.panel,
10428
+ backgroundImage: 'linear-gradient(rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.12))',
10429
+ p: 0,
10430
+ }, children: (isSearching || isSearchingContacts) ? (jsxRuntimeExports.jsx(Box, { sx: { p: 2, textAlign: 'center' }, children: jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: "Buscando..." }) })) : filteredContacts.length > 0 ? (filteredContacts.map((contact) => (jsxRuntimeExports.jsxs(ListItemButton, { onClick: () => {
10344
10431
  handleAddContact(contact);
10345
- setContactSearch('');
10432
+ setContactSearchValue('');
10433
+ contactSearchRef.current = '';
10346
10434
  setSearchResults([]);
10347
- }, children: [jsxRuntimeExports.jsx(Typography, { variant: "body2", children: contact.name }), contact.email && (jsxRuntimeExports.jsx(Typography, { variant: "caption", color: "text.secondary", children: contact.email }))] }, contact.id)))) : (jsxRuntimeExports.jsx(Box, { sx: { p: 2, textAlign: 'center' }, children: jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: "No se encontraron contactos" }) })) }))] })), isEvent && config.showLocation && (slots.location ? slots.location({
10435
+ }, children: [jsxRuntimeExports.jsx(ListItemIcon, { children: jsxRuntimeExports.jsx(Person, { sx: { color: 'text.disabled' } }) }), jsxRuntimeExports.jsx(ListItemText, { primary: contact.name, secondary: contact.email })] }, contact.id)))) : (jsxRuntimeExports.jsx(Box, { sx: { p: 2, textAlign: 'center' }, children: jsxRuntimeExports.jsx(Typography, { variant: "body2", color: "text.secondary", children: "No se encontraron contactos" }) })) }))] })), isEvent && config.showLocation && ((slots.location && !isViewMode) ? slots.location({
10348
10436
  disabled: isViewMode,
10349
10437
  mode,
10350
10438
  type: currentType,
10351
10439
  value: localEventData.location || '',
10352
10440
  onChange: (location) => handleFieldChange('location', location),
10353
10441
  placeholder: l.locationPlaceholder,
10354
- }) : (jsxRuntimeExports.jsx(InputContainer, { title: l.location, children: jsxRuntimeExports.jsx(TextField, { fullWidth: true, size: "small", placeholder: l.locationPlaceholder, value: localEventData.location || '', onChange: (e) => handleFieldChange('location', e.target.value), disabled: isViewMode, InputProps: {
10442
+ }) : (jsxRuntimeExports.jsx(InputContainer, { title: l.location, children: isViewMode ? (jsxRuntimeExports.jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [jsxRuntimeExports.jsx(Place, { fontSize: "small", sx: { color: 'text.secondary' } }), renderViewValue(localEventData.location)] })) : (jsxRuntimeExports.jsx(TextField, { fullWidth: true, size: "small", placeholder: l.locationPlaceholder, value: localEventData.location || '', onChange: (e) => handleFieldChange('location', e.target.value), InputProps: {
10355
10443
  startAdornment: jsxRuntimeExports.jsx(Place, { fontSize: "small", sx: { mr: 1, color: 'text.secondary' } }),
10356
- } }) })))] }), jsxRuntimeExports.jsxs(DialogActions, { sx: { px: 3, pb: 2 }, children: [jsxRuntimeExports.jsx(Button, { variant: "outlined", color: "secondary", size: "small", onClick: onClose, disabled: isSaving || isDeleting, children: l.cancel }), !isViewMode && (jsxRuntimeExports.jsx(Button, { variant: "contained", color: "primary", size: "small", onClick: handleSave, disabled: isSaving || isDeleting, children: isSaving ? 'Guardando...' : l.save }))] })] }));
10444
+ } })) })))] }), jsxRuntimeExports.jsxs(DialogActions, { sx: { px: 3, pb: 2 }, children: [jsxRuntimeExports.jsx(Button, { variant: "outlined", color: "secondary", size: "small", onClick: onClose, disabled: isSaving || isDeleting, children: l.cancel }), !isViewMode && (jsxRuntimeExports.jsx(Button, { variant: "contained", color: "primary", size: "small", onClick: handleSave, disabled: isSaving || isDeleting, children: isSaving ? 'Guardando...' : l.save }))] })] }));
10357
10445
  };
10358
10446
 
10359
10447
  export { ContactInfoPopup, ModalEvents, TestBox };