create consumer domain accounts permissions
This commit is contained in:
@@ -18,9 +18,6 @@ export const errorInterceptor: HttpInterceptorFn = (req, next) => {
|
|||||||
|
|
||||||
return next(req).pipe(
|
return next(req).pipe(
|
||||||
catchError((error: HttpErrorResponse) => {
|
catchError((error: HttpErrorResponse) => {
|
||||||
console.log('error');
|
|
||||||
console.log(error);
|
|
||||||
|
|
||||||
let errorMessage = 'خطای نامشخص رخ داده است';
|
let errorMessage = 'خطای نامشخص رخ داده است';
|
||||||
|
|
||||||
if (error.error instanceof ErrorEvent) {
|
if (error.error instanceof ErrorEvent) {
|
||||||
@@ -133,13 +130,9 @@ export enum ErrorType {
|
|||||||
* Helper function to determine error type
|
* Helper function to determine error type
|
||||||
*/
|
*/
|
||||||
export function getErrorType(error: HttpErrorResponse): ErrorType {
|
export function getErrorType(error: HttpErrorResponse): ErrorType {
|
||||||
console.log('getErrorType');
|
|
||||||
console.log(error);
|
|
||||||
|
|
||||||
if (error.error instanceof ErrorEvent) {
|
if (error.error instanceof ErrorEvent) {
|
||||||
return ErrorType.NETWORK;
|
return ErrorType.NETWORK;
|
||||||
}
|
}
|
||||||
console.log(error.status);
|
|
||||||
|
|
||||||
switch (error.status) {
|
switch (error.status) {
|
||||||
case 400:
|
case 400:
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export interface IAuthAccountResponse {
|
|||||||
provider_id?: string;
|
provider_id?: string;
|
||||||
pos_id?: string;
|
pos_id?: string;
|
||||||
user: IAuthAccountUser;
|
user: IAuthAccountUser;
|
||||||
|
role: string;
|
||||||
}
|
}
|
||||||
interface IAuthAccountUser {
|
interface IAuthAccountUser {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -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 { AccountStore } from '../store/account.store';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'consumer-account-layout',
|
||||||
|
templateUrl: './layout.component.html',
|
||||||
|
imports: [PageLoadingComponent, RouterOutlet],
|
||||||
|
})
|
||||||
|
export class ConsumerAccountLayoutComponent {
|
||||||
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
private readonly store = inject(AccountStore);
|
||||||
|
|
||||||
|
readonly accountId = signal<string>(this.route.snapshot.paramMap.get('accountId')!);
|
||||||
|
|
||||||
|
readonly loading = computed(() => this.store.loading());
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.store.getData(this.accountId());
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.getData();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<div class="flex flex-col gap-6">
|
||||||
|
<app-card-data cardTitle="مدیریت سطح دسترسی">
|
||||||
|
@if (isOwner()) {
|
||||||
|
<div class="py-20 flex items-center justify-center">
|
||||||
|
کاربر با سطح Owner به تمامی سطوح دسترسی داشته و قابل ویرایش نمیباشد
|
||||||
|
</div>
|
||||||
|
} @else if (loading()) {
|
||||||
|
<div class="py-20 flex items-center justify-center">
|
||||||
|
<p-progressSpinner />
|
||||||
|
</div>
|
||||||
|
} @else if (permissions()) {
|
||||||
|
<div class="flex flex-col gap-6">
|
||||||
|
<p-message severity="secondary"> پیام مفهومی برای مشخص کردن نوع دسترسی دادن</p-message>
|
||||||
|
@for (pos of permissions()?.poses; track $index) {
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<p-toggleSwitch [(ngModel)]="pos.hasAccess" />
|
||||||
|
<span class="text-lg font-bold">
|
||||||
|
{{ pos.name }} - {{ pos.complex.name }} - {{ pos.complex.business_activity.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@for (complex of permissions()?.complexes; track $index) {
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<p-toggleSwitch [(ngModel)]="complex.hasAccess" />
|
||||||
|
<span class="text-lg font-bold"> {{ complex.name }} - {{ complex.business_activity.name }} </span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@for (ba of permissions()?.business_activities; track $index) {
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<p-toggleSwitch [(ngModel)]="ba.hasAccess" />
|
||||||
|
<span class="text-lg font-bold"> {{ ba.name }} </span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-10">
|
||||||
|
<button pButton [loading]="submitLoading()" (click)="submit()">ثبت تغییرات</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</app-card-data>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
||||||
|
import { Maybe } from '@/core';
|
||||||
|
import { AppCardComponent } from '@/shared/components';
|
||||||
|
import pageParamsUtils from '@/utils/page-params.utils';
|
||||||
|
import { Component, computed, inject, signal } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { ButtonDirective } from 'primeng/button';
|
||||||
|
import { Message } from 'primeng/message';
|
||||||
|
import { ProgressSpinner } from 'primeng/progressspinner';
|
||||||
|
import { ToggleSwitch } from 'primeng/toggleswitch';
|
||||||
|
import { finalize } from 'rxjs';
|
||||||
|
import { IPermissionRequest, IPermissionResponse } from '../../models';
|
||||||
|
import { PermissionsService } from '../../services/permissions.service';
|
||||||
|
import { AccountStore } from '../../store/account.store';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'consumer-account-permission-list',
|
||||||
|
templateUrl: './list.component.html',
|
||||||
|
imports: [AppCardComponent, ProgressSpinner, ToggleSwitch, FormsModule, Message, ButtonDirective],
|
||||||
|
})
|
||||||
|
export class ConsumerAccountPermissionListComponent {
|
||||||
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
|
||||||
|
private readonly service = inject(PermissionsService);
|
||||||
|
private readonly accountStore = inject(AccountStore);
|
||||||
|
|
||||||
|
pageParams = computed(() => pageParamsUtils(this.route));
|
||||||
|
accountId = signal<string>(this.pageParams()['accountId']);
|
||||||
|
permissions = signal<Maybe<IPermissionResponse>>(null);
|
||||||
|
loading = signal<boolean>(true);
|
||||||
|
submitLoading = signal<boolean>(false);
|
||||||
|
|
||||||
|
account = computed(() => this.accountStore.entity());
|
||||||
|
isOwner = computed(() => this.account()?.role === 'OWNER');
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.loading.set(true);
|
||||||
|
this.permissions.set(null);
|
||||||
|
this.service
|
||||||
|
.getAll(this.accountId())
|
||||||
|
.pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.loading.set(false);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.subscribe((res) => {
|
||||||
|
if (res) {
|
||||||
|
this.permissions.set(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
const dataToSet: IPermissionRequest = {};
|
||||||
|
const posPermissions = this.permissions()
|
||||||
|
?.poses.filter((pos) => pos.hasAccess)
|
||||||
|
.map((pos) => pos.id);
|
||||||
|
const complexPermissions = this.permissions()
|
||||||
|
?.complexes?.filter((complex) => complex.hasAccess)
|
||||||
|
.map((pos) => pos.id);
|
||||||
|
const baPermissions = this.permissions()
|
||||||
|
?.business_activities?.filter((ba) => ba.hasAccess)
|
||||||
|
.map((ba) => ba.id);
|
||||||
|
|
||||||
|
if (posPermissions?.length) {
|
||||||
|
dataToSet.poses = posPermissions;
|
||||||
|
}
|
||||||
|
if (complexPermissions?.length) {
|
||||||
|
dataToSet.complexes = complexPermissions;
|
||||||
|
}
|
||||||
|
if (baPermissions?.length) {
|
||||||
|
dataToSet.business_activities = baPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.submitLoading.set(true);
|
||||||
|
|
||||||
|
this.service
|
||||||
|
.update(this.accountId(), dataToSet)
|
||||||
|
.pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.submitLoading.set(false);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.subscribe((res) => {
|
||||||
|
this.getData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (!this.isOwner()) {
|
||||||
|
this.getData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
export * from './permissions';
|
||||||
|
|
||||||
const baseUrl = '/api/v1/consumer/accounts';
|
const baseUrl = '/api/v1/consumer/accounts';
|
||||||
|
|
||||||
export const CONSUMER_Accounts_API_ROUTES = {
|
export const CONSUMER_Accounts_API_ROUTES = {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
const baseUrl = (accountId: string) => `/api/v1/consumer/accounts/${accountId}/permissions`;
|
||||||
|
|
||||||
|
export const CONSUMER_PERMISSIONS_API_ROUTES = {
|
||||||
|
list: (accountId: string) => `${baseUrl(accountId)}`,
|
||||||
|
single: (accountId: string, id: string) => `${baseUrl(accountId)}/${id}`,
|
||||||
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { NamedRoutes } from '@/core';
|
import { NamedRoutes } from '@/core';
|
||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
|
import { CONSUMER_ACCOUNT_PERMISSIONS_ROUTES } from './permissions';
|
||||||
|
|
||||||
export type TConsumerAccountsRouteNames = 'accounts' | 'account';
|
export type TConsumerAccountsRouteNames = 'accounts' | 'account';
|
||||||
|
|
||||||
@@ -24,4 +25,18 @@ export const consumerAccountsNamedRoutes: NamedRoutes<TConsumerAccountsRouteName
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CONSUMER_ACCOUNTS_ROUTES: Routes = Object.values(consumerAccountsNamedRoutes);
|
export const CONSUMER_ACCOUNTS_ROUTES: Routes = [
|
||||||
|
consumerAccountsNamedRoutes.accounts,
|
||||||
|
{
|
||||||
|
path: consumerAccountsNamedRoutes.account.path,
|
||||||
|
loadComponent: () =>
|
||||||
|
import('../../components/layout.component').then((m) => m.ConsumerAccountLayoutComponent),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
...consumerAccountsNamedRoutes.account,
|
||||||
|
path: '',
|
||||||
|
},
|
||||||
|
...CONSUMER_ACCOUNT_PERMISSIONS_ROUTES,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { NamedRoutes } from '@/core';
|
||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
export type TConsumerAccountPermissionsRouteNames = 'permissions';
|
||||||
|
|
||||||
|
export const consumerAccountPermissionsNamedRoutes: NamedRoutes<TConsumerAccountPermissionsRouteNames> =
|
||||||
|
{
|
||||||
|
permissions: {
|
||||||
|
path: 'permissions',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('../../views/permissions/list.component').then(
|
||||||
|
(m) => m.ConsumerAccountPermissionsComponent,
|
||||||
|
),
|
||||||
|
meta: {
|
||||||
|
title: 'سطح دسترسی',
|
||||||
|
pagePath: (accountId: string) => `/consumer/accounts/${accountId}/permissions`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CONSUMER_ACCOUNT_PERMISSIONS_ROUTES: Routes = Object.values(
|
||||||
|
consumerAccountPermissionsNamedRoutes,
|
||||||
|
);
|
||||||
@@ -1 +1,2 @@
|
|||||||
export * from './io';
|
export * from './io';
|
||||||
|
export * from './permissions.io';
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
export interface IAccountRawResponse {
|
export interface IAccountRawResponse {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
role: string;
|
||||||
|
created_at: string;
|
||||||
|
account: Account;
|
||||||
}
|
}
|
||||||
export interface IAccountResponse extends IAccountRawResponse {}
|
export interface IAccountResponse extends IAccountRawResponse {}
|
||||||
|
|
||||||
@@ -11,3 +13,8 @@ export interface IAccountRequest {
|
|||||||
export interface IAccountPasswordRequest {
|
export interface IAccountPasswordRequest {
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Account {
|
||||||
|
username: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import ISummary from '@/core/models/summary';
|
||||||
|
|
||||||
|
export interface IPermissionRawResponse {
|
||||||
|
poses: IPosPermissionResponse[];
|
||||||
|
complexes: IComplexPermissionResponse[];
|
||||||
|
business_activities: ICommonPermissionResponse[];
|
||||||
|
}
|
||||||
|
export interface IPermissionResponse extends IPermissionRawResponse {}
|
||||||
|
|
||||||
|
export interface IPermissionRequest {
|
||||||
|
poses?: string[];
|
||||||
|
complexes?: string[];
|
||||||
|
business_activities?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ICommonPermissionResponse {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
hasAccess: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IComplexPermissionResponse extends ICommonPermissionResponse {
|
||||||
|
business_activity: ISummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IPosPermissionResponse extends ICommonPermissionResponse {
|
||||||
|
complex: Complex;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Complex extends ISummary {
|
||||||
|
business_activity: ISummary;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { CONSUMER_PERMISSIONS_API_ROUTES } from '../constants';
|
||||||
|
import { IPermissionRawResponse, IPermissionRequest, IPermissionResponse } from '../models';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class PermissionsService {
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
private apiRoutes = CONSUMER_PERMISSIONS_API_ROUTES;
|
||||||
|
|
||||||
|
getAll(accountId: string): Observable<IPermissionResponse> {
|
||||||
|
return this.http.get<IPermissionRawResponse>(this.apiRoutes.list(accountId));
|
||||||
|
}
|
||||||
|
|
||||||
|
update(accountId: string, data: IPermissionRequest): Observable<IPermissionResponse> {
|
||||||
|
return this.http.put<IPermissionResponse>(this.apiRoutes.list(accountId), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 { consumerAccountsNamedRoutes } from '../constants';
|
||||||
|
import { IAccountResponse } from '../models';
|
||||||
|
import { AccountsService } from '../services/main.service';
|
||||||
|
|
||||||
|
interface AccountState extends EntityState<IAccountResponse> {
|
||||||
|
breadcrumbItems: MenuItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class AccountStore extends EntityStore<IAccountResponse, AccountState> {
|
||||||
|
private readonly service = inject(AccountsService);
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
entity: null,
|
||||||
|
initialized: false,
|
||||||
|
isRefreshing: false,
|
||||||
|
breadcrumbItems: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
breadcrumbItems = computed(() => this._state().breadcrumbItems);
|
||||||
|
|
||||||
|
private setBreadcrumb(accountId: string) {
|
||||||
|
this.patchState({
|
||||||
|
breadcrumbItems: [
|
||||||
|
{
|
||||||
|
...consumerAccountsNamedRoutes.accounts.meta,
|
||||||
|
routerLink: consumerAccountsNamedRoutes.accounts.meta.pagePath!(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.entity()?.account.username,
|
||||||
|
routerLink: consumerAccountsNamedRoutes.account.meta.pagePath!(accountId),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(accountId: string) {
|
||||||
|
this.patchState({ loading: true });
|
||||||
|
this.service
|
||||||
|
.getSingle(accountId)
|
||||||
|
.pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.patchState({ loading: false });
|
||||||
|
}),
|
||||||
|
catchError(() => {
|
||||||
|
this.patchState({
|
||||||
|
error: '',
|
||||||
|
});
|
||||||
|
return throwError('');
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.subscribe((entity) => {
|
||||||
|
this.patchState({ entity });
|
||||||
|
this.setBreadcrumb(accountId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
override reset(): void {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
entity: null,
|
||||||
|
initialized: false,
|
||||||
|
isRefreshing: false,
|
||||||
|
breadcrumbItems: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from './list.component';
|
export * from './list.component';
|
||||||
|
export * from './permissions';
|
||||||
export * from './single.component';
|
export * from './single.component';
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
emptyPlaceholderTitle="حساب کاربریای یافت نشد"
|
emptyPlaceholderTitle="حساب کاربریای یافت نشد"
|
||||||
[items]="items()"
|
[items]="items()"
|
||||||
|
[showDetails]="true"
|
||||||
[loading]="loading()"
|
[loading]="loading()"
|
||||||
|
(onDetails)="toSinglePage($event)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@if (selectedItemForEdit()) {
|
@if (selectedItemForEdit()) {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
||||||
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
import { ConsumerAccountPasswordFormComponent } from '../components/form.component';
|
import { ConsumerAccountPasswordFormComponent } from '../components/form.component';
|
||||||
|
import { consumerAccountsNamedRoutes } from '../constants';
|
||||||
import { IAccountResponse } from '../models';
|
import { IAccountResponse } from '../models';
|
||||||
import { AccountsService } from '../services/main.service';
|
import { AccountsService } from '../services/main.service';
|
||||||
|
|
||||||
@@ -13,6 +15,7 @@ import { AccountsService } from '../services/main.service';
|
|||||||
})
|
})
|
||||||
export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
||||||
private readonly service = inject(AccountsService);
|
private readonly service = inject(AccountsService);
|
||||||
|
private readonly router = inject(Router);
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = [
|
this.columns = [
|
||||||
@@ -31,4 +34,8 @@ export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
|||||||
override getDataRequest() {
|
override getDataRequest() {
|
||||||
return this.service.getAll();
|
return this.service.getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toSinglePage(account: IAccountResponse) {
|
||||||
|
this.router.navigateByUrl(consumerAccountsNamedRoutes.account.meta.pagePath!(account.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './list.component';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<consumer-account-permission-list />
|
||||||
@@ -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 { ConsumerAccountPermissionListComponent } from '../../components/permissions/list.component';
|
||||||
|
import { consumerAccountPermissionsNamedRoutes } from '../../constants/routes/permissions';
|
||||||
|
import { AccountStore } from '../../store/account.store';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'consumer-account-permissions',
|
||||||
|
templateUrl: './list.component.html',
|
||||||
|
imports: [ConsumerAccountPermissionListComponent],
|
||||||
|
})
|
||||||
|
export class ConsumerAccountPermissionsComponent {
|
||||||
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
private readonly breadcrumbService = inject(BreadcrumbService);
|
||||||
|
|
||||||
|
private readonly accountStore = inject(AccountStore);
|
||||||
|
|
||||||
|
pageParams = computed(() => pageParamsUtils(this.route));
|
||||||
|
accountId = signal<string>(this.pageParams()['accountId']);
|
||||||
|
|
||||||
|
account = computed(() => this.accountStore.entity());
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.setBreadcrumb();
|
||||||
|
}
|
||||||
|
|
||||||
|
setBreadcrumb() {
|
||||||
|
this.breadcrumbService.setItems([
|
||||||
|
...this.accountStore.breadcrumbItems(),
|
||||||
|
consumerAccountPermissionsNamedRoutes.permissions.meta,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,13 @@
|
|||||||
<div class=""></div>
|
<div class="flex flex-col gap-6">
|
||||||
|
<app-card-data cardTitle="اطلاعات کاربری" [editable]="false" [(editMode)]="editMode">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<div class="grid grid-cols-3 gap-4 items-center">
|
||||||
|
<app-key-value label="نام کاربری" [value]="account()?.account?.username" />
|
||||||
|
<app-key-value label="نقش" [value]="account()?.role" />
|
||||||
|
<app-key-value label="وضعیت" [value]="account()?.account?.status" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</app-card-data>
|
||||||
|
|
||||||
|
<consumer-account-permission-list />
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,40 @@
|
|||||||
import { Component } from '@angular/core';
|
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 { ConsumerAccountPermissionListComponent } from '../components/permissions/list.component';
|
||||||
|
import { AccountStore } from '../store/account.store';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-account',
|
selector: 'consumer-account',
|
||||||
templateUrl: './single.component.html',
|
templateUrl: './single.component.html',
|
||||||
|
imports: [AppCardComponent, KeyValueComponent, ConsumerAccountPermissionListComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerAccountComponent {
|
export class ConsumerAccountComponent {
|
||||||
constructor() {}
|
private readonly store = inject(AccountStore);
|
||||||
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
private readonly breadcrumbService = inject(BreadcrumbService);
|
||||||
|
|
||||||
|
readonly accountId = signal<string>(this.route.snapshot.paramMap.get('accountId')!);
|
||||||
|
editMode = signal<boolean>(false);
|
||||||
|
|
||||||
|
readonly loading = computed(() => this.store.loading());
|
||||||
|
readonly account = computed(() => this.store.entity());
|
||||||
|
readonly accountBreadcrumb = computed(() => this.store.breadcrumbItems());
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
effect(() => {
|
||||||
|
if (this.account()?.id) {
|
||||||
|
this.setBreadcrumb();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.store.getData(this.accountId());
|
||||||
|
}
|
||||||
|
|
||||||
|
setBreadcrumb() {
|
||||||
|
this.breadcrumbService.setItems(this.accountBreadcrumb());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export class SuperAdminUserPosComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toPosLanding() {
|
toPosLanding() {
|
||||||
|
// this.cookieService.delete('posId', '/', 'localhost', false, 'Lax');
|
||||||
this.cookieService.set('posId', this.posId(), {
|
this.cookieService.set('posId', this.posId(), {
|
||||||
sameSite: 'Lax', // or 'Strict' for same-site requests only
|
sameSite: 'Lax', // or 'Strict' for same-site requests only
|
||||||
secure: false,
|
secure: false,
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
<div class="flex flex-col gap-6">
|
<div class="flex flex-col gap-6">
|
||||||
<app-card-data cardTitle="اطلاعات فاکتور" [editable]="true" [(editMode)]="editMode">
|
<app-card-data cardTitle="اطلاعات فاکتور" [editable]="false" [(editMode)]="editMode">
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="grid grid-cols-3 gap-4 items-center">
|
<div class="grid grid-cols-3 gap-4 items-center">
|
||||||
<app-key-value label="کد رهگیری" [value]="invoice()?.code" />
|
<app-key-value label="کد رهگیری" [value]="invoice()?.code" />
|
||||||
<app-key-value label="تاریخ فاکتور" [value]="invoice()?.invoice_date" type="dateTime" />
|
<app-key-value label="تاریخ فاکتور" [value]="invoice()?.invoice_date" type="dateTime" />
|
||||||
<app-key-value label="تاریخ ایجاد فاکتور" [value]="invoice()?.created_at" type="dateTime" />
|
<app-key-value label="تاریخ ایجاد فاکتور" [value]="invoice()?.created_at" type="dateTime" />
|
||||||
|
<app-key-value label="وضعیت صدور به سامانهی مودیان">
|
||||||
|
<p-badge value="ارسال نشده" severity="danger" />
|
||||||
|
</app-key-value>
|
||||||
<div class="col-span-3">
|
<div class="col-span-3">
|
||||||
<app-key-value label="توضیحات" [value]="invoice()?.notes" />
|
<app-key-value label="توضیحات" [value]="invoice()?.notes" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
|||||||
import pageParamsUtils from '@/utils/page-params.utils';
|
import pageParamsUtils from '@/utils/page-params.utils';
|
||||||
import { Component, computed, effect, inject, signal } from '@angular/core';
|
import { Component, computed, effect, inject, signal } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Badge } from 'primeng/badge';
|
||||||
import { Divider } from 'primeng/divider';
|
import { Divider } from 'primeng/divider';
|
||||||
import { ConsumerCustomerStore } from '../../store/customer.store';
|
import { ConsumerCustomerStore } from '../../store/customer.store';
|
||||||
import { ConsumerCustomerSaleInvoiceStore } from '../../store/saleInvoice.store';
|
import { ConsumerCustomerSaleInvoiceStore } from '../../store/saleInvoice.store';
|
||||||
@@ -10,7 +11,7 @@ import { ConsumerCustomerSaleInvoiceStore } from '../../store/saleInvoice.store'
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-customer-saleInvoice',
|
selector: 'consumer-customer-saleInvoice',
|
||||||
templateUrl: './single.component.html',
|
templateUrl: './single.component.html',
|
||||||
imports: [AppCardComponent, KeyValueComponent, Divider],
|
imports: [AppCardComponent, KeyValueComponent, Divider, Badge],
|
||||||
})
|
})
|
||||||
export class ConsumerCustomerSaleInvoiceComponent {
|
export class ConsumerCustomerSaleInvoiceComponent {
|
||||||
private readonly route = inject(ActivatedRoute);
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class PosLayoutComponent {
|
|||||||
now = new Date();
|
now = new Date();
|
||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
this.store.getData();
|
this.store.getData().subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { EntityState, EntityStore } from '@/core/state';
|
import { EntityState, EntityStore } from '@/core/state';
|
||||||
import { computed, inject, Injectable } from '@angular/core';
|
import { computed, inject, Injectable } from '@angular/core';
|
||||||
import { CookieService } from 'ngx-cookie-service';
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
import { catchError, finalize, throwError } from 'rxjs';
|
import { finalize, map } from 'rxjs';
|
||||||
import { IPosInfoResponse } from './models/pos.io';
|
import { IPosInfoResponse } from './models/pos.io';
|
||||||
import { PosService } from './modules/landing/services/main.service';
|
import { PosService } from './modules/landing/services/main.service';
|
||||||
|
|
||||||
@@ -30,22 +30,18 @@ export class PosStore extends EntityStore<IPosInfoResponse, PosState> {
|
|||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
this.patchState({ loading: true });
|
this.patchState({ loading: true });
|
||||||
this.service
|
return this.service.getInfo().pipe(
|
||||||
.getInfo()
|
finalize(() => {
|
||||||
.pipe(
|
this.patchState({ loading: false });
|
||||||
finalize(() => {
|
}),
|
||||||
this.patchState({ loading: false });
|
|
||||||
}),
|
map((entity: IPosInfoResponse) => {
|
||||||
catchError(() => {
|
if (entity) {
|
||||||
this.patchState({
|
this.patchState({ entity: entity });
|
||||||
error: '',
|
}
|
||||||
});
|
return entity;
|
||||||
return throwError('');
|
}),
|
||||||
}),
|
);
|
||||||
)
|
|
||||||
.subscribe((entity) => {
|
|
||||||
this.patchState({ entity });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override reset(): void {
|
override reset(): void {
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
>
|
>
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<app-input label="نام کاربری" [control]="form.controls.username" name="username" />
|
<app-input label="نام کاربری" [control]="form.controls.username" name="username" />
|
||||||
<app-enum-select [control]="form.controls.type" name="type" type="accountType" />
|
<app-enum-select [control]="form.controls.role" name="role" type="consumerRole" />
|
||||||
<uikit-field label="رمز عبور" class="" [control]="form.controls.password">
|
<uikit-field label="رمز عبور" class="" [control]="form.controls.password">
|
||||||
<p-password
|
<p-password
|
||||||
id="password1"
|
id="password1"
|
||||||
|
|||||||
@@ -50,9 +50,7 @@ export class ConsumerAccountFormComponent extends AbstractFormDialog<
|
|||||||
return this.fb.group(
|
return this.fb.group(
|
||||||
{
|
{
|
||||||
username: [this.initialValues?.username || '', [Validators.required]],
|
username: [this.initialValues?.username || '', [Validators.required]],
|
||||||
// @ts-ignore
|
role: ['', [Validators.required]],
|
||||||
type: [this.initialValues?.type, [Validators.required]],
|
|
||||||
|
|
||||||
password: ['', [Validators.required, password()]],
|
password: ['', [Validators.required, password()]],
|
||||||
confirmPassword: ['', [Validators.required]],
|
confirmPassword: ['', [Validators.required]],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export class AuthComponent {
|
|||||||
activeStep = signal<TSteps>(this.defaultStep);
|
activeStep = signal<TSteps>(this.defaultStep);
|
||||||
|
|
||||||
selectedRole = signal<TRoles | undefined>(this.role);
|
selectedRole = signal<TRoles | undefined>(this.role);
|
||||||
|
accountRole = signal<string>('');
|
||||||
|
|
||||||
toSignUp = () => {
|
toSignUp = () => {
|
||||||
this.activeStep.set('signup');
|
this.activeStep.set('signup');
|
||||||
@@ -36,7 +37,9 @@ export class AuthComponent {
|
|||||||
|
|
||||||
onLoggedIn = (data: IAuthResponse) => {
|
onLoggedIn = (data: IAuthResponse) => {
|
||||||
this.toastService.success({ text: 'شما با موفقیت وارد شدید.' });
|
this.toastService.success({ text: 'شما با موفقیت وارد شدید.' });
|
||||||
|
|
||||||
this.selectedRole.set(data.account.type.toUpperCase() as TRoles);
|
this.selectedRole.set(data.account.type.toUpperCase() as TRoles);
|
||||||
|
this.accountRole.set(data.account.role);
|
||||||
// if (data.mustChangePassword) {
|
// if (data.mustChangePassword) {
|
||||||
// this.activeStep.set('modifyLoginInfo');
|
// this.activeStep.set('modifyLoginInfo');
|
||||||
// return;
|
// return;
|
||||||
@@ -70,7 +73,11 @@ export class AuthComponent {
|
|||||||
redirectUrl = '/partner';
|
redirectUrl = '/partner';
|
||||||
break;
|
break;
|
||||||
case 'CONSUMER':
|
case 'CONSUMER':
|
||||||
redirectUrl = '/consumer';
|
if (this.accountRole() === 'OPERATOR') {
|
||||||
|
redirectUrl = '/pos';
|
||||||
|
} else {
|
||||||
|
redirectUrl = '/consumer';
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export const apiEnumTranslates = {
|
|||||||
partnerRole: 'نقش',
|
partnerRole: 'نقش',
|
||||||
businessRole: 'نقش',
|
businessRole: 'نقش',
|
||||||
providerRole: 'نقش',
|
providerRole: 'نقش',
|
||||||
|
consumerRole: 'نقش',
|
||||||
unitType: 'واحد اندازهگیری',
|
unitType: 'واحد اندازهگیری',
|
||||||
goodPricingModel: 'مدل محاسبه',
|
goodPricingModel: 'مدل محاسبه',
|
||||||
} as Record<TEnumApi, string>;
|
} as Record<TEnumApi, string>;
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ export const ENUMS_API_ROUTES = {
|
|||||||
tokenType: `${baseUrl}/token_type`,
|
tokenType: `${baseUrl}/token_type`,
|
||||||
unitType: `${baseUrl}/unit_type`,
|
unitType: `${baseUrl}/unit_type`,
|
||||||
goodPricingModel: `${baseUrl}/good_pricing_model`,
|
goodPricingModel: `${baseUrl}/good_pricing_model`,
|
||||||
|
consumerRole: `${baseUrl}/consumer_role`,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user