@bit.rhplus/ui.f7.detail-item 0.0.15 → 0.0.17
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/components/Calendar.jsx +257 -21
- package/components/Contact.jsx +74 -35
- package/components/Custom.jsx +10 -2
- package/components/InputText.jsx +4 -3
- package/components/List.jsx +14 -8
- package/dist/components/Calendar.d.ts +2 -1
- package/dist/components/Calendar.js +218 -29
- package/dist/components/Calendar.js.map +1 -1
- package/dist/components/Contact.d.ts +2 -1
- package/dist/components/Contact.js +49 -20
- package/dist/components/Contact.js.map +1 -1
- package/dist/components/Custom.d.ts +2 -1
- package/dist/components/Custom.js +8 -2
- package/dist/components/Custom.js.map +1 -1
- package/dist/components/InputText.js +1 -1
- package/dist/components/InputText.js.map +1 -1
- package/dist/components/List.js +14 -8
- package/dist/components/List.js.map +1 -1
- package/package.json +5 -4
- /package/dist/{preview-1758580664787.js → preview-1758725544565.js} +0 -0
package/components/Calendar.jsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
|
3
|
-
import { f7, Popup, Page, Navbar, NavLeft, NavTitle, NavTitleLarge, NavRight, Link, Block, Icon, Card } from 'framework7-react';
|
|
4
|
-
import { Calendar as CalendarIcon } from 'lucide-react';
|
|
3
|
+
import { f7, Popup, Popover, Page, Navbar, NavLeft, NavTitle, NavTitleLarge, NavRight, Link, Block, Icon, Card, List, ListInput, Picker, Button } from 'framework7-react';
|
|
4
|
+
import { Calendar as CalendarIcon, X } from 'lucide-react';
|
|
5
|
+
import SaveButton from '@bit.rhplus/ui.f7.save-button';
|
|
6
|
+
import SmallButton from '@bit.rhplus/ui.f7.small-button';
|
|
5
7
|
|
|
6
8
|
export const Calendar = ({
|
|
7
9
|
value,
|
|
@@ -16,6 +18,7 @@ export const Calendar = ({
|
|
|
16
18
|
icon,
|
|
17
19
|
iconSize = 16,
|
|
18
20
|
field = null,
|
|
21
|
+
enableTime = false, // Nový prop pro povolení výběru času
|
|
19
22
|
calendarParams = {},
|
|
20
23
|
...restProps
|
|
21
24
|
}) => {
|
|
@@ -24,7 +27,20 @@ export const Calendar = ({
|
|
|
24
27
|
const isInitializingRef = useRef(false);
|
|
25
28
|
const [displayValue, setDisplayValue] = useState('');
|
|
26
29
|
const [popupOpened, setPopupOpened] = useState(false);
|
|
30
|
+
const [timePopoverOpened, setTimePopoverOpened] = useState(false);
|
|
31
|
+
const timePickerRef = useRef(null);
|
|
27
32
|
const [selectedDate, setSelectedDate] = useState(value ? new Date(value) : null);
|
|
33
|
+
const [selectedTime, setSelectedTime] = useState(() => {
|
|
34
|
+
if (value && enableTime) {
|
|
35
|
+
const d = new Date(value);
|
|
36
|
+
return {
|
|
37
|
+
hours: String(d.getHours()).padStart(2, '0'),
|
|
38
|
+
minutes: String(d.getMinutes()).padStart(2, '0'),
|
|
39
|
+
isSet: true
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return { hours: null, minutes: null, isSet: false };
|
|
43
|
+
});
|
|
28
44
|
|
|
29
45
|
// Převod hodnoty na display formát
|
|
30
46
|
const formatDate = (date) => {
|
|
@@ -36,7 +52,16 @@ export const Calendar = ({
|
|
|
36
52
|
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
37
53
|
const year = d.getFullYear();
|
|
38
54
|
|
|
39
|
-
|
|
55
|
+
let dateStr = `${day}.${month}.${year}`;
|
|
56
|
+
|
|
57
|
+
// Pokud je povolený čas a je nastaven, přidej ho k formátu
|
|
58
|
+
if (enableTime && selectedTime.isSet && selectedTime.hours !== null) {
|
|
59
|
+
const hours = String(d.getHours()).padStart(2, '0');
|
|
60
|
+
const minutes = String(d.getMinutes()).padStart(2, '0');
|
|
61
|
+
dateStr += ` ${hours}:${minutes}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return dateStr;
|
|
40
65
|
};
|
|
41
66
|
|
|
42
67
|
// Aktualizace display hodnoty při změně value
|
|
@@ -54,12 +79,21 @@ export const Calendar = ({
|
|
|
54
79
|
// Cleanup kalendáře při zavírání popup
|
|
55
80
|
useEffect(() => {
|
|
56
81
|
if (!popupOpened && calendarRef.current) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
82
|
+
// Bezpečný cleanup s timeout pro prevenci konfliktů
|
|
83
|
+
setTimeout(() => {
|
|
84
|
+
if (calendarRef.current) {
|
|
85
|
+
try {
|
|
86
|
+
calendarRef.current.destroy();
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.warn('Calendar cleanup error:', error);
|
|
89
|
+
}
|
|
90
|
+
calendarRef.current = null;
|
|
91
|
+
}
|
|
92
|
+
// Vyčisti i DOM kontejner
|
|
93
|
+
if (calendarContainerRef.current) {
|
|
94
|
+
calendarContainerRef.current.innerHTML = '';
|
|
95
|
+
}
|
|
96
|
+
}, 100);
|
|
63
97
|
}
|
|
64
98
|
}, [popupOpened]);
|
|
65
99
|
|
|
@@ -106,6 +140,10 @@ export const Calendar = ({
|
|
|
106
140
|
dayNames,
|
|
107
141
|
dayNamesShort: dayNames,
|
|
108
142
|
firstDay: 1, // Pondělí jako první den
|
|
143
|
+
// Vypne timePicker - použijeme vlastní řešení
|
|
144
|
+
timePicker: false,
|
|
145
|
+
// Vypne automatické zavírání při enableTime
|
|
146
|
+
closeOnSelect: !enableTime,
|
|
109
147
|
on: {
|
|
110
148
|
change: (calendar, value) => {
|
|
111
149
|
// Ignoruj změny během inicializace
|
|
@@ -116,14 +154,16 @@ export const Calendar = ({
|
|
|
116
154
|
if (value && value.length > 0) {
|
|
117
155
|
const newSelectedDate = value[0];
|
|
118
156
|
setSelectedDate(newSelectedDate);
|
|
119
|
-
//
|
|
120
|
-
if (
|
|
121
|
-
onChange
|
|
157
|
+
// Pokud není povolen čas, automaticky potvrď a zavři popup
|
|
158
|
+
if (!enableTime) {
|
|
159
|
+
if (onChange) {
|
|
160
|
+
onChange(newSelectedDate);
|
|
161
|
+
}
|
|
162
|
+
// Zavři popup s mírným zpožděním pro lepší UX
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
setPopupOpened(false);
|
|
165
|
+
}, 200);
|
|
122
166
|
}
|
|
123
|
-
// Zavři popup s mírným zpožděním pro lepší UX
|
|
124
|
-
setTimeout(() => {
|
|
125
|
-
setPopupOpened(false);
|
|
126
|
-
}, 200);
|
|
127
167
|
}
|
|
128
168
|
}
|
|
129
169
|
},
|
|
@@ -141,25 +181,157 @@ export const Calendar = ({
|
|
|
141
181
|
return () => {
|
|
142
182
|
clearTimeout(timeoutId);
|
|
143
183
|
if (calendarRef.current) {
|
|
144
|
-
|
|
184
|
+
try {
|
|
185
|
+
calendarRef.current.destroy();
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.warn('Calendar cleanup error:', error);
|
|
188
|
+
}
|
|
145
189
|
calendarRef.current = null;
|
|
146
190
|
}
|
|
147
191
|
};
|
|
148
192
|
}, [popupOpened, selectedDate, calendarParams]);
|
|
149
193
|
|
|
194
|
+
// Otevření time picker
|
|
195
|
+
const openTimePicker = useCallback(() => {
|
|
196
|
+
if (!enableTime) return;
|
|
197
|
+
|
|
198
|
+
// Bezpečný cleanup existujícího pickeru
|
|
199
|
+
if (timePickerRef.current) {
|
|
200
|
+
try {
|
|
201
|
+
timePickerRef.current.destroy();
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.warn('Time picker cleanup error:', error);
|
|
204
|
+
}
|
|
205
|
+
timePickerRef.current = null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Krátký timeout pro zajištění úplného cleanup
|
|
209
|
+
setTimeout(() => {
|
|
210
|
+
// Vytvoř hodnoty pro picker
|
|
211
|
+
const hours = Array.from({ length: 24 }, (_, i) => ({
|
|
212
|
+
value: String(i).padStart(2, '0'),
|
|
213
|
+
displayValue: String(i).padStart(2, '0')
|
|
214
|
+
}));
|
|
215
|
+
|
|
216
|
+
const minutes = Array.from({ length: 60 }, (_, i) => ({
|
|
217
|
+
value: String(i).padStart(2, '0'),
|
|
218
|
+
displayValue: String(i).padStart(2, '0')
|
|
219
|
+
}));
|
|
220
|
+
|
|
221
|
+
timePickerRef.current = f7.picker.create({
|
|
222
|
+
inputEl: '.time-picker-button',
|
|
223
|
+
value: selectedTime.isSet ? [selectedTime.hours, selectedTime.minutes] : ['09', '00'],
|
|
224
|
+
cols: [
|
|
225
|
+
{
|
|
226
|
+
textAlign: 'center',
|
|
227
|
+
values: hours.map(h => h.value),
|
|
228
|
+
displayValues: hours.map(h => h.displayValue),
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
textAlign: 'center',
|
|
232
|
+
values: minutes.map(m => m.value),
|
|
233
|
+
displayValues: minutes.map(m => m.displayValue),
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
formatValue: (values) => `${values[0]}:${values[1]}`,
|
|
237
|
+
on: {
|
|
238
|
+
change: (picker, values) => {
|
|
239
|
+
setSelectedTime({
|
|
240
|
+
hours: values[0],
|
|
241
|
+
minutes: values[1],
|
|
242
|
+
isSet: true
|
|
243
|
+
});
|
|
244
|
+
},
|
|
245
|
+
close: () => {
|
|
246
|
+
// Cleanup při zavření
|
|
247
|
+
setTimeout(() => {
|
|
248
|
+
if (timePickerRef.current) {
|
|
249
|
+
try {
|
|
250
|
+
timePickerRef.current.destroy();
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.warn('Time picker close cleanup error:', error);
|
|
253
|
+
}
|
|
254
|
+
timePickerRef.current = null;
|
|
255
|
+
}
|
|
256
|
+
}, 100);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
timePickerRef.current.open();
|
|
262
|
+
}, 50);
|
|
263
|
+
}, [enableTime, selectedTime]);
|
|
264
|
+
|
|
265
|
+
// Vynulování času
|
|
266
|
+
const clearTime = useCallback(() => {
|
|
267
|
+
setSelectedTime({ hours: null, minutes: null, isSet: false });
|
|
268
|
+
}, []);
|
|
269
|
+
|
|
270
|
+
// Cleanup time pickeru
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
return () => {
|
|
273
|
+
if (timePickerRef.current) {
|
|
274
|
+
try {
|
|
275
|
+
timePickerRef.current.destroy();
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.warn('Time picker unmount cleanup error:', error);
|
|
278
|
+
}
|
|
279
|
+
timePickerRef.current = null;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}, []);
|
|
283
|
+
|
|
284
|
+
// Cleanup při zavírání hlavního popup
|
|
285
|
+
useEffect(() => {
|
|
286
|
+
if (!popupOpened && timePickerRef.current) {
|
|
287
|
+
try {
|
|
288
|
+
timePickerRef.current.destroy();
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.warn('Time picker popup cleanup error:', error);
|
|
291
|
+
}
|
|
292
|
+
timePickerRef.current = null;
|
|
293
|
+
}
|
|
294
|
+
}, [popupOpened]);
|
|
295
|
+
|
|
150
296
|
// Potvrzení výběru data
|
|
151
297
|
const confirmSelection = useCallback(() => {
|
|
152
298
|
if (selectedDate && onChange) {
|
|
153
|
-
|
|
299
|
+
let finalDate = new Date(selectedDate);
|
|
300
|
+
|
|
301
|
+
// Pokud je povolen čas a je nastaven, aplikuj vybraný čas
|
|
302
|
+
if (enableTime && selectedTime.isSet && selectedTime.hours !== null) {
|
|
303
|
+
finalDate.setHours(parseInt(selectedTime.hours));
|
|
304
|
+
finalDate.setMinutes(parseInt(selectedTime.minutes));
|
|
305
|
+
} else if (enableTime && !selectedTime.isSet) {
|
|
306
|
+
// Pokud čas není nastaven, použij 00:00
|
|
307
|
+
finalDate.setHours(0);
|
|
308
|
+
finalDate.setMinutes(0);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
onChange(finalDate);
|
|
154
312
|
}
|
|
155
313
|
setPopupOpened(false);
|
|
156
|
-
}, [selectedDate, onChange]);
|
|
314
|
+
}, [selectedDate, selectedTime, enableTime, onChange]);
|
|
157
315
|
|
|
158
316
|
// Zrušení výběru
|
|
159
317
|
const cancelSelection = useCallback(() => {
|
|
160
318
|
setSelectedDate(value ? new Date(value) : null);
|
|
161
|
-
|
|
162
|
-
|
|
319
|
+
// Obnovení původního stavu času
|
|
320
|
+
if (value && enableTime) {
|
|
321
|
+
const d = new Date(value);
|
|
322
|
+
setSelectedTime({
|
|
323
|
+
hours: String(d.getHours()).padStart(2, '0'),
|
|
324
|
+
minutes: String(d.getMinutes()).padStart(2, '0'),
|
|
325
|
+
isSet: true
|
|
326
|
+
});
|
|
327
|
+
} else {
|
|
328
|
+
setSelectedTime({ hours: null, minutes: null, isSet: false });
|
|
329
|
+
}
|
|
330
|
+
// Bezpečné zavření s delay
|
|
331
|
+
setTimeout(() => {
|
|
332
|
+
setPopupOpened(false);
|
|
333
|
+
}, 50);
|
|
334
|
+
}, [value, enableTime]);
|
|
163
335
|
|
|
164
336
|
const containerStyle = {
|
|
165
337
|
display: 'flex',
|
|
@@ -250,11 +422,75 @@ export const Calendar = ({
|
|
|
250
422
|
/>
|
|
251
423
|
</Block>
|
|
252
424
|
</Card>
|
|
425
|
+
|
|
426
|
+
{/* Pokud je povolen čas, zobraz tlačítko pro výběr času */}
|
|
427
|
+
{enableTime && (
|
|
428
|
+
<Block
|
|
429
|
+
style={{
|
|
430
|
+
padding: '10px 0',
|
|
431
|
+
}}
|
|
432
|
+
>
|
|
433
|
+
<Card>
|
|
434
|
+
<Block style={{ padding: '20px' }}>
|
|
435
|
+
<div style={{
|
|
436
|
+
display: 'flex',
|
|
437
|
+
justifyContent: 'space-between',
|
|
438
|
+
alignItems: 'center'
|
|
439
|
+
}}>
|
|
440
|
+
<h3 style={{ margin: 0, fontSize: '18px', fontWeight: '600' }}>Čas</h3>
|
|
441
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
442
|
+
<SmallButton
|
|
443
|
+
className="time-picker-button"
|
|
444
|
+
onClick={openTimePicker}
|
|
445
|
+
style={{
|
|
446
|
+
width: 'auto',
|
|
447
|
+
opacity: selectedTime.isSet ? 1 : 0.6,
|
|
448
|
+
padding: '16px 22px',
|
|
449
|
+
}}
|
|
450
|
+
>
|
|
451
|
+
{selectedTime.isSet ? `${selectedTime.hours}:${selectedTime.minutes}` : 'Vyberte čas'}
|
|
452
|
+
</SmallButton>
|
|
453
|
+
{selectedTime.isSet && (
|
|
454
|
+
<button
|
|
455
|
+
onClick={clearTime}
|
|
456
|
+
style={{
|
|
457
|
+
background: 'transparent',
|
|
458
|
+
border: 'none',
|
|
459
|
+
padding: '4px',
|
|
460
|
+
cursor: 'pointer',
|
|
461
|
+
borderRadius: '4px',
|
|
462
|
+
display: 'flex',
|
|
463
|
+
alignItems: 'center',
|
|
464
|
+
justifyContent: 'center',
|
|
465
|
+
opacity: 0.6,
|
|
466
|
+
transition: 'opacity 0.2s'
|
|
467
|
+
}}
|
|
468
|
+
onMouseOver={(e) => e.target.style.opacity = '1'}
|
|
469
|
+
onMouseOut={(e) => e.target.style.opacity = '0.6'}
|
|
470
|
+
>
|
|
471
|
+
<X size={16} color="#666" />
|
|
472
|
+
</button>
|
|
473
|
+
)}
|
|
474
|
+
</div>
|
|
475
|
+
</div>
|
|
476
|
+
</Block>
|
|
477
|
+
</Card>
|
|
478
|
+
</Block>
|
|
479
|
+
)}
|
|
480
|
+
|
|
481
|
+
{/* Tlačítko pro potvrzení */}
|
|
482
|
+
{enableTime && (
|
|
483
|
+
<SaveButton
|
|
484
|
+
onClick={confirmSelection}
|
|
485
|
+
variant="black"
|
|
486
|
+
/>
|
|
487
|
+
)}
|
|
253
488
|
</Block>
|
|
254
489
|
</div>
|
|
255
490
|
</div>
|
|
256
491
|
</div>
|
|
257
492
|
</Popup>
|
|
493
|
+
|
|
258
494
|
</>
|
|
259
495
|
);
|
|
260
496
|
};
|
package/components/Contact.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { ListInput } from 'framework7-react';
|
|
3
|
+
import { ListInput, Block, List } from 'framework7-react';
|
|
4
4
|
import { UserCheck } from 'lucide-react';
|
|
5
5
|
import { Custom } from './Custom';
|
|
6
6
|
|
|
@@ -12,29 +12,36 @@ const ContactRenderer = ({ fields, formData, onChange }) => {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
15
|
+
<Block inset>
|
|
16
|
+
<List>
|
|
17
|
+
{fields.map((field, index) => (
|
|
18
|
+
<ListInput
|
|
19
|
+
key={field.key || index}
|
|
20
|
+
type={field.type || 'text'}
|
|
21
|
+
label={field.label}
|
|
22
|
+
placeholder={field.placeholder}
|
|
23
|
+
value={formData[field.key] || ''}
|
|
24
|
+
onInput={(e) => handleInputChange(field.key, e)}
|
|
25
|
+
clearButton
|
|
26
|
+
style={{ fontSize: '18px' }}
|
|
27
|
+
// Speciální styling pro různé typy polí
|
|
28
|
+
{...(field.type === 'email' && {
|
|
29
|
+
inputMode: 'email',
|
|
30
|
+
autoComplete: 'email'
|
|
31
|
+
})}
|
|
32
|
+
{...(field.type === 'tel' && {
|
|
33
|
+
inputMode: 'tel',
|
|
34
|
+
autoComplete: 'tel'
|
|
35
|
+
})}
|
|
36
|
+
{...(field.type === 'textarea' && {
|
|
37
|
+
type: 'textarea',
|
|
38
|
+
resizable: false,
|
|
39
|
+
inputStyle: { minHeight: '60px', resize: 'none' }
|
|
40
|
+
})}
|
|
41
|
+
/>
|
|
42
|
+
))}
|
|
43
|
+
</List>
|
|
44
|
+
</Block>
|
|
38
45
|
);
|
|
39
46
|
};
|
|
40
47
|
|
|
@@ -48,22 +55,17 @@ export const Contact = ({
|
|
|
48
55
|
color = '#6887d3',
|
|
49
56
|
size = 16,
|
|
50
57
|
field = null, // Pole pro výběr konkrétní vlastnosti objektu
|
|
58
|
+
visibleFields = ['name', 'email', 'phone', 'position'], // Pole k zobrazení v popup
|
|
51
59
|
...restProps
|
|
52
60
|
}) => {
|
|
53
61
|
// Předdefinovaná pole pro Externí PM
|
|
54
|
-
const
|
|
62
|
+
const allFields = [
|
|
55
63
|
{
|
|
56
|
-
key: '
|
|
64
|
+
key: 'fullName',
|
|
57
65
|
label: 'Jméno',
|
|
58
66
|
type: 'text',
|
|
59
67
|
placeholder: 'Zadejte jméno'
|
|
60
68
|
},
|
|
61
|
-
{
|
|
62
|
-
key: 'lastName',
|
|
63
|
-
label: 'Příjmení',
|
|
64
|
-
type: 'text',
|
|
65
|
-
placeholder: 'Zadejte příjmení'
|
|
66
|
-
},
|
|
67
69
|
{
|
|
68
70
|
key: 'email',
|
|
69
71
|
label: 'Email',
|
|
@@ -81,11 +83,48 @@ export const Contact = ({
|
|
|
81
83
|
label: 'Pozice',
|
|
82
84
|
type: 'text',
|
|
83
85
|
placeholder: 'Zadejte pozici'
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
key: 'note',
|
|
89
|
+
label: 'Poznámka',
|
|
90
|
+
type: 'textarea',
|
|
91
|
+
placeholder: 'Zadejte poznámku'
|
|
84
92
|
}
|
|
85
93
|
];
|
|
86
94
|
|
|
87
|
-
//
|
|
88
|
-
const
|
|
95
|
+
// Filtrování polí podle visibleFields
|
|
96
|
+
const pmFields = allFields.filter(field => visibleFields.includes(field.key));
|
|
97
|
+
|
|
98
|
+
// Funkce pro generování zobrazovaného textu
|
|
99
|
+
const getContactDisplayText = (contactData) => {
|
|
100
|
+
if (!contactData || typeof contactData !== 'object') {
|
|
101
|
+
return placeholder;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Priorita: fullName > firstName + lastName > email > phone > position
|
|
105
|
+
if (contactData.fullName) {
|
|
106
|
+
return contactData.fullName + (contactData.position ? ` - ${contactData.position}` : '');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (contactData.firstName || contactData.lastName) {
|
|
110
|
+
const name = [contactData.firstName, contactData.lastName].filter(Boolean).join(' ');
|
|
111
|
+
return name + (contactData.position ? ` - ${contactData.position}` : '');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (contactData.email) {
|
|
115
|
+
return contactData.email + (contactData.position ? ` - ${contactData.position}` : '');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (contactData.phone) {
|
|
119
|
+
return contactData.phone + (contactData.position ? ` - ${contactData.position}` : '');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (contactData.position) {
|
|
123
|
+
return contactData.position;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return placeholder;
|
|
127
|
+
};
|
|
89
128
|
|
|
90
129
|
return (
|
|
91
130
|
<Custom
|
|
@@ -99,7 +138,7 @@ export const Contact = ({
|
|
|
99
138
|
lucideIcon={UserCheck}
|
|
100
139
|
FormRenderer={ContactRenderer}
|
|
101
140
|
fields={pmFields}
|
|
102
|
-
|
|
141
|
+
getDisplayText={getContactDisplayText}
|
|
103
142
|
field={field}
|
|
104
143
|
{...restProps}
|
|
105
144
|
/>
|
package/components/Custom.jsx
CHANGED
|
@@ -36,6 +36,7 @@ export const Custom = ({
|
|
|
36
36
|
{ key: 'position', label: 'Pozice', type: 'text', placeholder: 'Zadejte pozici' }
|
|
37
37
|
],
|
|
38
38
|
displayFields = ['firstName', 'lastName', 'position'], // Pole pro zobrazení v linku
|
|
39
|
+
getDisplayText = null, // Custom funkce pro generování zobrazovaného textu
|
|
39
40
|
field = null, // Pole pro výběr konkrétní vlastnosti objektu
|
|
40
41
|
...restProps
|
|
41
42
|
}) => {
|
|
@@ -164,8 +165,15 @@ export const Custom = ({
|
|
|
164
165
|
};
|
|
165
166
|
|
|
166
167
|
// Zobrazí text v linku podle vyplněných dat
|
|
167
|
-
const
|
|
168
|
+
const getDisplayTextInternal = () => {
|
|
168
169
|
const currentObject = findObjectByValue(value);
|
|
170
|
+
|
|
171
|
+
// Pokud je poskytnut custom getDisplayText, použij ho
|
|
172
|
+
if (getDisplayText && typeof getDisplayText === 'function') {
|
|
173
|
+
return getDisplayText(currentObject);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Jinak použij defaultní logiku
|
|
169
177
|
if (currentObject && typeof currentObject === 'object') {
|
|
170
178
|
const displayValues = displayFields
|
|
171
179
|
.map(fieldKey => currentObject[fieldKey])
|
|
@@ -182,7 +190,7 @@ export const Custom = ({
|
|
|
182
190
|
<div {...restProps}>
|
|
183
191
|
<Link onClick={handleOpenPopup} className="link" style={linkStyle}>
|
|
184
192
|
{renderIcon()}
|
|
185
|
-
{
|
|
193
|
+
{getDisplayTextInternal()}
|
|
186
194
|
</Link>
|
|
187
195
|
|
|
188
196
|
<Popup
|
package/components/InputText.jsx
CHANGED
|
@@ -108,17 +108,18 @@ export const InputText = ({
|
|
|
108
108
|
<NavTitleLarge>{title}</NavTitleLarge>
|
|
109
109
|
</Navbar>
|
|
110
110
|
|
|
111
|
-
<Block
|
|
111
|
+
<Block inset>
|
|
112
112
|
<List>
|
|
113
113
|
<ListInput
|
|
114
|
-
type="
|
|
115
|
-
label="Typ dokladu"
|
|
114
|
+
type="textarea"
|
|
116
115
|
placeholder={placeholder}
|
|
117
116
|
value={inputValue}
|
|
118
117
|
onInput={(e) => setInputValue(e.target.value)}
|
|
119
118
|
clearButton
|
|
120
119
|
autoFocus
|
|
120
|
+
resizable
|
|
121
121
|
style={{ fontSize: '18px' }}
|
|
122
|
+
inputStyle={{ minHeight: '24px' }}
|
|
122
123
|
/>
|
|
123
124
|
</List>
|
|
124
125
|
</Block>
|
package/components/List.jsx
CHANGED
|
@@ -82,12 +82,15 @@ export const List = ({
|
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
//
|
|
86
|
-
const
|
|
87
|
-
return findItemsByValue(value);
|
|
88
|
-
}, []); // Prázdné dependency array - pouze při mount
|
|
85
|
+
// State pro vybrané položky - inicializace s prázdným polem
|
|
86
|
+
const [selectedItems, setSelectedItems] = useState([]);
|
|
89
87
|
|
|
90
|
-
|
|
88
|
+
// Synchronizace selectedItems s value prop
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
const items = findItemsByValue(value);
|
|
91
|
+
console.log("🚀 ~ List ~ items:", items, value)
|
|
92
|
+
setSelectedItems(items);
|
|
93
|
+
}, [value, options, field]);
|
|
91
94
|
|
|
92
95
|
const linkStyle = {
|
|
93
96
|
color,
|
|
@@ -98,13 +101,16 @@ export const List = ({
|
|
|
98
101
|
};
|
|
99
102
|
|
|
100
103
|
const handleCancel = () => {
|
|
101
|
-
|
|
104
|
+
// Reset selected items na aktuální value
|
|
105
|
+
const items = findItemsByValue(value);
|
|
106
|
+
setSelectedItems(items);
|
|
102
107
|
setPopupOpened(false);
|
|
103
108
|
};
|
|
104
109
|
|
|
105
110
|
const handleOpenPopup = () => {
|
|
106
|
-
// Reset selected items při otevření
|
|
107
|
-
|
|
111
|
+
// Reset selected items při otevření na aktuální value
|
|
112
|
+
const items = findItemsByValue(value);
|
|
113
|
+
setSelectedItems(items);
|
|
108
114
|
setPopupOpened(true);
|
|
109
115
|
};
|
|
110
116
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function Calendar({ value, title, onChange, placeholder, format, color, style, disabled, lucideIcon, icon, iconSize, field, calendarParams, ...restProps }: {
|
|
1
|
+
export function Calendar({ value, title, onChange, placeholder, format, color, style, disabled, lucideIcon, icon, iconSize, field, enableTime, calendarParams, ...restProps }: {
|
|
2
2
|
[x: string]: any;
|
|
3
3
|
value: any;
|
|
4
4
|
title: any;
|
|
@@ -12,6 +12,7 @@ export function Calendar({ value, title, onChange, placeholder, format, color, s
|
|
|
12
12
|
icon: any;
|
|
13
13
|
iconSize?: number | undefined;
|
|
14
14
|
field?: null | undefined;
|
|
15
|
+
enableTime?: boolean | undefined;
|
|
15
16
|
calendarParams?: {} | undefined;
|
|
16
17
|
}): import("react/jsx-runtime").JSX.Element;
|
|
17
18
|
import React from 'react';
|