Files
psp_panel/src/app/uikit/datepicker/datepicker.component.ts
T

167 lines
3.1 KiB
TypeScript

import {
Component,
EventEmitter,
Input,
Output,
ViewChild,
computed,
effect,
signal,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormControl } from '@angular/forms';
import dayjs from 'dayjs';
import jalaliday from 'jalaliday';
import { InputText } from 'primeng/inputtext';
import { Popover } from 'primeng/popover';
import { Maybe } from '@/core';
import { formatJalali } from '@/utils';
import { UikitFieldComponent } from '../uikit-field.component';
import {
MonthInfo,
MonthlyWeekDate,
daysName,
prepareMonthInfo,
prepareWeekDayDates,
} from './monthly-calendar.helper.util';
dayjs.extend(jalaliday);
@Component({
selector: 'app-datepicker',
standalone: true,
templateUrl: './datepicker.component.html',
imports: [CommonModule, Popover, InputText, UikitFieldComponent],
})
export class DatepickerComponent {
@Input({ required: true })
control!: FormControl<Maybe<string>>;
@Input()
alignment: 'vertical' | 'horizontal' = 'vertical';
@Input()
name = 'date';
@Input()
label = 'تاریخ';
@Input()
closeOnSelect = true;
/**
* Gregorian YYYY-MM-DD
*/
@Input()
min?: string;
/**
* Gregorian YYYY-MM-DD
*/
@Input()
max?: string;
@Input()
closedDays: number[] = [];
@Output()
valueChange = new EventEmitter<string>();
@Output()
clickOnDayEvent = new EventEmitter<MonthlyWeekDate>();
@ViewChild('op')
op!: Popover;
readonly daysName = daysName;
/**
* Currently displayed month
*/
private readonly activeDateSignal = signal(dayjs().format('YYYY-MM-DD'));
monthInfo = computed<MonthInfo>(() => prepareMonthInfo(this.activeDateSignal()));
weekDaysDates = computed(() => prepareWeekDayDates(this.monthInfo(), this.min, this.max));
constructor() {
effect(() => {
const value = this.value;
if (value) {
this.activeDateSignal.set(value);
}
});
}
ngOnInit(): void {
if (this.control?.value) {
this.activeDateSignal.set(this.control.value);
}
this.control.valueChanges.subscribe((value) => {
if (value) {
this.activeDateSignal.set(value);
}
});
}
get value(): Maybe<string> {
return this.control?.value ?? null;
}
get valueToShow(): Maybe<string> {
if (!this.value) {
return null;
}
return formatJalali(this.value);
}
get activeDate(): string {
return this.activeDateSignal();
}
set activeDate(date: string) {
this.activeDateSignal.set(date);
}
changeMonth(months: number): void {
this.activeDateSignal.set(
dayjs(this.activeDateSignal()).add(months, 'month').format('YYYY-MM-DD')
);
}
selectDate(day: MonthlyWeekDate): void {
if (day.isDisabled) {
return;
}
this.control.setValue(day.gregorianDate);
this.control.markAsDirty();
this.control.markAsTouched();
this.valueChange.emit(day.gregorianDate);
this.clickOnDayEvent.emit(day);
if (this.closeOnSelect) {
this.op.hide();
}
}
isSelected(day: MonthlyWeekDate): boolean {
return this.value === day.gregorianDate;
}
trackByIndex(index: number): number {
return index;
}
}