@up_si_vale/sivale-componentes-angular 1.0.0
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/README.md +81 -0
- package/ng-package.json +9 -0
- package/package.json +40 -0
- package/src/lib/atoms/button/button.component.html +21 -0
- package/src/lib/atoms/button/button.component.scss +242 -0
- package/src/lib/atoms/button/button.component.ts +43 -0
- package/src/lib/atoms/checkbox/checkbox.component.scss +131 -0
- package/src/lib/atoms/checkbox/checkbox.component.ts +130 -0
- package/src/lib/atoms/date-picker/date-picker.component.html +295 -0
- package/src/lib/atoms/date-picker/date-picker.component.scss +1002 -0
- package/src/lib/atoms/date-picker/date-picker.component.ts +942 -0
- package/src/lib/atoms/input/input.component.ts +239 -0
- package/src/lib/atoms/loader/loader.component.scss +144 -0
- package/src/lib/atoms/loader/loader.component.ts +44 -0
- package/src/lib/atoms/radio/radio.component.scss +115 -0
- package/src/lib/atoms/radio/radio.component.ts +103 -0
- package/src/lib/atoms/textarea/textarea.component.ts +155 -0
- package/src/lib/directives/asset-source.directive.ts +64 -0
- package/src/lib/directives/icon-source.directive.ts +74 -0
- package/src/lib/directives/no-leading-space.directive.ts +18 -0
- package/src/lib/directives/only-letters.directive.ts +21 -0
- package/src/lib/directives/only-number.directive.ts +15 -0
- package/src/lib/directives/rfc.directive.ts +60 -0
- package/src/lib/directives/tooltip.directive.ts +211 -0
- package/src/lib/models/snackbar.models.ts +16 -0
- package/src/lib/molecules/copy-input/copy-input.component.html +29 -0
- package/src/lib/molecules/copy-input/copy-input.component.scss +101 -0
- package/src/lib/molecules/copy-input/copy-input.component.ts +41 -0
- package/src/lib/molecules/multiselect/multiselect.component.scss +298 -0
- package/src/lib/molecules/multiselect/multiselect.component.ts +487 -0
- package/src/lib/molecules/option/option.component.ts +45 -0
- package/src/lib/molecules/phone-input/phone-input.component.scss +78 -0
- package/src/lib/molecules/phone-input/phone-input.component.ts +43 -0
- package/src/lib/molecules/select/select.component.ts +482 -0
- package/src/lib/molecules/snackbar/snackbar.component.scss +201 -0
- package/src/lib/molecules/snackbar/snackbar.component.ts +321 -0
- package/src/lib/services/snackbar.service.ts +103 -0
- package/src/lib/tokens/asset-base-url.token.ts +10 -0
- package/src/public-api.ts +38 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,942 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component,
|
|
3
|
+
Input,
|
|
4
|
+
forwardRef,
|
|
5
|
+
ViewChild,
|
|
6
|
+
ElementRef,
|
|
7
|
+
OnDestroy,
|
|
8
|
+
HostListener,
|
|
9
|
+
Renderer2,
|
|
10
|
+
OnInit
|
|
11
|
+
} from '@angular/core';
|
|
12
|
+
import { CommonModule, DOCUMENT } from '@angular/common';
|
|
13
|
+
import { ControlValueAccessor, NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
14
|
+
import { Inject } from '@angular/core';
|
|
15
|
+
|
|
16
|
+
export interface DateRange {
|
|
17
|
+
startDate: Date | null;
|
|
18
|
+
endDate: Date | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type DatePickerValue = Date | null | DateRange;
|
|
22
|
+
|
|
23
|
+
interface CalendarDay {
|
|
24
|
+
date: Date;
|
|
25
|
+
isCurrentMonth: boolean;
|
|
26
|
+
isToday: boolean;
|
|
27
|
+
isSelected: boolean;
|
|
28
|
+
isInRange: boolean;
|
|
29
|
+
isRangeStart: boolean;
|
|
30
|
+
isRangeEnd: boolean;
|
|
31
|
+
isDisabled: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type FilterOption = 'hoy' | 'ayer' | 'esta-semana' | 'semana-pasada' | 'este-mes' | 'mes-pasado' | 'este-ano' | 'ano-pasado' | 'mostrar-todo';
|
|
35
|
+
|
|
36
|
+
@Component({
|
|
37
|
+
selector: 'app-date-picker',
|
|
38
|
+
standalone: true,
|
|
39
|
+
imports: [CommonModule, ReactiveFormsModule, FormsModule],
|
|
40
|
+
templateUrl: './date-picker.component.html',
|
|
41
|
+
styleUrls: ['./date-picker.component.scss'],
|
|
42
|
+
providers: [
|
|
43
|
+
{
|
|
44
|
+
provide: NG_VALUE_ACCESSOR,
|
|
45
|
+
useExisting: forwardRef(() => DatePickerComponent),
|
|
46
|
+
multi: true
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
})
|
|
50
|
+
export class DatePickerComponent implements ControlValueAccessor, OnDestroy, OnInit {
|
|
51
|
+
@Input() label = '';
|
|
52
|
+
@Input() id = '';
|
|
53
|
+
@Input() placeholder = 'Seleccionar fecha';
|
|
54
|
+
@Input() hasError = false;
|
|
55
|
+
@Input() errorMessage = '';
|
|
56
|
+
@Input() disabled = false;
|
|
57
|
+
@Input() minDate?: Date;
|
|
58
|
+
@Input() maxDate?: Date;
|
|
59
|
+
@Input() rangeMode = false; // false = single date, true = date range
|
|
60
|
+
@Input() iconPosition: 'left' | 'right' = 'left';
|
|
61
|
+
|
|
62
|
+
@ViewChild('trigger', { read: ElementRef }) trigger!: ElementRef;
|
|
63
|
+
@ViewChild('dropdown', { read: ElementRef }) dropdown?: ElementRef;
|
|
64
|
+
|
|
65
|
+
// Single date value
|
|
66
|
+
singleValue: Date | null = null;
|
|
67
|
+
// Range value
|
|
68
|
+
rangeValue: DateRange = { startDate: null, endDate: null };
|
|
69
|
+
|
|
70
|
+
isOpen = false;
|
|
71
|
+
onChange: any = () => {};
|
|
72
|
+
onTouched: any = () => {};
|
|
73
|
+
|
|
74
|
+
leftMonthDate: Date = new Date();
|
|
75
|
+
rightMonthDate: Date = new Date();
|
|
76
|
+
tempStartDate: Date | null = null;
|
|
77
|
+
tempEndDate: Date | null = null;
|
|
78
|
+
tempSingleDate: Date | null = null;
|
|
79
|
+
hoverDate: Date | null = null;
|
|
80
|
+
|
|
81
|
+
// Store original calendar positions for cancel
|
|
82
|
+
originalLeftMonthDate: Date = new Date();
|
|
83
|
+
originalRightMonthDate: Date = new Date();
|
|
84
|
+
|
|
85
|
+
// Cached calendar days
|
|
86
|
+
leftCalendarDays: CalendarDay[] = [];
|
|
87
|
+
rightCalendarDays: CalendarDay[] = [];
|
|
88
|
+
|
|
89
|
+
filterOptions: { value: FilterOption; label: string }[] = [
|
|
90
|
+
{ value: 'hoy', label: 'Hoy' },
|
|
91
|
+
{ value: 'ayer', label: 'Ayer' },
|
|
92
|
+
{ value: 'esta-semana', label: 'Esta semana' },
|
|
93
|
+
{ value: 'semana-pasada', label: 'Semana pasada' },
|
|
94
|
+
{ value: 'este-mes', label: 'Este mes' },
|
|
95
|
+
{ value: 'mes-pasado', label: 'Mes pasado' },
|
|
96
|
+
{ value: 'este-ano', label: 'Este año' },
|
|
97
|
+
{ value: 'ano-pasado', label: 'Año pasado' },
|
|
98
|
+
{ value: 'mostrar-todo', label: 'Mostrar todo' }
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
selectedFilter: FilterOption | '' = '';
|
|
102
|
+
|
|
103
|
+
weekDays = ['Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa', 'Do'];
|
|
104
|
+
months = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
|
|
105
|
+
|
|
106
|
+
// Month/Year picker state
|
|
107
|
+
showLeftMonthPicker = false;
|
|
108
|
+
showRightMonthPicker = false;
|
|
109
|
+
years: number[] = [];
|
|
110
|
+
leftYearPickerPage = 0;
|
|
111
|
+
rightYearPickerPage = 0;
|
|
112
|
+
yearsPerPage = 12;
|
|
113
|
+
|
|
114
|
+
private scrollHandler: (() => void) | null = null;
|
|
115
|
+
private resizeHandler: (() => void) | null = null;
|
|
116
|
+
dropdownPosition: { top: string; left: string } = { top: '0px', left: '0px' };
|
|
117
|
+
|
|
118
|
+
constructor(
|
|
119
|
+
private renderer: Renderer2,
|
|
120
|
+
@Inject(DOCUMENT) private document: Document
|
|
121
|
+
) {}
|
|
122
|
+
|
|
123
|
+
ngOnInit(): void {
|
|
124
|
+
this.initializeDates();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
ngOnDestroy(): void {
|
|
128
|
+
this.removeRepositionListeners();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private initializeDates(): void {
|
|
132
|
+
const today = new Date();
|
|
133
|
+
this.leftMonthDate = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
134
|
+
this.rightMonthDate = new Date(today.getFullYear(), today.getMonth() + 1, 1);
|
|
135
|
+
this.updateCalendarDays();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private updateCalendarDays(): void {
|
|
139
|
+
this.leftCalendarDays = this.generateCalendarDays(this.leftMonthDate);
|
|
140
|
+
if (this.rangeMode) {
|
|
141
|
+
this.rightCalendarDays = this.generateCalendarDays(this.rightMonthDate);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@HostListener('document:click', ['$event'])
|
|
146
|
+
onDocumentClick(event: MouseEvent): void {
|
|
147
|
+
if (!this.isOpen) return;
|
|
148
|
+
|
|
149
|
+
const triggerElement = this.trigger?.nativeElement;
|
|
150
|
+
const dropdownElement = this.document.querySelector('.date-picker-dropdown');
|
|
151
|
+
const monthYearPickers = this.document.querySelectorAll('.month-year-picker');
|
|
152
|
+
const monthYearButtons = this.document.querySelectorAll('.month-year');
|
|
153
|
+
|
|
154
|
+
let isOnMonthYearButton = false;
|
|
155
|
+
monthYearButtons.forEach(button => {
|
|
156
|
+
if (button.contains(event.target as Node)) {
|
|
157
|
+
isOnMonthYearButton = true;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
let isInsideMonthYearPicker = false;
|
|
162
|
+
monthYearPickers.forEach(picker => {
|
|
163
|
+
if (picker.contains(event.target as Node)) {
|
|
164
|
+
isInsideMonthYearPicker = true;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (isOnMonthYearButton || isInsideMonthYearPicker) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (dropdownElement && dropdownElement.contains(event.target as Node)) {
|
|
173
|
+
this.showLeftMonthPicker = false;
|
|
174
|
+
this.showRightMonthPicker = false;
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (triggerElement && !triggerElement.contains(event.target as Node)) {
|
|
179
|
+
if (dropdownElement && !dropdownElement.contains(event.target as Node)) {
|
|
180
|
+
this.closeDropdown();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
toggleDropdown(event: Event): void {
|
|
186
|
+
event.stopPropagation();
|
|
187
|
+
if (this.disabled) return;
|
|
188
|
+
|
|
189
|
+
if (this.isOpen) {
|
|
190
|
+
this.closeDropdown();
|
|
191
|
+
} else {
|
|
192
|
+
this.openDropdown();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private openDropdown(): void {
|
|
197
|
+
if (!this.trigger) return;
|
|
198
|
+
|
|
199
|
+
if (this.rangeMode) {
|
|
200
|
+
this.tempStartDate = this.rangeValue.startDate;
|
|
201
|
+
this.tempEndDate = this.rangeValue.endDate;
|
|
202
|
+
} else {
|
|
203
|
+
this.tempSingleDate = this.singleValue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
this.originalLeftMonthDate = new Date(this.leftMonthDate);
|
|
207
|
+
this.originalRightMonthDate = new Date(this.rightMonthDate);
|
|
208
|
+
|
|
209
|
+
this.leftYearPickerPage = 0;
|
|
210
|
+
this.rightYearPickerPage = 0;
|
|
211
|
+
|
|
212
|
+
this.isOpen = true;
|
|
213
|
+
|
|
214
|
+
setTimeout(() => {
|
|
215
|
+
this.updateDropdownPosition();
|
|
216
|
+
this.addRepositionListeners();
|
|
217
|
+
}, 0);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
getDropdownStyle(): any {
|
|
221
|
+
if (!this.trigger) return {};
|
|
222
|
+
|
|
223
|
+
const position = this.calculatePosition();
|
|
224
|
+
return {
|
|
225
|
+
'position': 'fixed',
|
|
226
|
+
'left': position.left,
|
|
227
|
+
'top': position.top,
|
|
228
|
+
'z-index': '10000'
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private calculatePosition(): { top: string; left: string } {
|
|
233
|
+
const triggerElement = this.trigger.nativeElement;
|
|
234
|
+
const rect = triggerElement.getBoundingClientRect();
|
|
235
|
+
|
|
236
|
+
let dropdownWidth = this.rangeMode ? 830 : 320;
|
|
237
|
+
let dropdownHeight = this.rangeMode ? 520 : 400;
|
|
238
|
+
|
|
239
|
+
if (this.dropdown) {
|
|
240
|
+
const dropdownElement = this.dropdown.nativeElement;
|
|
241
|
+
const dropdownRect = dropdownElement.getBoundingClientRect();
|
|
242
|
+
|
|
243
|
+
if (dropdownRect.width > 0) {
|
|
244
|
+
dropdownWidth = dropdownRect.width;
|
|
245
|
+
} else {
|
|
246
|
+
dropdownWidth = window.innerWidth < 768 ? 280 : (this.rangeMode ? 830 : 320);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (dropdownRect.height > 0) {
|
|
250
|
+
dropdownHeight = dropdownRect.height;
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
dropdownWidth = window.innerWidth < 768 ? 280 : (this.rangeMode ? 830 : 320);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const spaceOnRight = window.innerWidth - rect.left;
|
|
257
|
+
|
|
258
|
+
let left = rect.left;
|
|
259
|
+
|
|
260
|
+
if (spaceOnRight < dropdownWidth) {
|
|
261
|
+
left = rect.right - dropdownWidth;
|
|
262
|
+
|
|
263
|
+
if (left < 0) {
|
|
264
|
+
left = Math.max(8, window.innerWidth - dropdownWidth - 8);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (window.innerWidth < 768) {
|
|
269
|
+
const centeredLeft = rect.left + (rect.width / 2) - (dropdownWidth / 2);
|
|
270
|
+
const minLeft = 8;
|
|
271
|
+
const maxLeft = window.innerWidth - dropdownWidth - 8;
|
|
272
|
+
|
|
273
|
+
left = Math.max(minLeft, Math.min(centeredLeft, maxLeft));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
277
|
+
const spaceAbove = rect.top;
|
|
278
|
+
|
|
279
|
+
let top = rect.bottom + 4;
|
|
280
|
+
|
|
281
|
+
if (spaceBelow < dropdownHeight && spaceAbove > spaceBelow) {
|
|
282
|
+
top = rect.top - dropdownHeight - 4;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
top: `${top}px`,
|
|
287
|
+
left: `${left}px`
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
closeDropdown(): void {
|
|
292
|
+
this.leftMonthDate = new Date(this.originalLeftMonthDate);
|
|
293
|
+
this.rightMonthDate = new Date(this.originalRightMonthDate);
|
|
294
|
+
|
|
295
|
+
if (this.rangeMode) {
|
|
296
|
+
this.tempStartDate = this.rangeValue.startDate;
|
|
297
|
+
this.tempEndDate = this.rangeValue.endDate;
|
|
298
|
+
} else {
|
|
299
|
+
this.tempSingleDate = this.singleValue;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
this.updateCalendarDays();
|
|
303
|
+
this.removeRepositionListeners();
|
|
304
|
+
this.isOpen = false;
|
|
305
|
+
this.hoverDate = null;
|
|
306
|
+
this.showLeftMonthPicker = false;
|
|
307
|
+
this.showRightMonthPicker = false;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private addRepositionListeners(): void {
|
|
311
|
+
const scrollHandler = () => this.updateDropdownPosition();
|
|
312
|
+
const resizeHandler = () => this.updateDropdownPosition();
|
|
313
|
+
|
|
314
|
+
window.addEventListener('scroll', scrollHandler, true);
|
|
315
|
+
this.scrollHandler = () => window.removeEventListener('scroll', scrollHandler, true);
|
|
316
|
+
|
|
317
|
+
window.addEventListener('resize', resizeHandler);
|
|
318
|
+
this.resizeHandler = () => window.removeEventListener('resize', resizeHandler);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private removeRepositionListeners(): void {
|
|
322
|
+
if (this.scrollHandler) {
|
|
323
|
+
this.scrollHandler();
|
|
324
|
+
this.scrollHandler = null;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (this.resizeHandler) {
|
|
328
|
+
this.resizeHandler();
|
|
329
|
+
this.resizeHandler = null;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
private updateDropdownPosition(): void {
|
|
334
|
+
if (!this.trigger) return;
|
|
335
|
+
this.dropdownPosition = this.calculatePosition();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
getDisplayValue(): string {
|
|
339
|
+
if (this.rangeMode) {
|
|
340
|
+
if (this.rangeValue.startDate && this.rangeValue.endDate) {
|
|
341
|
+
const start = this.formatDateShort(this.rangeValue.startDate);
|
|
342
|
+
const end = this.formatDateShort(this.rangeValue.endDate);
|
|
343
|
+
return `${start} - ${end}`;
|
|
344
|
+
}
|
|
345
|
+
} else {
|
|
346
|
+
if (this.singleValue) {
|
|
347
|
+
return this.formatDateShort(this.singleValue);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return '';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
formatDateShort(date: Date): string {
|
|
354
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
355
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
356
|
+
const year = date.getFullYear();
|
|
357
|
+
return `${day}/${month}/${year}`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
generateCalendarDays(monthDate: Date): CalendarDay[] {
|
|
361
|
+
const year = monthDate.getFullYear();
|
|
362
|
+
const month = monthDate.getMonth();
|
|
363
|
+
const firstDay = new Date(year, month, 1);
|
|
364
|
+
const lastDay = new Date(year, month + 1, 0);
|
|
365
|
+
|
|
366
|
+
let startDay = firstDay.getDay() - 1;
|
|
367
|
+
if (startDay === -1) startDay = 6;
|
|
368
|
+
|
|
369
|
+
const days: CalendarDay[] = [];
|
|
370
|
+
|
|
371
|
+
const prevMonthLastDay = new Date(year, month, 0);
|
|
372
|
+
for (let i = startDay - 1; i >= 0; i--) {
|
|
373
|
+
const date = new Date(year, month - 1, prevMonthLastDay.getDate() - i);
|
|
374
|
+
date.setHours(0, 0, 0, 0);
|
|
375
|
+
days.push(this.createCalendarDay(date, false));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
for (let day = 1; day <= lastDay.getDate(); day++) {
|
|
379
|
+
const date = new Date(year, month, day);
|
|
380
|
+
date.setHours(0, 0, 0, 0);
|
|
381
|
+
days.push(this.createCalendarDay(date, true));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const remainingDays = 42 - days.length;
|
|
385
|
+
for (let day = 1; day <= remainingDays; day++) {
|
|
386
|
+
const date = new Date(year, month + 1, day);
|
|
387
|
+
date.setHours(0, 0, 0, 0);
|
|
388
|
+
days.push(this.createCalendarDay(date, false));
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return days;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
private createCalendarDay(date: Date, isCurrentMonth: boolean): CalendarDay {
|
|
395
|
+
const today = new Date();
|
|
396
|
+
today.setHours(0, 0, 0, 0);
|
|
397
|
+
|
|
398
|
+
const dateOnly = new Date(date);
|
|
399
|
+
dateOnly.setHours(0, 0, 0, 0);
|
|
400
|
+
|
|
401
|
+
const isToday = dateOnly.getTime() === today.getTime();
|
|
402
|
+
|
|
403
|
+
let isSelected = false;
|
|
404
|
+
let isRangeStart = false;
|
|
405
|
+
let isRangeEnd = false;
|
|
406
|
+
let isInRange = false;
|
|
407
|
+
|
|
408
|
+
if (this.rangeMode) {
|
|
409
|
+
const startDate = this.tempStartDate ? new Date(this.tempStartDate) : null;
|
|
410
|
+
const endDate = this.tempEndDate ? new Date(this.tempEndDate) : null;
|
|
411
|
+
|
|
412
|
+
if (startDate) startDate.setHours(0, 0, 0, 0);
|
|
413
|
+
if (endDate) endDate.setHours(0, 0, 0, 0);
|
|
414
|
+
|
|
415
|
+
isRangeStart = isCurrentMonth && startDate ? dateOnly.getTime() === startDate.getTime() : false;
|
|
416
|
+
isRangeEnd = isCurrentMonth && endDate ? dateOnly.getTime() === endDate.getTime() : false;
|
|
417
|
+
isSelected = isRangeStart || isRangeEnd;
|
|
418
|
+
|
|
419
|
+
if (isCurrentMonth && startDate && endDate) {
|
|
420
|
+
isInRange = dateOnly > startDate && dateOnly < endDate;
|
|
421
|
+
} else if (isCurrentMonth && startDate && this.hoverDate && !endDate) {
|
|
422
|
+
const hoverDateOnly = new Date(this.hoverDate);
|
|
423
|
+
hoverDateOnly.setHours(0, 0, 0, 0);
|
|
424
|
+
if (hoverDateOnly > startDate) {
|
|
425
|
+
isInRange = dateOnly > startDate && dateOnly < hoverDateOnly;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
} else {
|
|
429
|
+
const selectedDate = this.tempSingleDate ? new Date(this.tempSingleDate) : null;
|
|
430
|
+
if (selectedDate) selectedDate.setHours(0, 0, 0, 0);
|
|
431
|
+
isSelected = isCurrentMonth && selectedDate ? dateOnly.getTime() === selectedDate.getTime() : false;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const isDisabled = !isCurrentMonth || this.isDateDisabled(date);
|
|
435
|
+
|
|
436
|
+
return {
|
|
437
|
+
date,
|
|
438
|
+
isCurrentMonth,
|
|
439
|
+
isToday,
|
|
440
|
+
isSelected,
|
|
441
|
+
isInRange,
|
|
442
|
+
isRangeStart,
|
|
443
|
+
isRangeEnd,
|
|
444
|
+
isDisabled
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private isDateDisabled(date: Date): boolean {
|
|
449
|
+
if (this.minDate && date < this.minDate) return true;
|
|
450
|
+
if (this.maxDate && date > this.maxDate) return true;
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
trackByDate(index: number, day: CalendarDay): string {
|
|
455
|
+
return day.date.getTime().toString();
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
isInRange(date: Date): boolean {
|
|
459
|
+
if (!this.rangeMode) return false;
|
|
460
|
+
|
|
461
|
+
const dateOnly = new Date(date);
|
|
462
|
+
dateOnly.setHours(0, 0, 0, 0);
|
|
463
|
+
|
|
464
|
+
const startDate = this.tempStartDate ? new Date(this.tempStartDate) : null;
|
|
465
|
+
const endDate = this.tempEndDate ? new Date(this.tempEndDate) : null;
|
|
466
|
+
|
|
467
|
+
if (startDate) startDate.setHours(0, 0, 0, 0);
|
|
468
|
+
if (endDate) endDate.setHours(0, 0, 0, 0);
|
|
469
|
+
|
|
470
|
+
if (startDate && endDate) {
|
|
471
|
+
return dateOnly > startDate && dateOnly < endDate;
|
|
472
|
+
} else if (startDate && this.hoverDate && !endDate) {
|
|
473
|
+
const hoverDateOnly = new Date(this.hoverDate);
|
|
474
|
+
hoverDateOnly.setHours(0, 0, 0, 0);
|
|
475
|
+
if (hoverDateOnly > startDate) {
|
|
476
|
+
return dateOnly > startDate && dateOnly < hoverDateOnly;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
onDayClick(day: CalendarDay): void {
|
|
483
|
+
if (day.isDisabled) return;
|
|
484
|
+
|
|
485
|
+
const clickedDate = new Date(day.date);
|
|
486
|
+
clickedDate.setHours(0, 0, 0, 0);
|
|
487
|
+
|
|
488
|
+
if (this.rangeMode) {
|
|
489
|
+
this.selectedFilter = '' as FilterOption;
|
|
490
|
+
|
|
491
|
+
if (!this.tempStartDate || (this.tempStartDate && this.tempEndDate)) {
|
|
492
|
+
this.tempStartDate = clickedDate;
|
|
493
|
+
this.tempEndDate = null;
|
|
494
|
+
this.hoverDate = null;
|
|
495
|
+
} else if (this.tempStartDate && !this.tempEndDate) {
|
|
496
|
+
const startDate = new Date(this.tempStartDate);
|
|
497
|
+
startDate.setHours(0, 0, 0, 0);
|
|
498
|
+
|
|
499
|
+
if (clickedDate.getTime() === startDate.getTime()) {
|
|
500
|
+
this.tempEndDate = clickedDate;
|
|
501
|
+
} else if (clickedDate > startDate) {
|
|
502
|
+
this.tempEndDate = clickedDate;
|
|
503
|
+
} else {
|
|
504
|
+
this.tempEndDate = startDate;
|
|
505
|
+
this.tempStartDate = clickedDate;
|
|
506
|
+
}
|
|
507
|
+
this.hoverDate = null;
|
|
508
|
+
}
|
|
509
|
+
} else {
|
|
510
|
+
this.tempSingleDate = clickedDate;
|
|
511
|
+
// Auto-apply for single date mode
|
|
512
|
+
this.apply();
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
this.updateCalendarDays();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
onDayHover(day: CalendarDay): void {
|
|
520
|
+
if (day.isDisabled || !this.rangeMode) return;
|
|
521
|
+
this.hoverDate = day.date;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
onDayLeave(): void {
|
|
525
|
+
this.hoverDate = null;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
previousMonth(): void {
|
|
529
|
+
if (!this.canNavigatePreviousMonth()) return;
|
|
530
|
+
this.leftMonthDate = new Date(this.leftMonthDate.getFullYear(), this.leftMonthDate.getMonth() - 1, 1);
|
|
531
|
+
if (this.rangeMode) {
|
|
532
|
+
this.rightMonthDate = new Date(this.rightMonthDate.getFullYear(), this.rightMonthDate.getMonth() - 1, 1);
|
|
533
|
+
}
|
|
534
|
+
this.updateCalendarDays();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
nextMonth(): void {
|
|
538
|
+
if (!this.canNavigateNextMonth()) return;
|
|
539
|
+
this.leftMonthDate = new Date(this.leftMonthDate.getFullYear(), this.leftMonthDate.getMonth() + 1, 1);
|
|
540
|
+
if (this.rangeMode) {
|
|
541
|
+
this.rightMonthDate = new Date(this.rightMonthDate.getFullYear(), this.rightMonthDate.getMonth() + 1, 1);
|
|
542
|
+
}
|
|
543
|
+
this.updateCalendarDays();
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
canNavigatePreviousMonth(): boolean {
|
|
547
|
+
if (!this.minDate) return true;
|
|
548
|
+
|
|
549
|
+
const newLeftMonth = new Date(this.leftMonthDate.getFullYear(), this.leftMonthDate.getMonth() - 1, 1);
|
|
550
|
+
const minDateMonth = new Date(this.minDate.getFullYear(), this.minDate.getMonth(), 1);
|
|
551
|
+
|
|
552
|
+
return newLeftMonth >= minDateMonth;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
canNavigateNextMonth(): boolean {
|
|
556
|
+
if (!this.maxDate) return true;
|
|
557
|
+
|
|
558
|
+
const checkMonth = this.rangeMode ? this.rightMonthDate : this.leftMonthDate;
|
|
559
|
+
const newMonth = new Date(checkMonth.getFullYear(), checkMonth.getMonth() + 1, 1);
|
|
560
|
+
const maxDateMonth = new Date(this.maxDate.getFullYear(), this.maxDate.getMonth(), 1);
|
|
561
|
+
|
|
562
|
+
return newMonth <= maxDateMonth;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
getMonthYear(date: Date): string {
|
|
566
|
+
return `${this.months[date.getMonth()]} ${date.getFullYear()}`;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
selectFilter(filter: FilterOption): void {
|
|
570
|
+
this.selectedFilter = filter;
|
|
571
|
+
this.applyFilter(filter);
|
|
572
|
+
this.updateCalendarDays();
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
private applyFilter(filter: FilterOption): void {
|
|
576
|
+
const today = new Date();
|
|
577
|
+
today.setHours(0, 0, 0, 0);
|
|
578
|
+
|
|
579
|
+
let startDate: Date | null = null;
|
|
580
|
+
let endDate: Date | null = null;
|
|
581
|
+
|
|
582
|
+
switch (filter) {
|
|
583
|
+
case 'hoy':
|
|
584
|
+
startDate = new Date(today);
|
|
585
|
+
endDate = new Date(today);
|
|
586
|
+
break;
|
|
587
|
+
case 'ayer':
|
|
588
|
+
startDate = new Date(today);
|
|
589
|
+
startDate.setDate(startDate.getDate() - 1);
|
|
590
|
+
endDate = new Date(startDate);
|
|
591
|
+
break;
|
|
592
|
+
case 'esta-semana':
|
|
593
|
+
startDate = this.getStartOfWeek(today);
|
|
594
|
+
endDate = new Date(today);
|
|
595
|
+
break;
|
|
596
|
+
case 'semana-pasada':
|
|
597
|
+
const lastWeekEnd = new Date(this.getStartOfWeek(today));
|
|
598
|
+
lastWeekEnd.setDate(lastWeekEnd.getDate() - 1);
|
|
599
|
+
startDate = this.getStartOfWeek(lastWeekEnd);
|
|
600
|
+
endDate = lastWeekEnd;
|
|
601
|
+
break;
|
|
602
|
+
case 'este-mes':
|
|
603
|
+
startDate = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
604
|
+
endDate = new Date(today);
|
|
605
|
+
break;
|
|
606
|
+
case 'mes-pasado':
|
|
607
|
+
startDate = new Date(today.getFullYear(), today.getMonth() - 1, 1);
|
|
608
|
+
endDate = new Date(today.getFullYear(), today.getMonth(), 0);
|
|
609
|
+
break;
|
|
610
|
+
case 'este-ano':
|
|
611
|
+
startDate = new Date(today.getFullYear(), 0, 1);
|
|
612
|
+
endDate = new Date(today);
|
|
613
|
+
break;
|
|
614
|
+
case 'ano-pasado':
|
|
615
|
+
startDate = new Date(today.getFullYear() - 1, 0, 1);
|
|
616
|
+
endDate = new Date(today.getFullYear() - 1, 11, 31);
|
|
617
|
+
break;
|
|
618
|
+
case 'mostrar-todo':
|
|
619
|
+
startDate = null;
|
|
620
|
+
endDate = null;
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
this.tempStartDate = startDate;
|
|
625
|
+
this.tempEndDate = endDate;
|
|
626
|
+
|
|
627
|
+
if (startDate) {
|
|
628
|
+
this.leftMonthDate = new Date(startDate.getFullYear(), startDate.getMonth(), 1);
|
|
629
|
+
this.rightMonthDate = new Date(startDate.getFullYear(), startDate.getMonth() + 1, 1);
|
|
630
|
+
} else {
|
|
631
|
+
const currentDate = new Date();
|
|
632
|
+
this.leftMonthDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
|
|
633
|
+
this.rightMonthDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
private getStartOfWeek(date: Date): Date {
|
|
638
|
+
const day = date.getDay();
|
|
639
|
+
const diff = day === 0 ? -6 : 1 - day;
|
|
640
|
+
const startOfWeek = new Date(date);
|
|
641
|
+
startOfWeek.setDate(date.getDate() + diff);
|
|
642
|
+
return startOfWeek;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
cancel(): void {
|
|
646
|
+
if (this.rangeMode) {
|
|
647
|
+
this.tempStartDate = this.rangeValue.startDate;
|
|
648
|
+
this.tempEndDate = this.rangeValue.endDate;
|
|
649
|
+
} else {
|
|
650
|
+
this.tempSingleDate = this.singleValue;
|
|
651
|
+
}
|
|
652
|
+
this.selectedFilter = '';
|
|
653
|
+
|
|
654
|
+
this.leftMonthDate = new Date(this.originalLeftMonthDate);
|
|
655
|
+
this.rightMonthDate = new Date(this.originalRightMonthDate);
|
|
656
|
+
|
|
657
|
+
this.updateCalendarDays();
|
|
658
|
+
this.closeDropdown();
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
apply(): void {
|
|
662
|
+
if (this.rangeMode) {
|
|
663
|
+
this.rangeValue = {
|
|
664
|
+
startDate: this.tempStartDate,
|
|
665
|
+
endDate: this.tempEndDate
|
|
666
|
+
};
|
|
667
|
+
this.onChange(this.rangeValue);
|
|
668
|
+
} else {
|
|
669
|
+
this.singleValue = this.tempSingleDate;
|
|
670
|
+
this.onChange(this.singleValue);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
this.originalLeftMonthDate = new Date(this.leftMonthDate);
|
|
674
|
+
this.originalRightMonthDate = new Date(this.rightMonthDate);
|
|
675
|
+
|
|
676
|
+
this.onTouched();
|
|
677
|
+
|
|
678
|
+
this.removeRepositionListeners();
|
|
679
|
+
this.isOpen = false;
|
|
680
|
+
this.hoverDate = null;
|
|
681
|
+
this.showLeftMonthPicker = false;
|
|
682
|
+
this.showRightMonthPicker = false;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
getStartDateDisplay(): string {
|
|
686
|
+
if (this.tempStartDate) {
|
|
687
|
+
return this.formatDateForInput(this.tempStartDate);
|
|
688
|
+
}
|
|
689
|
+
return 'Fecha inicio';
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
getEndDateDisplay(): string {
|
|
693
|
+
if (this.tempEndDate) {
|
|
694
|
+
return this.formatDateForInput(this.tempEndDate);
|
|
695
|
+
}
|
|
696
|
+
return 'Fecha fin';
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private formatDateForInput(date: Date): string {
|
|
700
|
+
const day = date.getDate();
|
|
701
|
+
const month = date.toLocaleString('es-ES', { month: 'short' });
|
|
702
|
+
const year = date.getFullYear();
|
|
703
|
+
return `${day} ${month} ${year}`;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
toggleLeftMonthPicker(event: Event): void {
|
|
707
|
+
event.stopPropagation();
|
|
708
|
+
this.showLeftMonthPicker = !this.showLeftMonthPicker;
|
|
709
|
+
this.showRightMonthPicker = false;
|
|
710
|
+
if (this.showLeftMonthPicker) {
|
|
711
|
+
this.leftYearPickerPage = 0;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
toggleRightMonthPicker(event: Event): void {
|
|
716
|
+
event.stopPropagation();
|
|
717
|
+
this.showRightMonthPicker = !this.showRightMonthPicker;
|
|
718
|
+
this.showLeftMonthPicker = false;
|
|
719
|
+
if (this.showRightMonthPicker) {
|
|
720
|
+
this.rightYearPickerPage = 0;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
getLeftYears(): number[] {
|
|
725
|
+
const currentYear = this.leftMonthDate.getFullYear();
|
|
726
|
+
const baseYear = currentYear + (this.leftYearPickerPage * this.yearsPerPage);
|
|
727
|
+
const years: number[] = [];
|
|
728
|
+
|
|
729
|
+
for (let i = 0; i < this.yearsPerPage; i++) {
|
|
730
|
+
const year = baseYear - 5 + i;
|
|
731
|
+
years.push(year);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return years;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
getRightYears(): number[] {
|
|
738
|
+
const currentYear = this.rightMonthDate.getFullYear();
|
|
739
|
+
const baseYear = currentYear + (this.rightYearPickerPage * this.yearsPerPage);
|
|
740
|
+
const years: number[] = [];
|
|
741
|
+
|
|
742
|
+
for (let i = 0; i < this.yearsPerPage; i++) {
|
|
743
|
+
const year = baseYear - 5 + i;
|
|
744
|
+
years.push(year);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
return years;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
previousLeftYearPage(event: Event): void {
|
|
751
|
+
event.stopPropagation();
|
|
752
|
+
this.leftYearPickerPage--;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
nextLeftYearPage(event: Event): void {
|
|
756
|
+
event.stopPropagation();
|
|
757
|
+
this.leftYearPickerPage++;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
previousRightYearPage(event: Event): void {
|
|
761
|
+
event.stopPropagation();
|
|
762
|
+
this.rightYearPickerPage--;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
nextRightYearPage(event: Event): void {
|
|
766
|
+
event.stopPropagation();
|
|
767
|
+
this.rightYearPickerPage++;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
isMonthDisabled(monthIndex: number, calendarDate: Date): boolean {
|
|
771
|
+
const testDate = new Date(calendarDate.getFullYear(), monthIndex, 1);
|
|
772
|
+
|
|
773
|
+
if (this.minDate) {
|
|
774
|
+
const minDateMonth = new Date(this.minDate.getFullYear(), this.minDate.getMonth(), 1);
|
|
775
|
+
if (testDate < minDateMonth) return true;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (this.maxDate) {
|
|
779
|
+
const maxDateMonth = new Date(this.maxDate.getFullYear(), this.maxDate.getMonth(), 1);
|
|
780
|
+
if (testDate > maxDateMonth) return true;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
isYearDisabled(year: number): boolean {
|
|
787
|
+
if (this.minDate && year < this.minDate.getFullYear()) return true;
|
|
788
|
+
if (this.maxDate && year > this.maxDate.getFullYear()) return true;
|
|
789
|
+
return false;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
getLeftYearRangeLabel(): string {
|
|
793
|
+
const years = this.getLeftYears();
|
|
794
|
+
return `${years[0]} - ${years[years.length - 1]}`;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
getRightYearRangeLabel(): string {
|
|
798
|
+
const years = this.getRightYears();
|
|
799
|
+
return `${years[0]} - ${years[years.length - 1]}`;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
canNavigateLeftYearsPrevious(): boolean {
|
|
803
|
+
if (!this.minDate && !this.maxDate) return true;
|
|
804
|
+
|
|
805
|
+
const currentYear = this.leftMonthDate.getFullYear();
|
|
806
|
+
const baseYear = currentYear + ((this.leftYearPickerPage - 1) * this.yearsPerPage);
|
|
807
|
+
|
|
808
|
+
const previousPageYears: number[] = [];
|
|
809
|
+
for (let i = 0; i < this.yearsPerPage; i++) {
|
|
810
|
+
previousPageYears.push(baseYear - 5 + i);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
return previousPageYears.some(year => !this.isYearDisabled(year));
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
canNavigateLeftYearsNext(): boolean {
|
|
817
|
+
if (!this.minDate && !this.maxDate) return true;
|
|
818
|
+
|
|
819
|
+
const currentYear = this.leftMonthDate.getFullYear();
|
|
820
|
+
const baseYear = currentYear + ((this.leftYearPickerPage + 1) * this.yearsPerPage);
|
|
821
|
+
|
|
822
|
+
const nextPageYears: number[] = [];
|
|
823
|
+
for (let i = 0; i < this.yearsPerPage; i++) {
|
|
824
|
+
nextPageYears.push(baseYear - 5 + i);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
return nextPageYears.some(year => !this.isYearDisabled(year));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
canNavigateRightYearsPrevious(): boolean {
|
|
831
|
+
if (!this.minDate && !this.maxDate) return true;
|
|
832
|
+
|
|
833
|
+
const currentYear = this.rightMonthDate.getFullYear();
|
|
834
|
+
const baseYear = currentYear + ((this.rightYearPickerPage - 1) * this.yearsPerPage);
|
|
835
|
+
|
|
836
|
+
const previousPageYears: number[] = [];
|
|
837
|
+
for (let i = 0; i < this.yearsPerPage; i++) {
|
|
838
|
+
previousPageYears.push(baseYear - 5 + i);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
return previousPageYears.some(year => !this.isYearDisabled(year));
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
canNavigateRightYearsNext(): boolean {
|
|
845
|
+
if (!this.minDate && !this.maxDate) return true;
|
|
846
|
+
|
|
847
|
+
const currentYear = this.rightMonthDate.getFullYear();
|
|
848
|
+
const baseYear = currentYear + ((this.rightYearPickerPage + 1) * this.yearsPerPage);
|
|
849
|
+
|
|
850
|
+
const nextPageYears: number[] = [];
|
|
851
|
+
for (let i = 0; i < this.yearsPerPage; i++) {
|
|
852
|
+
nextPageYears.push(baseYear - 5 + i);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
return nextPageYears.some(year => !this.isYearDisabled(year));
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
selectLeftMonth(monthIndex: number, event?: Event): void {
|
|
859
|
+
if (event) {
|
|
860
|
+
event.stopPropagation();
|
|
861
|
+
}
|
|
862
|
+
this.leftMonthDate = new Date(this.leftMonthDate.getFullYear(), monthIndex, 1);
|
|
863
|
+
if (this.rangeMode) {
|
|
864
|
+
this.rightMonthDate = new Date(this.leftMonthDate.getFullYear(), monthIndex + 1, 1);
|
|
865
|
+
}
|
|
866
|
+
this.updateCalendarDays();
|
|
867
|
+
this.showLeftMonthPicker = false;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
selectRightMonth(monthIndex: number, event?: Event): void {
|
|
871
|
+
if (event) {
|
|
872
|
+
event.stopPropagation();
|
|
873
|
+
}
|
|
874
|
+
this.rightMonthDate = new Date(this.rightMonthDate.getFullYear(), monthIndex, 1);
|
|
875
|
+
this.leftMonthDate = new Date(this.rightMonthDate.getFullYear(), monthIndex - 1, 1);
|
|
876
|
+
this.updateCalendarDays();
|
|
877
|
+
this.showRightMonthPicker = false;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
selectLeftYear(year: number, event?: Event): void {
|
|
881
|
+
if (event) {
|
|
882
|
+
event.stopPropagation();
|
|
883
|
+
}
|
|
884
|
+
this.leftMonthDate = new Date(year, this.leftMonthDate.getMonth(), 1);
|
|
885
|
+
if (this.rangeMode) {
|
|
886
|
+
this.rightMonthDate = new Date(year, this.leftMonthDate.getMonth() + 1, 1);
|
|
887
|
+
}
|
|
888
|
+
this.updateCalendarDays();
|
|
889
|
+
this.showLeftMonthPicker = false;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
selectRightYear(year: number, event?: Event): void {
|
|
893
|
+
if (event) {
|
|
894
|
+
event.stopPropagation();
|
|
895
|
+
}
|
|
896
|
+
this.rightMonthDate = new Date(year, this.rightMonthDate.getMonth(), 1);
|
|
897
|
+
this.leftMonthDate = new Date(year, this.rightMonthDate.getMonth() - 1, 1);
|
|
898
|
+
this.updateCalendarDays();
|
|
899
|
+
this.showRightMonthPicker = false;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
writeValue(value: DatePickerValue): void {
|
|
903
|
+
if (this.rangeMode) {
|
|
904
|
+
const rangeVal = value as DateRange;
|
|
905
|
+
this.rangeValue = rangeVal || { startDate: null, endDate: null };
|
|
906
|
+
this.tempStartDate = this.rangeValue.startDate;
|
|
907
|
+
this.tempEndDate = this.rangeValue.endDate;
|
|
908
|
+
} else {
|
|
909
|
+
this.singleValue = value as Date | null;
|
|
910
|
+
this.tempSingleDate = this.singleValue;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
registerOnChange(fn: any): void {
|
|
915
|
+
this.onChange = fn;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
registerOnTouched(fn: any): void {
|
|
919
|
+
this.onTouched = fn;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
setDisabledState(isDisabled: boolean): void {
|
|
923
|
+
this.disabled = isDisabled;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
public resetDatePicker(): void {
|
|
927
|
+
if (this.rangeMode) {
|
|
928
|
+
this.rangeValue = { startDate: null, endDate: null };
|
|
929
|
+
this.tempStartDate = null;
|
|
930
|
+
this.tempEndDate = null;
|
|
931
|
+
this.onChange(this.rangeValue);
|
|
932
|
+
} else {
|
|
933
|
+
this.singleValue = null;
|
|
934
|
+
this.tempSingleDate = null;
|
|
935
|
+
this.onChange(this.singleValue);
|
|
936
|
+
}
|
|
937
|
+
this.selectedFilter = '';
|
|
938
|
+
|
|
939
|
+
this.initializeDates();
|
|
940
|
+
this.updateCalendarDays();
|
|
941
|
+
}
|
|
942
|
+
}
|