feat(pos): add shop and statistics modules with components, services, and routing

- Implemented shop module with root component, loading state, and invoice handling.
- Created statistics module with invoice type card component, API routes, and data models.
- Added season picker component for selecting year and season.
- Integrated services for fetching statistics data and managing state.
- Established routing for statistics and shop views.
This commit is contained in:
2026-05-23 18:09:44 +03:30
parent 8c07dc7c3f
commit 6ad1a73c16
100 changed files with 768 additions and 231 deletions
@@ -1,17 +1,20 @@
import { Maybe } from '@/core';
import { jalaliToGregorian, nowJalali } from '@/utils';
import { CommonModule } from '@angular/common';
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnInit,
OnDestroy,
Output,
ViewChild,
} from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import dayjs from 'dayjs';
import flatpickr from 'flatpickr-wrap';
import { Persian } from 'flatpickr-wrap/dist/l10n/fa';
import { BaseOptions, DateOption } from 'flatpickr-wrap/dist/types/options';
import { InputTextModule } from 'primeng/inputtext';
import { UikitFieldComponent } from '../uikit-field.component';
@@ -22,7 +25,7 @@ import { UikitFieldComponent } from '../uikit-field.component';
imports: [CommonModule, ReactiveFormsModule, InputTextModule, UikitFieldComponent],
templateUrl: './datepicker.component.html',
})
export class UikitFlatpickrJalaliComponent implements OnInit {
export class UikitFlatpickrJalaliComponent implements AfterViewInit, OnDestroy {
@Input() control?: FormControl<Maybe<string>>;
@Input() placeholder = 'انتخاب تاریخ';
@Input() label = 'تاریخ';
@@ -41,19 +44,34 @@ export class UikitFlatpickrJalaliComponent implements OnInit {
private fpInstance: any | null = null;
ngOnInit(): void {
ngAfterViewInit(): void {
this.fpInstance = flatpickr(this.wrapperRef.nativeElement, {
wrap: true,
...this.options,
locale: 'fa',
locale: Persian,
disableMobile: true,
clickOpens: !this.disabled,
minDate: this.minDate,
maxDate: this.maxDate,
altInputClass: 'p-inputtext w-full',
now: nowJalali(),
altInputClass: 'flatpicker-field w-full',
altInput: true,
dateFormat: 'Y-m-d',
altFormat: 'Y-m-d',
altFormat: 'Y/m/d',
onChange: (selectedDates: Date[], dateStr: string) => {
console.log('dateStr', jalaliToGregorian(dateStr));
this.valueChange.emit(dateStr);
if (this.control) this.control.setValue(dayjs(dateStr).toISOString());
},
});
}
ngOnDestroy(): void {
if (this.fpInstance?.destroy) {
this.fpInstance.destroy();
this.fpInstance = null;
}
}
}