/**
* @ai-summary Review screen for extracted maintenance schedules from manual OCR
* @ai-context Dialog showing extracted items with checkboxes, inline editing, batch create
*/
import React, { useState, useCallback } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
Box,
Typography,
TextField,
Checkbox,
IconButton,
Alert,
CircularProgress,
Chip,
useTheme,
useMediaQuery,
} from '@mui/material';
import EditIcon from '@mui/icons-material/Edit';
import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
import SelectAllIcon from '@mui/icons-material/SelectAll';
import DeselectIcon from '@mui/icons-material/Deselect';
import type { MaintenanceScheduleItem } from '../../documents/hooks/useManualExtraction';
import { useCreateSchedulesFromExtraction } from '../hooks/useCreateSchedulesFromExtraction';
export interface MaintenanceScheduleReviewScreenProps {
open: boolean;
items: MaintenanceScheduleItem[];
vehicleId: string;
onClose: () => void;
onCreated: (count: number) => void;
}
interface EditableItem extends MaintenanceScheduleItem {
selected: boolean;
}
const ConfidenceIndicator: React.FC<{ confidence: number }> = ({ confidence }) => {
const filledDots = Math.round(confidence * 4);
const isLow = confidence < 0.6;
return (
{[0, 1, 2, 3].map((i) => (
))}
);
};
interface InlineFieldProps {
label: string;
value: string | number | null;
type?: 'text' | 'number';
onSave: (value: string | number | null) => void;
suffix?: string;
}
const InlineField: React.FC = ({ label, value, type = 'text', onSave, suffix }) => {
const [isEditing, setIsEditing] = useState(false);
const [editValue, setEditValue] = useState(value !== null ? String(value) : '');
const displayValue = value !== null
? (suffix ? `${value} ${suffix}` : String(value))
: '-';
const handleSave = () => {
let parsed: string | number | null = editValue || null;
if (type === 'number' && editValue) {
const num = parseFloat(editValue);
parsed = isNaN(num) ? null : num;
}
onSave(parsed);
setIsEditing(false);
};
const handleCancel = () => {
setEditValue(value !== null ? String(value) : '');
setIsEditing(false);
};
if (isEditing) {
return (
{label}:
setEditValue(e.target.value)}
type={type === 'number' ? 'number' : 'text'}
inputProps={{ step: type === 'number' ? 1 : undefined }}
autoFocus
sx={{ flex: 1, '& .MuiInputBase-input': { py: 0.5, px: 1, fontSize: '0.875rem' } }}
onKeyDown={(e) => {
if (e.key === 'Enter') handleSave();
if (e.key === 'Escape') handleCancel();
}}
/>
);
}
return (
setIsEditing(true)}
role="button"
tabIndex={0}
aria-label={`Edit ${label}`}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setIsEditing(true);
}
}}
>
{label}:
{displayValue}
);
};
export const MaintenanceScheduleReviewScreen: React.FC = ({
open,
items,
vehicleId,
onClose,
onCreated,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const createMutation = useCreateSchedulesFromExtraction();
const [editableItems, setEditableItems] = useState(() =>
items.map((item) => ({ ...item, selected: true }))
);
const [createError, setCreateError] = useState(null);
const selectedCount = editableItems.filter((i) => i.selected).length;
const handleToggle = useCallback((index: number) => {
setEditableItems((prev) =>
prev.map((item, i) => (i === index ? { ...item, selected: !item.selected } : item))
);
}, []);
const handleSelectAll = useCallback(() => {
setEditableItems((prev) => prev.map((item) => ({ ...item, selected: true })));
}, []);
const handleDeselectAll = useCallback(() => {
setEditableItems((prev) => prev.map((item) => ({ ...item, selected: false })));
}, []);
const handleFieldUpdate = useCallback((index: number, field: keyof MaintenanceScheduleItem, value: string | number | null) => {
setEditableItems((prev) =>
prev.map((item, i) => (i === index ? { ...item, [field]: value } : item))
);
}, []);
const handleCreate = async () => {
setCreateError(null);
const selectedItems = editableItems.filter((i) => i.selected);
if (selectedItems.length === 0) return;
try {
await createMutation.mutateAsync({ vehicleId, items: selectedItems });
onCreated(selectedItems.length);
} catch (err: any) {
setCreateError(err?.message || 'Failed to create maintenance schedules');
}
};
const isEmpty = items.length === 0;
return (
);
};
export default MaintenanceScheduleReviewScreen;