Skip to content

Commit

Permalink
Added VehicleDisclosure to Inspection capture worflow
Browse files Browse the repository at this point in the history
  • Loading branch information
dlymonkai committed Dec 24, 2024
1 parent 4b73c04 commit fc3b0dc
Show file tree
Hide file tree
Showing 32 changed files with 604 additions and 90 deletions.
2 changes: 1 addition & 1 deletion apps/demo-app/src/local-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "demo-app-dev",
"description": "Config for the dev Demo App.",
"allowSkipRetake": true,
"enableAddDamage": true,
"addDamage": "part_select",
"enableSightGuidelines": true,
"allowVehicleTypeSelection": true,
"allowManualLogin": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export function PhotoCapturePage() {
sights={currentSights}
onComplete={handleComplete}
lang={i18n.language}
damageDisclosure={false}
/>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions apps/demo-app/test/pages/PhotoCapturePage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const appState = {
enforceOrientation: 'test-enforceOrientation-test',
maxUploadDurationWarning: 'test-maxUploadDurationWarning-test',
allowSkipRetake: 'test-allowSkipRetake-test',
enableAddDamage: 'test-enableAddDamage-test',
addDamage: 'test-addDamage-test',
enableCompliance: 'test-enableCompliance-test',
enableCompliancePerSight: 'test-enableCompliancePerSight-test',
complianceIssues: 'test-complianceIssues-test',
Expand Down Expand Up @@ -53,7 +53,7 @@ describe('PhotoCapture page', () => {
enforceOrientation: appState.config.enforceOrientation,
maxUploadDurationWarning: appState.config.maxUploadDurationWarning,
allowSkipRetake: appState.config.allowSkipRetake,
enableAddDamage: appState.config.enableAddDamage,
addDamage: appState.config.addDamage,
enableCompliance: appState.config.enableCompliance,
enableCompliancePerSight: appState.config.enableCompliancePerSight,
complianceIssues: appState.config.complianceIssues,
Expand Down
2 changes: 1 addition & 1 deletion documentation/docs/photo-capture-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ increase the detection rate. This feature is called `Add Damage`, and there two
take a close-up picture of the damage.

For now, only the 2-shot workflow is implemented in the PhotoCapture workflow. This feature is enabled by default in the
`PhotoCapture` component. To disable it, pass the `enableAddDamage` prop to `false`.
`PhotoCapture` component. To disable it, pass the `addDamage` prop to `AddDamage.DISABLED`.

## Using Compliance
The compliance is a feature that allows our AI models to analyze the quality of the pictures taken by the user, and if
Expand Down
3 changes: 2 additions & 1 deletion documentation/src/utils/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z, CustomErrorParams } from 'zod';
import {
AddDamage,
CameraResolution,
ComplianceIssue,
CompressionFormat,
Expand Down Expand Up @@ -307,7 +308,7 @@ export const LiveConfigSchema = z
maxUploadDurationWarning: z.number().positive().or(z.literal(-1)).optional(),
useAdaptiveImageQuality: z.boolean().optional(),
allowSkipRetake: z.boolean().optional(),
enableAddDamage: z.boolean().optional(),
addDamage: z.nativeEnum(AddDamage).optional(),
enableSightGuidelines: z.boolean().optional(),
sightGuidelines: z.array(SightGuidelineSchema).optional(),
enableTutorial: z.nativeEnum(PhotoCaptureTutorialOption).optional(),
Expand Down
48 changes: 38 additions & 10 deletions packages/inspection-capture-web/src/PhotoCapture/PhotoCapture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { useMonitoring } from '@monkvision/monitoring';
import { MonkApiConfig } from '@monkvision/network';
import {
AddDamage,
CameraConfig,
CaptureAppConfig,
ComplianceOptions,
Expand Down Expand Up @@ -60,7 +61,7 @@ export interface PhotoCaptureProps
| 'showCloseButton'
| 'enforceOrientation'
| 'allowSkipRetake'
| 'enableAddDamage'
| 'addDamage'
| 'sightGuidelines'
| 'enableSightGuidelines'
| 'enableTutorial'
Expand Down Expand Up @@ -107,6 +108,13 @@ export interface PhotoCaptureProps
* Custom label for validate button in gallery view.
*/
validateButtonLabel?: string;
/**
* Boolean indicating whether damage disclosure is enabled.
* If true, the user will first be prompted to take close-up pictures, followed by sights pictures.
*
* @default false
*/
damageDisclosure?: boolean;
}

enum PhotoCaptureScreen {
Expand Down Expand Up @@ -135,7 +143,7 @@ export function PhotoCapture({
customComplianceThresholdsPerSight,
useLiveCompliance = false,
allowSkipRetake = false,
enableAddDamage = true,
addDamage = AddDamage.PART_SELECT,
sightGuidelines,
enableTutorial = PhotoCaptureTutorialOption.FIRST_TIME_ONLY,
allowSkipTutorial = true,
Expand All @@ -145,6 +153,7 @@ export function PhotoCapture({
lang,
enforceOrientation,
validateButtonLabel,
damageDisclosure = false,
...initialCameraConfig
}: PhotoCaptureProps) {
useI18nSync(lang);
Expand All @@ -163,7 +172,15 @@ export function PhotoCapture({
const dimensions = useWindowDimensions();
const analytics = useAnalytics();
const loading = useLoadingState();
const addDamageHandle = useAddDamageMode();
const handleOpenGallery = () => {
setCurrentScreen(PhotoCaptureScreen.GALLERY);
analytics.trackEvent('Gallery Opened');
};
const addDamageHandle = useAddDamageMode({
damageDisclosure,
addDamage,
onOpenGallery: handleOpenGallery,
});
useTracking({ inspectionId, authToken: apiConfig.authToken });
const { setIsInitialInspectionFetched } = useComplianceAnalytics({ inspectionId, sights });
const { adaptiveCameraConfig, uploadEventHandlers: adaptiveUploadEventHandlers } =
Expand Down Expand Up @@ -218,11 +235,10 @@ export function PhotoCapture({
tasksBySight,
onPictureTaken,
});
const handleOpenGallery = () => {
setCurrentScreen(PhotoCaptureScreen.GALLERY);
analytics.trackEvent('Gallery Opened');
const handleGalleryBack = () => {
setCurrentScreen(PhotoCaptureScreen.CAMERA);
addDamageHandle.handleCancelAddDamage();
};
const handleGalleryBack = () => setCurrentScreen(PhotoCaptureScreen.CAMERA);
const handleNavigateToCapture = (options: NavigateToCaptureOptions) => {
if (options.reason === NavigateToCaptureReason.ADD_DAMAGE) {
addDamageHandle.handleAddDamage();
Expand All @@ -239,6 +255,11 @@ export function PhotoCapture({
};
const { allowRedirect } = usePreventExit(sightState.sightsTaken.length !== 0);
const handleGalleryValidate = () => {
if (addDamageHandle.damageDisclosure) {
setCurrentScreen(PhotoCaptureScreen.CAMERA);
addDamageHandle.handleDamageDisclosure();
return;
}
startTasks()
.then(() => {
analytics.trackEvent('Capture Completed');
Expand All @@ -264,18 +285,22 @@ export function PhotoCapture({
sightsTaken: sightState.sightsTaken,
lastPictureTakenUri: sightState.lastPictureTakenUri,
mode: addDamageHandle.mode,
vehicleParts: addDamageHandle.vehicleParts,
showVehiclePartSelector: addDamageHandle.showVehiclePartSelector,
onOpenGallery: handleOpenGallery,
onSelectSight: sightState.selectSight,
onRetakeSight: sightState.retakeSight,
onAddDamage: addDamageHandle.handleAddDamage,
onAddDamagePartsSelected: addDamageHandle.handleAddDamagePartsSelected,
onCancelAddDamage: addDamageHandle.handleCancelAddDamage,
onRetry: sightState.retryLoadingInspection,
loading,
onClose,
inspectionId,
showCloseButton,
images,
enableAddDamage,
addDamage,
onValidateVehicleParts: addDamageHandle.handleValidateVehicleParts,
sightGuidelines,
enableSightGuidelines,
currentTutorialStep,
Expand Down Expand Up @@ -317,9 +342,12 @@ export function PhotoCapture({
onBack={handleGalleryBack}
onNavigateToCapture={handleNavigateToCapture}
onValidate={handleGalleryValidate}
enableAddDamage={enableAddDamage}
validateButtonLabel={validateButtonLabel}
addDamage={addDamage}
validateButtonLabel={
addDamageHandle.damageDisclosure ? t('photo.gallery.next') : validateButtonLabel
}
isInspectionCompleted={sightState.isInspectionCompleted}
disableSightPicture={addDamageHandle.damageDisclosure}
{...complianceOptions}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMemo, useState } from 'react';
import { CaptureAppConfig, Image, ImageStatus, Sight } from '@monkvision/types';
import { CaptureAppConfig, Image, ImageStatus, Sight, VehiclePart } from '@monkvision/types';
import { useTranslation } from 'react-i18next';
import { BackdropDialog } from '@monkvision/common-ui-web';
import { CameraHUDProps } from '@monkvision/camera-web';
Expand All @@ -21,7 +21,7 @@ export interface PhotoCaptureHUDProps
CaptureAppConfig,
| 'enableSightGuidelines'
| 'sightGuidelines'
| 'enableAddDamage'
| 'addDamage'
| 'showCloseButton'
| 'allowSkipTutorial'
> {
Expand Down Expand Up @@ -57,6 +57,14 @@ export interface PhotoCaptureHUDProps
* The current tutorial step in PhotoCapture component.
*/
currentTutorialStep: TutorialSteps | null;
/**
* Current vehicle parts selected to take a picture of.
*/
vehicleParts: VehiclePart[];
/**
* Boolean indicating if the vehicle part selector is currently displayed.
*/
showVehiclePartSelector: boolean;
/**
* Callback called when the user clicks on "Next" button in PhotoCapture tutorial.
*/
Expand All @@ -74,11 +82,15 @@ export interface PhotoCaptureHUDProps
*/
onRetakeSight: (sight: string) => void;
/**
* Callback to be called when the user clicks on the "Add Damage" button.
* Callback called when the user clicks on the "Add Damage" button.
*/
onAddDamage: () => void;
/**
* Callback to be called when the user clicks on the "Cancel" button of the Add Damage mode.
* Callback called when the user selects the parts to take a picture of.
*/
onAddDamagePartsSelected?: (parts: VehiclePart[]) => void;
/**
* Callback called when the user clicks on the "Cancel" button of the Add Damage mode.
*/
onCancelAddDamage: () => void;
/**
Expand All @@ -89,6 +101,10 @@ export interface PhotoCaptureHUDProps
* Callback called when the user clicks on the gallery icon.
*/
onOpenGallery: () => void;
/**
* Callback called when the user clicks on the "Validate" button of the Add Damage mode.
*/
onValidateVehicleParts: () => void;
/**
* Callback called when the user clicks on the close button. If this callback is not provided, the close button is not
* displayed.
Expand All @@ -112,9 +128,13 @@ export function PhotoCaptureHUD({
sightsTaken,
lastPictureTakenUri,
mode,
vehicleParts,
showVehiclePartSelector,
onSelectSight,
onRetakeSight,
onAddDamage,
onAddDamagePartsSelected,
onValidateVehicleParts,
onCancelAddDamage,
onOpenGallery,
onRetry,
Expand All @@ -124,7 +144,7 @@ export function PhotoCaptureHUD({
handle,
cameraPreview,
images,
enableAddDamage,
addDamage,
sightGuidelines,
enableSightGuidelines,
currentTutorialStep,
Expand Down Expand Up @@ -152,6 +172,14 @@ export function PhotoCaptureHUD({
onClose?.();
};

const handleCloseHUDButton = () => {
if (mode === PhotoCaptureMode.ADD_DAMAGE_PART_SELECT) {
onValidateVehicleParts();
} else {
setShowCloseModal(true);
}
};

return (
<div style={style.container}>
<div style={style.previewContainer} data-testid='camera-preview'>
Expand All @@ -161,34 +189,40 @@ export function PhotoCaptureHUD({
sights={sights}
sightsTaken={sightsTaken}
mode={mode}
vehicleParts={vehicleParts}
showVehiclePartSelector={showVehiclePartSelector}
onAddDamage={onAddDamage}
onCancelAddDamage={onCancelAddDamage}
onAddDamagePartsSelected={onAddDamagePartsSelected}
onSelectSight={onSelectSight}
onRetakeSight={onRetakeSight}
onValidateVehicleParts={onValidateVehicleParts}
isLoading={loading.isLoading}
error={loading.error ?? handle.error}
previewDimensions={handle.previewDimensions}
images={images}
enableAddDamage={enableAddDamage}
addDamage={addDamage}
sightGuidelines={sightGuidelines}
enableSightGuidelines={enableSightGuidelines}
tutorialStep={currentTutorialStep}
/>
</div>
<PhotoCaptureHUDButtons
onOpenGallery={onOpenGallery}
onTakePicture={handle?.takePicture}
onClose={() => setShowCloseModal(true)}
galleryPreview={lastPictureTakenUri ?? undefined}
closeDisabled={!!loading.error || !!handle.error}
galleryDisabled={!!loading.error || !!handle.error}
takePictureDisabled={
!!loading.error || !!handle.error || handle.isLoading || loading.isLoading
}
showCloseButton={showCloseButton}
showGalleryBadge={retakeCount > 0}
retakeCount={retakeCount}
/>
{!showVehiclePartSelector && (
<PhotoCaptureHUDButtons
onOpenGallery={onOpenGallery}
onTakePicture={handle?.takePicture}
onClose={handleCloseHUDButton}
galleryPreview={lastPictureTakenUri ?? undefined}
closeDisabled={!!loading.error || !!handle.error}
galleryDisabled={!!loading.error || !!handle.error}
takePictureDisabled={
!!loading.error || !!handle.error || handle.isLoading || loading.isLoading
}
showCloseButton={showCloseButton}
showGalleryBadge={retakeCount > 0}
retakeCount={retakeCount}
/>
)}
<PhotoCaptureHUDOverlay
inspectionId={inspectionId}
handle={handle}
Expand All @@ -211,6 +245,7 @@ export function PhotoCaptureHUD({
allowSkipTutorial={allowSkipTutorial}
sightId={selectedSight.id}
sightGuidelines={sightGuidelines}
addDamage={addDamage}
/>
</div>
);
Expand Down
Loading

0 comments on commit fc3b0dc

Please sign in to comment.