create consumer domain until pos list

This commit is contained in:
2026-03-16 17:56:22 +03:30
parent 3c9f6eed1d
commit 739aef67a3
67 changed files with 1638 additions and 1 deletions
@@ -7,6 +7,16 @@ export const CONSUMER_MENU_ITEMS = [
icon: 'pi pi-fw pi-home',
routerLink: ['/'],
},
{
label: 'حساب‌های کاربری',
icon: 'pi pi-fw pi-home',
routerLink: ['/consumer/accounts'],
},
{
label: 'فعالیت‌های اقتصادی',
icon: 'pi pi-fw pi-home',
routerLink: ['/consumer/business_activities'],
},
],
},
] as MenuItem[];
@@ -0,0 +1,41 @@
<p-dialog
header="ویرایش گذرواژه"
[(visible)]="visible"
[modal]="true"
[style]="{ width: '500px' }"
[closable]="true"
(onHide)="close()"
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<uikit-field label="رمز عبور" class="" [control]="form.controls.password">
<p-password
id="password1"
name="password"
formControlName="password"
autocomplete="password"
[toggleMask]="true"
[fluid]="true"
[feedback]="false"
[invalid]="form.controls.password.touched && form.controls.password.invalid"
/>
<span class="text-xs mt-1 text-muted-color">
رمز باید حداقل ۸ کاراکتر بوده و شامل حداقل یک حرف بزرگ، یک حرف کوچک، یک عدد و یک کاراکتر ویژه باشد.
</span>
</uikit-field>
<uikit-field label="تکرار رمز عبور" class="" [control]="form.controls.confirmPassword">
<p-password
id="confirmPassword"
name="confirmPassword"
formControlName="confirmPassword"
autocomplete="new-password"
[toggleMask]="true"
[fluid]="true"
[feedback]="false"
[invalid]="form.controls.confirmPassword.touched && form.controls.confirmPassword.invalid"
/>
</uikit-field>
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form>
</p-dialog>
@@ -0,0 +1,40 @@
import { MustMatch, password } from '@/core/validators';
import { AbstractFormDialog } from '@/shared/abstractClasses';
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
import { UikitFieldComponent } from '@/uikit';
import { Component, inject, Input } from '@angular/core';
import { ReactiveFormsModule, Validators } from '@angular/forms';
import { Dialog } from 'primeng/dialog';
import { Password } from 'primeng/password';
import { IAccountRequest, IAccountResponse } from '../models';
import { AccountsService } from '../services/main.service';
@Component({
selector: 'account-password-form',
templateUrl: './form.component.html',
imports: [ReactiveFormsModule, Dialog, FormFooterActionsComponent, UikitFieldComponent, Password],
})
export class ConsumerAccountPasswordFormComponent extends AbstractFormDialog<
IAccountRequest,
IAccountResponse
> {
@Input({ required: true }) accountId!: string;
private service = inject(AccountsService);
form = this.fb.group(
{
password: ['', [Validators.required, password()]],
confirmPassword: ['', [Validators.required]],
},
{
validators: [MustMatch('password', 'confirmPassword')],
},
);
override submitForm(payload: IAccountRequest) {
return this.service.update(this.accountId, payload);
// @ts-ignore
// const { confirmPassword, ...rest } = payload;
// return this.service.create(rest);
}
}
@@ -0,0 +1,6 @@
const baseUrl = '/api/v1/consumer/accounts';
export const CONSUMERS_API_ROUTES = {
list: () => `${baseUrl}`,
single: (id: string) => `${baseUrl}/${id}`,
};
@@ -0,0 +1,2 @@
export * from './apiRoutes';
export * from './routes';
@@ -0,0 +1,27 @@
import { NamedRoutes } from '@/core';
import { Routes } from '@angular/router';
export type TConsumerAccountsRouteNames = 'accounts' | 'account';
export const consumerAccountsNamedRoutes: NamedRoutes<TConsumerAccountsRouteNames> = {
accounts: {
path: 'accounts',
loadComponent: () =>
import('../../views/list.component').then((m) => m.ConsumerAccountsComponent),
meta: {
title: 'حساب‌های کاربری',
pagePath: () => '/consumer/accounts',
},
},
account: {
path: 'accounts/:accountId',
loadComponent: () =>
import('../../views/single.component').then((m) => m.ConsumerAccountComponent),
meta: {
title: 'حساب کاربری',
pagePath: (accountId: string) => `/consumer/accounts/${accountId}`,
},
},
};
export const CONSUMER_ACCOUNTS_ROUTES: Routes = Object.values(consumerAccountsNamedRoutes);
@@ -0,0 +1 @@
export * from './io';
@@ -0,0 +1,13 @@
export interface IAccountRawResponse {
id: string;
name: string;
}
export interface IAccountResponse extends IAccountRawResponse {}
export interface IAccountRequest {
name: string;
}
export interface IAccountPasswordRequest {
password: string;
}
@@ -0,0 +1,24 @@
import { IPaginatedResponse } from '@/core/models/service.model';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { CONSUMERS_API_ROUTES as CONSUMER_ACCOUNTS_API_ROUTES } from '../constants';
import { IAccountRawResponse, IAccountRequest, IAccountResponse } from '../models';
@Injectable({ providedIn: 'root' })
export class AccountsService {
constructor(private http: HttpClient) {}
private apiRoutes = CONSUMER_ACCOUNTS_API_ROUTES;
getAll(): Observable<IPaginatedResponse<IAccountResponse>> {
return this.http.get<IPaginatedResponse<IAccountRawResponse>>(this.apiRoutes.list());
}
getSingle(accountId: string): Observable<IAccountResponse> {
return this.http.get<IAccountRawResponse>(this.apiRoutes.single(accountId));
}
update(accountId: string, userData: IAccountRequest): Observable<IAccountResponse> {
return this.http.patch<IAccountResponse>(this.apiRoutes.single(accountId), userData);
}
}
@@ -0,0 +1,2 @@
export * from './list.component';
export * from './single.component';
@@ -0,0 +1,17 @@
<app-page-data-list
[pageTitle]="'لیست حساب‌های کاربری'"
[columns]="columns"
emptyPlaceholderTitle="حساب‌ کاربری‌ای یافت نشد"
[items]="items()"
[loading]="loading()"
/>
@if (selectedItemForEdit()) {
<account-password-form
[(visible)]="visibleForm"
[editMode]="editMode()"
[accountId]="selectedItemForEdit()?.id!"
[initialValues]="selectedItemForEdit() || undefined"
(onSubmit)="refresh()"
/>
}
@@ -0,0 +1,34 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { Component, inject } from '@angular/core';
import { ConsumerAccountPasswordFormComponent } from '../components/form.component';
import { IAccountResponse } from '../models';
import { AccountsService } from '../services/main.service';
@Component({
selector: 'consumer-accounts',
templateUrl: './list.component.html',
imports: [PageDataListComponent, ConsumerAccountPasswordFormComponent],
})
export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
private readonly service = inject(AccountsService);
override setColumns(): void {
this.columns = [
{ field: 'id', header: 'شناسه' },
{ field: 'username', header: 'نام کاربری', type: 'nested', nestedPath: 'account.username' },
{ field: 'role', header: 'نقش' },
{ field: 'status', header: 'وضعیت', type: 'nested', nestedPath: 'account.status' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
}
override getDataRequest() {
return this.service.getAll();
}
}
@@ -0,0 +1 @@
<div class=""></div>
@@ -0,0 +1,9 @@
import { Component } from '@angular/core';
@Component({
selector: 'consumer-account',
templateUrl: './single.component.html',
})
export class ConsumerAccountComponent {
constructor() {}
}
@@ -0,0 +1,15 @@
<p-dialog
[header]="preparedTitle"
[(visible)]="visible"
[modal]="true"
[style]="{ width: '500px' }"
[closable]="true"
(onHide)="close()"
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<app-input label="عنوان" [control]="form.controls.name" name="name" />
<app-input label="کد مالیاتی" [control]="form.controls.tax_id" name="tax_id" />
<app-input label="آدرس" [control]="form.controls.address" name="address" />
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form>
</p-dialog>
@@ -0,0 +1,47 @@
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
import { AbstractFormDialog } from '@/shared/abstractClasses';
import { InputComponent } from '@/shared/components';
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
import { Component, inject, Input } from '@angular/core';
import { ReactiveFormsModule, Validators } from '@angular/forms';
import { Dialog } from 'primeng/dialog';
import { IComplexRequest, IComplexResponse } from '../../models';
import { ConsumerComplexesService } from '../../services/complexes.service';
@Component({
selector: 'consumer-complex-form',
templateUrl: './form.component.html',
imports: [ReactiveFormsModule, Dialog, InputComponent, FormFooterActionsComponent],
})
export class ConsumerComplexFormComponent extends AbstractFormDialog<
IComplexRequest,
IComplexResponse
> {
private readonly service = inject(ConsumerComplexesService);
@Input({ required: true }) businessActivityId!: string;
@Input({ required: true }) complexId!: string;
initForm = () => {
return this.fb.group({
name: [this.initialValues?.name || '', [Validators.required]],
tax_id: [this.initialValues?.tax_id || '', [Validators.required]],
address: [this.initialValues?.address || '', [Validators.required]],
});
};
form = this.initForm();
get preparedTitle() {
return `ویرایش فروشگاه ${this.initialValues?.name}`;
}
override ngOnChanges(): void {
this.form = this.initForm();
}
submitForm() {
const formValue = this.form.value as IComplexRequest;
return this.service.update(this.businessActivityId, this.complexId, formValue);
}
}
@@ -0,0 +1,5 @@
@if (loading()) {
<shared-page-loading />
} @else {
<router-outlet></router-outlet>
}
@@ -0,0 +1,29 @@
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
import pageParamsUtils from '@/utils/page-params.utils';
import { Component, computed, inject } from '@angular/core';
import { ActivatedRoute, RouterOutlet } from '@angular/router';
import { ConsumerComplexStore } from '../../store/complex.store';
@Component({
selector: 'consumer-complex-layout',
templateUrl: './layout.component.html',
imports: [PageLoadingComponent, RouterOutlet],
})
export class ConsumerComplexLayoutComponent {
private readonly store = inject(ConsumerComplexStore);
private readonly route = inject(ActivatedRoute);
readonly loading = computed(() => this.store.loading());
readonly pageParams = computed(() => pageParamsUtils(this.route));
readonly businessId = computed(() => this.pageParams()['businessActivityId']!);
readonly complexId = computed(() => this.pageParams()['complexId']!);
getData() {
this.store.getData(this.businessId(), this.complexId());
}
ngOnInit() {
this.getData();
}
}
@@ -0,0 +1,20 @@
<app-page-data-list
pageTitle="لیست فروشگاه‌ها"
[columns]="columns"
emptyPlaceholderTitle="فروشگاهی یافت نشد."
[items]="items()"
[loading]="loading()"
[showDetails]="true"
[showEdit]="true"
(onEdit)="onEditClick($event)"
(onDetails)="toSinglePage($event)"
>
</app-page-data-list>
<consumer-complex-form
[(visible)]="visibleForm"
[editMode]="editMode()"
[businessActivityId]="businessId"
[complexId]="selectedItemForEdit()?.id || ''"
[initialValues]="selectedItemForEdit() || undefined"
(onSubmit)="refresh()"
/>
@@ -0,0 +1,48 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { Component, inject, Input } from '@angular/core';
import { Router } from '@angular/router';
import { consumerComplexesNamedRoutes } from '../../constants/routes/complexes';
import { IComplexResponse } from '../../models';
import { ConsumerComplexesService } from '../../services/complexes.service';
import { ConsumerComplexFormComponent } from './form.component';
@Component({
selector: 'consumer-complex-list',
templateUrl: './list.component.html',
imports: [PageDataListComponent, ConsumerComplexFormComponent],
})
export class ConsumerComplexListComponent extends AbstractList<IComplexResponse> {
@Input({ required: true }) businessId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
{ field: 'id', header: 'شناسه' },
{ field: 'name', header: 'عنوان' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
private readonly service = inject(ConsumerComplexesService);
private readonly router = inject(Router);
override setColumns(): void {
this.columns = this.header;
}
override getDataRequest() {
return this.service.getAll(this.businessId);
}
toSinglePage(item: IComplexResponse) {
this.router.navigateByUrl(
consumerComplexesNamedRoutes.complex.meta.pagePath!(this.businessId, item.id),
);
}
}
@@ -0,0 +1,13 @@
<p-dialog
header="ویرایش فعالیت اقتصادی"
[(visible)]="visible"
[modal]="true"
[style]="{ width: '500px' }"
[closable]="true"
(onHide)="close()"
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<app-input [control]="form.controls.name" name="name" label="عنوان" />
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form>
</p-dialog>
@@ -0,0 +1,29 @@
import { AbstractFormDialog } from '@/shared/abstractClasses';
import { InputComponent } from '@/shared/components';
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
import { Component, inject, Input } from '@angular/core';
import { ReactiveFormsModule, Validators } from '@angular/forms';
import { Dialog } from 'primeng/dialog';
import { IBusinessActivityRequest, IBusinessActivityResponse } from '../models';
import { BusinessActivitiesService } from '../services/main.service';
@Component({
selector: 'consumer-businessActivity-form',
templateUrl: './form.component.html',
imports: [ReactiveFormsModule, Dialog, FormFooterActionsComponent, InputComponent],
})
export class ConsumerBusinessActivityFormComponent extends AbstractFormDialog<
IBusinessActivityRequest,
IBusinessActivityResponse
> {
@Input({ required: true }) businessId!: string;
private service = inject(BusinessActivitiesService);
form = this.fb.group({
name: [this.initialValues?.name, [Validators.required]],
});
override submitForm(payload: IBusinessActivityRequest) {
return this.service.update(this.businessId, payload);
}
}
@@ -0,0 +1,5 @@
@if (loading()) {
<shared-page-loading />
} @else {
<router-outlet></router-outlet>
}
@@ -0,0 +1,26 @@
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute, RouterOutlet } from '@angular/router';
import { BusinessActivityStore } from '../store/businessActivity.store';
@Component({
selector: 'businessActivity-layout',
templateUrl: './layout.component.html',
imports: [PageLoadingComponent, RouterOutlet],
})
export class BusinessActivityLayoutComponent {
private readonly route = inject(ActivatedRoute);
private readonly store = inject(BusinessActivityStore);
readonly businessId = signal<string>(this.route.snapshot.paramMap.get('businessActivityId')!);
readonly loading = computed(() => this.store.loading());
getData() {
this.store.getData(this.businessId());
}
ngOnInit() {
this.getData();
}
}
@@ -0,0 +1,18 @@
<app-page-data-list
pageTitle="لیست فعالیت‌های اقتصادی"
[columns]="columns"
[items]="items()"
[loading]="loading()"
[showEdit]="true"
[showDetails]="true"
(onEdit)="onEditClick($event)"
(onDetails)="toSinglePage($event)"
>
</app-page-data-list>
<consumer-businessActivity-form
[(visible)]="visibleForm"
[editMode]="editMode()"
[businessId]="selectedItemForEdit()?.id || ''"
[initialValues]="selectedItemForEdit() || undefined"
(onSubmit)="refresh()"
/>
@@ -0,0 +1,48 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { Component, inject, Input } from '@angular/core';
import { Router } from '@angular/router';
import { consumerBusinessActivityNamedRoutes } from '../constants';
import { IBusinessActivityResponse } from '../models';
import { BusinessActivitiesService } from '../services/main.service';
import { ConsumerBusinessActivityFormComponent } from './form.component';
@Component({
selector: 'consumer-businessActivity-list',
templateUrl: './list.component.html',
imports: [PageDataListComponent, ConsumerBusinessActivityFormComponent],
})
export class ConsumerBusinessActivityListComponent extends AbstractList<IBusinessActivityResponse> {
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
{ field: 'id', header: 'شناسه' },
{ field: 'name', header: 'عنوان' },
{ field: 'guild', header: 'صنف', type: 'nested', nestedPath: 'name' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
private readonly service = inject(BusinessActivitiesService);
private readonly router = inject(Router);
override setColumns(): void {
this.columns = this.header;
}
override getDataRequest() {
return this.service.getAll();
}
toSinglePage(item: IBusinessActivityResponse) {
this.router.navigateByUrl(
consumerBusinessActivityNamedRoutes.businessActivity.meta.pagePath!(item.id),
);
}
}
@@ -0,0 +1,20 @@
<p-dialog
[header]="preparedTitle"
[(visible)]="visible"
[modal]="true"
[style]="{ width: '500px' }"
[closable]="true"
(onHide)="close()"
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<app-input label="عنوان" [control]="form.controls.name" name="name" />
<app-input label="سریال دستگاه" [control]="form.controls.serial" name="serial" />
<!-- <app-input label="مدل دستگاه" [control]="form.controls.model" name="model" /> -->
<app-enum-select [control]="form.controls.pos_type" type="posType" name="pos_type" />
@if (form.controls.pos_type.value === "PSP") {
<catalog-device-select [control]="form.controls.device_id" />
<catalog-provider-select [control]="form.controls.provider_id" />
}
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form>
</p-dialog>
@@ -0,0 +1,83 @@
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
import { AbstractFormDialog } from '@/shared/abstractClasses';
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
import { CatalogProviderSelectComponent } from '@/shared/catalog';
import { CatalogDeviceSelectComponent } from '@/shared/catalog/devices';
import { InputComponent } from '@/shared/components';
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
import { Component, inject, Input } from '@angular/core';
import { ReactiveFormsModule, Validators } from '@angular/forms';
import { Dialog } from 'primeng/dialog';
import { IPosRequest, IPosResponse } from '../../models';
import { ConsumerPosesService } from '../../services/poses.service';
@Component({
selector: 'consumer-pos-form',
templateUrl: './form.component.html',
imports: [
ReactiveFormsModule,
Dialog,
InputComponent,
FormFooterActionsComponent,
CatalogDeviceSelectComponent,
CatalogProviderSelectComponent,
EnumSelectComponent,
],
})
export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IPosResponse> {
private readonly service = inject(ConsumerPosesService);
@Input({ required: true }) businessActivityId!: string;
@Input({ required: true }) complexId!: string;
@Input({ required: true }) posId!: string;
initForm = () => {
const form = this.fb.group({
name: [this.initialValues?.name || '', [Validators.required]],
serial: [this.initialValues?.serial || '', [Validators.required]],
// model: [this.initialValues?.model || '', [Validators.required]],
pos_type: [this.initialValues?.pos_type || '', [Validators.required]],
device_id: [this.initialValues?.device?.id || ''],
provider_id: [this.initialValues?.provider?.id || ''],
});
form.controls.pos_type.valueChanges.subscribe((value) => {
if (value === 'PSP') {
form.addControl(
'device_id',
this.fb.control<string>(this.initialValues?.device?.id ?? '', {
nonNullable: true,
validators: [Validators.required],
}),
);
form.addControl(
'provider_id',
this.fb.control<string>(this.initialValues?.provider?.id ?? '', {
nonNullable: true,
validators: [Validators.required],
}),
);
} else {
// @ts-ignore
form.removeControl('device_id');
// @ts-ignore
form.removeControl('provider_id');
}
});
return form;
};
form = this.initForm();
get preparedTitle() {
return `ویرایش پایانه فروش ${this.initialValues?.name}`;
}
override ngOnChanges(): void {
this.form = this.initForm();
}
submitForm() {
const formValue = this.form.value as IPosRequest;
return this.service.update(this.businessActivityId, this.complexId, this.posId, formValue);
}
}
@@ -0,0 +1,5 @@
@if (loading()) {
<shared-page-loading />
} @else {
<router-outlet></router-outlet>
}
@@ -0,0 +1,30 @@
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
import pageParamsUtils from '@/utils/page-params.utils';
import { Component, computed, inject } from '@angular/core';
import { ActivatedRoute, RouterOutlet } from '@angular/router';
import { PosStore } from '../../store/pos.store';
@Component({
selector: 'superAdmin-consumer-pos-layout',
templateUrl: './layout.component.html',
imports: [PageLoadingComponent, RouterOutlet],
})
export class SuperAdminConsumerPosLayoutComponent {
private readonly store = inject(PosStore);
private readonly route = inject(ActivatedRoute);
readonly loading = computed(() => this.store.loading());
readonly pageParams = computed(() => pageParamsUtils(this.route));
readonly businessId = computed(() => this.pageParams()['businessActivityId']!);
readonly complexId = computed(() => this.pageParams()['complexId']!);
readonly posId = computed(() => this.pageParams()['posId']!);
getData() {
this.store.getData(this.businessId(), this.complexId(), this.posId());
}
ngOnInit() {
this.getData();
}
}
@@ -0,0 +1,21 @@
<app-page-data-list
pageTitle="لیست پایانه‌های فروش"
[columns]="columns"
emptyPlaceholderTitle="پایانه‌ی فروشی یافت نشد."
[items]="items()"
[loading]="loading()"
[showDetails]="true"
[showEdit]="true"
(onEdit)="onEditClick($event)"
(onDetails)="toSinglePage($event)"
>
</app-page-data-list>
<consumer-pos-form
[(visible)]="visibleForm"
[editMode]="editMode()"
[businessActivityId]="businessId"
[complexId]="complexId"
[posId]="selectedItemForEdit()?.id || ''"
[initialValues]="selectedItemForEdit() || undefined"
(onSubmit)="refresh()"
/>
@@ -0,0 +1,54 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { Component, inject, Input } from '@angular/core';
import { Router } from '@angular/router';
import { consumerPosesNamedRoutes } from '../../constants/routes/poses';
import { IPosResponse } from '../../models';
import { ConsumerPosesService } from '../../services/poses.service';
import { ConsumerPosFormComponent } from './form.component';
@Component({
selector: 'consumer-poses-list',
templateUrl: './list.component.html',
imports: [PageDataListComponent, ConsumerPosFormComponent],
})
export class ConsumerPosesComponent extends AbstractList<IPosResponse> {
@Input({ required: true }) businessId!: string;
@Input({ required: true }) complexId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
{ field: 'id', header: 'شناسه' },
{ field: 'name', header: 'عنوان' },
{ field: 'serial', header: 'شماره سریال' },
{ field: 'device', header: 'دستگاه', type: 'nested', nestedPath: 'device.name' },
{ field: 'pos_type', header: 'نوع دستگاه' },
{ field: 'provider', header: 'ارایه‌دهنده', type: 'nested', nestedPath: 'provider.name' },
{ field: 'status', header: 'وضعیت' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
private readonly service = inject(ConsumerPosesService);
private readonly router = inject(Router);
override setColumns(): void {
this.columns = this.header;
}
override getDataRequest() {
return this.service.getAll(this.businessId, this.complexId);
}
toSinglePage(item: IPosResponse) {
this.router.navigateByUrl(
consumerPosesNamedRoutes.pos.meta.pagePath!(this.businessId, this.complexId, item.id),
);
}
}
@@ -0,0 +1,8 @@
const baseUrl = (business_activity_id: string) =>
`/api/v1/consumer/business_activities/${business_activity_id}/complexes`;
export const BUSINESS_ACTIVITY_COMPLEXES_API_ROUTES = {
list: (business_activity_id: string) => `${baseUrl(business_activity_id)}`,
single: (business_activity_id: string, complex_id: string) =>
`${baseUrl(business_activity_id)}/${complex_id}`,
};
@@ -0,0 +1,9 @@
const baseUrl = (business_activity_id: string, complex_id: string) =>
`/api/v1/consumer/business_activities/${business_activity_id}/complexes/${complex_id}/poses`;
export const COMPLEX_POSES_API_ROUTES = {
list: (business_activity_id: string, complex_id: string) =>
`${baseUrl(business_activity_id, complex_id)}`,
single: (business_activity_id: string, complex_id: string, posId: string) =>
`${baseUrl(business_activity_id, complex_id)}/${posId}`,
};
@@ -0,0 +1,6 @@
const baseUrl = '/api/v1/consumer/business_activities';
export const CONSUMER_BUSINESS_ACTIVITIES_API_ROUTES = {
list: () => `${baseUrl}`,
single: (id: string) => `${baseUrl}/${id}`,
};
@@ -0,0 +1,2 @@
export * from './apiRoutes';
export * from './routes';
@@ -0,0 +1,46 @@
import { NamedRoutes } from '@/core';
import { Routes } from '@angular/router';
import { CONSUMER_POSES_ROUTES } from './poses';
export type TComplexesRouteNames = 'complexes' | 'complex';
const baseUrl = (businessId: string) => `/consumer/business_activities/${businessId}/complexes`;
export const consumerComplexesNamedRoutes: NamedRoutes<TComplexesRouteNames> = {
complexes: {
path: 'complexes',
loadComponent: () =>
import('../../views/complexes/list.component').then((m) => m.ConsumerComplexesComponent),
meta: {
title: 'فروشگاه‌ها',
pagePath: (businessId: string) => baseUrl(businessId),
},
},
complex: {
path: 'complexes/:complexId',
loadComponent: () =>
import('../../views/complexes/single.component').then((m) => m.ConsumerComplexComponent),
meta: {
title: 'فروشگاه',
pagePath: (businessId: string, complexId: string) => `${baseUrl(businessId)}/${complexId}`,
},
},
};
export const CONSUMER_COMPLEXES_ROUTES: Routes = [
consumerComplexesNamedRoutes.complexes,
{
path: consumerComplexesNamedRoutes.complex.path,
loadComponent: () =>
import('../../components/complexes/layout.component').then(
(m) => m.ConsumerComplexLayoutComponent,
),
children: [
{
...consumerComplexesNamedRoutes.complex,
path: '',
},
...CONSUMER_POSES_ROUTES,
],
},
];
@@ -0,0 +1,44 @@
import { NamedRoutes } from '@/core';
import { Routes } from '@angular/router';
import { CONSUMER_COMPLEXES_ROUTES } from './complexes';
export type TConsumerBusinessActivityRouteNames = 'businessActivities' | 'businessActivity';
export const consumerBusinessActivityNamedRoutes: NamedRoutes<TConsumerBusinessActivityRouteNames> =
{
businessActivities: {
path: 'business_activities',
loadComponent: () =>
import('../../views/list.component').then((m) => m.ConsumerBusinessActivitiesComponent),
meta: {
title: 'کسب‌و‌کارها',
pagePath: () => '/consumer/business_activities',
},
},
businessActivity: {
path: 'business_activities/:businessActivityId',
loadComponent: () =>
import('../../views/single.component').then((m) => m.ConsumerBusinessActivityComponent),
meta: {
title: 'کسب‌و‌کار',
pagePath: (businessActivityId: string) =>
`/consumer/business_activities/${businessActivityId}`,
},
},
};
export const CONSUMER_BUSINESS_ACTIVITIES_ROUTES: Routes = [
consumerBusinessActivityNamedRoutes.businessActivities,
{
path: consumerBusinessActivityNamedRoutes.businessActivity.path,
loadComponent: () =>
import('../../components/layout.component').then((m) => m.BusinessActivityLayoutComponent),
children: [
{
...consumerBusinessActivityNamedRoutes.businessActivity,
path: '',
},
...CONSUMER_COMPLEXES_ROUTES,
],
},
];
@@ -0,0 +1,48 @@
import { NamedRoutes } from '@/core';
import { Routes } from '@angular/router';
export type TPosesRouteNames = 'poses' | 'pos';
const baseUrl = (businessId: string, complexId: string) =>
`/consumer/business_activities/${businessId}/complexes/${complexId}/poses`;
export const consumerPosesNamedRoutes: NamedRoutes<TPosesRouteNames> = {
poses: {
path: 'poses',
loadComponent: () =>
import('../../views/poses/list.component').then((m) => m.SuperAdminUserPosesComponent),
// @ts-ignore
meta: {
title: 'پایانه‌های فروش',
pagePath: (businessId: string, complexId: string) => baseUrl(businessId, complexId),
},
},
pos: {
path: 'poses/:posId',
loadComponent: () =>
import('../../views/poses/single.component').then((m) => m.SuperAdminUserPosComponent),
// @ts-ignore
meta: {
title: 'پایانه‌ی فروش',
pagePath: (businessId: string, complexId: string, posId: string) =>
`${baseUrl(businessId, complexId)}/${posId}`,
},
},
};
export const CONSUMER_POSES_ROUTES: Routes = [
consumerPosesNamedRoutes.poses,
{
path: consumerPosesNamedRoutes.pos.path,
loadComponent: () =>
import('../../components/poses/layout.component').then(
(m) => m.SuperAdminConsumerPosLayoutComponent,
),
children: [
{
path: '',
loadComponent: consumerPosesNamedRoutes.pos.loadComponent,
},
],
},
];
@@ -0,0 +1,13 @@
export interface IComplexRawResponse {
name: string;
address: string;
tax_id: string;
id: string;
}
export interface IComplexResponse extends IComplexRawResponse {}
export interface IComplexRequest {
name: string;
address: string;
tax_id: string;
}
@@ -0,0 +1,3 @@
export * from './complexes_io';
export * from './io';
export * from './poses_io';
@@ -0,0 +1,12 @@
import ISummary from '@/core/models/summary';
export interface IBusinessActivityRawResponse {
id: string;
name: string;
guild: ISummary;
}
export interface IBusinessActivityResponse extends IBusinessActivityRawResponse {}
export interface IBusinessActivityRequest {
name: string;
}
@@ -0,0 +1,24 @@
import ISummary from '@/core/models/summary';
export interface IPosRawResponse {
id: string;
name: string;
serial: string;
model?: string;
status: string;
pos_type: string;
complex: ISummary;
device?: ISummary;
provider?: ISummary;
}
export interface IPosResponse extends IPosRawResponse {}
export interface IPosRequest {
name: string;
serial: string;
model?: string;
status: string;
pos_type: string;
device_id: string;
provider_id: string;
}
@@ -0,0 +1,33 @@
import { IPaginatedResponse } from '@/core/models/service.model';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { BUSINESS_ACTIVITY_COMPLEXES_API_ROUTES } from '../constants/apiRoutes/businessActivityComplexes';
import { IComplexRawResponse, IComplexRequest, IComplexResponse } from '../models';
@Injectable({ providedIn: 'root' })
export class ConsumerComplexesService {
constructor(private http: HttpClient) {}
private apiRoutes = BUSINESS_ACTIVITY_COMPLEXES_API_ROUTES;
getAll(businessActivityId: string): Observable<IPaginatedResponse<IComplexResponse>> {
return this.http.get<IPaginatedResponse<IComplexRawResponse>>(
this.apiRoutes.list(businessActivityId),
);
}
getSingle(businessActivityId: string, complexId: string): Observable<IComplexResponse> {
return this.http.get<IComplexRawResponse>(this.apiRoutes.single(businessActivityId, complexId));
}
update(
businessActivityId: string,
complexId: string,
data: IComplexRequest,
): Observable<IComplexResponse> {
return this.http.patch<IComplexRawResponse>(
this.apiRoutes.single(businessActivityId, complexId),
data,
);
}
}
@@ -0,0 +1,31 @@
import { IPaginatedResponse } from '@/core/models/service.model';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { CONSUMER_BUSINESS_ACTIVITIES_API_ROUTES } from '../constants';
import {
IBusinessActivityRawResponse,
IBusinessActivityRequest,
IBusinessActivityResponse,
} from '../models';
@Injectable({ providedIn: 'root' })
export class BusinessActivitiesService {
constructor(private http: HttpClient) {}
private apiRoutes = CONSUMER_BUSINESS_ACTIVITIES_API_ROUTES;
getAll(): Observable<IPaginatedResponse<IBusinessActivityResponse>> {
return this.http.get<IPaginatedResponse<IBusinessActivityRawResponse>>(this.apiRoutes.list());
}
getSingle(businessId: string): Observable<IBusinessActivityResponse> {
return this.http.get<IBusinessActivityRawResponse>(this.apiRoutes.single(businessId));
}
update(
businessId: string,
userData: IBusinessActivityRequest,
): Observable<IBusinessActivityResponse> {
return this.http.patch<IBusinessActivityResponse>(this.apiRoutes.single(businessId), userData);
}
}
@@ -0,0 +1,43 @@
import { IPaginatedResponse } from '@/core/models/service.model';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { COMPLEX_POSES_API_ROUTES } from '../constants/apiRoutes/complexPoses';
import { IPosRawResponse, IPosRequest, IPosResponse } from '../models';
@Injectable({ providedIn: 'root' })
export class ConsumerPosesService {
constructor(private http: HttpClient) {}
private apiRoutes = COMPLEX_POSES_API_ROUTES;
getAll(
businessActivityId: string,
complexId: string,
): Observable<IPaginatedResponse<IPosResponse>> {
return this.http.get<IPaginatedResponse<IPosRawResponse>>(
this.apiRoutes.list(businessActivityId, complexId),
);
}
getSingle(
businessActivityId: string,
complexId: string,
posId: string,
): Observable<IPosResponse> {
return this.http.get<IPosRawResponse>(
this.apiRoutes.single(businessActivityId, complexId, posId),
);
}
update(
businessActivityId: string,
complexId: string,
posId: string,
data: IPosRequest,
): Observable<IPosResponse> {
return this.http.patch<IPosRawResponse>(
this.apiRoutes.single(businessActivityId, complexId, posId),
data,
);
}
}
@@ -0,0 +1,81 @@
import { EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize, throwError } from 'rxjs';
import { consumerBusinessActivityNamedRoutes } from '../constants';
import { IBusinessActivityResponse } from '../models';
import { BusinessActivitiesService } from '../services/main.service';
interface BusinessActivityState extends EntityState<IBusinessActivityResponse> {
breadcrumbItems: MenuItem[];
}
@Injectable({
providedIn: 'root',
})
export class BusinessActivityStore extends EntityStore<
IBusinessActivityResponse,
BusinessActivityState
> {
private readonly service = inject(BusinessActivitiesService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
breadcrumbItems: [],
});
}
breadcrumbItems = computed(() => this._state().breadcrumbItems);
private setBreadcrumb(business_id: string) {
this.patchState({
breadcrumbItems: [
{
...consumerBusinessActivityNamedRoutes.businessActivities.meta,
routerLink: consumerBusinessActivityNamedRoutes.businessActivities.meta.pagePath!(),
},
{
title: this.entity()?.name,
routerLink:
consumerBusinessActivityNamedRoutes.businessActivity.meta.pagePath!(business_id),
},
],
});
}
getData(business_id: string) {
this.patchState({ loading: true });
this.service
.getSingle(business_id)
.pipe(
finalize(() => {
this.patchState({ loading: false });
}),
catchError(() => {
this.patchState({
error: '',
});
return throwError('');
}),
)
.subscribe((entity) => {
this.patchState({ entity });
this.setBreadcrumb(business_id);
});
}
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
breadcrumbItems: [],
});
}
}
@@ -0,0 +1,76 @@
import { EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize, throwError } from 'rxjs';
import { consumerComplexesNamedRoutes } from '../constants/routes/complexes';
import { IComplexResponse } from '../models';
import { ConsumerComplexesService } from '../services/complexes.service';
interface ComplexState extends EntityState<IComplexResponse> {
breadcrumbItems: MenuItem[];
}
@Injectable({
providedIn: 'root',
})
export class ConsumerComplexStore extends EntityStore<IComplexResponse, ComplexState> {
private readonly service = inject(ConsumerComplexesService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
breadcrumbItems: [],
});
}
breadcrumbItems = computed(() => this._state().breadcrumbItems);
private setBreadcrumb(businessId: string, complexId: string) {
this.patchState({
breadcrumbItems: [
{
...consumerComplexesNamedRoutes.complexes.meta,
routerLink: consumerComplexesNamedRoutes.complexes.meta.pagePath!(businessId),
},
{
title: this.entity()?.name,
routerLink: consumerComplexesNamedRoutes.complex.meta.pagePath!(businessId, complexId),
},
],
});
}
getData(businessId: string, complexId: string) {
this.patchState({ loading: true });
this.service
.getSingle(businessId, complexId)
.pipe(
finalize(() => {
this.patchState({ loading: false });
}),
catchError(() => {
this.patchState({
error: '',
});
return throwError('');
}),
)
.subscribe((entity) => {
this.patchState({ entity });
this.setBreadcrumb(businessId, complexId);
});
}
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
breadcrumbItems: [],
});
}
}
@@ -0,0 +1,77 @@
import { EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize, throwError } from 'rxjs';
import { consumerPosesNamedRoutes } from '../constants/routes/poses';
import { IPosResponse } from '../models';
import { ConsumerPosesService } from '../services/poses.service';
interface PosState extends EntityState<IPosResponse> {
breadcrumbItems: MenuItem[];
}
@Injectable({
providedIn: 'root',
})
export class PosStore extends EntityStore<IPosResponse, PosState> {
private readonly service = inject(ConsumerPosesService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
breadcrumbItems: [],
});
}
breadcrumbItems = computed(() => this._state().breadcrumbItems);
private setBreadcrumb(businessId: string, complexId: string, posId: string) {
this.patchState({
breadcrumbItems: [
{
...consumerPosesNamedRoutes.poses.meta,
routerLink: consumerPosesNamedRoutes.poses.meta.pagePath!(businessId, complexId),
},
{
title: this.entity()?.name,
routerLink: consumerPosesNamedRoutes.pos.meta.pagePath!(businessId, complexId, posId),
},
],
});
}
getData(businessId: string, complexId: string, posId: string) {
this.patchState({ loading: true });
this.service
.getSingle(businessId, complexId, posId)
.pipe(
finalize(() => {
this.patchState({ loading: false });
}),
catchError(() => {
this.patchState({
error: '',
});
return throwError('');
}),
)
.subscribe((entity) => {
this.patchState({ entity });
this.setBreadcrumb(businessId, complexId, posId);
});
}
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
breadcrumbItems: [],
});
}
}
@@ -0,0 +1 @@
export * from './list.component';
@@ -0,0 +1 @@
<consumer-complex-list [businessId]="businessId()" />
@@ -0,0 +1,36 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { BreadcrumbService } from '@/core/services';
import pageParamsUtils from '@/utils/page-params.utils';
import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ConsumerComplexListComponent } from '../../components/complexes/list.component';
import { consumerComplexesNamedRoutes } from '../../constants/routes/complexes';
import { BusinessActivityStore } from '../../store/businessActivity.store';
@Component({
selector: 'superAdmin-user-complexes',
templateUrl: './list.component.html',
imports: [ConsumerComplexListComponent],
})
export class ConsumerComplexesComponent {
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly businessStore = inject(BusinessActivityStore);
pageParams = computed(() => pageParamsUtils(this.route));
businessId = signal<string>(this.pageParams()['businessActivityId']);
ngAfterViewInit() {
this.setBreadcrumb();
}
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.businessStore.breadcrumbItems(),
{
title: consumerComplexesNamedRoutes.complexes.meta.title,
routerLink: consumerComplexesNamedRoutes.complexes.meta.pagePath!(this.businessId()),
},
]);
}
}
@@ -0,0 +1,22 @@
<div class="flex flex-col gap-6">
<app-card-data cardTitle="اطلاعات فروشگاه" [editable]="true" [(editMode)]="editMode">
<div class="flex flex-col gap-4">
<div class="grid grid-cols-3 gap-4 items-center">
<app-key-value label="عنوان" [value]="complex()?.name" />
<app-key-value label="کد مالیاتی" [value]="complex()?.tax_id" />
<app-key-value label="آدرس" [value]="complex()?.address" />
</div>
</div>
</app-card-data>
<consumer-poses-list [businessId]="businessId()" [complexId]="complexId()" />
<consumer-complex-form
[(visible)]="editMode"
[editMode]="true"
[businessActivityId]="businessId()"
[complexId]="complexId()"
[initialValues]="complex() || undefined"
(onSubmit)="getData()"
/>
</div>
@@ -0,0 +1,55 @@
import { BreadcrumbService } from '@/core/services';
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
import pageParamsUtils from '@/utils/page-params.utils';
import { Component, computed, effect, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ConsumerComplexFormComponent } from '../../components/complexes/form.component';
import { ConsumerPosesComponent } from '../../components/poses/list.component';
import { BusinessActivityStore } from '../../store/businessActivity.store';
import { ConsumerComplexStore } from '../../store/complex.store';
@Component({
selector: 'consumer-complex',
templateUrl: './single.component.html',
imports: [
AppCardComponent,
KeyValueComponent,
ConsumerComplexFormComponent,
ConsumerPosesComponent,
],
})
export class ConsumerComplexComponent {
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly store = inject(ConsumerComplexStore);
private readonly businessStore = inject(BusinessActivityStore);
pageParams = computed(() => pageParamsUtils(this.route));
readonly businessId = signal<string>(this.pageParams()['businessActivityId']!);
readonly complexId = signal<string>(this.pageParams()['complexId']!);
editMode = signal<boolean>(false);
readonly loading = computed(() => this.store.loading());
readonly complex = computed(() => this.store.entity());
constructor() {
effect(() => {
if (this.complex()?.id) {
this.setBreadcrumb();
}
});
}
getData() {
this.store.getData(this.businessId(), this.complexId());
}
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.businessStore.breadcrumbItems(),
...this.store.breadcrumbItems(),
]);
}
}
@@ -0,0 +1,2 @@
export * from './list.component';
export * from './single.component';
@@ -0,0 +1 @@
<consumer-businessActivity-list />
@@ -0,0 +1,31 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { Component, inject } from '@angular/core';
import { ConsumerBusinessActivityListComponent } from '../components/list.component';
import { IBusinessActivityResponse } from '../models';
import { BusinessActivitiesService } from '../services/main.service';
@Component({
selector: 'consumer-businessActivities',
templateUrl: './list.component.html',
imports: [ConsumerBusinessActivityListComponent],
})
export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessActivityResponse> {
private readonly service = inject(BusinessActivitiesService);
override setColumns(): void {
this.columns = [
{ field: 'id', header: 'شناسه' },
{ field: 'name', header: 'عنوان' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
}
override getDataRequest() {
return this.service.getAll();
}
}
@@ -0,0 +1 @@
export * from './list.component';
@@ -0,0 +1 @@
<consumer-poses-list [businessId]="businessId()" [complexId]="complexId()" />
@@ -0,0 +1,43 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { BreadcrumbService } from '@/core/services';
import pageParamsUtils from '@/utils/page-params.utils';
import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ConsumerPosesComponent } from '../../components/poses/list.component';
import { consumerPosesNamedRoutes } from '../../constants/routes/poses';
import { BusinessActivityStore } from '../../store/businessActivity.store';
import { ConsumerComplexStore } from '../../store/complex.store';
@Component({
selector: 'superAdmin-user-poses',
templateUrl: './list.component.html',
imports: [ConsumerPosesComponent],
})
export class SuperAdminUserPosesComponent {
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly businessStore = inject(BusinessActivityStore);
private readonly complexStore = inject(ConsumerComplexStore);
pageParams = computed(() => pageParamsUtils(this.route));
businessId = signal<string>(this.pageParams()['businessActivityId']);
complexId = signal<string>(this.pageParams()['complexId']);
ngOnInit() {
this.setBreadcrumb();
}
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.businessStore.breadcrumbItems(),
...this.complexStore.breadcrumbItems(),
{
title: consumerPosesNamedRoutes.poses.meta.title,
routerLink: consumerPosesNamedRoutes.poses.meta.pagePath!(
this.businessId(),
this.complexId(),
),
},
]);
}
}
@@ -0,0 +1,19 @@
<div class="flex flex-col gap-6">
<app-card-data cardTitle="اطلاعات پایانه‌ی فروش" [editable]="true" [(editMode)]="editMode">
<div class="flex flex-col gap-4">
<div class="grid grid-cols-3 gap-4 items-center">
<app-key-value label="عنوان" [value]="pos()?.name" />
</div>
</div>
</app-card-data>
<consumer-pos-form
[(visible)]="editMode"
[editMode]="true"
[businessActivityId]="businessId()"
[complexId]="complexId()"
[posId]="posId()"
[initialValues]="pos() || undefined"
(onSubmit)="getData()"
/>
</div>
@@ -0,0 +1,52 @@
import { BreadcrumbService } from '@/core/services';
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
import pageParamsUtils from '@/utils/page-params.utils';
import { Component, computed, effect, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ConsumerPosFormComponent } from '../../components/poses/form.component';
import { BusinessActivityStore } from '../../store/businessActivity.store';
import { ConsumerComplexStore } from '../../store/complex.store';
import { PosStore } from '../../store/pos.store';
@Component({
selector: 'superAdmin-user-pos',
templateUrl: './single.component.html',
imports: [AppCardComponent, KeyValueComponent, ConsumerPosFormComponent],
})
export class SuperAdminUserPosComponent {
private readonly businessStore = inject(BusinessActivityStore);
private readonly complexStore = inject(ConsumerComplexStore);
private readonly store = inject(PosStore);
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
pageParams = computed(() => pageParamsUtils(this.route));
readonly businessId = signal<string>(this.pageParams()['businessActivityId']!);
readonly complexId = signal<string>(this.pageParams()['complexId']!);
readonly posId = signal<string>(this.pageParams()['posId']!);
editMode = signal<boolean>(false);
constructor() {
effect(() => {
if (this.pos()?.id) {
this.setBreadcrumb();
}
});
}
readonly loading = computed(() => this.store.loading());
readonly pos = computed(() => this.store.entity());
getData() {
this.store.getData(this.businessId(), this.complexId(), this.posId());
}
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.businessStore.breadcrumbItems(),
...this.complexStore.breadcrumbItems(),
...this.store.breadcrumbItems(),
]);
}
}
@@ -0,0 +1,21 @@
<div class="flex flex-col gap-6">
<app-card-data cardTitle="اطلاعات فعالیت اقتصادی" [editable]="true" [(editMode)]="editMode">
<ng-template #moreAction> </ng-template>
<div class="flex flex-col gap-4">
<div class="grid grid-cols-3 gap-4 items-center">
<app-key-value label="عنوان" [value]="business()?.name" />
<app-key-value label="صنف" [value]="business()?.guild?.name" />
</div>
</div>
</app-card-data>
<consumer-complex-list [businessId]="businessId()" />
<consumer-businessActivity-form
[(visible)]="editMode"
[editMode]="true"
[businessId]="businessId()"
[initialValues]="business() || undefined"
(onSubmit)="getData()"
/>
</div>
@@ -0,0 +1,46 @@
import { BreadcrumbService } from '@/core/services';
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
import { Component, computed, effect, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ConsumerComplexListComponent } from '../components/complexes/list.component';
import { ConsumerBusinessActivityFormComponent } from '../components/form.component';
import { BusinessActivityStore } from '../store/businessActivity.store';
@Component({
selector: 'business-businessActivity',
templateUrl: './single.component.html',
imports: [
AppCardComponent,
KeyValueComponent,
ConsumerBusinessActivityFormComponent,
ConsumerComplexListComponent,
],
})
export class ConsumerBusinessActivityComponent {
private readonly store = inject(BusinessActivityStore);
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
readonly businessId = signal<string>(this.route.snapshot.paramMap.get('businessActivityId')!);
editMode = signal<boolean>(false);
readonly loading = computed(() => this.store.loading());
readonly business = computed(() => this.store.entity());
readonly businessBreadcrumb = computed(() => this.store.breadcrumbItems());
constructor() {
effect(() => {
if (this.business()?.id) {
this.setBreadcrumb();
}
});
}
getData() {
this.store.getData(this.businessId());
}
setBreadcrumb() {
this.breadcrumbService.setItems(this.businessBreadcrumb());
}
}
@@ -1,3 +1,3 @@
<div class="flex items-center justify-center h-svh w-svw">
<div class="flex items-center justify-center h-[100cqmin]">
<span class="text-center"> به پنل کسب و کار خوش آمدید </span>
</div>
+4
View File
@@ -1,4 +1,6 @@
import { Route } from '@angular/router';
import { CONSUMER_ACCOUNTS_ROUTES } from './modules/accounts/constants';
import { CONSUMER_BUSINESS_ACTIVITIES_ROUTES } from './modules/businessActivities/constants';
export const CONSUMER_ROUTES = {
path: 'consumer',
@@ -9,5 +11,7 @@ export const CONSUMER_ROUTES = {
loadComponent: () =>
import('./modules/dashboard/views/index.component').then((m) => m.DashboardComponent),
},
...CONSUMER_ACCOUNTS_ROUTES,
...CONSUMER_BUSINESS_ACTIVITIES_ROUTES,
],
} as Route;