From f71fa13e19acb8dcaa94d5c58d2408f4b6b6e2a8 Mon Sep 17 00:00:00 2001
From: Simone Angeloni Bei <simone.angeloni.bei@gmail.com>
Date: Fri, 9 May 2025 12:56:00 +0200
Subject: [PATCH] first implementation, still a bug on first openeing

---
 src/index.ts                                  |  87 ++---
 .../nbp-fid-calendar-genric.component.html    | 120 +++++++
 .../nbp-fid-calendar-genric.component.scss    | 124 +++++++
 .../nbp-fid-calendar-genric.component.ts      | 321 ++++++++++++++++++
 .../showcase/showcase1.component.html         |  10 +-
 5 files changed, 618 insertions(+), 44 deletions(-)
 create mode 100644 src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.html
 create mode 100644 src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.scss
 create mode 100644 src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.ts

diff --git a/src/index.ts b/src/index.ts
index 2be30d2..a451233 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,48 +1,47 @@
 import { ModuleWithProviders, NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
 import { XdceArchModule } from '@isp/xdce-arch-core';
 import { NbpModule } from '@isp/xdce-widget';
-
-import { NbpBreadCrumbsComponent } from './widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component';
-export { NbpBreadCrumbsComponent } from './widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component';
-import { NbpFidBarChartComponent } from './widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component';
-export { NbpFidBarChartComponent } from './widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component';
-import { NbpFidButtonBarComponent } from './widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component';
-export { NbpFidButtonBarComponent } from './widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component';
-import { NbpFidDonutChartComponent } from './widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component';
-export { NbpFidDonutChartComponent } from './widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component';
-import { NbpFidPyramidChartComponent } from './widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component';
-export { NbpFidPyramidChartComponent } from './widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component';
-import { NbpFidSidePopupComponent } from './widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component';
-export { NbpFidSidePopupComponent } from './widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component';
-import { NbpFidTableComponent } from './widgetfideuram/components/nbp-fid-table/nbp-fid-table.component';
-export { NbpFidTableComponent } from './widgetfideuram/components/nbp-fid-table/nbp-fid-table.component';
-import { NbpFidToggleTabComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y';
-export { NbpFidToggleTabComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y';
-import { NbpFidToggleTabComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y';
-export { NbpFidToggleTabComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y';
-import { NbpFidToggleTabComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component';
-export { NbpFidToggleTabComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component';
-import { NbpFidToggleTabsetComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y';
-export { NbpFidToggleTabsetComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y';
-import { NbpFidToggleTabsetComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y';
-export { NbpFidToggleTabsetComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y';
-import { NbpFidToggleTabsetComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component';
-export { NbpFidToggleTabsetComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component';
-import { NbpFidComboComponent } from './widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component';
-export { NbpFidComboComponent } from './widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component';
-
-import { ShowcaseComponent } from './widgetfideuram/components/showcase/showcase.component';
-export { ShowcaseComponent } from './widgetfideuram/components/showcase/showcase.component';
-import { Showcase1Component } from './widgetfideuram/components/showcase/showcase1.component';
-export { Showcase1Component } from './widgetfideuram/components/showcase/showcase1.component';
-import { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component';
-export { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component';
-
 import { AgGridModule, AngularFrameworkComponentWrapper, AngularFrameworkOverrides } from 'ag-grid-angular';
-import { FormsModule } from '@angular/forms';
+import { NbpBreadCrumbsComponent } from './widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component';
+import { NbpFidBarChartComponent } from './widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component';
+import { NbpFidButtonBarComponent } from './widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component';
+import { NbpFidCalendarGenericComponent } from './widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component';
+import { NbpFidComboComponent } from './widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component';
+import { NbpFidDonutChartComponent } from './widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component';
+import { NbpFidPyramidChartComponent } from './widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component';
+import { NbpFidSidePopupComponent } from './widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component';
+import { NbpFidTableComponent } from './widgetfideuram/components/nbp-fid-table/nbp-fid-table.component';
+import { NbpFidToggleTabComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component';
+import { NbpFidToggleTabComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y';
+import { NbpFidToggleTabComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y';
+import { NbpFidToggleTabsetComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component';
+import { NbpFidToggleTabsetComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y';
+import { NbpFidToggleTabsetComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y';
+import { ShowcaseComponent } from './widgetfideuram/components/showcase/showcase.component';
+import { Showcase1Component } from './widgetfideuram/components/showcase/showcase1.component';
+import { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component';
+import { CommonModule } from '@angular/common';
 export { AgGridModule } from 'ag-grid-angular';
-
-export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearSpinnerMessage } from './widgetfideuram/Utils';
+export { NbpBreadCrumbsComponent } from './widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component';
+export { NbpFidBarChartComponent } from './widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component';
+export { NbpFidButtonBarComponent } from './widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component';
+export { NbpFidCalendarGenericComponent } from './widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component';
+export { NbpFidComboComponent } from './widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component';
+export { NbpFidDonutChartComponent } from './widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component';
+export { NbpFidPyramidChartComponent } from './widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component';
+export { NbpFidSidePopupComponent } from './widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component';
+export { NbpFidTableComponent } from './widgetfideuram/components/nbp-fid-table/nbp-fid-table.component';
+export { NbpFidToggleTabComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component';
+export { NbpFidToggleTabComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y';
+export { NbpFidToggleTabComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y';
+export { NbpFidToggleTabsetComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component';
+export { NbpFidToggleTabsetComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y';
+export { NbpFidToggleTabsetComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y';
+export { ShowcaseComponent } from './widgetfideuram/components/showcase/showcase.component';
+export { Showcase1Component } from './widgetfideuram/components/showcase/showcase1.component';
+export { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component';
+export { clearSpinnerMessage, DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage } from './widgetfideuram/Utils';
 
 
 @NgModule({
@@ -51,6 +50,7 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
     NbpModule,
     AgGridModule,
     FormsModule,
+    CommonModule
   ],
   declarations: [
     NbpBreadCrumbsComponent,
@@ -70,6 +70,7 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
     ShowcaseComponent,
     Showcase1Component,
     WidgetFideuramShowcaseComponent,
+    NbpFidCalendarGenericComponent
   ],
   exports: [
     NbpBreadCrumbsComponent,
@@ -89,7 +90,8 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
     ShowcaseComponent,
     Showcase1Component,
     WidgetFideuramShowcaseComponent,
-    AgGridModule
+    AgGridModule,
+    NbpFidCalendarGenericComponent
   ],
   providers: [
     AngularFrameworkOverrides,
@@ -101,7 +103,8 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
     NbpFidToggleTabsetComponentA11Y,
     NbpFidToggleTabsetComponentNOA11Y,
     NbpFidToggleTabComponent,
-    NbpFidToggleTabsetComponent
+    NbpFidToggleTabsetComponent,
+    NbpFidCalendarGenericComponent
   ]
 })
 export class XdceWidgetFideuramModule {
diff --git a/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.html b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.html
new file mode 100644
index 0000000..7fa8a76
--- /dev/null
+++ b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.html
@@ -0,0 +1,120 @@
+<div class="datepicker-wrapper">
+  <input
+    #dateInput
+    [id]="id"
+    [name]="name"
+    [value]="selectedDateStr"
+    (input)="setDate($event.target.value)"
+    class="datepicker-input"
+    type="text"
+    readonly
+    placeholder="Seleziona una data"
+  />
+  <svg
+    id="calendarIcon"
+    class="datepicker-icon"
+    viewBox="0 0 24 24"
+    (click)="showCalendar()"
+  >
+    <path
+      d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V9h14v11zm0-13H5V6h14v1z"
+    />
+  </svg>
+
+  <div #calendarPopup class="calendar calendar-popup" id="calendarPopup">
+    <div class="calendar-header">
+      <button id="prevBtn" class="fa fa-chevron-left" (click)="prev()"></button>
+      <div id="monthYear" (click)="changeView()">{{ monthYearText }}</div>
+      <button id="nextBtn" class="fa fa-chevron-right" (click)="next()"></button>
+    </div>
+
+    <ng-container [ngSwitch]="view">
+      <ng-container *ngSwitchCase="'days'">
+        <div class="calendar-grid calendar-grid-7" id="calendar">
+          <!-- DAYS of Week -->
+          <ng-container *ngFor="let d of daysOfWeek; index as i">
+            <div class="day">{{ d }}</div>
+          </ng-container>
+
+          <!-- PREV Month days -->
+          <ng-container *ngFor="let d of daysInPrevMonthToBeRendered">
+            <div
+              [ngClass]="{
+                'other-month calendar-cell': true,
+                disabled: isDateDisabled(d)
+              }"
+              (click)="selectDate(d)"
+            >
+              {{ pad(d.getDate()) }}
+            </div>
+          </ng-container>
+
+          <!-- CURR Month days -->
+          <ng-container *ngFor="let d of daysInCurrentMonthToBeRendered">
+            <div
+              [ngClass]="{
+                'calendar-cell': true,
+                disabled: isDateDisabled(d),
+                selected: sameDate(selectedDate, d)
+              }"
+              (click)="selectDate(d)"
+            >
+              {{ pad(d.getDate()) }}
+            </div>
+          </ng-container>
+
+          <!-- NEXT Month days -->
+          <ng-container *ngFor="let d of daysInNextMonthToBeRendered">
+            <div
+              [ngClass]="{
+                'other-month calendar-cell': true,
+                disabled: isDateDisabled(d),
+                selected: sameDate(selectedDate, d),
+                today: isToday(d)
+              }"
+              (click)="selectDate(d)"
+            >
+              {{ pad(d.getDate()) }}
+            </div>
+          </ng-container>
+        </div>
+      </ng-container>
+      <ng-container *ngSwitchCase="'months'">
+        <div class="calendar-grid calendar-grid-3" id="calendar">
+          <ng-container *ngFor="let m of monthsToBeRendered; index as i">
+            <div
+              [ngClass]="{
+                'calendar-cell': true,
+                today: isCurrentMonth(i),
+                selected: sameMonth(selectDate?.getMonth(), i)
+              }"
+              (click)="selectMonth(i)"
+            >
+             {{m}}
+            </div>
+          </ng-container>
+        </div>
+      </ng-container>
+      <ng-container *ngSwitchCase="'years'">
+        <div class="calendar-grid calendar-grid-5" id="calendar">
+          <ng-container *ngFor="let y of yearsToBeRendered">
+            <div
+              [ngClass]="{
+                'calendar-cell': true,
+                today: isCurrentYear(y),
+                selected: sameYear(selectDate?.getFullYear(), y)
+              }"
+              (click)="selectYear(y)"
+            >
+              {{y}}
+            </div>
+          </ng-container>
+        </div>
+      </ng-container>
+    </ng-container>
+    <div class="calendar-actions">
+      <button id="todayBtn">Oggi</button><button id="clearBtn">Cancella</button
+      ><button id="confirmBtn">Conferma</button>
+    </div>
+  </div>
+</div>
diff --git a/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.scss b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.scss
new file mode 100644
index 0000000..96dc31e
--- /dev/null
+++ b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.scss
@@ -0,0 +1,124 @@
+.calendar {
+    border: 1px solid #ccc;
+    border-radius: 10px;
+    padding: 15px;
+    color: #333333;
+}
+
+.calendar-popup {
+    position: absolute;
+    z-index: 100;
+    display: none;
+
+    min-width: 160px;
+    padding: 5px 0;
+    margin: 2px 0 0;
+    list-style: none;
+    font-size: 12px;
+    text-align: left;
+    background-color: #ffffff;
+    border: 1px solid #e1e1e1;
+    border-radius: 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: flex;
+    align-items: center;
+    margin-bottom: 10px;
+}
+
+.calendar-cell {
+    padding: 5px 10px;
+    font-size: 12px;
+    border: 1px solid #dde6e9;
+    border-radius: 3px;
+    cursor: pointer;
+}
+
+#monthYear {
+    font-weight: bold;
+    flex-grow: 1;
+    text-align: center;
+}
+
+.calendar-grid {
+    display: grid;
+    grid-template-columns: repeat(4, 1fr);
+    gap: 5px;
+    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-weight: bold;
+    background-color: #eee;
+    cursor: default;
+}
+
+.calendar-grid .selected {
+    background-color: #009fe3;
+    color: white;
+}
+
+.calendar-grid .other-month {
+    color: #ccc;
+}
+
+.calendar-grid .disabled {
+    color: #bbb;
+    background: #f5f5f5;
+    cursor: not-allowed;
+}
+
+.calendar-actions {
+    margin-top: 15px;
+    display: flex;
+    justify-content: space-around;
+}
+
+.calendar-actions button {
+    padding: 6px 12px;
+    background-color: orange;
+    color: white;
+    border: none;
+    border-radius: 4px;
+    cursor: pointer;
+}
+
+.datepicker-wrapper {
+    display: inline-block;
+    position: relative;
+    margin-bottom: 8px;
+}
+
+.datepicker-input {
+    width: 200px;
+    padding: 8px 36px 8px 8px;
+    border-radius: 5px;
+    border: 1px solid #ccc;
+    background: #fafafa;
+    cursor: pointer;
+    font-size: 16px;
+}
+
+.datepicker-icon {
+    position: absolute;
+    right: 8px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 20px;
+    height: 20px;
+    fill: #888;
+    cursor: pointer;
+    pointer-events: auto;
+}
\ No newline at end of file
diff --git a/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.ts b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.ts
new file mode 100644
index 0000000..0acb414
--- /dev/null
+++ b/src/widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-genric.component.ts
@@ -0,0 +1,321 @@
+import {
+  AfterViewInit,
+  Component,
+  ElementRef,
+  forwardRef,
+  Input,
+  Renderer2,
+  ViewChild,
+} from "@angular/core";
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
+import { NbpCalendarPattern, NbpCalendarPosition } from "@isp/xdce-widget";
+
+@Component({
+  selector: 'nbp-fid-calendar-generic',
+  templateUrl: './nbp-fid-calendar-genric.component.html',
+  styleUrls: ["./nbp-fid-calendar-genric.component.scss"],
+  providers: [
+    {
+        provide: NG_VALUE_ACCESSOR,
+        useExisting: forwardRef(() => NbpFidCalendarGenericComponent),
+        multi: true
+      }
+  ]
+})
+export class NbpFidCalendarGenericComponent implements AfterViewInit, ControlValueAccessor  {
+  @Input("nbpLabelPattern") pattern: NbpCalendarPattern =
+    NbpCalendarPattern.GGMMAAAA;
+  @Input("nbpPlacement") placement: string = "bottom-right";
+  @Input("id") id: string;
+  @Input("name") name: string;
+  daysOfWeek = ["lun", "mar", "mer", "gio", "ven", "sab", "dom"];
+  months = [
+    "Gennaio",
+    "Febbraio",
+    "Marzo",
+    "Aprile",
+    "Maggio",
+    "Giugno",
+    "Luglio",
+    "Agosto",
+    "Settembre",
+    "Ottobre",
+    "Novembre",
+    "Dicembre",
+  ];
+  view: "days" | "months" | "years" = "days";
+
+  visibility: "shown" | "hidden" = "hidden";
+
+  disabledWeekdays = [0, 6]; // es: weekend
+  // CONFIGURAZIONE: range di date da disabilitare (array di oggetti {start, end})
+  disabledDateRanges = [
+    { start: new Date(2025, 4, 10), end: new Date(2025, 4, 15) }, // 10-15 maggio 2025
+    // aggiungi altri range se necessario
+  ];
+
+  ngAfterViewInit(): void {
+    this.renderer.setStyle(
+      this.calendarPopupRef.nativeElement,
+      "display",
+      "none"
+    );
+  }
+  constructor(private renderer: Renderer2) {}
+
+  
+
+  currentDate = new Date();
+  selectedDate: Date | null = null;
+  selectedDateStr : string | null = null;
+  monthYearText: string = "";
+  firstDayOfMonth: Date | null = null;
+  startDay: number = 0;
+  daysInCurrentMonth: number = 0;
+  daysInCurrentMonthToBeRendered: Date[] = [];
+  daysInPrevMonth: number = 0;
+  daysInPrevMonthToBeRendered: Date[] = [];
+  daysInNextMonthToBeRendered: Date[] = [];
+  monthsToBeRendered: string[] = [];
+  yearsToBeRendered: string[] = [];
+
+  @ViewChild("dateInput") dateInputRef: ElementRef;
+  @ViewChild("calendarPopup") calendarPopupRef: ElementRef;
+
+  public showCalendar() {
+    this.positionCalendarPopup();
+    this.renderCalendar();
+  }
+
+  public hideCalendar() {
+    this.renderer.setStyle(
+      this.calendarPopupRef.nativeElement,
+      "display",
+      "none"
+    );
+  }
+
+  private renderCalendar() {
+    if (this.view == "days") this.renderDays();
+    else if (this.view == "months") this.renderMonths();
+    else this.renderYears();
+  }
+
+  private positionCalendarPopup(): void {
+    const input = this.dateInputRef.nativeElement;
+    const popup = this.calendarPopupRef.nativeElement;
+
+    // Append to body if not already
+    if (popup.parentNode !== document.body) {
+      this.renderer.appendChild(document.body, popup);
+    }
+
+    const rect = input.getBoundingClientRect();
+    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
+    const scrollLeft =
+      window.pageXOffset || document.documentElement.scrollLeft;
+
+    this.renderer.setStyle(popup, "display", "block");
+    this.renderer.setStyle(popup, "position", "absolute");
+    this.renderer.setStyle(popup, "z-index", "9999");
+    this.renderer.setStyle(popup, "top", `${rect.bottom + scrollTop}px`);
+    this.renderer.setStyle(popup, "left", `${rect.left + scrollLeft}px`);
+    // this.renderer.setStyle(popup, 'min-width', `${rect.width}px`);
+  }
+  public pad(n: number): string {
+    return n < 10 ? "0" + n : n + "";
+  }
+  public isDateDisabled(date: Date): boolean {
+    // 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;
+  }
+  public sameDate(d1: Date, d2: Date) {
+    return (
+      d1.getFullYear() === d2.getFullYear() &&
+      d1.getMonth() === d2.getMonth() &&
+      d1.getDate() === d2.getDate()
+    );
+  }
+
+  public sameMonth(m1: number, m2: number) {
+    return m1 == m2;
+  }
+
+  public sameYear(y1: number, y2: number) {
+    return y1 == y2;
+  }
+
+  private formatDate(date: Date, format: string) {
+    if (!date) return "";
+    return format
+      .replace("gg", this.pad(date.getDate()))
+      .replace("mm", this.pad(date.getMonth() + 1))
+      .replace("aaaa", date.getFullYear().toString())
+      .replace("aa", String(date.getFullYear()).slice(-2));
+  }
+
+  public selectDate(date: Date) {
+    if (this.isDateDisabled(date)) {
+      return;
+    }
+    this.selectedDate = date;
+    this.setDate(this.formatDate(date, this.pattern));
+    this.renderCalendar();
+  }
+
+  public selectMonth(idx) {
+    this.currentDate.setMonth(idx);
+    this.view = "days";
+    this.renderCalendar();
+  }
+
+  public selectYear(year: string) {
+    this.currentDate.setFullYear(Number(year));
+    this.view = "months";
+    this.renderCalendar();
+  }
+
+  public isToday(date: Date) {
+    return this.sameDate(date, new Date());
+  }
+
+  public isCurrentMonth(idx) {
+    return idx == this.currentDate.getMonth();
+  }
+
+  public isCurrentYear(year: string) {
+    return year === this.currentDate.getFullYear().toString();
+  }
+
+  private renderDays() {
+    this.daysInPrevMonthToBeRendered = [];
+    this.daysInCurrentMonthToBeRendered = [];
+    this.daysInNextMonthToBeRendered = [];
+
+    this.monthYearText = `${
+      this.months[this.currentDate.getMonth()]
+    } ${this.currentDate.getFullYear()}`;
+
+    const year = this.currentDate.getFullYear();
+    const month = this.currentDate.getMonth();
+
+    this.firstDayOfMonth = new Date(year, month, 1);
+    this.startDay = (this.firstDayOfMonth.getDay() + 6) % 7;
+
+    this.daysInCurrentMonth = new Date(year, month + 1, 0).getDate();
+    this.daysInPrevMonth = new Date(year, month, 0).getDate();
+
+    for (let i = this.startDay; i > 0; i--) {
+      const day = this.daysInPrevMonth - i + 1;
+      const prevMonthDate = new Date(year, month - 1, day);
+      this.daysInPrevMonthToBeRendered.push(prevMonthDate);
+    }
+
+    for (let i = 1; i <= this.daysInCurrentMonth; i++) {
+      const currMonthDate = new Date(year, month, i);
+      this.daysInCurrentMonthToBeRendered.push(currMonthDate);
+    }
+
+    const totalCells = 42; // 7 giorni x 6 settimane
+    const filledCells = this.startDay + this.daysInCurrentMonth;
+    const nextMonthDays = totalCells - filledCells;
+    for (let i = 1; i <= nextMonthDays; i++) {
+      const nextMonthDate = new Date(year, month + 1, i);
+      this.daysInNextMonthToBeRendered.push(nextMonthDate);
+    }
+  }
+
+  private renderMonths() {
+    this.monthsToBeRendered = [];
+    const monthTexts = this.months.map((m) => m.substring(0, 3));
+    this.monthYearText = this.currentDate.getFullYear().toString();
+    monthTexts.forEach((m, idx) => {
+      this.monthsToBeRendered.push(m);
+    });
+  }
+
+  private renderYears() {
+    this.yearsToBeRendered = [];
+    // 20 anni, 5x4
+    const base = Math.floor(this.currentDate.getFullYear() / 20) * 20;
+    this.monthYearText = `${base} - ${base + 19}`;
+    for (let y = base; y < base + 20; y++) {
+      this.yearsToBeRendered.push(y.toString());
+    }
+  }
+
+  public changeView() {
+    if (this.view === "days") this.view = "months";
+    else if (this.view === "months") this.view = "years";
+    this.renderCalendar();
+  }
+
+  public prev() {
+    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() - 10);
+    this.renderCalendar();
+  }
+
+  public next() {
+    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() + 10);
+    this.renderCalendar();
+  }
+
+  public goToday() {
+    this.currentDate = new Date();
+    this.selectedDate = new Date();
+    this.setDate(this.formatDate(
+      this.selectedDate,
+      this.pattern
+    ));
+    this.view = "days";
+    this.renderCalendar();
+  }
+
+  public clearSelection() {
+    this.selectedDate = null;
+    this.setDate("")
+    this.renderCalendar();
+  }
+
+  public confirmDate() {
+    this.hideCalendar();
+  }
+
+  private onChange = (_: any) => {};
+  private onTouched = () => {};
+
+  writeValue(value: string | null): void {
+    this.selectedDateStr = value;
+  }
+
+  registerOnChange(fn: any): void {
+    this.onChange = fn;
+  }
+
+  registerOnTouched(fn: any): void {
+    this.onTouched = fn;
+  }
+
+  setDate(value: string): void {
+    this.selectedDateStr = value;
+    this.onChange(value);
+    this.onTouched();
+  }
+    
+    setDisabledState?(isDisabled: boolean): void {
+        throw new Error("Method not implemented.");
+    }
+}
diff --git a/src/widgetfideuram/components/showcase/showcase1.component.html b/src/widgetfideuram/components/showcase/showcase1.component.html
index 2e809eb..97d41c8 100644
--- a/src/widgetfideuram/components/showcase/showcase1.component.html
+++ b/src/widgetfideuram/components/showcase/showcase1.component.html
@@ -50,8 +50,14 @@
         </nbp-input-container>
     </div>
 
-    <p class="new-part">Calendar generic (nbp-input-container + nbp-calendar-generic)</p>
+    
+
+     <p class="new-part">Calendar generic (nbp-input-container + nbp-calendar-generic)</p>
     <div>
+        <nbp-fid-calendar-generic [id]="'calendarDefault'" [name]="'calendarDefault'" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_LEFT"></nbp-fid-calendar-generic>
+    </div>
+    <!--
+     <div>
         <nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
             <nbp-calendar-generic [id]="'calendarDefault'" [name]="'calendarDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
                 [nbpPlacement]="_nbpCalendarPosition.BOTTOM_LEFT" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA"
@@ -76,7 +82,7 @@
             [startDateEnabled]="startDate" [endDateEnabled]="endDate">
           </nbp-calendar-generic>
         </nbp-input-container>
-    </div>
+    </div> -->
 
     <p class="new-part">Combo (nbp-input-container + nbp-combo)</p>
     <div>