diff --git a/app/src/app/app.component.html b/app/src/app/app.component.html
index 5e19703..5db2da5 100644
--- a/app/src/app/app.component.html
+++ b/app/src/app/app.component.html
@@ -1,4 +1,4 @@
-
+
-
+
-
-
+
+
diff --git a/app/src/app/app.component.ts b/app/src/app/app.component.ts
index 8e171e5..2015f11 100644
--- a/app/src/app/app.component.ts
+++ b/app/src/app/app.component.ts
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from './state/app.state';
-import { combineLatest, map, Observable } from 'rxjs';
+import { Observable } from 'rxjs';
import { areLibrariesLoaded } from './state/init/init.selectors';
import {
isLoading,
@@ -11,8 +11,8 @@ import {
getBottomItems,
getTopItems,
} from './state/components/menu/menu.selector';
-import { isMapLoading } from './state/map/map.selectors';
-import { hasError } from './state/errors/error.selectors';
+import { clientHasErrorConnection } from './state/errors/error.selectors';
+import { cleanError } from './state/errors/error.actions';
@Component({
selector: 'app-root',
@@ -23,19 +23,21 @@ export class AppComponent implements OnInit {
topMenuItems$ = this.store.select(getTopItems);
bottomMenuItems$ = this.store.select(getBottomItems);
isLoading$: Observable = this.store.select(isLoading);
- isMapLoading$: Observable = this.store.select(isMapLoading);
- hasError$: Observable = this.store.select(hasError);
- librariesAreLoaded$: Observable =
- this.store.select(areLibrariesLoaded);
- canShowPage$ = combineLatest([this.librariesAreLoaded$, this.hasError$]).pipe(
- map(([librariesAreLoaded, hasError]) => librariesAreLoaded || hasError),
+ public alertButtons = [
+ {
+ text: 'OK',
+ role: 'confirm',
+ handler: () => {
+ this.store.dispatch(cleanError());
+ },
+ },
+ ];
+ hasConnectionError$: Observable = this.store.select(
+ clientHasErrorConnection,
);
+ canShowPage$ = this.store.select(areLibrariesLoaded);
- constructor(private store: Store) {
- this.canShowPage$.subscribe((canShowPage) => {
- console.log('canShowPage', canShowPage);
- });
- }
+ constructor(private store: Store) {}
ngOnInit(): void {}
}
diff --git a/app/src/app/pages/reservations/reservations.page.html b/app/src/app/pages/reservations/reservations.page.html
index 440430e..00ca5da 100644
--- a/app/src/app/pages/reservations/reservations.page.html
+++ b/app/src/app/pages/reservations/reservations.page.html
@@ -9,7 +9,7 @@
-
+
{{ res.refuge.name }}
@@ -36,4 +36,23 @@
+
+
+
+
+
+
+
diff --git a/app/src/app/pages/reservations/reservations.page.ts b/app/src/app/pages/reservations/reservations.page.ts
index ebcfd61..3ae0755 100644
--- a/app/src/app/pages/reservations/reservations.page.ts
+++ b/app/src/app/pages/reservations/reservations.page.ts
@@ -5,7 +5,11 @@ import { TranslateService } from '@ngx-translate/core';
import { Store } from '@ngrx/store';
import { AppState } from '../../state/app.state';
import { deleteReservation } from '../../state/reservations/reservations.actions';
-import { getReservationsSortedByRefuge } from '../../state/reservations/reservations.selectors';
+import {
+ deletedReservation,
+ getDeleteReservationErrors,
+ getReservationsSortedByRefuge,
+} from '../../state/reservations/reservations.selectors';
@Component({
selector: 'app-reservations',
@@ -13,11 +17,13 @@ import { getReservationsSortedByRefuge } from '../../state/reservations/reservat
styleUrls: ['./reservations.page.scss'],
})
export class ReservationsPage implements OnInit {
- reservations = this.store.select(getReservationsSortedByRefuge);
+ reservations$ = this.store.select(getReservationsSortedByRefuge);
+ deleteErrors$ = this.store.select(getDeleteReservationErrors);
+ deletedReservation$ = this.store.select(deletedReservation);
onRemoveReservation(reservation: ReservationWithId) {
this.showDeleteReservationMessage(reservation, () => {
- this.removeReservation(reservation);
+ this.store.dispatch(deleteReservation({ id: reservation.id }));
}).then();
}
@@ -27,10 +33,6 @@ export class ReservationsPage implements OnInit {
private translateService: TranslateService,
) {}
- private removeReservation(reservation: ReservationWithId) {
- this.store.dispatch(deleteReservation({ id: reservation.id }));
- }
-
private async showDeleteReservationMessage(
reservation: ReservationWithId,
onClick: () => void,
diff --git a/app/src/app/schemas/errors/common.ts b/app/src/app/schemas/errors/common.ts
new file mode 100644
index 0000000..8bae00d
--- /dev/null
+++ b/app/src/app/schemas/errors/common.ts
@@ -0,0 +1,3 @@
+export enum CommonErrors {
+ PROGRAMMING_ERROR = 'PROGRAMMING_ERROR',
+}
diff --git a/app/src/app/schemas/errors/permissions.ts b/app/src/app/schemas/errors/permissions.ts
new file mode 100644
index 0000000..1817251
--- /dev/null
+++ b/app/src/app/schemas/errors/permissions.ts
@@ -0,0 +1,4 @@
+export enum PermissionsErrors {
+ NOT_ALLOWED_OPERATION_FOR_USER = 'NOT_ALLOWED_OPERATION_FOR_USER',
+ NOT_AUTHENTICATED = 'NOT_AUTHENTICATED',
+}
diff --git a/app/src/app/schemas/reservations/create-reservation.ts b/app/src/app/schemas/reservations/create-reservation.ts
index d311cbf..3f6a165 100644
--- a/app/src/app/schemas/reservations/create-reservation.ts
+++ b/app/src/app/schemas/reservations/create-reservation.ts
@@ -1,21 +1,22 @@
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { isMatching, match } from 'ts-pattern';
-import {
- Reservation,
- ReservationPattern,
- ReservationWithId,
-} from './reservation';
+import { ReservationPattern, ReservationWithId } from './reservation';
+import { ServerErrors } from '../errors/server';
+import { PermissionsErrors } from '../errors/permissions';
+import { CommonErrors } from '../errors/common';
-export enum CreateReservationError {
+export enum CreateReservationDataError {
REFUGE_OR_USER_NOT_FOUND = 'REFUGE_OR_USER_NOT_FOUND',
- PROGRAMMING_ERROR = 'PROGRAMMING_ERROR',
- SERVER_ERROR = 'SERVER_DATA_ERROR',
- NOT_ALLOWED_CREATION_FOR_USER = 'NOT_ALLOWED_CREATION_FOR_USER',
- NOT_AUTHENTICATED_OR_INVALID_DATE = 'NOT_AUTHENTICATED_OR_INVALID_DATE',
- UNKNOWN_ERROR = 'UNKNOWN_ERROR',
+ INVALID_DATE = 'INVALID_DATE',
NTP_SERVER_IS_DOWN = 'NTP_SERVER_IS_DOWN',
}
+export type CreateReservationError =
+ | CreateReservationDataError
+ | ServerErrors
+ | PermissionsErrors
+ | CommonErrors;
+
export namespace CreateReservationError {
export function from(
error: HttpErrorResponse,
@@ -24,27 +25,32 @@ export namespace CreateReservationError {
.with(0, () => {
throw new Error('You are offline or the server is down.');
})
- .with(
- HttpStatusCode.Unauthorized,
- () => CreateReservationError.NOT_AUTHENTICATED_OR_INVALID_DATE,
- )
+ .with(HttpStatusCode.Unauthorized, () => {
+ if (
+ error.message.includes(
+ 'You are not allowed to get a reservation of another user',
+ )
+ )
+ return CreateReservationDataError.INVALID_DATE;
+ return PermissionsErrors.NOT_AUTHENTICATED;
+ })
.with(
HttpStatusCode.NotFound,
- () => CreateReservationError.REFUGE_OR_USER_NOT_FOUND,
+ () => CreateReservationDataError.REFUGE_OR_USER_NOT_FOUND,
)
.with(
HttpStatusCode.Forbidden,
- () => CreateReservationError.NOT_ALLOWED_CREATION_FOR_USER,
+ () => PermissionsErrors.NOT_ALLOWED_OPERATION_FOR_USER,
)
.with(
HttpStatusCode.UnprocessableEntity,
- () => CreateReservationError.PROGRAMMING_ERROR,
+ () => CommonErrors.PROGRAMMING_ERROR,
)
.with(
HttpStatusCode.InternalServerError,
- () => CreateReservationError.NTP_SERVER_IS_DOWN,
+ () => CreateReservationDataError.NTP_SERVER_IS_DOWN,
)
- .otherwise(() => CreateReservationError.UNKNOWN_ERROR);
+ .otherwise(() => ServerErrors.UNKNOWN_ERROR);
}
}
@@ -65,7 +71,7 @@ export type CreateReservation =
export function fromResponse(response: any): CreateReservation {
if (isMatching(ReservationPattern, response))
return { status: 'ok', reservation: response };
- return { status: 'error', error: CreateReservationError.SERVER_ERROR };
+ return { status: 'error', error: ServerErrors.INCORRECT_DATA_FORMAT };
}
export function fromError(error: HttpErrorResponse): CreateReservation | never {
diff --git a/app/src/app/schemas/reservations/delete-reservation.ts b/app/src/app/schemas/reservations/delete-reservation.ts
index bb339ea..2b4251a 100644
--- a/app/src/app/schemas/reservations/delete-reservation.ts
+++ b/app/src/app/schemas/reservations/delete-reservation.ts
@@ -5,16 +5,22 @@ import {
ReservationPattern,
ReservationWithId,
} from './reservation';
+import { ServerErrors } from '../errors/server';
+import { PermissionsErrors } from '../errors/permissions';
+import { CommonErrors } from '../errors/common';
+import { CreateReservationDataError } from './create-reservation';
+import { AuthenticationErrors } from '../auth/errors';
-export enum DeleteReservationError {
+export enum DeleteReservationDataError {
RESERVATION_NOT_FOUND = 'RESERVATION_NOT_FOUND',
- PROGRAMMING_ERROR = 'PROGRAMMING_ERROR',
- SERVER_ERROR = 'SERVER_DATA_ERROR',
- NOT_ALLOWED_DELETION_FOR_USER = 'NOT_ALLOWED_DELETION_FOR_USER',
- NOT_AUTHENTICATED = 'NOT_AUTHENTICATED',
- UNKNOWN_ERROR = 'UNKNOWN_ERROR',
}
+export type DeleteReservationError =
+ | DeleteReservationDataError
+ | ServerErrors
+ | PermissionsErrors
+ | CommonErrors;
+
export namespace DeleteReservationError {
export function from(
error: HttpErrorResponse,
@@ -25,21 +31,21 @@ export namespace DeleteReservationError {
})
.with(
HttpStatusCode.Unauthorized,
- () => DeleteReservationError.NOT_AUTHENTICATED,
+ () => PermissionsErrors.NOT_AUTHENTICATED,
)
.with(
HttpStatusCode.NotFound,
- () => DeleteReservationError.RESERVATION_NOT_FOUND,
+ () => DeleteReservationDataError.RESERVATION_NOT_FOUND,
)
.with(
HttpStatusCode.Forbidden,
- () => DeleteReservationError.NOT_ALLOWED_DELETION_FOR_USER,
+ () => PermissionsErrors.NOT_ALLOWED_OPERATION_FOR_USER,
)
.with(
HttpStatusCode.UnprocessableEntity,
- () => DeleteReservationError.PROGRAMMING_ERROR,
+ () => CommonErrors.PROGRAMMING_ERROR,
)
- .otherwise(() => DeleteReservationError.UNKNOWN_ERROR);
+ .otherwise(() => ServerErrors.UNKNOWN_ERROR);
}
}
@@ -60,7 +66,7 @@ export type DeleteReservation =
export function fromResponse(response: any): DeleteReservation {
if (isMatching(ReservationPattern, response))
return { status: 'ok', reservation: response };
- return { status: 'error', error: DeleteReservationError.SERVER_ERROR };
+ return { status: 'error', error: ServerErrors.INCORRECT_DATA_FORMAT };
}
export function fromError(error: HttpErrorResponse): DeleteReservation | never {
diff --git a/app/src/app/state/components/loading/loading.selector.ts b/app/src/app/state/components/loading/loading.selector.ts
index 4c401ab..c48fc4a 100644
--- a/app/src/app/state/components/loading/loading.selector.ts
+++ b/app/src/app/state/components/loading/loading.selector.ts
@@ -1,6 +1,7 @@
import { createSelector } from '@ngrx/store';
import { selectAuth } from '../../auth/auth.selectors';
import { selectCreateUser } from '../../create-user/create-user.selectors';
+import { selectMap } from '../../map/map.selectors';
export type LoadingState = {
isLoading: boolean;
@@ -10,7 +11,8 @@ export type LoadingState = {
export const isLoading = createSelector(
selectAuth,
selectCreateUser,
- (auth, create) => {
+ selectMap,
+ (auth, create, map) => {
if (auth.isLoading)
return { isLoading: true, keyMessage: 'LOGIN.LOADING' } as LoadingState;
if (create.isLoading)
@@ -18,6 +20,11 @@ export const isLoading = createSelector(
isLoading: true,
keyMessage: 'SIGNUP.LOADING',
} as LoadingState;
+ if (map.loadingMap)
+ return {
+ isLoading: true,
+ keyMessage: 'TODO: LOADING_MAP',
+ } as LoadingState;
return { isLoading: false } as LoadingState;
},
);
diff --git a/app/src/app/state/create-user/create-user.actions.ts b/app/src/app/state/create-user/create-user.actions.ts
index c6dd251..5a6e632 100644
--- a/app/src/app/state/create-user/create-user.actions.ts
+++ b/app/src/app/state/create-user/create-user.actions.ts
@@ -8,6 +8,10 @@ export const createUserRequest = createAction(
props<{ credentials: UserForm }>(),
);
+export const createUserDevicesError = createAction(
+ '[User] Create User Device Error',
+);
+
export const createUserError = createAction(
'[User] Create User Error',
props<{
diff --git a/app/src/app/state/create-user/create-user.effects.ts b/app/src/app/state/create-user/create-user.effects.ts
index 0bbfdff..28f9baa 100644
--- a/app/src/app/state/create-user/create-user.effects.ts
+++ b/app/src/app/state/create-user/create-user.effects.ts
@@ -2,9 +2,10 @@ import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { UserService } from '../../services/user/user.service';
import { loginRequest } from '../auth/auth.actions';
-import { map, of, switchMap } from 'rxjs';
+import { catchError, map, of, switchMap } from 'rxjs';
import {
createUserCorrect,
+ createUserDevicesError,
createUserError,
createUserRequest,
} from './create-user.actions';
@@ -18,7 +19,11 @@ import {
import { ServerErrors } from '../../schemas/errors/server';
import { CreateUserError } from '../../schemas/user/create/create-user-error';
import { CreateUserResponse } from '../../schemas/user/create/create-user-response';
-import { programmingError, unknownError } from '../errors/error.actions';
+import {
+ connectionError,
+ programmingError,
+ unknownError,
+} from '../errors/error.actions';
@Injectable()
export class CreateUserEffects {
@@ -64,6 +69,7 @@ export class CreateUserEffects {
map((response) =>
this.getNewStateFromUserCreateServer(response, createUserData),
),
+ catchError((error) => [connectionError(), createUserDevicesError()]),
);
}
diff --git a/app/src/app/state/create-user/create-user.reducer.ts b/app/src/app/state/create-user/create-user.reducer.ts
index 52f5bf3..34a2401 100644
--- a/app/src/app/state/create-user/create-user.reducer.ts
+++ b/app/src/app/state/create-user/create-user.reducer.ts
@@ -3,6 +3,7 @@ import { RepeatedData } from '../../schemas/user/create/create-user-error';
import { UserFormError } from '../../schemas/user/validate/form';
import {
createUserCorrect,
+ createUserDevicesError,
createUserError,
createUserRequest,
} from './create-user.actions';
@@ -54,4 +55,8 @@ export const createUserReducer = createReducer(
isLoading: false,
error: action.error,
})),
+ on(createUserDevicesError, (state, action) => ({
+ ...state,
+ isLoading: false,
+ })),
);
diff --git a/app/src/app/state/errors/error.actions.ts b/app/src/app/state/errors/error.actions.ts
index dd4bd7e..e1d3e3c 100644
--- a/app/src/app/state/errors/error.actions.ts
+++ b/app/src/app/state/errors/error.actions.ts
@@ -4,6 +4,8 @@ export const resourceNotFound = createAction('[Error] Resource Not Found');
export const programmingError = createAction('[Error] Programming Error');
+export const connectionError = createAction('[Error] Connection Error');
+
export const unknownError = createAction('[Error] Unknown Error');
export const cleanError = createAction('[Error] Clean Error');
diff --git a/app/src/app/state/errors/error.reducer.ts b/app/src/app/state/errors/error.reducer.ts
index 2e9007f..339d89b 100644
--- a/app/src/app/state/errors/error.reducer.ts
+++ b/app/src/app/state/errors/error.reducer.ts
@@ -1,9 +1,19 @@
import { createReducer, on } from '@ngrx/store';
-import { cleanError, resourceNotFound, unknownError } from './error.actions';
+import {
+ cleanError,
+ connectionError,
+ resourceNotFound,
+ unknownError,
+} from './error.actions';
export type ErrorState = {
hasError: boolean;
- type: 'resourceNotFound' | 'programmingError' | 'unknownError' | undefined;
+ type:
+ | 'resourceNotFound'
+ | 'programmingError'
+ | 'unknownError'
+ | 'connectionError'
+ | undefined;
};
export const reservationState = {
@@ -24,6 +34,10 @@ export const errorReducer = createReducer(
hasError: true,
type: 'programmingError',
})),
+ on(connectionError, (state, action) => ({
+ hasError: true,
+ type: 'connectionError',
+ })),
on(cleanError, (state, action) => ({
hasError: false,
type: undefined,
diff --git a/app/src/app/state/errors/error.selectors.ts b/app/src/app/state/errors/error.selectors.ts
index e5c3825..284f952 100644
--- a/app/src/app/state/errors/error.selectors.ts
+++ b/app/src/app/state/errors/error.selectors.ts
@@ -7,3 +7,8 @@ export const hasError = createSelector(
selectError,
(errorState) => errorState.hasError,
);
+
+export const clientHasErrorConnection = createSelector(
+ selectError,
+ (errorState) => errorState.type === 'connectionError',
+);
diff --git a/app/src/app/state/init/init.effects.ts b/app/src/app/state/init/init.effects.ts
index 9afb740..6bdb1cd 100644
--- a/app/src/app/state/init/init.effects.ts
+++ b/app/src/app/state/init/init.effects.ts
@@ -13,7 +13,7 @@ import {
} from './init.actions';
import { fromPromise } from 'rxjs/internal/observable/innerFrom';
import { secretEnvironment } from '../../../environments/environment.secret';
-import { unknownError } from '../errors/error.actions';
+import { connectionError, unknownError } from '../errors/error.actions';
@Injectable()
export class InitEffects {
@@ -32,7 +32,7 @@ export class InitEffects {
switchMap((createData) =>
fromPromise(this.fetchGoogleMapsLibrary()).pipe(
map(() => loadedMapLibrary()),
- catchError(() => [unknownError(), errorLoadingMapLibrary()]),
+ catchError(() => [connectionError(), errorLoadingMapLibrary()]),
),
),
),
diff --git a/app/src/app/state/map/map.effects.ts b/app/src/app/state/map/map.effects.ts
index 75afc16..f399703 100644
--- a/app/src/app/state/map/map.effects.ts
+++ b/app/src/app/state/map/map.effects.ts
@@ -24,7 +24,11 @@ import {
moveMapTo,
} from './map.actions';
import { loadedMapLibrary } from '../init/init.actions';
-import { programmingError, unknownError } from '../errors/error.actions';
+import {
+ connectionError,
+ programmingError,
+ unknownError,
+} from '../errors/error.actions';
import { match } from 'ts-pattern';
import { GetAllRefugesErrors } from '../../schemas/refuge/get-all-refuges-schema';
@@ -81,6 +85,7 @@ export class MapEffects {
return loadedRefuges({ refuges: refuges.data });
return loadRefugesError({ error: refuges.error });
}),
+ catchError(() => of(connectionError())),
),
);
diff --git a/app/src/app/state/reservations/reservations.actions.ts b/app/src/app/state/reservations/reservations.actions.ts
index 5835a48..1200571 100644
--- a/app/src/app/state/reservations/reservations.actions.ts
+++ b/app/src/app/state/reservations/reservations.actions.ts
@@ -5,10 +5,12 @@ import {
} from '../../schemas/reservations/reservation';
import { RefugeReservationsRelations } from '../../services/reservations/grouped-by/refuge';
import {
+ CreateReservationDataError,
CreateReservationError,
ErrorCreateReservation,
} from '../../schemas/reservations/create-reservation';
import {
+ DeleteReservationDataError,
DeleteReservationError,
ErrorDeleteReservation,
} from '../../schemas/reservations/delete-reservation';
@@ -28,16 +30,28 @@ export const fetchReservations = createAction(
props<{ reservations: RefugeReservationsRelations }>(),
);
+export const connectionErrorFetchReservations = createAction(
+ '[Reservations] Fetch Reservations had a connection error',
+);
+
export const errorAddingReservation = createAction(
'[Reservations] Error Adding Reservation',
props<{ error: CreateReservationError }>(),
);
+export const connectionErrorAddReservation = createAction(
+ '[Reservations] Add Reservation had a connection error',
+);
+
export const deleteReservation = createAction(
'[Reservations] Delete Reservation',
props<{ id: string }>(),
);
+export const connectionErrorDeleteReservation = createAction(
+ '[Reservations] Delete Reservation had a connection error',
+);
+
export const deletedReservation = createAction(
'[Reservations] Deleted Reservation',
props<{ reservation: ReservationWithId }>(),
diff --git a/app/src/app/state/reservations/reservations.effects.ts b/app/src/app/state/reservations/reservations.effects.ts
index f584f48..c877cf8 100644
--- a/app/src/app/state/reservations/reservations.effects.ts
+++ b/app/src/app/state/reservations/reservations.effects.ts
@@ -5,12 +5,15 @@ import {
ofType,
ROOT_EFFECTS_INIT,
} from '@ngrx/effects';
-import { combineLatest, map, mergeMap, switchMap } from 'rxjs';
+import { catchError, combineLatest, map, mergeMap, of, switchMap } from 'rxjs';
import { loginCompleted } from '../auth/auth.actions';
import { UserReservationService } from '../../services/reservations/user-reservation.service';
import {
addedReservation,
addReservation,
+ connectionErrorAddReservation,
+ connectionErrorDeleteReservation,
+ connectionErrorFetchReservations,
deletedReservation,
deleteReservation,
errorAddingReservation,
@@ -43,9 +46,8 @@ export class ReservationsEffects {
this.userReservationService
.getReservationsGroupedByRefugeForUser(actions[0].userId)
.pipe(
- map((reservations) => {
- return fetchReservations({ reservations });
- }),
+ map((reservations) => fetchReservations({ reservations })),
+ catchError(() => of(connectionErrorFetchReservations())),
),
),
),
@@ -65,6 +67,7 @@ export class ReservationsEffects {
});
return errorDeletingReservation({ error: reservations.error });
}),
+ catchError(() => of(connectionErrorDeleteReservation())),
),
),
),
@@ -89,6 +92,7 @@ export class ReservationsEffects {
});
return errorAddingReservation({ error: reservations.error });
}),
+ catchError(() => of(connectionErrorAddReservation())),
),
),
),
@@ -107,6 +111,7 @@ export class ReservationsEffects {
orderByRefuge(reservations, this.reservationFactory),
),
map((reservations) => fetchReservations({ reservations })),
+ catchError(() => of(connectionErrorFetchReservations())),
),
),
),
diff --git a/app/src/app/state/reservations/reservations.reducer.ts b/app/src/app/state/reservations/reservations.reducer.ts
index 26527d2..5782296 100644
--- a/app/src/app/state/reservations/reservations.reducer.ts
+++ b/app/src/app/state/reservations/reservations.reducer.ts
@@ -2,6 +2,9 @@ import { createReducer, on } from '@ngrx/store';
import {
addedReservation,
addReservation,
+ connectionErrorAddReservation,
+ connectionErrorDeleteReservation,
+ connectionErrorFetchReservations,
deletedReservation,
deleteReservation,
errorAddingReservation,
@@ -9,54 +12,83 @@ import {
fetchReservations,
} from './reservations.actions';
import { RefugeReservationsRelations } from '../../services/reservations/grouped-by/refuge';
+import { CreateReservationError } from '../../schemas/reservations/create-reservation';
+import { DeleteReservationError } from '../../schemas/reservations/delete-reservation';
export type ReservationsState = {
reservations: RefugeReservationsRelations;
- createError?: any;
- deleteError?: any;
+ createError?: CreateReservationError;
+ deleteError?: DeleteReservationError;
isLoading: boolean;
+ hasNewReservation: boolean;
+ hasDeletedReservation: boolean;
};
export const reservationState = {
reservations: [],
isLoading: false,
+ hasNewReservation: false,
+ hasDeletedReservation: false,
} as ReservationsState;
export const reservationsReducer = createReducer(
reservationState,
on(deleteReservation, (state, action) => ({
- ...state,
- deleteError: undefined,
+ reservations: state.reservations,
+ hasNewReservation: false,
+ hasDeletedReservation: false,
isLoading: true,
})),
on(fetchReservations, (state, action) => ({
- ...state,
+ hasNewReservation: true,
+ hasDeletedReservation: false,
+ isLoading: false,
reservations: action.reservations,
})),
- on(addReservation, (state, action) => ({
+ on(connectionErrorFetchReservations, (state, action) => ({
...state,
- createError: undefined,
+ isLoading: false,
+ })),
+ on(connectionErrorAddReservation, (state, action) => ({
+ ...state,
+ isLoading: false,
+ })),
+ on(connectionErrorDeleteReservation, (state, action) => ({
+ ...state,
+ isLoading: false,
+ })),
+ on(addReservation, (state, action) => ({
+ reservations: state.reservations,
+ hasNewReservation: false,
+ hasDeletedReservation: false,
isLoading: true,
})),
on(addedReservation, (state, action) => ({
- ...state,
+ reservations: state.reservations,
+ hasNewReservation: true,
+ hasDeletedReservation: false,
isLoading: false,
})),
on(deletedReservation, (state, action) => ({
- ...state,
isLoading: false,
reservations: removeReservationWithId(
action.reservation.id,
state.reservations,
),
+ hasNewReservation: false,
+ hasDeletedReservation: true,
})),
on(errorAddingReservation, (state, action) => ({
- ...state,
+ reservations: state.reservations,
+ hasNewReservation: false,
+ hasDeletedReservation: false,
isLoading: false,
createError: action.error,
})),
on(errorDeletingReservation, (state, action) => ({
- ...state,
+ reservations: state.reservations,
+ hasNewReservation: false,
+ hasDeletedReservation: false,
isLoading: false,
deleteError: action.error,
})),
@@ -66,12 +98,17 @@ function removeReservationWithId(
id: string,
reservations: RefugeReservationsRelations,
) {
- return reservations.map((relation) => {
- return {
- ...relation,
- reservations: relation.reservations.filter(
+ return reservations
+ .map((relation) => {
+ const newReservations = relation.reservations.filter(
(reservation) => reservation.id !== id,
- ),
- };
- });
+ );
+ if (newReservations.length !== 0)
+ return {
+ ...relation,
+ reservations: newReservations,
+ };
+ return null;
+ })
+ .filter((relation) => relation !== null) as RefugeReservationsRelations;
}
diff --git a/app/src/app/state/reservations/reservations.selectors.ts b/app/src/app/state/reservations/reservations.selectors.ts
index 9de912d..30f7cb4 100644
--- a/app/src/app/state/reservations/reservations.selectors.ts
+++ b/app/src/app/state/reservations/reservations.selectors.ts
@@ -1,5 +1,11 @@
import { createSelector } from '@ngrx/store';
import { AppState } from '../app.state';
+import { match } from 'ts-pattern';
+import { DeleteReservationDataError } from '../../schemas/reservations/delete-reservation';
+import { ServerErrors } from '../../schemas/errors/server';
+import { PermissionsErrors } from '../../schemas/errors/permissions';
+import { CommonErrors } from '../../schemas/errors/common';
+import { CreateReservationDataError } from '../../schemas/reservations/create-reservation';
export const selectReservations = (state: AppState) => state.reservations;
@@ -10,10 +16,80 @@ export const getReservationsSortedByRefuge = createSelector(
export const getCreateReservationErrors = createSelector(
selectReservations,
- (reservations) => reservations.createError,
+ (reservations) => {
+ if (reservations.createError) {
+ return match(reservations.createError)
+ .with(
+ CreateReservationDataError.INVALID_DATE,
+ () => 'TODO: INVALID_DATE_STRING',
+ )
+ .with(
+ CreateReservationDataError.NTP_SERVER_IS_DOWN,
+ () => 'TODO: NTP_SERVER_IS_DOWN_STRING',
+ )
+ .with(
+ CreateReservationDataError.REFUGE_OR_USER_NOT_FOUND,
+ () => 'TODO: REFUGE_OR_USER_NOT_FOUND_STRING',
+ )
+ .with(
+ ServerErrors.UNKNOWN_ERROR,
+ ServerErrors.INCORRECT_DATA_FORMAT,
+ () => 'TODO: SERVER_ERROR_STRING',
+ )
+ .with(
+ PermissionsErrors.NOT_ALLOWED_OPERATION_FOR_USER,
+ PermissionsErrors.NOT_AUTHENTICATED,
+ () => 'TODO: PERMISSIONS_ERROR_STRING',
+ )
+ .with(
+ CommonErrors.PROGRAMMING_ERROR,
+ () => 'TODO: PROGRAMMING_ERROR_STRING',
+ )
+ .exhaustive();
+ }
+ return null;
+ },
);
-export const isLoadingReservations = createSelector(
+export const getDeleteReservationErrors = createSelector(
+ selectReservations,
+ (reservations) => {
+ if (reservations.deleteError)
+ return match(reservations.deleteError)
+ .with(
+ DeleteReservationDataError.RESERVATION_NOT_FOUND,
+ () => 'TODO: RESERVATION_NOT_FOUND_STRING',
+ )
+ .with(
+ ServerErrors.UNKNOWN_ERROR,
+ ServerErrors.INCORRECT_DATA_FORMAT,
+ () => 'TODO: SERVER_ERROR_STRING',
+ )
+ .with(
+ PermissionsErrors.NOT_ALLOWED_OPERATION_FOR_USER,
+ PermissionsErrors.NOT_AUTHENTICATED,
+ () => 'TODO: PERMISSIONS_ERROR_STRING',
+ )
+ .with(
+ CommonErrors.PROGRAMMING_ERROR,
+ () => 'TODO: PROGRAMMING_ERROR_STRING',
+ )
+ .exhaustive();
+ return null;
+ },
+);
+
+export const addedNewReservation = createSelector(
+ selectReservations,
+ (reservations) => reservations.hasNewReservation,
+);
+
+export const deletedReservation = createSelector(
+ selectReservations,
+ (reservations) => reservations.hasDeletedReservation,
+);
+
+export const isDoingReservationOperation = createSelector(
selectReservations,
(reservations) => reservations.isLoading,
);