ui update, init to consumer statistics and manage pos user types
This commit is contained in:
@@ -43,7 +43,7 @@ export const errorInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
errorMessage = 'منبع مورد نظر یافت نشد';
|
||||
break;
|
||||
case 412:
|
||||
errorMessage = error.error?.detail || 'اطلاعات ارسالی نامعتبر است';
|
||||
errorMessage = error.error?.message || '';
|
||||
break;
|
||||
case 422:
|
||||
errorMessage = error.error?.message || 'اطلاعات ارسالی نامعتبر است';
|
||||
@@ -118,6 +118,7 @@ function showErrorNotification(message: string, status: number): void {
|
||||
* Error types for better error handling
|
||||
*/
|
||||
export enum ErrorType {
|
||||
PRE_CONDITION = 'PRE_CONDITION',
|
||||
NETWORK = 'NETWORK',
|
||||
SERVER = 'SERVER',
|
||||
CLIENT = 'CLIENT',
|
||||
@@ -136,9 +137,10 @@ export function getErrorType(error: HttpErrorResponse): ErrorType {
|
||||
|
||||
switch (error.status) {
|
||||
case 400:
|
||||
case 412:
|
||||
case 422:
|
||||
return ErrorType.VALIDATION;
|
||||
case 412:
|
||||
return ErrorType.PRE_CONDITION;
|
||||
case 401:
|
||||
return ErrorType.AUTHENTICATION;
|
||||
case 403:
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { computed, inject, Injectable, signal } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
import { BehaviorSubject, Observable, throwError } from 'rxjs';
|
||||
import { catchError, finalize, tap } from 'rxjs/operators';
|
||||
import { LOCAL_STORAGE_KEYS } from '../../../assets/constants';
|
||||
import { COOKIE_KEYS, LOCAL_STORAGE_KEYS } from '../../../assets/constants';
|
||||
import {
|
||||
IAuthAccountResponse,
|
||||
IAuthResponse,
|
||||
@@ -28,6 +29,7 @@ export class AuthService {
|
||||
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly router = inject(Router);
|
||||
private readonly cookieService = inject(CookieService);
|
||||
private captchaService = inject(CaptchaService);
|
||||
|
||||
private readonly currentAccountSubject = new BehaviorSubject<Maybe<IAuthAccountResponse>>(null);
|
||||
@@ -81,6 +83,7 @@ export class AuthService {
|
||||
.pipe(
|
||||
tap((response) => {
|
||||
this.handleAuthSuccess(response);
|
||||
this.refreshCookies();
|
||||
return response;
|
||||
}),
|
||||
catchError((error) => {
|
||||
@@ -98,11 +101,17 @@ export class AuthService {
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEYS.AUTH_TOKEN);
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEYS.USER_DATA);
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEYS.REFRESH_TOKEN);
|
||||
this.refreshCookies();
|
||||
|
||||
this.setCurrentUser(null);
|
||||
this.router.navigate(['/auth']);
|
||||
}
|
||||
|
||||
refreshCookies() {
|
||||
this.cookieService.set(COOKIE_KEYS.POS_ID, '', new Date());
|
||||
this.cookieService.set(COOKIE_KEYS.ACCESS_TOKEN, '', new Date());
|
||||
}
|
||||
|
||||
doRefreshToken(): Observable<IAuthResponse> {
|
||||
const refreshToken = this.getRefreshToken();
|
||||
if (!refreshToken) {
|
||||
|
||||
@@ -26,33 +26,33 @@ export class ErrorHandlerService {
|
||||
*/
|
||||
private handleHttpError(error: HttpErrorResponse): void {
|
||||
const errorType = getErrorType(error);
|
||||
|
||||
const userMessage = this.getUserMessage(error);
|
||||
|
||||
if (userMessage) {
|
||||
this.toastService.error({
|
||||
title: error.error?.title || 'خطا',
|
||||
text: userMessage,
|
||||
});
|
||||
} else {
|
||||
switch (errorType) {
|
||||
case ErrorType.NETWORK:
|
||||
this.showNetworkError(userMessage);
|
||||
break;
|
||||
case ErrorType.AUTHENTICATION:
|
||||
this.showAuthError(userMessage);
|
||||
break;
|
||||
case ErrorType.AUTHORIZATION:
|
||||
this.showAuthorizationError(userMessage);
|
||||
break;
|
||||
case ErrorType.VALIDATION:
|
||||
this.showValidationError(userMessage, error);
|
||||
break;
|
||||
case ErrorType.SERVER:
|
||||
this.showServerError(userMessage);
|
||||
break;
|
||||
default:
|
||||
this.showGenericError(userMessage);
|
||||
}
|
||||
switch (errorType) {
|
||||
case ErrorType.NETWORK:
|
||||
this.showNetworkError(userMessage);
|
||||
break;
|
||||
case ErrorType.PRE_CONDITION:
|
||||
this.showPreConditionError(userMessage);
|
||||
break;
|
||||
case ErrorType.AUTHENTICATION:
|
||||
this.showAuthError(userMessage);
|
||||
break;
|
||||
case ErrorType.AUTHORIZATION:
|
||||
this.showAuthorizationError(userMessage);
|
||||
break;
|
||||
case ErrorType.VALIDATION:
|
||||
this.showValidationError(userMessage, error);
|
||||
break;
|
||||
case ErrorType.SERVER:
|
||||
this.showServerError(userMessage);
|
||||
break;
|
||||
case ErrorType.SERVER:
|
||||
this.showServerError(userMessage);
|
||||
break;
|
||||
default:
|
||||
this.showGenericError(userMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ export class ErrorHandlerService {
|
||||
* Handle generic JavaScript errors
|
||||
*/
|
||||
private handleGenericError(error: any): void {
|
||||
console.error('Generic error:', error);
|
||||
this.toastService.error({
|
||||
text: 'یک خطای غیرمنتظره رخ داده است. لطفاً صفحه را تازهسازی کنید.',
|
||||
});
|
||||
@@ -76,6 +75,15 @@ export class ErrorHandlerService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show preCondition error notification
|
||||
*/
|
||||
private showPreConditionError(message: string): void {
|
||||
this.toastService.warn({
|
||||
text: message,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show authentication error notification
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Signal, WritableSignal, computed, signal } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { Maybe } from '../models';
|
||||
@@ -8,7 +9,7 @@ import { IPaginatedQuery, IResponseMetadata } from '../models/service.model';
|
||||
*/
|
||||
export interface BaseState {
|
||||
loading: boolean;
|
||||
error: Maybe<string>;
|
||||
error: Maybe<HttpErrorResponse>;
|
||||
isRefreshing?: boolean;
|
||||
initialized: boolean;
|
||||
}
|
||||
@@ -72,6 +73,15 @@ export interface StateChange<T = any> {
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export const defaultBaseStateData = {
|
||||
loading: false,
|
||||
error: null,
|
||||
errorStatus: null,
|
||||
entity: null,
|
||||
initialized: false,
|
||||
isRefreshing: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Base store class with common functionality
|
||||
*/
|
||||
@@ -82,7 +92,7 @@ export abstract class BaseStore<T extends BaseState> {
|
||||
// Public readonly signals
|
||||
readonly state: Signal<T>;
|
||||
readonly loading: Signal<boolean>;
|
||||
readonly error: Signal<Maybe<string>>;
|
||||
readonly error: Signal<Maybe<HttpErrorResponse>>;
|
||||
readonly initialized: Signal<boolean>;
|
||||
|
||||
// Observable for RxJS compatibility
|
||||
@@ -135,7 +145,7 @@ export abstract class BaseStore<T extends BaseState> {
|
||||
/**
|
||||
* Set error state
|
||||
*/
|
||||
protected setError(error: string): void {
|
||||
protected setError(error: HttpErrorResponse): void {
|
||||
this.patchState({
|
||||
loading: false,
|
||||
error,
|
||||
@@ -180,6 +190,7 @@ export abstract class EntityStore<
|
||||
setEntity(entity: Maybe<T>): void {
|
||||
this.patchState({
|
||||
entity,
|
||||
error: null,
|
||||
} as Partial<TState>);
|
||||
}
|
||||
override reset(): void {
|
||||
|
||||
Reference in New Issue
Block a user