Skip to content

Commit

Permalink
Docs + improve function/const naming
Browse files Browse the repository at this point in the history
  • Loading branch information
dlymonkai committed Jan 10, 2025
1 parent 35a74c4 commit 229348a
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 80 deletions.
1 change: 1 addition & 0 deletions documentation/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ The following table lists the available configuration options in the `CaptureApp
| allowImageUpscaling | `boolean` | Allow images to be scaled up if the device does not support the specified resolution in the `resolution` prop. | | `false` |
| format | `CompressionFormat` | The output format of the compression. | | `CompressionFormat.JPEG` |
| quality | `number` | Value indicating image quality for the compression output. | | `0.6` |
| addDamage | `AddDamage` | Options for Add Damage, If disabled, the `Add Damage` button will be hidden. | | `AddDamage.PART_SELECT` |
| allowSkipRetake | `boolean` | If compliance is enabled, this prop indicate if the user is allowed to skip the retaking process if some pictures are not compliant. | | `false` |
| enableCompliance | `boolean` | Indicates if compliance checks should be enabled or not. | | `true` |
| enableCompliancePerSight | `string[]` | Array of Sight IDs that indicates for which sight IDs the compliance should be enabled. | | |
Expand Down
31 changes: 31 additions & 0 deletions packages/common-ui-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,37 @@ function App() {

---

## CaptureSelection
### Description
A single page component that allows the user to select between "Add Damage" or "Photo Capture" workflow.

### Example

```tsx
import { CaptureSelection } from "@monkvision/common-ui-web";
import { useNavigate } from "react-router-dom";

function App() {
const { navigate } = useNavigate();

return (
<CaptureSelection
onAddDamage={() => navigate('/add-damage-page')}
onCapture={() => navigate('/photo-capture-page')}
/>
);
}
```

### Props
| Prop | Type | Description | Required | Default Value |
|-------------|------------|----------------------------------------------------------------|----------|---------------|
| lang | string | The language used by the component. | | `'en'` |
| onAddDamage | () => void | Callback called when the user clicks on "Add Damage" button. | | |
| onCapture | () => void | Callback called when the user clicks on "Take Picture" button. | | |

---

## Checkbox
### Description
Custom component implementing a simple checkbox.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,8 @@
import { PartSelectionOrientation, VehiclePart, VehicleType } from '@monkvision/types';
import { SVGProps } from 'react';
import { PartSelectionOrientation } from '@monkvision/types';
import { DynamicSVG } from '../DynamicSVG';
import { useVehicleDynamicWireframe } from './hooks';
import { useVehicleDynamicWireframe, VehicleDynamicWireframeProps } from './hooks';
import { styles } from './VehicleDynamicWireframe.style';

/**
* Props accepted by the VehicleDynamicWireframe component.
*/
export interface VehicleDynamicWireframeProps {
/**
* Vehicle type to display the wireframe for.
*/
vehicleType: VehicleType;
/**
* The orientation of the wireframe.
*
* @default PartSelectionOrientation.FRONT_LEFT
*/
orientation?: PartSelectionOrientation;
/**
* Callback when the user clicks a part.
*/
onClickPart?: (parts: VehiclePart) => void;
/**
* Callback used to customize the display style of each vehicle part on the wireframe.
* See `DynamicSVGCustomizationFunctions` for more details.
*
* @see DynamicSVGCustomizationFunctions
*/
getPartAttributes?: (part: VehiclePart) => SVGProps<SVGElement>;
}

/**
* Component that displays a dynamic wireframe of a vehicle, allowing the user to select parts of the vehicle.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ function isCarPartElement(element: SVGElement): boolean {
return element.id !== '' && element.classList.contains('car-part');
}

function getWireframes(vehicleType: VehicleType, orientation: PartSelectionOrientation) {
function getWireframes(vehicleType: VehicleType, orientation: PartSelectionOrientation): string {
const wireframes = partSelectionWireframes[getVehicleModel(vehicleType)];
if (wireframes === undefined) {
throw new Error(`No wireframe found for vehicle type ${vehicleType}`);
}
return wireframes[orientation];
}

export interface VehicleDynamicWireframeParams {
/**
* Props accepted by the VehicleDynamicWireframe component.
*/
export interface VehicleDynamicWireframeProps {
/**
* Vehicle type to display the wireframe for.
* The type of vehicle for which the wireframe will be displayed.
*/
vehicleType: VehicleType;
/**
Expand All @@ -28,11 +31,11 @@ export interface VehicleDynamicWireframeParams {
*/
orientation?: PartSelectionOrientation;
/**
* Callback when the user clicks a part.
* Callback when the user clicks on a vehicle part.
*/
onClickPart?: (parts: VehiclePart) => void;
/**
* Callback used to customize the display style of each vehicle part on the wireframe.
* Customizes the display attributes (e.g., styles, colors) of vehicle parts.
* See `DynamicSVGCustomizationFunctions` for more details.
*
* @see DynamicSVGCustomizationFunctions
Expand All @@ -45,7 +48,7 @@ export function useVehicleDynamicWireframe({
orientation = PartSelectionOrientation.FRONT_LEFT,
onClickPart = () => {},
getPartAttributes = () => ({}),
}: VehicleDynamicWireframeParams) {
}: VehicleDynamicWireframeProps) {
const overlay = useMemo(
() => getWireframes(vehicleType, orientation),
[vehicleType, orientation],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
export {
VehicleDynamicWireframe,
type VehicleDynamicWireframeProps,
} from './VehicleDynamicWireframe';
export { VehicleDynamicWireframe } from './VehicleDynamicWireframe';
export { type VehicleDynamicWireframeProps } from './hooks';
4 changes: 2 additions & 2 deletions packages/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ you can refer to their own README directly :
- [State Management](README/STATE_MANAGEMENT.md).
- [Theming](README/THEMING.md).
- [Internationalization](README/INTERNATIONALIZATION.md).
- [Hooks](README/APP_UTILS).
- [Hooks](README/APP_UTILS.md).
- [Utilities](README/UTILITIES.md).
- [Application Utilities](README/HOOKS).
- [Application Utilities](README/HOOKS.md).
36 changes: 36 additions & 0 deletions packages/common/README/UTILITIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ method, available on all versions of JavaScript.

---

# Browser Utils
### isMobileDevice

```typescript
import { isMobileDevice } from "@monkvision/common";

console.log(isMobileDevice());
// Output : true or false
```
Checks if the current device is a mobile device.

### getAspectRatio
```typescript
import { getAspectRatio } from "@monkvision/common";

const streamDimensions = {width: 1920, height: 1080}
console.log(getAspectRatio(streamDimensions));
// Output : '1920/1080'
```
Returns the aspect ratio of the stream. If not a mobile device, it will return 16/9 by default.

---

# Color Utils
### getRGBAFromString
```typescript
Expand Down Expand Up @@ -286,6 +309,19 @@ Converts a string to camel case.

---

# Vehicle
### getVehicleModel
```typescript
import { getVehicleModel } from '@monkvision/common'
import { VehicleType } from '@monkvision/types'

console.log(getVehicleModel(VehicleType.SUV))
output : 'fesc20'
```
Returns the vehicle model corresponding to the given vehicle type.

---

# Zlib Utils
### zlibCompress
```typescript
Expand Down
4 changes: 2 additions & 2 deletions packages/common/src/utils/browser.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export function isMobileDevice(): boolean {
}

/**
* Returns the aspect ratio of the stream.
* Returns the aspect ratio of the stream. If not a mobile device, it will return 16/9 by default.
*/
export function getAspectRatio(streamDimensions?: PixelDimensions | null) {
export function getAspectRatio(streamDimensions?: PixelDimensions | null): string {
if (isMobileDevice() && streamDimensions) {
return `${streamDimensions?.width}/${streamDimensions?.height}`;
}
Expand Down
11 changes: 7 additions & 4 deletions packages/inspection-capture-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ There are two main workflows for capturing pictures of a vehicle for a Monk insp
to take pictures of the vehicle by aligning the vehicle with the Sight overlays.
- The **VideoCapture** workflow : the user is asked to record a quick video of their vehicle by filming it and rotating
in a full circle around it.
- The **DamageDisclosure** workflow : The user is guided to capture close-up pictures of specific damaged parts of the vehicle. Before taking the picture, the user must first select the damaged part on the vehicle wireframe.
- The **DamageDisclosure** workflow : The user is guided to capture close-up pictures of specific damaged parts of the vehicle. There are 2 workflows available:
- Part-selection: Before taking the picture, the user must first select the damaged part on the vehicle wireframe then a close-up picture of the damage.
- Two-shot: The user is asked to take, first a wide picture of the vehicle, then a close-up picture of the damage.

# Installing
To install the package, you can run the following command :
Expand Down Expand Up @@ -99,16 +101,17 @@ export function MonkPhotoCapturePage({ authToken }) {

# DamageDisclosure

The DamageDisclosure workflow is designed to guide users in documenting and disclosing damage to their vehicles during a Monk inspection. Once the damaged areas are identified, the user is prompted to take close-up photos of each selected area, ensuring accurate documentation for the inspection.
The DamageDisclosure workflow is designed to guide users in documenting and disclosing damage to their vehicles during a Monk inspection.
This workflow is ideal for capturing detailed images of specific damages such as dents, scratches, or other issues that need to be highlighted in the inspection report.
There are 2 workflows available.

Please refer to the [official MonkJs documentation](https://monkvision.github.io/monkjs/docs/photo-capture-workflow) for a comprehensive overview of the Add damage workflow.

## DamageDisclosure component

This package exports a ready-to-use single-page component called DamageDisclosure that implements the DamageDisclosure workflow. You can integrate it into your application by creating a new page containing only this component. Before using it, you must generate an Auth0 authentication token and create a new inspection using the Monk API. Ensure that all task statuses in the inspection are set to NOT_STARTED. This component will automatically handle starting tasks after the capture process is complete.
This package exports a ready-to-use single-page component called DamageDisclosure that implements the DamageDisclosure workflow. You can integrate it into your application by creating a new page containing only this component. Before using it, you must generate an Auth0 authentication token and create a new inspection using the Monk API. Ensure that all task statuses in the inspection are set to NOT_STARTED.

You can then pass the inspection ID, API configuration (including the auth token), and a list of sights to be displayed to the user. Once the user completes the workflow, the onComplete callback is triggered, allowing you to navigate to another page or perform additional actions.
You can then pass the inspection ID, API configuration (including the auth token). Once the user completes the workflow, the onComplete callback is triggered, allowing you to navigate to another page or perform additional actions.

The following example demonstrates how to use the DamageDisclosure component:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export interface DamageDisclosureProps
*/
onClose?: () => void;
/**
* Callback called when inspection capture is complete.
* Callback called when damage disclosure is complete.
*/
onComplete?: () => void;
/**
Expand Down Expand Up @@ -147,7 +147,7 @@ export function DamageDisclosure({
});
const images = usePhotoCaptureImages(inspectionId);
const handlePictureTaken = usePictureTaken({
sightState: disclosureState,
captureState: disclosureState,
addDamageHandle,
uploadQueue,
onPictureTaken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ import { DamageDisclosure, DamageDisclosureProps } from './DamageDisclosure';
* The DamageDisclosure component is a ready-to-use, single page component that implements a Camera app, allowing users
* to capture photos of damaged parts of their vehicle for the purpose of disclosing damage. In order to use this
* component, you first need to generate an Auth0 authentication token, and create an inspection using the Monk Api.
* When creating the inspection, don't forget to set the tasks statuses to `NOT_STARTED`. This component will handle the
* starting of the tasks at the end of the capturing process. You can then pass the inspection ID, the api config (with
* the auth token), as well as the list of sights to be taken by the user to this component, and everything will be
* handled automatically for you.
* When creating the inspection, don't forget to set the tasks statuses to `NOT_STARTED`. You can then pass the
* inspection ID, the api config (with the auth token) and everything will be handled automatically for you.
*
* @example
* import { DamageDisclosure } from '@monkvision/inspection-capture-web';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export function PhotoCapture({
});
const images = usePhotoCaptureImages(inspectionId);
const handlePictureTaken = usePictureTaken({
sightState,
captureState: sightState,
addDamageHandle,
uploadQueue,
tasksBySight,
Expand Down
25 changes: 13 additions & 12 deletions packages/inspection-capture-web/src/hooks/usePictureTaken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { PhotoCaptureSightState, DamageDisclosureState, CaptureMode } from '../t
*/
export interface UseTakePictureParams {
/**
* The PhotoCapture sight state, created using the usePhotoCaptureSightState hook.
* The capture state, created using the usePhotoCaptureSightState or useDamageDisclosureState hook.
*/
sightState: PhotoCaptureSightState | DamageDisclosureState;
captureState: PhotoCaptureSightState | DamageDisclosureState;
/**
* The PhotoCapture add damage handle, created using the useAddDamageMode hook.
*/
Expand Down Expand Up @@ -42,36 +42,37 @@ export type HandleTakePictureFunction = (picture: MonkPicture) => void;
* Custom hook used to generate the callback called when the user has taken a picture to handle picture upload etc.
*/
export function usePictureTaken({
sightState,
captureState,
addDamageHandle,
uploadQueue,
tasksBySight,
onPictureTaken,
}: UseTakePictureParams): HandleTakePictureFunction {
const { trackEvent } = useAnalytics();

const selectedSightId = 'selectedSight' in sightState ? sightState.selectedSight.id : undefined;
const selectedSightId =
'selectedSight' in captureState ? captureState.selectedSight.id : undefined;

const takeSelectedSight =
'takeSelectedSight' in sightState ? sightState.takeSelectedSight : undefined;
'takeSelectedSight' in captureState ? captureState.takeSelectedSight : undefined;

return useCallback(
(picture: MonkPicture) => {
onPictureTaken?.(picture);
sightState.setLastPictureTakenUri(picture.uri);
captureState.setLastPictureTakenUri(picture.uri);
if (addDamageHandle.mode === CaptureMode.ADD_DAMAGE_PART_SELECT_SHOT) {
uploadQueue.push({
mode: addDamageHandle.mode,
picture,
vehicleParts: addDamageHandle.vehicleParts,
});
}
if (addDamageHandle.mode === CaptureMode.SIGHT && 'selectedSight' in sightState) {
if (addDamageHandle.mode === CaptureMode.SIGHT && 'selectedSight' in captureState) {
uploadQueue.push({
mode: addDamageHandle.mode,
picture,
sightId: sightState.selectedSight.id,
tasks: tasksBySight?.[sightState.selectedSight.id] ?? sightState.selectedSight.tasks,
sightId: captureState.selectedSight.id,
tasks: tasksBySight?.[captureState.selectedSight.id] ?? captureState.selectedSight.tasks,
});
}
if (
Expand All @@ -80,8 +81,8 @@ export function usePictureTaken({
) {
uploadQueue.push({ mode: addDamageHandle.mode, picture });
}
if (addDamageHandle.mode === CaptureMode.SIGHT && 'takeSelectedSight' in sightState) {
sightState.takeSelectedSight();
if (addDamageHandle.mode === CaptureMode.SIGHT && 'takeSelectedSight' in captureState) {
captureState.takeSelectedSight();
} else {
trackEvent('AddDamage Captured', {
mode: addDamageHandle.mode,
Expand All @@ -90,7 +91,7 @@ export function usePictureTaken({
addDamageHandle.updatePhotoCaptureModeAfterPictureTaken();
},
[
sightState.setLastPictureTakenUri,
captureState.setLastPictureTakenUri,
addDamageHandle.mode,
selectedSightId,
tasksBySight,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,12 @@ describe('DamageDisclosure component', () => {
expect(useAddDamageMode).toHaveBeenCalled();
const addDamageHandle = (useAddDamageMode as jest.Mock).mock.results[0].value;
expect(useDamageDisclosureState).toHaveBeenCalled();
const sightState = (useDamageDisclosureState as jest.Mock).mock.results[0].value;
const captureState = (useDamageDisclosureState as jest.Mock).mock.results[0].value;
expect(useUploadQueue).toHaveBeenCalled();
const uploadQueue = (useUploadQueue as jest.Mock).mock.results[0].value;
expect(usePictureTaken).toHaveBeenCalledWith({
addDamageHandle,
sightState,
captureState,
uploadQueue,
onPictureTaken: props.onPictureTaken,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,12 @@ describe('PhotoCapture component', () => {
expect(useAddDamageMode).toHaveBeenCalled();
const addDamageHandle = (useAddDamageMode as jest.Mock).mock.results[0].value;
expect(usePhotoCaptureSightState).toHaveBeenCalled();
const sightState = (usePhotoCaptureSightState as jest.Mock).mock.results[0].value;
const captureState = (usePhotoCaptureSightState as jest.Mock).mock.results[0].value;
expect(useUploadQueue).toHaveBeenCalled();
const uploadQueue = (useUploadQueue as jest.Mock).mock.results[0].value;
expect(usePictureTaken).toHaveBeenCalledWith({
addDamageHandle,
sightState,
captureState,
uploadQueue,
tasksBySight: props.tasksBySight,
onPictureTaken: props.onPictureTaken,
Expand Down
Loading

0 comments on commit 229348a

Please sign in to comment.