init
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { Component, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'abstract-dialog',
|
||||
template: '',
|
||||
})
|
||||
export abstract class AbstractDialog {
|
||||
@Input()
|
||||
set visible(v: boolean) {
|
||||
this.visibleSignal.set(!!v);
|
||||
this.visibleChange.emit(!!v);
|
||||
}
|
||||
get visible() {
|
||||
return this.visibleSignal();
|
||||
}
|
||||
private visibleSignal = signal(false);
|
||||
|
||||
close() {
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
@Output() visibleChange = new EventEmitter<boolean>();
|
||||
}
|
||||
+11
-10
@@ -1,5 +1,4 @@
|
||||
import { ToastService } from '@/core/services/toast.service';
|
||||
import { Component, effect, EventEmitter, inject, Input, Output, signal } from '@angular/core';
|
||||
import { Component, effect, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { AbstractForm } from './abstract-form';
|
||||
|
||||
@@ -8,9 +7,9 @@ import { AbstractForm } from './abstract-form';
|
||||
template: '',
|
||||
imports: [ReactiveFormsModule],
|
||||
})
|
||||
export abstract class AbstractFormDialog<Response, Request> extends AbstractForm<
|
||||
Response,
|
||||
Request
|
||||
export abstract class AbstractFormDialog<Request, Response> extends AbstractForm<
|
||||
Request,
|
||||
Response
|
||||
> {
|
||||
@Input()
|
||||
set visible(v: boolean) {
|
||||
@@ -25,17 +24,19 @@ export abstract class AbstractFormDialog<Response, Request> extends AbstractForm
|
||||
@Output() visibleChange = new EventEmitter<boolean>();
|
||||
|
||||
constructor() {
|
||||
super(inject(ToastService));
|
||||
super();
|
||||
effect(() => {
|
||||
const v = this.visibleSignal();
|
||||
if (!v) this.form.reset(this.defaultValues);
|
||||
});
|
||||
this.submit.bind(() => {
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
|
||||
override onSuccess(response: Response): void {
|
||||
this.close();
|
||||
}
|
||||
|
||||
override close() {
|
||||
this.visibleSignal.set(false);
|
||||
this.onClose.emit();
|
||||
this.visibleChange.emit(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { ToastService } from '@/core/services/toast.service';
|
||||
import { Component, EventEmitter, inject, Input, Output, signal } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { finalize, Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'abstract-form-dialog',
|
||||
template: '',
|
||||
imports: [ReactiveFormsModule],
|
||||
})
|
||||
export abstract class AbstractForm<
|
||||
FormInterface,
|
||||
Response,
|
||||
InitialValue = Response,
|
||||
RequestPayload extends FormInterface = FormInterface,
|
||||
> {
|
||||
@Input() initialValues?: InitialValue;
|
||||
@Input() editMode?: boolean;
|
||||
|
||||
@Output() onSubmit = new EventEmitter<Response>();
|
||||
@Output() onClose = new EventEmitter<void>();
|
||||
|
||||
protected readonly fb = inject(FormBuilder);
|
||||
private readonly toastService = inject(ToastService);
|
||||
constructor() {}
|
||||
|
||||
abstract form: ReturnType<FormBuilder['group']>;
|
||||
showSuccessMessage: boolean = true;
|
||||
successMessage = 'عملیات با موفقیت انجام شد';
|
||||
defaultValues: Partial<FormInterface> = {};
|
||||
|
||||
abstract submitForm(payload: FormInterface): Observable<Response> | void;
|
||||
|
||||
prepareRequestPayload(payload: FormInterface): RequestPayload {
|
||||
// @ts-ignore
|
||||
return payload;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.form.patchValue(this.initialValues ?? {});
|
||||
}
|
||||
|
||||
onSuccess(response: Response): void {}
|
||||
|
||||
submitLoading = signal(false);
|
||||
|
||||
submit() {
|
||||
this.form.markAllAsTouched();
|
||||
|
||||
if (this.form.valid) {
|
||||
// this.form.disable();
|
||||
this.submitLoading.set(true);
|
||||
|
||||
this.submitForm(this.prepareRequestPayload(this.form.value))
|
||||
?.pipe(
|
||||
finalize(() => {
|
||||
this.submitLoading.set(false);
|
||||
// this.form.enable();
|
||||
}),
|
||||
)
|
||||
.subscribe((res) => {
|
||||
this.onSuccess(res);
|
||||
if (this.showSuccessMessage) {
|
||||
this.toastService.success({
|
||||
text: this.successMessage,
|
||||
});
|
||||
}
|
||||
this.onSubmit.emit(res);
|
||||
// this.form.reset();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.onClose.emit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||
import { Component, signal } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { IColumn } from '../components/pageDataList/page-data-list.component';
|
||||
|
||||
@Component({
|
||||
selector: 'abstract-list',
|
||||
template: '',
|
||||
})
|
||||
export abstract class AbstractList<ResponseModel, RequestParams = null> {
|
||||
columns = [] as IColumn[];
|
||||
loading = signal(false);
|
||||
items = signal<ResponseModel[]>([]);
|
||||
visibleForm = signal(false);
|
||||
requestPayload = signal<Maybe<RequestParams>>(null);
|
||||
selectedItemForEdit = signal<Maybe<ResponseModel>>(null);
|
||||
editMode = signal(false);
|
||||
|
||||
ngOnInit() {
|
||||
this.setColumns();
|
||||
this.getData();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.getData();
|
||||
}
|
||||
|
||||
getData() {
|
||||
this.loading.set(true);
|
||||
this.getDataRequest(this.requestPayload())?.subscribe((res) => {
|
||||
this.loading.set(false);
|
||||
this.items.set(res.data);
|
||||
});
|
||||
}
|
||||
|
||||
openAddForm() {
|
||||
this.selectedItemForEdit.set(null);
|
||||
this.editMode.set(false);
|
||||
this.visibleForm.set(true);
|
||||
}
|
||||
|
||||
abstract getDataRequest(
|
||||
payload: Maybe<RequestParams>,
|
||||
): Observable<IPaginatedResponse<ResponseModel>> | void;
|
||||
|
||||
abstract setColumns(): void;
|
||||
|
||||
// constructor() {
|
||||
// if (this.editable) {
|
||||
// if (!this.ed) {
|
||||
// throw new Error('onEdit output must be bound when editable is true');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
onEditClick(selectedItem: ResponseModel) {
|
||||
this.selectedItemForEdit.set(selectedItem);
|
||||
this.editMode.set(true);
|
||||
this.visibleForm.set(true);
|
||||
}
|
||||
onCloseEdit() {
|
||||
this.visibleForm.set(false);
|
||||
}
|
||||
}
|
||||
-2
@@ -89,8 +89,6 @@ export abstract class AbstractSelectComponent<T = ISelectItem, serviceResponse =
|
||||
}
|
||||
|
||||
change(value: Maybe<T>) {
|
||||
console.log('first');
|
||||
|
||||
if (typeof value !== 'object') {
|
||||
// @ts-ignore
|
||||
this.onChange.emit(this.items()?.find((item) => item[this.optionValue] === value));
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './abstract-form';
|
||||
export * from './abstract-form-dialog.component';
|
||||
export * from './abstract-list';
|
||||
export * from './abstract-select.component';
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './select/select.component';
|
||||
export * from './tag/tag.component';
|
||||
@@ -1,14 +0,0 @@
|
||||
<uikit-field label="بانک" [control]="control" [showLabel]="showLabel" [showErrors]="showErrors">
|
||||
<p-select
|
||||
[loading]="loading()"
|
||||
[options]="items()"
|
||||
optionLabel="name"
|
||||
[optionValue]="selectOptionValue"
|
||||
placeholder="انتخاب بانک"
|
||||
[formControl]="control"
|
||||
[showClear]="true"
|
||||
[filter]="true"
|
||||
appendTo="body"
|
||||
>
|
||||
</p-select>
|
||||
</uikit-field>
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AbstractSelectComponent } from '@/shared/components';
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { Component } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { Select } from 'primeng/select';
|
||||
import { IBankResponse } from '../../models';
|
||||
import { BanksStore } from '../../store/main.store';
|
||||
|
||||
@Component({
|
||||
selector: 'banks-select-field',
|
||||
templateUrl: './select.component.html',
|
||||
imports: [ReactiveFormsModule, Select, UikitFieldComponent],
|
||||
})
|
||||
export class BanksSelectComponent extends AbstractSelectComponent<IBankResponse, IBankResponse[]> {
|
||||
constructor(private store: BanksStore) {
|
||||
super();
|
||||
this.getData();
|
||||
}
|
||||
|
||||
getDataService() {
|
||||
return this.store.getItems();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<span>
|
||||
{{ selectedBank?.name }}
|
||||
</span>
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Component, inject, Input } from '@angular/core';
|
||||
import { BanksStore } from '../../store/main.store';
|
||||
|
||||
@Component({
|
||||
selector: 'app-catalog-banks-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
})
|
||||
export class CatalogBanksComponent {
|
||||
@Input() bankId!: number;
|
||||
|
||||
private readonly store = inject(BanksStore);
|
||||
|
||||
banks = this.store.banks;
|
||||
|
||||
selectedBank = this.banks().find((bank) => bank.id === this.bankId);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
const baseUrl = '/api/v1/banks';
|
||||
|
||||
export const BANKS_API_ROUTES = {
|
||||
list: () => `${baseUrl}`,
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './apiRoutes';
|
||||
@@ -1 +0,0 @@
|
||||
export * from './components';
|
||||
@@ -1 +0,0 @@
|
||||
export * from './io';
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
export interface IBankRawResponse {
|
||||
id: number;
|
||||
name: string;
|
||||
shortName: string;
|
||||
}
|
||||
|
||||
export interface IBankResponse extends IBankRawResponse {}
|
||||
|
||||
export interface IBankRequest {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
mobileNumber: string;
|
||||
address: string;
|
||||
city: string;
|
||||
state: string;
|
||||
country: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BANKS_API_ROUTES } from '../constants';
|
||||
import { IBankRawResponse, IBankResponse } from '../models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BanksService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private apiRoutes = BANKS_API_ROUTES;
|
||||
|
||||
getAll(): Observable<IPaginatedResponse<IBankResponse>> {
|
||||
return this.http.get<IPaginatedResponse<IBankRawResponse>>(this.apiRoutes.list());
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { BaseState, BaseStore } from '@/core/state';
|
||||
import { computed, Injectable } from '@angular/core';
|
||||
import { of } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { IBankResponse } from '../models';
|
||||
import { BanksService } from '../services/main.service';
|
||||
|
||||
export interface banksState extends BaseState<IBankResponse[]> {
|
||||
items: IBankResponse[];
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class BanksStore extends BaseStore<banksState> {
|
||||
constructor(private service: BanksService) {
|
||||
super({
|
||||
loading: false,
|
||||
initialized: false,
|
||||
error: null,
|
||||
isRefreshing: false,
|
||||
items: [],
|
||||
});
|
||||
this.initial();
|
||||
}
|
||||
|
||||
readonly banks = computed(() => this.getCurrentState().items || []);
|
||||
|
||||
reset(): void {
|
||||
this.setState({
|
||||
loading: false,
|
||||
initialized: false,
|
||||
error: null,
|
||||
isRefreshing: false,
|
||||
items: [],
|
||||
});
|
||||
}
|
||||
|
||||
initial() {
|
||||
this.getItems().subscribe();
|
||||
}
|
||||
|
||||
getItems() {
|
||||
if (this.getCurrentState().items?.length === 0) {
|
||||
this.setLoading(true);
|
||||
return this.service.getAll().pipe(
|
||||
map((res: { data: IBankResponse[] }) => {
|
||||
this.patchState({
|
||||
items: res.data,
|
||||
initialized: true,
|
||||
});
|
||||
this.setLoading(false);
|
||||
return res.data;
|
||||
}),
|
||||
catchError((err: any) => {
|
||||
this.setError(err.message || 'Failed to load banks');
|
||||
this.setLoading(false);
|
||||
return of([] as IBankResponse[]);
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
return of(this.getCurrentState().items);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<uikit-field label="جنسیت" name="gender" [control]="control">
|
||||
<ng-container *ngIf="formControl as fc">
|
||||
<p-select
|
||||
[options]="[
|
||||
{ label: 'مرد', id: true },
|
||||
{ label: 'زن', id: false },
|
||||
]"
|
||||
[size]="size"
|
||||
[id]="'gender'"
|
||||
[optionValue]="'id'"
|
||||
[attr.name]="'gender'"
|
||||
[formControl]="fc"
|
||||
[invalid]="fc.invalid && (fc.dirty || fc.touched)"
|
||||
></p-select>
|
||||
</ng-container>
|
||||
</uikit-field>
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { UikitFieldComponent } from '@/uikit/uikit-field.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { AbstractControl, FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Select } from 'primeng/select';
|
||||
|
||||
@Component({
|
||||
selector: 'app-gender-select',
|
||||
templateUrl: './gender-select.component.html',
|
||||
imports: [CommonModule, UikitFieldComponent, Select, ReactiveFormsModule],
|
||||
})
|
||||
export class GenderSelectComponent {
|
||||
@Input() control!: Maybe<AbstractControl<any, any>>;
|
||||
@Input() size?: 'small' | 'large';
|
||||
|
||||
get formControl(): FormControl | undefined {
|
||||
return this.control as FormControl | undefined;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{{ genderTitle() }}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Component, computed, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-gender-tag',
|
||||
templateUrl: './gender-tag.component.html',
|
||||
})
|
||||
export class CatalogGenderTagComponent {
|
||||
@Input() gender!: boolean;
|
||||
|
||||
constructor() {}
|
||||
|
||||
genderTitle = computed(() => (this.gender ? 'مرد' : 'زن'));
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './gender-select.component';
|
||||
export * from './gender-tag.component';
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './gender';
|
||||
export * from './movementTypes';
|
||||
export * from './purchaseReceiptStatus';
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { MovementType } from '../movementTypes';
|
||||
import { MovementReferenceType } from './types';
|
||||
import { getMovementReferenceTypeColor, getMovementReferenceTypeText } from './utils';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-movement-reference-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogMovementReferenceTagComponent {
|
||||
@Input() type!: MovementReferenceType;
|
||||
@Input() movementType?: MovementType;
|
||||
@Input() counterName?: string;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getMovementReferenceTypeText(this.type, this.movementType, this.counterName);
|
||||
}
|
||||
get color() {
|
||||
return getMovementReferenceTypeColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export const MovementReferenceType = {
|
||||
PURCHASE: 'PURCHASE',
|
||||
SALES: 'SALES',
|
||||
ADJUSTMENT: 'ADJUSTMENT',
|
||||
INVENTORY_TRANSFER: 'INVENTORY_TRANSFER',
|
||||
} as const;
|
||||
|
||||
export type MovementReferenceType =
|
||||
(typeof MovementReferenceType)[keyof typeof MovementReferenceType];
|
||||
@@ -1,39 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { MovementType } from '../movementTypes';
|
||||
import { MovementReferenceType } from './types';
|
||||
|
||||
export const getMovementReferenceTypeText = (
|
||||
movementType: MovementReferenceType,
|
||||
type?: MovementType,
|
||||
counterName?: string,
|
||||
): string => {
|
||||
switch (movementType) {
|
||||
case MovementReferenceType.PURCHASE:
|
||||
return 'خرید';
|
||||
case MovementReferenceType.SALES:
|
||||
return 'فروش';
|
||||
case MovementReferenceType.ADJUSTMENT:
|
||||
return 'تعدیل';
|
||||
case MovementReferenceType.INVENTORY_TRANSFER:
|
||||
if (type === MovementType.IN) {
|
||||
return `دریافت از انبار ${counterName ?? 'دیگر'}`;
|
||||
} else {
|
||||
return `ارسال به انبار ${counterName ?? 'دیگر'}`;
|
||||
}
|
||||
default:
|
||||
return 'انتقال بین انبارها';
|
||||
}
|
||||
};
|
||||
|
||||
export const getMovementReferenceTypeColor = (movementType: MovementReferenceType): TagSeverity => {
|
||||
switch (movementType) {
|
||||
case MovementReferenceType.PURCHASE:
|
||||
return 'success';
|
||||
case MovementReferenceType.SALES:
|
||||
return 'danger';
|
||||
case MovementReferenceType.ADJUSTMENT:
|
||||
return 'warn';
|
||||
case MovementReferenceType.INVENTORY_TRANSFER:
|
||||
return 'info';
|
||||
}
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { MovementType } from './types';
|
||||
import { getMovementTypeColor, getMovementTypeText } from './utils';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-movement-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogMovementTagComponent {
|
||||
@Input() type!: MovementType;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getMovementTypeText(this.type);
|
||||
}
|
||||
get color() {
|
||||
return getMovementTypeColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export const MovementType = {
|
||||
IN: 'IN',
|
||||
OUT: 'OUT',
|
||||
ADJUST: 'ADJUST',
|
||||
} as const;
|
||||
|
||||
export type MovementType = (typeof MovementType)[keyof typeof MovementType];
|
||||
@@ -1,24 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { MovementType } from './types';
|
||||
|
||||
export const getMovementTypeText = (movementType: MovementType): string => {
|
||||
switch (movementType) {
|
||||
case MovementType.IN:
|
||||
return 'ورودی';
|
||||
case MovementType.OUT:
|
||||
return 'خروجی';
|
||||
case MovementType.ADJUST:
|
||||
return 'تعدیل';
|
||||
}
|
||||
};
|
||||
|
||||
export const getMovementTypeColor = (movementType: MovementType): TagSeverity => {
|
||||
switch (movementType) {
|
||||
case MovementType.IN:
|
||||
return 'success';
|
||||
case MovementType.OUT:
|
||||
return 'danger';
|
||||
case MovementType.ADJUST:
|
||||
return 'warn';
|
||||
}
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './select/select.component';
|
||||
export * from './tag/tag.component';
|
||||
@@ -1,13 +0,0 @@
|
||||
<uikit-field label="نوع پرداخت" [control]="control" [showLabel]="showLabel" [showErrors]="showErrors">
|
||||
<p-select
|
||||
[options]="items"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="انتخاب نوع پرداخت"
|
||||
[formControl]="control"
|
||||
[showClear]="true"
|
||||
[filter]="true"
|
||||
appendTo="body"
|
||||
>
|
||||
</p-select>
|
||||
</uikit-field>
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Select } from 'primeng/select';
|
||||
import { PaymentMethodType } from '../../types';
|
||||
|
||||
@Component({
|
||||
selector: 'app-catalog-payment-method-type-select-field',
|
||||
templateUrl: './select.component.html',
|
||||
imports: [ReactiveFormsModule, Select, UikitFieldComponent],
|
||||
})
|
||||
export class PaymentMethodTypeSelectComponent {
|
||||
@Input() control = new FormControl<Maybe<PaymentMethodType>>(null);
|
||||
@Input() showLabel: boolean = true;
|
||||
@Input() showErrors: boolean = true;
|
||||
@Input() showClear: boolean = false;
|
||||
@Input() isFullDataOptionValue: boolean = false;
|
||||
@Output() onChange = new EventEmitter<Maybe<PaymentMethodType>>();
|
||||
|
||||
items = [
|
||||
{ label: 'نقدی', value: 'CASH' },
|
||||
{ label: 'کارت بانکی', value: 'CARD' },
|
||||
{ label: 'حساب', value: 'BANK' },
|
||||
{ label: 'چک', value: 'CHECK' },
|
||||
{ label: 'سایر', value: 'OTHER' },
|
||||
] as { label: string; value: PaymentMethodType }[];
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { PaymentMethodType } from '../../types';
|
||||
import { getPaymentMethodTypeColor, getPaymentMethodTypeText } from '../../utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-catalog-payment-method-type-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogPaymentMethodTypeTagComponent {
|
||||
@Input() type!: PaymentMethodType;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getPaymentMethodTypeText(this.type);
|
||||
}
|
||||
get color() {
|
||||
return getPaymentMethodTypeColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './components/tag/tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,9 +0,0 @@
|
||||
export const PaymentMethodType = {
|
||||
CASH: 'CASH',
|
||||
CARD: 'CARD',
|
||||
BANK: 'BANK',
|
||||
CHECK: 'CHECK',
|
||||
OTHER: 'OTHER',
|
||||
} as const;
|
||||
|
||||
export type PaymentMethodType = (typeof PaymentMethodType)[keyof typeof PaymentMethodType];
|
||||
@@ -1,32 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { PaymentMethodType } from './types';
|
||||
|
||||
export const getPaymentMethodTypeText = (value: PaymentMethodType): string => {
|
||||
switch (value) {
|
||||
case PaymentMethodType.CASH:
|
||||
return 'نقدی';
|
||||
case PaymentMethodType.CARD:
|
||||
return 'کارت';
|
||||
case PaymentMethodType.BANK:
|
||||
return 'بانک';
|
||||
case PaymentMethodType.CHECK:
|
||||
return 'چک';
|
||||
case PaymentMethodType.OTHER:
|
||||
return 'سایر';
|
||||
}
|
||||
};
|
||||
|
||||
export const getPaymentMethodTypeColor = (value: PaymentMethodType): TagSeverity => {
|
||||
switch (value) {
|
||||
case PaymentMethodType.CASH:
|
||||
return 'danger';
|
||||
case PaymentMethodType.CARD:
|
||||
return 'info';
|
||||
case PaymentMethodType.BANK:
|
||||
return 'success';
|
||||
case PaymentMethodType.CHECK:
|
||||
return 'warn';
|
||||
case PaymentMethodType.OTHER:
|
||||
return 'secondary';
|
||||
}
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './tag/tag.component';
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { PaymentType } from '../../types';
|
||||
import { getPaymentTypeColor, getPaymentTypeText } from '../../utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-catalog-payment-type-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogPaymentTypeTagComponent {
|
||||
@Input() type!: PaymentType;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getPaymentTypeText(this.type);
|
||||
}
|
||||
get color() {
|
||||
return getPaymentTypeColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './components/tag/tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,6 +0,0 @@
|
||||
export const PaymentType = {
|
||||
PAYMENT: 'PAYMENT',
|
||||
REFUND: 'REFUND',
|
||||
} as const;
|
||||
|
||||
export type PaymentType = (typeof PaymentType)[keyof typeof PaymentType];
|
||||
@@ -1,20 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { PaymentType } from './types';
|
||||
|
||||
export const getPaymentTypeText = (value: PaymentType): string => {
|
||||
switch (value) {
|
||||
case PaymentType.PAYMENT:
|
||||
return 'پرداخت';
|
||||
case PaymentType.REFUND:
|
||||
return 'بازگشت وجه';
|
||||
}
|
||||
};
|
||||
|
||||
export const getPaymentTypeColor = (value: PaymentType): TagSeverity => {
|
||||
switch (value) {
|
||||
case PaymentType.PAYMENT:
|
||||
return 'success';
|
||||
case PaymentType.REFUND:
|
||||
return 'warn';
|
||||
}
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { PurchaseReceiptStatus } from './types';
|
||||
import { getPurchaseReceiptStatusColor, getPurchaseReceiptStatusText } from './utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-catalog-purchase-receipt-status-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogPurchaseReceiptStatusTagComponent {
|
||||
@Input() type!: PurchaseReceiptStatus;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getPurchaseReceiptStatusText(this.type);
|
||||
}
|
||||
get color() {
|
||||
return getPurchaseReceiptStatusColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export const PurchaseReceiptStatus = {
|
||||
UNPAID: 'UNPAID',
|
||||
PARTIALLY_PAID: 'PARTIALLY_PAID',
|
||||
PAID: 'PAID',
|
||||
} as const;
|
||||
|
||||
export type PurchaseReceiptStatus =
|
||||
(typeof PurchaseReceiptStatus)[keyof typeof PurchaseReceiptStatus];
|
||||
@@ -1,24 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { PurchaseReceiptStatus } from './types';
|
||||
|
||||
export const getPurchaseReceiptStatusText = (value: PurchaseReceiptStatus): string => {
|
||||
switch (value) {
|
||||
case PurchaseReceiptStatus.UNPAID:
|
||||
return 'پرداخت نشده';
|
||||
case PurchaseReceiptStatus.PARTIALLY_PAID:
|
||||
return 'پرداخت شده جزئی';
|
||||
case PurchaseReceiptStatus.PAID:
|
||||
return 'تسویه شده';
|
||||
}
|
||||
};
|
||||
|
||||
export const getPurchaseReceiptStatusColor = (value: PurchaseReceiptStatus): TagSeverity => {
|
||||
switch (value) {
|
||||
case PurchaseReceiptStatus.UNPAID:
|
||||
return 'danger';
|
||||
case PurchaseReceiptStatus.PARTIALLY_PAID:
|
||||
return 'warn';
|
||||
case PurchaseReceiptStatus.PAID:
|
||||
return 'success';
|
||||
}
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './select.component';
|
||||
export * from './tag.component';
|
||||
@@ -1,12 +0,0 @@
|
||||
<uikit-field label="نقش" name="role" [control]="control">
|
||||
<p-select
|
||||
[options]="roles()"
|
||||
[id]="'role'"
|
||||
[optionValue]="'id'"
|
||||
optionLabel="name"
|
||||
[attr.name]="'role'"
|
||||
[formControl]="control"
|
||||
[loading]="loading()"
|
||||
[invalid]="control.invalid && (control.dirty || control.touched)"
|
||||
></p-select>
|
||||
</uikit-field>
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { Component, Input, signal } from '@angular/core';
|
||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Select } from 'primeng/select';
|
||||
import { IRoleResponse } from '../models';
|
||||
import { RolesService } from '../services';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-roles-select',
|
||||
templateUrl: './select.component.html',
|
||||
imports: [UikitFieldComponent, Select, ReactiveFormsModule],
|
||||
})
|
||||
export class CatalogRolesComponent {
|
||||
@Input() control!: FormControl<Maybe<number>>;
|
||||
|
||||
constructor(private service: RolesService) {
|
||||
this.getData();
|
||||
}
|
||||
|
||||
roles = signal<IRoleResponse[]>([]);
|
||||
loading = signal<boolean>(false);
|
||||
|
||||
private getData() {
|
||||
this.loading.set(true);
|
||||
return this.service.getAll().subscribe({
|
||||
next: (res) => {
|
||||
this.roles.set(res);
|
||||
},
|
||||
error: () => {
|
||||
this.roles.set([]);
|
||||
},
|
||||
complete: () => {
|
||||
this.loading.set(false);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{{ roleTitle() }}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { IRoleResponse } from '../models';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-role-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
})
|
||||
export class CatalogRoleTagComponent {
|
||||
@Input() role!: IRoleResponse;
|
||||
|
||||
constructor() {}
|
||||
|
||||
roleTitle() {
|
||||
return this.role.name;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
const baseUrl = '/api/v1/roles';
|
||||
|
||||
export const ROLES_API_ROUTES = {
|
||||
list: () => `${baseUrl}`,
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './apiRoutes';
|
||||
@@ -1,4 +0,0 @@
|
||||
export * from './components';
|
||||
export * from './constants';
|
||||
export * from './models';
|
||||
export * from './services';
|
||||
@@ -1 +0,0 @@
|
||||
export * from './io';
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface IRoleRawResponse {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
export interface IRoleResponse extends IRoleRawResponse {}
|
||||
@@ -1 +0,0 @@
|
||||
export * from './main.service';
|
||||
@@ -1,19 +0,0 @@
|
||||
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { ROLES_API_ROUTES } from '../constants';
|
||||
import { IRoleRawResponse, IRoleResponse } from '../models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class RolesService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private apiRoutes = ROLES_API_ROUTES;
|
||||
|
||||
getAll(): Observable<IRoleResponse[]> {
|
||||
return this.http
|
||||
.get<IPaginatedResponse<IRoleRawResponse>>(this.apiRoutes.list())
|
||||
.pipe(map((response) => response.data as IRoleResponse[]));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { BankTransactionReferenceType } from './types';
|
||||
import {
|
||||
getBankAccountTransactionReferenceTypeColor,
|
||||
getBankAccountTransactionReferenceTypeText,
|
||||
} from './utils';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-bank-account-transaction-reference-type-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogBankAccountTransactionReferenceTypeTagComponent {
|
||||
@Input() type!: BankTransactionReferenceType;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getBankAccountTransactionReferenceTypeText(this.type);
|
||||
}
|
||||
get color() {
|
||||
return getBankAccountTransactionReferenceTypeColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
export const BankTransactionReferenceType = {
|
||||
PURCHASE_PAYMENT: 'PURCHASE_PAYMENT',
|
||||
PURCHASE_REFUND: 'PURCHASE_REFUND',
|
||||
POS_SALE: 'POS_SALE',
|
||||
POS_REFUND: 'POS_REFUND',
|
||||
BANK_TRANSFER: 'BANK_TRANSFER',
|
||||
MANUAL_ADJUSTMENT: 'MANUAL_ADJUSTMENT',
|
||||
} as const;
|
||||
|
||||
export type BankTransactionReferenceType =
|
||||
(typeof BankTransactionReferenceType)[keyof typeof BankTransactionReferenceType];
|
||||
@@ -1,40 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { BankTransactionReferenceType } from './types';
|
||||
|
||||
export const getBankAccountTransactionReferenceTypeText = (
|
||||
type: BankTransactionReferenceType,
|
||||
): string => {
|
||||
switch (type) {
|
||||
case BankTransactionReferenceType.BANK_TRANSFER:
|
||||
return 'انتقال بانکی';
|
||||
case BankTransactionReferenceType.MANUAL_ADJUSTMENT:
|
||||
return 'تعدیل دستی';
|
||||
case BankTransactionReferenceType.POS_REFUND:
|
||||
return 'بازپرداخت فروشگاه';
|
||||
case BankTransactionReferenceType.POS_SALE:
|
||||
return 'فروش فروشگاه';
|
||||
case BankTransactionReferenceType.PURCHASE_REFUND:
|
||||
return 'بازپرداخت خرید';
|
||||
case BankTransactionReferenceType.PURCHASE_PAYMENT:
|
||||
return 'پرداخت خرید';
|
||||
}
|
||||
};
|
||||
|
||||
export const getBankAccountTransactionReferenceTypeColor = (
|
||||
type: BankTransactionReferenceType,
|
||||
): TagSeverity => {
|
||||
switch (type) {
|
||||
case BankTransactionReferenceType.BANK_TRANSFER:
|
||||
return 'secondary';
|
||||
case BankTransactionReferenceType.MANUAL_ADJUSTMENT:
|
||||
return 'secondary';
|
||||
case BankTransactionReferenceType.POS_REFUND:
|
||||
return 'warn';
|
||||
case BankTransactionReferenceType.POS_SALE:
|
||||
return 'info';
|
||||
case BankTransactionReferenceType.PURCHASE_REFUND:
|
||||
return 'warn';
|
||||
case BankTransactionReferenceType.PURCHASE_PAYMENT:
|
||||
return 'info';
|
||||
}
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './tag.component';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
@@ -1,3 +0,0 @@
|
||||
<p-tag [severity]="color">
|
||||
{{ text }}
|
||||
</p-tag>
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Tag } from 'primeng/tag';
|
||||
import { BankAccountTransactionType } from './types';
|
||||
import { getBankAccountTransactionTypeColor, getBankAccountTransactionTypeText } from './utils';
|
||||
|
||||
@Component({
|
||||
selector: 'catalog-bank-account-transaction-type-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
imports: [Tag],
|
||||
})
|
||||
export class CatalogBankAccountTransactionTypeTagComponent {
|
||||
@Input() type!: BankAccountTransactionType;
|
||||
constructor() {}
|
||||
|
||||
get text() {
|
||||
return getBankAccountTransactionTypeText(this.type);
|
||||
}
|
||||
get color() {
|
||||
return getBankAccountTransactionTypeColor(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export const BankAccountTransactionType = {
|
||||
DEPOSIT: 'DEPOSIT',
|
||||
WITHDRAWAL: 'WITHDRAWAL',
|
||||
} as const;
|
||||
|
||||
export type BankAccountTransactionType =
|
||||
(typeof BankAccountTransactionType)[keyof typeof BankAccountTransactionType];
|
||||
@@ -1,22 +0,0 @@
|
||||
import { TagSeverity } from '@/core/models/tag';
|
||||
import { BankAccountTransactionType } from './types';
|
||||
|
||||
export const getBankAccountTransactionTypeText = (type: BankAccountTransactionType): string => {
|
||||
switch (type) {
|
||||
case BankAccountTransactionType.DEPOSIT:
|
||||
return 'واریز';
|
||||
case BankAccountTransactionType.WITHDRAWAL:
|
||||
return 'برداشت';
|
||||
}
|
||||
};
|
||||
|
||||
export const getBankAccountTransactionTypeColor = (
|
||||
type: BankAccountTransactionType,
|
||||
): TagSeverity => {
|
||||
switch (type) {
|
||||
case BankAccountTransactionType.DEPOSIT:
|
||||
return 'success';
|
||||
case BankAccountTransactionType.WITHDRAWAL:
|
||||
return 'danger';
|
||||
}
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
import { ToastService } from '@/core/services/toast.service';
|
||||
import { Component, EventEmitter, inject, Input, Output, signal } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Subscribable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'abstract-form-dialog',
|
||||
template: '',
|
||||
imports: [ReactiveFormsModule],
|
||||
})
|
||||
export abstract class AbstractForm<Response, Request> {
|
||||
@Input() initialValues?: Response;
|
||||
|
||||
@Output() onSubmit = new EventEmitter<Response>();
|
||||
@Output() onClose = new EventEmitter<void>();
|
||||
|
||||
protected readonly fb = inject(FormBuilder);
|
||||
constructor(private toastService: ToastService) {}
|
||||
|
||||
abstract form: ReturnType<FormBuilder['group']>;
|
||||
defaultValues: Partial<Request> = {};
|
||||
|
||||
abstract submitForm(payload: Request): Subscribable<Response> | void;
|
||||
|
||||
submitLoading = signal(false);
|
||||
|
||||
submit() {
|
||||
this.form.markAllAsTouched();
|
||||
if (this.form.valid) {
|
||||
this.form.disable();
|
||||
this.submitLoading.set(true);
|
||||
this.submitForm(this.form.value as Request)?.subscribe({
|
||||
next: (res) => {
|
||||
this.toastService.success({
|
||||
text: `با موفقیت ایجاد شد`,
|
||||
});
|
||||
this.submitLoading.set(false);
|
||||
this.form.enable();
|
||||
this.form.reset();
|
||||
this.onSubmit.emit(res);
|
||||
},
|
||||
error: () => {
|
||||
this.submitLoading.set(false);
|
||||
this.form.enable();
|
||||
},
|
||||
complete: () => {
|
||||
this.submitLoading.set(false);
|
||||
this.form.enable();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.onClose.emit();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<ng-template #title>
|
||||
<ng-container [ngTemplateOutlet]="header">
|
||||
<div class="flex items-center gap-10 justify-between">
|
||||
<span>{{ cardTitle }}</span>
|
||||
<h5 class="font-bold">{{ cardTitle }}</h5>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<ng-container [ngTemplateOutlet]="moreAction"></ng-container>
|
||||
@if (editable) {
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, ContentChild, EventEmitter, Input, Output, TemplateRef } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
ContentChild,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
signal,
|
||||
TemplateRef,
|
||||
} from '@angular/core';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
import { Card } from 'primeng/card';
|
||||
|
||||
@@ -13,22 +21,30 @@ import { Card } from 'primeng/card';
|
||||
export class AppCardComponent {
|
||||
@Input() cardTitle!: string;
|
||||
@Input() editable: boolean = false;
|
||||
@Input() editMode: boolean = false;
|
||||
|
||||
@Output() onEdit = new EventEmitter<void>();
|
||||
@Input()
|
||||
set editMode(v: boolean) {
|
||||
this.editModeSignal.set(!!v);
|
||||
this.editModeChange.emit(!!v);
|
||||
}
|
||||
get editMode() {
|
||||
return this.editModeSignal();
|
||||
}
|
||||
private editModeSignal = signal(false);
|
||||
@Output() editModeChange = new EventEmitter<boolean>();
|
||||
|
||||
@ContentChild('header', { static: true }) header?: Maybe<TemplateRef<any>>;
|
||||
@ContentChild('moreAction', { static: true }) moreAction?: Maybe<TemplateRef<any>>;
|
||||
|
||||
constructor() {
|
||||
if (this.editable) {
|
||||
if (!this.onEdit) {
|
||||
throw new Error('onEdit output must be bound when editable is true');
|
||||
}
|
||||
}
|
||||
}
|
||||
// constructor() {
|
||||
// if (this.editable) {
|
||||
// if (!this.ed) {
|
||||
// throw new Error('onEdit output must be bound when editable is true');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
onEditClick() {
|
||||
this.onEdit.emit();
|
||||
this.editModeChange.emit(!this.editMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<p-table
|
||||
stripedRows
|
||||
[value]="items"
|
||||
[loading]="loading"
|
||||
showGridlines
|
||||
tableStyleClass="table-fixed border-collapse"
|
||||
scrollable
|
||||
>
|
||||
<ng-template #header>
|
||||
<tr>
|
||||
<th rowspan="2" [style]="{ textAlign: 'center', width: '4rem' }">ردیف</th>
|
||||
<th rowspan="2" [style]="{ textAlign: 'center', width: '8rem' }">تاریخ</th>
|
||||
<th rowspan="2" [style]="{ textAlign: 'center', width: '12rem' }">شرح</th>
|
||||
<th rowspan="2" [style]="{ textAlign: 'center', width: '6rem' }">شماره</th>
|
||||
<th rowspan="2" [style]="{ textAlign: 'center', minWidth: '14rem', width: '14rem' }">طرف حساب</th>
|
||||
<th rowspan="2" [style]="{ textAlign: 'center', width: '12rem' }">انبار</th>
|
||||
<th colspan="2" class="text-center!" [style]="{ width: '15rem' }">ورودی</th>
|
||||
<th colspan="2" class="text-center!" [style]="{ width: '15rem' }">خروجی</th>
|
||||
<th colspan="1" class="text-center!" [style]="{ width: '5rem' }">مانده</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th [style]="{ textAlign: 'center', width: '5rem' }">تعداد</th>
|
||||
<th [style]="{ textAlign: 'center', width: '10rem' }">فی</th>
|
||||
<th [style]="{ textAlign: 'center', width: '5rem' }">تعداد</th>
|
||||
<th [style]="{ textAlign: 'center', width: '10rem' }">فی</th>
|
||||
<th [style]="{ textAlign: 'center', width: '5rem' }">تعداد</th>
|
||||
<!-- <th [style]="{ textAlign: 'center', width: '10rem' }">فی</th>
|
||||
<th [style]="{ textAlign: 'center', width: '10rem' }">مجموع قیمت</th> -->
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #body let-item let-i="rowIndex">
|
||||
<tr>
|
||||
<td class="text-center!">{{ i + 1 }}</td>
|
||||
<td class="text-center!" [jalaliDate]="item.createdAt"></td>
|
||||
<td class="text-center!">
|
||||
<catalog-movement-reference-tag [type]="item.referenceType" [movementType]="item.type" />
|
||||
</td>
|
||||
<td class="text-center!">{{ item.referenceId || "-" }}</td>
|
||||
<td class="text-center!">{{ item.supplier?.name || "-" }}</td>
|
||||
<td class="text-center!">{{ item.inventory.name || "-" }}</td>
|
||||
<td class="text-center!">
|
||||
{{ item.type === "IN" ? item.quantity : 0 }}
|
||||
</td>
|
||||
<td class="text-center!">
|
||||
@if (item.type === "IN") {
|
||||
<span [appPriceMask]="item.unitPrice"></span>
|
||||
} @else {
|
||||
0
|
||||
}
|
||||
</td>
|
||||
<td class="text-center!">
|
||||
{{ item.type === "OUT" ? item.quantity : 0 }}
|
||||
</td>
|
||||
<td class="text-center!">
|
||||
@if (item.type === "OUT") {
|
||||
<span [appPriceMask]="item.unitPrice"></span>
|
||||
} @else {
|
||||
0
|
||||
}
|
||||
</td>
|
||||
<td class="text-center!">{{ item.remainedInStock }}</td>
|
||||
<!-- <td class="text-center!"><span [appPriceMask]="item.unitPrice"></span></td>
|
||||
<td class="text-center!"><span [appPriceMask]="item.totalCost"></span></td> -->
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="emptymessage">
|
||||
<tr>
|
||||
<td [attr.colspan]="11">
|
||||
<uikit-empty-state
|
||||
[title]="'هیچ رکوردی یافت نشد'"
|
||||
[description]="'برای این بازه زمانی و فیلترهای انتخاب شده، رکوردی وجود ندارد.'"
|
||||
></uikit-empty-state>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
@@ -1,24 +0,0 @@
|
||||
import { CatalogMovementReferenceTagComponent } from '@/shared/catalog/movementReferenceTypes';
|
||||
import { JalaliDateDirective, PriceMaskDirective } from '@/shared/directives';
|
||||
import { UikitEmptyStateComponent } from '@/uikit';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { ICardexItem } from './type';
|
||||
|
||||
@Component({
|
||||
selector: 'shared-cardex',
|
||||
templateUrl: './cardex.component.html',
|
||||
imports: [
|
||||
TableModule,
|
||||
JalaliDateDirective,
|
||||
CatalogMovementReferenceTagComponent,
|
||||
PriceMaskDirective,
|
||||
UikitEmptyStateComponent,
|
||||
],
|
||||
hostDirectives: [PriceMaskDirective],
|
||||
})
|
||||
export class CardexComponent {
|
||||
@Input() items: ICardexItem[] = [];
|
||||
@Input() loading: boolean = false;
|
||||
constructor() {}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import { IInventoryStockMovementResponse } from '@/modules/inventories/models';
|
||||
|
||||
export interface ICardexItem extends IInventoryStockMovementResponse {}
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './abstract-select.component';
|
||||
// export * from './abstract-select.component';
|
||||
export * from './breadcrumb.component';
|
||||
export * from './card-data.component';
|
||||
export * from './inlineConfirmation/inline-confirmation.component';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="h-full bg-surface-overlay">
|
||||
<div class="h-full bg-surface-overlay rounded-(--p-card-border-radius) overflow-hidden">
|
||||
<div class="h-full flex flex-col gap-4">
|
||||
<p-table
|
||||
[columns]="columns"
|
||||
|
||||
@@ -5,9 +5,11 @@ import {
|
||||
Component,
|
||||
computed,
|
||||
ContentChild,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
Renderer2,
|
||||
signal,
|
||||
TemplateRef,
|
||||
} from '@angular/core';
|
||||
@@ -32,6 +34,9 @@ export interface IColumn<T = any> {
|
||||
@Component({
|
||||
selector: 'app-page-data-list',
|
||||
templateUrl: './page-data-list.component.html',
|
||||
// host: {
|
||||
// class: 'inline-block w-full',
|
||||
// },
|
||||
imports: [
|
||||
CommonModule,
|
||||
TableActionRowComponent,
|
||||
@@ -46,7 +51,10 @@ export interface IColumn<T = any> {
|
||||
],
|
||||
})
|
||||
export class PageDataListComponent<I> {
|
||||
constructor() {}
|
||||
constructor(
|
||||
private host: ElementRef,
|
||||
private renderer: Renderer2,
|
||||
) {}
|
||||
|
||||
@Input() pageTitle!: string;
|
||||
@Input() addNewCtaLabel?: string;
|
||||
@@ -64,7 +72,8 @@ export class PageDataListComponent<I> {
|
||||
@Input() showDetails: boolean = false;
|
||||
@Input() showAdd: boolean = false;
|
||||
@Input() isFiltered: boolean = false;
|
||||
@Input() fullHeight: boolean = false;
|
||||
@Input() fullHeight?: boolean = false;
|
||||
@Input() height: string = '500px';
|
||||
|
||||
@ContentChild('filter', { static: true }) filter!: TemplateRef<any> | null;
|
||||
@ContentChild('caption', { static: true }) caption!: TemplateRef<any> | null;
|
||||
@@ -78,8 +87,15 @@ export class PageDataListComponent<I> {
|
||||
filterDrawerVisible = signal<boolean>(false);
|
||||
|
||||
ngOnInit() {
|
||||
console.log(this.fullHeight);
|
||||
console.log(this.height);
|
||||
|
||||
this.renderer.setStyle(
|
||||
this.host.nativeElement,
|
||||
'height',
|
||||
this.fullHeight ? '100cqmin' : this.height,
|
||||
);
|
||||
// if (this.fullHeight) {
|
||||
// this.renderer.setStyle(this.host.nativeElement, 'height', '100cqmin');
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@if (showPaymentForm()) {
|
||||
<!-- @if (showPaymentForm()) {
|
||||
<app-supplier-invoice-pay-form
|
||||
[(visible)]="showPaymentForm"
|
||||
[debtAmount]="purchaseReceipt.totalAmount"
|
||||
@@ -7,4 +7,4 @@
|
||||
[invoiceId]="purchaseReceipt.id.toString()"
|
||||
(onSubmit)="submitted()"
|
||||
/>
|
||||
}
|
||||
} -->
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
import { ToastService } from '@/core/services/toast.service';
|
||||
import { SupplierInvoicePayFormComponent } from '@/modules/suppliers/components/invoices/pay-form.component';
|
||||
import { Component, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||
import { IPurchaseReceiptResponse } from '../../../modules/purchases/models';
|
||||
import { ConfirmationDialogService } from '../confirmationDialog/confirmation-dialog.service';
|
||||
// import { ToastService } from '@/core/services/toast.service';
|
||||
// import { SupplierInvoicePayFormComponent } from '@/modules/suppliers/components/invoices/pay-form.component';
|
||||
// import { Component, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||
// import { IPurchaseReceiptResponse } from '../../../modules/purchases/models';
|
||||
// import { ConfirmationDialogService } from '../confirmationDialog/confirmation-dialog.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-purchase-receipt-payment-wrapper',
|
||||
templateUrl: './wrapper.component.html',
|
||||
imports: [SupplierInvoicePayFormComponent],
|
||||
})
|
||||
export class PurchaseReceiptPaymentWrapperComponent {
|
||||
@Input() purchaseReceipt!: IPurchaseReceiptResponse;
|
||||
// @Component({
|
||||
// selector: 'app-purchase-receipt-payment-wrapper',
|
||||
// templateUrl: './wrapper.component.html',
|
||||
// imports: [SupplierInvoicePayFormComponent],
|
||||
// })
|
||||
// export class PurchaseReceiptPaymentWrapperComponent {
|
||||
// @Input() purchaseReceipt!: IPurchaseReceiptResponse;
|
||||
|
||||
@Output() onSubmit = new EventEmitter<void>();
|
||||
// @Output() onSubmit = new EventEmitter<void>();
|
||||
|
||||
showPaymentForm = signal(false);
|
||||
constructor(
|
||||
private confirmService: ConfirmationDialogService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
setTimeout(() => {
|
||||
this.showConfirm();
|
||||
}, 1);
|
||||
}
|
||||
// showPaymentForm = signal(false);
|
||||
// constructor(
|
||||
// private confirmService: ConfirmationDialogService,
|
||||
// private toastService: ToastService,
|
||||
// ) {
|
||||
// setTimeout(() => {
|
||||
// this.showConfirm();
|
||||
// }, 1);
|
||||
// }
|
||||
|
||||
showConfirm() {
|
||||
this.confirmService.confirm({
|
||||
message: 'آیا پرداخت فاکتور انجام شده است؟',
|
||||
header: 'وضعیت پرداخت فاکتور',
|
||||
acceptLabel: 'بله',
|
||||
rejectLabel: 'خیر',
|
||||
accept: () => {
|
||||
this.toPaymentForm();
|
||||
},
|
||||
reject: () => {
|
||||
this.toastService.info({
|
||||
text: 'میتوانید از طریق منوی پرداخت فاکتور، در آینده اقدام به پرداخت نمایید.',
|
||||
title: 'پرداخت فاکتور انجام نشد',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
// showConfirm() {
|
||||
// this.confirmService.confirm({
|
||||
// message: 'آیا پرداخت فاکتور انجام شده است؟',
|
||||
// header: 'وضعیت پرداخت فاکتور',
|
||||
// acceptLabel: 'بله',
|
||||
// rejectLabel: 'خیر',
|
||||
// accept: () => {
|
||||
// this.toPaymentForm();
|
||||
// },
|
||||
// reject: () => {
|
||||
// this.toastService.info({
|
||||
// text: 'میتوانید از طریق منوی پرداخت فاکتور، در آینده اقدام به پرداخت نمایید.',
|
||||
// title: 'پرداخت فاکتور انجام نشد',
|
||||
// });
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
|
||||
submitted() {
|
||||
console.log('submitted');
|
||||
// submitted() {
|
||||
// console.log('submitted');
|
||||
|
||||
this.showPaymentForm.set(false);
|
||||
this.onSubmit.emit();
|
||||
}
|
||||
// this.showPaymentForm.set(false);
|
||||
// this.onSubmit.emit();
|
||||
// }
|
||||
|
||||
toPaymentForm() {
|
||||
this.showPaymentForm.set(true);
|
||||
}
|
||||
}
|
||||
// toPaymentForm() {
|
||||
// this.showPaymentForm.set(true);
|
||||
// }
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user