Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -4,7 +4,7 @@
"workflow": "photo",
"allowSkipRetake": true,
"addDamage": "part_select",
"enableSightGuidelines": true,
"enableSightGuidelines": "ephemeral",
"allowVehicleTypeSelection": true,
"allowManualLogin": true,
"fetchFromSearchParams": true,
Expand Down
2 changes: 1 addition & 1 deletion documentation/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ The following table lists the available configuration options in the `PhotoCaptu
| 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` |
| addDamage | `AddDamage` | Options for Add Damage. If disabled, the `Add Damage` button will be hidden. | | `AddDamage.PART_SELECT` |
| sightGuidelines | `sightGuideline[]` | A collection of sight guidelines in different language with a list of sightIds associate to it. | | |
| enableSightGuideline | `boolean` | Boolean indicating whether the sight guideline feature is enabled. If disabled, the guideline text will be hidden. | | `true` |
| enableSightGuidelines | `PhotoCaptureSightGuidelinesOption` | Option for displaying the Sight guidelines. If disabled, the guideline text will be hidden. | | `PhotoCaptureSightGuidelines.EPHEMERAL` |
| defaultVehicleType | `VehicleType` | Default vehicle type to use if no vehicle type has been specified. | ✔️ | |
| allowVehicleTypeSelection | `boolean` | Indicates if manual vehicle type selection should be enabled if the vehicle type is not defined. | ✔️ | |
| enableTutorial | `PhotoCaptureTutorialOption` | Options for displaying the photo capture tutorial. | | `PhotoCaptureTutorialOption.FIRST_TIME_ONLY` |
Expand Down
3 changes: 2 additions & 1 deletion documentation/src/utils/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DeviceOrientation,
MileageUnit,
MonkApiPermission,
PhotoCaptureSightGuidelinesOption,
PhotoCaptureTutorialOption,
SteeringWheelPosition,
TaskName,
Expand Down Expand Up @@ -309,7 +310,7 @@ export const LiveConfigSchema = z
useAdaptiveImageQuality: z.boolean().optional(),
allowSkipRetake: z.boolean().optional(),
addDamage: z.nativeEnum(AddDamage).optional(),
enableSightGuidelines: z.boolean().optional(),
enableSightGuidelines: z.nativeEnum(PhotoCaptureSightGuidelinesOption).optional(),
sightGuidelines: z.array(SightGuidelineSchema).optional(),
enableTutorial: z.nativeEnum(PhotoCaptureTutorialOption).optional(),
allowSkipTutorial: z.boolean().optional(),
Expand Down
3 changes: 2 additions & 1 deletion documentation/src/utils/schemas/photoCaptureConfig.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SharedCaptureAppConfigSchema } from '@site/src/utils/schemas/sharedConf
import { ComplianceOptionsSchema } from '@site/src/utils/schemas/compliance.schema';
import {
CaptureWorkflow,
PhotoCaptureSightGuidelinesOption,
PhotoCaptureTutorialOption,
TaskName,
VehicleType,
Expand All @@ -27,7 +28,7 @@ export const PhotoCaptureAppConfigSchema = z
maxUploadDurationWarning: z.number().optional(),
useAdaptiveImageQuality: z.boolean().optional(),
sightGuidelines: z.array(SightGuidelineSchema).optional(),
enableSightGuidelines: z.boolean().optional(),
enableSightGuidelines: z.nativeEnum(PhotoCaptureSightGuidelinesOption).optional(),
defaultVehicleType: z.nativeEnum(VehicleType),
allowVehicleTypeSelection: z.boolean(),
enableTutorial: z.nativeEnum(PhotoCaptureTutorialOption).optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ComplianceOptions,
MonkPicture,
PhotoCaptureAppConfig,
PhotoCaptureSightGuidelinesOption,
PhotoCaptureTutorialOption,
Sight,
VehicleType,
Expand All @@ -37,6 +38,7 @@ import {
useComplianceAnalytics,
usePhotoCaptureSightState,
usePhotoCaptureTutorial,
usePhotoCaptureSightGuidelines,
} from './hooks';

/**
Expand Down Expand Up @@ -137,7 +139,7 @@ export function PhotoCapture({
enableTutorial = PhotoCaptureTutorialOption.FIRST_TIME_ONLY,
allowSkipTutorial = true,
enableSightTutorial = true,
enableSightGuidelines = true,
enableSightGuidelines = PhotoCaptureSightGuidelinesOption.EPHEMERAL,
useAdaptiveImageQuality = true,
lang,
enforceOrientation,
Expand Down Expand Up @@ -202,6 +204,9 @@ export function PhotoCapture({
enableSightGuidelines,
enableSightTutorial,
});
const { showSightGuidelines, handleDisableSightGuidelines } = usePhotoCaptureSightGuidelines({
enableSightGuidelines,
});
const {
isBadConnectionWarningDialogDisplayed,
closeBadConnectionWarningDialog,
Expand Down Expand Up @@ -277,10 +282,11 @@ export function PhotoCapture({
addDamage,
onValidateVehicleParts: addDamageHandle.handleValidateVehicleParts,
sightGuidelines,
enableSightGuidelines,
showSightGuidelines,
currentTutorialStep,
onNextTutorialStep: goToNextTutorialStep,
onCloseTutorial: closeTutorial,
onDisableSightGuidelines: handleDisableSightGuidelines,
allowSkipTutorial,
enforceOrientation,
vehicleType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export interface PhotoCaptureHUDProps
extends CameraHUDProps,
Pick<
PhotoCaptureAppConfig,
| 'enableSightGuidelines'
| 'sightGuidelines'
| 'addDamage'
| 'showCloseButton'
Expand Down Expand Up @@ -109,6 +108,10 @@ export interface PhotoCaptureHUDProps
* Callback called when the user clicks on the "Validate" button of the Add Damage mode.
*/
onValidateVehicleParts: () => void;
/**
* Callback called when the user clicks on both: 'disable' checkbox and 'okay' button.
*/
onDisableSightGuidelines: () => 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 @@ -122,6 +125,10 @@ export interface PhotoCaptureHUDProps
* The vehicle type of the inspection.
*/
vehicleType: VehicleType;
/**
* Boolean indicating whether the sight guidelines should be displayed.
*/
showSightGuidelines: boolean;
}

/**
Expand Down Expand Up @@ -153,13 +160,14 @@ export function PhotoCaptureHUD({
images,
addDamage,
sightGuidelines,
enableSightGuidelines,
showSightGuidelines,
currentTutorialStep,
allowSkipTutorial,
onNextTutorialStep,
onCloseTutorial,
enforceOrientation,
vehicleType,
onDisableSightGuidelines,
}: PhotoCaptureHUDProps) {
const { t } = useTranslation();
const [showCloseModal, setShowCloseModal] = useState(false);
Expand Down Expand Up @@ -203,9 +211,10 @@ export function PhotoCaptureHUD({
images={images}
addDamage={addDamage}
sightGuidelines={sightGuidelines}
enableSightGuidelines={enableSightGuidelines}
showSightGuidelines={showSightGuidelines}
tutorialStep={currentTutorialStep}
vehicleType={vehicleType}
onDisableSightGuidelines={onDisableSightGuidelines}
/>
</div>
{mode !== CaptureMode.ADD_DAMAGE_PART_SELECT && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { CaptureMode } from '../../../types';
* Props of the PhotoCaptureHUDElements component.
*/
export interface PhotoCaptureHUDElementsProps
extends Pick<PhotoCaptureAppConfig, 'enableSightGuidelines' | 'sightGuidelines' | 'addDamage'> {
extends Pick<PhotoCaptureAppConfig, 'sightGuidelines' | 'addDamage'> {
/**
* The currently selected sight in the PhotoCapture component : the sight that the user needs to capture.
*/
Expand Down Expand Up @@ -64,6 +64,10 @@ export interface PhotoCaptureHUDElementsProps
* Callback called when the user clicks on the "Validate" button of the Add Damage mode.
*/
onValidateVehicleParts: () => void;
/**
* Callback called when the user clicks on both: 'disable' checkbox and 'okay' button.
*/
onDisableSightGuidelines?: () => void;
/**
* The effective pixel dimensions of the Camera video stream on the screen.
*/
Expand All @@ -84,6 +88,10 @@ export interface PhotoCaptureHUDElementsProps
* The vehicle type of the inspection.
*/
vehicleType: VehicleType;
/**
* Boolean indicating whether the sight guidelines should be displayed.
*/
showSightGuidelines?: boolean;
}

/**
Expand All @@ -106,8 +114,9 @@ export function PhotoCaptureHUDElements(params: PhotoCaptureHUDElementsProps) {
images={params.images}
addDamage={params.addDamage}
sightGuidelines={params.sightGuidelines}
enableSightGuidelines={params.enableSightGuidelines}
showSightGuidelines={params.showSightGuidelines}
tutorialStep={params.tutorialStep}
onDisableSightGuidelines={params.onDisableSightGuidelines}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ export function PhotoCaptureHUDElementsSight({
onSelectedSight = () => {},
onRetakeSight = () => {},
onAddDamage = () => {},
onDisableSightGuidelines = () => {},
sightsTaken,
previewDimensions,
images,
addDamage,
sightGuidelines,
enableSightGuidelines,
showSightGuidelines,
tutorialStep,
}: PhotoCaptureHUDElementsSightProps) {
const style = usePhotoCaptureHUDSightPreviewStyle({ previewDimensions });
Expand All @@ -39,8 +40,9 @@ export function PhotoCaptureHUDElementsSight({
<SightGuideline
sightId={selectedSight.id}
sightGuidelines={sightGuidelines}
enableSightGuidelines={enableSightGuidelines}
disabled={!showSightGuidelines}
addDamage={addDamage}
onDisableSightGuidelines={onDisableSightGuidelines}
/>
<AddDamageButton onAddDamage={onAddDamage} addDamage={addDamage} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,29 @@ export const styles: Styles = {
width: `calc(98% - (${PHOTO_CAPTURE_HUD_BUTTONS_BAR_WIDTH * 4}px))`,
justifyContent: 'center',
},
button: {
textAlign: 'start',
guideline: {
display: 'flex',
flexDirection: 'column',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderRadius: '12px',
fontSize: 14,
flexDirection: 'row-reverse',
paddingRight: 0,
alignItems: 'start',
gap: 10,
justifyContent: 'start',
padding: '10px',
gap: '8px',
letterSpacing: '0.15px',
fontSize: '14',
},
buttonContainer: {
display: 'flex',
justifyContent: 'space-between',
padding: '0px 10px 0px',
},
checkbox: {
display: 'flex',
cursor: 'pointer',
gap: '5px',
},
button: {
all: 'unset',
cursor: 'pointer',
},
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { useEffect, useState } from 'react';
import { Button } from '@monkvision/common-ui-web';
import { AddDamage, PhotoCaptureAppConfig } from '@monkvision/types';
import { PhotoCaptureAppConfig } from '@monkvision/types';
import { useTranslation } from 'react-i18next';
import { getLanguage } from '@monkvision/common';
import { styles } from './SightGuideline.styles';
import { useColorBackground } from '../../../../hooks';
import { useSightGuidelineStyle } from './hooks';

/**
* Props of the SightGuideline component.
*/
export interface SightGuidelineProps
extends Pick<PhotoCaptureAppConfig, 'addDamage' | 'sightGuidelines' | 'enableSightGuidelines'> {
extends Pick<PhotoCaptureAppConfig, 'addDamage' | 'sightGuidelines'> {
/**
* The id of the sight.
*/
Expand All @@ -21,6 +20,16 @@ export interface SightGuidelineProps
* @default false
*/
enableDefaultMessage?: boolean;
/**
* Boolean indicating if the sight guidelines are enabled.
*
* @default true
*/
disabled?: boolean;
/**
* Callback called when the user clicks on both: 'disable' checkbox and 'okay' button.
*/
onDisableSightGuidelines?: () => void;
}

/**
Expand All @@ -29,15 +38,16 @@ export interface SightGuidelineProps
export function SightGuideline({
sightId,
sightGuidelines,
enableSightGuidelines,
addDamage,
enableDefaultMessage = false,
disabled = false,
onDisableSightGuidelines = () => {},
}: SightGuidelineProps) {
const [showGuideline, setShowGuideline] = useState(true);
const primaryColor = useColorBackground();
const { i18n, t } = useTranslation();
const [checked, setChecked] = useState(false);

const style = addDamage === AddDamage.DISABLED ? styles['containerWide'] : styles['container'];
const { i18n, t } = useTranslation();
const style = useSightGuidelineStyle({ addDamage });

const guidelineFound = sightGuidelines?.find((value) => value.sightIds.includes(sightId));

Expand All @@ -47,19 +57,46 @@ export function SightGuideline({

const guideline = guidelineFound ? guidelineFound[getLanguage(i18n.language)] : defaultMessage;

const handleShowSightGuidelines = () => {
if (checked) {
onDisableSightGuidelines();
}
setShowGuideline(false);
};

useEffect(() => setShowGuideline(true), [sightId]);

return (
<div style={style}>
{enableSightGuidelines && showGuideline && guideline && (
<Button
icon='close'
primaryColor={primaryColor}
style={styles['button']}
onClick={() => setShowGuideline(false)}
>
<div style={style.container} data-testid='container'>
{!disabled && showGuideline && guideline && (
<div style={style.guideline} data-testid='guideline'>
{guideline}
</Button>
<div style={styles['buttonContainer']}>
<div
style={styles['checkbox']}
role='checkbox'
aria-checked={checked}
tabIndex={0}
onClick={() => setChecked(!checked)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
setChecked(!checked);
}
}}
data-testid='checkbox-container'
>
<input type='checkbox' checked={checked} onChange={(e) => e.stopPropagation()} />
<span>{t('photo.hud.guidelines.disable')}</span>
</div>
<button
style={styles['button']}
onClick={handleShowSightGuidelines}
data-testid='button'
>
{t('photo.hud.guidelines.validate')}
</button>
</div>
</div>
)}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { AddDamage } from '@monkvision/types';
import { styles } from './SightGuideline.styles';
import { useColorBackground } from '../../../../hooks';

export interface SightGuidelineParams {
addDamage?: AddDamage;
}

export function useSightGuidelineStyle({ addDamage }: SightGuidelineParams) {
const backgroundColor = useColorBackground();

return {
container: addDamage === AddDamage.DISABLED ? styles['containerWide'] : styles['container'],
guideline: {
...styles['guideline'],
backgroundColor,
},
};
}
Loading