diff --git a/projects/demo/src/app/demos/demo-basic/demo-basic.component.html b/projects/demo/src/app/demos/demo-basic/demo-basic.component.html index 86769c8..39d680b 100644 --- a/projects/demo/src/app/demos/demo-basic/demo-basic.component.html +++ b/projects/demo/src/app/demos/demo-basic/demo-basic.component.html @@ -61,19 +61,19 @@

IonCalendar Options

- + readonly - + Custom MonthPicker - + Custom WeekDays @@ -125,7 +125,7 @@

IonCalendar Options

0 1 2 - 3 + 3 4 5 6 @@ -176,7 +176,7 @@

IonCalendar Options

- showAdjacentMonthDay + showMonthSubtitle diff --git a/projects/ion-calendar/src/lib/components/calendar-month/calendar-month.component.scss b/projects/ion-calendar/src/lib/components/calendar-month/calendar-month.component.scss index 634dafa..92f3e47 100644 --- a/projects/ion-calendar/src/lib/components/calendar-month/calendar-month.component.scss +++ b/projects/ion-calendar/src/lib/components/calendar-month/calendar-month.component.scss @@ -123,7 +123,6 @@ ion-note { left: 0; right: 0; display: block; - // background-color: white; background-color: $color; opacity: 0.25; } diff --git a/projects/ion-calendar/src/lib/components/calendar/calendar.component.html b/projects/ion-calendar/src/lib/components/calendar/calendar.component.html index 23d6795..07d955f 100644 --- a/projects/ion-calendar/src/lib/components/calendar/calendar.component.html +++ b/projects/ion-calendar/src/lib/components/calendar/calendar.component.html @@ -26,11 +26,11 @@ + = new EventEmitter(); - @Output() onMonthChange: EventEmitter = new EventEmitter(); - @Output() onWeekChange: EventEmitter = new EventEmitter(); - @Output() onSelect: EventEmitter = new EventEmitter(); - @Output() onSelectStart: EventEmitter = new EventEmitter(); - @Output() onSelectEnd: EventEmitter = new EventEmitter(); + @Output() onChange: EventEmitter = new EventEmitter(); + @Output() onMonthChange: EventEmitter = new EventEmitter(); + @Output() onWeekChange: EventEmitter = new EventEmitter(); + @Output() onSelect: EventEmitter = new EventEmitter(); + @Output() onSelectStart: EventEmitter = new EventEmitter(); + @Output() onSelectEnd: EventEmitter = new EventEmitter(); // private readonly MONTH_DATE_FORMAT = 'MMMM yyyy'; constructor(public calSvc: IonCalendarService) { @@ -192,14 +192,11 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { } private nextWeek() { - let oldWeek = this.calSvc.multiFormat(this.monthOpt.original.time); - // let nextTime = moment(this.monthOpt.original.time).add(this.def.weeks, 'weeks').valueOf(); let nextTime = DateTime.fromMillis(this.monthOpt.original.time).plus({ weeks: this.def.weeks }).valueOf(); let newWeek = this.calSvc.multiFormat(nextTime); + const oldWeek = this.calSvc.multiFormat(this.monthOpt.original.time); if (oldWeek.month != newWeek.month && !this.def.continuous) { - // let _start = new Date(nextTime); - // nextTime = new Date(_start.getFullYear(), _start.getMonth(), 1).getTime(); nextTime = DateTime.fromMillis(nextTime).set({ day: 1 }).valueOf(); newWeek = this.calSvc.multiFormat(nextTime); } @@ -215,18 +212,12 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { canNext(): boolean { if (!this.def.to || this.view !== 'days') return true; - // if (!this.def.to) return true; - - // return this.monthOpt.original.time < moment(this.def.to).valueOf(); - // const toMillis = (this.def.to instanceof Date) ? this.def.to.getTime() : this.def.to; - // return this.monthOpt.original.time < DateTime.fromMillis(toMillis).toMillis(); const toDate = DateTimeHelper.parse(this.def.to); return this.monthOpt.original.lastDay < toDate.toMillis(); } private backMonth(): void { - // const backTime = moment(this.monthOpt.original.time).subtract(1, 'months').valueOf(); const backTime = DateTime.fromMillis(this.monthOpt.original.time).minus({ months: 1 }).valueOf(); this.onMonthChange.emit({ oldMonth: this.calSvc.multiFormat(this.monthOpt.original.time), @@ -236,14 +227,13 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { } private backWeek(): void { - // let backTime = moment(this.monthOpt.original.time).subtract(this.def.weeks, 'weeks').valueOf(); let backTime = DateTime.fromMillis(this.monthOpt.original.time).minus({ weeks: this.def.weeks }).valueOf(); - let oldWeek = this.calSvc.multiFormat(this.monthOpt.original.time); let newWeek = this.calSvc.multiFormat(backTime); + const oldWeek = this.calSvc.multiFormat(this.monthOpt.original.time); if (oldWeek.month != newWeek.month && !this.def.continuous) { - let _start = new Date(this.monthOpt.original.time); - let dayToSubstrac = _start.getDay(); + const start = new Date(this.monthOpt.original.time); + let dayToSubstrac = start.getDay(); if (this.options.weekStart === 1) { dayToSubstrac--; if (dayToSubstrac < 0) { @@ -251,36 +241,35 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { } } - let firstDayMonth = new Date(_start.getFullYear(), _start.getMonth(), 1).getTime(); - // let momentBackTime = moment(firstDayMonth); + const firstDayMonth = new Date(start.getFullYear(), start.getMonth(), 1).getTime(); let momentBackTime = DateTime.fromMillis(firstDayMonth); - if (_start.getDate() - dayToSubstrac <= 1) { - // momentBackTime = momentBackTime.subtract(1, 'd'); + if (start.getDate() - dayToSubstrac <= 1) { momentBackTime = momentBackTime.minus({ days: 1 }); } backTime = momentBackTime.valueOf(); newWeek = this.calSvc.multiFormat(backTime); } + this.onWeekChange.emit({ oldWeek: oldWeek, newWeek: newWeek, }); + if (oldWeek.month != newWeek.month) { this.onMonthChange.emit({ oldMonth: oldWeek, newMonth: newWeek, }); } + this.monthOpt = this.createWeek(backTime); } canPrev(): boolean { - // if (!this._d.from || this._view !== 'days') { return true; } if (!this.def.from || this.view !== 'days') return true; - // return this.monthOpt.original.time > moment(this.def.from).valueOf(); + const fromDate = DateTimeHelper.parse(this.def.from); return this.monthOpt.original.time > fromDate.valueOf(); } - onMonthSelect(month: number | any): void { + onMonthSelect(month: number): void { this.view = 'days'; - // const newMonth = moment(this.monthOpt.original.time).month(month).valueOf(); const newMonth = DateTimeHelper.parse(this.monthOpt.original.time).set({ month }).valueOf(); this.onMonthChange.emit({ oldMonth: this.calSvc.multiFormat(this.monthOpt.original.time), @@ -289,10 +278,9 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { this.createWeekOrMonth(newMonth); } - public onYearSelect(year: number | any): void { + public onYearSelect(year: number): void { this.view = 'month'; - // const newYear = moment(this.monthOpt.original.time).year(year).valueOf(); const newYear = DateTimeHelper.parse(this.monthOpt.original.time).set({ year }).valueOf(); this.onMonthChange.emit({ oldMonth: this.calSvc.multiFormat(this.monthOpt.original.time), @@ -301,64 +289,77 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { this.monthOpt = this.createMonth(newYear); } - protected onChanged($event: ICalendarDay[] | any): void { + protected onChanged($event: ICalendarDay[]): void { const eCD: ICalendarDay[] = $event; this.yearStep = 0; + const emitOnChange = (date: CalendarComponentOnChangeType) => { + this._onChanged(date); + this.onChange.emit(date); + } + switch (this.def.pickMode) { case pickModes.single: - const date = this._handleType(eCD[0].time); - this.selectedDates = DateTimeHelper.parse(date.valueOf()).toJSDate(); - this._onChanged(date); - this.onChange.emit(date); + const time = eCD[0].time; + const date = this._handleType(time); + + this.selectedDates = DateTimeHelper.parse(time).toJSDate(); + emitOnChange(date); break; case pickModes.range: if (eCD[0] && eCD[1]) { - const rangeDate = { - from: this._handleType(eCD[0].time), - to: this._handleType(eCD[1].time), + const timeFrom = eCD[0].time; + const timeTo = eCD[1].time; + + const rangeDate: CalendarComponentPayloadRangeType = { + from: this._handleType(timeFrom), + to: this._handleType(timeTo), }; this.selectedDates = Array( - DateTimeHelper.parse(rangeDate.from.valueOf()).toJSDate(), - DateTimeHelper.parse(rangeDate.to.valueOf()).toJSDate() + DateTimeHelper.parse(timeFrom).toJSDate(), + DateTimeHelper.parse(timeTo).toJSDate() ); - this._onChanged(rangeDate); - this.onChange.emit(rangeDate); + emitOnChange(rangeDate); } break; case pickModes.multi: - const dates = []; - this.selectedDates = Array(); - - for (let i = 0; i < eCD.length; i++) { - if (eCD[i] && eCD[i].time) { - const payload = this._handleType(eCD[i].time); - dates.push(payload); - this.selectedDates.push(DateTimeHelper.parse(payload.valueOf()).toJSDate()); + const emitChangeForMulti = (days: ICalendarDay[]): Array => { + const dates: Array = []; + + const payloads: Array = []; + for (let i = 0; i < days.length; i++) { + if (days[i] && days[i].time) { + const time = days[i].time; + const payload = this._handleType(time); + payloads.push(payload); + dates.push(DateTimeHelper.parse(time).toJSDate()); + } } - } - this._onChanged(dates); - this.onChange.emit(dates); + emitOnChange(payloads); + return dates + } + this.selectedDates = emitChangeForMulti(eCD); break; default: } } - protected onSwipe($event: any): void { - const isNext = $event.deltaX < 0; - if (isNext && this.canNext()) { - this.nextMonth(); - } else if (!isNext && this.canPrev()) { - this.backMonth(); - } - } + // onSwipe($event: any): void { + // console.log('onSwipe', $event); // TODO remove debug + // const isNext = $event.deltaX < 0; + // if (isNext && this.canNext()) { + // this.nextMonth(); + // } else if (!isNext && this.canPrev()) { + // this.backMonth(); + // } + // } private _onChanged: Function = () => { }; private _onTouched: Function = () => { }; @@ -379,14 +380,13 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { return date.valueOf(); } - monthFormat(date: number | any): string { + monthFormat(date: number): string { if (!this.def.monthFormat) return ''; // return moment(date).format(this.def.monthFormat.replace(/y/g, 'Y')); return DateTimeHelper.parse(date).toFormat(this.def.monthFormat.replace(/Y/g, 'y'), { locale: this._options.locale?.locale }); } private initOpt(): void { - this.showToggleButtons = this._options.showToggleButtons ?? true; this.showMonthPicker = this._options.showMonthPicker ?? true; @@ -471,21 +471,23 @@ export class CalendarComponent implements ControlValueAccessor, OnInit { this._onTouched = fn; } - private _writeValue(value: any): void { + private _writeValue(value: CalendarComponentOnChangeType): void { if (!value) { this.calendarMonthValue = [null, null]; return; } + this.onChange.emit(value); + switch (this.def.pickMode) { case 'single': - this.calendarMonthValue[0] = this._createCalendarDay(value); + this.calendarMonthValue[0] = this._createCalendarDay(value as CalendarComponentPayloadType); break; case 'range': - this.calendarMonthValue[0] = value.from ? this._createCalendarDay(value.from) : null; - this.calendarMonthValue[1] = value.to ? this._createCalendarDay(value.to) : null; - + const { from, to } = value as CalendarComponentPayloadRangeType; + this.calendarMonthValue[0] = from ? this._createCalendarDay(from) : null; + this.calendarMonthValue[1] = to ? this._createCalendarDay(to) : null; break; case 'multi': diff --git a/projects/ion-calendar/src/lib/helpers/DateTimeHelper.ts b/projects/ion-calendar/src/lib/helpers/DateTimeHelper.ts index 14dcfbb..65a5218 100644 --- a/projects/ion-calendar/src/lib/helpers/DateTimeHelper.ts +++ b/projects/ion-calendar/src/lib/helpers/DateTimeHelper.ts @@ -41,18 +41,18 @@ class DateTimeHelper { return false; } - /** - * Calculates the first and last day of the week for a given date. - * - * @param {Date} date - The date for which to calculate the first and last day of the week. - * @return {{firstDay: Date, lastDay: Date}} - An object containing the first and last day of the week. - * - * @example - * const today = new Date(); - * const weekRange = getFirstAndLastDayOfWeek(today); - * console.log(weekRange.firstDay.toDateString()); // Output: Sun Oct 08 2023 - * console.log(weekRange.lastDay.toDateString()); // Output: Sat Oct 14 2023 - */ + /** + * Calculates the first and last day of the week for a given date. + * + * @param {Date} date - The date for which to calculate the first and last day of the week. + * @return {{firstDay: Date, lastDay: Date}} - An object containing the first and last day of the week. + * + * @example + * const today = new Date(); + * const weekRange = getFirstAndLastDayOfWeek(today); + * console.log(weekRange.firstDay.toDateString()); // Output: Sun Oct 08 2023 + * console.log(weekRange.lastDay.toDateString()); // Output: Sat Oct 14 2023 + */ static getFirstAndLastDayOfWeek(date: Date): { firstDay: Date, lastDay: Date } { const currentDay = date.getDay(); // Dia da semana (0 - Domingo, 1 - Segunda, ..., 6 - Sábado) const diff = currentDay - 0; // 0 representa o Domingo @@ -80,7 +80,6 @@ class DateTimeHelper { const firstDay = this.getFirstAndLastDayOfWeek(today.toJSDate()).firstDay.getDay(); if (firstDay < Number(today.startOf('week').toFormat('dd'))) { - // if (s ?? 'sunday' === 'sunday') { weeksDay.unshift(weeksDay.pop()!); } return weeksDay; diff --git a/projects/ion-calendar/src/lib/types/index.ts b/projects/ion-calendar/src/lib/types/index.ts index 8230d3d..049c47e 100644 --- a/projects/ion-calendar/src/lib/types/index.ts +++ b/projects/ion-calendar/src/lib/types/index.ts @@ -1,8 +1,11 @@ -import { ICalendarLocale } from '../models'; +import { DateObjectUnits, DateTime } from 'luxon'; +import { ICalendarDay, ICalendarLocale } from '../models'; export type DateType = Date | string | number | null; -export type CalendarComponentPayloadType = string | number | Date | {}; export type CalendarComponentType = 'string' | 'js-date' | 'luxon' | 'time' | 'object'; +export type CalendarComponentPayloadType = string | number | Date | DateTime | DateObjectUnits ; +export type CalendarComponentPayloadRangeType = { from: CalendarComponentPayloadType, to: CalendarComponentPayloadType }; +export type CalendarComponentOnChangeType = CalendarComponentPayloadType | CalendarComponentPayloadType[] | CalendarComponentPayloadRangeType // export enum Colors { // PRIMARY = 'primary',