Skip to content

Commit

Permalink
Added getInspections to network package (#869)
Browse files Browse the repository at this point in the history
  • Loading branch information
dlymonkai authored Nov 14, 2024
1 parent 3d312a7 commit 08bf980
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 7 deletions.
14 changes: 14 additions & 0 deletions packages/network/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,20 @@ Delete a damage of an inspection.
|-----------|---------------------|-----------------------------|----------|
| options | DeleteDamageOptions | The options of the request. | ✔️ |

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

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

Fetch the details of multiple inspections using the provided filters. The resulting action of this request will contain
a list of all entities that match the specified criteria.

| Parameter | Type | Description | Required |
|-----------|-----------------------|-----------------------------|----------|
| options | getInspectionsOptions | 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
custom hook returns a custom version of the `MonkApi` object described in the section above, in which the requests do
Expand Down
8 changes: 7 additions & 1 deletion packages/network/src/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { getInspection, createInspection, updateAdditionalData } from './inspection';
import {
getInspection,
createInspection,
updateAdditionalData,
getInspections,
} from './inspection';
import { addImage } from './image';
import { startInspectionTasks, updateTaskStatus } from './task';
import { getLiveConfig } from './liveConfigs';
Expand All @@ -12,6 +17,7 @@ import { createDamage, deleteDamage } from './damage';
*/
export const MonkApi = {
getInspection,
getInspections,
createInspection,
addImage,
updateTaskStatus,
Expand Down
139 changes: 139 additions & 0 deletions packages/network/src/api/inspection/mappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
Severity,
SeverityResult,
SeverityResultTargetType,
SortOrder,
Task,
TaskName,
Vehicle,
Expand All @@ -40,6 +41,7 @@ import {
ApiImagesOCRTaskPostComponent,
ApiInspectionGet,
ApiInspectionPost,
ApiInspectionsGet,
ApiPartSeverityValue,
ApiPricingTaskPostComponent,
ApiPricingV2Details,
Expand Down Expand Up @@ -374,6 +376,60 @@ function mapInspection(
};
}

export function mapApiInspectionsGet(
response: ApiInspectionsGet,
thumbnailDomain: string,
): MonkState {
const state: MonkState = {
damages: [],
images: [],
inspections: [],
parts: [],
renderedOutputs: [],
severityResults: [],
tasks: [],
vehicles: [],
views: [],
pricings: [],
partOperations: [],
};
if (!response.data) {
return state;
}
return response.data.reduce<MonkState>((acc, inspection) => {
const { images, renderedOutputs, imageIds, renderedOutputIds, viewIds } = mapImages(
inspection as ApiInspectionGet,
thumbnailDomain,
);
const { damages, damageIds } = mapDamages(inspection as ApiInspectionGet);
const { parts, partIds } = mapParts(inspection as ApiInspectionGet);
const { pricings, pricingIds } = mapPricingV2(inspection as ApiInspectionGet);
const vehicle = mapVehicle(inspection as ApiInspectionGet);
const mappedInspection = mapInspection(inspection as ApiInspectionGet, {
imageIds,
renderedOutputIds,
viewIds,
damageIds,
partIds,
severityResultIds: [],
taskIds: [],
pricingIds,
vehicleId: vehicle?.id,
});
acc.damages.push(...damages);
acc.images.push(...images);
acc.inspections.push(mappedInspection);
acc.parts.push(...parts);
acc.renderedOutputs.push(...renderedOutputs);
if (vehicle) {
acc.vehicles.push(vehicle);
}
acc.pricings.push(...pricings);

return acc;
}, state);
}

export function mapApiInspectionGet(
response: ApiInspectionGet,
thumbnailDomain: string,
Expand Down Expand Up @@ -569,3 +625,86 @@ export function mapApiInspectionPost(options: CreateInspectionOptions): ApiInspe
},
};
}

/**
* Parameters for pagination requests.
*/
export interface PaginationRequestParams {
/**
* The number of inspections fetched.
*
* @default 100
*/
limit?: number;
/**
* The inspection ID to filter that occurred before this ID.
*/
before?: string;
/**
* The inspection ID to filter that occurred after this date.
*/
after?: string;
}

/**
* Parameters for sorting requests.
*/
export interface SortRequestParams {
/**
* The property to sort by.
*/
sortByProperty: string;
/**
* The order of the pagination.
*
* @default SortOrder.DESC
*/
sortOrder?: SortOrder;
}

/**
* Options passed to the `getInspections` API request.
*/
export interface GetInspectionsOptions {
/**
* If true, only the total count of inspections will be returned.
*
* @default false
*/
count?: boolean;
/**
* The filter request parameters.
*/
filters?: Record<string, string | number>;
/**
* The pagination request parameters.
*/
pagination?: PaginationRequestParams;
/**
* The sort request parameters.
*/
sort?: SortRequestParams;
}

export function mapApiInspectionsUrlParamsGet(options: GetInspectionsOptions): string {
const params = new URLSearchParams();
let url = options.count ? '/count' : '';
url = options.filters || options.pagination ? `${url}?` : url;

if (options.filters) {
Object.entries(options.filters).forEach(([key, value]) => {
params.append(key, value.toString());
});
}
if (options.pagination) {
Object.entries(options.pagination).forEach(([key, value]) => {
params.append(key, value.toString());
});
}
if (options.sort) {
Object.entries(options.sort).forEach(([key, value]) => {
params.append(key, value.toString());
});
}
return `${url}${params.toString()}`;
}
34 changes: 32 additions & 2 deletions packages/network/src/api/inspection/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ import {
import { AdditionalData, ComplianceOptions, CreateInspectionOptions } from '@monkvision/types';
import { Dispatch } from 'react';
import { getDefaultOptions, MonkApiConfig } from '../config';
import { ApiIdColumn, ApiInspectionGet } from '../models';
import { mapApiInspectionGet, mapApiInspectionPost } from './mappers';
import { ApiIdColumn, ApiInspectionGet, ApiInspectionsGet } from '../models';
import {
GetInspectionsOptions,
mapApiInspectionGet,
mapApiInspectionPost,
mapApiInspectionsGet,
mapApiInspectionsUrlParamsGet,
} from './mappers';
import { MonkApiResponse } from '../types';

/**
Expand Down Expand Up @@ -143,3 +149,27 @@ export async function updateAdditionalData(
body,
};
}

/**
* Fetch the details of multiple inspections.
*
* @param options The options of the request.
* @param config The API config.
* @param [dispatch] Optional MonkState dispatch function that you can pass if you want this request to handle React
* state management for you.
*/
export async function getInspections(
options: GetInspectionsOptions,
config: MonkApiConfig,
dispatch?: Dispatch<MonkGotOneInspectionAction>,
): Promise<MonkApiResponse | MonkApiResponse<GetInspectionResponse, ApiInspectionsGet>> {
const kyOptions = getDefaultOptions(config);
const response = await ky.get(`inspections${mapApiInspectionsUrlParamsGet(options)}`, kyOptions);
const body = await response.json<ApiInspectionsGet>();
const entities = mapApiInspectionsGet(body, config.thumbnailDomain);
dispatch?.({
type: MonkActionType.GOT_ONE_INSPECTION,
payload: entities,
});
return { entities, response, body };
}
32 changes: 32 additions & 0 deletions packages/network/src/api/models/inspection.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SortOrder } from '@monkvision/types';
import type { ApiAdditionalData } from './common';
import type { ApiDamages } from './damage';
import type { ApiImagePost, ApiImages } from './image';
Expand Down Expand Up @@ -29,6 +30,37 @@ export interface ApiInspectionGet {
wheel_analysis?: ApiWheelAnalysis;
}

interface ApiData
extends Pick<
ApiInspectionGet,
'id' | 'additional_data' | 'images' | 'damages' | 'pricing' | 'parts' | 'vehicle'
> {
pdf_url?: string;
}

interface ApiPaginationParams {
limit?: number;
before?: string;
after?: string;
pagination_order?: SortOrder;
}

interface ApiCursors {
before?: Pick<ApiPaginationParams, 'before'>;
after?: Pick<ApiPaginationParams, 'after'>;
next?: ApiPaginationParams;
previous?: ApiPaginationParams;
}

interface ApiPagination {
cursors: ApiCursors;
}

export interface ApiInspectionsGet {
data: ApiData[];
paging: ApiPagination;
}

export interface ApiDamageSeverity {
output_format: ApiBusinessClients;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/network/src/api/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ export function useMonkApi(config: MonkApiConfig) {
* @param options The options of the request.
*/
getInspection: reactify(MonkApi.getInspection, config, dispatch, handleError),
/**
* Fetch multiple inspection.
*
* @param options The options of the request.
*/
getInspections: reactify(MonkApi.getInspections, config, dispatch, handleError),
/**
* Create a new inspection with the given options. See the `CreateInspectionOptions` interface for more details.
*
Expand Down
45 changes: 43 additions & 2 deletions packages/network/test/api/inspection/requests.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const mockInspection: Inspection = {
parts: [],
tasks: [],
};
const mockUrlParams = 'test-url-params';

jest.mock('../../../src/api/config', () => ({
getDefaultOptions: jest.fn(() => ({ prefixUrl: 'getDefaultOptionsTest' })),
Expand All @@ -37,12 +38,26 @@ jest.mock('../../../src/api/inspection/mappers', () => ({
inspections: [mockInspection] as unknown as Inspection[],
parts: [],
})),
mapApiInspectionsGet: jest.fn(() => ({
inspections: [mockInspection] as unknown as Inspection[],
parts: [],
})),
mapApiInspectionPost: jest.fn(() => ({ test: 'ok-ok-ok' })),
mapApiInspectionsUrlParamsGet: jest.fn(() => mockUrlParams),
}));

import { getDefaultOptions } from '../../../src/api/config';
import { createInspection, getInspection, updateAdditionalData } from '../../../src/api/inspection';
import { mapApiInspectionGet, mapApiInspectionPost } from '../../../src/api/inspection/mappers';
import {
createInspection,
getInspection,
getInspections,
updateAdditionalData,
} from '../../../src/api/inspection';
import {
mapApiInspectionGet,
mapApiInspectionPost,
mapApiInspectionsGet,
} from '../../../src/api/inspection/mappers';

const apiConfig = {
apiDomain: 'apiDomain',
Expand Down Expand Up @@ -133,4 +148,30 @@ describe('Inspection requests', () => {
});
});
});

describe('getInspections request', () => {
it('should make the proper API call and map the resulting response', async () => {
const dispatch = jest.fn();
const result = await getInspections({ filters: { test: 'test' } }, apiConfig, dispatch);
const response = await (ky.get as jest.Mock).mock.results[0].value;
const body = await response.json();

expect(mapApiInspectionsGet).toHaveBeenCalledWith(body, apiConfig.thumbnailDomain);
const entities = (mapApiInspectionsGet as jest.Mock).mock.results[0].value;
expect(getDefaultOptions).toHaveBeenCalledWith(apiConfig);
expect(ky.get).toHaveBeenCalledWith(
`inspections${mockUrlParams}`,
getDefaultOptions(apiConfig),
);
expect(dispatch).toHaveBeenCalledWith({
type: MonkActionType.GOT_ONE_INSPECTION,
payload: entities,
});
expect(result).toEqual({
entities,
response,
body,
});
});
});
});
11 changes: 11 additions & 0 deletions packages/network/test/api/react.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ jest.mock('../../src/api/api', () => ({
updatePricing: jest.fn(() => Promise.resolve({ test: 'updatePricing' })),
createDamage: jest.fn(() => Promise.resolve({ test: 'createDamage' })),
deleteDamage: jest.fn(() => Promise.resolve({ test: 'deleteDamage' })),
getInspections: jest.fn(() => Promise.resolve({ test: 'getInspections' })),
},
}));

Expand Down Expand Up @@ -96,6 +97,16 @@ describe('Monk API React utilities', () => {
expect(requestMock).toHaveBeenCalledWith(param, config, dispatchMock);
requestResultMock = await requestMock.mock.results[0].value;
expect(resultMock).toBe(requestResultMock);

dispatchMock.mockClear();

param = 'test-getInspections';
resultMock = await (result.current.getInspections as any)(param);
requestMock = MonkApi.getInspections as jest.Mock;
expect(requestMock).toHaveBeenCalledWith(param, config, dispatchMock);
requestResultMock = await requestMock.mock.results[0].value;
expect(resultMock).toBe(requestResultMock);

unmount();
});

Expand Down
Loading

0 comments on commit 08bf980

Please sign in to comment.