feat: add public sale invoices module with routing and service integration
- Introduced PUBLIC_SALE_INVOICES_ROUTES for handling sale invoice routes. - Created PublicSaleInvoicesService to fetch single invoice data from the API. - Implemented PublicSaleInvoiceStore for managing invoice state. - Added PublicSaleInvoiceComponent to display invoice details. - Updated app routes to include public sale invoices. - Removed pre-invoice dialog component and its associated files. - Enhanced order submitted dialog with QR code for invoice sharing. - Updated sale invoice single view to reflect new data structure. - Refactored page data list component for improved layout and functionality.
This commit is contained in:
+8
-6
@@ -4,13 +4,15 @@
|
||||
[modal]="true"
|
||||
[style]="{ 'max-height': '90svh', height: 'auto' }"
|
||||
[closable]="true"
|
||||
(onHide)="close()"
|
||||
>
|
||||
<div class="text-center pt-10 pb-14 flex flex-col items-center justify-center gap-4">
|
||||
<i class="" class="pi pi-check-circle text-6xl! text-green-700"></i>
|
||||
<p class="text-lg font-bold">فاکتور شما با موفقیت ایجاد شد.</p>
|
||||
(onHide)="close()">
|
||||
<div class="flex flex-col items-center justify-center gap-4 pt-10 pb-14 text-center">
|
||||
<qrcode [qrdata]="publicInvoiceRoute()" [width]="220" [errorCorrectionLevel]="'M'"></qrcode>
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="" class="pi pi-check-circle text-xl! text-green-700"></i>
|
||||
<p class="text-lg font-bold">فاکتور شما با موفقیت ایجاد شد.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2 justify-center">
|
||||
<div class="flex justify-center gap-2">
|
||||
<button pButton type="button" outlined (click)="printInvoice()">چاپ</button>
|
||||
<button pButton type="button" outlined (click)="sendInvoice()">ارسال به سامانه مودیان</button>
|
||||
<button pButton type="button" outlined (click)="openOrderDetails()">جزئیات</button>
|
||||
|
||||
+7
-2
@@ -6,6 +6,7 @@ import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/ligh
|
||||
import { formatJalali } from '@/utils';
|
||||
import { Component, computed, inject, Input, signal } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { QRCodeComponent } from 'angularx-qrcode';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
import { finalize } from 'rxjs';
|
||||
import { posSaleInvoicesNamedRoutes } from '../../../saleInvoices/constants';
|
||||
@@ -15,7 +16,7 @@ import { IPosOrderResponse } from '../../models';
|
||||
@Component({
|
||||
selector: 'pos-order-submitted-dialog',
|
||||
templateUrl: 'order-submitted-dialog.component.html',
|
||||
imports: [SharedLightBottomsheetComponent, ButtonDirective],
|
||||
imports: [SharedLightBottomsheetComponent, ButtonDirective, QRCodeComponent],
|
||||
})
|
||||
export class PosOrderSubmittedDialogComponent extends AbstractDialog {
|
||||
@Input({ required: true }) invoice!: IPosOrderResponse;
|
||||
@@ -33,12 +34,16 @@ export class PosOrderSubmittedDialogComponent extends AbstractDialog {
|
||||
return '';
|
||||
});
|
||||
|
||||
readonly publicInvoiceRoute = computed(
|
||||
() => `${window.location.origin}/sale-invoices/${this.invoice.id}`
|
||||
);
|
||||
|
||||
sendingLoading = signal(false);
|
||||
sended = signal(false);
|
||||
|
||||
openOrderDetails() {
|
||||
this.router.navigateByUrl(
|
||||
posSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(this.invoice.id),
|
||||
posSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(this.invoice.id)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<shared-light-bottomsheet
|
||||
[(visible)]="visible"
|
||||
header="پیش فاکتور"
|
||||
[modal]="true"
|
||||
[style]="{ 'max-height': '90svh', height: 'auto' }"
|
||||
[closable]="true"
|
||||
(onHide)="close()"
|
||||
>
|
||||
<form [formGroup]="form"></form>
|
||||
<uikit-datepicker [control]="form.controls.invoiceDate" label="تاریخ فاکتور" />
|
||||
</shared-light-bottomsheet>
|
||||
@@ -1,25 +0,0 @@
|
||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||
import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/light-bottomsheet.component';
|
||||
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { PosLandingStore } from '../store/main.store';
|
||||
|
||||
@Component({
|
||||
selector: 'pos-pre-invoice-dialog',
|
||||
templateUrl: './pre-invoice-dialog.component.html',
|
||||
imports: [SharedLightBottomsheetComponent, UikitFlatpickrJalaliComponent, ReactiveFormsModule],
|
||||
})
|
||||
export class PosPreInvoiceDialogComponent extends AbstractDialog {
|
||||
private readonly store = inject(PosLandingStore);
|
||||
private readonly fb = inject(FormBuilder);
|
||||
|
||||
private initForm() {
|
||||
const form = this.fb.group({
|
||||
invoiceDate: [this.store.invoiceDate(), [Validators.required]],
|
||||
});
|
||||
return form;
|
||||
}
|
||||
|
||||
form = this.initForm();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
const baseUrl = () => `/api/v1/public-invoices`;
|
||||
|
||||
export const PUBLIC_SALE_INVOICES_API_ROUTES = {
|
||||
single: (invoiceId: string) => `${baseUrl()}/${invoiceId}`,
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './apiRoutes/index';
|
||||
export * from './routes/index';
|
||||
@@ -0,0 +1,18 @@
|
||||
import { NamedRoutes } from '@/core';
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
export type TPublicSaleInvoicesRouteNames = 'saleInvoice';
|
||||
|
||||
export const publicSaleInvoicesNamedRoutes: NamedRoutes<TPublicSaleInvoicesRouteNames> = {
|
||||
saleInvoice: {
|
||||
path: 'sale-invoices/:invoiceId',
|
||||
loadComponent: () =>
|
||||
import('../../views/single.component').then((m) => m.PublicSaleInvoiceComponent),
|
||||
meta: {
|
||||
title: 'جزئیات فاکتور',
|
||||
pagePath: (invoiceId: string) => `sale-invoices/${invoiceId}`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const PUBLIC_SALE_INVOICES_ROUTES: Routes = [publicSaleInvoicesNamedRoutes.saleInvoice];
|
||||
@@ -0,0 +1 @@
|
||||
export * from './io';
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
import { Maybe } from '@/core';
|
||||
import ISummary from '@/core/models/summary';
|
||||
import { IEnumTranslate } from '@/shared/models/enum_translate.type';
|
||||
|
||||
export interface IPublicSaleInvoicesRawResponse {
|
||||
id: string;
|
||||
code: string;
|
||||
invoice_date: string;
|
||||
invoice_number: string;
|
||||
total_amount: string;
|
||||
pos: Pos;
|
||||
consumer_account: ConsumerAccount;
|
||||
payments: Payments[];
|
||||
type: IEnumTranslate;
|
||||
status: IEnumTranslate;
|
||||
customer: Maybe<Customer>;
|
||||
unknown_customer: Maybe<Record<string, unknown>>;
|
||||
items: InvoiceItem[];
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export interface IPublicSaleInvoicesResponse extends IPublicSaleInvoicesRawResponse {}
|
||||
|
||||
interface ConsumerAccount {
|
||||
role: string;
|
||||
account: Account;
|
||||
}
|
||||
|
||||
interface Account {
|
||||
username: string;
|
||||
}
|
||||
|
||||
interface Pos extends ISummary {
|
||||
complex: Complex;
|
||||
}
|
||||
|
||||
interface Complex extends ISummary {
|
||||
business_activity: BA;
|
||||
}
|
||||
|
||||
interface BA extends ISummary {
|
||||
guild: ISummary;
|
||||
}
|
||||
|
||||
interface Payments {
|
||||
amount: string;
|
||||
paid_at?: string;
|
||||
payment_method: string;
|
||||
}
|
||||
|
||||
interface Customer {
|
||||
type: string;
|
||||
individual: Individual;
|
||||
legal: Legal;
|
||||
}
|
||||
|
||||
interface Individual {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
national_code: string;
|
||||
mobile_number: string;
|
||||
}
|
||||
|
||||
interface Legal {
|
||||
company_name: string;
|
||||
economic_code: string;
|
||||
registration_number: string;
|
||||
}
|
||||
|
||||
interface InvoiceItem {
|
||||
good_snapshot: GoodSnapshot;
|
||||
measure_unit_text: string;
|
||||
quantity: string;
|
||||
total_amount: string;
|
||||
unit_price: string;
|
||||
discount: string;
|
||||
payload: InvoiceItemPayload;
|
||||
sku_code: string;
|
||||
sku_vat: string;
|
||||
notes: Maybe<string>;
|
||||
}
|
||||
|
||||
interface InvoiceItemPayload {
|
||||
karat: string;
|
||||
wages: number;
|
||||
profit: number;
|
||||
commission: number;
|
||||
}
|
||||
|
||||
interface GoodSnapshot {
|
||||
good: Good;
|
||||
}
|
||||
|
||||
interface Good {
|
||||
id: string;
|
||||
sku: Sku;
|
||||
name: string;
|
||||
barcode: Maybe<string>;
|
||||
category: ISummary;
|
||||
image_url: string;
|
||||
local_sku: Maybe<string>;
|
||||
measure_unit: MeasureUnit;
|
||||
pricing_model: string;
|
||||
base_sale_price: string;
|
||||
}
|
||||
|
||||
interface MeasureUnit extends ISummary {
|
||||
code: string;
|
||||
}
|
||||
|
||||
interface Sku extends ISummary {
|
||||
VAT: string;
|
||||
code: string;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ISaleInvoiceFullResponse } from '@/domains/consumer/models';
|
||||
import { ISaleInvoiceFullRawResponse } from '@/shared/components/invoices/sale-invoice-full-response.model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { PUBLIC_SALE_INVOICES_API_ROUTES } from '../constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PublicSaleInvoicesService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private apiRoutes = PUBLIC_SALE_INVOICES_API_ROUTES;
|
||||
|
||||
getSingle(invoiceId: string): Observable<ISaleInvoiceFullResponse> {
|
||||
return this.http.get<ISaleInvoiceFullRawResponse>(this.apiRoutes.single(invoiceId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { defaultBaseStateData, EntityState, EntityStore } from '@/core/state';
|
||||
import { ISaleInvoiceFullResponse } from '@/domains/consumer/models';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { PublicSaleInvoicesService } from '../services/main.service';
|
||||
|
||||
interface PublicSaleInvoiceState extends EntityState<ISaleInvoiceFullResponse> {}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PublicSaleInvoiceStore extends EntityStore<
|
||||
ISaleInvoiceFullResponse,
|
||||
PublicSaleInvoiceState
|
||||
> {
|
||||
private readonly service = inject(PublicSaleInvoicesService);
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
...defaultBaseStateData,
|
||||
});
|
||||
}
|
||||
|
||||
getData(invoiceId: string) {
|
||||
this.patchState({ loading: true });
|
||||
this.service
|
||||
.getSingle(invoiceId)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
})
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
console.log('entity', entity);
|
||||
|
||||
this.patchState({ entity });
|
||||
});
|
||||
}
|
||||
|
||||
override reset(): void {
|
||||
this.setState({
|
||||
...defaultBaseStateData,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './single.component';
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="p-4">
|
||||
<shared-sale-invoice-single-view [loading]="loading()" [invoice]="invoice()" />
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { SharedSaleInvoiceSingleViewComponent } from '@/shared/components/invoices/sale-invoice-single-view.component';
|
||||
import pageParamsUtils from '@/utils/page-params.utils';
|
||||
import { Component, computed, inject, signal } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { PublicSaleInvoiceStore } from '../store/main.store';
|
||||
|
||||
@Component({
|
||||
selector: 'public-saleInvoice',
|
||||
templateUrl: './single.component.html',
|
||||
imports: [SharedSaleInvoiceSingleViewComponent],
|
||||
})
|
||||
export class PublicSaleInvoiceComponent {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly store = inject(PublicSaleInvoiceStore);
|
||||
|
||||
pageParams = computed(() => pageParamsUtils(this.route));
|
||||
invoiceId = signal<string>(this.pageParams()['invoiceId']);
|
||||
|
||||
readonly invoice = computed(() => this.store.entity());
|
||||
readonly loading = computed(() => this.store.loading());
|
||||
|
||||
ngOnInit() {
|
||||
this.store.getData(this.invoiceId());
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,6 @@ import { Button } from 'primeng/button';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(15, 23, 42, 0.22);
|
||||
will-change: opacity;
|
||||
animation: sheetFadeIn var(--sheet-transition, 130ms cubic-bezier(0.2, 0, 0, 1));
|
||||
}
|
||||
|
||||
.light-bottomsheet-panel {
|
||||
@@ -45,10 +43,7 @@ import { Button } from 'primeng/button';
|
||||
background: var(--surface-card, #fff);
|
||||
border-radius: 12px 12px 0 0;
|
||||
box-shadow: none;
|
||||
transform: translate3d(0, 0, 0);
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
animation: sheetSlideUp var(--sheet-transition, 130ms cubic-bezier(0.2, 0, 0, 1));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -87,24 +82,6 @@ import { Button } from 'primeng/button';
|
||||
line-height: 1;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
@keyframes sheetSlideUp {
|
||||
from {
|
||||
transform: translate3d(0, 100%, 0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sheetFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`,
|
||||
],
|
||||
host: {
|
||||
@@ -139,7 +116,7 @@ export class SharedLightBottomsheetComponent implements OnInit, OnDestroy, OnCha
|
||||
constructor(
|
||||
private readonly elementRef: ElementRef<HTMLElement>,
|
||||
private readonly renderer: Renderer2,
|
||||
@Inject(DOCUMENT) private readonly document: Document,
|
||||
@Inject(DOCUMENT) private readonly document: Document
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -214,7 +191,7 @@ export class SharedLightBottomsheetComponent implements OnInit, OnDestroy, OnCha
|
||||
private syncZIndex() {
|
||||
const host = this.elementRef.nativeElement;
|
||||
const siblingDrawers = Array.from(
|
||||
this.document.body.querySelectorAll('.p-drawer'),
|
||||
this.document.body.querySelectorAll('.p-drawer')
|
||||
) as HTMLElement[];
|
||||
const drawerZIndexes = siblingDrawers
|
||||
.map((drawer) => Number.parseInt(drawer.style.zIndex || '0', 10))
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
icon="pi pi-print"
|
||||
outlined
|
||||
size="small"
|
||||
(click)="printInvoice()"
|
||||
></button>
|
||||
(click)="printInvoice()"></button>
|
||||
</ng-template>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="listKeyValue">
|
||||
@@ -29,14 +28,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<p-divider align="center"> اطلاعات پرداخت </p-divider>
|
||||
<div class="grid md:grid-cols-3 sm:grid-cols-2 sm:gap-4 gap-3 items-center">
|
||||
<div class="grid items-center gap-3 sm:grid-cols-2 sm:gap-4 md:grid-cols-3">
|
||||
<app-key-value label="مجموع قابل پرداخت" [value]="invoice.total_amount" type="price" />
|
||||
@for (payment of invoice.payments; track $index) {
|
||||
<app-key-value
|
||||
[label]="`${payment.payment_method === 'SET_OFF' ? 'تهاتر' : payment.payment_method === 'TERMINAL' ? 'پوز' : 'نقدی/ کارتخوان دیگر/ کارت به کارت'}`"
|
||||
[value]="payment.amount"
|
||||
type="price"
|
||||
/>
|
||||
type="price" />
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -45,14 +43,16 @@
|
||||
<app-key-value label="کسب و کار" [value]="invoice.pos!.complex.business_activity.name" />
|
||||
<app-key-value label="مجموعه" [value]="invoice.pos!.complex.name" />
|
||||
<app-key-value label="پایانه فروش" [value]="invoice.pos!.name" />
|
||||
<app-key-value label="ایجاد کننده" [value]="invoice.consumer_account.account.username" />
|
||||
@if (invoice.consumer_account?.account?.username) {
|
||||
<app-key-value label="ایجاد کننده" [value]="invoice.consumer_account.account.username" />
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (variant !== "customer") {
|
||||
@if (variant !== 'customer') {
|
||||
<p-divider align="center"> اطلاعات مشتری </p-divider>
|
||||
@if (invoice.customer) {
|
||||
<div class="listKeyValue">
|
||||
@if (invoice.customer.type === "INDIVIDUAL") {
|
||||
@if (invoice.customer.type === 'INDIVIDUAL') {
|
||||
<app-key-value label="نوع مشتری" value="حقیقی" />
|
||||
<app-key-value label="نام" [value]="invoice.customer.individual?.first_name" />
|
||||
<app-key-value label="نام خانوادگی" [value]="invoice.customer.individual?.last_name" />
|
||||
@@ -74,7 +74,7 @@
|
||||
<app-key-value label="کد ثبتی" [value]="invoice.unknown_customer.national_code" />
|
||||
</div>
|
||||
} @else {
|
||||
<p class="text-center text-text-color pt-3 pb-5">اطلاعات مشتری ثبت نشده است.</p>
|
||||
<p class="text-text-color pt-3 pb-5 text-center">اطلاعات مشتری ثبت نشده است.</p>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@@ -88,16 +88,10 @@
|
||||
[items]="invoice.items"
|
||||
[loading]="loading"
|
||||
pageTitle=""
|
||||
[showRefresh]="false"
|
||||
>
|
||||
[showRefresh]="false">
|
||||
<ng-template #totalAmount let-item>
|
||||
@if (!item.discount_amount) {
|
||||
<span [appPriceMask]="item.total_amount"></span>
|
||||
} @else {
|
||||
<!-- <div class="flex flex-col items-end">
|
||||
<span class="line-through text-muted-color text-xs" [appPriceMask]="item.total_amount"></span>
|
||||
<span [appPriceMask]="item.total_amount - item.discount_amount"></span>
|
||||
</div> -->
|
||||
}
|
||||
</ng-template>
|
||||
</app-page-data-list>
|
||||
|
||||
@@ -250,7 +250,7 @@ export class SharedSaleInvoiceSingleViewComponent {
|
||||
header: 'عنوان',
|
||||
type: 'nested',
|
||||
nestedOption: {
|
||||
path: 'good.name',
|
||||
path: 'good_snapshot.name',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<div class="h-full bg-surface-overlay rounded-lg shadow border border-surface-border p-0! overflow-hidden">
|
||||
<div
|
||||
[ngClass]="{
|
||||
'bg-surface-overlay h-full overflow-hidden rounded-lg p-0!': true,
|
||||
'border-surface-border border shadow': hasCaption(),
|
||||
}">
|
||||
<ng-template #captionTemplate let-isMobileView="isMobileView">
|
||||
@if (pageTitle || showAdd || filter || showRefresh || moreActions) {
|
||||
<ng-container [ngTemplateOutlet]="caption">
|
||||
<div class="flex justify-between items-center gap-4">
|
||||
<div class="flex items-center justify-between gap-4">
|
||||
<h5 class="font-bold">{{ pageTitle }}</h5>
|
||||
@if (showAdd || filter || showRefresh || moreActions) {
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -15,8 +19,7 @@
|
||||
badgeSeverity="info"
|
||||
size="small"
|
||||
[badge]="isFiltered ? '1' : undefined"
|
||||
(click)="openFilter()"
|
||||
></p-button>
|
||||
(click)="openFilter()"></p-button>
|
||||
}
|
||||
@if (showRefresh) {
|
||||
<p-button icon="pi pi-refresh" outlined size="small" (click)="refresh()"></p-button>
|
||||
@@ -36,8 +39,7 @@
|
||||
label="{{ addNewCtaLabel }}"
|
||||
icon="pi pi-plus"
|
||||
size="small"
|
||||
(click)="openAddForm()"
|
||||
></p-button>
|
||||
(click)="openAddForm()"></p-button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@@ -52,8 +54,7 @@
|
||||
[description]="emptyPlaceholderDescription"
|
||||
[ctaLabel]="emptyPlaceholderCtaLabel || addNewCtaLabel"
|
||||
[showCTA]="showAdd"
|
||||
(ctaClick)="openAddForm()"
|
||||
></uikit-empty-state>
|
||||
(ctaClick)="openAddForm()"></uikit-empty-state>
|
||||
</ng-template>
|
||||
<ng-template #paginatorTemplate>
|
||||
<app-paginator
|
||||
@@ -61,8 +62,7 @@
|
||||
[totalRecords]="totalRecords"
|
||||
[perPage]="perPage || 10"
|
||||
[loading]="loading"
|
||||
(onChange)="onPage($event)"
|
||||
/>
|
||||
(onChange)="onPage($event)" />
|
||||
</ng-template>
|
||||
|
||||
@if (!isMobile) {
|
||||
@@ -81,7 +81,7 @@
|
||||
[showDelete]="showDelete"
|
||||
[showDetails]="showDetails"
|
||||
[showIndex]="showIndex"
|
||||
[hasCaption]="!!(pageTitle || showAdd || filter || showRefresh || moreActions)"
|
||||
[hasCaption]="hasCaption()"
|
||||
[expandable]="expandable"
|
||||
[expandableItemKey]="expandableItemKey"
|
||||
[expandColumns]="expandColumns"
|
||||
@@ -89,8 +89,7 @@
|
||||
(onEdit)="edit($event)"
|
||||
(onDelete)="remove($event)"
|
||||
(onDetails)="details($event)"
|
||||
(onChangePage)="onPage($event)"
|
||||
>
|
||||
(onChangePage)="onPage($event)">
|
||||
@if (pageTitle || showAdd || filter || showRefresh || moreActions) {
|
||||
<ng-template #captionBox>
|
||||
<ng-container [ngTemplateOutlet]="captionTemplate" [ngTemplateOutletContext]="{ isMobileView: false }" />
|
||||
@@ -117,14 +116,13 @@
|
||||
[showEdit]="showEdit"
|
||||
[showDelete]="showDelete"
|
||||
[showDetails]="showDetails"
|
||||
[hasCaption]="!!(pageTitle || showAdd || filter || showRefresh || moreActions)"
|
||||
[hasCaption]="hasCaption()"
|
||||
[expandable]="expandable"
|
||||
[expandableItemKey]="expandableItemKey"
|
||||
[expandColumns]="expandColumns"
|
||||
(onEdit)="edit($event)"
|
||||
(onDelete)="remove($event)"
|
||||
(onDetails)="details($event)"
|
||||
>
|
||||
(onDetails)="details($event)">
|
||||
<ng-template #captionBox>
|
||||
@if (pageTitle || showAdd || filter || showRefresh || moreActions) {
|
||||
<ng-container [ngTemplateOutlet]="captionTemplate" [ngTemplateOutletContext]="{ isMobileView: true }" />
|
||||
@@ -145,8 +143,7 @@
|
||||
(onHide)="closeFilter()"
|
||||
header="فیلتر"
|
||||
class="contnet"
|
||||
styleClass="!w-[80vw] md:!w-96 md:!max-w-96 !max-w-sm"
|
||||
>
|
||||
styleClass="!w-[80vw] md:!w-96 md:!max-w-96 !max-w-sm">
|
||||
<hr class="mt-0!" />
|
||||
<div class="pt-2">
|
||||
<ng-container [ngTemplateOutlet]="filter" [ngTemplateOutletContext]="{ $implicit: columns }"> </ng-container>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { jalaliDiff } from '@/utils';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
computed,
|
||||
ContentChild,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
@@ -92,7 +93,7 @@ export interface IColumn<T = any> {
|
||||
export class PageDataListComponent<I = any> {
|
||||
constructor(
|
||||
private host: ElementRef,
|
||||
private renderer: Renderer2,
|
||||
private renderer: Renderer2
|
||||
) {}
|
||||
|
||||
@Input({ required: true }) pageTitle!: string;
|
||||
@@ -138,12 +139,16 @@ export class PageDataListComponent<I = any> {
|
||||
filterDrawerVisible = signal<boolean>(false);
|
||||
expandedRows: { [key: string]: boolean } = {};
|
||||
|
||||
hasCaption = computed(
|
||||
() => !!(this.pageTitle || this.showAdd || this.filter || this.showRefresh || this.moreActions)
|
||||
);
|
||||
|
||||
ngOnInit() {
|
||||
if (this.height)
|
||||
this.renderer.setStyle(
|
||||
this.host.nativeElement,
|
||||
'height',
|
||||
this.fullHeight ? '100cqmin' : this.height,
|
||||
this.fullHeight ? '100cqmin' : this.height
|
||||
);
|
||||
// if (this.fullHeight) {
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user