feat: add stock keeping units list component and related services

feat: implement checkbox component with label and hint support

feat: create sale invoice full response model for invoice details

feat: add single view component for displaying sale invoice details

feat: define various list configurations for account, business activity, and consumer management

feat: establish list configurations for managing devices, goods, and licenses

feat: create list configurations for managing partners and their accounts

feat: implement user management list configuration
This commit is contained in:
2026-05-12 19:58:53 +03:30
parent fecdf4a06b
commit 561aca32d3
104 changed files with 1611 additions and 678 deletions
@@ -4,6 +4,7 @@ import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { superAdminConsumerAccountListConfig } from '@/shared/constants/list-configs';
import { Component, inject, Input } from '@angular/core';
import { IConsumerAccountResponse } from '../../models';
import { AdminConsumerAccountsService } from '../../services/accounts.service';
@@ -17,38 +18,7 @@ import { ConsumerAccountFormComponent } from './form.component';
export class ConsumerAccountListComponent extends AbstractList<IConsumerAccountResponse> {
@Input({ required: true }) consumerId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
// { field: 'id', header: 'شناسه', type: 'id' },
{
field: 'username',
header: 'نام کاربری',
type: 'nested',
nestedOption: { path: 'account.username' },
},
{
field: 'role',
header: 'نوع حساب',
type: 'nested',
nestedOption: { path: 'role.translate' },
},
{
field: 'pos',
header: 'پایانه مرتبط',
customDataModel: (item) =>
`${item.pos.name} (${item.pos.complex.name} - ${item.pos.complex.business_activity.name})`,
},
{
field: 'status',
header: 'وضعیت',
type: 'nested',
nestedOption: { path: 'status.translate' },
},
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
@Input() header: IColumn[] = superAdminConsumerAccountListConfig.columns;
private readonly service = inject(AdminConsumerAccountsService);
override setColumns(): void {
@@ -4,6 +4,7 @@ import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { businessActivityListConfig } from '@/shared/constants/list-configs';
import { Component, inject, Input } from '@angular/core';
import { Router } from '@angular/router';
import { superAdminConsumerBusinessActivitiesNamedRoutes } from '../../constants/routes/businessActivities';
@@ -19,16 +20,7 @@ import { ConsumerBusinessActivitiesFormComponent } from './form.component';
export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessActivityResponse> {
@Input({ required: true }) consumerId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'عنوان' },
{ field: 'guild', header: 'صنف', type: 'nested', nestedOption: { path: 'guild.name' } },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
@Input() header: IColumn[] = businessActivityListConfig.columns;
private readonly service = inject(AdminConsumerBusinessActivitiesService);
private readonly router = inject(Router);
@@ -4,6 +4,7 @@ import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { complexListConfig } from '@/shared/constants/list-configs';
import { Component, inject, Input } from '@angular/core';
import { Router } from '@angular/router';
import { superAdminConsumerComplexesNamedRoutes } from '../../constants/routes/complexes';
@@ -20,15 +21,7 @@ export class ConsumerComplexesComponent extends AbstractList<IComplexResponse> {
@Input() consumerId!: string;
@Input() businessId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'عنوان' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
@Input() header: IColumn[] = complexListConfig.columns;
private readonly service = inject(AdminComplexesService);
private readonly router = inject(Router);
@@ -1,4 +1,4 @@
import { EntityState, EntityStore } from '@/core/state';
import { defaultBaseStateData, EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize } from 'rxjs';
@@ -20,11 +20,7 @@ export class BusinessActivityStore extends EntityStore<
private readonly service = inject(AdminConsumerBusinessActivitiesService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -71,11 +67,7 @@ export class BusinessActivityStore extends EntityStore<
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -1,4 +1,4 @@
import { EntityState, EntityStore } from '@/core/state';
import { defaultBaseStateData, EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize } from 'rxjs';
@@ -17,11 +17,7 @@ export class ComplexStore extends EntityStore<IComplexResponse, ComplexState> {
private readonly service = inject(AdminComplexesService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -71,11 +67,7 @@ export class ComplexStore extends EntityStore<IComplexResponse, ComplexState> {
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -1,4 +1,4 @@
import { EntityState, EntityStore } from '@/core/state';
import { defaultBaseStateData, EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize } from 'rxjs';
@@ -17,11 +17,7 @@ export class ConsumerStore extends EntityStore<IAdminConsumerResponse, ConsumerS
private readonly service = inject(ConsumersService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -1,4 +1,4 @@
import { EntityState, EntityStore } from '@/core/state';
import { defaultBaseStateData, EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize } from 'rxjs';
@@ -17,11 +17,7 @@ export class PosStore extends EntityStore<IPosResponse, PosState> {
private readonly service = inject(AdminPosesService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -74,11 +70,7 @@ export class PosStore extends EntityStore<IPosResponse, PosState> {
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
@@ -1,6 +1,7 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { consumerListConfig } from '@/shared/constants/list-configs';
import { Component, inject } from '@angular/core';
import { Router } from '@angular/router';
import { ConsumerUserFormComponent } from '../components/form.component';
@@ -18,41 +19,8 @@ export class ConsumersComponent extends AbstractList<IAdminConsumerResponse> {
private readonly router = inject(Router);
override setColumns(): void {
this.columns = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'نام' },
{ field: 'business_counts', header: 'تعداد فعالیت اقتصادی' },
{
field: 'partner',
header: 'ایجاد شده توسط',
type: 'nested',
nestedOption: { path: 'partner.name' },
},
{
field: 'status',
header: 'وضعیت',
type: 'nested',
nestedOption: { path: 'status.translate' },
},
// {
// field: 'license_expires_at',
// header: 'تاریخ انقضا لایسنس',
// customDataModel(item) {
// if (item.license_info) {
// return formatJalali(item.license_info.expires_at);
// }
// return 'بدون لایسنس';
// },
// },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
this.columns = consumerListConfig.columns;
}
override getDataRequest() {
return this.service.getAll();
}
@@ -1,6 +1,7 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { deviceBrandListConfig } from '@/shared/constants/list-configs';
import { Component, inject } from '@angular/core';
import { DeviceBrandFormComponent } from '../components/form.component';
import { IDeviceBrandResponse } from '../models';
@@ -15,15 +16,7 @@ export class DeviceBrandsComponent extends AbstractList<IDeviceBrandResponse> {
private readonly service = inject(DeviceBrandsService);
override setColumns(): void {
this.columns = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'عنوان' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
this.columns = deviceBrandListConfig.columns;
}
override getDataRequest() {
@@ -1,6 +1,7 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { deviceListConfig } from '@/shared/constants/list-configs';
import { Component, inject } from '@angular/core';
import { UserComplexFormComponent } from '../components/form.component';
import { IDeviceResponse } from '../models';
@@ -15,21 +16,7 @@ export class DevicesComponent extends AbstractList<IDeviceResponse> {
private readonly service = inject(SuperAdminDeviceService);
override setColumns(): void {
this.columns = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'عنوان' },
{
field: 'brand',
header: 'برند دستگاه',
type: 'nested',
nestedOption: { path: 'brand.name' },
},
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
this.columns = deviceListConfig.columns;
}
override getDataRequest() {
@@ -9,6 +9,7 @@
[fullHeight]="fullHeight"
[showAdd]="true"
[showEdit]="true"
[showAll]="showAllBtn"
[allItemsPageRoute]="allItemsPageRoute()"
(onEdit)="onEditClick($event)"
(onAdd)="openAddForm()"
@@ -4,6 +4,7 @@ import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { categoryListConfig } from '@/shared/constants/list-configs';
import { Component, computed, inject, Input } from '@angular/core';
import { guildGoodCategoriesNamedRoutes } from '../../constants/routes/goodCategories';
import { IGoodCategoriesResponse } from '../../models';
@@ -18,16 +19,10 @@ import { GuildGoodCategoryFormComponent } from './form.component';
export class GuildGoodCategoriesListComponent extends AbstractList<IGoodCategoriesResponse> {
@Input() guildId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'عنوان' },
{ field: 'goods_count', header: 'تعداد کالاها' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
@Input() showAllBtn?: boolean;
@Input() header: IColumn[] = categoryListConfig.columns;
listConfig = categoryListConfig;
service = inject(GuildGoodCategoriesService);
allItemsPageRoute = computed(() =>
@@ -2,13 +2,14 @@
pageTitle="مدیریت کالاها"
[addNewCtaLabel]="'افزودن کالا'"
[columns]="columns"
[showAdd]="true"
emptyPlaceholderTitle="کالایی یافت نشد"
emptyPlaceholderDescription="برای افزودن کالای، روی دکمهٔ بالا کلیک کنید."
[items]="items()"
[loading]="loading()"
[showAdd]="true"
[showEdit]="true"
[showAll]="showAllBtn"
[allItemsPageRoute]="showAllPageRoute()"
[fullHeight]="fullHeight"
(onEdit)="onEditClick($event)"
(onAdd)="openAddForm()"
@@ -4,7 +4,9 @@ import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { Component, inject, Input } from '@angular/core';
import { goodListConfig } from '@/shared/constants/list-configs';
import { Component, computed, inject, Input } from '@angular/core';
import { guildGoodsNamedRoutes } from '../../constants/routes/goods';
import { IGuildGoodsResponse } from '../../models';
import { GuildGoodsService } from '../../services/goods.service';
import { GuildGoodFormComponent } from './form.component';
@@ -17,19 +19,14 @@ import { GuildGoodFormComponent } from './form.component';
export class GuildGoodsListComponent extends AbstractList<IGuildGoodsResponse> {
@Input() guildId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = [
{ field: 'image_url', header: 'تصویر', type: 'thumbnail' },
{ field: 'name', header: 'عنوان' },
{ field: 'sku', header: 'شناسه کالا', type: 'nested', nestedOption: { path: 'sku.name' } },
{
field: 'category',
header: 'دسته‌بندی',
type: 'nested',
nestedOption: { path: 'category.name' },
},
];
@Input() showAllBtn?: boolean;
@Input() header: IColumn[] = goodListConfig.columns;
listConfig = goodListConfig;
service = inject(GuildGoodsService);
showAllPageRoute = computed(() => guildGoodsNamedRoutes.goods.meta.pagePath!(this.guildId));
override setColumns(): void {
this.columns = this.header;
}
@@ -0,0 +1,24 @@
<app-page-data-list
[pageTitle]="'مدیریت شناسه کالاها'"
[addNewCtaLabel]="'افزودن شناسه'"
[columns]="columns"
emptyPlaceholderTitle="شناسه‌ای یافت نشد"
emptyPlaceholderDescription="برای افزودن شناسه، روی دکمهٔ بالا کلیک کنید."
[items]="items()"
[loading]="loading()"
[fullHeight]="fullHeight"
[showAdd]="true"
[showEdit]="true"
[allItemsPageRoute]="allItemsPageRoute()"
(onEdit)="onEditClick($event)"
(onAdd)="openAddForm()"
(onRefresh)="refresh()"
/>
<stock-keeping-unit-form
[(visible)]="visibleForm"
[initialValues]="selectedItemForEdit() || undefined"
[guildId]="guildId"
[editMode]="editMode()"
(onSubmit)="refresh()"
/>
@@ -0,0 +1,38 @@
// 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 { skuListConfig } from '@/shared/constants/list-configs';
import { Component, computed, inject, Input } from '@angular/core';
import { stockKeepingUnitsNamedRoutes } from '../../constants/routes/stockKeepingUnits';
import { IStockKeepingUnitResponse } from '../../models';
import { StockKeepingUnitsService } from '../../services/stockKeepingUnits.service';
import { StockKeepingUnitFormComponent } from './form.component';
@Component({
selector: 'admin-guild-stock-keeping-units-list',
templateUrl: './list.component.html',
imports: [PageDataListComponent, StockKeepingUnitFormComponent],
})
export class GuildStockKeepingUnitsListComponent extends AbstractList<IStockKeepingUnitResponse> {
@Input() guildId!: string;
@Input() fullHeight?: boolean;
@Input() header: IColumn[] = skuListConfig.columns;
listConfig = skuListConfig;
service = inject(StockKeepingUnitsService);
allItemsPageRoute = computed(() =>
stockKeepingUnitsNamedRoutes.stockKeepingUnits.meta.pagePath!(this.guildId),
);
override setColumns(): void {
this.columns = this.header;
}
override getDataRequest() {
return this.service.getAll(this.guildId);
}
}
@@ -11,6 +11,7 @@ export const guildGoodsNamedRoutes: NamedRoutes<TGuildGoodsRouteNames> = {
// @ts-ignore
meta: {
title: 'کالاها',
pagePath: (guildId: string) => `/super_admin/guilds/${guildId}/goods`,
},
},
// goodCategory: {
@@ -8,7 +8,7 @@ export const stockKeepingUnitsNamedRoutes: NamedRoutes<TStockKeepingUnitsRouteNa
path: 'stock-keeping-units',
loadComponent: () =>
import('../../views/stockKeepingUnits/list.component').then(
(m) => m.StockKeepingUnitsComponent,
(m) => m.GuildStockKeepingUnitsComponent,
),
meta: {
title: 'شناسه کالاها',
@@ -1,10 +1,14 @@
import { EntityState, EntityStore } from '@/core/state';
import { inject, Injectable } from '@angular/core';
import { defaultBaseStateData, EntityState, EntityStore } from '@/core/state';
import { computed, inject, Injectable } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { catchError, finalize } from 'rxjs';
import { guildsNamedRoutes } from '../constants';
import { IGuildResponse } from '../models';
import { GuildsService } from '../services/main.service';
interface GuildState extends EntityState<IGuildResponse> {}
interface GuildState extends EntityState<IGuildResponse> {
breadcrumbItems: MenuItem[];
}
@Injectable({
providedIn: 'root',
@@ -13,11 +17,25 @@ export class GuildStore extends EntityStore<IGuildResponse, GuildState> {
private readonly service = inject(GuildsService);
constructor() {
super({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
breadcrumbItems = computed(() => this._state().breadcrumbItems);
private setBreadcrumb(guildId: string) {
this.patchState({
breadcrumbItems: [
{
...guildsNamedRoutes.guilds.meta,
routerLink: guildsNamedRoutes.guilds.meta.pagePath!(),
},
{
title: this.entity()?.name,
routerLink: guildsNamedRoutes.guild.meta.pagePath!(guildId),
},
],
});
}
@@ -36,16 +54,14 @@ export class GuildStore extends EntityStore<IGuildResponse, GuildState> {
)
.subscribe((entity) => {
this.patchState({ entity });
this.setBreadcrumb(guildId);
});
}
override reset(): void {
this.setState({
loading: false,
error: null,
entity: null,
initialized: false,
isRefreshing: false,
...defaultBaseStateData,
breadcrumbItems: [],
});
}
}
@@ -1,7 +1,11 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { Component, inject, signal } from '@angular/core';
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 { GuildGoodCategoriesListComponent } from '../../components/categories/list.component';
import { guildGoodCategoriesNamedRoutes } from '../../constants/routes/goodCategories';
import { GuildStore } from '../../store/guild.store';
@Component({
selector: 'admin-guild-good-categories',
@@ -10,6 +14,22 @@ import { GuildGoodCategoriesListComponent } from '../../components/categories/li
})
export class GuildGoodCategoriesComponent {
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly store = inject(GuildStore);
readonly guildId = signal<string>(this.route.snapshot.paramMap.get('guildId')!);
pageParams = computed(() => pageParamsUtils(this.route));
readonly guildId = signal<string>(this.pageParams()['guildId']!);
ngOnInit() {
this.setBreadcrumb();
}
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.store.breadcrumbItems(),
{
title: guildGoodCategoriesNamedRoutes.goodCategories.meta.title,
},
]);
}
}
@@ -1,14 +1,35 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { Component, inject, signal } from '@angular/core';
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 { GuildGoodsListComponent } from '../../components/goods/list.component';
import { guildGoodsNamedRoutes } from '../../constants/routes/goods';
import { GuildStore } from '../../store/guild.store';
@Component({
selector: 'admin-guild_goods',
selector: 'admin-guild-goods',
templateUrl: './list.component.html',
imports: [GuildGoodsListComponent],
})
export class GuildGoodsComponent {
route = inject(ActivatedRoute);
guildId = signal<string>(this.route.snapshot.paramMap.get('guildId')!);
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly store = inject(GuildStore);
pageParams = computed(() => pageParamsUtils(this.route));
readonly guildId = signal<string>(this.pageParams()['guildId']!);
ngOnInit() {
this.setBreadcrumb();
}
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.store.breadcrumbItems(),
{
title: guildGoodsNamedRoutes.goods.meta.title,
},
]);
}
}
@@ -24,7 +24,6 @@ export class GuildsComponent extends AbstractList<IGuildResponse> {
override setColumns(): void {
this.columns = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'عنوان' },
{ field: 'code', header: 'کد' },
{ field: 'businessActivitiesCount', header: 'تعداد فعالیت‌‌های اقتصادی‌ مرتبط' },
@@ -9,10 +9,13 @@
</app-card-data>
<div class="max-h-125 flex">
<admin-guild-good-categories-list [guildId]="guildId()" class="w-full" />
<admin-guild-good-categories-list [guildId]="guildId()" [showAllBtn]="true" class="w-full" />
</div>
<div class="max-h-125 flex">
<admin-guild-goods-list [guildId]="guildId()" class="w-full" />
<admin-guild-goods-list [guildId]="guildId()" [showAllBtn]="true" class="w-full" />
</div>
<div class="max-h-125 flex">
<admin-guild-stock-keeping-units-list [guildId]="guildId()" class="w-full" />
</div>
<admin-guild-form
@@ -1,9 +1,11 @@
import { BreadcrumbService } from '@/core/services';
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { GuildGoodCategoriesListComponent } from '../components/categories/list.component';
import { GuildFormComponent } from '../components/form.component';
import { GuildGoodsListComponent } from '../components/goods/list.component';
import { GuildStockKeepingUnitsListComponent } from '../components/stockKeepingUnits/list.component';
import { GuildStore } from '../store/guild.store';
@Component({
@@ -14,11 +16,13 @@ import { GuildStore } from '../store/guild.store';
KeyValueComponent,
GuildGoodCategoriesListComponent,
GuildGoodsListComponent,
GuildStockKeepingUnitsListComponent,
GuildFormComponent,
],
})
export class GuildComponent {
private readonly store = inject(GuildStore);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly route = inject(ActivatedRoute);
readonly guildId = signal<string>(this.route.snapshot.paramMap.get('guildId')!);
@@ -30,4 +34,12 @@ export class GuildComponent {
getData() {
this.store.getData(this.guildId());
}
ngOnInit() {
this.setBreadcrumb();
}
setBreadcrumb() {
this.breadcrumbService.setItems([...this.store.breadcrumbItems()]);
}
}
@@ -1,22 +1 @@
<app-page-data-list
[pageTitle]="'مدیریت شناسه کالاها'"
[addNewCtaLabel]="'افزودن شناسه کالا'"
[columns]="columns"
emptyPlaceholderTitle="شناسه کالایی یافت نشد"
emptyPlaceholderDescription="برای افزودن شناسه کالا، روی دکمهٔ بالا کلیک کنید."
[items]="items()"
[loading]="loading()"
[showDetails]="false"
[showAdd]="true"
(onAdd)="openAddForm()"
(onRefresh)="refresh()"
>
</app-page-data-list>
<stock-keeping-unit-form
[guildId]="guildId()"
[(visible)]="visibleForm"
[initialValues]="selectedItemForEdit()!"
[editMode]="false"
[stockKeepingUnitId]="selectedItemForEdit()?.id"
(onSubmit)="refresh()"
/>
<admin-guild-stock-keeping-units-list [guildId]="guildId()" class="w-full" />
@@ -1,33 +1,35 @@
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
// 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 { StockKeepingUnitFormComponent } from '../../components/stockKeepingUnits/form.component';
import { IStockKeepingUnitResponse } from '../../models';
import { StockKeepingUnitsService } from '../../services/stockKeepingUnits.service';
import { GuildStockKeepingUnitsListComponent } from '../../components/stockKeepingUnits/list.component';
import { stockKeepingUnitsNamedRoutes } from '../../constants/routes/stockKeepingUnits';
import { GuildStore } from '../../store/guild.store';
@Component({
selector: 'superAdmin-stockKeepingUnits',
selector: 'admin-guild-stock-keeping-units',
templateUrl: './list.component.html',
imports: [PageDataListComponent, StockKeepingUnitFormComponent],
imports: [GuildStockKeepingUnitsListComponent],
})
export class StockKeepingUnitsComponent extends AbstractList<IStockKeepingUnitResponse> {
export class GuildStockKeepingUnitsComponent {
private readonly route = inject(ActivatedRoute);
private readonly breadcrumbService = inject(BreadcrumbService);
private readonly store = inject(GuildStore);
pageParams = computed(() => pageParamsUtils(this.route));
readonly guildId = signal<string>(this.pageParams()['guildId']!);
private readonly service = inject(StockKeepingUnitsService);
override setColumns(): void {
this.columns = [
{ field: 'code', header: 'کد' },
{ field: 'name', header: 'عنوان' },
{ field: 'VAT', header: 'مالیات ارزش افزوده' },
];
ngOnInit() {
this.setBreadcrumb();
}
override getDataRequest() {
return this.service.getAll(this.guildId());
setBreadcrumb() {
this.breadcrumbService.setItems([
...this.store.breadcrumbItems(),
{
title: stockKeepingUnitsNamedRoutes.stockKeepingUnits.meta.title,
},
]);
}
}
@@ -1,8 +1,9 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { licenseListConfig } from '@/shared/constants/list-configs';
import { Component, inject } from '@angular/core';
import { ILicenseRawResponse, ILicenseResponse } from '../models';
import { ILicenseResponse } from '../models';
import { LicensesService } from '../services/main.service';
@Component({
@@ -14,24 +15,7 @@ export class LicensesComponent extends AbstractList<ILicenseResponse> {
private readonly service = inject(LicensesService);
override setColumns(): void {
this.columns = [
{
field: 'consumer',
header: 'مشتری',
customDataModel(item) {
return `${item.consumer.first_name} ${item.consumer.last_name}`;
},
},
{
field: 'partner',
header: 'ارایه شده توسط',
customDataModel(item: ILicenseRawResponse) {
return item.license.charged_license_transaction.partner.name || 'برند نرم‌افزار';
},
},
{ field: 'expires_at', header: 'تاریخ انقضا', type: 'date' },
{ field: 'created_at', header: 'تاریخ ایجاد', type: 'date' },
];
this.columns = licenseListConfig.columns;
}
override getDataRequest() {
@@ -1,6 +1,7 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { partnerListConfig } from '@/shared/constants/list-configs';
import { Component, inject, TemplateRef, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { Avatar } from 'primeng/avatar';
@@ -24,30 +25,15 @@ export class PartnersComponent extends AbstractList<IPartnerResponse> {
@ViewChild('licensesRenewStatus', { static: true }) licensesRenewStatus!: TemplateRef<any>;
override setColumns(): void {
this.columns = [
{ field: 'name', header: 'عنوان', customDataModel: this.name },
{ field: 'code', header: 'کد' },
{ field: 'licenses', header: 'تعداد لایسنس‌ها', customDataModel: this.licensesStatus },
{
field: 'account_quota',
header: 'تعداد کاربرهای خریداری شده',
customDataModel: this.accountQuotaStatus,
},
{
field: 'license_renew',
header: 'تعداد لایسنس تمدیدی',
customDataModel: this.licensesRenewStatus,
},
{
field: 'status',
header: 'وضعیت',
type: 'nested',
variant: 'tag',
nestedOption: {
path: 'status.translate',
},
},
];
this.columns = partnerListConfig.columns.map((col) => {
if (col.field === 'name') return { ...col, customDataModel: this.name };
if (col.field === 'licenses') return { ...col, customDataModel: this.licensesStatus };
if (col.field === 'account_quota')
return { ...col, customDataModel: this.accountQuotaStatus };
if (col.field === 'license_renew')
return { ...col, customDataModel: this.licensesRenewStatus };
return col;
});
}
override getDataRequest() {
@@ -1,6 +1,7 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { providerListConfig } from '@/shared/constants/list-configs';
import { Component, inject } from '@angular/core';
import { ProviderFormComponent } from '../components/form.component';
import { IProviderResponse } from '../models';
@@ -15,15 +16,7 @@ export class ProvidersComponent extends AbstractList<IProviderResponse> {
private readonly service = inject(ProvidersService);
override setColumns(): void {
this.columns = [
// { field: 'id', header: 'شناسه', type: 'id' },
{ field: 'name', header: 'نام' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
this.columns = providerListConfig.columns;
}
override getDataRequest() {
@@ -1,6 +1,7 @@
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
import { userListConfig } from '@/shared/constants/list-configs';
import { Component, inject } from '@angular/core';
import { Router } from '@angular/router';
import { UserAccountFormComponent } from '../components/form.component';
@@ -18,16 +19,7 @@ export class UsersComponent extends AbstractList<IUserResponse> {
private readonly router = inject(Router);
override setColumns(): void {
this.columns = [
{ field: 'fullname', header: 'نام' },
{ field: 'mobile_number', header: 'شماره موبایل' },
{ field: 'national_code', header: 'کد ملی' },
{
field: 'created_at',
header: 'تاریخ ایجاد',
type: 'date',
},
];
this.columns = userListConfig.columns;
}
override getDataRequest() {