@@ -464,6 +464,9 @@ const InspectionDetailsPanel = ({
464464 const [ maintenanceModalMode , setMaintenanceModalMode ] = useState < "form" | "view" > ( "form" ) ;
465465 const [ showMaintenanceModal , setShowMaintenanceModal ] = useState ( false ) ;
466466 const [ isSavingMaintenance , setIsSavingMaintenance ] = useState ( false ) ;
467+ const [ isDeletingMaintenance , setIsDeletingMaintenance ] = useState ( false ) ;
468+ const [ showDeleteMaintenanceConfirm , setShowDeleteMaintenanceConfirm ] = useState ( false ) ;
469+ const [ deleteMaintenanceError , setDeleteMaintenanceError ] = useState < string | null > ( null ) ;
467470 const [ isReportGenerating , setIsReportGenerating ] = useState ( false ) ;
468471 const [ userRole , setUserRole ] = useState < string | null > ( null ) ;
469472
@@ -1183,10 +1186,20 @@ const InspectionDetailsPanel = ({
11831186 } ;
11841187
11851188 const closeMaintenanceModal = ( ) => {
1186- if ( isSavingMaintenance ) return ;
1189+ if ( isSavingMaintenance || isDeletingMaintenance ) return ;
11871190 setShowMaintenanceModal ( false ) ;
11881191 } ;
11891192
1193+ const openMaintenanceDeleteConfirm = ( ) => {
1194+ setDeleteMaintenanceError ( null ) ;
1195+ setShowDeleteMaintenanceConfirm ( true ) ;
1196+ } ;
1197+
1198+ const closeMaintenanceDeleteConfirm = ( ) => {
1199+ if ( isDeletingMaintenance ) return ;
1200+ setShowDeleteMaintenanceConfirm ( false ) ;
1201+ } ;
1202+
11901203 const handleMaintenanceInputChange = (
11911204 field : keyof MaintenanceFormState ,
11921205 value : string
@@ -1195,7 +1208,7 @@ const InspectionDetailsPanel = ({
11951208 } ;
11961209
11971210 const handleMaintenanceSave = async ( ) => {
1198- if ( ! inspection . id ) return ;
1211+ if ( ! inspection . id || isSavingMaintenance || isDeletingMaintenance ) return ;
11991212 const trimmedTimestamp = maintenanceForm . timestamp . trim ( ) ;
12001213 if ( ! trimmedTimestamp ) {
12011214 setMaintenanceFormError ( "Timestamp is required." ) ;
@@ -1247,6 +1260,46 @@ const InspectionDetailsPanel = ({
12471260 }
12481261 } ;
12491262
1263+ const handleMaintenanceDelete = async ( ) => {
1264+ if ( ! inspection . id || ! maintenanceRecord || isDeletingMaintenance || isSavingMaintenance ) {
1265+ return ;
1266+ }
1267+ setIsDeletingMaintenance ( true ) ;
1268+ setMaintenanceFormError ( null ) ;
1269+ setDeleteMaintenanceError ( null ) ;
1270+ try {
1271+ const response = await fetch (
1272+ apiUrl ( `/api/inspections/${ inspection . id } /maintenance-record` ) ,
1273+ {
1274+ method : "DELETE" ,
1275+ headers : {
1276+ ...authHeaders ( ) ,
1277+ } ,
1278+ }
1279+ ) ;
1280+ if ( ! response . ok ) {
1281+ const text = await response . text ( ) . catch ( ( ) => "" ) ;
1282+ throw new Error (
1283+ text || `Failed to delete maintenance record (${ response . status } )`
1284+ ) ;
1285+ }
1286+ setMaintenanceRecord ( null ) ;
1287+ setMaintenanceForm ( buildMaintenanceFormState ( ) ) ;
1288+ setMaintenanceError ( null ) ;
1289+ setShowDeleteMaintenanceConfirm ( false ) ;
1290+ setShowMaintenanceModal ( false ) ;
1291+ } catch ( error ) {
1292+ const message =
1293+ error instanceof Error
1294+ ? error . message
1295+ : "Unable to delete maintenance record." ;
1296+ setMaintenanceFormError ( message ) ;
1297+ setDeleteMaintenanceError ( message ) ;
1298+ } finally {
1299+ setIsDeletingMaintenance ( false ) ;
1300+ }
1301+ } ;
1302+
12501303 const handleResetModelClick = ( ) => {
12511304 setResetModelMessage ( null ) ;
12521305 setResetModelError ( null ) ;
@@ -3014,12 +3067,12 @@ const InspectionDetailsPanel = ({
30143067 < span className = "block text-xs uppercase tracking-wide mb-1" > Timestamp *</ span >
30153068 < input
30163069 type = "text"
3017- className = "w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 text-sm bg-white dark:bg-[#111] "
3070+ className = "w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 text-sm bg-gray-100 dark:bg-[#1a1a1a] cursor-not-allowed "
30183071 placeholder = "e.g. 2025-11-24T10:00Z"
30193072 value = { maintenanceForm . timestamp }
3020- onChange = { ( event ) =>
3021- handleMaintenanceInputChange ( "timestamp" , event . target . value )
3022- }
3073+ readOnly
3074+ aria-readonly = "true"
3075+ title = "Timestamp is generated automatically"
30233076 />
30243077 </ label >
30253078 < label className = "text-sm text-gray-700 dark:text-gray-200" >
@@ -3103,26 +3156,38 @@ const InspectionDetailsPanel = ({
31033156 }
31043157 />
31053158 </ label >
3106- < div className = "flex justify-end gap-2" >
3107- < button
3108- type = "button"
3109- className = "px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded text-gray-900 dark:text-white"
3110- onClick = { closeMaintenanceModal }
3111- disabled = { isSavingMaintenance }
3112- >
3113- Cancel
3114- </ button >
3115- < button
3116- type = "submit"
3117- className = "px-4 py-1.5 text-sm rounded bg-green-600 text-white disabled:opacity-60"
3118- disabled = { isSavingMaintenance }
3119- >
3120- { isSavingMaintenance
3121- ? "Saving…"
3122- : maintenanceRecord
3123- ? "Update record"
3124- : "Save record" }
3125- </ button >
3159+ < div className = "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between" >
3160+ { maintenanceRecord && (
3161+ < button
3162+ type = "button"
3163+ className = "w-full sm:w-auto px-4 py-1.5 text-sm rounded border border-red-200 bg-red-50 text-red-700 dark:border-red-700/50 dark:bg-red-900/20 dark:text-red-300 disabled:opacity-60"
3164+ onClick = { openMaintenanceDeleteConfirm }
3165+ disabled = { isSavingMaintenance || isDeletingMaintenance }
3166+ >
3167+ { isDeletingMaintenance ? "Deleting…" : "Delete record" }
3168+ </ button >
3169+ ) }
3170+ < div className = "flex justify-end gap-2" >
3171+ < button
3172+ type = "button"
3173+ className = "px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded text-gray-900 dark:text-white"
3174+ onClick = { closeMaintenanceModal }
3175+ disabled = { isSavingMaintenance || isDeletingMaintenance }
3176+ >
3177+ Cancel
3178+ </ button >
3179+ < button
3180+ type = "submit"
3181+ className = "px-4 py-1.5 text-sm rounded bg-green-600 text-white disabled:opacity-60"
3182+ disabled = { isSavingMaintenance || isDeletingMaintenance }
3183+ >
3184+ { isSavingMaintenance
3185+ ? "Saving…"
3186+ : maintenanceRecord
3187+ ? "Update record"
3188+ : "Save record" }
3189+ </ button >
3190+ </ div >
31263191 </ div >
31273192 </ form >
31283193 < MaintenanceAnnotationPreview
@@ -3139,6 +3204,41 @@ const InspectionDetailsPanel = ({
31393204 </ div >
31403205 </ div >
31413206 ) }
3207+ { showDeleteMaintenanceConfirm && (
3208+ < div className = "fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4" >
3209+ < div className = "details-panel w-full max-w-md rounded-lg bg-white dark:bg-[#111] p-5 shadow-2xl" >
3210+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white mb-2" >
3211+ Delete maintenance record?
3212+ </ h3 >
3213+ < p className = "text-sm text-gray-700 dark:text-gray-300 mb-4" >
3214+ This record will be removed permanently and cannot be recovered. Are you sure you want to continue?
3215+ </ p >
3216+ { deleteMaintenanceError && (
3217+ < div className = "mb-3 text-sm text-red-600" role = "alert" >
3218+ { deleteMaintenanceError }
3219+ </ div >
3220+ ) }
3221+ < div className = "flex justify-end gap-2" >
3222+ < button
3223+ type = "button"
3224+ className = "px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded text-gray-900 dark:text-white"
3225+ onClick = { closeMaintenanceDeleteConfirm }
3226+ disabled = { isDeletingMaintenance }
3227+ >
3228+ Cancel
3229+ </ button >
3230+ < button
3231+ type = "button"
3232+ className = "px-4 py-1.5 text-sm rounded bg-red-600 text-white disabled:opacity-60"
3233+ onClick = { ( ) => void handleMaintenanceDelete ( ) }
3234+ disabled = { isDeletingMaintenance }
3235+ >
3236+ { isDeletingMaintenance ? "Deleting…" : "Delete" }
3237+ </ button >
3238+ </ div >
3239+ </ div >
3240+ </ div >
3241+ ) }
31423242 { /* Fault selection modal */ }
31433243 { showFaultModal && pendingRect && (
31443244 < div className = "fixed inset-0 z-50 flex items-center justify-center bg-black/50" >
0 commit comments