diff --git a/src/index.ts b/src/index.ts
index 2be30d2..08f543a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -40,6 +40,8 @@ export { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/wid
import { AgGridModule, AngularFrameworkComponentWrapper, AngularFrameworkOverrides } from 'ag-grid-angular';
import { FormsModule } from '@angular/forms';
+import { NbpFidCalendarGenericComponent } from './widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component';
+export { NbpFidCalendarGenericComponent } from './widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component';
export { AgGridModule } from 'ag-grid-angular';
export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearSpinnerMessage } from './widgetfideuram/Utils';
@@ -70,6 +72,7 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
ShowcaseComponent,
Showcase1Component,
WidgetFideuramShowcaseComponent,
+ NbpFidCalendarGenericComponent
],
exports: [
NbpBreadCrumbsComponent,
@@ -89,7 +92,8 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
ShowcaseComponent,
Showcase1Component,
WidgetFideuramShowcaseComponent,
- AgGridModule
+ AgGridModule,
+ NbpFidCalendarGenericComponent
],
providers: [
AngularFrameworkOverrides,
diff --git a/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.html b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.html
new file mode 100644
index 0000000..22e855c
--- /dev/null
+++ b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.html
@@ -0,0 +1,91 @@
+
+
+
+
+
+
diff --git a/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.scss b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.scss
new file mode 100644
index 0000000..66653f8
--- /dev/null
+++ b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.scss
@@ -0,0 +1,201 @@
+// Stili del calendario
+.calendar {
+ font-size: 12px;
+ padding: 15px;
+ border: 1px solid #e6e6e6;
+ color: #333333;
+ background-color: #ffffff;
+}
+
+.calendar-popup {
+ position: absolute;
+ z-index: 100;
+ display: none;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ background-clip: padding-box;
+}
+
+.calendar-header {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ align-items: center;
+}
+
+.view-days .calendar-header {
+ grid-template-columns: 1fr 5fr 1fr;
+}
+
+.view-years .calendar-header {
+ grid-template-columns: 1fr 3fr 1fr;
+}
+
+.view-months .calendar-cell,
+.view-years .calendar-cell {
+ padding: 6px 20px;
+}
+
+.calendar-cell {
+ padding: 5px 10px;
+ line-height: 1.5;
+ font-size: 12px;
+ background-color: #ffffff;
+ border: 1px solid #e6e6e6;
+ border-radius: 3px;
+ cursor: pointer;
+ -webkit-transition: all 0.1s;
+ -o-transition: all 0.1s;
+ transition: all 0.1s;
+}
+
+.calendar-cell:not(.disabled):not(.selected):hover {
+ background-color: #e6e6e6;
+}
+
+#monthYear {
+ font-weight: bold;
+ flex-grow: 1;
+ text-align: center;
+}
+
+.calendar-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ text-align: center;
+}
+
+.calendar-grid-7 {
+ grid-template-columns: repeat(7, 1fr);
+}
+
+.calendar-grid-5 {
+ grid-template-columns: repeat(5, 1fr);
+}
+
+.calendar-grid .day {
+ font-size: 11px;
+ line-height: 1.5;
+ font-weight: bold;
+}
+
+.calendar-grid .selected {
+ background-color: #1797be;
+ color: white;
+}
+
+.calendar-grid .selected:hover {
+ background-color: #137d9f;
+ border-color: #0e5d76;
+}
+
+.calendar-grid .other-month {
+ color: #909fa7;
+}
+
+.calendar-grid .today {
+ color: #23b7e5;
+}
+
+.calendar-grid:not(:has(.selected)) .today {
+ background-color: #e6e6e6;
+}
+
+.calendar-grid .disabled {
+ color: #989898;
+ background-color: #edf1f2;
+ border-color: #dde6e9;
+ cursor: not-allowed;
+}
+
+.calendar-actions {
+ padding: 10px 9px 2px;
+ display: flex;
+}
+
+.calendar-actions button {
+ font-size: 12px;
+ padding: 5px 10px;
+ line-height: 1.5;
+ background-color: #eb690b;
+ color: #fff;
+ border: 1px solid #e6e6e6;
+ border-radius: 3px;
+ cursor: pointer;
+}
+
+.calendar-actions button#todayBtn {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+
+.calendar-actions button#clearBtn {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-left-width: 0;
+ background-color: #fff;
+ color: #eb690b;
+}
+
+.calendar-actions button#confirmBtn {
+ margin-left: auto;
+}
+
+// Stili del datepicker
+.datepicker-wrapper {
+ position: relative;
+ display: inline-flex;
+}
+
+.datepicker-input {
+ padding: 5px;
+ height: 22px;
+ box-sizing: border-box;
+ border: 1px solid #ccc;
+ border-right-width: 0;
+ background: #fff;
+ font-size: 12px;
+ width: 100%;
+}
+
+.datepicker-input::placeholder {
+ color: #909fa7;
+}
+
+.datepicker-input:focus {
+ border-color: #66afe9;
+ outline: 0;
+}
+
+.datepicker-input.input-error {
+ border-color: #f05050;
+ background-color: #fff0f0;
+}
+
+.datepicker-icon {
+ display: inline-flex;
+ align-items: center;
+ font-size: 13.5px;
+ padding: 0 10px;
+ box-sizing: border-box;
+ height: 22px;
+ background: #fff;
+ border: 1px solid #ccc;
+ border-bottom-right-radius: 5px;
+ border-top-right-radius: 5px;
+ cursor: pointer;
+}
+
+.datepicker-icon:active,
+.datepicker-icon:hover,
+.datepicker-icon:focus {
+ background-color: #e6e6e6;
+ border-color: #cbcbcb;
+}
+
+.datepicker-icon:hover:active {
+ background-color: #d4d4d4;
+ border-color: #aaaaaa;
+}
diff --git a/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.ts b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.ts
new file mode 100644
index 0000000..0ab53fa
--- /dev/null
+++ b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component.ts
@@ -0,0 +1,503 @@
+import { Component, OnInit, Input, Output, EventEmitter, ElementRef, ViewChild, HostListener, Renderer2 } from '@angular/core';
+
+@Component({
+ selector: 'nbp-fid-calendar-generic',
+ templateUrl: './nbp-fid-calendar-generic.component.html',
+ styleUrls: ['./nbp-fid-calendar-generic.component.scss']
+})
+export class NbpFidCalendarGenericComponent implements OnInit {
+ @Input() dateFormat: string = 'dd/MM/yyyy';
+ @Input() disabledWeekdays: number[] = []; // 0=domenica, 6=sabato
+ @Input() disabledDateRanges: { start: Date, end: Date }[] = [];
+ @Input() minDate: Date;
+ @Input() maxDate: Date;
+ @Output() dateChange = new EventEmitter();
+
+ @ViewChild('dateInput') dateInput: ElementRef;
+
+ // Cache per evitare ricalcoli continui e problemi di rendering
+ private _previousMonthDaysCache: { day: number, disabled: boolean }[] = [];
+ private _currentMonthDaysCache: { day: number, isToday: boolean, isSelected: boolean, disabled: boolean }[] = [];
+ private _nextMonthDaysCache: { day: number, disabled: boolean }[] = [];
+ private _visibleMonthsCache: { monthIndex: number, name: string, isCurrentMonth: boolean, isSelected: boolean, disabled: boolean }[] = [];
+ private _visibleYearsCache: { year: number, isCurrentYear: boolean, isSelected: boolean, disabled: boolean }[] = [];
+ @ViewChild('calendarPopup') calendarPopup: ElementRef;
+
+ currentDate: Date = new Date();
+ selectedDate: Date = null;
+ view: 'days' | 'months' | 'years' = 'days';
+ months: string[] = ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'];
+ daysOfWeek: string[] = ['lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom'];
+ formattedSelectedDate: string = '';
+ calendarVisible: boolean = false;
+
+ constructor(private renderer: Renderer2, private elementRef: ElementRef) { }
+
+ ngOnInit(): void {
+ // Inizializza la data selezionata se presente
+ if (this.selectedDate) {
+ this.formattedSelectedDate = this.formatDate(this.selectedDate, this.dateFormat);
+ }
+
+ // Inizializza le cache
+ this.updateAllCaches();
+ }
+
+ // --- UTILITY ---
+ private pad(n: number): string {
+ return n < 10 ? '0' + n : n.toString();
+ }
+
+ formatDate(date: Date, format: string): string {
+ if (!date) return '';
+ return format
+ .replace('dd', this.pad(date.getDate()))
+ .replace('MM', this.pad(date.getMonth() + 1))
+ .replace('yyyy', date.getFullYear().toString())
+ .replace('yy', String(date.getFullYear()).slice(-2));
+ }
+
+ sameDate(d1: Date, d2: Date): boolean {
+ return d1.getFullYear() === d2.getFullYear() &&
+ d1.getMonth() === d2.getMonth() &&
+ d1.getDate() === d2.getDate();
+ }
+
+ // --- GESTIONE POPUP ---
+ positionCalendarPopup(): void {
+ if (!this.calendarPopup || !this.dateInput) return;
+
+ const input = this.dateInput.nativeElement;
+ const popup = this.calendarPopup.nativeElement;
+
+ // Sposta il popup in fondo al body (portal)
+ if (popup.parentNode !== document.body) {
+ document.body.appendChild(popup);
+ }
+
+ popup.style.display = 'block';
+ popup.style.position = 'absolute';
+ popup.style.zIndex = '9999';
+
+ const rect = input.getBoundingClientRect();
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
+
+ popup.style.top = (rect.bottom + scrollTop) + 'px';
+ popup.style.left = (rect.left + scrollLeft) + 'px';
+ }
+
+ toggleCalendar(): void {
+ this.calendarVisible = !this.calendarVisible;
+ if (this.calendarVisible) {
+ this.showCalendar();
+ this.updateAllCaches();
+ } else {
+ this.hideCalendar();
+ }
+ }
+
+ showCalendar(): void {
+ this.calendarVisible = true;
+ setTimeout(() => {
+ this.positionCalendarPopup();
+ });
+ }
+
+ hideCalendar(): void {
+ this.calendarVisible = false;
+ if (this.calendarPopup) {
+ this.calendarPopup.nativeElement.style.display = 'none';
+ }
+
+ if (this.selectedDate) {
+ this.currentDate = new Date(this.selectedDate);
+ } else {
+ this.currentDate = new Date();
+ }
+ }
+
+ @HostListener('document:mousedown', ['$event'])
+ onClickOutside(event: MouseEvent): void {
+ if (this.calendarVisible &&
+ !this.elementRef.nativeElement.contains(event.target) &&
+ this.calendarPopup &&
+ !this.calendarPopup.nativeElement.contains(event.target)) {
+ this.hideCalendar();
+ }
+ }
+
+ // --- LOGICA DATE ---
+ isDateDisabled(date: Date): boolean {
+ // Disabilita date precedenti alla minDate
+ if (this.minDate && date < this.minDate) return true;
+
+ // Disabilita date precedenti alla maxDate
+ if (this.maxDate && date > this.maxDate) return true;
+
+ // Disabilita per giorno della settimana
+ if (this.disabledWeekdays.indexOf(date.getDay()) !== -1) return true;
+
+ // Disabilita per range
+ for (const range of this.disabledDateRanges) {
+ if (date >= range.start && date <= range.end) return true;
+ }
+
+ return false;
+ }
+
+ // --- NAVIGATION ---
+ prev(): void {
+ if (this.view === 'days') {
+ this.currentDate.setMonth(this.currentDate.getMonth() - 1);
+ } else if (this.view === 'months') {
+ this.currentDate.setFullYear(this.currentDate.getFullYear() - 1);
+ } else {
+ this.currentDate.setFullYear(this.currentDate.getFullYear() - 20);
+ }
+ this.currentDate = new Date(this.currentDate); // Forza refresh
+ this.updateAllCaches();
+ }
+
+ next(): void {
+ if (this.view === 'days') {
+ this.currentDate.setMonth(this.currentDate.getMonth() + 1);
+ } else if (this.view === 'months') {
+ this.currentDate.setFullYear(this.currentDate.getFullYear() + 1);
+ } else {
+ this.currentDate.setFullYear(this.currentDate.getFullYear() + 20);
+ }
+ this.currentDate = new Date(this.currentDate); // Forza refresh
+ this.updateAllCaches();
+ }
+
+ goToday(): void {
+ this.currentDate = new Date();
+ this.selectedDate = new Date();
+ this.formattedSelectedDate = this.formatDate(this.selectedDate, this.dateFormat);
+ this.view = 'days';
+ this.dateChange.emit(this.selectedDate);
+ this.updateAllCaches();
+ }
+
+ clearSelection(): void {
+ this.selectedDate = null;
+ this.formattedSelectedDate = '';
+ this.dateChange.emit(null);
+ }
+
+ confirmDate(): void {
+ // Metodo usato per confermare esplicitamente la data corrente
+ this.dateChange.emit(this.selectedDate);
+ this.hideCalendar();
+ }
+
+ changeView(): void {
+ if (this.view === 'days') {
+ this.view = 'months';
+ } else if (this.view === 'months') {
+ this.view = 'years';
+ }
+ this.updateAllCaches();
+ }
+
+ // --- SELEZIONE DATE ---
+ selectDate(date: Date): void {
+ if (this.isDateDisabled(date)) return;
+
+ this.selectedDate = date;
+ this.formattedSelectedDate = this.formatDate(this.selectedDate, this.dateFormat);
+ // Non emettiamo qui l'evento dateChange per evitare doppie emissioni
+ this.updateAllCaches();
+ }
+
+ selectMonth(monthIndex: number): void {
+ if (this.isMonthDisabled(monthIndex)) return;
+
+ this.currentDate.setMonth(monthIndex);
+ this.currentDate = new Date(this.currentDate); // Forza refresh
+ this.view = 'days';
+ this.updateAllCaches();
+ }
+
+ selectYear(year: number): void {
+ if (this.isYearDisabled(year)) return;
+
+ this.currentDate.setFullYear(year);
+ this.currentDate = new Date(this.currentDate); // Forza refresh
+ this.view = 'months';
+ this.updateAllCaches();
+ }
+
+ selectDayFromPrevMonth(day: number): void {
+ const year = this.currentDate.getFullYear();
+ const month = this.currentDate.getMonth();
+ const prevMonthDate = new Date(year, month - 1, day);
+
+ if (this.isDateDisabled(prevMonthDate)) return;
+
+ this.currentDate.setMonth(month - 1);
+ this.currentDate = new Date(this.currentDate); // Forza refresh
+ this.selectedDate = prevMonthDate;
+ this.formattedSelectedDate = this.formatDate(this.selectedDate, this.dateFormat);
+ this.dateChange.emit(this.selectedDate);
+ this.updateAllCaches();
+ this.hideCalendar(); // Chiudi il calendario dopo la selezione
+ }
+
+ selectDayFromNextMonth(day: number): void {
+ const year = this.currentDate.getFullYear();
+ const month = this.currentDate.getMonth();
+ const nextMonthDate = new Date(year, month + 1, day);
+
+ if (this.isDateDisabled(nextMonthDate)) return;
+
+ this.currentDate.setMonth(month + 1);
+ this.currentDate = new Date(this.currentDate); // Forza refresh
+ this.selectedDate = nextMonthDate;
+ this.formattedSelectedDate = this.formatDate(this.selectedDate, this.dateFormat);
+ this.dateChange.emit(this.selectedDate);
+ this.updateAllCaches();
+ this.hideCalendar(); // Chiudi il calendario dopo la selezione
+ }
+
+ // --- UTILITY PER MESI E ANNI ---
+ isMonthDisabled(monthIndex: number): boolean {
+ // Se non ci sono restrizioni, il mese è abilitato
+ if (!this.minDate && !this.maxDate && (!this.disabledDateRanges || this.disabledDateRanges.length === 0)) {
+ return false;
+ }
+
+ const year = this.currentDate.getFullYear();
+ const firstDayOfMonth = new Date(year, monthIndex, 1, 0, 0, 0, 0);
+ const lastDayOfMonth = new Date(year, monthIndex + 1, 0, 23, 59, 59, 999);
+
+ // Disabilita mese se completamente fuori dai limiti
+ if (this.minDate && lastDayOfMonth < this.minDate) return true;
+ if (this.maxDate && firstDayOfMonth > this.maxDate) return true;
+
+ return false;
+ }
+
+ isYearDisabled(year: number): boolean {
+ // Se non ci sono restrizioni, l'anno è abilitato
+ if (!this.minDate && !this.maxDate) {
+ return false;
+ }
+
+ const firstDayOfYear = new Date(year, 0, 1, 0, 0, 0, 0);
+ const lastDayOfYear = new Date(year, 11, 31, 23, 59, 59, 999);
+
+ // Disabilita anno se completamente fuori dai limiti
+ if (this.minDate && lastDayOfYear < this.minDate) return true;
+ if (this.maxDate && firstDayOfYear > this.maxDate) return true;
+
+ return false;
+ }
+
+ // --- INPUT HANDLING ---
+ onDateInputChange(event: Event): void {
+ const value = (event.target as HTMLInputElement).value;
+ const datePattern = /^(\d{2})\/(\d{2})\/(\d{4})$/;
+
+ if (datePattern.test(value)) {
+ const [, dd, mm, yyyy] = value.match(datePattern);
+ const date = new Date(parseInt(yyyy), parseInt(mm) - 1, parseInt(dd));
+
+ // Controlla che sia una data valida
+ if (date &&
+ date.getDate() === parseInt(dd) &&
+ (date.getMonth() + 1) === parseInt(mm) &&
+ date.getFullYear() === parseInt(yyyy)) {
+
+ if (!this.isDateDisabled(date)) {
+ this.selectedDate = date;
+ this.currentDate = new Date(date);
+ this.formattedSelectedDate = this.formatDate(this.selectedDate, this.dateFormat);
+ this.dateChange.emit(this.selectedDate);
+ this.updateAllCaches();
+ return;
+ }
+ }
+ }
+ }
+
+ // --- CALENDAR DATA ---
+ getDaysInMonth(year: number, month: number): number {
+ return new Date(year, month + 1, 0).getDate();
+ }
+
+ // Metodo per aggiornare tutte le cache quando cambiano i dati
+ private updateAllCaches(): void {
+ this.updatePreviousMonthDaysCache();
+ this.updateCurrentMonthDaysCache();
+ this.updateNextMonthDaysCache();
+ this.updateVisibleMonthsCache();
+ this.updateVisibleYearsCache();
+ }
+
+ // Metodi per aggiornare le singole cache
+ private updatePreviousMonthDaysCache(): void {
+ const year = this.currentDate.getFullYear();
+ const month = this.currentDate.getMonth();
+ const startDay = this.getFirstDayOfMonth(year, month);
+ const daysInPrevMonth = this.getDaysInMonth(year, month - 1);
+
+ const days = [];
+ for (let i = startDay; i > 0; i--) {
+ const day = daysInPrevMonth - i + 1;
+ const prevMonthDate = new Date(year, month - 1, day);
+ days.push({
+ day,
+ disabled: this.isDateDisabled(prevMonthDate)
+ });
+ }
+
+ this._previousMonthDaysCache = days;
+ }
+
+ private updateCurrentMonthDaysCache(): void {
+ const year = this.currentDate.getFullYear();
+ const month = this.currentDate.getMonth();
+ const daysInMonth = this.getDaysInMonth(year, month);
+ const today = new Date();
+
+ const days = [];
+ for (let i = 1; i <= daysInMonth; i++) {
+ const date = new Date(year, month, i);
+ days.push({
+ day: i,
+ isToday: this.sameDate(today, date),
+ isSelected: this.selectedDate ? this.sameDate(this.selectedDate, date) : false,
+ disabled: this.isDateDisabled(date)
+ });
+ }
+
+ this._currentMonthDaysCache = days;
+ }
+
+ private updateNextMonthDaysCache(): void {
+ const year = this.currentDate.getFullYear();
+ const month = this.currentDate.getMonth();
+ const startDay = this.getFirstDayOfMonth(year, month);
+ const daysInMonth = this.getDaysInMonth(year, month);
+
+ const totalCells = 42; // 7 giorni x 6 settimane
+ const nextMonthDays = totalCells - (startDay + daysInMonth);
+
+ const days = [];
+ for (let i = 1; i <= nextMonthDays; i++) {
+ const nextMonthDate = new Date(year, month + 1, i);
+ days.push({
+ day: i,
+ disabled: this.isDateDisabled(nextMonthDate)
+ });
+ }
+
+ this._nextMonthDaysCache = days;
+ }
+
+ private updateVisibleMonthsCache(): void {
+ const currentYear = this.currentDate.getFullYear();
+ const today = new Date();
+
+ const months = this.months.map((name, idx) => ({
+ monthIndex: idx,
+ name,
+ isCurrentMonth: currentYear === today.getFullYear() && idx === today.getMonth(),
+ isSelected: this.selectedDate ?
+ currentYear === this.selectedDate.getFullYear() &&
+ idx === this.selectedDate.getMonth() : false,
+ disabled: this.isMonthDisabled(idx)
+ }));
+
+ this._visibleMonthsCache = months;
+ }
+
+ private updateVisibleYearsCache(): void {
+ const base = Math.floor(this.currentDate.getFullYear() / 20) * 20;
+ const currentYear = new Date().getFullYear();
+
+ const years = [];
+ for (let y = base; y < base + 20; y++) {
+ years.push({
+ year: y,
+ isCurrentYear: y === currentYear,
+ isSelected: this.selectedDate ? y === this.selectedDate.getFullYear() : false,
+ disabled: this.isYearDisabled(y)
+ });
+ }
+
+ this._visibleYearsCache = years;
+ }
+
+ getFirstDayOfMonth(year: number, month: number): number {
+ return (new Date(year, month, 1).getDay() + 6) % 7; // Lunedì=0, Domenica=6
+ }
+
+ getPreviousMonthDays(): { day: number, disabled: boolean }[] {
+ return this._previousMonthDaysCache;
+ }
+
+ getCurrentMonthDays(): { day: number, isToday: boolean, isSelected: boolean, disabled: boolean }[] {
+ return this._currentMonthDaysCache;
+ }
+
+ getNextMonthDays(): { day: number, disabled: boolean }[] {
+ return this._nextMonthDaysCache;
+ }
+
+ getVisibleYears(): { year: number, isCurrentYear: boolean, isSelected: boolean, disabled: boolean }[] {
+ return this._visibleYearsCache;
+ }
+
+ getVisibleMonths(): { monthIndex: number, name: string, isCurrentMonth: boolean, isSelected: boolean, disabled: boolean }[] {
+ return this._visibleMonthsCache;
+ }
+
+ get yearRange(): string {
+ if (this.view === 'years') {
+ const base = Math.floor(this.currentDate.getFullYear() / 20) * 20;
+ return `${base} - ${base + 19}`;
+ }
+ return this.currentDate.getFullYear().toString();
+ }
+
+ get monthYearHeader(): string {
+ if (this.view === 'days') {
+ return `${this.months[this.currentDate.getMonth()]} ${this.currentDate.getFullYear()}`;
+ }
+ return this.yearRange;
+ }
+
+ // --- AZIONI SUI GIORNI, MESI E ANNI ---
+ onPrevMonthDayClick(day: { day: number, disabled: boolean }): void {
+ if (day.disabled) return;
+ this.selectDayFromPrevMonth(day.day);
+ // Non serve chiamare hideCalendar() qui perché lo fa già selectDayFromPrevMonth
+ }
+
+ onCurrentMonthDayClick(day: { day: number, isToday: boolean, isSelected: boolean, disabled: boolean }): void {
+ if (day.disabled) return;
+ const date = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth(), day.day);
+ this.selectDate(date);
+ this.dateChange.emit(this.selectedDate);
+ this.hideCalendar();
+ }
+
+ onNextMonthDayClick(day: { day: number, disabled: boolean }): void {
+ if (day.disabled) return;
+ this.selectDayFromNextMonth(day.day);
+ // Non serve chiamare hideCalendar() qui perché lo fa già selectDayFromNextMonth
+ }
+
+ onMonthClick(month: { monthIndex: number, name: string, isCurrentMonth: boolean, isSelected: boolean, disabled: boolean }): void {
+ if (month.disabled) return;
+ this.selectMonth(month.monthIndex);
+ }
+
+ onYearClick(yearObj: { year: number, isCurrentYear: boolean, isSelected: boolean, disabled: boolean }): void {
+ if (yearObj.disabled) return;
+ this.selectYear(yearObj.year);
+ }
+}
diff --git a/src/widgetfideuram/components/showcase/showcase1.component.html b/src/widgetfideuram/components/showcase/showcase1.component.html
index 2e809eb..cf82f81 100644
--- a/src/widgetfideuram/components/showcase/showcase1.component.html
+++ b/src/widgetfideuram/components/showcase/showcase1.component.html
@@ -62,22 +62,33 @@
-
+ [nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT"
+ [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel"
+ [startDateEnabled]="startDate" [endDateEnabled]="endDate">
+
-
+ [nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT" [disabled]="true"
+ [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel"
+ [startDateEnabled]="startDate" [endDateEnabled]="endDate">
+
+ Fideuram Calendar generic (nbp-input-container + bp-fid-calendar-generic)
+
+
+
+
+
+
+
+
Combo (nbp-input-container + nbp-combo)
@@ -87,7 +98,8 @@
+ [nbpDataSource]="comboDatasource" [(ngModel)]="comboSelectedValue" [nbpShowEmptyValue]="true"
+ [disabled]="true">
@@ -149,12 +161,11 @@
[nbpDataSource]="tableDs" [nbpAutoBind]="true" [nbpSelectionType]="tableSelectionType"
[nbpLayoutAuto]="true">
-
+
+ [nbpSortable]="true" [nbpVisible]='true'>
@@ -171,12 +182,12 @@
[nbpDataSource]="campiStandardData" ariaLabel="multi selection table" [nbpAutoBind]="true"
[nbpSelectionType]="multi">
-
+
-
+
diff --git a/src/widgetfideuram/components/showcase/showcase1.component.ts b/src/widgetfideuram/components/showcase/showcase1.component.ts
index dcfaa69..0ba13a0 100644
--- a/src/widgetfideuram/components/showcase/showcase1.component.ts
+++ b/src/widgetfideuram/components/showcase/showcase1.component.ts
@@ -43,6 +43,19 @@ export class Showcase1Component extends NbpBaseComponent {
startDate: NgbDateStruct = { year: 2023, month: 3, day: 15 };
endDate: NgbDateStruct = { year: 2023, month: 8, day: 15 };
+
+ // FIDEURAM CALENDAR GENERIC
+ fidCalendarModel: Date = null;
+
+ // Date di limite per l'esempio min/max
+ fidMinDate: Date = new Date(2025, 4, 1); // 1 maggio 2025
+ fidMaxDate: Date = new Date(2025, 5, 30); // 30 giugno 2025
+
+ // Range di date disabilitate per l'esempio
+ fidDisabledDateRanges: { start: Date, end: Date }[] = [
+ { start: new Date(2025, 4, 10), end: new Date(2025, 4, 15) }, // 10-15 maggio 2025
+ { start: new Date(2025, 4, 25), end: new Date(2025, 4, 28) } // 25-28 maggio 2025
+ ];
//
//
@@ -192,6 +205,12 @@ export class Showcase1Component extends NbpBaseComponent {
array = array.map(convertPageToRowModel);
this.table2Data.setData(array, pageNumber, sortField, pageSize);
}
+
+ // Metodo per gestire il cambio di data nel calendario Fideuram
+ onDateChange(date: Date): void {
+ console.log('Data selezionata:', date);
+ // Puoi aggiungere qui la logica per gestire il cambio di data
+ }
}
export class RowExpanderTreeExpandedTest implements RowDataExpander {