Skip to content

Commit

Permalink
Added API create / delete damage routes (#859)
Browse files Browse the repository at this point in the history
* Added API create / delete damage routes

* Added state management for create and delete damage
  • Loading branch information
dlymonkai authored Oct 21, 2024
1 parent 6b099cf commit 527b510
Show file tree
Hide file tree
Showing 23 changed files with 600 additions and 7 deletions.
57 changes: 57 additions & 0 deletions packages/common/src/state/actions/createdOneDamage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Damage } from '@monkvision/types';
import { MonkAction, MonkActionType } from './monkAction';
import { MonkState } from '../state';

/**
* The payload of a MonkCreatedOneDamagePayload.
*/
export interface MonkCreatedOneDamagePayload {
/**
* The damage created.
*/
damage: Damage;
}

/**
* Action dispatched when a vehicle have been updated.
*/
export interface MonkCreatedOneDamageAction extends MonkAction {
/**
* The type of the action : `MonkActionType.CREATED_ONE_DAMAGE`.
*/
type: MonkActionType.CREATED_ONE_DAMAGE;
/**
* The payload of the action containing the fetched entities.
*/
payload: MonkCreatedOneDamagePayload;
}

/**
* Matcher function that matches a CreatedOneDamage while also inferring its type using TypeScript's type predicate
* feature.
*/
export function isCreatedOneDamageAction(action: MonkAction): action is MonkCreatedOneDamageAction {
return action.type === MonkActionType.CREATED_ONE_DAMAGE;
}

/**
* Reducer function for a createdOneDamage action.
*/
export function createdOneDamage(state: MonkState, action: MonkCreatedOneDamageAction): MonkState {
const { damages, inspections, parts } = state;
const { payload } = action;

const inspection = inspections.find((value) => value.id === payload.damage.inspectionId);
if (inspection) {
inspection.damages.push(action.payload.damage.id);
}
const partsRelated = action.payload.damage.parts
.map((part) => parts.find((value) => value.type === part)?.id)
.filter((v) => v !== undefined) as string[];
damages.push({ ...action.payload.damage, parts: partsRelated });
return {
...state,
damages: [...damages],
inspections: [...inspections],
};
}
2 changes: 1 addition & 1 deletion packages/common/src/state/actions/createdOnePricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface MonkCreatedOnePricingPayload {
}

/**
* Action dispatched when a vehicle have been updated.
* Action dispatched when a pricing have been updated.
*/
export interface MonkCreatedOnePricingAction extends MonkAction {
/**
Expand Down
57 changes: 57 additions & 0 deletions packages/common/src/state/actions/deletedOneDamage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { MonkAction, MonkActionType } from './monkAction';
import { MonkState } from '../state';

/**
* The payload of a MonkDeletedOneDamagePayload.
*/
export interface MonkDeletedOneDamagePayload {
/**
* The ID of the inspection to which the damage was deleted.
*/
inspectionId: string;
/**
* The damage ID deleted.
*/
damageId: string;
}

/**
* Action dispatched when a vehicle have been updated.
*/
export interface MonkDeletedOneDamageAction extends MonkAction {
/**
* The type of the action : `MonkActionType.DELETED_ONE_DAMAGE`.
*/
type: MonkActionType.DELETED_ONE_DAMAGE;
/**
* The payload of the action containing the fetched entities.
*/
payload: MonkDeletedOneDamagePayload;
}

/**
* Matcher function that matches a DeletedOneDamage while also inferring its type using TypeScript's type predicate
* feature.
*/
export function isDeletedOneDamageAction(action: MonkAction): action is MonkDeletedOneDamageAction {
return action.type === MonkActionType.DELETED_ONE_DAMAGE;
}

/**
* Reducer function for a deletedOneDamage action.
*/
export function deletedOneDamage(state: MonkState, action: MonkDeletedOneDamageAction): MonkState {
const { damages, inspections } = state;
const { payload } = action;

const inspection = inspections.find((value) => value.id === payload.inspectionId);
if (inspection) {
inspection.damages = inspection.damages?.filter((damageId) => damageId !== payload.damageId);
}
const newDamages = damages.filter((damage) => damage.id !== payload.damageId);
return {
...state,
damages: [...newDamages],
inspections: [...inspections],
};
}
2 changes: 2 additions & 0 deletions packages/common/src/state/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from './createdOnePricing';
export * from './deletedOnePricing';
export * from './updatedOnePricing';
export * from './updatedOneInspectionAdditionalData';
export * from './createdOneDamage';
export * from './deletedOneDamage';
8 changes: 8 additions & 0 deletions packages/common/src/state/actions/monkAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ export enum MonkActionType {
* A pricing has been deleted.
*/
DELETED_ONE_PRICING = 'deleted_one_pricing',
/**
* A damage has been uploaded to the API.
*/
CREATED_ONE_DAMAGE = 'created_one_damage',
/**
* A damage has been deleted.
*/
DELETED_ONE_DAMAGE = 'deleted_one_damage',
/**
* Clear and reset the state.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MonkState } from '../state';
*/
export interface MonkUpdatedOneInspectionAdditionalDataPayload {
/**
* The ID of the inspection to which the pricing was updated.
* The ID of the inspection to which the additionalData was updated.
*/
inspectionId: string;
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/state/actions/updatedOnePricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MonkState } from '../state';
*/
export interface MonkUpdatedOnePricingPayload {
/**
* The pricing created.
* The pricing updated.
*/
pricing: PricingV2;
}
Expand Down
10 changes: 10 additions & 0 deletions packages/common/src/state/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import {
updatedOnePricing,
updatedOneInspectionAdditionalData,
updatedVehicle,
createdOneDamage,
isCreatedOneDamageAction,
deletedOneDamage,
isDeletedOneDamageAction,
} from './actions';
import { MonkState } from './state';

Expand Down Expand Up @@ -52,5 +56,11 @@ export function monkReducer(state: MonkState, action: MonkAction): MonkState {
if (isUpdatedVehicleAction(action)) {
return updatedVehicle(state, action);
}
if (isCreatedOneDamageAction(action)) {
return createdOneDamage(state, action);
}
if (isDeletedOneDamageAction(action)) {
return deletedOneDamage(state, action);
}
return state;
}
65 changes: 65 additions & 0 deletions packages/common/test/state/actions/createdOneDamage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
createEmptyMonkState,
MonkActionType,
createdOneDamage,
isCreatedOneDamageAction,
MonkCreatedOneDamageAction,
} from '../../../src';
import { Inspection, MonkEntityType, VehiclePart, DamageType, Part } from '@monkvision/types';

const action: MonkCreatedOneDamageAction = {
type: MonkActionType.CREATED_ONE_DAMAGE,
payload: {
damage: {
entityType: MonkEntityType.DAMAGE,
id: 'test-id',
inspectionId: 'inspections-test',
parts: [VehiclePart.ROOF],
relatedImages: [],
type: DamageType.SCRATCH,
},
},
};

describe('CreatedOneDamage action handlers', () => {
describe('Action matcher', () => {
it('should return true if the action has the proper type', () => {
expect(isCreatedOneDamageAction({ type: MonkActionType.CREATED_ONE_DAMAGE })).toBe(true);
});

it('should return false if the action does not have the proper type', () => {
expect(isCreatedOneDamageAction({ type: MonkActionType.RESET_STATE })).toBe(false);
});
});

describe('Action handler', () => {
it('should return a new state', () => {
const state = createEmptyMonkState();
expect(Object.is(createdOneDamage(state, action), state)).toBe(false);
});

it('should create damage in the state', () => {
const state = createEmptyMonkState();
const part = {
id: 'part-id',
type: VehiclePart.ROOF,
};
state.inspections.push({
id: 'inspections-test',
damages: [] as string[],
} as Inspection);
state.parts.push(part as Part);
const newState = createdOneDamage(state, action);
const inspectionDamage = newState.inspections.find(
(ins) => ins.id === action.payload.damage.inspectionId,
)?.damages;

expect(inspectionDamage?.length).toBe(1);
expect(inspectionDamage).toContainEqual(action.payload.damage.id);
expect(newState.damages).toContainEqual({
...action.payload.damage,
parts: [part.id],
});
});
});
});
53 changes: 53 additions & 0 deletions packages/common/test/state/actions/deletedOneDamage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
createEmptyMonkState,
MonkActionType,
isDeletedOneDamageAction,
deletedOneDamage,
MonkDeletedOneDamageAction,
} from '../../../src';
import { Inspection } from '@monkvision/types';

const action: MonkDeletedOneDamageAction = {
type: MonkActionType.DELETED_ONE_DAMAGE,
payload: {
inspectionId: 'inspections-test',
damageId: 'pricing-id-test',
},
};

describe('DeletedOneDamage action handlers', () => {
describe('Action matcher', () => {
it('should return true if the action has the proper type', () => {
expect(isDeletedOneDamageAction({ type: MonkActionType.DELETED_ONE_DAMAGE })).toBe(true);
});

it('should return false if the action does not have the proper type', () => {
expect(isDeletedOneDamageAction({ type: MonkActionType.RESET_STATE })).toBe(false);
});
});

describe('Action handler', () => {
it('should return a new state', () => {
const state = createEmptyMonkState();
expect(Object.is(deletedOneDamage(state, action), state)).toBe(false);
});

it('should delete damage in the state', () => {
const state = createEmptyMonkState();
state.inspections.push({
id: 'inspections-test',
damages: [action.payload.damageId] as string[],
} as Inspection);
const newState = deletedOneDamage(state, action);
const inspectionDamage = newState.inspections.find(
(ins) => ins.id === action.payload.inspectionId,
)?.damages;

expect(inspectionDamage?.length).toBe(0);
expect(inspectionDamage).not.toContainEqual(action.payload.damageId);
expect(
newState.damages.find((damage) => damage.id === action.payload.damageId),
).toBeUndefined();
});
});
});
10 changes: 10 additions & 0 deletions packages/common/test/state/reducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ jest.mock('../../src/state/actions', () => ({
isCreatedOnePricingAction: jest.fn(() => false),
isDeletedOnePricingAction: jest.fn(() => false),
isUpdatedOnePricingAction: jest.fn(() => false),
isCreatedOneDamageAction: jest.fn(() => false),
isDeletedOneDamageAction: jest.fn(() => false),
isUpdatedOneInspectionAdditionalDataAction: jest.fn(() => false),
isUpdatedVehicleAction: jest.fn(() => false),
createdOneImage: jest.fn(() => null),
Expand All @@ -15,6 +17,8 @@ jest.mock('../../src/state/actions', () => ({
createdOnePricing: jest.fn(() => null),
deletedOnePricing: jest.fn(() => null),
updatedOnePricing: jest.fn(() => null),
createdOneDamage: jest.fn(() => null),
deletedOneDamage: jest.fn(() => null),
updatedOneInspectionAdditionalData: jest.fn(() => null),
updatedVehicle: jest.fn(() => null),
}));
Expand All @@ -25,6 +29,8 @@ import {
createdOnePricing,
deletedOnePricing,
updatedOnePricing,
createdOneDamage,
deletedOneDamage,
updatedOneInspectionAdditionalData,
updatedVehicle,
isCreatedOneImageAction,
Expand All @@ -34,6 +40,8 @@ import {
isCreatedOnePricingAction,
isDeletedOnePricingAction,
isUpdatedOnePricingAction,
isCreatedOneDamageAction,
isDeletedOneDamageAction,
isUpdatedOneInspectionAdditionalDataAction,
isUpdatedVehicleAction,
MonkAction,
Expand All @@ -51,6 +59,8 @@ const actions = [
{ matcher: isCreatedOnePricingAction, handler: createdOnePricing },
{ matcher: isDeletedOnePricingAction, handler: deletedOnePricing },
{ matcher: isUpdatedOnePricingAction, handler: updatedOnePricing },
{ matcher: isCreatedOneDamageAction, handler: createdOneDamage },
{ matcher: isDeletedOneDamageAction, handler: deletedOneDamage },
{
matcher: isUpdatedOneInspectionAdditionalDataAction,
handler: updatedOneInspectionAdditionalData,
Expand Down
27 changes: 26 additions & 1 deletion packages/network/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ import { MonkApi } from '@monkvision/network';
MonkApi.deletePricing(options, apiConfig, dispatch);
```

Update a pricing of an inspection.
Delete a pricing of an inspection.

| Parameter | Type | Description | Required |
|-----------|----------------------|-----------------------------|----------|
Expand All @@ -184,6 +184,31 @@ Update the additional data of an inspection.
|-----------|-----------------------------|-----------------------------|----------|
| options | UpdateAdditionalDataOptions | The options of the request. | ✔️ |

### createDamage
```typescript
import { MonkApi } from '@monkvision/network';

MonkApi.createDamage(options, apiConfig, dispatch);
```

Create a new damage of an inspection.

| Parameter | Type | Description | Required |
|-----------|---------------------|-----------------------------|----------|
| options | CreateDamageOptions | The options of the request. | ✔️ |

### deleteDamage
```typescript
import { MonkApi } from '@monkvision/network';

MonkApi.deleteDamage(options, apiConfig, dispatch);
```

Delete a damage of an inspection.

| Parameter | Type | Description | Required |
|-----------|---------------------|-----------------------------|----------|
| options | DeleteDamageOptions | The options of the request. | ✔️ |

# React Tools
In order to simply integrate the Monk Api requests into your React app, you can make use of the `useMonkApi` hook. This
Expand Down
Loading

0 comments on commit 527b510

Please sign in to comment.