@inspectorhub/field-ui 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/{data-source-IaWUdrIc.d.ts → data-source-B3NrVs6i.d.ts} +27 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1102 -644
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ function isDecodeImageError(e) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// src/context.tsx
|
|
19
|
-
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
19
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
20
20
|
|
|
21
21
|
// src/i18n/generated/messages/_index.js
|
|
22
22
|
var index_exports = {};
|
|
@@ -456,6 +456,9 @@ __export(index_exports, {
|
|
|
456
456
|
editor_dock_photo_studio: () => editor_dock_photo_studio3,
|
|
457
457
|
editor_dock_speed_mode: () => editor_dock_speed_mode3,
|
|
458
458
|
editor_finish_fieldwork: () => editor_finish_fieldwork3,
|
|
459
|
+
editor_finish_fieldwork_confirm_body: () => editor_finish_fieldwork_confirm_body3,
|
|
460
|
+
editor_finish_fieldwork_confirm_title: () => editor_finish_fieldwork_confirm_title3,
|
|
461
|
+
editor_finish_fieldwork_done: () => editor_finish_fieldwork_done3,
|
|
459
462
|
editor_finish_fieldwork_error: () => editor_finish_fieldwork_error3,
|
|
460
463
|
editor_finish_fieldwork_pending: () => editor_finish_fieldwork_pending3,
|
|
461
464
|
editor_followup_notes_placeholder: () => editor_followup_notes_placeholder3,
|
|
@@ -688,6 +691,8 @@ __export(index_exports, {
|
|
|
688
691
|
editor_route_exit_batch_mode: () => editor_route_exit_batch_mode3,
|
|
689
692
|
editor_route_expand_photo_rail: () => editor_route_expand_photo_rail3,
|
|
690
693
|
editor_route_filter_all: () => editor_route_filter_all3,
|
|
694
|
+
editor_route_filter_all_in_section: () => editor_route_filter_all_in_section3,
|
|
695
|
+
editor_route_filter_count_in_section: () => editor_route_filter_count_in_section3,
|
|
691
696
|
editor_route_filter_flagged: () => editor_route_filter_flagged3,
|
|
692
697
|
editor_route_filter_issues: () => editor_route_filter_issues3,
|
|
693
698
|
editor_route_filter_unrated: () => editor_route_filter_unrated3,
|
|
@@ -835,6 +840,7 @@ __export(index_exports, {
|
|
|
835
840
|
editor_structuredelete_title: () => editor_structuredelete_title3,
|
|
836
841
|
editor_tagchiprow_more: () => editor_tagchiprow_more3,
|
|
837
842
|
editor_tagchiprow_open_library_aria: () => editor_tagchiprow_open_library_aria3,
|
|
843
|
+
editor_tagpicker_empty: () => editor_tagpicker_empty3,
|
|
838
844
|
editor_tagpicker_title: () => editor_tagpicker_title3,
|
|
839
845
|
editor_template_applied_reopen: () => editor_template_applied_reopen3,
|
|
840
846
|
editor_typeahead_kind_defect: () => editor_typeahead_kind_defect3,
|
|
@@ -8187,6 +8193,33 @@ var editor_finish_fieldwork_error = (
|
|
|
8187
8193
|
);
|
|
8188
8194
|
}
|
|
8189
8195
|
);
|
|
8196
|
+
var editor_finish_fieldwork_confirm_title = (
|
|
8197
|
+
/** @type {(inputs: Editor_Finish_Fieldwork_Confirm_TitleInputs) => LocalizedString} */
|
|
8198
|
+
() => {
|
|
8199
|
+
return (
|
|
8200
|
+
/** @type {LocalizedString} */
|
|
8201
|
+
`Finish fieldwork?`
|
|
8202
|
+
);
|
|
8203
|
+
}
|
|
8204
|
+
);
|
|
8205
|
+
var editor_finish_fieldwork_confirm_body = (
|
|
8206
|
+
/** @type {(inputs: Editor_Finish_Fieldwork_Confirm_BodyInputs) => LocalizedString} */
|
|
8207
|
+
() => {
|
|
8208
|
+
return (
|
|
8209
|
+
/** @type {LocalizedString} */
|
|
8210
|
+
`The on-site work will be marked as finished. Publishing the report does not depend on it.`
|
|
8211
|
+
);
|
|
8212
|
+
}
|
|
8213
|
+
);
|
|
8214
|
+
var editor_finish_fieldwork_done = (
|
|
8215
|
+
/** @type {(inputs: Editor_Finish_Fieldwork_DoneInputs) => LocalizedString} */
|
|
8216
|
+
() => {
|
|
8217
|
+
return (
|
|
8218
|
+
/** @type {LocalizedString} */
|
|
8219
|
+
`Fieldwork marked as finished.`
|
|
8220
|
+
);
|
|
8221
|
+
}
|
|
8222
|
+
);
|
|
8190
8223
|
var editor_publish_not_completed_prompt = (
|
|
8191
8224
|
/** @type {(inputs: Editor_Publish_Not_Completed_PromptInputs) => LocalizedString} */
|
|
8192
8225
|
() => {
|
|
@@ -8772,6 +8805,15 @@ var editor_tagpicker_title = (
|
|
|
8772
8805
|
);
|
|
8773
8806
|
}
|
|
8774
8807
|
);
|
|
8808
|
+
var editor_tagpicker_empty = (
|
|
8809
|
+
/** @type {(inputs: Editor_Tagpicker_EmptyInputs) => LocalizedString} */
|
|
8810
|
+
() => {
|
|
8811
|
+
return (
|
|
8812
|
+
/** @type {LocalizedString} */
|
|
8813
|
+
`There are no tags yet. Add tags in the Library, then choose them here.`
|
|
8814
|
+
);
|
|
8815
|
+
}
|
|
8816
|
+
);
|
|
8775
8817
|
var editor_unitprogress_summary_aria = (
|
|
8776
8818
|
/** @type {(inputs: Editor_Unitprogress_Summary_AriaInputs) => LocalizedString} */
|
|
8777
8819
|
(i) => {
|
|
@@ -9792,6 +9834,24 @@ var editor_route_filter_flagged = (
|
|
|
9792
9834
|
);
|
|
9793
9835
|
}
|
|
9794
9836
|
);
|
|
9837
|
+
var editor_route_filter_all_in_section = (
|
|
9838
|
+
/** @type {(inputs: Editor_Route_Filter_All_In_SectionInputs) => LocalizedString} */
|
|
9839
|
+
() => {
|
|
9840
|
+
return (
|
|
9841
|
+
/** @type {LocalizedString} */
|
|
9842
|
+
`All items in this section`
|
|
9843
|
+
);
|
|
9844
|
+
}
|
|
9845
|
+
);
|
|
9846
|
+
var editor_route_filter_count_in_section = (
|
|
9847
|
+
/** @type {(inputs: Editor_Route_Filter_Count_In_SectionInputs) => LocalizedString} */
|
|
9848
|
+
(i) => {
|
|
9849
|
+
return (
|
|
9850
|
+
/** @type {LocalizedString} */
|
|
9851
|
+
`${i?.label} ${i?.count} in this section`
|
|
9852
|
+
);
|
|
9853
|
+
}
|
|
9854
|
+
);
|
|
9795
9855
|
var editor_route_exit_batch_mode = (
|
|
9796
9856
|
/** @type {(inputs: Editor_Route_Exit_Batch_ModeInputs) => LocalizedString} */
|
|
9797
9857
|
() => {
|
|
@@ -22460,7 +22520,7 @@ var report_publish_body_delivery = (
|
|
|
22460
22520
|
() => {
|
|
22461
22521
|
return (
|
|
22462
22522
|
/** @type {LocalizedString} */
|
|
22463
|
-
`It does not send the report itself. Report notices are queued to your automations and go out on the next delivery pass \u2014 to put the report in someone's inbox now,
|
|
22523
|
+
`It does not send the report itself. Report notices are queued to your automations and go out on the next delivery pass \u2014 to put the report in someone's inbox now, send it from the inspection.`
|
|
22464
22524
|
);
|
|
22465
22525
|
}
|
|
22466
22526
|
);
|
|
@@ -28748,6 +28808,33 @@ var editor_finish_fieldwork_error2 = (
|
|
|
28748
28808
|
);
|
|
28749
28809
|
}
|
|
28750
28810
|
);
|
|
28811
|
+
var editor_finish_fieldwork_confirm_title2 = (
|
|
28812
|
+
/** @type {(inputs: Editor_Finish_Fieldwork_Confirm_TitleInputs) => LocalizedString} */
|
|
28813
|
+
() => {
|
|
28814
|
+
return (
|
|
28815
|
+
/** @type {LocalizedString} */
|
|
28816
|
+
`\xBFFinalizar el trabajo de campo?`
|
|
28817
|
+
);
|
|
28818
|
+
}
|
|
28819
|
+
);
|
|
28820
|
+
var editor_finish_fieldwork_confirm_body2 = (
|
|
28821
|
+
/** @type {(inputs: Editor_Finish_Fieldwork_Confirm_BodyInputs) => LocalizedString} */
|
|
28822
|
+
() => {
|
|
28823
|
+
return (
|
|
28824
|
+
/** @type {LocalizedString} */
|
|
28825
|
+
`El trabajo en sitio se marcar\xE1 como finalizado. Publicar el informe no depende de ello.`
|
|
28826
|
+
);
|
|
28827
|
+
}
|
|
28828
|
+
);
|
|
28829
|
+
var editor_finish_fieldwork_done2 = (
|
|
28830
|
+
/** @type {(inputs: Editor_Finish_Fieldwork_DoneInputs) => LocalizedString} */
|
|
28831
|
+
() => {
|
|
28832
|
+
return (
|
|
28833
|
+
/** @type {LocalizedString} */
|
|
28834
|
+
`Trabajo de campo marcado como finalizado.`
|
|
28835
|
+
);
|
|
28836
|
+
}
|
|
28837
|
+
);
|
|
28751
28838
|
var editor_publish_not_completed_prompt2 = (
|
|
28752
28839
|
/** @type {(inputs: Editor_Publish_Not_Completed_PromptInputs) => LocalizedString} */
|
|
28753
28840
|
() => {
|
|
@@ -29333,6 +29420,15 @@ var editor_tagpicker_title2 = (
|
|
|
29333
29420
|
);
|
|
29334
29421
|
}
|
|
29335
29422
|
);
|
|
29423
|
+
var editor_tagpicker_empty2 = (
|
|
29424
|
+
/** @type {(inputs: Editor_Tagpicker_EmptyInputs) => LocalizedString} */
|
|
29425
|
+
() => {
|
|
29426
|
+
return (
|
|
29427
|
+
/** @type {LocalizedString} */
|
|
29428
|
+
`Todav\xEDa no hay etiquetas. Agrega etiquetas en la Biblioteca y luego el\xEDgelas aqu\xED.`
|
|
29429
|
+
);
|
|
29430
|
+
}
|
|
29431
|
+
);
|
|
29336
29432
|
var editor_unitprogress_summary_aria2 = (
|
|
29337
29433
|
/** @type {(inputs: Editor_Unitprogress_Summary_AriaInputs) => LocalizedString} */
|
|
29338
29434
|
(i) => {
|
|
@@ -30353,6 +30449,24 @@ var editor_route_filter_flagged2 = (
|
|
|
30353
30449
|
);
|
|
30354
30450
|
}
|
|
30355
30451
|
);
|
|
30452
|
+
var editor_route_filter_all_in_section2 = (
|
|
30453
|
+
/** @type {(inputs: Editor_Route_Filter_All_In_SectionInputs) => LocalizedString} */
|
|
30454
|
+
() => {
|
|
30455
|
+
return (
|
|
30456
|
+
/** @type {LocalizedString} */
|
|
30457
|
+
`Todos los elementos de esta secci\xF3n`
|
|
30458
|
+
);
|
|
30459
|
+
}
|
|
30460
|
+
);
|
|
30461
|
+
var editor_route_filter_count_in_section2 = (
|
|
30462
|
+
/** @type {(inputs: Editor_Route_Filter_Count_In_SectionInputs) => LocalizedString} */
|
|
30463
|
+
(i) => {
|
|
30464
|
+
return (
|
|
30465
|
+
/** @type {LocalizedString} */
|
|
30466
|
+
`${i?.label} ${i?.count} en esta secci\xF3n`
|
|
30467
|
+
);
|
|
30468
|
+
}
|
|
30469
|
+
);
|
|
30356
30470
|
var editor_route_exit_batch_mode2 = (
|
|
30357
30471
|
/** @type {(inputs: Editor_Route_Exit_Batch_ModeInputs) => LocalizedString} */
|
|
30358
30472
|
() => {
|
|
@@ -43021,7 +43135,7 @@ var report_publish_body_delivery2 = (
|
|
|
43021
43135
|
() => {
|
|
43022
43136
|
return (
|
|
43023
43137
|
/** @type {LocalizedString} */
|
|
43024
|
-
`No env\xEDa el informe por s\xED mismo. Los avisos del informe se ponen en cola seg\xFAn sus automatizaciones y salen en la pr\xF3xima tanda de env\xEDos \u2014 para que el informe llegue ahora a la bandeja de alguien,
|
|
43138
|
+
`No env\xEDa el informe por s\xED mismo. Los avisos del informe se ponen en cola seg\xFAn sus automatizaciones y salen en la pr\xF3xima tanda de env\xEDos \u2014 para que el informe llegue ahora a la bandeja de alguien, env\xEDelo desde la inspecci\xF3n.`
|
|
43025
43139
|
);
|
|
43026
43140
|
}
|
|
43027
43141
|
);
|
|
@@ -48705,6 +48819,30 @@ var editor_finish_fieldwork_error3 = (
|
|
|
48705
48819
|
return editor_finish_fieldwork_error2(inputs);
|
|
48706
48820
|
})
|
|
48707
48821
|
);
|
|
48822
|
+
var editor_finish_fieldwork_confirm_title3 = (
|
|
48823
|
+
/** @type {((inputs?: Editor_Finish_Fieldwork_Confirm_TitleInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Finish_Fieldwork_Confirm_TitleInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
48824
|
+
((inputs = {}, options = {}) => {
|
|
48825
|
+
const locale = experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
48826
|
+
if (locale === "en") return editor_finish_fieldwork_confirm_title(inputs);
|
|
48827
|
+
return editor_finish_fieldwork_confirm_title2(inputs);
|
|
48828
|
+
})
|
|
48829
|
+
);
|
|
48830
|
+
var editor_finish_fieldwork_confirm_body3 = (
|
|
48831
|
+
/** @type {((inputs?: Editor_Finish_Fieldwork_Confirm_BodyInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Finish_Fieldwork_Confirm_BodyInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
48832
|
+
((inputs = {}, options = {}) => {
|
|
48833
|
+
const locale = experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
48834
|
+
if (locale === "en") return editor_finish_fieldwork_confirm_body(inputs);
|
|
48835
|
+
return editor_finish_fieldwork_confirm_body2(inputs);
|
|
48836
|
+
})
|
|
48837
|
+
);
|
|
48838
|
+
var editor_finish_fieldwork_done3 = (
|
|
48839
|
+
/** @type {((inputs?: Editor_Finish_Fieldwork_DoneInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Finish_Fieldwork_DoneInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
48840
|
+
((inputs = {}, options = {}) => {
|
|
48841
|
+
const locale = experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
48842
|
+
if (locale === "en") return editor_finish_fieldwork_done(inputs);
|
|
48843
|
+
return editor_finish_fieldwork_done2(inputs);
|
|
48844
|
+
})
|
|
48845
|
+
);
|
|
48708
48846
|
var editor_publish_not_completed_prompt3 = (
|
|
48709
48847
|
/** @type {((inputs?: Editor_Publish_Not_Completed_PromptInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Publish_Not_Completed_PromptInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
48710
48848
|
((inputs = {}, options = {}) => {
|
|
@@ -49225,6 +49363,14 @@ var editor_tagpicker_title3 = (
|
|
|
49225
49363
|
return editor_tagpicker_title2(inputs);
|
|
49226
49364
|
})
|
|
49227
49365
|
);
|
|
49366
|
+
var editor_tagpicker_empty3 = (
|
|
49367
|
+
/** @type {((inputs?: Editor_Tagpicker_EmptyInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Tagpicker_EmptyInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
49368
|
+
((inputs = {}, options = {}) => {
|
|
49369
|
+
const locale = experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
49370
|
+
if (locale === "en") return editor_tagpicker_empty(inputs);
|
|
49371
|
+
return editor_tagpicker_empty2(inputs);
|
|
49372
|
+
})
|
|
49373
|
+
);
|
|
49228
49374
|
var editor_unitprogress_summary_aria3 = (
|
|
49229
49375
|
/** @type {((inputs: Editor_Unitprogress_Summary_AriaInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Unitprogress_Summary_AriaInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
49230
49376
|
((inputs, options = {}) => {
|
|
@@ -50129,6 +50275,22 @@ var editor_route_filter_flagged3 = (
|
|
|
50129
50275
|
return editor_route_filter_flagged2(inputs);
|
|
50130
50276
|
})
|
|
50131
50277
|
);
|
|
50278
|
+
var editor_route_filter_all_in_section3 = (
|
|
50279
|
+
/** @type {((inputs?: Editor_Route_Filter_All_In_SectionInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Route_Filter_All_In_SectionInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
50280
|
+
((inputs = {}, options = {}) => {
|
|
50281
|
+
const locale = experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
50282
|
+
if (locale === "en") return editor_route_filter_all_in_section(inputs);
|
|
50283
|
+
return editor_route_filter_all_in_section2(inputs);
|
|
50284
|
+
})
|
|
50285
|
+
);
|
|
50286
|
+
var editor_route_filter_count_in_section3 = (
|
|
50287
|
+
/** @type {((inputs: Editor_Route_Filter_Count_In_SectionInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Route_Filter_Count_In_SectionInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
50288
|
+
((inputs, options = {}) => {
|
|
50289
|
+
const locale = experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
50290
|
+
if (locale === "en") return editor_route_filter_count_in_section(inputs);
|
|
50291
|
+
return editor_route_filter_count_in_section2(inputs);
|
|
50292
|
+
})
|
|
50293
|
+
);
|
|
50132
50294
|
var editor_route_exit_batch_mode3 = (
|
|
50133
50295
|
/** @type {((inputs?: Editor_Route_Exit_Batch_ModeInputs, options?: { locale?: "en" | "es-419" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Editor_Route_Exit_Batch_ModeInputs, { locale?: "en" | "es-419" }, {}>} */
|
|
50134
50296
|
((inputs = {}, options = {}) => {
|
|
@@ -62178,6 +62340,35 @@ function useFieldDataSource() {
|
|
|
62178
62340
|
}
|
|
62179
62341
|
return dataSource;
|
|
62180
62342
|
}
|
|
62343
|
+
function usePhotoUrlVersion() {
|
|
62344
|
+
const { urls } = useFieldDataSource();
|
|
62345
|
+
const store = useMemo(() => {
|
|
62346
|
+
let version = 0;
|
|
62347
|
+
return {
|
|
62348
|
+
// A host that fires once per fetched photo is coalesced to one render per tick.
|
|
62349
|
+
subscribe: (onChange) => {
|
|
62350
|
+
let queued = false;
|
|
62351
|
+
let live = true;
|
|
62352
|
+
const off = urls.subscribe?.(() => {
|
|
62353
|
+
if (queued) return;
|
|
62354
|
+
queued = true;
|
|
62355
|
+
queueMicrotask(() => {
|
|
62356
|
+
queued = false;
|
|
62357
|
+
if (!live) return;
|
|
62358
|
+
version += 1;
|
|
62359
|
+
onChange();
|
|
62360
|
+
});
|
|
62361
|
+
});
|
|
62362
|
+
return () => {
|
|
62363
|
+
live = false;
|
|
62364
|
+
off?.();
|
|
62365
|
+
};
|
|
62366
|
+
},
|
|
62367
|
+
read: () => version
|
|
62368
|
+
};
|
|
62369
|
+
}, [urls]);
|
|
62370
|
+
return useSyncExternalStore(store.subscribe, store.read, store.read);
|
|
62371
|
+
}
|
|
62181
62372
|
function useFieldSlots() {
|
|
62182
62373
|
return useContext(SlotsContext);
|
|
62183
62374
|
}
|
|
@@ -62264,7 +62455,7 @@ function useFieldCommand(inspectionId) {
|
|
|
62264
62455
|
}
|
|
62265
62456
|
|
|
62266
62457
|
// src/editor/FieldEditor.tsx
|
|
62267
|
-
import { useState as
|
|
62458
|
+
import { useState as useState64, useCallback as useCallback47, useMemo as useMemo16, useEffect as useEffect51, useRef as useRef62 } from "react";
|
|
62268
62459
|
|
|
62269
62460
|
// src/shared/inspection-status.ts
|
|
62270
62461
|
var INSPECTION_STATUS_COMPLETED = "completed";
|
|
@@ -62330,7 +62521,7 @@ function makeCustomDefect(input, genId = () => crypto.randomUUID()) {
|
|
|
62330
62521
|
}
|
|
62331
62522
|
|
|
62332
62523
|
// src/hooks/useInspection.ts
|
|
62333
|
-
import { useState as useState2, useCallback as useCallback6, useMemo as
|
|
62524
|
+
import { useState as useState2, useCallback as useCallback6, useMemo as useMemo5, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
62334
62525
|
|
|
62335
62526
|
// src/hooks/findings/shared.ts
|
|
62336
62527
|
var DEFAULT_UNIT = "_default";
|
|
@@ -62371,6 +62562,9 @@ function backfillLevelDescriptions(levels) {
|
|
|
62371
62562
|
});
|
|
62372
62563
|
}
|
|
62373
62564
|
|
|
62565
|
+
// src/lib/severity.ts
|
|
62566
|
+
var FALLBACK_RATING_COLOR = "var(--ih-fg-5, #d4d4d8)";
|
|
62567
|
+
|
|
62374
62568
|
// src/shared/batch-range.ts
|
|
62375
62569
|
function rangeIds(orderedIds, fromId, toId) {
|
|
62376
62570
|
const i = orderedIds.indexOf(fromId);
|
|
@@ -62482,10 +62676,10 @@ function formatCurrency(cents, opts) {
|
|
|
62482
62676
|
}
|
|
62483
62677
|
|
|
62484
62678
|
// src/hooks/inspection/useInspectionProgress.ts
|
|
62485
|
-
import { useCallback as useCallback2, useMemo } from "react";
|
|
62679
|
+
import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
62486
62680
|
function useInspectionProgress(ctx) {
|
|
62487
62681
|
const { sections, ratingLevels, getResult, severityForRatingId } = ctx;
|
|
62488
|
-
const progress =
|
|
62682
|
+
const progress = useMemo2(() => {
|
|
62489
62683
|
let total = 0;
|
|
62490
62684
|
let rated = 0;
|
|
62491
62685
|
for (const sec of sections) {
|
|
@@ -62549,7 +62743,7 @@ function useInspectionProgress(ctx) {
|
|
|
62549
62743
|
},
|
|
62550
62744
|
[sections, ratingLevels, getResult]
|
|
62551
62745
|
);
|
|
62552
|
-
const reportStats =
|
|
62746
|
+
const reportStats = useMemo2(() => {
|
|
62553
62747
|
let total = 0;
|
|
62554
62748
|
let rated = 0;
|
|
62555
62749
|
let satisfactory = 0;
|
|
@@ -62709,7 +62903,7 @@ function useInspectionNavigation(ctx) {
|
|
|
62709
62903
|
}
|
|
62710
62904
|
|
|
62711
62905
|
// src/hooks/inspection/useInspectionSearch.ts
|
|
62712
|
-
import { useCallback as useCallback4, useMemo as
|
|
62906
|
+
import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
|
|
62713
62907
|
function useInspectionSearch(ctx) {
|
|
62714
62908
|
const {
|
|
62715
62909
|
searchQuery,
|
|
@@ -62720,7 +62914,7 @@ function useInspectionSearch(ctx) {
|
|
|
62720
62914
|
currentSection,
|
|
62721
62915
|
getResult
|
|
62722
62916
|
} = ctx;
|
|
62723
|
-
const searchNeedle =
|
|
62917
|
+
const searchNeedle = useMemo3(
|
|
62724
62918
|
() => (searchQuery || "").trim().toLowerCase(),
|
|
62725
62919
|
[searchQuery]
|
|
62726
62920
|
);
|
|
@@ -62766,7 +62960,7 @@ function useInspectionSearch(ctx) {
|
|
|
62766
62960
|
},
|
|
62767
62961
|
[itemFilter, getResult, ratingLevels, tagsByItem]
|
|
62768
62962
|
);
|
|
62769
|
-
const filterCounts =
|
|
62963
|
+
const filterCounts = useMemo3(() => {
|
|
62770
62964
|
const items = currentSectionItems;
|
|
62771
62965
|
const counts = { all: items.length, unrated: 0, issues: 0, flagged: 0 };
|
|
62772
62966
|
for (const item of items) {
|
|
@@ -62791,7 +62985,7 @@ function useInspectionSearch(ctx) {
|
|
|
62791
62985
|
}
|
|
62792
62986
|
|
|
62793
62987
|
// src/hooks/inspection/useInspectionBatch.ts
|
|
62794
|
-
import { useCallback as useCallback5, useMemo as
|
|
62988
|
+
import { useCallback as useCallback5, useMemo as useMemo4 } from "react";
|
|
62795
62989
|
function useInspectionBatch(ctx, selectSection) {
|
|
62796
62990
|
const {
|
|
62797
62991
|
sections,
|
|
@@ -62816,11 +63010,11 @@ function useInspectionBatch(ctx, selectSection) {
|
|
|
62816
63010
|
}
|
|
62817
63011
|
setBatchSelected(next);
|
|
62818
63012
|
}, [currentSectionItems]);
|
|
62819
|
-
const selectedBatchCount =
|
|
63013
|
+
const selectedBatchCount = useMemo4(
|
|
62820
63014
|
() => Object.values(batchSelected).filter(Boolean).length,
|
|
62821
63015
|
[batchSelected]
|
|
62822
63016
|
);
|
|
62823
|
-
const filteredSectionsForPicker =
|
|
63017
|
+
const filteredSectionsForPicker = useMemo4(() => {
|
|
62824
63018
|
const q = (sectionPickerQuery || "").toLowerCase().trim();
|
|
62825
63019
|
const src = sections.map((s, idx) => ({
|
|
62826
63020
|
idx,
|
|
@@ -62940,7 +63134,7 @@ function useInspectionState(opts) {
|
|
|
62940
63134
|
}, []);
|
|
62941
63135
|
const currentSection = sections[currentSectionIdx] || null;
|
|
62942
63136
|
const currentSectionItems = currentSection?.items || [];
|
|
62943
|
-
const activeItem =
|
|
63137
|
+
const activeItem = useMemo5(() => {
|
|
62944
63138
|
if (!activeItemId) return null;
|
|
62945
63139
|
return currentSectionItems.find((i) => i.id === activeItemId) || null;
|
|
62946
63140
|
}, [activeItemId, currentSectionItems]);
|
|
@@ -62992,7 +63186,7 @@ function useInspectionState(opts) {
|
|
|
62992
63186
|
);
|
|
62993
63187
|
const getRatingColor = useCallback6(
|
|
62994
63188
|
(ratingId) => {
|
|
62995
|
-
if (!ratingId) return
|
|
63189
|
+
if (!ratingId) return FALLBACK_RATING_COLOR;
|
|
62996
63190
|
const lvl = ratingLevels.find((l) => l.id === ratingId);
|
|
62997
63191
|
if (lvl?.color) return lvl.color;
|
|
62998
63192
|
const legacy = {
|
|
@@ -63000,7 +63194,7 @@ function useInspectionState(opts) {
|
|
|
63000
63194
|
Monitor: "var(--ih-status-watch, #f59e0b)",
|
|
63001
63195
|
Defect: "var(--ih-status-bad, #ef4444)"
|
|
63002
63196
|
};
|
|
63003
|
-
return legacy[ratingId] ||
|
|
63197
|
+
return legacy[ratingId] || FALLBACK_RATING_COLOR;
|
|
63004
63198
|
},
|
|
63005
63199
|
[ratingLevels]
|
|
63006
63200
|
);
|
|
@@ -63071,7 +63265,7 @@ function useInspectionState(opts) {
|
|
|
63071
63265
|
return next;
|
|
63072
63266
|
});
|
|
63073
63267
|
}, [currentSectionItems]);
|
|
63074
|
-
const formattedDate =
|
|
63268
|
+
const formattedDate = useMemo5(() => {
|
|
63075
63269
|
const d = inspection.date || inspection.scheduledDate || inspection.createdAt;
|
|
63076
63270
|
if (!d) return "";
|
|
63077
63271
|
return formatDate(d, { locale });
|
|
@@ -63522,6 +63716,7 @@ function removeElement(arr, identityField, identityValue) {
|
|
|
63522
63716
|
}
|
|
63523
63717
|
function applyItemPatch(doc, findingKey3, field, value) {
|
|
63524
63718
|
const results = doc.getMap("results");
|
|
63719
|
+
if (results.get(findingKey3)?.get?.(field) === value) return;
|
|
63525
63720
|
doc.transact(() => {
|
|
63526
63721
|
const item = getOrSeedItem(results, findingKey3);
|
|
63527
63722
|
item.set(field, value);
|
|
@@ -64157,7 +64352,7 @@ function useFindings(results, setResults, options) {
|
|
|
64157
64352
|
}
|
|
64158
64353
|
|
|
64159
64354
|
// src/hooks/usePhotoOps.ts
|
|
64160
|
-
import { useState as useState10, useCallback as useCallback16, useMemo as
|
|
64355
|
+
import { useState as useState10, useCallback as useCallback16, useMemo as useMemo6, useEffect as useEffect8, useRef as useRef11 } from "react";
|
|
64161
64356
|
|
|
64162
64357
|
// src/components/media-studio/photo-display-key.ts
|
|
64163
64358
|
function resolvePhotoDisplayKey(entry) {
|
|
@@ -67945,7 +68140,7 @@ function usePhotoOps(ctx) {
|
|
|
67945
68140
|
setPhotoStudioOpen
|
|
67946
68141
|
} = ctx;
|
|
67947
68142
|
const dataSource = useFieldDataSource();
|
|
67948
|
-
const { urls } = dataSource;
|
|
68143
|
+
const { urls } = dataSource, photoUrlVersion = usePhotoUrlVersion();
|
|
67949
68144
|
const mediaSavesInFlight = useRef11(/* @__PURE__ */ new Set());
|
|
67950
68145
|
const [galleryCropSource, setGalleryCropSource] = useState10(null);
|
|
67951
68146
|
const [sessionCoverCrop, setSessionCoverCrop] = useState10(null);
|
|
@@ -67971,7 +68166,7 @@ function usePhotoOps(ctx) {
|
|
|
67971
68166
|
[findings, state.sectionIdForItem]
|
|
67972
68167
|
);
|
|
67973
68168
|
const [pendingUrls, setPendingUrls] = useState10({});
|
|
67974
|
-
const pendingIds =
|
|
68169
|
+
const pendingIds = useMemo6(() => {
|
|
67975
68170
|
const ids = /* @__PURE__ */ new Set();
|
|
67976
68171
|
if (!collabDoc) return ids;
|
|
67977
68172
|
for (const sec of state.sections) {
|
|
@@ -68067,7 +68262,7 @@ function usePhotoOps(ctx) {
|
|
|
68067
68262
|
durationSec: p.durationSec
|
|
68068
68263
|
};
|
|
68069
68264
|
}),
|
|
68070
|
-
[getItemPhotos, state.inspection.id, pendingUrls, urls]
|
|
68265
|
+
[getItemPhotos, state.inspection.id, pendingUrls, urls, photoUrlVersion]
|
|
68071
68266
|
);
|
|
68072
68267
|
const onOpenPhoto = useCallback16((itemId, index) => {
|
|
68073
68268
|
setViewer({ itemId, index });
|
|
@@ -68113,14 +68308,14 @@ function usePhotoOps(ctx) {
|
|
|
68113
68308
|
(itemId, indices) => {
|
|
68114
68309
|
const sectionId = state.currentSection?.id;
|
|
68115
68310
|
const fk = docFindingKey(itemId, sectionId);
|
|
68116
|
-
const
|
|
68117
|
-
const keys = indices.map((i) =>
|
|
68311
|
+
const snapshot2 = getItemPhotos(itemId);
|
|
68312
|
+
const keys = indices.map((i) => snapshot2[i]?.key).filter((k) => !!k);
|
|
68118
68313
|
patchItemPhotos(itemId, (photos) => photos.filter((_, i) => !indices.includes(i)));
|
|
68119
68314
|
if (collabDoc && fk) for (const key of keys) removePhoto2(collabDoc, fk, key);
|
|
68120
68315
|
},
|
|
68121
68316
|
[state.currentSection, collabDoc, docFindingKey, getItemPhotos, patchItemPhotos]
|
|
68122
68317
|
);
|
|
68123
|
-
const moveTargets =
|
|
68318
|
+
const moveTargets = useMemo6(
|
|
68124
68319
|
() => state.sections.flatMap(
|
|
68125
68320
|
(sec) => (sec.items || []).map((it) => ({
|
|
68126
68321
|
itemId: it.id,
|
|
@@ -68135,8 +68330,8 @@ function usePhotoOps(ctx) {
|
|
|
68135
68330
|
const fromSectionId = state.currentSection?.id;
|
|
68136
68331
|
const fromFk = docFindingKey(fromItemId, fromSectionId);
|
|
68137
68332
|
const toFk = docFindingKey(to.itemId, to.sectionId);
|
|
68138
|
-
const
|
|
68139
|
-
const keys = indices.map((i) =>
|
|
68333
|
+
const snapshot2 = getItemPhotos(fromItemId);
|
|
68334
|
+
const keys = indices.map((i) => snapshot2[i]?.key).filter((k) => !!k);
|
|
68140
68335
|
patchItemPhotos(fromItemId, (photos) => photos.filter((_, i) => !indices.includes(i)));
|
|
68141
68336
|
if (collabDoc && fromFk && toFk) for (const key of keys) movePhoto2(collabDoc, fromFk, toFk, key);
|
|
68142
68337
|
},
|
|
@@ -68397,6 +68592,7 @@ function useInspectionPrefs() {
|
|
|
68397
68592
|
const [saving, setSaving] = useState11(false);
|
|
68398
68593
|
const requested = useRef13(false);
|
|
68399
68594
|
const committed = useRef13(DEFAULT_INSPECTION_PREFS);
|
|
68595
|
+
const latest = useRef13(DEFAULT_INSPECTION_PREFS);
|
|
68400
68596
|
const mounted = useRef13(true);
|
|
68401
68597
|
useEffect10(() => {
|
|
68402
68598
|
mounted.current = true;
|
|
@@ -68415,6 +68611,7 @@ function useInspectionPrefs() {
|
|
|
68415
68611
|
(loadedPrefs) => {
|
|
68416
68612
|
committed.current = loadedPrefs;
|
|
68417
68613
|
if (!mounted.current) return;
|
|
68614
|
+
latest.current = loadedPrefs;
|
|
68418
68615
|
setPrefs(loadedPrefs);
|
|
68419
68616
|
setLoaded(true);
|
|
68420
68617
|
},
|
|
@@ -68441,7 +68638,8 @@ function useInspectionPrefs() {
|
|
|
68441
68638
|
if (mounted.current) {
|
|
68442
68639
|
const later = queued.current;
|
|
68443
68640
|
const base = committed.current;
|
|
68444
|
-
|
|
68641
|
+
latest.current = { ...base, ...later };
|
|
68642
|
+
setPrefs(latest.current);
|
|
68445
68643
|
}
|
|
68446
68644
|
} else {
|
|
68447
68645
|
const back = {};
|
|
@@ -68449,7 +68647,8 @@ function useInspectionPrefs() {
|
|
|
68449
68647
|
if (!(key in queued.current)) back[key] = committed.current[key];
|
|
68450
68648
|
}
|
|
68451
68649
|
if (mounted.current) {
|
|
68452
|
-
|
|
68650
|
+
latest.current = { ...latest.current, ...back };
|
|
68651
|
+
setPrefs(latest.current);
|
|
68453
68652
|
setSaveFailed(true);
|
|
68454
68653
|
}
|
|
68455
68654
|
}
|
|
@@ -68459,8 +68658,11 @@ function useInspectionPrefs() {
|
|
|
68459
68658
|
if (mounted.current) setSaving(false);
|
|
68460
68659
|
}
|
|
68461
68660
|
}, []);
|
|
68462
|
-
const patch = useCallback18((
|
|
68463
|
-
|
|
68661
|
+
const patch = useCallback18((change) => {
|
|
68662
|
+
const delta = typeof change === "function" ? change(latest.current) : change;
|
|
68663
|
+
if (Object.keys(delta).length === 0) return;
|
|
68664
|
+
latest.current = { ...latest.current, ...delta };
|
|
68665
|
+
setPrefs(latest.current);
|
|
68464
68666
|
setSaveFailed(false);
|
|
68465
68667
|
if (!prefsStore) return;
|
|
68466
68668
|
queued.current = { ...queued.current, ...delta };
|
|
@@ -68482,8 +68684,59 @@ function useInspectionPrefs() {
|
|
|
68482
68684
|
};
|
|
68483
68685
|
}
|
|
68484
68686
|
|
|
68687
|
+
// src/hooks/useItemTags.ts
|
|
68688
|
+
import { useCallback as useCallback19, useEffect as useEffect11, useRef as useRef14 } from "react";
|
|
68689
|
+
function useItemTags(inspectionId, setTagsByItem) {
|
|
68690
|
+
const dataSource = useFieldDataSource();
|
|
68691
|
+
const store = dataSource.resources.itemTags;
|
|
68692
|
+
const notify = dataSource.notify;
|
|
68693
|
+
const inflight = useRef14(/* @__PURE__ */ new Set());
|
|
68694
|
+
const mounted = useRef14(true);
|
|
68695
|
+
useEffect11(() => {
|
|
68696
|
+
mounted.current = true;
|
|
68697
|
+
return () => {
|
|
68698
|
+
mounted.current = false;
|
|
68699
|
+
};
|
|
68700
|
+
}, []);
|
|
68701
|
+
useEffect11(() => {
|
|
68702
|
+
if (!store || !inspectionId) return;
|
|
68703
|
+
let live = true;
|
|
68704
|
+
void store.list(inspectionId).then(
|
|
68705
|
+
(saved) => {
|
|
68706
|
+
if (!live || !saved) return;
|
|
68707
|
+
setTagsByItem((prev) => ({ ...saved, ...prev }));
|
|
68708
|
+
},
|
|
68709
|
+
() => {
|
|
68710
|
+
}
|
|
68711
|
+
);
|
|
68712
|
+
return () => {
|
|
68713
|
+
live = false;
|
|
68714
|
+
};
|
|
68715
|
+
}, [store, inspectionId, setTagsByItem]);
|
|
68716
|
+
const toggle = useCallback19((itemId, tag, current) => {
|
|
68717
|
+
const key = `${itemId}:${tag.id}`;
|
|
68718
|
+
if (inflight.current.has(key)) return;
|
|
68719
|
+
const attach = !current.some((t) => t.id === tag.id);
|
|
68720
|
+
const apply = (adding) => setTagsByItem((prev) => {
|
|
68721
|
+
const rest = (prev[itemId] ?? []).filter((t) => t.id !== tag.id);
|
|
68722
|
+
return { ...prev, [itemId]: adding ? [...rest, tag] : rest };
|
|
68723
|
+
});
|
|
68724
|
+
apply(attach);
|
|
68725
|
+
if (!store || !inspectionId) return;
|
|
68726
|
+
inflight.current.add(key);
|
|
68727
|
+
const write = attach ? store.add(inspectionId, itemId, tag.id) : store.remove(inspectionId, itemId, tag.id);
|
|
68728
|
+
void Promise.resolve(write).then((result) => result.ok, () => false).then((stored) => {
|
|
68729
|
+
inflight.current.delete(key);
|
|
68730
|
+
if (stored || !mounted.current) return;
|
|
68731
|
+
apply(!attach);
|
|
68732
|
+
notify(index_exports.editor_route_save_failed(), "error", { durationMs: 8e3 });
|
|
68733
|
+
});
|
|
68734
|
+
}, [store, inspectionId, setTagsByItem, notify]);
|
|
68735
|
+
return { toggle, canSave: store !== void 0 };
|
|
68736
|
+
}
|
|
68737
|
+
|
|
68485
68738
|
// src/hooks/useKeyboard.ts
|
|
68486
|
-
import { useEffect as
|
|
68739
|
+
import { useEffect as useEffect12, useRef as useRef15 } from "react";
|
|
68487
68740
|
|
|
68488
68741
|
// src/lib/shortcut-scope.ts
|
|
68489
68742
|
function singleKeyShortcutsAllowed(active, isComposing) {
|
|
@@ -68498,11 +68751,11 @@ function singleKeyShortcutsAllowed(active, isComposing) {
|
|
|
68498
68751
|
|
|
68499
68752
|
// src/hooks/useKeyboard.ts
|
|
68500
68753
|
function useKeyboard(handlers, enabled = true) {
|
|
68501
|
-
const handlersRef =
|
|
68754
|
+
const handlersRef = useRef15(handlers);
|
|
68502
68755
|
handlersRef.current = handlers;
|
|
68503
|
-
const gPrefixRef =
|
|
68504
|
-
const gPrefixTimerRef =
|
|
68505
|
-
|
|
68756
|
+
const gPrefixRef = useRef15(false);
|
|
68757
|
+
const gPrefixTimerRef = useRef15(null);
|
|
68758
|
+
useEffect12(() => {
|
|
68506
68759
|
if (!enabled) return;
|
|
68507
68760
|
function isInField() {
|
|
68508
68761
|
const tag = document.activeElement?.tagName || "";
|
|
@@ -68715,7 +68968,7 @@ function useKeyboard(handlers, enabled = true) {
|
|
|
68715
68968
|
}
|
|
68716
68969
|
|
|
68717
68970
|
// src/hooks/useCannedComments.ts
|
|
68718
|
-
import { useState as useState12, useCallback as
|
|
68971
|
+
import { useState as useState12, useCallback as useCallback20, useMemo as useMemo7, useEffect as useEffect13, useRef as useRef16 } from "react";
|
|
68719
68972
|
var BUILT_IN_LIBRARY = buildLibrary();
|
|
68720
68973
|
function buildLibrary() {
|
|
68721
68974
|
const L = [];
|
|
@@ -68786,8 +69039,8 @@ function mapRow(r) {
|
|
|
68786
69039
|
function useCannedComments(options) {
|
|
68787
69040
|
const { inspectionId, severityForRatingId } = options;
|
|
68788
69041
|
const library = useFieldDataSource().resources.commentsLibrary;
|
|
68789
|
-
const saveInFlight =
|
|
68790
|
-
const touchInFlight =
|
|
69042
|
+
const saveInFlight = useRef16(/* @__PURE__ */ new Map());
|
|
69043
|
+
const touchInFlight = useRef16(/* @__PURE__ */ new Set());
|
|
68791
69044
|
const [userSnippets, setUserSnippets] = useState12([]);
|
|
68792
69045
|
const [localSnippets, setLocalSnippets] = useState12([]);
|
|
68793
69046
|
const [sort, setSortInner] = useState12(() => {
|
|
@@ -68804,28 +69057,28 @@ function useCannedComments(options) {
|
|
|
68804
69057
|
return "auto";
|
|
68805
69058
|
}
|
|
68806
69059
|
});
|
|
68807
|
-
const setSort =
|
|
69060
|
+
const setSort = useCallback20((s) => {
|
|
68808
69061
|
setSortInner(s);
|
|
68809
69062
|
try {
|
|
68810
69063
|
localStorage.setItem("oi:library:sort", s);
|
|
68811
69064
|
} catch {
|
|
68812
69065
|
}
|
|
68813
69066
|
}, []);
|
|
68814
|
-
const setFilterMode =
|
|
69067
|
+
const setFilterMode = useCallback20((m) => {
|
|
68815
69068
|
setFilterModeInner(m);
|
|
68816
69069
|
try {
|
|
68817
69070
|
localStorage.setItem("oi:library:filter-mode", m);
|
|
68818
69071
|
} catch {
|
|
68819
69072
|
}
|
|
68820
69073
|
}, []);
|
|
68821
|
-
const loadServerRows =
|
|
69074
|
+
const loadServerRows = useCallback20(async (query) => {
|
|
68822
69075
|
try {
|
|
68823
69076
|
return await library?.list(query) ?? [];
|
|
68824
69077
|
} catch {
|
|
68825
69078
|
return [];
|
|
68826
69079
|
}
|
|
68827
69080
|
}, [library]);
|
|
68828
|
-
const fetchFiltered =
|
|
69081
|
+
const fetchFiltered = useCallback20(
|
|
68829
69082
|
async (ctx) => {
|
|
68830
69083
|
const query = { sort, filterMode };
|
|
68831
69084
|
if (ctx.search) query.search = ctx.search;
|
|
@@ -68838,7 +69091,7 @@ function useCannedComments(options) {
|
|
|
68838
69091
|
},
|
|
68839
69092
|
[sort, filterMode, loadServerRows]
|
|
68840
69093
|
);
|
|
68841
|
-
const searchLibrary =
|
|
69094
|
+
const searchLibrary = useCallback20(
|
|
68842
69095
|
async (query) => {
|
|
68843
69096
|
const q = query.trim();
|
|
68844
69097
|
if (q.length < 2) return [];
|
|
@@ -68847,20 +69100,20 @@ function useCannedComments(options) {
|
|
|
68847
69100
|
},
|
|
68848
69101
|
[loadServerRows]
|
|
68849
69102
|
);
|
|
68850
|
-
const touchSnippet =
|
|
69103
|
+
const touchSnippet = useCallback20((id) => {
|
|
68851
69104
|
if (!library || touchInFlight.current.has(id)) return;
|
|
68852
69105
|
touchInFlight.current.add(id);
|
|
68853
69106
|
void library.touch(id).catch(() => void 0).finally(() => {
|
|
68854
69107
|
touchInFlight.current.delete(id);
|
|
68855
69108
|
});
|
|
68856
69109
|
}, [library]);
|
|
68857
|
-
|
|
69110
|
+
useEffect13(() => {
|
|
68858
69111
|
(async () => {
|
|
68859
69112
|
const rows = await loadServerRows();
|
|
68860
69113
|
if (rows.length > 0) setUserSnippets(rows.map(mapRow));
|
|
68861
69114
|
})();
|
|
68862
69115
|
}, [inspectionId]);
|
|
68863
|
-
|
|
69116
|
+
useEffect13(() => {
|
|
68864
69117
|
try {
|
|
68865
69118
|
const raw = localStorage.getItem("oi:snippets");
|
|
68866
69119
|
if (raw) {
|
|
@@ -68872,14 +69125,14 @@ function useCannedComments(options) {
|
|
|
68872
69125
|
} catch {
|
|
68873
69126
|
}
|
|
68874
69127
|
}, []);
|
|
68875
|
-
const commentPool =
|
|
69128
|
+
const commentPool = useMemo7(() => {
|
|
68876
69129
|
const preset = BUILT_IN_LIBRARY;
|
|
68877
69130
|
const seenTexts = /* @__PURE__ */ new Set();
|
|
68878
69131
|
for (const s of userSnippets) seenTexts.add(s.text);
|
|
68879
69132
|
const dedupedLocal = localSnippets.filter((c) => !seenTexts.has(c.text));
|
|
68880
69133
|
return [...preset, ...userSnippets, ...dedupedLocal];
|
|
68881
69134
|
}, [userSnippets, localSnippets]);
|
|
68882
|
-
const getFilteredComments =
|
|
69135
|
+
const getFilteredComments = useCallback20(
|
|
68883
69136
|
(filter, search) => {
|
|
68884
69137
|
let filtered;
|
|
68885
69138
|
if (filter === "my-snippets") {
|
|
@@ -68901,7 +69154,7 @@ function useCannedComments(options) {
|
|
|
68901
69154
|
},
|
|
68902
69155
|
[commentPool]
|
|
68903
69156
|
);
|
|
68904
|
-
const getQuickComments =
|
|
69157
|
+
const getQuickComments = useCallback20(
|
|
68905
69158
|
(ratingId, itemLabel, sectionTitle) => {
|
|
68906
69159
|
const severity = severityForRatingId(ratingId);
|
|
68907
69160
|
const filtered = severity === "all" ? commentPool : commentPool.filter(
|
|
@@ -68935,7 +69188,7 @@ function useCannedComments(options) {
|
|
|
68935
69188
|
},
|
|
68936
69189
|
[commentPool, severityForRatingId]
|
|
68937
69190
|
);
|
|
68938
|
-
const saveSnippet =
|
|
69191
|
+
const saveSnippet = useCallback20(
|
|
68939
69192
|
(text, severity, section, title, itemLabel) => {
|
|
68940
69193
|
const flightKey = JSON.stringify([text, severity, section, title, itemLabel]);
|
|
68941
69194
|
const running = saveInFlight.current.get(flightKey);
|
|
@@ -68998,14 +69251,14 @@ function useCannedComments(options) {
|
|
|
68998
69251
|
}
|
|
68999
69252
|
|
|
69000
69253
|
// src/hooks/useEditorCapabilities.ts
|
|
69001
|
-
import { useSyncExternalStore } from "react";
|
|
69254
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
69002
69255
|
var subscribeNever = () => () => {
|
|
69003
69256
|
};
|
|
69004
69257
|
var cameraSnapshot = () => typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getUserMedia === "function";
|
|
69005
69258
|
function useEditorCapabilities() {
|
|
69006
69259
|
const { resources } = useFieldDataSource();
|
|
69007
69260
|
const { renderThemeControl } = useFieldSlots();
|
|
69008
|
-
const cameraCapture =
|
|
69261
|
+
const cameraCapture = useSyncExternalStore2(subscribeNever, cameraSnapshot, () => false);
|
|
69009
69262
|
return {
|
|
69010
69263
|
commentsLibrary: resources.commentsLibrary !== void 0,
|
|
69011
69264
|
costItems: resources.costItems !== void 0,
|
|
@@ -69039,7 +69292,7 @@ function unsavedChangesAtRisk(input) {
|
|
|
69039
69292
|
}
|
|
69040
69293
|
|
|
69041
69294
|
// src/hooks/usePhotoBatchUpload.ts
|
|
69042
|
-
import { useCallback as
|
|
69295
|
+
import { useCallback as useCallback21, useEffect as useEffect14, useRef as useRef17, useState as useState13 } from "react";
|
|
69043
69296
|
var CONCURRENCY = 4;
|
|
69044
69297
|
function newPendingId() {
|
|
69045
69298
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
@@ -69051,25 +69304,25 @@ function metaOf(batch) {
|
|
|
69051
69304
|
}
|
|
69052
69305
|
function usePhotoBatchUpload(inspectionId, doc) {
|
|
69053
69306
|
const dataSource = useFieldDataSource();
|
|
69054
|
-
const dataSourceRef =
|
|
69307
|
+
const dataSourceRef = useRef17(dataSource);
|
|
69055
69308
|
dataSourceRef.current = dataSource;
|
|
69056
|
-
const docRef =
|
|
69309
|
+
const docRef = useRef17(doc);
|
|
69057
69310
|
docRef.current = doc;
|
|
69058
|
-
const inspectionRef =
|
|
69311
|
+
const inspectionRef = useRef17(inspectionId);
|
|
69059
69312
|
inspectionRef.current = inspectionId;
|
|
69060
69313
|
const [pending, setPending] = useState13(0);
|
|
69061
69314
|
const [outcomes, setOutcomes] = useState13([]);
|
|
69062
69315
|
const [failedSinceIdle, setFailedSinceIdle] = useState13(false);
|
|
69063
|
-
const pendingRef =
|
|
69064
|
-
const tail =
|
|
69065
|
-
const mounted =
|
|
69066
|
-
|
|
69316
|
+
const pendingRef = useRef17(0);
|
|
69317
|
+
const tail = useRef17(Promise.resolve());
|
|
69318
|
+
const mounted = useRef17(true);
|
|
69319
|
+
useEffect14(() => {
|
|
69067
69320
|
mounted.current = true;
|
|
69068
69321
|
return () => {
|
|
69069
69322
|
mounted.current = false;
|
|
69070
69323
|
};
|
|
69071
69324
|
}, []);
|
|
69072
|
-
const runBatch =
|
|
69325
|
+
const runBatch = useCallback21(async (batch) => {
|
|
69073
69326
|
const uploader = dataSourceRef.current.media.uploader(inspectionRef.current, docRef.current);
|
|
69074
69327
|
const meta = metaOf(batch);
|
|
69075
69328
|
const results = new Array(batch.files.length);
|
|
@@ -69107,7 +69360,7 @@ function usePhotoBatchUpload(inspectionId, doc) {
|
|
|
69107
69360
|
defectKind: batch.target?.kind ?? "canned"
|
|
69108
69361
|
};
|
|
69109
69362
|
}, []);
|
|
69110
|
-
const submit =
|
|
69363
|
+
const submit = useCallback21(
|
|
69111
69364
|
(batch) => {
|
|
69112
69365
|
if (pendingRef.current === 0) setFailedSinceIdle(false);
|
|
69113
69366
|
pendingRef.current += 1;
|
|
@@ -69136,41 +69389,41 @@ function usePhotoBatchUpload(inspectionId, doc) {
|
|
|
69136
69389
|
},
|
|
69137
69390
|
[runBatch]
|
|
69138
69391
|
);
|
|
69139
|
-
const consume =
|
|
69392
|
+
const consume = useCallback21((count) => {
|
|
69140
69393
|
if (count > 0) setOutcomes((prev) => prev.slice(count));
|
|
69141
69394
|
}, []);
|
|
69142
69395
|
return { busy: pending > 0, outcomes, failedSinceIdle, consume, submit };
|
|
69143
69396
|
}
|
|
69144
69397
|
|
|
69145
69398
|
// src/hooks/useReportCoverWrites.ts
|
|
69146
|
-
import { useCallback as
|
|
69399
|
+
import { useCallback as useCallback22, useRef as useRef18 } from "react";
|
|
69147
69400
|
var FAILED_MS = 8e3;
|
|
69148
69401
|
function useReportCoverWrites(inspectionId) {
|
|
69149
69402
|
const dataSource = useFieldDataSource();
|
|
69150
|
-
const dataSourceRef =
|
|
69403
|
+
const dataSourceRef = useRef18(dataSource);
|
|
69151
69404
|
dataSourceRef.current = dataSource;
|
|
69152
69405
|
const { submit: submitCover } = useLatestWinsCommand(inspectionId);
|
|
69153
69406
|
const { submit: submitCrop } = useLatestWinsCommand(inspectionId);
|
|
69154
69407
|
const { submit: submitAnnotate } = useLatestWinsCommand(inspectionId);
|
|
69155
|
-
const report =
|
|
69408
|
+
const report = useCallback22((res) => {
|
|
69156
69409
|
if (isIgnored(res)) return;
|
|
69157
69410
|
if (!res.ok) {
|
|
69158
69411
|
dataSourceRef.current.notify(index_exports.editor_route_save_failed(), "error", { durationMs: FAILED_MS });
|
|
69159
69412
|
}
|
|
69160
69413
|
}, []);
|
|
69161
|
-
const setCover =
|
|
69414
|
+
const setCover = useCallback22(
|
|
69162
69415
|
(coverPhotoId) => {
|
|
69163
69416
|
void submitCover({ type: "set-cover", coverPhotoId }).then(report);
|
|
69164
69417
|
},
|
|
69165
69418
|
[submitCover, report]
|
|
69166
69419
|
);
|
|
69167
|
-
const cropCover =
|
|
69420
|
+
const cropCover = useCallback22(
|
|
69168
69421
|
(input) => {
|
|
69169
69422
|
void submitCrop({ type: "crop-cover", sourceKey: input.sourceKey, crop: input.crop, image: input.image }).then(report);
|
|
69170
69423
|
},
|
|
69171
69424
|
[submitCrop, report]
|
|
69172
69425
|
);
|
|
69173
|
-
const annotate =
|
|
69426
|
+
const annotate = useCallback22(
|
|
69174
69427
|
(input) => {
|
|
69175
69428
|
void submitAnnotate({ type: "annotate", ...input }).then(report);
|
|
69176
69429
|
},
|
|
@@ -69180,7 +69433,7 @@ function useReportCoverWrites(inspectionId) {
|
|
|
69180
69433
|
}
|
|
69181
69434
|
|
|
69182
69435
|
// src/hooks/usePresence.ts
|
|
69183
|
-
import { useState as useState14, useEffect as
|
|
69436
|
+
import { useState as useState14, useEffect as useEffect15, useCallback as useCallback23, useRef as useRef19 } from "react";
|
|
69184
69437
|
var HEARTBEAT_MS = 3e4;
|
|
69185
69438
|
var MAX_BACKOFF = 3e4;
|
|
69186
69439
|
function usePresence(options) {
|
|
@@ -69189,17 +69442,17 @@ function usePresence(options) {
|
|
|
69189
69442
|
const [roster, setRoster] = useState14([]);
|
|
69190
69443
|
const [connected, setConnected] = useState14(false);
|
|
69191
69444
|
const [status, setStatus] = useState14("connecting");
|
|
69192
|
-
const everConnectedRef =
|
|
69193
|
-
const wsRef =
|
|
69194
|
-
const heartbeatRef =
|
|
69195
|
-
const backoffRef =
|
|
69196
|
-
const closedRef =
|
|
69197
|
-
const send =
|
|
69445
|
+
const everConnectedRef = useRef19(false);
|
|
69446
|
+
const wsRef = useRef19(null);
|
|
69447
|
+
const heartbeatRef = useRef19(null);
|
|
69448
|
+
const backoffRef = useRef19(400);
|
|
69449
|
+
const closedRef = useRef19(false);
|
|
69450
|
+
const send = useCallback23((msg) => {
|
|
69198
69451
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
69199
69452
|
wsRef.current.send(JSON.stringify(msg));
|
|
69200
69453
|
}
|
|
69201
69454
|
}, []);
|
|
69202
|
-
const connect =
|
|
69455
|
+
const connect = useCallback23(() => {
|
|
69203
69456
|
if (closedRef.current || !enabled) return;
|
|
69204
69457
|
if (!inspectionId) return;
|
|
69205
69458
|
const wsUrl = dataSource.urls.presenceSocket(inspectionId);
|
|
@@ -69265,13 +69518,13 @@ function usePresence(options) {
|
|
|
69265
69518
|
}
|
|
69266
69519
|
}
|
|
69267
69520
|
}, [dataSource, inspectionId, userName, photoUrl, enabled, send]);
|
|
69268
|
-
const setFocus =
|
|
69521
|
+
const setFocus = useCallback23(
|
|
69269
69522
|
(itemId) => {
|
|
69270
69523
|
send({ type: "focus", itemId });
|
|
69271
69524
|
},
|
|
69272
69525
|
[send]
|
|
69273
69526
|
);
|
|
69274
|
-
const close =
|
|
69527
|
+
const close = useCallback23(() => {
|
|
69275
69528
|
closedRef.current = true;
|
|
69276
69529
|
try {
|
|
69277
69530
|
send({ type: "bye" });
|
|
@@ -69285,7 +69538,7 @@ function usePresence(options) {
|
|
|
69285
69538
|
heartbeatRef.current = null;
|
|
69286
69539
|
setConnected(false);
|
|
69287
69540
|
}, [send]);
|
|
69288
|
-
|
|
69541
|
+
useEffect15(() => {
|
|
69289
69542
|
if (!enabled) return;
|
|
69290
69543
|
closedRef.current = false;
|
|
69291
69544
|
connect();
|
|
@@ -69303,13 +69556,13 @@ function usePresence(options) {
|
|
|
69303
69556
|
}
|
|
69304
69557
|
|
|
69305
69558
|
// src/collab/use-results-doc.ts
|
|
69306
|
-
import { useState as useState15, useEffect as
|
|
69559
|
+
import { useState as useState15, useEffect as useEffect16, useRef as useRef20 } from "react";
|
|
69307
69560
|
function useResultsDoc(inspectionId, onSynced) {
|
|
69308
69561
|
const { collab } = useFieldDataSource();
|
|
69309
69562
|
const [handle, setHandle] = useState15(null);
|
|
69310
|
-
const onSyncedRef =
|
|
69563
|
+
const onSyncedRef = useRef20(onSynced);
|
|
69311
69564
|
onSyncedRef.current = onSynced;
|
|
69312
|
-
|
|
69565
|
+
useEffect16(() => {
|
|
69313
69566
|
if (!inspectionId) {
|
|
69314
69567
|
setHandle(null);
|
|
69315
69568
|
return;
|
|
@@ -69317,10 +69570,10 @@ function useResultsDoc(inspectionId, onSynced) {
|
|
|
69317
69570
|
let persisted = false;
|
|
69318
69571
|
let live = null;
|
|
69319
69572
|
let closed = false;
|
|
69320
|
-
const
|
|
69573
|
+
const snapshot2 = () => live === null ? null : { doc: live.doc, persistenceSynced: persisted, synced: live.synced() };
|
|
69321
69574
|
const publish = () => {
|
|
69322
69575
|
if (closed) return;
|
|
69323
|
-
const next =
|
|
69576
|
+
const next = snapshot2();
|
|
69324
69577
|
if (next !== null) setHandle(next);
|
|
69325
69578
|
};
|
|
69326
69579
|
live = collab.connect(inspectionId, {
|
|
@@ -69346,7 +69599,7 @@ function useResultsDoc(inspectionId, onSynced) {
|
|
|
69346
69599
|
}
|
|
69347
69600
|
|
|
69348
69601
|
// src/hooks/useMediaDrain.ts
|
|
69349
|
-
import { useCallback as
|
|
69602
|
+
import { useCallback as useCallback24, useEffect as useEffect17, useRef as useRef21 } from "react";
|
|
69350
69603
|
function asDrainUploader(uploader) {
|
|
69351
69604
|
return {
|
|
69352
69605
|
async upload(rec) {
|
|
@@ -69359,11 +69612,11 @@ function asDrainUploader(uploader) {
|
|
|
69359
69612
|
}
|
|
69360
69613
|
function useMediaDrain(inspectionId, doc, revokePendingUrl) {
|
|
69361
69614
|
const dataSource = useFieldDataSource();
|
|
69362
|
-
const docRef =
|
|
69615
|
+
const docRef = useRef21(doc);
|
|
69363
69616
|
docRef.current = doc;
|
|
69364
|
-
const revokeRef =
|
|
69617
|
+
const revokeRef = useRef21(revokePendingUrl);
|
|
69365
69618
|
revokeRef.current = revokePendingUrl;
|
|
69366
|
-
const drain =
|
|
69619
|
+
const drain = useCallback24(() => {
|
|
69367
69620
|
const liveDoc = docRef.current;
|
|
69368
69621
|
if (!liveDoc) return;
|
|
69369
69622
|
void drainMediaQueue({
|
|
@@ -69386,7 +69639,7 @@ function useMediaDrain(inspectionId, doc, revokePendingUrl) {
|
|
|
69386
69639
|
}
|
|
69387
69640
|
});
|
|
69388
69641
|
}, [dataSource, inspectionId]);
|
|
69389
|
-
|
|
69642
|
+
useEffect17(
|
|
69390
69643
|
() => dataSource.onOnlineChange((online) => {
|
|
69391
69644
|
if (online) drain();
|
|
69392
69645
|
}),
|
|
@@ -69421,7 +69674,7 @@ async function addOfflinePhotos(store, doc, target, files) {
|
|
|
69421
69674
|
}
|
|
69422
69675
|
|
|
69423
69676
|
// src/hooks/useResultsProjection.ts
|
|
69424
|
-
import { useEffect as
|
|
69677
|
+
import { useEffect as useEffect18, useRef as useRef22 } from "react";
|
|
69425
69678
|
|
|
69426
69679
|
// src/collab/results-merge.ts
|
|
69427
69680
|
import * as Y3 from "yjs";
|
|
@@ -69460,27 +69713,27 @@ function mergeUnsyncedResults(prev, doc) {
|
|
|
69460
69713
|
|
|
69461
69714
|
// src/hooks/useResultsProjection.ts
|
|
69462
69715
|
function useResultsProjection(collab, setResults) {
|
|
69463
|
-
const synced =
|
|
69716
|
+
const synced = useRef22(false);
|
|
69464
69717
|
synced.current = collab?.synced === true;
|
|
69465
69718
|
const doc = collab?.doc;
|
|
69466
|
-
|
|
69719
|
+
useEffect18(() => {
|
|
69467
69720
|
if (!doc) return;
|
|
69468
69721
|
return bindResultMap(doc, (next) => setResults((prev) => synced.current ? next : mergeUnsyncedResults(prev, doc)));
|
|
69469
69722
|
}, [doc, setResults]);
|
|
69470
69723
|
}
|
|
69471
69724
|
|
|
69472
69725
|
// src/hooks/useSpeedRating.ts
|
|
69473
|
-
import { useCallback as
|
|
69726
|
+
import { useCallback as useCallback25, useEffect as useEffect19, useRef as useRef23, useState as useState16 } from "react";
|
|
69474
69727
|
var SPEED_DONE_LINGER_MS = 3500;
|
|
69475
69728
|
function useSpeedRating({ state, commitRating, doc, activeUnitId, onUndoUnavailable }) {
|
|
69476
|
-
const queueRef =
|
|
69729
|
+
const queueRef = useRef23(state.speedQueue);
|
|
69477
69730
|
queueRef.current = state.speedQueue;
|
|
69478
|
-
const unitRef =
|
|
69731
|
+
const unitRef = useRef23(activeUnitId);
|
|
69479
69732
|
unitRef.current = activeUnitId;
|
|
69480
|
-
const ratedUnit =
|
|
69481
|
-
const lastRated =
|
|
69733
|
+
const ratedUnit = useRef23(/* @__PURE__ */ new Map());
|
|
69734
|
+
const lastRated = useRef23(null);
|
|
69482
69735
|
const [pendingUndo, setPendingUndo] = useState16(null);
|
|
69483
|
-
const speedRate =
|
|
69736
|
+
const speedRate = useCallback25(
|
|
69484
69737
|
(levelIdx) => {
|
|
69485
69738
|
if (!state.speedMode) return;
|
|
69486
69739
|
const qi = state.speedQueue[state.speedCurrent];
|
|
@@ -69498,7 +69751,7 @@ function useSpeedRating({ state, commitRating, doc, activeUnitId, onUndoUnavaila
|
|
|
69498
69751
|
},
|
|
69499
69752
|
[state, commitRating]
|
|
69500
69753
|
);
|
|
69501
|
-
const undoSpeedRating =
|
|
69754
|
+
const undoSpeedRating = useCallback25(
|
|
69502
69755
|
(itemId, previous) => {
|
|
69503
69756
|
const sid = state.sectionIdForItem(itemId);
|
|
69504
69757
|
if (!sid) return;
|
|
@@ -69525,19 +69778,19 @@ function useSpeedRating({ state, commitRating, doc, activeUnitId, onUndoUnavaila
|
|
|
69525
69778
|
);
|
|
69526
69779
|
const done = state.speedMode && state.speedQueue.length === 0;
|
|
69527
69780
|
const setSpeedMode = state.setSpeedMode;
|
|
69528
|
-
|
|
69781
|
+
useEffect19(() => {
|
|
69529
69782
|
if (!done) return;
|
|
69530
69783
|
const t = setTimeout(() => setSpeedMode(false), SPEED_DONE_LINGER_MS);
|
|
69531
69784
|
return () => clearTimeout(t);
|
|
69532
69785
|
}, [done, setSpeedMode]);
|
|
69533
|
-
|
|
69786
|
+
useEffect19(() => {
|
|
69534
69787
|
if (!state.speedMode) setPendingUndo(null);
|
|
69535
69788
|
}, [state.speedMode]);
|
|
69536
69789
|
return { speedRate, undoSpeedRating, finishedItem: done ? lastRated.current : null, pendingUndo, setPendingUndo };
|
|
69537
69790
|
}
|
|
69538
69791
|
|
|
69539
69792
|
// src/components/editor-shared/SectionRail.tsx
|
|
69540
|
-
import { useRef as
|
|
69793
|
+
import { useRef as useRef26, useState as useState18 } from "react";
|
|
69541
69794
|
|
|
69542
69795
|
// src/components/editor/SectionDonut.tsx
|
|
69543
69796
|
import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
@@ -69659,15 +69912,15 @@ function sectionIconFor(nameOrId) {
|
|
|
69659
69912
|
}
|
|
69660
69913
|
|
|
69661
69914
|
// src/components/editor-shared/useSortableReorder.ts
|
|
69662
|
-
import { useEffect as
|
|
69915
|
+
import { useEffect as useEffect20, useRef as useRef24 } from "react";
|
|
69663
69916
|
import Sortable from "sortablejs";
|
|
69664
69917
|
function useSortableReorder({ ids, onReorder, disabled = false }) {
|
|
69665
|
-
const containerRef =
|
|
69666
|
-
const idsRef =
|
|
69918
|
+
const containerRef = useRef24(null);
|
|
69919
|
+
const idsRef = useRef24(ids);
|
|
69667
69920
|
idsRef.current = ids;
|
|
69668
|
-
const onReorderRef =
|
|
69921
|
+
const onReorderRef = useRef24(onReorder);
|
|
69669
69922
|
onReorderRef.current = onReorder;
|
|
69670
|
-
|
|
69923
|
+
useEffect20(() => {
|
|
69671
69924
|
const el = containerRef.current;
|
|
69672
69925
|
if (!el || disabled) return;
|
|
69673
69926
|
const s = Sortable.create(el, {
|
|
@@ -69695,13 +69948,13 @@ function useSortableReorder({ ids, onReorder, disabled = false }) {
|
|
|
69695
69948
|
}
|
|
69696
69949
|
|
|
69697
69950
|
// src/components/editor-shared/InlineRename.tsx
|
|
69698
|
-
import { useEffect as
|
|
69951
|
+
import { useEffect as useEffect21, useRef as useRef25, useState as useState17 } from "react";
|
|
69699
69952
|
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
69700
69953
|
function InlineRename({ value, onCommit, onCancel, className, ariaLabel }) {
|
|
69701
69954
|
const [draft, setDraft] = useState17(value);
|
|
69702
|
-
const ref =
|
|
69703
|
-
const doneRef =
|
|
69704
|
-
|
|
69955
|
+
const ref = useRef25(null);
|
|
69956
|
+
const doneRef = useRef25(false);
|
|
69957
|
+
useEffect21(() => {
|
|
69705
69958
|
ref.current?.focus();
|
|
69706
69959
|
ref.current?.select();
|
|
69707
69960
|
}, []);
|
|
@@ -69794,7 +70047,7 @@ function SectionRail({
|
|
|
69794
70047
|
}) {
|
|
69795
70048
|
const [openMenuId, setOpenMenuId] = useState18(null);
|
|
69796
70049
|
const [editingId, setEditingId] = useState18(null);
|
|
69797
|
-
const menuAnchorRef =
|
|
70050
|
+
const menuAnchorRef = useRef26(null);
|
|
69798
70051
|
const openSectionMenu = (sectionId, el) => {
|
|
69799
70052
|
if (openMenuId === sectionId) {
|
|
69800
70053
|
setOpenMenuId(null);
|
|
@@ -70003,13 +70256,88 @@ function SectionRail({
|
|
|
70003
70256
|
// src/components/editor/EditorHeader.tsx
|
|
70004
70257
|
import { useState as useState22 } from "react";
|
|
70005
70258
|
|
|
70259
|
+
// src/lib/readable-text.ts
|
|
70260
|
+
var DARK_INK = "#0f172a";
|
|
70261
|
+
var WHITE = "#ffffff";
|
|
70262
|
+
function isFallbackRatingColor(color) {
|
|
70263
|
+
return color === FALLBACK_RATING_COLOR;
|
|
70264
|
+
}
|
|
70265
|
+
function parseHex(v) {
|
|
70266
|
+
const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(v)?.[1];
|
|
70267
|
+
if (!hex) return null;
|
|
70268
|
+
const full = hex.length === 3 ? [...hex].map((c) => c + c).join("") : hex;
|
|
70269
|
+
return [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16));
|
|
70270
|
+
}
|
|
70271
|
+
function parseRgb(v) {
|
|
70272
|
+
const m = /^rgba?\(\s*(\d+(?:\.\d+)?)[\s,]+(\d+(?:\.\d+)?)[\s,]+(\d+(?:\.\d+)?)(?:[\s,/]+[\d.]+%?)?\s*\)$/i.exec(v);
|
|
70273
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
70274
|
+
}
|
|
70275
|
+
var HEX = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
70276
|
+
var COLOR_FN = /^(?:rgba?|hsla?)\(\s*[\d.]+(?:deg|%)?(?:\s*[,/]\s*[\d.]+(?:deg|%)?|\s+[\d.]+(?:deg|%)?)*\s*\)$/i;
|
|
70277
|
+
var TOKEN = /^var\(\s*--ih-[\w-]+\s*(?:,\s*([^;{}"'()]+(?:\([^;{}"'()]*\))?))?\s*\)$/;
|
|
70278
|
+
function safeCssColor(color) {
|
|
70279
|
+
if (typeof color !== "string") return null;
|
|
70280
|
+
const v = color.trim();
|
|
70281
|
+
if (v === "" || v.length > 120) return null;
|
|
70282
|
+
if (HEX.test(v) || COLOR_FN.test(v) || namedHex(v) !== null) return v;
|
|
70283
|
+
const palette = paletteHex(v);
|
|
70284
|
+
if (palette !== null) return palette;
|
|
70285
|
+
const token = TOKEN.exec(v);
|
|
70286
|
+
if (token) return token[1] === void 0 || safeCssColor(token[1]) !== null ? v : null;
|
|
70287
|
+
return null;
|
|
70288
|
+
}
|
|
70289
|
+
var NAMED = {
|
|
70290
|
+
red: "#ff0000",
|
|
70291
|
+
orange: "#ffa500",
|
|
70292
|
+
yellow: "#ffff00",
|
|
70293
|
+
blue: "#0000ff",
|
|
70294
|
+
green: "#008000",
|
|
70295
|
+
teal: "#008080",
|
|
70296
|
+
purple: "#800080",
|
|
70297
|
+
indigo: "#4b0082",
|
|
70298
|
+
pink: "#ffc0cb",
|
|
70299
|
+
brown: "#a52a2a",
|
|
70300
|
+
gray: "#808080",
|
|
70301
|
+
grey: "#808080",
|
|
70302
|
+
white: "#ffffff",
|
|
70303
|
+
black: "#000000"
|
|
70304
|
+
};
|
|
70305
|
+
function namedHex(name) {
|
|
70306
|
+
const key = name.toLowerCase();
|
|
70307
|
+
return Object.hasOwn(NAMED, key) ? NAMED[key] : null;
|
|
70308
|
+
}
|
|
70309
|
+
var PALETTE = { amber: "#f59e0b", slate: "#64748b", rose: "#f43f5e", emerald: "#10b981" };
|
|
70310
|
+
function paletteHex(name) {
|
|
70311
|
+
const key = name.toLowerCase();
|
|
70312
|
+
return Object.hasOwn(PALETTE, key) ? PALETTE[key] : null;
|
|
70313
|
+
}
|
|
70314
|
+
function luminance([r, g, b]) {
|
|
70315
|
+
const lin = (c) => {
|
|
70316
|
+
const s = c / 255;
|
|
70317
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
70318
|
+
};
|
|
70319
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
70320
|
+
}
|
|
70321
|
+
var WHITE_FLOOR = 3;
|
|
70322
|
+
function readableTextOn(background) {
|
|
70323
|
+
if (!background) return null;
|
|
70324
|
+
const v = background.trim();
|
|
70325
|
+
const rgb = parseHex(v) ?? parseRgb(v) ?? parseHex(namedHex(v) ?? paletteHex(v) ?? "");
|
|
70326
|
+
if (!rgb) return null;
|
|
70327
|
+
const bg = luminance(rgb);
|
|
70328
|
+
const onWhite = 1.05 / (bg + 0.05);
|
|
70329
|
+
if (onWhite >= WHITE_FLOOR) return WHITE;
|
|
70330
|
+
const onInk = (bg + 0.05) / (luminance(parseHex(DARK_INK)) + 0.05);
|
|
70331
|
+
return onWhite >= onInk ? WHITE : DARK_INK;
|
|
70332
|
+
}
|
|
70333
|
+
|
|
70006
70334
|
// src/components/editor/ProgressStripText.tsx
|
|
70007
70335
|
import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
70008
70336
|
var Dot = ({ color }) => /* @__PURE__ */ jsx33(
|
|
70009
70337
|
"span",
|
|
70010
70338
|
{
|
|
70011
70339
|
className: "inline-block w-1.5 h-1.5 rounded-full mr-1 align-middle",
|
|
70012
|
-
style: { backgroundColor: color }
|
|
70340
|
+
style: { backgroundColor: safeCssColor(color) ?? void 0 }
|
|
70013
70341
|
}
|
|
70014
70342
|
);
|
|
70015
70343
|
function ProgressStripText({ rated, total, defects, monitor, etaMinutes }) {
|
|
@@ -70032,7 +70360,7 @@ function ProgressStripText({ rated, total, defects, monitor, etaMinutes }) {
|
|
|
70032
70360
|
}
|
|
70033
70361
|
|
|
70034
70362
|
// src/components/editor/TemplateMenu.tsx
|
|
70035
|
-
import { useRef as
|
|
70363
|
+
import { useRef as useRef27, useState as useState19 } from "react";
|
|
70036
70364
|
import { Fragment as Fragment2, jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
70037
70365
|
function TemplateMenu({
|
|
70038
70366
|
onChangeTemplate,
|
|
@@ -70041,7 +70369,7 @@ function TemplateMenu({
|
|
|
70041
70369
|
canUpdateSource
|
|
70042
70370
|
}) {
|
|
70043
70371
|
const [open, setOpen] = useState19(false);
|
|
70044
|
-
const anchorRef =
|
|
70372
|
+
const anchorRef = useRef27(null);
|
|
70045
70373
|
const run = (fn) => {
|
|
70046
70374
|
setOpen(false);
|
|
70047
70375
|
fn();
|
|
@@ -70099,7 +70427,7 @@ function TemplateMenu({
|
|
|
70099
70427
|
}
|
|
70100
70428
|
|
|
70101
70429
|
// src/components/editor/PreviewMenu.tsx
|
|
70102
|
-
import { useRef as
|
|
70430
|
+
import { useRef as useRef28, useState as useState20 } from "react";
|
|
70103
70431
|
import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
70104
70432
|
function PreviewMenu({
|
|
70105
70433
|
onPreviewReport,
|
|
@@ -70109,7 +70437,7 @@ function PreviewMenu({
|
|
|
70109
70437
|
pdfLabel
|
|
70110
70438
|
}) {
|
|
70111
70439
|
const [open, setOpen] = useState20(false);
|
|
70112
|
-
const anchorRef =
|
|
70440
|
+
const anchorRef = useRef28(null);
|
|
70113
70441
|
const run = (fn) => {
|
|
70114
70442
|
setOpen(false);
|
|
70115
70443
|
fn();
|
|
@@ -70246,10 +70574,10 @@ function runWithPending(handler, setPending) {
|
|
|
70246
70574
|
}
|
|
70247
70575
|
|
|
70248
70576
|
// src/components/editor/HeaderOverflowMenu.tsx
|
|
70249
|
-
import { useRef as
|
|
70577
|
+
import { useRef as useRef29, useState as useState21 } from "react";
|
|
70250
70578
|
|
|
70251
70579
|
// src/read-only.tsx
|
|
70252
|
-
import { createContext as createContext2, useContext as useContext2, useMemo as
|
|
70580
|
+
import { createContext as createContext2, useContext as useContext2, useMemo as useMemo8 } from "react";
|
|
70253
70581
|
|
|
70254
70582
|
// src/read-only-view.ts
|
|
70255
70583
|
var refused = () => ({ ok: false, error: index_exports.editor_read_only() });
|
|
@@ -70304,7 +70632,7 @@ function useReadOnly() {
|
|
|
70304
70632
|
function ReadOnlyScope({ readOnly, children }) {
|
|
70305
70633
|
const dataSource = useFieldDataSource();
|
|
70306
70634
|
const slots = useFieldSlots();
|
|
70307
|
-
const view =
|
|
70635
|
+
const view = useMemo8(() => readOnly ? readOnlyView(dataSource) : dataSource, [readOnly, dataSource]);
|
|
70308
70636
|
return /* @__PURE__ */ jsx37(FieldDataSourceProvider, { dataSource: view, slots, children: /* @__PURE__ */ jsx37(ReadOnlyContext.Provider, { value: readOnly, children }) });
|
|
70309
70637
|
}
|
|
70310
70638
|
|
|
@@ -70318,7 +70646,7 @@ function HeaderOverflowMenu({
|
|
|
70318
70646
|
themeControl
|
|
70319
70647
|
}) {
|
|
70320
70648
|
const [open, setOpen] = useState21(false);
|
|
70321
|
-
const anchorRef =
|
|
70649
|
+
const anchorRef = useRef29(null);
|
|
70322
70650
|
const readOnly = useReadOnly();
|
|
70323
70651
|
const run = (fn) => {
|
|
70324
70652
|
setOpen(false);
|
|
@@ -70666,7 +70994,7 @@ function FullscreenToggle({ active, onToggle }) {
|
|
|
70666
70994
|
}
|
|
70667
70995
|
|
|
70668
70996
|
// src/components/editor-shared/ItemList.tsx
|
|
70669
|
-
import { useState as useState24, useRef as
|
|
70997
|
+
import { useState as useState24, useRef as useRef30 } from "react";
|
|
70670
70998
|
|
|
70671
70999
|
// src/shared/template-hierarchy.ts
|
|
70672
71000
|
var MAX_ITEM_DEPTH = 3;
|
|
@@ -70844,6 +71172,19 @@ function ItemRowIndent({ depth, outline }) {
|
|
|
70844
71172
|
] });
|
|
70845
71173
|
}
|
|
70846
71174
|
|
|
71175
|
+
// src/components/editor-shared/rating-dot.ts
|
|
71176
|
+
function ratingDotClass(rating) {
|
|
71177
|
+
if (rating === "Satisfactory" || rating === "SAT") return "bg-ih-ok";
|
|
71178
|
+
if (rating === "Monitor" || rating === "MON") return "bg-ih-watch";
|
|
71179
|
+
if (rating === "Defect" || rating === "DEF") return "bg-ih-bad";
|
|
71180
|
+
return "bg-ih-border-strong";
|
|
71181
|
+
}
|
|
71182
|
+
function ratingDot(rating, getRatingColor) {
|
|
71183
|
+
const color = safeCssColor(getRatingColor?.(rating));
|
|
71184
|
+
if (color && !isFallbackRatingColor(color)) return { className: "", style: { background: color } };
|
|
71185
|
+
return { className: ratingDotClass(rating) };
|
|
71186
|
+
}
|
|
71187
|
+
|
|
70847
71188
|
// src/components/editor-shared/ItemSubtreeDeleteModal.tsx
|
|
70848
71189
|
import { Fragment as Fragment7, jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
70849
71190
|
function ItemSubtreeDeleteModal({ pending, onCancel, onConfirm }) {
|
|
@@ -70888,12 +71229,6 @@ function slotHeadings(groups, items) {
|
|
|
70888
71229
|
return { heading, closes };
|
|
70889
71230
|
}
|
|
70890
71231
|
var PANE_SELECTED = "bg-ih-primary-tint border-l-[3px] border-ih-primary font-bold text-ih-primary-text";
|
|
70891
|
-
function ratingDotClass(rating) {
|
|
70892
|
-
if (rating === "Satisfactory" || rating === "SAT") return "bg-ih-ok";
|
|
70893
|
-
if (rating === "Monitor" || rating === "MON") return "bg-ih-watch";
|
|
70894
|
-
if (rating === "Defect" || rating === "DEF") return "bg-ih-bad";
|
|
70895
|
-
return "bg-ih-border-strong";
|
|
70896
|
-
}
|
|
70897
71232
|
function ItemList({
|
|
70898
71233
|
mode,
|
|
70899
71234
|
items,
|
|
@@ -70916,7 +71251,9 @@ function ItemList({
|
|
|
70916
71251
|
activeUnitId = null,
|
|
70917
71252
|
groups,
|
|
70918
71253
|
onAddGroupInstance,
|
|
70919
|
-
pane = false
|
|
71254
|
+
pane = false,
|
|
71255
|
+
fullWidth = false,
|
|
71256
|
+
getRatingColor
|
|
70920
71257
|
}) {
|
|
70921
71258
|
const { heading: slotHeading, closes: groupClosedBy } = slotHeadings(groups, items);
|
|
70922
71259
|
const grouped = Boolean(groups?.length);
|
|
@@ -70931,10 +71268,10 @@ function ItemList({
|
|
|
70931
71268
|
}
|
|
70932
71269
|
setPendingDelete({ id, label, count });
|
|
70933
71270
|
};
|
|
70934
|
-
const lastClickedRef =
|
|
71271
|
+
const lastClickedRef = useRef30(null);
|
|
70935
71272
|
const [editingId, setEditingId] = useState24(null);
|
|
70936
71273
|
const { menuItemId, openItemMenu, closeItemMenu } = useItemRowMenu();
|
|
70937
|
-
const menuAnchorRef =
|
|
71274
|
+
const menuAnchorRef = useRef30(null);
|
|
70938
71275
|
const structuralEditing = Boolean(onDuplicateItem || onDeleteItem || onMoveItem || onRenameItem);
|
|
70939
71276
|
const resultsMap = results ?? {};
|
|
70940
71277
|
const scopedResult = (itemId) => resultsMap[findingKey(activeUnitId, sectionId, itemId)] || (activeUnitId == null ? resultsMap[itemId] : void 0) || {};
|
|
@@ -70944,7 +71281,7 @@ function ItemList({
|
|
|
70944
71281
|
}),
|
|
70945
71282
|
disabled: !onReorderItem || Boolean(batchMode) || editingId !== null
|
|
70946
71283
|
});
|
|
70947
|
-
return /* @__PURE__ */ jsxs34("div", { "data-shortcut-scope": true, className: pane ? "w-full min-w-0 flex-1 min-h-0 overflow-y-auto overscroll-contain flex flex-col" : "w-[280px] flex-shrink-0 border-r border-ih-border overflow-y-auto flex flex-col", children: [
|
|
71284
|
+
return /* @__PURE__ */ jsxs34("div", { "data-shortcut-scope": true, className: pane ? "w-full min-w-0 flex-1 min-h-0 overflow-y-auto overscroll-contain flex flex-col" : fullWidth ? "w-full min-w-0 overflow-y-auto flex flex-col" : "w-[280px] flex-shrink-0 border-r border-ih-border overflow-y-auto flex flex-col", children: [
|
|
70948
71285
|
/* @__PURE__ */ jsx43("div", { ref: containerRef, className: "flex-1 overflow-y-auto p-2 space-y-0.5", children: items.map((item) => {
|
|
70949
71286
|
const result = scopedResult(item.id);
|
|
70950
71287
|
const fullIdx = items.findIndex((i) => i.id === item.id);
|
|
@@ -71021,12 +71358,10 @@ function ItemList({
|
|
|
71021
71358
|
),
|
|
71022
71359
|
/* @__PURE__ */ jsx43(ItemRowIndent, { depth: depths.get(item.id) ?? 0, outline: outlines.get(item.id) ?? "" }),
|
|
71023
71360
|
/* @__PURE__ */ jsx43("span", { className: "flex-1 truncate", children: item.label }),
|
|
71024
|
-
mode === "fill" && Boolean(result.rating) &&
|
|
71025
|
-
|
|
71026
|
-
{
|
|
71027
|
-
|
|
71028
|
-
}
|
|
71029
|
-
),
|
|
71361
|
+
mode === "fill" && Boolean(result.rating) && (() => {
|
|
71362
|
+
const dot = ratingDot(result.rating, getRatingColor);
|
|
71363
|
+
return /* @__PURE__ */ jsx43("span", { className: `w-2 h-2 rounded-full flex-shrink-0 ${dot.className}`, style: dot.style });
|
|
71364
|
+
})(),
|
|
71030
71365
|
mode === "author" && /* @__PURE__ */ jsx43("span", { className: "text-[10px] font-mono px-1.5 py-0.5 rounded bg-ih-bg-muted text-ih-fg-2 flex-shrink-0", children: item.type })
|
|
71031
71366
|
]
|
|
71032
71367
|
}
|
|
@@ -71126,7 +71461,7 @@ function ItemList({
|
|
|
71126
71461
|
}
|
|
71127
71462
|
|
|
71128
71463
|
// src/hooks/useStatutoryGroups.ts
|
|
71129
|
-
import { useMemo as
|
|
71464
|
+
import { useMemo as useMemo9 } from "react";
|
|
71130
71465
|
|
|
71131
71466
|
// src/shared/statutory-groups.ts
|
|
71132
71467
|
function parseGroupKey(key) {
|
|
@@ -71168,8 +71503,8 @@ function formBoundItemIds(declaration) {
|
|
|
71168
71503
|
}
|
|
71169
71504
|
return ids;
|
|
71170
71505
|
}
|
|
71171
|
-
function declaresStatutoryForm(
|
|
71172
|
-
return Boolean(
|
|
71506
|
+
function declaresStatutoryForm(snapshot2) {
|
|
71507
|
+
return Boolean(snapshot2?.statutoryForm);
|
|
71173
71508
|
}
|
|
71174
71509
|
|
|
71175
71510
|
// src/shared/form-completeness.ts
|
|
@@ -71196,17 +71531,17 @@ function formCompleteness(boundItemIds, results) {
|
|
|
71196
71531
|
|
|
71197
71532
|
// src/hooks/useStatutoryGroups.ts
|
|
71198
71533
|
function useStatutoryGroups(templateSnapshot) {
|
|
71199
|
-
return
|
|
71534
|
+
return useMemo9(() => {
|
|
71200
71535
|
const declaration = templateSnapshot?.statutoryForm;
|
|
71201
71536
|
const groups = deriveEditorGroups(declaration);
|
|
71202
71537
|
return groups.length > 0 ? groups : void 0;
|
|
71203
71538
|
}, [templateSnapshot]);
|
|
71204
71539
|
}
|
|
71205
71540
|
function useStructuralEditingAllowed(templateSnapshot) {
|
|
71206
|
-
return
|
|
71541
|
+
return useMemo9(() => !declaresStatutoryForm(templateSnapshot), [templateSnapshot]);
|
|
71207
71542
|
}
|
|
71208
71543
|
function useStatutoryFormProgress(templateSnapshot, results) {
|
|
71209
|
-
return
|
|
71544
|
+
return useMemo9(() => {
|
|
71210
71545
|
const declaration = templateSnapshot?.statutoryForm;
|
|
71211
71546
|
if (!declaration) return null;
|
|
71212
71547
|
const done = formCompleteness(formBoundItemIds(declaration), results);
|
|
@@ -71256,7 +71591,7 @@ function RevisionBanner({ status, inspectionDate }) {
|
|
|
71256
71591
|
}
|
|
71257
71592
|
|
|
71258
71593
|
// src/components/editor/ItemEditor.tsx
|
|
71259
|
-
import { useState as useState32, useMemo as
|
|
71594
|
+
import { useState as useState32, useMemo as useMemo13, useEffect as useEffect28, useRef as useRef35 } from "react";
|
|
71260
71595
|
|
|
71261
71596
|
// src/components/editor/CommentTypeahead.tsx
|
|
71262
71597
|
import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
@@ -71307,7 +71642,7 @@ function CommentTypeahead({
|
|
|
71307
71642
|
}
|
|
71308
71643
|
|
|
71309
71644
|
// src/hooks/useCommentTypeahead.ts
|
|
71310
|
-
import { useMemo as
|
|
71645
|
+
import { useMemo as useMemo10, useState as useState25, useEffect as useEffect22, useCallback as useCallback26 } from "react";
|
|
71311
71646
|
|
|
71312
71647
|
// src/shared/comment-typeahead.ts
|
|
71313
71648
|
function isSubsequence(needle, haystack) {
|
|
@@ -71370,15 +71705,15 @@ function replaceFragmentBeforeCaret(value, caret, replacement) {
|
|
|
71370
71705
|
// src/hooks/useCommentTypeahead.ts
|
|
71371
71706
|
function useCommentTypeahead(entries, query, opts) {
|
|
71372
71707
|
const max = opts?.max ?? 8;
|
|
71373
|
-
const matches =
|
|
71708
|
+
const matches = useMemo10(
|
|
71374
71709
|
() => rankTypeaheadMatches(entries, query).slice(0, max),
|
|
71375
71710
|
[entries, query, max]
|
|
71376
71711
|
);
|
|
71377
71712
|
const [selectedIndex, setSelectedIndex] = useState25(0);
|
|
71378
|
-
|
|
71713
|
+
useEffect22(() => {
|
|
71379
71714
|
setSelectedIndex(0);
|
|
71380
71715
|
}, [query, matches.length]);
|
|
71381
|
-
const move =
|
|
71716
|
+
const move = useCallback26(
|
|
71382
71717
|
(delta) => {
|
|
71383
71718
|
setSelectedIndex((i) => {
|
|
71384
71719
|
const n = matches.length;
|
|
@@ -71388,7 +71723,7 @@ function useCommentTypeahead(entries, query, opts) {
|
|
|
71388
71723
|
},
|
|
71389
71724
|
[matches.length]
|
|
71390
71725
|
);
|
|
71391
|
-
const current =
|
|
71726
|
+
const current = useCallback26(
|
|
71392
71727
|
() => matches[selectedIndex] ?? null,
|
|
71393
71728
|
[matches, selectedIndex]
|
|
71394
71729
|
);
|
|
@@ -71396,21 +71731,21 @@ function useCommentTypeahead(entries, query, opts) {
|
|
|
71396
71731
|
}
|
|
71397
71732
|
|
|
71398
71733
|
// src/components/editor/AiAssistPanel.tsx
|
|
71399
|
-
import { useEffect as
|
|
71734
|
+
import { useEffect as useEffect23, useRef as useRef31, useState as useState26 } from "react";
|
|
71400
71735
|
import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
71401
71736
|
function AiAssistPanel({ notes, context, resultId, onAccept }) {
|
|
71402
71737
|
const ai = useFieldDataSource().resources.aiAssist;
|
|
71403
71738
|
const [draft, setDraft] = useState26(null);
|
|
71404
71739
|
const [reviewed, setReviewed] = useState26(false);
|
|
71405
71740
|
const [error, setError] = useState26(null);
|
|
71406
|
-
const inFlight2 =
|
|
71741
|
+
const inFlight2 = useRef31(false);
|
|
71407
71742
|
const [busy, setBusy] = useState26(false);
|
|
71408
|
-
const mounted =
|
|
71409
|
-
const draftRef =
|
|
71743
|
+
const mounted = useRef31(true);
|
|
71744
|
+
const draftRef = useRef31(draft);
|
|
71410
71745
|
draftRef.current = draft;
|
|
71411
|
-
const onAcceptRef =
|
|
71746
|
+
const onAcceptRef = useRef31(onAccept);
|
|
71412
71747
|
onAcceptRef.current = onAccept;
|
|
71413
|
-
|
|
71748
|
+
useEffect23(() => {
|
|
71414
71749
|
mounted.current = true;
|
|
71415
71750
|
return () => {
|
|
71416
71751
|
mounted.current = false;
|
|
@@ -71556,21 +71891,21 @@ function NotesFieldHeader({
|
|
|
71556
71891
|
}
|
|
71557
71892
|
|
|
71558
71893
|
// src/components/editor/CloneLastButton.tsx
|
|
71559
|
-
import { useState as useState27, useRef as
|
|
71894
|
+
import { useState as useState27, useRef as useRef32, useEffect as useEffect24 } from "react";
|
|
71560
71895
|
import { jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
71561
71896
|
function CloneLastButton({ defaultScope, onClone, disabled }) {
|
|
71562
71897
|
const [open, setOpen] = useState27(false);
|
|
71563
71898
|
const [sessionScope, setSessionScope] = useState27(defaultScope);
|
|
71564
|
-
const ref =
|
|
71899
|
+
const ref = useRef32(null);
|
|
71565
71900
|
const SCOPE_LABELS = {
|
|
71566
71901
|
rating: index_exports.editor_clone_scope_rating(),
|
|
71567
71902
|
rating_notes: index_exports.editor_clone_scope_rating_notes(),
|
|
71568
71903
|
all: index_exports.editor_clone_scope_all()
|
|
71569
71904
|
};
|
|
71570
|
-
|
|
71905
|
+
useEffect24(() => {
|
|
71571
71906
|
setSessionScope(defaultScope);
|
|
71572
71907
|
}, [defaultScope]);
|
|
71573
|
-
|
|
71908
|
+
useEffect24(() => {
|
|
71574
71909
|
if (!open) return;
|
|
71575
71910
|
const fn = (e) => {
|
|
71576
71911
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -71812,7 +72147,9 @@ function RatingSegment({
|
|
|
71812
72147
|
children: ratings.map((r, i) => {
|
|
71813
72148
|
const selected = r.value === value;
|
|
71814
72149
|
const toneClass = selected ? TONE_FILLED[r.tone] : TONE_IDLE[r.tone];
|
|
71815
|
-
const
|
|
72150
|
+
const colour = safeCssColor(r.color);
|
|
72151
|
+
const tokenFill = !!colour && isFallbackRatingColor(colour);
|
|
72152
|
+
const style = colour && !tokenFill ? { background: colour, color: readableTextOn(colour) ?? "#fff" } : void 0;
|
|
71816
72153
|
const text = size === "sm" ? r.shortLabel ?? r.label : r.shortLabel ? /* @__PURE__ */ jsxs40(Fragment8, { children: [
|
|
71817
72154
|
/* @__PURE__ */ jsx50("span", { className: "@min-[6.5rem]:hidden", children: r.shortLabel }),
|
|
71818
72155
|
/* @__PURE__ */ jsx50("span", { className: "hidden @min-[6.5rem]:inline", children: r.label })
|
|
@@ -71832,7 +72169,7 @@ function RatingSegment({
|
|
|
71832
72169
|
tabIndex: i === focusIndex ? 0 : -1,
|
|
71833
72170
|
onClick: () => onChange(r.value),
|
|
71834
72171
|
onKeyDown: (e) => onKeyDown(e, i),
|
|
71835
|
-
className: `transition-colors focus:outline-none focus:shadow-ih-focus ${sizeClass} ${
|
|
72172
|
+
className: `transition-colors focus:outline-none focus:shadow-ih-focus ${sizeClass} ${tokenFill ? "bg-ih-bg-muted text-ih-fg-1 border border-ih-border" : colour ? "" : toneClass}`,
|
|
71836
72173
|
style,
|
|
71837
72174
|
children: [
|
|
71838
72175
|
/* @__PURE__ */ jsx50("span", { className: "block truncate px-0.5", children: text }),
|
|
@@ -71892,12 +72229,13 @@ var CATEGORY_TOKENS = {
|
|
|
71892
72229
|
};
|
|
71893
72230
|
var DEFAULT_TOKENS = "bg-ih-bg-muted text-ih-fg-2";
|
|
71894
72231
|
function DefectCategoryChip({ category, className, color }) {
|
|
71895
|
-
const
|
|
72232
|
+
const safe = safeCssColor(color);
|
|
72233
|
+
const tokens = safe ? "bg-ih-bg-muted" : CATEGORY_TOKENS[category] ?? DEFAULT_TOKENS;
|
|
71896
72234
|
return /* @__PURE__ */ jsx52(
|
|
71897
72235
|
"span",
|
|
71898
72236
|
{
|
|
71899
72237
|
className: `text-[9px] font-bold uppercase tracking-wider px-1.5 py-0.5 rounded-full ${tokens}${className ? ` ${className}` : ""}`,
|
|
71900
|
-
style:
|
|
72238
|
+
style: safe ? { color: safe } : void 0,
|
|
71901
72239
|
children: category
|
|
71902
72240
|
}
|
|
71903
72241
|
);
|
|
@@ -71937,7 +72275,7 @@ function CannedCommentRow({
|
|
|
71937
72275
|
}
|
|
71938
72276
|
|
|
71939
72277
|
// src/components/editor/DefectFieldsRow.tsx
|
|
71940
|
-
import { useMemo as
|
|
72278
|
+
import { useMemo as useMemo11 } from "react";
|
|
71941
72279
|
|
|
71942
72280
|
// src/shared/defect-fields.types.ts
|
|
71943
72281
|
var DEFECT_TRADES = [
|
|
@@ -72045,7 +72383,7 @@ function DefectFieldsRow({
|
|
|
72045
72383
|
locationRequired,
|
|
72046
72384
|
tradeRequired
|
|
72047
72385
|
}) {
|
|
72048
|
-
const dedupedSuggestions =
|
|
72386
|
+
const dedupedSuggestions = useMemo11(
|
|
72049
72387
|
() => Array.from(new Set(locationSuggestions.filter((s) => s.length > 0))),
|
|
72050
72388
|
[locationSuggestions]
|
|
72051
72389
|
);
|
|
@@ -72122,7 +72460,7 @@ function DefectFieldsRow({
|
|
|
72122
72460
|
}
|
|
72123
72461
|
|
|
72124
72462
|
// src/components/editor/RepairItemsPanel.tsx
|
|
72125
|
-
import { useEffect as
|
|
72463
|
+
import { useEffect as useEffect25, useState as useState28 } from "react";
|
|
72126
72464
|
import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
72127
72465
|
function RepairItemsPanel({
|
|
72128
72466
|
attached,
|
|
@@ -72133,7 +72471,7 @@ function RepairItemsPanel({
|
|
|
72133
72471
|
const [open, setOpen] = useState28(false);
|
|
72134
72472
|
const [q, setQ] = useState28("");
|
|
72135
72473
|
const repairItems = useFieldDataSource().resources.repairItems;
|
|
72136
|
-
|
|
72474
|
+
useEffect25(() => {
|
|
72137
72475
|
let cancelled = false;
|
|
72138
72476
|
void (repairItems?.list() ?? Promise.resolve([])).then((items) => {
|
|
72139
72477
|
if (!cancelled) setCatalog(items);
|
|
@@ -72545,7 +72883,7 @@ function CannedCommentTabs({
|
|
|
72545
72883
|
}
|
|
72546
72884
|
|
|
72547
72885
|
// src/components/media-studio/ItemPhotoStrip.tsx
|
|
72548
|
-
import { useEffect as
|
|
72886
|
+
import { useEffect as useEffect26, useRef as useRef33, useState as useState29 } from "react";
|
|
72549
72887
|
import Sortable2 from "sortablejs";
|
|
72550
72888
|
import { Fragment as Fragment10, jsx as jsx58, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
72551
72889
|
function formatDuration(sec) {
|
|
@@ -72572,10 +72910,10 @@ function ItemPhotoStrip({
|
|
|
72572
72910
|
videoPosterUrl,
|
|
72573
72911
|
pendingPhotoUrl
|
|
72574
72912
|
}) {
|
|
72575
|
-
const rowRef =
|
|
72913
|
+
const rowRef = useRef33(null);
|
|
72576
72914
|
const [selecting, setSelecting] = useState29(false);
|
|
72577
72915
|
const [sel, setSel] = useState29(/* @__PURE__ */ new Set());
|
|
72578
|
-
const lp =
|
|
72916
|
+
const lp = useRef33(void 0);
|
|
72579
72917
|
const toggle = (i) => setSel((prev) => {
|
|
72580
72918
|
const next = new Set(prev);
|
|
72581
72919
|
if (next.has(i)) next.delete(i);
|
|
@@ -72595,11 +72933,11 @@ function ItemPhotoStrip({
|
|
|
72595
72933
|
}, 450);
|
|
72596
72934
|
};
|
|
72597
72935
|
const cancelLongPress = () => clearTimeout(lp.current);
|
|
72598
|
-
const photosRef =
|
|
72936
|
+
const photosRef = useRef33(photos);
|
|
72599
72937
|
photosRef.current = photos;
|
|
72600
|
-
const onReorderRef =
|
|
72938
|
+
const onReorderRef = useRef33(onReorder);
|
|
72601
72939
|
onReorderRef.current = onReorder;
|
|
72602
|
-
|
|
72940
|
+
useEffect26(() => {
|
|
72603
72941
|
if (!rowRef.current || !onReorder) return;
|
|
72604
72942
|
const s = Sortable2.create(rowRef.current, {
|
|
72605
72943
|
animation: 150,
|
|
@@ -73029,7 +73367,7 @@ function FormField({
|
|
|
73029
73367
|
}
|
|
73030
73368
|
|
|
73031
73369
|
// src/components/editor/item-editor-ui.ts
|
|
73032
|
-
import { useCallback as
|
|
73370
|
+
import { useCallback as useCallback27, useState as useState31 } from "react";
|
|
73033
73371
|
var INITIAL_ITEM_EDITOR_UI = {
|
|
73034
73372
|
activeTab: "information",
|
|
73035
73373
|
defectQuery: "",
|
|
@@ -73042,7 +73380,7 @@ var INITIAL_ITEM_EDITOR_UI = {
|
|
|
73042
73380
|
};
|
|
73043
73381
|
function useItemEditorUiStore() {
|
|
73044
73382
|
const [byItem, setByItem] = useState31({});
|
|
73045
|
-
return
|
|
73383
|
+
return useCallback27(
|
|
73046
73384
|
(itemId) => ({
|
|
73047
73385
|
ui: byItem[itemId] ?? INITIAL_ITEM_EDITOR_UI,
|
|
73048
73386
|
patch: (change) => setByItem((prev) => ({ ...prev, [itemId]: { ...prev[itemId] ?? INITIAL_ITEM_EDITOR_UI, ...change } }))
|
|
@@ -73067,17 +73405,29 @@ function useItemEditorUi(external) {
|
|
|
73067
73405
|
}
|
|
73068
73406
|
|
|
73069
73407
|
// src/hooks/useNotesCommitOnLeave.ts
|
|
73070
|
-
import { useEffect as
|
|
73408
|
+
import { useCallback as useCallback28, useEffect as useEffect27, useMemo as useMemo12, useRef as useRef34 } from "react";
|
|
73409
|
+
var IDLE_MS = 1e3;
|
|
73071
73410
|
function useNotesCommitOnLeave(itemId, commit, flushRef) {
|
|
73072
|
-
const pending =
|
|
73073
|
-
const
|
|
73411
|
+
const pending = useRef34(null);
|
|
73412
|
+
const idle = useRef34(null);
|
|
73413
|
+
const composing = useRef34(false);
|
|
73414
|
+
const latest = useRef34({ itemId, commit });
|
|
73074
73415
|
latest.current = { itemId, commit };
|
|
73075
|
-
|
|
73076
|
-
|
|
73077
|
-
|
|
73078
|
-
|
|
73079
|
-
|
|
73080
|
-
|
|
73416
|
+
const cancelIdle = useCallback28(() => {
|
|
73417
|
+
if (idle.current !== null) clearTimeout(idle.current);
|
|
73418
|
+
idle.current = null;
|
|
73419
|
+
}, []);
|
|
73420
|
+
const flush = useCallback28(() => {
|
|
73421
|
+
cancelIdle();
|
|
73422
|
+
const held = pending.current;
|
|
73423
|
+
pending.current = null;
|
|
73424
|
+
if (held) latest.current.commit(held.text, held.itemId);
|
|
73425
|
+
}, [cancelIdle]);
|
|
73426
|
+
useEffect27(() => () => {
|
|
73427
|
+
composing.current = false;
|
|
73428
|
+
flush();
|
|
73429
|
+
}, [itemId, flush]);
|
|
73430
|
+
useEffect27(() => {
|
|
73081
73431
|
const onHide = () => {
|
|
73082
73432
|
if (document.visibilityState === "hidden") flush();
|
|
73083
73433
|
};
|
|
@@ -73091,12 +73441,35 @@ function useNotesCommitOnLeave(itemId, commit, flushRef) {
|
|
|
73091
73441
|
flush();
|
|
73092
73442
|
};
|
|
73093
73443
|
}, []);
|
|
73444
|
+
const armIdle = useCallback28(() => {
|
|
73445
|
+
cancelIdle();
|
|
73446
|
+
idle.current = setTimeout(function onIdle() {
|
|
73447
|
+
if (composing.current) idle.current = setTimeout(onIdle, IDLE_MS);
|
|
73448
|
+
else flush();
|
|
73449
|
+
}, IDLE_MS);
|
|
73450
|
+
}, [cancelIdle, flush]);
|
|
73451
|
+
const composition = useMemo12(
|
|
73452
|
+
() => ({
|
|
73453
|
+
onCompositionStart: () => {
|
|
73454
|
+
composing.current = true;
|
|
73455
|
+
},
|
|
73456
|
+
onCompositionEnd: () => {
|
|
73457
|
+
composing.current = false;
|
|
73458
|
+
if (pending.current) armIdle();
|
|
73459
|
+
}
|
|
73460
|
+
}),
|
|
73461
|
+
[armIdle]
|
|
73462
|
+
);
|
|
73094
73463
|
return {
|
|
73464
|
+
composition,
|
|
73095
73465
|
track: (text) => {
|
|
73096
73466
|
pending.current = { itemId: latest.current.itemId, text };
|
|
73467
|
+
armIdle();
|
|
73097
73468
|
},
|
|
73098
73469
|
settle: () => {
|
|
73099
73470
|
pending.current = null;
|
|
73471
|
+
composing.current = false;
|
|
73472
|
+
cancelIdle();
|
|
73100
73473
|
}
|
|
73101
73474
|
};
|
|
73102
73475
|
}
|
|
@@ -73164,10 +73537,10 @@ function ItemEditor({
|
|
|
73164
73537
|
const { urls } = useFieldDataSource();
|
|
73165
73538
|
const { activeTab, setActiveTab, defectQuery, setDefectQuery, customFormOpen, setCustomFormOpen, customTitle, setCustomTitle, customComment, setCustomComment, customCategory, setCustomCategory, customTrade, setCustomTrade, saveToLibrary, setSaveToLibrary } = useItemEditorUi(uiControl);
|
|
73166
73539
|
const notesCommit = useNotesCommitOnLeave(item?.id, onNotesBlur, notesFlushRef);
|
|
73167
|
-
const notesRef =
|
|
73540
|
+
const notesRef = useRef35(null);
|
|
73168
73541
|
const [taOpen, setTaOpen] = useState32(false);
|
|
73169
73542
|
const [taQuery, setTaQuery] = useState32("");
|
|
73170
|
-
const taEntries =
|
|
73543
|
+
const taEntries = useMemo13(() => flattenItemTabs(item?.tabs), [item?.tabs]);
|
|
73171
73544
|
const ta = useCommentTypeahead(taEntries, taQuery, { max: 8 });
|
|
73172
73545
|
const insertPick = (commentText) => {
|
|
73173
73546
|
const el = notesRef.current;
|
|
@@ -73186,7 +73559,7 @@ function ItemEditor({
|
|
|
73186
73559
|
});
|
|
73187
73560
|
};
|
|
73188
73561
|
const [libraryMatches, setLibraryMatches] = useState32([]);
|
|
73189
|
-
|
|
73562
|
+
useEffect28(() => {
|
|
73190
73563
|
const q = defectQuery.trim();
|
|
73191
73564
|
if (activeTab !== "defects" || q.length < 2 || !onSearchLibrary) {
|
|
73192
73565
|
setLibraryMatches([]);
|
|
@@ -73361,6 +73734,7 @@ function ItemEditor({
|
|
|
73361
73734
|
"textarea",
|
|
73362
73735
|
{
|
|
73363
73736
|
id: "notes-textarea",
|
|
73737
|
+
...notesCommit.composition,
|
|
73364
73738
|
ref: notesRef,
|
|
73365
73739
|
value: result.notes || "",
|
|
73366
73740
|
onChange: (e) => {
|
|
@@ -73372,7 +73746,7 @@ function ItemEditor({
|
|
|
73372
73746
|
},
|
|
73373
73747
|
onBlur: (e) => {
|
|
73374
73748
|
notesCommit.settle();
|
|
73375
|
-
onNotesBlur(e.target.value);
|
|
73749
|
+
onNotesBlur(e.target.value, item.id);
|
|
73376
73750
|
setTaOpen(false);
|
|
73377
73751
|
},
|
|
73378
73752
|
onKeyDown: (e) => {
|
|
@@ -73433,7 +73807,7 @@ function ItemEditor({
|
|
|
73433
73807
|
onAccept: (text) => {
|
|
73434
73808
|
onNotes(text);
|
|
73435
73809
|
notesCommit.settle();
|
|
73436
|
-
onNotesBlur(text);
|
|
73810
|
+
onNotesBlur(text, item.id);
|
|
73437
73811
|
}
|
|
73438
73812
|
}
|
|
73439
73813
|
),
|
|
@@ -73541,6 +73915,21 @@ function ItemEditor({
|
|
|
73541
73915
|
] });
|
|
73542
73916
|
}
|
|
73543
73917
|
|
|
73918
|
+
// src/hooks/useHasFinePointer.ts
|
|
73919
|
+
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
73920
|
+
var FINE = "(any-hover: hover) and (any-pointer: fine)";
|
|
73921
|
+
function subscribe(onChange) {
|
|
73922
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
|
|
73923
|
+
};
|
|
73924
|
+
const mq = window.matchMedia(FINE);
|
|
73925
|
+
mq.addEventListener("change", onChange);
|
|
73926
|
+
return () => mq.removeEventListener("change", onChange);
|
|
73927
|
+
}
|
|
73928
|
+
var snapshot = () => typeof window === "undefined" || typeof window.matchMedia !== "function" || window.matchMedia(FINE).matches;
|
|
73929
|
+
function useHasFinePointer() {
|
|
73930
|
+
return useSyncExternalStore3(subscribe, snapshot, () => true);
|
|
73931
|
+
}
|
|
73932
|
+
|
|
73544
73933
|
// src/components/editor/ItemPaneEmptyState.tsx
|
|
73545
73934
|
import { jsx as jsx64, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
73546
73935
|
function firstItemToOpen(items, isRated) {
|
|
@@ -73550,6 +73939,7 @@ function firstItemToOpen(items, isRated) {
|
|
|
73550
73939
|
}
|
|
73551
73940
|
function ItemPaneEmptyState({ items, isRated, onOpenItem }) {
|
|
73552
73941
|
const next = firstItemToOpen(items, isRated);
|
|
73942
|
+
const fine = useHasFinePointer();
|
|
73553
73943
|
if (!next) {
|
|
73554
73944
|
return /* @__PURE__ */ jsx64("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx64(
|
|
73555
73945
|
EmptyState,
|
|
@@ -73578,7 +73968,7 @@ function ItemPaneEmptyState({ items, isRated, onOpenItem }) {
|
|
|
73578
73968
|
children: index_exports.editor_pane_open_item({ label: next.item.label })
|
|
73579
73969
|
}
|
|
73580
73970
|
),
|
|
73581
|
-
/* @__PURE__ */ jsxs52("p", { className: "text-[11px] text-ih-fg-3", children: [
|
|
73971
|
+
fine && /* @__PURE__ */ jsxs52("p", { className: "text-[11px] text-ih-fg-3", children: [
|
|
73582
73972
|
index_exports.editor_route_navigate_hint_press(),
|
|
73583
73973
|
" ",
|
|
73584
73974
|
/* @__PURE__ */ jsx64("kbd", { className: "px-1.5 py-0.5 bg-ih-bg-muted rounded text-[10px] font-mono border", children: "J" }),
|
|
@@ -73594,20 +73984,27 @@ function ItemPaneEmptyState({ items, isRated, onOpenItem }) {
|
|
|
73594
73984
|
}
|
|
73595
73985
|
|
|
73596
73986
|
// src/components/editor/TagChipRow.tsx
|
|
73597
|
-
import { useMemo as
|
|
73987
|
+
import { useMemo as useMemo14 } from "react";
|
|
73598
73988
|
import { jsx as jsx65, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
73599
|
-
|
|
73600
|
-
|
|
73601
|
-
|
|
73602
|
-
|
|
73989
|
+
var COARSE = "[@media(pointer:coarse)]:min-h-9 [@media(pointer:coarse)]:px-3 [@media(pointer:coarse)]:text-xs";
|
|
73990
|
+
function TagChipRow({ pinnedTags, chosenTags, activeTagIds, onToggle, onOpenLibrary }) {
|
|
73991
|
+
const sorted = useMemo14(() => {
|
|
73992
|
+
const pinned = pinnedTags.slice(0, 5);
|
|
73993
|
+
const shown = new Set(pinned.map((t) => t.id));
|
|
73994
|
+
const unpinned = (chosenTags ?? []).filter((t) => !shown.has(t.id)).map((t) => ({ ...t, color: t.color ?? "" }));
|
|
73995
|
+
return [...pinned, ...unpinned];
|
|
73996
|
+
}, [pinnedTags, chosenTags]);
|
|
73997
|
+
if (sorted.length === 0 && !onOpenLibrary) return null;
|
|
73998
|
+
return /* @__PURE__ */ jsxs53("div", { className: "mt-2 flex flex-wrap items-center gap-1.5 [@media(pointer:coarse)]:gap-2", children: [
|
|
73603
73999
|
sorted.map((tag) => {
|
|
73604
74000
|
const active = activeTagIds.has(tag.id);
|
|
74001
|
+
const colour = safeCssColor(tag.color);
|
|
73605
74002
|
return /* @__PURE__ */ jsx65(
|
|
73606
74003
|
"button",
|
|
73607
74004
|
{
|
|
73608
74005
|
onClick: () => onToggle(tag),
|
|
73609
|
-
className: `px-2 py-0.5 rounded-full text-[11px] font-bold transition-colors border ${active ? "text-white border-transparent
|
|
73610
|
-
style: active ? { backgroundColor:
|
|
74006
|
+
className: `px-2 py-0.5 rounded-full text-[11px] font-bold transition-colors border ${COARSE} ${active ? `${colour ? "text-white" : "bg-ih-bg-muted text-ih-fg-1"} border-transparent` : "text-ih-fg-3 border-ih-border bg-transparent hover:bg-ih-bg-muted"}`,
|
|
74007
|
+
style: active && colour ? { backgroundColor: colour, color: readableTextOn(colour) ?? void 0 } : {},
|
|
73611
74008
|
children: tag.name
|
|
73612
74009
|
},
|
|
73613
74010
|
tag.id
|
|
@@ -73619,7 +74016,7 @@ function TagChipRow({ pinnedTags, activeTagIds, onToggle, onOpenLibrary }) {
|
|
|
73619
74016
|
variant: "ghost",
|
|
73620
74017
|
size: "sm",
|
|
73621
74018
|
onClick: onOpenLibrary,
|
|
73622
|
-
className:
|
|
74019
|
+
className: `h-auto px-2 py-0.5 rounded-full border border-dashed border-ih-border text-ih-fg-3 hover:bg-ih-bg-muted ${COARSE}`,
|
|
73623
74020
|
"aria-label": index_exports.editor_tagchiprow_open_library_aria(),
|
|
73624
74021
|
children: index_exports.editor_tagchiprow_more()
|
|
73625
74022
|
}
|
|
@@ -73628,7 +74025,7 @@ function TagChipRow({ pinnedTags, activeTagIds, onToggle, onOpenLibrary }) {
|
|
|
73628
74025
|
}
|
|
73629
74026
|
|
|
73630
74027
|
// src/components/editor/SideRail.tsx
|
|
73631
|
-
import { useState as useState35, useEffect as
|
|
74028
|
+
import { useState as useState35, useEffect as useEffect31 } from "react";
|
|
73632
74029
|
|
|
73633
74030
|
// src/shared/photo-name.ts
|
|
73634
74031
|
var UUID_TAIL = /_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}_(.+)$/i;
|
|
@@ -73642,7 +74039,7 @@ function withDownload(url) {
|
|
|
73642
74039
|
}
|
|
73643
74040
|
|
|
73644
74041
|
// src/components/media-studio/PhotoGallery.tsx
|
|
73645
|
-
import { useCallback as
|
|
74042
|
+
import { useCallback as useCallback30, useEffect as useEffect30, useRef as useRef37, useState as useState34 } from "react";
|
|
73646
74043
|
|
|
73647
74044
|
// src/components/media-studio/PhotoGrid.tsx
|
|
73648
74045
|
import { RowsPhotoAlbum } from "react-photo-album";
|
|
@@ -73666,6 +74063,7 @@ import Zoom from "yet-another-react-lightbox/plugins/zoom";
|
|
|
73666
74063
|
import "yet-another-react-lightbox/styles.css";
|
|
73667
74064
|
import { jsx as jsx67 } from "react/jsx-runtime";
|
|
73668
74065
|
function PhotoLightbox({ slides, index, open, onClose, toolbarButtons, toolbarWrap, renderSlide }) {
|
|
74066
|
+
useLayer(open, { onEscape: onClose, lockScroll: true, traps: true });
|
|
73669
74067
|
return /* @__PURE__ */ jsx67(
|
|
73670
74068
|
Lightbox,
|
|
73671
74069
|
{
|
|
@@ -73683,13 +74081,13 @@ function PhotoLightbox({ slides, index, open, onClose, toolbarButtons, toolbarWr
|
|
|
73683
74081
|
}
|
|
73684
74082
|
|
|
73685
74083
|
// src/hooks/useBreakpoint.ts
|
|
73686
|
-
import { useCallback as
|
|
74084
|
+
import { useCallback as useCallback29, useEffect as useEffect29, useRef as useRef36, useState as useState33, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
73687
74085
|
function useIsMobile() {
|
|
73688
74086
|
const [isMobile, setIsMobile] = useState33(() => {
|
|
73689
74087
|
if (typeof window === "undefined") return false;
|
|
73690
74088
|
return window.matchMedia("(max-width: 767.98px)").matches;
|
|
73691
74089
|
});
|
|
73692
|
-
|
|
74090
|
+
useEffect29(() => {
|
|
73693
74091
|
if (typeof window === "undefined") return;
|
|
73694
74092
|
const mq = window.matchMedia("(max-width: 767.98px)");
|
|
73695
74093
|
const fn = (e) => setIsMobile(e.matches);
|
|
@@ -73716,12 +74114,12 @@ function subscribeLayout(onChange) {
|
|
|
73716
74114
|
};
|
|
73717
74115
|
}
|
|
73718
74116
|
function useEditorLayout(initialLayout = "desktop", onObserved) {
|
|
73719
|
-
const serverSnapshot =
|
|
73720
|
-
const layout =
|
|
73721
|
-
const observer =
|
|
74117
|
+
const serverSnapshot = useCallback29(() => initialLayout, [initialLayout]);
|
|
74118
|
+
const layout = useSyncExternalStore4(subscribeLayout, readLayout, serverSnapshot);
|
|
74119
|
+
const observer = useRef36(onObserved);
|
|
73722
74120
|
observer.current = onObserved;
|
|
73723
|
-
const told =
|
|
73724
|
-
|
|
74121
|
+
const told = useRef36(null);
|
|
74122
|
+
useEffect29(() => {
|
|
73725
74123
|
const seen = readLayout();
|
|
73726
74124
|
if (told.current === seen) return;
|
|
73727
74125
|
told.current = seen;
|
|
@@ -73731,7 +74129,7 @@ function useEditorLayout(initialLayout = "desktop", onObserved) {
|
|
|
73731
74129
|
}
|
|
73732
74130
|
function useMaxWidth(px) {
|
|
73733
74131
|
const query = `(max-width: ${px}px)`;
|
|
73734
|
-
const
|
|
74132
|
+
const subscribe2 = useCallback29(
|
|
73735
74133
|
(onChange) => {
|
|
73736
74134
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
|
|
73737
74135
|
};
|
|
@@ -73741,11 +74139,11 @@ function useMaxWidth(px) {
|
|
|
73741
74139
|
},
|
|
73742
74140
|
[query]
|
|
73743
74141
|
);
|
|
73744
|
-
const getSnapshot =
|
|
74142
|
+
const getSnapshot = useCallback29(
|
|
73745
74143
|
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(query).matches,
|
|
73746
74144
|
[query]
|
|
73747
74145
|
);
|
|
73748
|
-
return
|
|
74146
|
+
return useSyncExternalStore4(subscribe2, getSnapshot, () => false);
|
|
73749
74147
|
}
|
|
73750
74148
|
|
|
73751
74149
|
// src/components/media-studio/VideoPlayer.tsx
|
|
@@ -74042,22 +74440,23 @@ var GALLERY_UNHANDLED_ACTIONS = ["crop", "rotate", "caption", "revert", "delete"
|
|
|
74042
74440
|
function PhotoGallery({ inspectionId, onSetCover, onAnnotate }) {
|
|
74043
74441
|
const mediaPool = useFieldDataSource().resources.mediaPool;
|
|
74044
74442
|
const readOnly = useReadOnly();
|
|
74443
|
+
const photoUrlVersion = usePhotoUrlVersion();
|
|
74045
74444
|
const [listing, setListing] = useState34(null);
|
|
74046
74445
|
const [lightbox, setLightbox] = useState34(null);
|
|
74047
74446
|
const photos = listing?.photos ?? [];
|
|
74048
|
-
const latestRead =
|
|
74049
|
-
const load =
|
|
74447
|
+
const latestRead = useRef37(0);
|
|
74448
|
+
const load = useCallback30(() => {
|
|
74050
74449
|
const read = latestRead.current += 1;
|
|
74051
74450
|
void (mediaPool?.list(inspectionId) ?? Promise.resolve({ photos: [], answered: false })).then((next) => {
|
|
74052
74451
|
if (read === latestRead.current) setListing(next);
|
|
74053
74452
|
});
|
|
74054
74453
|
}, [mediaPool, inspectionId]);
|
|
74055
|
-
|
|
74454
|
+
useEffect30(() => {
|
|
74056
74455
|
if (inspectionId) load();
|
|
74057
74456
|
return () => {
|
|
74058
74457
|
latestRead.current += 1;
|
|
74059
74458
|
};
|
|
74060
|
-
}, [inspectionId, load]);
|
|
74459
|
+
}, [inspectionId, load, photoUrlVersion]);
|
|
74061
74460
|
if (!listing) return /* @__PURE__ */ jsx70("p", { className: "text-[13px] text-ih-fg-3 text-center py-8", children: index_exports.media_gallery_loading() });
|
|
74062
74461
|
if (!listing.answered) {
|
|
74063
74462
|
return /* @__PURE__ */ jsxs56("div", { className: "text-center py-8 space-y-2", children: [
|
|
@@ -74117,6 +74516,10 @@ function CommentLibraryList({ serverComments, selectedIndex, sort, onInsertText,
|
|
|
74117
74516
|
|
|
74118
74517
|
// src/components/editor/SideRail.tsx
|
|
74119
74518
|
import { jsx as jsx72, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
74519
|
+
function ratingPillStyle(bg) {
|
|
74520
|
+
const color = readableTextOn(bg);
|
|
74521
|
+
return color ? { backgroundColor: bg, color } : { backgroundColor: bg };
|
|
74522
|
+
}
|
|
74120
74523
|
var TABS = [
|
|
74121
74524
|
{ id: "preview", label: () => index_exports.editor_siderail_tab_preview(), icon: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" },
|
|
74122
74525
|
{ id: "library", label: () => index_exports.editor_siderail_tab_library(), icon: "M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" },
|
|
@@ -74128,6 +74531,7 @@ function SideRail({ mode, activeItem, activeResult, getRatingColor, getRatingLab
|
|
|
74128
74531
|
const [activeTab, setActiveTab] = useState35("preview");
|
|
74129
74532
|
const [openState, setOpen] = useState35(initialOpen ?? false);
|
|
74130
74533
|
const open = fill || openState;
|
|
74534
|
+
const ratingColor = safeCssColor(getRatingColor?.(String(activeResult?.rating ?? ""))) ?? "#6b7280";
|
|
74131
74535
|
const hideLibrary = mode === "fill" && !!activeItem && activeItem.type !== "rich";
|
|
74132
74536
|
const visibleTabs = TABS.filter((t) => {
|
|
74133
74537
|
if (t.id === "photos" && (mode !== "fill" || !resources.mediaPool)) return false;
|
|
@@ -74136,7 +74540,7 @@ function SideRail({ mode, activeItem, activeResult, getRatingColor, getRatingLab
|
|
|
74136
74540
|
});
|
|
74137
74541
|
const photoKeys = (Array.isArray(activeResult?.photos) ? activeResult.photos : []).map((p) => typeof p === "string" ? p : p?.mediaType === "video" ? "" : p?.key ?? "").filter((k) => k !== "");
|
|
74138
74542
|
const effectiveTab = visibleTabs.some((t) => t.id === activeTab) ? activeTab : "preview";
|
|
74139
|
-
|
|
74543
|
+
useEffect31(() => {
|
|
74140
74544
|
if (hideLibrary && activeTab === "library") {
|
|
74141
74545
|
setActiveTab("preview");
|
|
74142
74546
|
onLibraryTabChange?.(false);
|
|
@@ -74162,7 +74566,7 @@ function SideRail({ mode, activeItem, activeResult, getRatingColor, getRatingLab
|
|
|
74162
74566
|
};
|
|
74163
74567
|
return /* @__PURE__ */ jsxs58("div", { className: "flex h-full", children: [
|
|
74164
74568
|
open && /* @__PURE__ */ jsxs58("div", { className: `${fill ? "flex-1 min-w-0" : "w-64"} border-l border-ih-border bg-ih-bg-card flex flex-col overflow-hidden`, children: [
|
|
74165
|
-
/* @__PURE__ */ jsxs58("div", { className:
|
|
74569
|
+
/* @__PURE__ */ jsxs58("div", { className: `flex items-center justify-between ${fill ? "px-3" : "pl-9 pr-3"} py-2 border-b border-ih-border`, children: [
|
|
74166
74570
|
/* @__PURE__ */ jsx72("span", { className: "text-[11px] font-bold uppercase tracking-[0.15em] text-ih-fg-3 capitalize", children: effectiveTab }),
|
|
74167
74571
|
!fill && /* @__PURE__ */ jsx72(IconButton, { onClick: closePanel, "aria-label": index_exports.editor_siderail_close_panel(), size: "sm", className: "w-6 h-6 text-ih-fg-4 hover:text-ih-fg-2", children: /* @__PURE__ */ jsx72(Icon, { name: "x", size: 14 }) })
|
|
74168
74572
|
] }),
|
|
@@ -74172,8 +74576,8 @@ function SideRail({ mode, activeItem, activeResult, getRatingColor, getRatingLab
|
|
|
74172
74576
|
Boolean(activeResult.rating) && /* @__PURE__ */ jsx72("div", { children: /* @__PURE__ */ jsx72(
|
|
74173
74577
|
"span",
|
|
74174
74578
|
{
|
|
74175
|
-
className:
|
|
74176
|
-
style:
|
|
74579
|
+
className: `inline-block px-2 py-0.5 rounded-full text-[10px] font-bold ${isFallbackRatingColor(ratingColor) ? "bg-ih-bg-muted text-ih-fg-1" : "text-white"}`,
|
|
74580
|
+
style: isFallbackRatingColor(ratingColor) ? void 0 : ratingPillStyle(ratingColor),
|
|
74177
74581
|
children: getRatingLabel?.(activeResult.rating) || activeResult.rating
|
|
74178
74582
|
}
|
|
74179
74583
|
) }),
|
|
@@ -74281,7 +74685,7 @@ function SideRail({ mode, activeItem, activeResult, getRatingColor, getRatingLab
|
|
|
74281
74685
|
className: `relative w-10 flex flex-col items-center gap-0.5 py-2.5 rounded-r-md transition-all ${effectiveTab === tab.id && open ? "bg-ih-bg-card text-ih-primary-text shadow-ih-card border-l-2 border-ih-primary -ml-px" : "text-ih-fg-3 hover:text-ih-fg-2"}`,
|
|
74282
74686
|
title: tab.label(),
|
|
74283
74687
|
children: [
|
|
74284
|
-
tab.id === "photos" && (photoCount ?? 0) > 0 && /* @__PURE__ */ jsx72("span", { className: "absolute
|
|
74688
|
+
tab.id === "photos" && (photoCount ?? 0) > 0 && /* @__PURE__ */ jsx72("span", { className: "absolute top-0.5 right-1 inline-flex items-center justify-center min-w-[16px] h-4 px-1 rounded-full bg-ih-primary text-ih-fg-inverse text-[9px] font-bold leading-none", children: photoCount }),
|
|
74285
74689
|
/* @__PURE__ */ jsx72("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx72("path", { d: tab.icon }) }),
|
|
74286
74690
|
/* @__PURE__ */ jsx72("span", { className: "text-[8px] font-bold uppercase tracking-[0.1em]", style: { writingMode: "vertical-rl", transform: "rotate(180deg)" }, children: tab.label() })
|
|
74287
74691
|
]
|
|
@@ -74292,18 +74696,18 @@ function SideRail({ mode, activeItem, activeResult, getRatingColor, getRatingLab
|
|
|
74292
74696
|
}
|
|
74293
74697
|
|
|
74294
74698
|
// src/components/editor/SpeedMode.tsx
|
|
74295
|
-
import { useState as useState36, useEffect as
|
|
74699
|
+
import { useState as useState36, useEffect as useEffect33, useCallback as useCallback32, useRef as useRef41 } from "react";
|
|
74296
74700
|
|
|
74297
74701
|
// src/hooks/usePointerGesture.ts
|
|
74298
|
-
import { useCallback as
|
|
74702
|
+
import { useCallback as useCallback31, useRef as useRef38 } from "react";
|
|
74299
74703
|
function usePointerGesture(h) {
|
|
74300
|
-
const startRef =
|
|
74301
|
-
const longPressTimer =
|
|
74302
|
-
const fired =
|
|
74704
|
+
const startRef = useRef38(null);
|
|
74705
|
+
const longPressTimer = useRef38(null);
|
|
74706
|
+
const fired = useRef38(false);
|
|
74303
74707
|
const threshold = h.swipeThresholdPx ?? 60;
|
|
74304
74708
|
const maxDuration = h.swipeMaxDurationMs ?? 500;
|
|
74305
74709
|
const longPressMs = h.longPressMs ?? 500;
|
|
74306
|
-
const onPointerDown =
|
|
74710
|
+
const onPointerDown = useCallback31((e) => {
|
|
74307
74711
|
startRef.current = { x: e.clientX, y: e.clientY, t: Date.now() };
|
|
74308
74712
|
fired.current = false;
|
|
74309
74713
|
if (h.onLongPress) {
|
|
@@ -74315,14 +74719,14 @@ function usePointerGesture(h) {
|
|
|
74315
74719
|
}, longPressMs);
|
|
74316
74720
|
}
|
|
74317
74721
|
}, [h.onLongPress, longPressMs]);
|
|
74318
|
-
const cancel =
|
|
74722
|
+
const cancel = useCallback31(() => {
|
|
74319
74723
|
if (longPressTimer.current) {
|
|
74320
74724
|
clearTimeout(longPressTimer.current);
|
|
74321
74725
|
longPressTimer.current = null;
|
|
74322
74726
|
}
|
|
74323
74727
|
startRef.current = null;
|
|
74324
74728
|
}, []);
|
|
74325
|
-
const onPointerMove =
|
|
74729
|
+
const onPointerMove = useCallback31((e) => {
|
|
74326
74730
|
if (!startRef.current || fired.current) return;
|
|
74327
74731
|
const dx = e.clientX - startRef.current.x;
|
|
74328
74732
|
const dy = e.clientY - startRef.current.y;
|
|
@@ -74333,7 +74737,7 @@ function usePointerGesture(h) {
|
|
|
74333
74737
|
}
|
|
74334
74738
|
}
|
|
74335
74739
|
}, []);
|
|
74336
|
-
const onPointerUp =
|
|
74740
|
+
const onPointerUp = useCallback31((e) => {
|
|
74337
74741
|
if (!startRef.current || fired.current) {
|
|
74338
74742
|
cancel();
|
|
74339
74743
|
return;
|
|
@@ -74352,10 +74756,10 @@ function usePointerGesture(h) {
|
|
|
74352
74756
|
}
|
|
74353
74757
|
|
|
74354
74758
|
// src/components/MobileBottomDrawer.tsx
|
|
74355
|
-
import { useRef as
|
|
74759
|
+
import { useRef as useRef39 } from "react";
|
|
74356
74760
|
import { Fragment as Fragment12, jsx as jsx73, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
74357
74761
|
function MobileBottomDrawer({ open, onClose, title, children, heightFraction = 0.7 }) {
|
|
74358
|
-
const sheetRef =
|
|
74762
|
+
const sheetRef = useRef39(null);
|
|
74359
74763
|
useDialogBehavior(open, onClose, sheetRef);
|
|
74360
74764
|
return /* @__PURE__ */ jsxs59(Fragment12, { children: [
|
|
74361
74765
|
/* @__PURE__ */ jsx73(
|
|
@@ -74375,7 +74779,7 @@ function MobileBottomDrawer({ open, onClose, title, children, heightFraction = 0
|
|
|
74375
74779
|
"aria-label": title,
|
|
74376
74780
|
inert: !open,
|
|
74377
74781
|
"aria-hidden": open ? void 0 : true,
|
|
74378
|
-
className: `fixed left-0 right-0 bottom-0 z-50 bg-ih-bg-card rounded-t-2xl shadow-ih-popover flex flex-col outline-none transition-transform ${open ? "translate-y-0" : "translate-y-full"}`,
|
|
74782
|
+
className: `fixed left-0 right-0 bottom-0 z-50 pl-[env(safe-area-inset-left)] pr-[env(safe-area-inset-right)] bg-ih-bg-card rounded-t-2xl shadow-ih-popover flex flex-col outline-none transition-transform ${open ? "translate-y-0" : "translate-y-full"}`,
|
|
74379
74783
|
style: { height: `${Math.round(heightFraction * 100)}vh`, maxHeight: `${Math.round(heightFraction * 100)}dvh` },
|
|
74380
74784
|
children: [
|
|
74381
74785
|
/* @__PURE__ */ jsx73("div", { className: "flex justify-center pt-2 pb-1", children: /* @__PURE__ */ jsx73("div", { className: "w-10 h-1 rounded-full bg-ih-border" }) }),
|
|
@@ -74388,13 +74792,13 @@ function MobileBottomDrawer({ open, onClose, title, children, heightFraction = 0
|
|
|
74388
74792
|
}
|
|
74389
74793
|
|
|
74390
74794
|
// src/components/editor/SpeedModeUndoToast.tsx
|
|
74391
|
-
import { useEffect as
|
|
74795
|
+
import { useEffect as useEffect32, useRef as useRef40 } from "react";
|
|
74392
74796
|
import { jsx as jsx74, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
74393
74797
|
var BOX = "px-4 py-2.5 bg-ih-bg-card border border-ih-border rounded-lg shadow-ih-popover flex items-center gap-3 text-[13px]";
|
|
74394
74798
|
function SpeedModeUndoToast({ pending, onDismiss, durationMs = 3e3, placement = "floating" }) {
|
|
74395
|
-
const dismissRef =
|
|
74799
|
+
const dismissRef = useRef40(onDismiss);
|
|
74396
74800
|
dismissRef.current = onDismiss;
|
|
74397
|
-
|
|
74801
|
+
useEffect32(() => {
|
|
74398
74802
|
if (!pending) return;
|
|
74399
74803
|
const t = setTimeout(() => dismissRef.current(), durationMs);
|
|
74400
74804
|
return () => clearTimeout(t);
|
|
@@ -74486,17 +74890,17 @@ function SpeedMode({
|
|
|
74486
74890
|
const hosted = onPendingUndoChange !== void 0;
|
|
74487
74891
|
const pendingUndo = hosted ? hostUndo ?? null : ownUndo;
|
|
74488
74892
|
const setPendingUndo = hosted ? onPendingUndoChange : setOwnUndo;
|
|
74489
|
-
const undoRef =
|
|
74893
|
+
const undoRef = useRef41(pendingUndo);
|
|
74490
74894
|
undoRef.current = pendingUndo;
|
|
74491
74895
|
const [showCoach, setShowCoach] = useState36(false);
|
|
74492
|
-
|
|
74896
|
+
useEffect33(() => {
|
|
74493
74897
|
if (shouldShowSpeedModeCoach()) setShowCoach(true);
|
|
74494
74898
|
}, []);
|
|
74495
|
-
const dismissCoach =
|
|
74899
|
+
const dismissCoach = useCallback32(() => {
|
|
74496
74900
|
setShowCoach(false);
|
|
74497
74901
|
markSpeedModeCoached();
|
|
74498
74902
|
}, []);
|
|
74499
|
-
|
|
74903
|
+
useEffect33(() => {
|
|
74500
74904
|
if (!showCoach) return;
|
|
74501
74905
|
window.addEventListener("keydown", dismissCoach);
|
|
74502
74906
|
return () => window.removeEventListener("keydown", dismissCoach);
|
|
@@ -74506,10 +74910,10 @@ function SpeedMode({
|
|
|
74506
74910
|
onSwipeRight: () => onPrevItem?.(),
|
|
74507
74911
|
onLongPress: () => setShowJumpTo(true)
|
|
74508
74912
|
});
|
|
74509
|
-
|
|
74913
|
+
useEffect33(() => {
|
|
74510
74914
|
if (undoRef.current && !undoRef.current.keep) setPendingUndo(null);
|
|
74511
74915
|
}, [item?.id]);
|
|
74512
|
-
const rootRef =
|
|
74916
|
+
const rootRef = useRef41(null);
|
|
74513
74917
|
useDialogBehavior(!!item, onExit, rootRef, rootRef, { trapTab: false });
|
|
74514
74918
|
if (!item) return null;
|
|
74515
74919
|
const levels = ratingLevels && ratingLevels.length > 0 ? ratingLevels : SPEED_FALLBACK_LEVELS;
|
|
@@ -74587,7 +74991,7 @@ function SpeedMode({
|
|
|
74587
74991
|
] }),
|
|
74588
74992
|
touch && /* @__PURE__ */ jsx75(SpeedModeUndoToast, { pending: pendingUndo, onDismiss: () => setPendingUndo(null), placement: "inline" }),
|
|
74589
74993
|
touch && !finished && /* @__PURE__ */ jsx75("div", { "data-testid": "speedmode-ratings", className: "flex flex-wrap gap-2 px-4 pt-3 shrink-0", children: tiles }),
|
|
74590
|
-
/* @__PURE__ */ jsxs61("div", { className: "h-10 flex items-center justify-center text-[11px] text-ih-fg-3 border-t border-ih-border", children: [
|
|
74994
|
+
!touch && /* @__PURE__ */ jsxs61("div", { className: "h-10 flex items-center justify-center text-[11px] text-ih-fg-3 border-t border-ih-border", children: [
|
|
74591
74995
|
index_exports.editor_speedmode_footer_press(),
|
|
74592
74996
|
" ",
|
|
74593
74997
|
/* @__PURE__ */ jsx75("kbd", { className: "mx-1 px-1.5 py-0.5 bg-ih-bg-muted rounded text-[10px] font-mono border border-ih-border", children: "Z" }),
|
|
@@ -74675,6 +75079,7 @@ import { jsx as jsx76, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
|
74675
75079
|
function FooterBar({ connected = false, status, roster = [] }) {
|
|
74676
75080
|
const effectiveStatus = status ?? (connected ? "connected" : "connecting");
|
|
74677
75081
|
const [shortcutsOpen, setShortcutsOpen] = useState37(false);
|
|
75082
|
+
const fine = useHasFinePointer();
|
|
74678
75083
|
const people = [...new Map(roster.map((u) => [u.userId, u])).values()];
|
|
74679
75084
|
const { commentsLibrary } = useEditorCapabilities();
|
|
74680
75085
|
const SHORTCUTS = [
|
|
@@ -74691,8 +75096,8 @@ function FooterBar({ connected = false, status, roster = [] }) {
|
|
|
74691
75096
|
{ keys: ["\u2318", "\\"], desc: index_exports.editor_footer_shortcut_sidebar() },
|
|
74692
75097
|
{ keys: ["?"], desc: index_exports.editor_footer_shortcut_help() }
|
|
74693
75098
|
];
|
|
74694
|
-
return /* @__PURE__ */ jsxs62("div", { className: "hidden md:flex fixed bottom-0 inset-x-0 z-30 bg-ih-bg-card border-t border-ih-border
|
|
74695
|
-
/* @__PURE__ */ jsxs62("div", { className: "relative", children: [
|
|
75099
|
+
return /* @__PURE__ */ jsxs62("div", { className: "hidden md:flex fixed bottom-0 inset-x-0 z-30 bg-ih-bg-card border-t border-ih-border pl-[max(1rem,env(safe-area-inset-left))] pr-[max(1rem,env(safe-area-inset-right))] py-1.5 items-center gap-3 text-[11px] text-ih-fg-3", children: [
|
|
75100
|
+
fine && /* @__PURE__ */ jsxs62("div", { className: "relative", children: [
|
|
74696
75101
|
/* @__PURE__ */ jsx76(
|
|
74697
75102
|
Button,
|
|
74698
75103
|
{
|
|
@@ -74749,7 +75154,7 @@ function BatchActionBar({
|
|
|
74749
75154
|
value: level.id,
|
|
74750
75155
|
label: String(idx + 1),
|
|
74751
75156
|
tone: "neutral",
|
|
74752
|
-
color: getRatingColor(level.id)
|
|
75157
|
+
color: safeCssColor(getRatingColor(level.id)) ?? void 0
|
|
74753
75158
|
}));
|
|
74754
75159
|
return /* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-2 bg-ih-bg-card border-t border-ih-border px-4 py-2", children: [
|
|
74755
75160
|
/* @__PURE__ */ jsx77(
|
|
@@ -74875,12 +75280,13 @@ function InspectorToolsDock({
|
|
|
74875
75280
|
}) {
|
|
74876
75281
|
const [dockOpen, setDockOpen] = useState38(false);
|
|
74877
75282
|
const readOnly = useReadOnly();
|
|
75283
|
+
const fine = useHasFinePointer();
|
|
74878
75284
|
const TILES = [
|
|
74879
75285
|
{ id: "speed-mode", label: index_exports.editor_dock_speed_mode(), iconPath: "M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z", hotkey: "Z" },
|
|
74880
75286
|
{ id: "burst-camera", label: index_exports.editor_dock_burst_camera(), iconPath: "M6.827 6.175A2.31 2.31 0 015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316zM16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0z" },
|
|
74881
75287
|
{ id: "photo-studio", label: index_exports.editor_dock_photo_studio(), iconPath: "M9.53 16.122a3 3 0 00-5.78 1.128 2.25 2.25 0 01-2.4 2.245 4.5 4.5 0 008.4-2.245c0-.399-.078-.78-.22-1.128zm0 0a15.998 15.998 0 003.388-1.62m-5.043-.025a15.994 15.994 0 011.622-3.395m3.42 3.42a15.995 15.995 0 004.764-4.648l3.876-5.814a1.151 1.151 0 00-1.597-1.597L14.146 6.32a15.996 15.996 0 00-4.649 4.763m3.42 3.42a6.776 6.776 0 00-3.42-3.42" },
|
|
74882
75288
|
{ id: "shortcuts", label: index_exports.editor_shortcuts_label(), iconPath: "M6 6.878V6a2.25 2.25 0 012.25-2.25h7.5A2.25 2.25 0 0118 6v.878m-12 0c.235-.083.487-.128.75-.128h10.5c.263 0 .515.045.75.128m-12 0A2.25 2.25 0 004.5 9v.878m13.5-3A2.25 2.25 0 0119.5 9v.878m0 0a2.246 2.246 0 00-.75-.128H5.25c-.263 0-.515.045-.75.128m15 0A2.25 2.25 0 0121 12v6a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 18v-6c0-.98.626-1.813 1.5-2.122", hotkey: "?" }
|
|
74883
|
-
].filter((t) => (t.id !== "burst-camera" || Boolean(activeItemId)) && (!readOnly || t.id === "shortcuts"));
|
|
75289
|
+
].filter((t) => (t.id !== "burst-camera" || Boolean(activeItemId)) && (!readOnly || t.id === "shortcuts") && (fine || t.id !== "shortcuts"));
|
|
74884
75290
|
useLayer(dockOpen && !hidden, { onEscape: () => setDockOpen(false) });
|
|
74885
75291
|
if (hidden) return null;
|
|
74886
75292
|
const handlers = {
|
|
@@ -74938,10 +75344,10 @@ function resolveActivePropertyPreset(propertyType, commercialSubtype, presets) {
|
|
|
74938
75344
|
}
|
|
74939
75345
|
|
|
74940
75346
|
// src/components/editor/InspectionSettingsSheet.tsx
|
|
74941
|
-
import { useState as useState41, useEffect as
|
|
75347
|
+
import { useState as useState41, useEffect as useEffect35, useRef as useRef44, useCallback as useCallback35 } from "react";
|
|
74942
75348
|
|
|
74943
75349
|
// src/components/TemplateCombobox.tsx
|
|
74944
|
-
import { useState as useState39, useEffect as
|
|
75350
|
+
import { useState as useState39, useEffect as useEffect34, useRef as useRef42, useCallback as useCallback33 } from "react";
|
|
74945
75351
|
import { Fragment as Fragment13, jsx as jsx80, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
74946
75352
|
function TemplateCombobox({
|
|
74947
75353
|
value,
|
|
@@ -74956,23 +75362,23 @@ function TemplateCombobox({
|
|
|
74956
75362
|
const [hasMore, setHasMore] = useState39(false);
|
|
74957
75363
|
const [page, setPage] = useState39(1);
|
|
74958
75364
|
const [activeIdx, setActiveIdx] = useState39(-1);
|
|
74959
|
-
const inputRef =
|
|
74960
|
-
const containerRef =
|
|
74961
|
-
const debounceRef =
|
|
75365
|
+
const inputRef = useRef42(null);
|
|
75366
|
+
const containerRef = useRef42(null);
|
|
75367
|
+
const debounceRef = useRef42(null);
|
|
74962
75368
|
const templateSearch = useFieldDataSource().resources.templateSearch;
|
|
74963
75369
|
const [isLoading, setIsLoading] = useState39(false);
|
|
74964
75370
|
const [isLoadingMore, setIsLoadingMore] = useState39(false);
|
|
74965
|
-
const searchSeq =
|
|
74966
|
-
const moreSeq =
|
|
74967
|
-
const mounted =
|
|
74968
|
-
|
|
75371
|
+
const searchSeq = useRef42(0);
|
|
75372
|
+
const moreSeq = useRef42(0);
|
|
75373
|
+
const mounted = useRef42(true);
|
|
75374
|
+
useEffect34(() => {
|
|
74969
75375
|
mounted.current = true;
|
|
74970
75376
|
return () => {
|
|
74971
75377
|
mounted.current = false;
|
|
74972
75378
|
};
|
|
74973
75379
|
}, []);
|
|
74974
75380
|
const selectedName = [...initialTemplates, ...results].find((t) => t.id === value)?.name ?? "";
|
|
74975
|
-
const doSearch =
|
|
75381
|
+
const doSearch = useCallback33((q, pg) => {
|
|
74976
75382
|
if (!templateSearch) return;
|
|
74977
75383
|
const seq = searchSeq.current += 1;
|
|
74978
75384
|
moreSeq.current += 1;
|
|
@@ -74989,7 +75395,7 @@ function TemplateCombobox({
|
|
|
74989
75395
|
if (mounted.current && seq === searchSeq.current) setIsLoading(false);
|
|
74990
75396
|
});
|
|
74991
75397
|
}, [templateSearch]);
|
|
74992
|
-
|
|
75398
|
+
useEffect34(() => {
|
|
74993
75399
|
if (!open) return;
|
|
74994
75400
|
if (initialTemplates.length > 0 && !query) {
|
|
74995
75401
|
setResults(initialTemplates);
|
|
@@ -75001,7 +75407,7 @@ function TemplateCombobox({
|
|
|
75001
75407
|
setActiveIdx(-1);
|
|
75002
75408
|
setTimeout(() => inputRef.current?.focus(), 0);
|
|
75003
75409
|
}, [open]);
|
|
75004
|
-
|
|
75410
|
+
useEffect34(() => {
|
|
75005
75411
|
if (!open) return;
|
|
75006
75412
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
75007
75413
|
debounceRef.current = setTimeout(() => {
|
|
@@ -75013,7 +75419,7 @@ function TemplateCombobox({
|
|
|
75013
75419
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
75014
75420
|
};
|
|
75015
75421
|
}, [query, open]);
|
|
75016
|
-
|
|
75422
|
+
useEffect34(() => {
|
|
75017
75423
|
if (!open) return;
|
|
75018
75424
|
const handler = (e) => {
|
|
75019
75425
|
if (!containerRef.current?.contains(e.target)) setOpen(false);
|
|
@@ -75136,7 +75542,7 @@ function TemplateCombobox({
|
|
|
75136
75542
|
}
|
|
75137
75543
|
|
|
75138
75544
|
// src/components/media-studio/PhotoCropper.tsx
|
|
75139
|
-
import { useState as useState40, useCallback as
|
|
75545
|
+
import { useState as useState40, useCallback as useCallback34, useRef as useRef43 } from "react";
|
|
75140
75546
|
import Cropper from "react-easy-crop";
|
|
75141
75547
|
import { jsx as jsx81, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
75142
75548
|
var RATIOS = {
|
|
@@ -75172,14 +75578,14 @@ function PhotoCropper({
|
|
|
75172
75578
|
const [rotation, setRotation] = useState40(0);
|
|
75173
75579
|
const [pixels, setPixels] = useState40(null);
|
|
75174
75580
|
const [busy, setBusy] = useState40(false);
|
|
75175
|
-
const inFlight2 =
|
|
75581
|
+
const inFlight2 = useRef43(false);
|
|
75176
75582
|
const [bakeError, setBakeError] = useState40(null);
|
|
75177
75583
|
const [sourceLongEdge, setSourceLongEdge] = useState40(void 0);
|
|
75178
75584
|
const isFree = aspectKey === "free";
|
|
75179
75585
|
const baseRatio = isFree ? void 0 : RATIOS[aspectKey];
|
|
75180
75586
|
const ratio = baseRatio == null ? void 0 : portrait ? 1 / baseRatio : baseRatio;
|
|
75181
|
-
const onCropComplete =
|
|
75182
|
-
const onMediaLoaded =
|
|
75587
|
+
const onCropComplete = useCallback34((_a, areaPixels) => setPixels(areaPixels), []);
|
|
75588
|
+
const onMediaLoaded = useCallback34((mediaSize) => {
|
|
75183
75589
|
setSourceLongEdge(Math.max(mediaSize.naturalWidth, mediaSize.naturalHeight));
|
|
75184
75590
|
}, []);
|
|
75185
75591
|
async function handleSave() {
|
|
@@ -75342,14 +75748,14 @@ function InspectionSettingsSheet({ open, onClose, inspectionId, onTemplateApplie
|
|
|
75342
75748
|
requireDefectFieldsOverride: "",
|
|
75343
75749
|
profileOverride: ""
|
|
75344
75750
|
});
|
|
75345
|
-
const templateIdAtOpen =
|
|
75751
|
+
const templateIdAtOpen = useRef44("");
|
|
75346
75752
|
const { run: runSave } = useFieldCommand(inspectionId);
|
|
75347
|
-
const templateChangedAtSubmit =
|
|
75348
|
-
const mounted =
|
|
75349
|
-
const idleTimer =
|
|
75350
|
-
const onTemplateAppliedRef =
|
|
75753
|
+
const templateChangedAtSubmit = useRef44(false);
|
|
75754
|
+
const mounted = useRef44(true);
|
|
75755
|
+
const idleTimer = useRef44(void 0);
|
|
75756
|
+
const onTemplateAppliedRef = useRef44(onTemplateApplied);
|
|
75351
75757
|
onTemplateAppliedRef.current = onTemplateApplied;
|
|
75352
|
-
|
|
75758
|
+
useEffect35(() => {
|
|
75353
75759
|
mounted.current = true;
|
|
75354
75760
|
return () => {
|
|
75355
75761
|
mounted.current = false;
|
|
@@ -75360,10 +75766,10 @@ function InspectionSettingsSheet({ open, onClose, inspectionId, onTemplateApplie
|
|
|
75360
75766
|
const [coverKey, setCoverKey] = useState41("");
|
|
75361
75767
|
const { run: runCover, busy: coverBusy } = useFieldCommand(inspectionId);
|
|
75362
75768
|
const [uploadingCover, setUploadingCover] = useState41(false);
|
|
75363
|
-
const coverFileRef =
|
|
75769
|
+
const coverFileRef = useRef44(null);
|
|
75364
75770
|
const [cropSource, setCropSource] = useState41(null);
|
|
75365
75771
|
const [originalQuality, setOriginalQuality] = useState41(false);
|
|
75366
|
-
|
|
75772
|
+
useEffect35(() => {
|
|
75367
75773
|
try {
|
|
75368
75774
|
setOriginalQuality(localStorage.getItem(ORIGINAL_QUALITY_KEY) === "1");
|
|
75369
75775
|
} catch {
|
|
@@ -75378,7 +75784,7 @@ function InspectionSettingsSheet({ open, onClose, inspectionId, onTemplateApplie
|
|
|
75378
75784
|
} catch {
|
|
75379
75785
|
}
|
|
75380
75786
|
}
|
|
75381
|
-
const applyLoaded =
|
|
75787
|
+
const applyLoaded = useCallback35((d) => {
|
|
75382
75788
|
const insp = d.inspection;
|
|
75383
75789
|
if (insp) {
|
|
75384
75790
|
const loadedTemplateId = insp.templateId || "";
|
|
@@ -75396,8 +75802,8 @@ function InspectionSettingsSheet({ open, onClose, inspectionId, onTemplateApplie
|
|
|
75396
75802
|
setCoverKey(insp?.coverPhotoId ?? insp?.coverPhoto ?? "");
|
|
75397
75803
|
setLoading(false);
|
|
75398
75804
|
}, []);
|
|
75399
|
-
const loadSeq =
|
|
75400
|
-
const loadSheet =
|
|
75805
|
+
const loadSeq = useRef44(0);
|
|
75806
|
+
const loadSheet = useCallback35(() => {
|
|
75401
75807
|
const seq = loadSeq.current += 1;
|
|
75402
75808
|
setLoading(true);
|
|
75403
75809
|
setLoadFailed(false);
|
|
@@ -75411,7 +75817,7 @@ function InspectionSettingsSheet({ open, onClose, inspectionId, onTemplateApplie
|
|
|
75411
75817
|
applyLoaded(d);
|
|
75412
75818
|
});
|
|
75413
75819
|
}, [sheet, inspectionId, applyLoaded]);
|
|
75414
|
-
|
|
75820
|
+
useEffect35(() => {
|
|
75415
75821
|
if (open && inspectionId) loadSheet();
|
|
75416
75822
|
return () => {
|
|
75417
75823
|
loadSeq.current += 1;
|
|
@@ -75644,7 +76050,7 @@ function InspectionSettingsSheet({ open, onClose, inspectionId, onTemplateApplie
|
|
|
75644
76050
|
}
|
|
75645
76051
|
|
|
75646
76052
|
// src/components/media-studio/VideoCapture.tsx
|
|
75647
|
-
import { useRef as
|
|
76053
|
+
import { useRef as useRef45, useState as useState42 } from "react";
|
|
75648
76054
|
import { jsx as jsx84, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
75649
76055
|
var MAX_VIDEO_BYTES = 200 * 1024 * 1024;
|
|
75650
76056
|
var MAX_VIDEO_SEC = 30;
|
|
@@ -75660,7 +76066,7 @@ function validateVideoFile(file) {
|
|
|
75660
76066
|
}
|
|
75661
76067
|
function VideoCapture({ inspectionId, provider, itemId, onClose, onUploaded }) {
|
|
75662
76068
|
const video = useFieldDataSource().resources.video;
|
|
75663
|
-
const inputRef =
|
|
76069
|
+
const inputRef = useRef45(null);
|
|
75664
76070
|
const [phase, setPhase] = useState42("pick");
|
|
75665
76071
|
const [error, setError] = useState42(null);
|
|
75666
76072
|
const [progress, setProgress] = useState42(0);
|
|
@@ -76081,7 +76487,7 @@ function AddMediaChooser({ onClose, onTakePhoto, onAddFromLibrary, onPickVideo }
|
|
|
76081
76487
|
}
|
|
76082
76488
|
|
|
76083
76489
|
// src/hooks/useStructureEdit.ts
|
|
76084
|
-
import { useState as useState43, useCallback as
|
|
76490
|
+
import { useState as useState43, useCallback as useCallback37, useEffect as useEffect36, useRef as useRef46 } from "react";
|
|
76085
76491
|
|
|
76086
76492
|
// src/shared/structure-ops.ts
|
|
76087
76493
|
var SECTION_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -76140,8 +76546,8 @@ function buildNewItem(label, type) {
|
|
|
76140
76546
|
}
|
|
76141
76547
|
return { id, label, type };
|
|
76142
76548
|
}
|
|
76143
|
-
function stripRuntimeKeys(
|
|
76144
|
-
const clone = structuredClone(
|
|
76549
|
+
function stripRuntimeKeys(snapshot2) {
|
|
76550
|
+
const clone = structuredClone(snapshot2);
|
|
76145
76551
|
clone.sections = clone.sections.map((rawSec) => {
|
|
76146
76552
|
const sec = {};
|
|
76147
76553
|
for (const key of SECTION_KEYS) {
|
|
@@ -76165,20 +76571,20 @@ function stripRuntimeKeys(snapshot) {
|
|
|
76165
76571
|
});
|
|
76166
76572
|
return clone;
|
|
76167
76573
|
}
|
|
76168
|
-
function addSection(
|
|
76574
|
+
function addSection(snapshot2, title) {
|
|
76169
76575
|
const newSec = { id: newId("sec"), title, items: [] };
|
|
76170
76576
|
const result = {
|
|
76171
|
-
...
|
|
76172
|
-
sections: [...
|
|
76577
|
+
...snapshot2,
|
|
76578
|
+
sections: [...snapshot2.sections, newSec]
|
|
76173
76579
|
};
|
|
76174
76580
|
return stripRuntimeKeys(result);
|
|
76175
76581
|
}
|
|
76176
|
-
function duplicateSection(
|
|
76177
|
-
const idx =
|
|
76582
|
+
function duplicateSection(snapshot2, sectionId) {
|
|
76583
|
+
const idx = snapshot2.sections.findIndex((s) => s.id === sectionId);
|
|
76178
76584
|
if (idx === -1) {
|
|
76179
|
-
return stripRuntimeKeys({ ...
|
|
76585
|
+
return stripRuntimeKeys({ ...snapshot2, sections: [...snapshot2.sections] });
|
|
76180
76586
|
}
|
|
76181
|
-
const source =
|
|
76587
|
+
const source = snapshot2.sections[idx];
|
|
76182
76588
|
const idMap = new Map(source.items.map((item) => [item.id, newId("item")]));
|
|
76183
76589
|
const renamed = source.items.map((item) => ({
|
|
76184
76590
|
...item,
|
|
@@ -76191,74 +76597,74 @@ function duplicateSection(snapshot, sectionId) {
|
|
|
76191
76597
|
items: clonedItems
|
|
76192
76598
|
};
|
|
76193
76599
|
const sections = [
|
|
76194
|
-
...
|
|
76600
|
+
...snapshot2.sections.slice(0, idx + 1),
|
|
76195
76601
|
cloned,
|
|
76196
|
-
...
|
|
76602
|
+
...snapshot2.sections.slice(idx + 1)
|
|
76197
76603
|
];
|
|
76198
|
-
return stripRuntimeKeys({ ...
|
|
76604
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76199
76605
|
}
|
|
76200
|
-
function deleteSection(
|
|
76201
|
-
const sections =
|
|
76202
|
-
return stripRuntimeKeys({ ...
|
|
76606
|
+
function deleteSection(snapshot2, sectionId) {
|
|
76607
|
+
const sections = snapshot2.sections.filter((s) => s.id !== sectionId);
|
|
76608
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76203
76609
|
}
|
|
76204
|
-
function moveSection(
|
|
76205
|
-
const idx =
|
|
76610
|
+
function moveSection(snapshot2, sectionId, dir) {
|
|
76611
|
+
const idx = snapshot2.sections.findIndex((s) => s.id === sectionId);
|
|
76206
76612
|
if (idx === -1) {
|
|
76207
|
-
return stripRuntimeKeys({ ...
|
|
76613
|
+
return stripRuntimeKeys({ ...snapshot2, sections: [...snapshot2.sections] });
|
|
76208
76614
|
}
|
|
76209
76615
|
const targetIdx = idx + dir;
|
|
76210
|
-
if (targetIdx < 0 || targetIdx >=
|
|
76211
|
-
return stripRuntimeKeys({ ...
|
|
76616
|
+
if (targetIdx < 0 || targetIdx >= snapshot2.sections.length) {
|
|
76617
|
+
return stripRuntimeKeys({ ...snapshot2, sections: [...snapshot2.sections] });
|
|
76212
76618
|
}
|
|
76213
|
-
const sections = [...
|
|
76619
|
+
const sections = [...snapshot2.sections];
|
|
76214
76620
|
[sections[idx], sections[targetIdx]] = [sections[targetIdx], sections[idx]];
|
|
76215
|
-
return stripRuntimeKeys({ ...
|
|
76621
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76216
76622
|
}
|
|
76217
|
-
function reorderSection(
|
|
76218
|
-
const from =
|
|
76219
|
-
const to =
|
|
76623
|
+
function reorderSection(snapshot2, fromId, toId) {
|
|
76624
|
+
const from = snapshot2.sections.findIndex((s) => s.id === fromId);
|
|
76625
|
+
const to = snapshot2.sections.findIndex((s) => s.id === toId);
|
|
76220
76626
|
if (from === -1 || to === -1 || from === to) {
|
|
76221
|
-
return stripRuntimeKeys({ ...
|
|
76627
|
+
return stripRuntimeKeys({ ...snapshot2, sections: [...snapshot2.sections] });
|
|
76222
76628
|
}
|
|
76223
|
-
const sections = [...
|
|
76629
|
+
const sections = [...snapshot2.sections];
|
|
76224
76630
|
const [moved] = sections.splice(from, 1);
|
|
76225
76631
|
sections.splice(to, 0, moved);
|
|
76226
|
-
return stripRuntimeKeys({ ...
|
|
76632
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76227
76633
|
}
|
|
76228
|
-
function renameSection(
|
|
76229
|
-
const sections =
|
|
76230
|
-
return stripRuntimeKeys({ ...
|
|
76634
|
+
function renameSection(snapshot2, sectionId, title) {
|
|
76635
|
+
const sections = snapshot2.sections.map((s) => s.id === sectionId ? { ...s, title } : s);
|
|
76636
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76231
76637
|
}
|
|
76232
|
-
function mapItems(
|
|
76233
|
-
const sections =
|
|
76234
|
-
return stripRuntimeKeys({ ...
|
|
76638
|
+
function mapItems(snapshot2, sectionId, fn) {
|
|
76639
|
+
const sections = snapshot2.sections.map((sec) => sec.id !== sectionId ? sec : { ...sec, items: fn(sec.items) });
|
|
76640
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76235
76641
|
}
|
|
76236
|
-
function addItem(
|
|
76237
|
-
return mapItems(
|
|
76642
|
+
function addItem(snapshot2, sectionId, label, type, seed = {}) {
|
|
76643
|
+
return mapItems(snapshot2, sectionId, (items) => [...items, { ...buildNewItem(label, type), ...seed, parentId: null }]);
|
|
76238
76644
|
}
|
|
76239
|
-
function duplicateItem(
|
|
76240
|
-
return mapItems(
|
|
76645
|
+
function duplicateItem(snapshot2, sectionId, itemId) {
|
|
76646
|
+
return mapItems(snapshot2, sectionId, (items) => duplicateSubtree(items, itemId, () => newId("item")));
|
|
76241
76647
|
}
|
|
76242
|
-
function deleteItem(
|
|
76243
|
-
return mapItems(
|
|
76648
|
+
function deleteItem(snapshot2, sectionId, itemId) {
|
|
76649
|
+
return mapItems(snapshot2, sectionId, (items) => deleteSubtree(items, itemId));
|
|
76244
76650
|
}
|
|
76245
|
-
function moveItem(
|
|
76246
|
-
return mapItems(
|
|
76651
|
+
function moveItem(snapshot2, sectionId, itemId, dir) {
|
|
76652
|
+
return mapItems(snapshot2, sectionId, (items) => moveSubtreeAmongSiblings(items, itemId, dir));
|
|
76247
76653
|
}
|
|
76248
|
-
function renameItem(
|
|
76249
|
-
const sections =
|
|
76654
|
+
function renameItem(snapshot2, sectionId, itemId, label) {
|
|
76655
|
+
const sections = snapshot2.sections.map((sec) => {
|
|
76250
76656
|
if (sec.id !== sectionId) return sec;
|
|
76251
76657
|
return { ...sec, items: sec.items.map((it) => it.id === itemId ? { ...it, label } : it) };
|
|
76252
76658
|
});
|
|
76253
|
-
return stripRuntimeKeys({ ...
|
|
76659
|
+
return stripRuntimeKeys({ ...snapshot2, sections });
|
|
76254
76660
|
}
|
|
76255
76661
|
|
|
76256
76662
|
// src/hooks/useRestructureSubmit.ts
|
|
76257
|
-
import { useCallback as
|
|
76663
|
+
import { useCallback as useCallback36 } from "react";
|
|
76258
76664
|
function useRestructureSubmit(inspectionId) {
|
|
76259
76665
|
const { submit } = useLatestWinsCommand(inspectionId);
|
|
76260
76666
|
const { notify } = useFieldDataSource();
|
|
76261
|
-
return
|
|
76667
|
+
return useCallback36(
|
|
76262
76668
|
async (cmd) => {
|
|
76263
76669
|
const result = await submit(cmd);
|
|
76264
76670
|
if (!isIgnored(result) && !result.ok) notify(result.error || index_exports.editor_structure_save_failed(), "error");
|
|
@@ -76278,15 +76684,15 @@ function useStructureEdit({
|
|
|
76278
76684
|
activeUnitId = null,
|
|
76279
76685
|
onApply
|
|
76280
76686
|
}) {
|
|
76281
|
-
const snapshotRef =
|
|
76282
|
-
|
|
76687
|
+
const snapshotRef = useRef46(rawSnapshot);
|
|
76688
|
+
useEffect36(() => {
|
|
76283
76689
|
snapshotRef.current = rawSnapshot;
|
|
76284
76690
|
}, [rawSnapshot]);
|
|
76285
76691
|
const submitRestructure = useRestructureSubmit(inspectionId);
|
|
76286
76692
|
const { run: saveTemplate } = useFieldCommand(inspectionId);
|
|
76287
|
-
const onApplyRef =
|
|
76693
|
+
const onApplyRef = useRef46(onApply);
|
|
76288
76694
|
onApplyRef.current = onApply;
|
|
76289
|
-
const applyStructure =
|
|
76695
|
+
const applyStructure = useCallback37(
|
|
76290
76696
|
(next) => {
|
|
76291
76697
|
onApplyRef.current?.(next);
|
|
76292
76698
|
snapshotRef.current = next;
|
|
@@ -76295,7 +76701,7 @@ function useStructureEdit({
|
|
|
76295
76701
|
[submitRestructure, collabEditing]
|
|
76296
76702
|
);
|
|
76297
76703
|
const [deletePending, setDeletePending] = useState43(null);
|
|
76298
|
-
const itemImpact =
|
|
76704
|
+
const itemImpact = useCallback37(
|
|
76299
76705
|
(sectionId, itemId) => {
|
|
76300
76706
|
const ck = findingKey(activeUnitId, sectionId, itemId);
|
|
76301
76707
|
const r = results[ck] || (activeUnitId == null ? results[itemId] : void 0);
|
|
@@ -76308,7 +76714,7 @@ function useStructureEdit({
|
|
|
76308
76714
|
},
|
|
76309
76715
|
[results, activeUnitId]
|
|
76310
76716
|
);
|
|
76311
|
-
const handleDeleteSection =
|
|
76717
|
+
const handleDeleteSection = useCallback37(
|
|
76312
76718
|
(id) => {
|
|
76313
76719
|
const sec = snapshotRef.current.sections.find((s) => s.id === id);
|
|
76314
76720
|
if (!sec) return;
|
|
@@ -76331,7 +76737,7 @@ function useStructureEdit({
|
|
|
76331
76737
|
},
|
|
76332
76738
|
[itemImpact]
|
|
76333
76739
|
);
|
|
76334
|
-
const handleDeleteItem =
|
|
76740
|
+
const handleDeleteItem = useCallback37(
|
|
76335
76741
|
(sectionId, itemId) => {
|
|
76336
76742
|
const sec = snapshotRef.current.sections.find((s) => s.id === sectionId);
|
|
76337
76743
|
const items = sec?.items ?? [];
|
|
@@ -76349,7 +76755,7 @@ function useStructureEdit({
|
|
|
76349
76755
|
},
|
|
76350
76756
|
[itemImpact]
|
|
76351
76757
|
);
|
|
76352
|
-
const confirmDelete =
|
|
76758
|
+
const confirmDelete = useCallback37(() => {
|
|
76353
76759
|
const pending = deletePending;
|
|
76354
76760
|
setDeletePending(null);
|
|
76355
76761
|
if (!pending) return;
|
|
@@ -76359,74 +76765,74 @@ function useStructureEdit({
|
|
|
76359
76765
|
applyStructure(deleteSection(snapshotRef.current, pending.sectionId));
|
|
76360
76766
|
}
|
|
76361
76767
|
}, [deletePending, applyStructure]);
|
|
76362
|
-
const cancelDelete =
|
|
76768
|
+
const cancelDelete = useCallback37(() => {
|
|
76363
76769
|
setDeletePending(null);
|
|
76364
76770
|
}, []);
|
|
76365
76771
|
const [addSectionPromptOpen, setAddSectionPromptOpen] = useState43(false);
|
|
76366
76772
|
const [addSectionTitle, setAddSectionTitle] = useState43("");
|
|
76367
|
-
const openAddSectionPrompt =
|
|
76773
|
+
const openAddSectionPrompt = useCallback37(() => {
|
|
76368
76774
|
setAddSectionTitle("");
|
|
76369
76775
|
setAddSectionPromptOpen(true);
|
|
76370
76776
|
}, []);
|
|
76371
|
-
const closeAddSectionPrompt =
|
|
76777
|
+
const closeAddSectionPrompt = useCallback37(() => {
|
|
76372
76778
|
setAddSectionPromptOpen(false);
|
|
76373
76779
|
}, []);
|
|
76374
|
-
const submitAddSection =
|
|
76780
|
+
const submitAddSection = useCallback37(() => {
|
|
76375
76781
|
const title = addSectionTitle.trim() || index_exports.helper_structure_new_section_default();
|
|
76376
76782
|
setAddSectionPromptOpen(false);
|
|
76377
76783
|
setAddSectionTitle("");
|
|
76378
76784
|
applyStructure(addSection(snapshotRef.current, title));
|
|
76379
76785
|
}, [addSectionTitle, applyStructure]);
|
|
76380
|
-
const handleDuplicateSection =
|
|
76786
|
+
const handleDuplicateSection = useCallback37(
|
|
76381
76787
|
(id) => {
|
|
76382
76788
|
applyStructure(duplicateSection(snapshotRef.current, id));
|
|
76383
76789
|
},
|
|
76384
76790
|
[applyStructure]
|
|
76385
76791
|
);
|
|
76386
|
-
const handleMoveSection =
|
|
76792
|
+
const handleMoveSection = useCallback37(
|
|
76387
76793
|
(id, dir) => {
|
|
76388
76794
|
applyStructure(moveSection(snapshotRef.current, id, dir));
|
|
76389
76795
|
},
|
|
76390
76796
|
[applyStructure]
|
|
76391
76797
|
);
|
|
76392
|
-
const handleReorderSection =
|
|
76798
|
+
const handleReorderSection = useCallback37(
|
|
76393
76799
|
(fromId, toId) => {
|
|
76394
76800
|
applyStructure(reorderSection(snapshotRef.current, fromId, toId));
|
|
76395
76801
|
},
|
|
76396
76802
|
[applyStructure]
|
|
76397
76803
|
);
|
|
76398
|
-
const handleRenameSection =
|
|
76804
|
+
const handleRenameSection = useCallback37(
|
|
76399
76805
|
(id, title) => {
|
|
76400
76806
|
applyStructure(renameSection(snapshotRef.current, id, title));
|
|
76401
76807
|
},
|
|
76402
76808
|
[applyStructure]
|
|
76403
76809
|
);
|
|
76404
|
-
const handleDuplicateItem =
|
|
76810
|
+
const handleDuplicateItem = useCallback37(
|
|
76405
76811
|
(sectionId, itemId) => {
|
|
76406
76812
|
applyStructure(duplicateItem(snapshotRef.current, sectionId, itemId));
|
|
76407
76813
|
},
|
|
76408
76814
|
[applyStructure]
|
|
76409
76815
|
);
|
|
76410
|
-
const handleMoveItem =
|
|
76816
|
+
const handleMoveItem = useCallback37(
|
|
76411
76817
|
(sectionId, itemId, dir) => {
|
|
76412
76818
|
applyStructure(moveItem(snapshotRef.current, sectionId, itemId, dir));
|
|
76413
76819
|
},
|
|
76414
76820
|
[applyStructure]
|
|
76415
76821
|
);
|
|
76416
|
-
const handleRenameItem =
|
|
76822
|
+
const handleRenameItem = useCallback37(
|
|
76417
76823
|
(sectionId, itemId, label) => {
|
|
76418
76824
|
applyStructure(renameItem(snapshotRef.current, sectionId, itemId, label));
|
|
76419
76825
|
},
|
|
76420
76826
|
[applyStructure]
|
|
76421
76827
|
);
|
|
76422
76828
|
const [addItemPending, setAddItemPending] = useState43(null);
|
|
76423
|
-
const openAddItemPrompt =
|
|
76829
|
+
const openAddItemPrompt = useCallback37((sectionId) => {
|
|
76424
76830
|
setAddItemPending({ sectionId });
|
|
76425
76831
|
}, []);
|
|
76426
|
-
const closeAddItemPrompt =
|
|
76832
|
+
const closeAddItemPrompt = useCallback37(() => {
|
|
76427
76833
|
setAddItemPending(null);
|
|
76428
76834
|
}, []);
|
|
76429
|
-
const submitAddItem =
|
|
76835
|
+
const submitAddItem = useCallback37(
|
|
76430
76836
|
(label, type) => {
|
|
76431
76837
|
const pending = addItemPending;
|
|
76432
76838
|
setAddItemPending(null);
|
|
@@ -76438,25 +76844,25 @@ function useStructureEdit({
|
|
|
76438
76844
|
);
|
|
76439
76845
|
const [saveTemplatePending, setSaveTemplatePending] = useState43(null);
|
|
76440
76846
|
const [saveTemplateName, setSaveTemplateName] = useState43("");
|
|
76441
|
-
const openSaveTemplate =
|
|
76847
|
+
const openSaveTemplate = useCallback37((mode) => {
|
|
76442
76848
|
setSaveTemplateName("");
|
|
76443
76849
|
setSaveTemplatePending({ mode });
|
|
76444
76850
|
}, []);
|
|
76445
|
-
const closeSaveTemplate =
|
|
76851
|
+
const closeSaveTemplate = useCallback37(() => {
|
|
76446
76852
|
setSaveTemplatePending(null);
|
|
76447
76853
|
}, []);
|
|
76448
|
-
const submitSaveTemplate =
|
|
76854
|
+
const submitSaveTemplate = useCallback37(() => {
|
|
76449
76855
|
const pending = saveTemplatePending;
|
|
76450
76856
|
setSaveTemplatePending(null);
|
|
76451
76857
|
if (!pending) return;
|
|
76452
|
-
const
|
|
76858
|
+
const snapshot2 = snapshotRef.current;
|
|
76453
76859
|
void saveTemplate(
|
|
76454
76860
|
pending.mode === "new" ? {
|
|
76455
76861
|
type: "save-structure-template",
|
|
76456
76862
|
mode: "new",
|
|
76457
|
-
snapshot,
|
|
76863
|
+
snapshot: snapshot2,
|
|
76458
76864
|
name: saveTemplateName.trim() || index_exports.helper_structure_custom_template_default()
|
|
76459
|
-
} : { type: "save-structure-template", mode: "back", snapshot, templateId: templateId ?? "" }
|
|
76865
|
+
} : { type: "save-structure-template", mode: "back", snapshot: snapshot2, templateId: templateId ?? "" }
|
|
76460
76866
|
);
|
|
76461
76867
|
}, [saveTemplatePending, saveTemplateName, templateId, saveTemplate]);
|
|
76462
76868
|
return {
|
|
@@ -76498,7 +76904,7 @@ function useStructureEdit({
|
|
|
76498
76904
|
}
|
|
76499
76905
|
|
|
76500
76906
|
// src/components/editor/PublishModal.tsx
|
|
76501
|
-
import { useEffect as
|
|
76907
|
+
import { useEffect as useEffect37, useRef as useRef47, useState as useState44 } from "react";
|
|
76502
76908
|
|
|
76503
76909
|
// src/shared/display-prefs.ts
|
|
76504
76910
|
var DEFAULT_DISPLAY_PREFS = { dateFormat: "us", timeFormat: "12h" };
|
|
@@ -76568,15 +76974,15 @@ function PublishModal({ open, inspectionId, progress, status, publishError, isSu
|
|
|
76568
76974
|
const [receiptOpen, setReceiptOpen] = useState44(false);
|
|
76569
76975
|
const latch = useActionLatch(isSubmitting);
|
|
76570
76976
|
const publish = (markComplete) => latch(() => onPublish(markComplete, extras()));
|
|
76571
|
-
const submitSeen =
|
|
76977
|
+
const submitSeen = useRef47(false);
|
|
76572
76978
|
const [inspectionHref, setInspectionHref] = useState44(null);
|
|
76573
|
-
|
|
76979
|
+
useEffect37(() => {
|
|
76574
76980
|
if (isSubmitting) submitSeen.current = true;
|
|
76575
76981
|
}, [isSubmitting]);
|
|
76576
|
-
|
|
76982
|
+
useEffect37(() => {
|
|
76577
76983
|
if (publishError) submitSeen.current = false;
|
|
76578
76984
|
}, [publishError]);
|
|
76579
|
-
|
|
76985
|
+
useEffect37(() => {
|
|
76580
76986
|
if (open || !submitSeen.current) return;
|
|
76581
76987
|
submitSeen.current = false;
|
|
76582
76988
|
if (publishError) return;
|
|
@@ -76709,16 +77115,17 @@ function PublishModal({ open, inspectionId, progress, status, publishError, isSu
|
|
|
76709
77115
|
}
|
|
76710
77116
|
|
|
76711
77117
|
// src/components/SignaturePad.tsx
|
|
76712
|
-
import { useRef as
|
|
77118
|
+
import { useRef as useRef48, useState as useState45, useEffect as useEffect38 } from "react";
|
|
76713
77119
|
import { jsx as jsx88, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
77120
|
+
var PAPER = { backgroundColor: "#ffffff", borderColor: "#cbd5e1" };
|
|
76714
77121
|
function SignaturePad({ onSubmit, onCancel, label }) {
|
|
76715
|
-
const canvasRef =
|
|
77122
|
+
const canvasRef = useRef48(null);
|
|
76716
77123
|
const [drawing, setDrawing] = useState45(false);
|
|
76717
77124
|
const [hasInk, setHasInk] = useState45(false);
|
|
76718
77125
|
const [busy, setBusy] = useState45(false);
|
|
76719
|
-
const inFlight2 =
|
|
77126
|
+
const inFlight2 = useRef48(false);
|
|
76720
77127
|
const [error, setError] = useState45(null);
|
|
76721
|
-
|
|
77128
|
+
useEffect38(() => {
|
|
76722
77129
|
const canvas = canvasRef.current;
|
|
76723
77130
|
if (!canvas) return;
|
|
76724
77131
|
const ctx = canvas.getContext("2d");
|
|
@@ -76731,7 +77138,9 @@ function SignaturePad({ onSubmit, onCancel, label }) {
|
|
|
76731
77138
|
const canvas = canvasRef.current;
|
|
76732
77139
|
const rect = canvas.getBoundingClientRect();
|
|
76733
77140
|
const point = "touches" in e ? e.touches[0] : e;
|
|
76734
|
-
|
|
77141
|
+
const sx = rect.width > 0 ? canvas.width / rect.width : 1;
|
|
77142
|
+
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
77143
|
+
return { x: (point.clientX - rect.left) * sx, y: (point.clientY - rect.top) * sy };
|
|
76735
77144
|
};
|
|
76736
77145
|
const start = (e) => {
|
|
76737
77146
|
const ctx = canvasRef.current?.getContext("2d");
|
|
@@ -76784,7 +77193,8 @@ function SignaturePad({ onSubmit, onCancel, label }) {
|
|
|
76784
77193
|
ref: canvasRef,
|
|
76785
77194
|
width: 400,
|
|
76786
77195
|
height: 150,
|
|
76787
|
-
|
|
77196
|
+
style: PAPER,
|
|
77197
|
+
className: "block w-full max-w-[400px] border rounded cursor-crosshair touch-none",
|
|
76788
77198
|
onMouseDown: start,
|
|
76789
77199
|
onMouseMove: move,
|
|
76790
77200
|
onMouseUp: end,
|
|
@@ -76839,7 +77249,7 @@ function SignModal({ open, onSubmit, onCancel, failed }) {
|
|
|
76839
77249
|
}
|
|
76840
77250
|
|
|
76841
77251
|
// src/components/collab/VersionHistoryPanel.tsx
|
|
76842
|
-
import { useCallback as
|
|
77252
|
+
import { useCallback as useCallback39, useEffect as useEffect40, useState as useState46 } from "react";
|
|
76843
77253
|
|
|
76844
77254
|
// src/shared/snapshot-diff.ts
|
|
76845
77255
|
var SCALAR_FIELDS = [
|
|
@@ -77123,20 +77533,20 @@ function VersionCompare({
|
|
|
77123
77533
|
}
|
|
77124
77534
|
|
|
77125
77535
|
// src/components/collab/useReturnFocusAfterCompare.ts
|
|
77126
|
-
import { useCallback as
|
|
77536
|
+
import { useCallback as useCallback38, useEffect as useEffect39, useRef as useRef49 } from "react";
|
|
77127
77537
|
function useReturnFocusAfterCompare(confirmOpen) {
|
|
77128
|
-
const opener =
|
|
77129
|
-
const fromCompare =
|
|
77130
|
-
|
|
77538
|
+
const opener = useRef49(null);
|
|
77539
|
+
const fromCompare = useRef49(false);
|
|
77540
|
+
useEffect39(() => {
|
|
77131
77541
|
if (confirmOpen || !fromCompare.current) return;
|
|
77132
77542
|
fromCompare.current = false;
|
|
77133
77543
|
const active = document.activeElement;
|
|
77134
77544
|
if (opener.current?.isConnected && (!active || active === document.body)) opener.current.focus();
|
|
77135
77545
|
}, [confirmOpen]);
|
|
77136
|
-
const rememberOpener =
|
|
77546
|
+
const rememberOpener = useCallback38((el) => {
|
|
77137
77547
|
opener.current = el;
|
|
77138
77548
|
}, []);
|
|
77139
|
-
const markFromCompare =
|
|
77549
|
+
const markFromCompare = useCallback38(() => {
|
|
77140
77550
|
fromCompare.current = true;
|
|
77141
77551
|
}, []);
|
|
77142
77552
|
return { rememberOpener, markFromCompare };
|
|
@@ -77208,7 +77618,7 @@ function VersionHistoryPanel({
|
|
|
77208
77618
|
dateFormat: session.tenantDateFormat,
|
|
77209
77619
|
timeFormat: session.tenantTimeFormat
|
|
77210
77620
|
};
|
|
77211
|
-
const handleCompare =
|
|
77621
|
+
const handleCompare = useCallback39(
|
|
77212
77622
|
async (seq) => {
|
|
77213
77623
|
if (!currentResults) return;
|
|
77214
77624
|
setCompareSeq(seq);
|
|
@@ -77231,7 +77641,7 @@ function VersionHistoryPanel({
|
|
|
77231
77641
|
},
|
|
77232
77642
|
[versionHistory, inspectionId, currentResults]
|
|
77233
77643
|
);
|
|
77234
|
-
const handleRecoverField =
|
|
77644
|
+
const handleRecoverField = useCallback39(
|
|
77235
77645
|
(findingKey3, field, value) => {
|
|
77236
77646
|
if (!doc) return;
|
|
77237
77647
|
if (!SCALAR_FIELD_SET.has(field)) return;
|
|
@@ -77253,7 +77663,7 @@ function VersionHistoryPanel({
|
|
|
77253
77663
|
},
|
|
77254
77664
|
[doc, currentResults]
|
|
77255
77665
|
);
|
|
77256
|
-
const loadSnapshots =
|
|
77666
|
+
const loadSnapshots = useCallback39(async () => {
|
|
77257
77667
|
setLoadState("loading");
|
|
77258
77668
|
try {
|
|
77259
77669
|
const listed = await versionHistory?.list(inspectionId);
|
|
@@ -77265,7 +77675,7 @@ function VersionHistoryPanel({
|
|
|
77265
77675
|
setLoadState("error");
|
|
77266
77676
|
}
|
|
77267
77677
|
}, [versionHistory, inspectionId]);
|
|
77268
|
-
|
|
77678
|
+
useEffect40(() => {
|
|
77269
77679
|
if (!open) return;
|
|
77270
77680
|
setConfirmSeq(null);
|
|
77271
77681
|
setRestoreError(null);
|
|
@@ -77519,20 +77929,20 @@ function AddGroupInstanceHost({
|
|
|
77519
77929
|
}
|
|
77520
77930
|
|
|
77521
77931
|
// src/components/editor/BurstCamera.tsx
|
|
77522
|
-
import { useState as useState48, useRef as
|
|
77932
|
+
import { useState as useState48, useRef as useRef50, useCallback as useCallback40, useEffect as useEffect41 } from "react";
|
|
77523
77933
|
import { jsx as jsx94, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
77524
77934
|
function BurstCamera({ open, onClose, onCommit }) {
|
|
77525
|
-
const videoRef =
|
|
77526
|
-
const canvasRef =
|
|
77527
|
-
const streamRef =
|
|
77528
|
-
const burstTimerRef =
|
|
77935
|
+
const videoRef = useRef50(null);
|
|
77936
|
+
const canvasRef = useRef50(null);
|
|
77937
|
+
const streamRef = useRef50(null);
|
|
77938
|
+
const burstTimerRef = useRef50(null);
|
|
77529
77939
|
const [captures, setCaptures] = useState48([]);
|
|
77530
77940
|
const [burstActive, setBurstActive] = useState48(false);
|
|
77531
77941
|
const [burstCount, setBurstCount] = useState48(0);
|
|
77532
77942
|
const [uploading, setUploading] = useState48(false);
|
|
77533
|
-
const committing =
|
|
77943
|
+
const committing = useRef50(false);
|
|
77534
77944
|
const [facing, setFacing] = useState48("environment");
|
|
77535
|
-
const startCamera =
|
|
77945
|
+
const startCamera = useCallback40(async (facingMode) => {
|
|
77536
77946
|
try {
|
|
77537
77947
|
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode } });
|
|
77538
77948
|
streamRef.current = stream;
|
|
@@ -77541,11 +77951,11 @@ function BurstCamera({ open, onClose, onCommit }) {
|
|
|
77541
77951
|
onClose();
|
|
77542
77952
|
}
|
|
77543
77953
|
}, [onClose]);
|
|
77544
|
-
const stopCamera =
|
|
77954
|
+
const stopCamera = useCallback40(() => {
|
|
77545
77955
|
streamRef.current?.getTracks().forEach((t) => t.stop());
|
|
77546
77956
|
streamRef.current = null;
|
|
77547
77957
|
}, []);
|
|
77548
|
-
|
|
77958
|
+
useEffect41(() => {
|
|
77549
77959
|
if (open) {
|
|
77550
77960
|
startCamera(facing);
|
|
77551
77961
|
} else {
|
|
@@ -77673,7 +78083,7 @@ function BurstCamera({ open, onClose, onCommit }) {
|
|
|
77673
78083
|
}
|
|
77674
78084
|
|
|
77675
78085
|
// src/components/media-studio/PhotoAnnotator.tsx
|
|
77676
|
-
import { useState as useState50, useEffect as
|
|
78086
|
+
import { useState as useState50, useEffect as useEffect43, useCallback as useCallback42, useRef as useRef51, Fragment as Fragment19 } from "react";
|
|
77677
78087
|
import { Stage, Layer, Image as KonvaImage, Circle, Arrow, Line, Label, Tag, Text } from "react-konva";
|
|
77678
78088
|
|
|
77679
78089
|
// src/components/media-studio/annotations.ts
|
|
@@ -77877,7 +78287,7 @@ function MeasureCalibration({
|
|
|
77877
78287
|
}
|
|
77878
78288
|
|
|
77879
78289
|
// src/components/media-studio/usePhotoSource.ts
|
|
77880
|
-
import { useCallback as
|
|
78290
|
+
import { useCallback as useCallback41, useEffect as useEffect42, useState as useState49 } from "react";
|
|
77881
78291
|
var FALLBACK = { w: 600, h: 400 };
|
|
77882
78292
|
function usePhotoSource(photoUrl, enabled) {
|
|
77883
78293
|
const [image, setImage] = useState49(null);
|
|
@@ -77885,7 +78295,7 @@ function usePhotoSource(photoUrl, enabled) {
|
|
|
77885
78295
|
const [fitScale, setFitScale] = useState49(1);
|
|
77886
78296
|
const [failed, setFailed] = useState49(false);
|
|
77887
78297
|
const [attempt, setAttempt] = useState49(0);
|
|
77888
|
-
|
|
78298
|
+
useEffect42(() => {
|
|
77889
78299
|
if (!enabled) return;
|
|
77890
78300
|
setFailed(false);
|
|
77891
78301
|
setImage(null);
|
|
@@ -77916,7 +78326,7 @@ function usePhotoSource(photoUrl, enabled) {
|
|
|
77916
78326
|
cancelled = true;
|
|
77917
78327
|
};
|
|
77918
78328
|
}, [enabled, photoUrl, attempt]);
|
|
77919
|
-
const retry =
|
|
78329
|
+
const retry = useCallback41(() => setAttempt((n) => n + 1), []);
|
|
77920
78330
|
return { image, natural, fitScale, failed, retry };
|
|
77921
78331
|
}
|
|
77922
78332
|
|
|
@@ -77937,7 +78347,7 @@ function PhotoAnnotator({
|
|
|
77937
78347
|
onClose
|
|
77938
78348
|
}) {
|
|
77939
78349
|
const [mounted, setMounted] = useState50(false);
|
|
77940
|
-
|
|
78350
|
+
useEffect43(() => setMounted(true), []);
|
|
77941
78351
|
const [tool, setTool] = useState50("circle");
|
|
77942
78352
|
const [zoom, setZoom] = useState50(1);
|
|
77943
78353
|
const [annotations, setAnnotations] = useState50([]);
|
|
@@ -77952,16 +78362,16 @@ function PhotoAnnotator({
|
|
|
77952
78362
|
const [isDrawingFreehand, setIsDrawingFreehand] = useState50(false);
|
|
77953
78363
|
const [labelInput, setLabelInput] = useState50(null);
|
|
77954
78364
|
const [labelText, setLabelText] = useState50("");
|
|
77955
|
-
const labelInputRef =
|
|
78365
|
+
const labelInputRef = useRef51(null);
|
|
77956
78366
|
const [showCalibration, setShowCalibration] = useState50(false);
|
|
77957
78367
|
const [pxPerUnit, setPxPerUnit] = useState50(null);
|
|
77958
78368
|
const [calibLine, setCalibLine] = useState50(null);
|
|
77959
78369
|
const [calibKnown, setCalibKnown] = useState50("");
|
|
77960
78370
|
const [calibUnit, setCalibUnit] = useState50("in");
|
|
77961
78371
|
const [measures, setMeasures] = useState50([]);
|
|
77962
|
-
const stageRef =
|
|
78372
|
+
const stageRef = useRef51(null);
|
|
77963
78373
|
const scale = fitScale * zoom;
|
|
77964
|
-
|
|
78374
|
+
useEffect43(() => {
|
|
77965
78375
|
if (!open) return;
|
|
77966
78376
|
const doc = deserializeMeasureDoc(initialAnnotationsJson);
|
|
77967
78377
|
setAnnotations(doc.annotations.filter((a) => a.kind !== "measure"));
|
|
@@ -77983,7 +78393,7 @@ function PhotoAnnotator({
|
|
|
77983
78393
|
setCalibKnown("");
|
|
77984
78394
|
setCalibUnit(doc.calibration?.calibUnit ?? "in");
|
|
77985
78395
|
}, [open, sectionName, initialAnnotationsJson]);
|
|
77986
|
-
|
|
78396
|
+
useEffect43(() => {
|
|
77987
78397
|
if (labelInput) {
|
|
77988
78398
|
const t = setTimeout(() => labelInputRef.current?.focus(), 50);
|
|
77989
78399
|
return () => clearTimeout(t);
|
|
@@ -77994,14 +78404,14 @@ function PhotoAnnotator({
|
|
|
77994
78404
|
// stack hears one the label box is already gone: this is always "close the annotator".
|
|
77995
78405
|
onEscape: onClose
|
|
77996
78406
|
});
|
|
77997
|
-
const naturalPointer =
|
|
78407
|
+
const naturalPointer = useCallback42(() => {
|
|
77998
78408
|
const stage = stageRef.current;
|
|
77999
78409
|
if (!stage) return null;
|
|
78000
78410
|
const p = stage.getPointerPosition();
|
|
78001
78411
|
if (!p) return null;
|
|
78002
78412
|
return { x: p.x / scale, y: p.y / scale };
|
|
78003
78413
|
}, [scale]);
|
|
78004
|
-
const handleStageClick =
|
|
78414
|
+
const handleStageClick = useCallback42(() => {
|
|
78005
78415
|
if (labelInput) return;
|
|
78006
78416
|
const pos = naturalPointer();
|
|
78007
78417
|
if (!pos) return;
|
|
@@ -78035,20 +78445,20 @@ function PhotoAnnotator({
|
|
|
78035
78445
|
}
|
|
78036
78446
|
}
|
|
78037
78447
|
}, [tool, arrowStart, measureStart, pxPerUnit, naturalPointer, labelInput]);
|
|
78038
|
-
const handleMouseDown =
|
|
78448
|
+
const handleMouseDown = useCallback42(() => {
|
|
78039
78449
|
if (tool !== "free" || labelInput) return;
|
|
78040
78450
|
const pos = naturalPointer();
|
|
78041
78451
|
if (!pos) return;
|
|
78042
78452
|
setFreehandPoints([pos]);
|
|
78043
78453
|
setIsDrawingFreehand(true);
|
|
78044
78454
|
}, [tool, labelInput, naturalPointer]);
|
|
78045
|
-
const handleMouseMove =
|
|
78455
|
+
const handleMouseMove = useCallback42(() => {
|
|
78046
78456
|
if (!isDrawingFreehand || tool !== "free") return;
|
|
78047
78457
|
const pos = naturalPointer();
|
|
78048
78458
|
if (!pos) return;
|
|
78049
78459
|
setFreehandPoints((prev) => [...prev, pos]);
|
|
78050
78460
|
}, [isDrawingFreehand, tool, naturalPointer]);
|
|
78051
|
-
const handleMouseUp =
|
|
78461
|
+
const handleMouseUp = useCallback42(() => {
|
|
78052
78462
|
if (!isDrawingFreehand || tool !== "free") return;
|
|
78053
78463
|
if (freehandPoints.length > 1) {
|
|
78054
78464
|
setAnnotations((prev) => [
|
|
@@ -78059,11 +78469,11 @@ function PhotoAnnotator({
|
|
|
78059
78469
|
setFreehandPoints([]);
|
|
78060
78470
|
setIsDrawingFreehand(false);
|
|
78061
78471
|
}, [isDrawingFreehand, tool, freehandPoints]);
|
|
78062
|
-
const cancelLabel =
|
|
78472
|
+
const cancelLabel = useCallback42(() => {
|
|
78063
78473
|
setLabelInput(null);
|
|
78064
78474
|
setLabelText("");
|
|
78065
78475
|
}, []);
|
|
78066
|
-
const commitLabel =
|
|
78476
|
+
const commitLabel = useCallback42(() => {
|
|
78067
78477
|
if (labelInput && labelText.trim()) {
|
|
78068
78478
|
setAnnotations((prev) => [
|
|
78069
78479
|
...prev,
|
|
@@ -78072,7 +78482,7 @@ function PhotoAnnotator({
|
|
|
78072
78482
|
}
|
|
78073
78483
|
cancelLabel();
|
|
78074
78484
|
}, [labelInput, labelText, cancelLabel]);
|
|
78075
|
-
const commitCalibration =
|
|
78485
|
+
const commitCalibration = useCallback42(() => {
|
|
78076
78486
|
const known = parseFloat(calibKnown);
|
|
78077
78487
|
if (calibLine && known > 0) {
|
|
78078
78488
|
const dx = calibLine.b.x - calibLine.a.x;
|
|
@@ -78087,11 +78497,11 @@ function PhotoAnnotator({
|
|
|
78087
78497
|
setCalibLine(null);
|
|
78088
78498
|
setCalibKnown("");
|
|
78089
78499
|
}, [calibLine, calibKnown]);
|
|
78090
|
-
const undoLast =
|
|
78091
|
-
const zoomIn =
|
|
78092
|
-
const zoomOut =
|
|
78093
|
-
const zoomReset =
|
|
78094
|
-
const handleSave =
|
|
78500
|
+
const undoLast = useCallback42(() => setAnnotations((prev) => prev.slice(0, -1)), []);
|
|
78501
|
+
const zoomIn = useCallback42(() => setZoom((z) => Math.min(z + 0.25, 4)), []);
|
|
78502
|
+
const zoomOut = useCallback42(() => setZoom((z) => Math.max(z - 0.25, 0.5)), []);
|
|
78503
|
+
const zoomReset = useCallback42(() => setZoom(1), []);
|
|
78504
|
+
const handleSave = useCallback42(async () => {
|
|
78095
78505
|
const stage = stageRef.current;
|
|
78096
78506
|
if (!stage) return;
|
|
78097
78507
|
let blob;
|
|
@@ -78498,7 +78908,7 @@ function StructureDeleteModal({ open, title, noun = "section", impact, onConfirm
|
|
|
78498
78908
|
}
|
|
78499
78909
|
|
|
78500
78910
|
// src/components/editor/AddSectionPromptModal.tsx
|
|
78501
|
-
import { useRef as
|
|
78911
|
+
import { useRef as useRef52 } from "react";
|
|
78502
78912
|
import { Fragment as Fragment22, jsx as jsx101, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
78503
78913
|
function AddSectionPromptModal({
|
|
78504
78914
|
open,
|
|
@@ -78507,7 +78917,7 @@ function AddSectionPromptModal({
|
|
|
78507
78917
|
onConfirm,
|
|
78508
78918
|
onCancel
|
|
78509
78919
|
}) {
|
|
78510
|
-
const inputRef =
|
|
78920
|
+
const inputRef = useRef52(null);
|
|
78511
78921
|
return /* @__PURE__ */ jsx101(
|
|
78512
78922
|
Modal,
|
|
78513
78923
|
{
|
|
@@ -78556,12 +78966,12 @@ function AddSectionPromptModal({
|
|
|
78556
78966
|
}
|
|
78557
78967
|
|
|
78558
78968
|
// src/components/editor/AddItemTypeModal.tsx
|
|
78559
|
-
import { useState as useState51, useEffect as
|
|
78969
|
+
import { useState as useState51, useEffect as useEffect44, useRef as useRef53 } from "react";
|
|
78560
78970
|
import { Fragment as Fragment23, jsx as jsx102, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
78561
78971
|
function AddItemTypeModal({ open, onConfirm, onCancel }) {
|
|
78562
78972
|
const [label, setLabel] = useState51("");
|
|
78563
78973
|
const [type, setType] = useState51("rich");
|
|
78564
|
-
const labelRef =
|
|
78974
|
+
const labelRef = useRef53(null);
|
|
78565
78975
|
const ITEM_TYPES = [
|
|
78566
78976
|
{ value: "rich", label: index_exports.editor_additem_type_rich() },
|
|
78567
78977
|
{ value: "boolean", label: index_exports.editor_additem_type_boolean() },
|
|
@@ -78573,7 +78983,7 @@ function AddItemTypeModal({ open, onConfirm, onCancel }) {
|
|
|
78573
78983
|
{ value: "date", label: index_exports.editor_additem_type_date() },
|
|
78574
78984
|
{ value: "photo_only", label: index_exports.editor_additem_type_photo_only() }
|
|
78575
78985
|
];
|
|
78576
|
-
|
|
78986
|
+
useEffect44(() => {
|
|
78577
78987
|
if (open) {
|
|
78578
78988
|
setLabel("");
|
|
78579
78989
|
setType("rich");
|
|
@@ -78649,11 +79059,11 @@ function AddItemTypeModal({ open, onConfirm, onCancel }) {
|
|
|
78649
79059
|
}
|
|
78650
79060
|
|
|
78651
79061
|
// src/components/editor/SaveTemplateModal.tsx
|
|
78652
|
-
import { useRef as
|
|
79062
|
+
import { useRef as useRef54 } from "react";
|
|
78653
79063
|
import { Fragment as Fragment24, jsx as jsx103, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
78654
79064
|
function SaveTemplateModal({ mode, name, onChangeName, onConfirm, onCancel }) {
|
|
78655
79065
|
const isNew = mode === "new";
|
|
78656
|
-
const nameRef =
|
|
79066
|
+
const nameRef = useRef54(null);
|
|
78657
79067
|
return /* @__PURE__ */ jsxs87(
|
|
78658
79068
|
Modal,
|
|
78659
79069
|
{
|
|
@@ -78707,10 +79117,10 @@ function SaveTemplateModal({ mode, name, onChangeName, onConfirm, onCancel }) {
|
|
|
78707
79117
|
}
|
|
78708
79118
|
|
|
78709
79119
|
// src/components/editor/CommentLibraryDrawer.tsx
|
|
78710
|
-
import { useRef as
|
|
79120
|
+
import { useRef as useRef55 } from "react";
|
|
78711
79121
|
import { Fragment as Fragment25, jsx as jsx104, jsxs as jsxs88 } from "react/jsx-runtime";
|
|
78712
79122
|
function CommentLibraryDrawer({ open, comments, state, serverComments, onInsert, onClose, sheet = false }) {
|
|
78713
|
-
const searchRef =
|
|
79123
|
+
const searchRef = useRef55(null);
|
|
78714
79124
|
const locale = useFieldDataSource().session().locale;
|
|
78715
79125
|
const searchBlock = /* @__PURE__ */ jsxs88("div", { className: "px-4 py-2", children: [
|
|
78716
79126
|
/* @__PURE__ */ jsx104(
|
|
@@ -78838,7 +79248,7 @@ function CommentLibraryDrawer({ open, comments, state, serverComments, onInsert,
|
|
|
78838
79248
|
}
|
|
78839
79249
|
|
|
78840
79250
|
// src/components/editor/SectionPickerModal.tsx
|
|
78841
|
-
import { useRef as
|
|
79251
|
+
import { useRef as useRef56 } from "react";
|
|
78842
79252
|
import { jsx as jsx105, jsxs as jsxs89 } from "react/jsx-runtime";
|
|
78843
79253
|
function SectionPickerModal({
|
|
78844
79254
|
open,
|
|
@@ -78849,7 +79259,7 @@ function SectionPickerModal({
|
|
|
78849
79259
|
pickSection,
|
|
78850
79260
|
closeSectionPicker
|
|
78851
79261
|
}) {
|
|
78852
|
-
const inputRef =
|
|
79262
|
+
const inputRef = useRef56(null);
|
|
78853
79263
|
return /* @__PURE__ */ jsxs89(Modal, { open, onClose: closeSectionPicker, title: index_exports.editor_sectionpicker_title(), size: "md", initialFocusRef: inputRef, children: [
|
|
78854
79264
|
/* @__PURE__ */ jsx105(
|
|
78855
79265
|
"input",
|
|
@@ -78886,34 +79296,37 @@ import { jsx as jsx106, jsxs as jsxs90 } from "react/jsx-runtime";
|
|
|
78886
79296
|
function TagPickerModal({ open, activeItemId, tagsByItem, presetTags, onToggle, onClose }) {
|
|
78887
79297
|
const selected = tagsByItem[activeItemId] || [];
|
|
78888
79298
|
return /* @__PURE__ */ jsxs90(Modal, { open, onClose, title: index_exports.editor_tagpicker_title(), size: "sm", children: [
|
|
78889
|
-
/* @__PURE__ */
|
|
78890
|
-
|
|
78891
|
-
|
|
78892
|
-
|
|
78893
|
-
|
|
78894
|
-
|
|
78895
|
-
|
|
78896
|
-
|
|
78897
|
-
|
|
78898
|
-
|
|
78899
|
-
|
|
78900
|
-
|
|
78901
|
-
|
|
78902
|
-
|
|
78903
|
-
|
|
78904
|
-
|
|
78905
|
-
|
|
78906
|
-
|
|
78907
|
-
|
|
78908
|
-
|
|
78909
|
-
|
|
78910
|
-
|
|
78911
|
-
|
|
79299
|
+
/* @__PURE__ */ jsxs90("div", { className: "space-y-1.5", children: [
|
|
79300
|
+
presetTags.length === 0 && /* @__PURE__ */ jsx106("p", { className: "text-[13px] text-ih-fg-3", children: index_exports.editor_tagpicker_empty() }),
|
|
79301
|
+
presetTags.map((tag) => {
|
|
79302
|
+
const isActive = selected.some((t) => t.id === tag.id);
|
|
79303
|
+
return /* @__PURE__ */ jsxs90(
|
|
79304
|
+
"button",
|
|
79305
|
+
{
|
|
79306
|
+
onClick: () => onToggle(tag),
|
|
79307
|
+
className: `w-full text-left px-3 py-2.5 rounded-lg text-[13px] font-medium flex items-center gap-3 transition-colors ${isActive ? "bg-ih-bg-muted ring-1 ring-inset" : "hover:bg-ih-bg-muted"}`,
|
|
79308
|
+
style: isActive && safeCssColor(tag.color) ? { "--tw-ring-color": safeCssColor(tag.color) } : void 0,
|
|
79309
|
+
children: [
|
|
79310
|
+
/* @__PURE__ */ jsx106(
|
|
79311
|
+
"span",
|
|
79312
|
+
{
|
|
79313
|
+
className: "w-3 h-3 rounded-full flex-shrink-0 bg-ih-border-strong",
|
|
79314
|
+
style: safeCssColor(tag.color) ? { backgroundColor: safeCssColor(tag.color) } : void 0
|
|
79315
|
+
}
|
|
79316
|
+
),
|
|
79317
|
+
/* @__PURE__ */ jsx106("span", { className: "flex-1 text-ih-fg-1", children: tag.name }),
|
|
79318
|
+
isActive && /* @__PURE__ */ jsx106("svg", { className: "w-4 h-4 text-ih-ok", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx106("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) })
|
|
79319
|
+
]
|
|
79320
|
+
},
|
|
79321
|
+
tag.id
|
|
79322
|
+
);
|
|
79323
|
+
})
|
|
79324
|
+
] }),
|
|
78912
79325
|
selected.length > 0 && /* @__PURE__ */ jsx106("div", { className: "mt-3 pt-3 border-t border-ih-border", children: /* @__PURE__ */ jsx106("div", { className: "flex flex-wrap gap-1.5", children: selected.map((tag) => /* @__PURE__ */ jsx106(
|
|
78913
79326
|
"span",
|
|
78914
79327
|
{
|
|
78915
79328
|
className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-bold text-white",
|
|
78916
|
-
style: { backgroundColor: tag.color
|
|
79329
|
+
style: { backgroundColor: safeCssColor(tag.color) ?? "#6b7280", color: readableTextOn(safeCssColor(tag.color) ?? "#6b7280") ?? void 0 },
|
|
78917
79330
|
children: tag.name
|
|
78918
79331
|
},
|
|
78919
79332
|
tag.id
|
|
@@ -79197,10 +79610,10 @@ function BulkCreateForm({ busy, onSubmit }) {
|
|
|
79197
79610
|
}
|
|
79198
79611
|
|
|
79199
79612
|
// src/components/editor/CostItemsHost.tsx
|
|
79200
|
-
import { useEffect as
|
|
79613
|
+
import { useEffect as useEffect46, useState as useState55 } from "react";
|
|
79201
79614
|
|
|
79202
79615
|
// src/components/editor/CostItemsPanel.tsx
|
|
79203
|
-
import { useEffect as
|
|
79616
|
+
import { useEffect as useEffect45, useRef as useRef57, useState as useState54 } from "react";
|
|
79204
79617
|
|
|
79205
79618
|
// src/shared/money.ts
|
|
79206
79619
|
function formatDollars(cents, opts) {
|
|
@@ -79301,7 +79714,7 @@ function CostExportButtons({
|
|
|
79301
79714
|
}
|
|
79302
79715
|
|
|
79303
79716
|
// src/components/editor/cost-items-rows.ts
|
|
79304
|
-
import { useCallback as
|
|
79717
|
+
import { useCallback as useCallback43 } from "react";
|
|
79305
79718
|
var THRESHOLD_CENTS = 3e5;
|
|
79306
79719
|
function rowTotalCents(item) {
|
|
79307
79720
|
if (item.costMethod === "unit") return (item.quantity ?? 0) * (item.unitCostCents ?? 0);
|
|
@@ -79337,7 +79750,7 @@ function isTempId(id) {
|
|
|
79337
79750
|
}
|
|
79338
79751
|
function useCostItemWrite(inspectionId) {
|
|
79339
79752
|
const costItems = useFieldDataSource().resources.costItems;
|
|
79340
|
-
return
|
|
79753
|
+
return useCallback43(
|
|
79341
79754
|
async (intent, item) => {
|
|
79342
79755
|
if (!costItems) return { success: false };
|
|
79343
79756
|
try {
|
|
@@ -79363,12 +79776,12 @@ function CostItemsPanel({
|
|
|
79363
79776
|
const [rows, setRows] = useState54(items);
|
|
79364
79777
|
const [saving, setSaving] = useState54({});
|
|
79365
79778
|
const [failure, setFailure] = useState54(null);
|
|
79366
|
-
const pendingRemovalRef =
|
|
79367
|
-
const writingRef =
|
|
79368
|
-
const removingRef =
|
|
79369
|
-
const dirtyRef =
|
|
79370
|
-
const rowsRef =
|
|
79371
|
-
|
|
79779
|
+
const pendingRemovalRef = useRef57(/* @__PURE__ */ new Set());
|
|
79780
|
+
const writingRef = useRef57(/* @__PURE__ */ new Set());
|
|
79781
|
+
const removingRef = useRef57(/* @__PURE__ */ new Set());
|
|
79782
|
+
const dirtyRef = useRef57(/* @__PURE__ */ new Set());
|
|
79783
|
+
const rowsRef = useRef57(rows);
|
|
79784
|
+
useEffect45(() => {
|
|
79372
79785
|
rowsRef.current = rows;
|
|
79373
79786
|
});
|
|
79374
79787
|
const bucketTotals = { immediate: 0, short_term: 0, long_term: 0 };
|
|
@@ -79726,7 +80139,7 @@ function CostItemsHost({
|
|
|
79726
80139
|
}) {
|
|
79727
80140
|
const costItems = useFieldDataSource().resources.costItems;
|
|
79728
80141
|
const [data, setData] = useState55(null);
|
|
79729
|
-
|
|
80142
|
+
useEffect46(() => {
|
|
79730
80143
|
if (!open) return;
|
|
79731
80144
|
let cancelled = false;
|
|
79732
80145
|
setData(null);
|
|
@@ -80102,7 +80515,7 @@ function AppBar({ platform, sectionTitle, itemLabel, onBack, onMore, tablet = fa
|
|
|
80102
80515
|
"header",
|
|
80103
80516
|
{
|
|
80104
80517
|
"data-platform": platform,
|
|
80105
|
-
className: `sticky top-0 z-30 ${height} bg-ih-bg-card border-b border-ih-border flex items-center
|
|
80518
|
+
className: `sticky top-0 z-30 ${height} bg-ih-bg-card border-b border-ih-border flex items-center pl-[max(0.5rem,env(safe-area-inset-left))] pr-[max(0.5rem,env(safe-area-inset-right))] gap-2`,
|
|
80106
80519
|
children: [
|
|
80107
80520
|
/* @__PURE__ */ jsx113(IconButton, { onClick: onBack, className: BTN, "aria-label": index_exports.common_back(), children: /* @__PURE__ */ jsx113(BackGlyph, { platform }) }),
|
|
80108
80521
|
tablet && onOpenSections && /* @__PURE__ */ jsx113(IconButton, { onClick: onOpenSections, className: BTN, "aria-label": index_exports.editor_mobile_drawer_sections(), children: "\u2630" }),
|
|
@@ -80166,7 +80579,7 @@ function TabletTree({ appBar, listHeader, sectionTitle, list, main, emptyTemplat
|
|
|
80166
80579
|
"aside",
|
|
80167
80580
|
{
|
|
80168
80581
|
"data-testid": "tablet-list-pane",
|
|
80169
|
-
className: "w-[clamp(280px,36vw,360px)] shrink-0 min-w-0 min-h-0 border-r border-ih-border flex flex-col",
|
|
80582
|
+
className: "w-[clamp(280px,36vw,360px)] shrink-0 min-w-0 min-h-0 pl-[env(safe-area-inset-left)] border-r border-ih-border flex flex-col",
|
|
80170
80583
|
children: [
|
|
80171
80584
|
listHeader,
|
|
80172
80585
|
/* @__PURE__ */ jsx116("div", { className: "sticky top-0 z-10 shrink-0 px-3 py-1.5 bg-ih-bg-card border-b border-ih-border text-[12px] font-bold text-ih-fg-2 truncate", children: sectionTitle }),
|
|
@@ -80178,7 +80591,7 @@ function TabletTree({ appBar, listHeader, sectionTitle, list, main, emptyTemplat
|
|
|
80178
80591
|
"main",
|
|
80179
80592
|
{
|
|
80180
80593
|
"data-testid": "tablet-editor-pane",
|
|
80181
|
-
className: "flex-1 min-w-0 min-h-0 overflow-y-auto overscroll-contain
|
|
80594
|
+
className: "flex-1 min-w-0 min-h-0 overflow-y-auto overscroll-contain pl-5 pr-[max(1.25rem,env(safe-area-inset-right))] py-4 pb-24 [@media(max-height:499px)]:py-2",
|
|
80182
80595
|
children: main
|
|
80183
80596
|
}
|
|
80184
80597
|
)
|
|
@@ -80190,9 +80603,9 @@ function TabletTree({ appBar, listHeader, sectionTitle, list, main, emptyTemplat
|
|
|
80190
80603
|
}
|
|
80191
80604
|
|
|
80192
80605
|
// src/hooks/useResetBatchOnPhone.ts
|
|
80193
|
-
import { useEffect as
|
|
80606
|
+
import { useEffect as useEffect47 } from "react";
|
|
80194
80607
|
function useResetBatchOnPhone(isPhone, batchMode, setBatchMode, setBatchSelected) {
|
|
80195
|
-
|
|
80608
|
+
useEffect47(() => {
|
|
80196
80609
|
if (!isPhone || !batchMode) return;
|
|
80197
80610
|
setBatchMode(false);
|
|
80198
80611
|
setBatchSelected({});
|
|
@@ -80229,7 +80642,7 @@ function InspectionIdentity({ address, id, date, status }) {
|
|
|
80229
80642
|
// src/components/editor/MobileDrawerTriggers.tsx
|
|
80230
80643
|
import { jsx as jsx118, jsxs as jsxs99 } from "react/jsx-runtime";
|
|
80231
80644
|
function MobileDrawerTriggers({ onOpen, showTheme = true }) {
|
|
80232
|
-
return /* @__PURE__ */ jsx118("nav", { "aria-label": index_exports.editor_mobile_nav_label(), className: "fixed left-0 right-0 bottom-0 z-30 h-[calc(3.5rem+env(safe-area-inset-bottom))] pb-[env(safe-area-inset-bottom)] bg-ih-bg-card border-t border-ih-border flex", children: [
|
|
80645
|
+
return /* @__PURE__ */ jsx118("nav", { "aria-label": index_exports.editor_mobile_nav_label(), className: "fixed left-0 right-0 bottom-0 z-30 h-[calc(3.5rem+env(safe-area-inset-bottom))] pb-[env(safe-area-inset-bottom)] pl-[env(safe-area-inset-left)] pr-[env(safe-area-inset-right)] bg-ih-bg-card border-t border-ih-border flex", children: [
|
|
80233
80646
|
{ id: "sections", label: index_exports.editor_mobile_drawer_sections(), icon: "\u2630" },
|
|
80234
80647
|
{ id: "items", label: index_exports.editor_mobile_drawer_items(), icon: "\u2263" },
|
|
80235
80648
|
{ id: "preview", label: index_exports.editor_route_drawer_preview(), icon: "\u{1F441}" },
|
|
@@ -80327,7 +80740,7 @@ function MobileFinishDrawer({
|
|
|
80327
80740
|
}
|
|
80328
80741
|
|
|
80329
80742
|
// src/components/editor/PropertyInfoForm.tsx
|
|
80330
|
-
import { useMemo as
|
|
80743
|
+
import { useMemo as useMemo15, useCallback as useCallback44, useEffect as useEffect48, useRef as useRef58, useState as useState57 } from "react";
|
|
80331
80744
|
|
|
80332
80745
|
// src/shared/property-facts-keys.ts
|
|
80333
80746
|
var DEDICATED_FACT_KEYS = [
|
|
@@ -80374,8 +80787,8 @@ function PropertyInfoForm({ inspection, templateFields, propertyAddress, onSave,
|
|
|
80374
80787
|
const readOnly = useReadOnly();
|
|
80375
80788
|
const defaultFields = inspection.propertyType === "commercial" ? commercialFields() : residentialFields();
|
|
80376
80789
|
const metaFields = templateFields?.length ? templateFields : defaultFields;
|
|
80377
|
-
const filled =
|
|
80378
|
-
const groups =
|
|
80790
|
+
const filled = useMemo15(() => metaFields.filter((f) => inspection[f.id]).length, [metaFields, inspection]);
|
|
80791
|
+
const groups = useMemo15(() => {
|
|
80379
80792
|
const seen = /* @__PURE__ */ new Set();
|
|
80380
80793
|
const result = [];
|
|
80381
80794
|
for (const f of metaFields) {
|
|
@@ -80387,7 +80800,7 @@ function PropertyInfoForm({ inspection, templateFields, propertyAddress, onSave,
|
|
|
80387
80800
|
}
|
|
80388
80801
|
return result;
|
|
80389
80802
|
}, [metaFields]);
|
|
80390
|
-
const fieldsByGroup =
|
|
80803
|
+
const fieldsByGroup = useCallback44(
|
|
80391
80804
|
(group) => metaFields.filter((f) => (f.group || index_exports.editor_property_group_general()) === group),
|
|
80392
80805
|
[metaFields]
|
|
80393
80806
|
);
|
|
@@ -80411,10 +80824,10 @@ function PropertyInfoForm({ inspection, templateFields, propertyAddress, onSave,
|
|
|
80411
80824
|
const { run, busy: autofilling } = useFieldCommand(String(inspection.id));
|
|
80412
80825
|
const [autofillMsg, setAutofillMsg] = useState57(null);
|
|
80413
80826
|
const addressString = (propertyAddress || inspection.propertyAddress || "").trim();
|
|
80414
|
-
const latest =
|
|
80827
|
+
const latest = useRef58({ metaFields, inspection, onSave, onCommit });
|
|
80415
80828
|
latest.current = { metaFields, inspection, onSave, onCommit };
|
|
80416
|
-
const mounted =
|
|
80417
|
-
|
|
80829
|
+
const mounted = useRef58(true);
|
|
80830
|
+
useEffect48(() => {
|
|
80418
80831
|
mounted.current = true;
|
|
80419
80832
|
return () => {
|
|
80420
80833
|
mounted.current = false;
|
|
@@ -80460,7 +80873,7 @@ function PropertyInfoForm({ inspection, templateFields, propertyAddress, onSave,
|
|
|
80460
80873
|
if (isIgnored(answer) || !mounted.current) return;
|
|
80461
80874
|
if (answer.data) applyAutofill(answer.data.facts, answer.data.reason);
|
|
80462
80875
|
}
|
|
80463
|
-
return /* @__PURE__ */ jsxs101("div", { className: "px-6 py-6 max-w-5xl", "data-testid": "property-info-form", children: [
|
|
80876
|
+
return /* @__PURE__ */ jsxs101("div", { className: "px-0 md:px-6 py-6 max-w-5xl", "data-testid": "property-info-form", children: [
|
|
80464
80877
|
/* @__PURE__ */ jsxs101("header", { className: "mb-6", children: [
|
|
80465
80878
|
/* @__PURE__ */ jsxs101("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
80466
80879
|
/* @__PURE__ */ jsx120("p", { className: "text-[10px] font-bold uppercase tracking-[0.2em] text-ih-fg-3", children: index_exports.editor_property_progress({ filled, total: metaFields.length }) }),
|
|
@@ -80533,7 +80946,7 @@ function PropertyInfoForm({ inspection, templateFields, propertyAddress, onSave,
|
|
|
80533
80946
|
}
|
|
80534
80947
|
|
|
80535
80948
|
// src/components/statutory/StatutoryDetailsHost.tsx
|
|
80536
|
-
import { useCallback as
|
|
80949
|
+
import { useCallback as useCallback45 } from "react";
|
|
80537
80950
|
|
|
80538
80951
|
// src/components/statutory/StatutoryDetailsPanel.tsx
|
|
80539
80952
|
import { useId as useId3, useState as useState58 } from "react";
|
|
@@ -80602,7 +81015,7 @@ function StatutoryDetailsHost({
|
|
|
80602
81015
|
details
|
|
80603
81016
|
}) {
|
|
80604
81017
|
const { run, busy } = useFieldCommand(inspectionId);
|
|
80605
|
-
const onCommit =
|
|
81018
|
+
const onCommit = useCallback45((next) => {
|
|
80606
81019
|
void run({ type: "save-statutory-details", payload: next });
|
|
80607
81020
|
}, [run]);
|
|
80608
81021
|
if (!details) return null;
|
|
@@ -80725,7 +81138,7 @@ function PcaNarrativePanel({ inspectionId, narrative }) {
|
|
|
80725
81138
|
}
|
|
80726
81139
|
|
|
80727
81140
|
// src/components/inspection-edit/CompliancePanel.tsx
|
|
80728
|
-
import { useRef as
|
|
81141
|
+
import { useRef as useRef59, useState as useState60 } from "react";
|
|
80729
81142
|
|
|
80730
81143
|
// src/components/ConfirmDialog.tsx
|
|
80731
81144
|
import { Fragment as Fragment32, jsx as jsx125, jsxs as jsxs105 } from "react/jsx-runtime";
|
|
@@ -81158,7 +81571,7 @@ function RelianceFieldRow({
|
|
|
81158
81571
|
}) {
|
|
81159
81572
|
const { run, busy } = useFieldCommand(inspectionId);
|
|
81160
81573
|
const [value, setValue2] = useState60(initial);
|
|
81161
|
-
const savedRef =
|
|
81574
|
+
const savedRef = useRef59(initial);
|
|
81162
81575
|
const commit = async () => {
|
|
81163
81576
|
if (value === savedRef.current) return;
|
|
81164
81577
|
const answer = await run({ type: "save-pca-narrative", key: fieldKey, value });
|
|
@@ -81273,7 +81686,7 @@ function CommercialReportControls({
|
|
|
81273
81686
|
}
|
|
81274
81687
|
|
|
81275
81688
|
// src/components/editor/PropertyTypeControl.tsx
|
|
81276
|
-
import { useEffect as
|
|
81689
|
+
import { useEffect as useEffect49, useRef as useRef60, useState as useState61 } from "react";
|
|
81277
81690
|
|
|
81278
81691
|
// src/shared/inspection-property-type.ts
|
|
81279
81692
|
var INSPECTION_PROPERTY_TYPES = [
|
|
@@ -81303,9 +81716,9 @@ function PropertyTypeControl({
|
|
|
81303
81716
|
const costItems = dataSource.resources.costItems;
|
|
81304
81717
|
const [costCount, setCostCount] = useState61(0);
|
|
81305
81718
|
const [counting, setCounting] = useState61(false);
|
|
81306
|
-
const countRead =
|
|
81307
|
-
const mounted =
|
|
81308
|
-
|
|
81719
|
+
const countRead = useRef60(0);
|
|
81720
|
+
const mounted = useRef60(true);
|
|
81721
|
+
useEffect49(() => {
|
|
81309
81722
|
mounted.current = true;
|
|
81310
81723
|
return () => {
|
|
81311
81724
|
mounted.current = false;
|
|
@@ -81350,7 +81763,7 @@ function PropertyTypeControl({
|
|
|
81350
81763
|
}
|
|
81351
81764
|
void save(next);
|
|
81352
81765
|
}
|
|
81353
|
-
|
|
81766
|
+
useEffect49(() => {
|
|
81354
81767
|
if (pending !== null && !busy && propertyType === (pending === "" ? null : pending)) {
|
|
81355
81768
|
setPending(null);
|
|
81356
81769
|
}
|
|
@@ -81481,11 +81894,11 @@ function InspectionOverview({
|
|
|
81481
81894
|
}
|
|
81482
81895
|
|
|
81483
81896
|
// src/components/editor/BreadcrumbDropdown.tsx
|
|
81484
|
-
import { useRef as
|
|
81897
|
+
import { useRef as useRef61, useState as useState62 } from "react";
|
|
81485
81898
|
import { Fragment as Fragment36, jsx as jsx130, jsxs as jsxs110 } from "react/jsx-runtime";
|
|
81486
81899
|
function BreadcrumbDropdown({ units, activeUnitId, onSelect }) {
|
|
81487
81900
|
const [open, setOpen] = useState62(false);
|
|
81488
|
-
const anchorRef =
|
|
81901
|
+
const anchorRef = useRef61(null);
|
|
81489
81902
|
const COMMON_LABEL = index_exports.editor_scope_common();
|
|
81490
81903
|
const scopes = units.filter((u) => (u.kind ?? "unit") === "unit").slice().sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
|
|
81491
81904
|
const active = activeUnitId ? scopes.find((u) => u.id === activeUnitId) : null;
|
|
@@ -81692,28 +82105,76 @@ function ReadOnlyItemView({ item, sectionTitle, result, ratingLevels, inspection
|
|
|
81692
82105
|
] });
|
|
81693
82106
|
}
|
|
81694
82107
|
|
|
82108
|
+
// src/components/editor/FinishFieldworkConfirm.tsx
|
|
82109
|
+
import { useCallback as useCallback46, useState as useState63 } from "react";
|
|
82110
|
+
import { jsx as jsx132 } from "react/jsx-runtime";
|
|
82111
|
+
function useFinishFieldworkConfirm(finish, busy) {
|
|
82112
|
+
const [open, setOpen] = useState63(false);
|
|
82113
|
+
const latch = useActionLatch(busy);
|
|
82114
|
+
const request = useCallback46(() => setOpen(true), []);
|
|
82115
|
+
const dialog = /* @__PURE__ */ jsx132(
|
|
82116
|
+
ConfirmDialog,
|
|
82117
|
+
{
|
|
82118
|
+
open,
|
|
82119
|
+
title: index_exports.editor_finish_fieldwork_confirm_title(),
|
|
82120
|
+
message: index_exports.editor_finish_fieldwork_confirm_body(),
|
|
82121
|
+
confirmLabel: index_exports.editor_finish_fieldwork(),
|
|
82122
|
+
tone: "default",
|
|
82123
|
+
busy,
|
|
82124
|
+
onConfirm: () => latch(() => void finish().catch(() => void 0).finally(() => setOpen(false))),
|
|
82125
|
+
onCancel: () => setOpen(false)
|
|
82126
|
+
}
|
|
82127
|
+
);
|
|
82128
|
+
return { request, dialog };
|
|
82129
|
+
}
|
|
82130
|
+
|
|
82131
|
+
// src/hooks/useScrollTopOnDetails.ts
|
|
82132
|
+
import { useEffect as useEffect50 } from "react";
|
|
82133
|
+
function useScrollTopOnDetails(activeView) {
|
|
82134
|
+
useEffect50(() => {
|
|
82135
|
+
if (activeView !== "property") return;
|
|
82136
|
+
window.scrollTo(0, 0);
|
|
82137
|
+
document.querySelectorAll("main").forEach((el) => {
|
|
82138
|
+
el.scrollTop = 0;
|
|
82139
|
+
});
|
|
82140
|
+
}, [activeView]);
|
|
82141
|
+
}
|
|
82142
|
+
|
|
82143
|
+
// src/hooks/notes-commit-target.ts
|
|
82144
|
+
function notesCommitTarget(input) {
|
|
82145
|
+
const itemId = input.itemId ?? input.activeItemId;
|
|
82146
|
+
const sectionId = input.itemId ? input.sectionIdForItem(input.itemId) : input.currentSectionId;
|
|
82147
|
+
return itemId && sectionId ? { sectionId, itemId } : null;
|
|
82148
|
+
}
|
|
82149
|
+
|
|
81695
82150
|
// src/components/editor/ItemFilterBar.tsx
|
|
81696
|
-
import { jsx as
|
|
82151
|
+
import { jsx as jsx133, jsxs as jsxs112 } from "react/jsx-runtime";
|
|
81697
82152
|
function ItemFilterBar({ state, formProgress, isMobile }) {
|
|
81698
82153
|
const readOnly = useReadOnly();
|
|
81699
82154
|
return /* @__PURE__ */ jsxs112("div", { className: "flex flex-wrap items-center gap-1 px-3 py-1.5 border-b border-ih-border", children: [
|
|
81700
|
-
/* @__PURE__ */
|
|
82155
|
+
/* @__PURE__ */ jsx133(
|
|
81701
82156
|
SegmentedControl,
|
|
81702
82157
|
{
|
|
81703
82158
|
ariaLabel: index_exports.editor_route_item_filter(),
|
|
82159
|
+
className: "w-full min-w-0 [&>button]:min-w-0 [&>button]:pointer-coarse:min-w-11 [&>button]:px-1.5 [&>button>span:last-child]:min-w-0",
|
|
81704
82160
|
value: state.itemFilter,
|
|
81705
82161
|
onChange: (v) => state.setItemFilter(v),
|
|
81706
|
-
options: ["all", "unrated", "issues", "flagged"].map((f) =>
|
|
81707
|
-
|
|
81708
|
-
|
|
81709
|
-
|
|
81710
|
-
|
|
81711
|
-
|
|
81712
|
-
|
|
82162
|
+
options: ["all", "unrated", "issues", "flagged"].map((f) => {
|
|
82163
|
+
const text = f === "all" ? index_exports.editor_route_filter_all() : f === "unrated" ? index_exports.editor_route_filter_unrated() : f === "issues" ? index_exports.editor_route_filter_issues() : index_exports.editor_route_filter_flagged();
|
|
82164
|
+
const count = f === "all" ? null : state.filterCounts[f];
|
|
82165
|
+
return {
|
|
82166
|
+
value: f,
|
|
82167
|
+
title: count === null ? index_exports.editor_route_filter_all_in_section() : index_exports.editor_route_filter_count_in_section({ label: text, count }),
|
|
82168
|
+
label: /* @__PURE__ */ jsxs112("span", { className: "flex min-w-0 items-baseline gap-1", children: [
|
|
82169
|
+
/* @__PURE__ */ jsx133("span", { className: "min-w-0 truncate", children: text }),
|
|
82170
|
+
count !== null && /* @__PURE__ */ jsx133("span", { className: "shrink-0 tabular-nums text-[10px]", children: count })
|
|
82171
|
+
] })
|
|
82172
|
+
};
|
|
82173
|
+
})
|
|
81713
82174
|
}
|
|
81714
82175
|
),
|
|
81715
|
-
formProgress && /* @__PURE__ */
|
|
81716
|
-
!readOnly && /* @__PURE__ */
|
|
82176
|
+
formProgress && /* @__PURE__ */ jsx133("span", { className: "ml-auto text-[11px] text-ih-fg-3 whitespace-nowrap", children: index_exports.statutory_form_completeness({ answered: String(formProgress.answered), total: String(formProgress.total) }) }),
|
|
82177
|
+
!readOnly && /* @__PURE__ */ jsx133(
|
|
81717
82178
|
IconButton,
|
|
81718
82179
|
{
|
|
81719
82180
|
onClick: () => {
|
|
@@ -81729,28 +82190,28 @@ function ItemFilterBar({ state, formProgress, isMobile }) {
|
|
|
81729
82190
|
className: isMobile ? "ml-auto w-11 h-11 touch-manipulation" : "ml-auto",
|
|
81730
82191
|
title: state.batchMode ? index_exports.editor_route_exit_batch_mode() : index_exports.editor_route_batch_mode(),
|
|
81731
82192
|
"aria-label": state.batchMode ? index_exports.editor_route_exit_batch_mode() : index_exports.editor_route_batch_select_items(),
|
|
81732
|
-
children: /* @__PURE__ */
|
|
82193
|
+
children: /* @__PURE__ */ jsx133("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx133("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4" }) })
|
|
81733
82194
|
}
|
|
81734
82195
|
)
|
|
81735
82196
|
] });
|
|
81736
82197
|
}
|
|
81737
82198
|
|
|
81738
82199
|
// src/components/editor/UnitControls.tsx
|
|
81739
|
-
import { jsx as
|
|
81740
|
-
var UNITS_ICON = /* @__PURE__ */
|
|
81741
|
-
var COST_ICON = /* @__PURE__ */
|
|
82200
|
+
import { jsx as jsx134, jsxs as jsxs113 } from "react/jsx-runtime";
|
|
82201
|
+
var UNITS_ICON = /* @__PURE__ */ jsx134("svg", { className: "w-3.5 h-3.5 text-ih-fg-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx134("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" }) });
|
|
82202
|
+
var COST_ICON = /* @__PURE__ */ jsx134("svg", { className: "w-3.5 h-3.5 text-ih-fg-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx134("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8c-1.66 0-3 .9-3 2s1.34 2 3 2 3 .9 3 2-1.34 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V6m0 12v-2m0-10a4 4 0 100 8 4 4 0 000-8z" }) });
|
|
81742
82203
|
function UnitControls({ isPerUnit, units, activeUnitId, onSelectScope, onOpenUnits, onOpenCostItems }) {
|
|
81743
82204
|
const caps = useEditorCapabilities();
|
|
81744
82205
|
const readOnly = useReadOnly();
|
|
81745
82206
|
return /* @__PURE__ */ jsxs113("div", { className: "flex items-center gap-2", children: [
|
|
81746
|
-
isPerUnit && /* @__PURE__ */
|
|
81747
|
-
!readOnly && /* @__PURE__ */
|
|
81748
|
-
!readOnly && caps.costItems && /* @__PURE__ */
|
|
82207
|
+
isPerUnit && /* @__PURE__ */ jsx134(BreadcrumbDropdown, { units, activeUnitId, onSelect: onSelectScope }),
|
|
82208
|
+
!readOnly && /* @__PURE__ */ jsx134(Button, { variant: "secondary", size: "sm", onClick: onOpenUnits, className: "hidden lg:inline-flex", title: index_exports.editor_route_manage_units(), "aria-label": index_exports.editor_route_units(), icon: UNITS_ICON, children: /* @__PURE__ */ jsx134("span", { className: "hidden min-[1700px]:inline", children: index_exports.editor_route_units() }) }),
|
|
82209
|
+
!readOnly && caps.costItems && /* @__PURE__ */ jsx134(Button, { variant: "secondary", size: "sm", onClick: onOpenCostItems, className: "hidden lg:inline-flex", title: index_exports.editor_route_cost_items_title(), "aria-label": index_exports.editor_route_cost_items(), icon: COST_ICON, children: /* @__PURE__ */ jsx134("span", { className: "hidden min-[1700px]:inline", children: index_exports.editor_route_cost_items() }) })
|
|
81749
82210
|
] });
|
|
81750
82211
|
}
|
|
81751
82212
|
|
|
81752
82213
|
// src/editor/FieldEditor.tsx
|
|
81753
|
-
import { Fragment as Fragment37, jsx as
|
|
82214
|
+
import { Fragment as Fragment37, jsx as jsx135, jsxs as jsxs114 } from "react/jsx-runtime";
|
|
81754
82215
|
function originalQualityEnabled() {
|
|
81755
82216
|
try {
|
|
81756
82217
|
return typeof localStorage !== "undefined" && localStorage.getItem(ORIGINAL_QUALITY_KEY) === "1";
|
|
@@ -81765,18 +82226,18 @@ function FieldEditorInner({ data }) {
|
|
|
81765
82226
|
const caps = useEditorCapabilities();
|
|
81766
82227
|
const fieldSession = dataSource.session();
|
|
81767
82228
|
const displayLocale = fieldSession.locale;
|
|
81768
|
-
const notify =
|
|
82229
|
+
const notify = useCallback47(
|
|
81769
82230
|
(message, variant, opts) => dataSource.notify(message, variant, opts),
|
|
81770
82231
|
[dataSource]
|
|
81771
82232
|
);
|
|
81772
82233
|
const ensureHuman = useFieldEnsureHuman();
|
|
81773
82234
|
const savePropertyFacts = usePropertyFactsSave(String(data.inspection.id));
|
|
81774
|
-
const cameraInputRef =
|
|
81775
|
-
const libraryInputRef =
|
|
81776
|
-
const [addMediaChooser, setAddMediaChooser] =
|
|
81777
|
-
const [videoCaptureTarget, setVideoCaptureTarget] =
|
|
81778
|
-
const [activeUnitId, setActiveUnitId] =
|
|
81779
|
-
const seededInspection =
|
|
82235
|
+
const cameraInputRef = useRef62(null);
|
|
82236
|
+
const libraryInputRef = useRef62(null);
|
|
82237
|
+
const [addMediaChooser, setAddMediaChooser] = useState64(null);
|
|
82238
|
+
const [videoCaptureTarget, setVideoCaptureTarget] = useState64(null);
|
|
82239
|
+
const [activeUnitId, setActiveUnitId] = useState64(null);
|
|
82240
|
+
const seededInspection = useMemo16(() => {
|
|
81780
82241
|
const insp = data.inspection;
|
|
81781
82242
|
const envelope = insp.propertyFacts ?? {};
|
|
81782
82243
|
return { ...envelope, ...insp };
|
|
@@ -81789,7 +82250,7 @@ function FieldEditorInner({ data }) {
|
|
|
81789
82250
|
ratingLevels: data.ratingLevels,
|
|
81790
82251
|
activeUnitId
|
|
81791
82252
|
});
|
|
81792
|
-
const activePropertyPreset =
|
|
82253
|
+
const activePropertyPreset = useMemo16(() => {
|
|
81793
82254
|
const insp = state.inspection;
|
|
81794
82255
|
return resolveActivePropertyPreset(
|
|
81795
82256
|
insp.propertyType,
|
|
@@ -81797,7 +82258,7 @@ function FieldEditorInner({ data }) {
|
|
|
81797
82258
|
data.commercialPresets
|
|
81798
82259
|
);
|
|
81799
82260
|
}, [state.inspection, data.commercialPresets]);
|
|
81800
|
-
const drainRef =
|
|
82261
|
+
const drainRef = useRef62(() => {
|
|
81801
82262
|
});
|
|
81802
82263
|
const collab = useResultsDoc(String(data.inspection.id), () => drainRef.current());
|
|
81803
82264
|
const writeDoc = readOnly ? null : collab?.doc ?? null;
|
|
@@ -81818,7 +82279,7 @@ function FieldEditorInner({ data }) {
|
|
|
81818
82279
|
});
|
|
81819
82280
|
const { prefs: inspectionPrefs, loaded: prefsLoaded } = useInspectionPrefs();
|
|
81820
82281
|
const tagLibrary = data.tagLibrary ?? [];
|
|
81821
|
-
const catColor =
|
|
82282
|
+
const catColor = useMemo16(() => {
|
|
81822
82283
|
const map = /* @__PURE__ */ new Map();
|
|
81823
82284
|
for (const c of data.defectCategories ?? []) {
|
|
81824
82285
|
map.set(c.name, c.color);
|
|
@@ -81826,18 +82287,18 @@ function FieldEditorInner({ data }) {
|
|
|
81826
82287
|
}
|
|
81827
82288
|
return map;
|
|
81828
82289
|
}, [data.defectCategories]);
|
|
81829
|
-
const pinnedTags =
|
|
82290
|
+
const pinnedTags = useMemo16(() => {
|
|
81830
82291
|
return inspectionPrefs.pinnedTagIds.map((id) => tagLibrary.find((t) => t.id === id)).filter((t) => Boolean(t));
|
|
81831
82292
|
}, [inspectionPrefs.pinnedTagIds, tagLibrary]);
|
|
81832
|
-
const activeTagIds =
|
|
82293
|
+
const activeTagIds = useMemo16(() => {
|
|
81833
82294
|
if (!state.activeItemId) return /* @__PURE__ */ new Set();
|
|
81834
82295
|
const tags = state.tagsByItem?.[state.activeItemId] || [];
|
|
81835
82296
|
return new Set(tags.map((t) => t.id));
|
|
81836
82297
|
}, [state.activeItemId, state.tagsByItem]);
|
|
81837
|
-
const [publishReadiness, setPublishReadiness] =
|
|
81838
|
-
const [showPublishGate, setShowPublishGate] =
|
|
82298
|
+
const [publishReadiness, setPublishReadiness] = useState64(null);
|
|
82299
|
+
const [showPublishGate, setShowPublishGate] = useState64(false);
|
|
81839
82300
|
const activeResult = state.activeItemId ? findings.getResult(state.activeItemId, state.currentSection?.id) : null;
|
|
81840
|
-
const defectStates =
|
|
82301
|
+
const defectStates = useMemo16(() => {
|
|
81841
82302
|
const map = /* @__PURE__ */ new Map();
|
|
81842
82303
|
const defects = activeResult?.tabs;
|
|
81843
82304
|
const rows = Array.isArray(defects?.defects) ? defects.defects : [];
|
|
@@ -81853,7 +82314,7 @@ function FieldEditorInner({ data }) {
|
|
|
81853
82314
|
}
|
|
81854
82315
|
return map;
|
|
81855
82316
|
}, [activeResult]);
|
|
81856
|
-
const inspectionPhotoCount =
|
|
82317
|
+
const inspectionPhotoCount = useMemo16(() => {
|
|
81857
82318
|
const keys = /* @__PURE__ */ new Set();
|
|
81858
82319
|
for (const value of Object.values(state.results)) {
|
|
81859
82320
|
const photos = value?.photos;
|
|
@@ -81864,7 +82325,7 @@ function FieldEditorInner({ data }) {
|
|
|
81864
82325
|
}
|
|
81865
82326
|
return keys.size;
|
|
81866
82327
|
}, [state.results]);
|
|
81867
|
-
const locationSuggestions =
|
|
82328
|
+
const locationSuggestions = useMemo16(() => {
|
|
81868
82329
|
const set = /* @__PURE__ */ new Set();
|
|
81869
82330
|
for (const value of Object.values(state.results)) {
|
|
81870
82331
|
const tabs = value?.tabs;
|
|
@@ -81875,7 +82336,7 @@ function FieldEditorInner({ data }) {
|
|
|
81875
82336
|
}
|
|
81876
82337
|
return Array.from(set);
|
|
81877
82338
|
}, [state.results]);
|
|
81878
|
-
const missingFields =
|
|
82339
|
+
const missingFields = useMemo16(() => {
|
|
81879
82340
|
const map = /* @__PURE__ */ new Map();
|
|
81880
82341
|
if (!publishReadiness) return map;
|
|
81881
82342
|
for (const b of publishReadiness.blockingDefects) {
|
|
@@ -81886,7 +82347,7 @@ function FieldEditorInner({ data }) {
|
|
|
81886
82347
|
}
|
|
81887
82348
|
return map;
|
|
81888
82349
|
}, [publishReadiness]);
|
|
81889
|
-
const requiredDefectFields =
|
|
82350
|
+
const requiredDefectFields = useMemo16(() => {
|
|
81890
82351
|
const override = data.inspection.requireDefectFieldsOverride;
|
|
81891
82352
|
const effective = override ?? inspectionPrefs.requireDefectFields;
|
|
81892
82353
|
return {
|
|
@@ -81898,9 +82359,9 @@ function FieldEditorInner({ data }) {
|
|
|
81898
82359
|
inspectionId: String(state.inspection.id),
|
|
81899
82360
|
severityForRatingId: state.severityForRatingId
|
|
81900
82361
|
});
|
|
81901
|
-
const [serverComments, setServerComments] =
|
|
81902
|
-
const [librarySideOpen, setLibrarySideOpen] =
|
|
81903
|
-
|
|
82362
|
+
const [serverComments, setServerComments] = useState64([]);
|
|
82363
|
+
const [librarySideOpen, setLibrarySideOpen] = useState64(false);
|
|
82364
|
+
useEffect51(() => {
|
|
81904
82365
|
if (!state.showCommentLibrary && !librarySideOpen) {
|
|
81905
82366
|
setServerComments([]);
|
|
81906
82367
|
return;
|
|
@@ -81947,11 +82408,11 @@ function FieldEditorInner({ data }) {
|
|
|
81947
82408
|
const units = data.units ?? [];
|
|
81948
82409
|
const unitInspectionMode = data.unitInspectionMode ?? "tagged";
|
|
81949
82410
|
const isPerUnit = unitInspectionMode === "per_unit";
|
|
81950
|
-
const [unitsManagerOpen, setUnitsManagerOpen] =
|
|
82411
|
+
const [unitsManagerOpen, setUnitsManagerOpen] = useState64(false);
|
|
81951
82412
|
const showUnitsSurface = data.inspection.propertyType === "commercial";
|
|
81952
|
-
const [costItemsOpen, setCostItemsOpen] =
|
|
82413
|
+
const [costItemsOpen, setCostItemsOpen] = useState64(false);
|
|
81953
82414
|
const collabSynced = Boolean(collab?.synced);
|
|
81954
|
-
const mergeScopeSlice =
|
|
82415
|
+
const mergeScopeSlice = useCallback47(
|
|
81955
82416
|
(slice) => state.setResults((prev) => ({ ...prev, ...slice })),
|
|
81956
82417
|
[state.setResults]
|
|
81957
82418
|
);
|
|
@@ -81960,14 +82421,14 @@ function FieldEditorInner({ data }) {
|
|
|
81960
82421
|
collabSynced,
|
|
81961
82422
|
onSlice: mergeScopeSlice
|
|
81962
82423
|
});
|
|
81963
|
-
const requestScope =
|
|
82424
|
+
const requestScope = useCallback47(
|
|
81964
82425
|
(unitId) => {
|
|
81965
82426
|
setActiveUnitId(unitId);
|
|
81966
82427
|
loadScope(unitId);
|
|
81967
82428
|
},
|
|
81968
82429
|
[loadScope]
|
|
81969
82430
|
);
|
|
81970
|
-
|
|
82431
|
+
useEffect51(() => {
|
|
81971
82432
|
if (activeUnitId == null) return;
|
|
81972
82433
|
if (!isPerUnit || !units.some((u) => u.id === activeUnitId)) {
|
|
81973
82434
|
setActiveUnitId(null);
|
|
@@ -81981,29 +82442,32 @@ function FieldEditorInner({ data }) {
|
|
|
81981
82442
|
userName: "Inspector",
|
|
81982
82443
|
enabled: true
|
|
81983
82444
|
});
|
|
81984
|
-
|
|
82445
|
+
useEffect51(() => {
|
|
81985
82446
|
presence.setFocus(state.activeItemId);
|
|
81986
82447
|
}, [state.activeItemId]);
|
|
81987
|
-
const [tagPickerOpen, setTagPickerOpen] =
|
|
81988
|
-
const [autoSign, setAutoSign] =
|
|
82448
|
+
const [tagPickerOpen, setTagPickerOpen] = useState64(false);
|
|
82449
|
+
const [autoSign, setAutoSign] = useState64(
|
|
81989
82450
|
!!state.inspection.autoSignOnPublish
|
|
81990
82451
|
);
|
|
81991
|
-
const [signModalOpen, setSignModalOpen] =
|
|
82452
|
+
const [signModalOpen, setSignModalOpen] = useState64(false);
|
|
81992
82453
|
const inspectorSignature = useInspectorSignature(String(data.inspection.id), () => setSignModalOpen(false));
|
|
81993
|
-
const [versionHistoryOpen, setVersionHistoryOpen] =
|
|
81994
|
-
|
|
82454
|
+
const [versionHistoryOpen, setVersionHistoryOpen] = useState64(false);
|
|
82455
|
+
useEffect51(() => {
|
|
81995
82456
|
setAutoSign(!!state.inspection.autoSignOnPublish);
|
|
81996
82457
|
}, [state.inspection]);
|
|
81997
|
-
const handleAutoSignToggle =
|
|
82458
|
+
const handleAutoSignToggle = useCallback47((checked) => setAutoSign(checked), []);
|
|
81998
82459
|
const publishFlow = usePublishFlow(String(state.inspection.id), {
|
|
81999
82460
|
confirmHuman: ensureHuman,
|
|
82000
82461
|
// The editor's inspection copy is frozen at mount (see useInspectionState), so revalidation alone
|
|
82001
82462
|
// leaves the header badge and the toolbar button stale: patch the status locally as structural edits do.
|
|
82002
82463
|
onMarkedComplete: () => state.setInspection((prev) => ({ ...prev, status: INSPECTION_STATUS_COMPLETED })),
|
|
82003
|
-
onFieldworkFinished: () =>
|
|
82464
|
+
onFieldworkFinished: () => {
|
|
82465
|
+
state.setInspection((prev) => ({ ...prev, status: INSPECTION_STATUS_COMPLETED }));
|
|
82466
|
+
notify(index_exports.editor_finish_fieldwork_done(), "success", { durationMs: 3e3 });
|
|
82467
|
+
},
|
|
82004
82468
|
onPublished: () => state.setShowPublishModal(false)
|
|
82005
82469
|
});
|
|
82006
|
-
const handlePublishClick =
|
|
82470
|
+
const handlePublishClick = useCallback47(async () => {
|
|
82007
82471
|
publishFlow.clearPublishError();
|
|
82008
82472
|
const readiness = await dataSource.resources.publishReadiness?.check(String(state.inspection.id)) ?? null;
|
|
82009
82473
|
if (readiness && (!readiness.ready || (readiness.warningDefects?.length ?? 0) > 0)) {
|
|
@@ -82013,25 +82477,24 @@ function FieldEditorInner({ data }) {
|
|
|
82013
82477
|
}
|
|
82014
82478
|
state.setShowPublishModal(true);
|
|
82015
82479
|
}, [dataSource, state.inspection.id, state.setShowPublishModal, publishFlow.clearPublishError]);
|
|
82016
|
-
|
|
82480
|
+
useEffect51(() => {
|
|
82017
82481
|
if (publishFlow.finishError) notify(publishFlow.finishError, "error", { durationMs: 8e3 });
|
|
82018
82482
|
}, [publishFlow.finishError, notify]);
|
|
82019
|
-
|
|
82020
|
-
|
|
82021
|
-
}, [publishFlow]);
|
|
82483
|
+
useScrollTopOnDetails(state.activeView);
|
|
82484
|
+
const { request: handleFinishFieldwork, dialog: finishDialog } = useFinishFieldworkConfirm(publishFlow.finishFieldwork, publishFlow.finishing);
|
|
82022
82485
|
const commercialSave = useCommercialReportSave(String(state.inspection.id), (patch) => {
|
|
82023
82486
|
state.setInspection((prev) => ({ ...prev, ...patch }));
|
|
82024
82487
|
});
|
|
82025
|
-
const handleItemAttribute =
|
|
82488
|
+
const handleItemAttribute = useCallback47((itemId, attributeId, value) => {
|
|
82026
82489
|
const sectionId = state.sectionIdForItem(itemId);
|
|
82027
82490
|
if (sectionId) findings.setItemAttribute(sectionId, itemId, attributeId, value);
|
|
82028
82491
|
}, [findings, state.sectionIdForItem]);
|
|
82029
|
-
const [photoStudioOpen, setPhotoStudioOpen] =
|
|
82030
|
-
const [photoStudioUrl, setPhotoStudioUrl] =
|
|
82031
|
-
const [photoStudioKey, setPhotoStudioKey] =
|
|
82032
|
-
const [photoStudioIndex, setPhotoStudioIndex] =
|
|
82033
|
-
const [photoStudioTotal, setPhotoStudioTotal] =
|
|
82034
|
-
const openPhotoStudio =
|
|
82492
|
+
const [photoStudioOpen, setPhotoStudioOpen] = useState64(false);
|
|
82493
|
+
const [photoStudioUrl, setPhotoStudioUrl] = useState64(null);
|
|
82494
|
+
const [photoStudioKey, setPhotoStudioKey] = useState64(null);
|
|
82495
|
+
const [photoStudioIndex, setPhotoStudioIndex] = useState64(0);
|
|
82496
|
+
const [photoStudioTotal, setPhotoStudioTotal] = useState64(0);
|
|
82497
|
+
const openPhotoStudio = useCallback47(
|
|
82035
82498
|
(next) => {
|
|
82036
82499
|
setPhotoStudioUrl(next.url);
|
|
82037
82500
|
setPhotoStudioKey(next.key);
|
|
@@ -82044,10 +82507,10 @@ function FieldEditorInner({ data }) {
|
|
|
82044
82507
|
const coverWrites = useReportCoverWrites(String(state.inspection.id));
|
|
82045
82508
|
const statutoryGroups = useStatutoryGroups(data.templateSnapshot);
|
|
82046
82509
|
const canEditStructure = useStructuralEditingAllowed(data.templateSnapshot) && !readOnly;
|
|
82047
|
-
const [addingToGroup, setAddingToGroup] =
|
|
82510
|
+
const [addingToGroup, setAddingToGroup] = useState64(null);
|
|
82048
82511
|
const statutoryInstance = useAddStatutoryInstance(String(data.inspection.id));
|
|
82049
82512
|
const formProgress = useStatutoryFormProgress(data.templateSnapshot, state.results);
|
|
82050
|
-
const revisionBannerEl = data.revisionStatus ? /* @__PURE__ */
|
|
82513
|
+
const revisionBannerEl = data.revisionStatus ? /* @__PURE__ */ jsx135("div", { className: "mb-4", children: /* @__PURE__ */ jsx135(
|
|
82051
82514
|
RevisionBanner,
|
|
82052
82515
|
{
|
|
82053
82516
|
status: data.revisionStatus,
|
|
@@ -82112,36 +82575,33 @@ function FieldEditorInner({ data }) {
|
|
|
82112
82575
|
const layout = useEditorLayout(data.initialLayout, slots.onLayoutObserved);
|
|
82113
82576
|
const isPhone = layout === "phone";
|
|
82114
82577
|
const isMobile = layout !== "desktop";
|
|
82115
|
-
const [mobileDrawer, setMobileDrawer] =
|
|
82578
|
+
const [mobileDrawer, setMobileDrawer] = useState64(null);
|
|
82116
82579
|
const itemUi = useItemEditorUiStore();
|
|
82117
|
-
const notesFlushRef =
|
|
82580
|
+
const notesFlushRef = useRef62(null);
|
|
82118
82581
|
useResetBatchOnPhone(isPhone, state.batchMode, state.setBatchMode, state.setBatchSelected);
|
|
82119
|
-
const
|
|
82582
|
+
const { toggle: toggleItemTag, canSave: canSaveTags } = useItemTags(String(state.inspection.id), state.setTagsByItem);
|
|
82583
|
+
const PRESET_TAGS = useMemo16(() => tagLibrary.length > 0 || canSaveTags ? tagLibrary : [
|
|
82120
82584
|
{ id: "follow-up", name: "Follow Up", color: "#ef4444" },
|
|
82121
82585
|
{ id: "urgent", name: "Urgent", color: "#f97316" },
|
|
82122
82586
|
{ id: "photo-needed", name: "Photo Needed", color: "#eab308" },
|
|
82123
82587
|
{ id: "re-inspect", name: "Re-inspect", color: "#3b82f6" },
|
|
82124
82588
|
{ id: "client-question", name: "Client Question", color: "#a855f7" }
|
|
82125
|
-
], []);
|
|
82126
|
-
const toggleTag =
|
|
82589
|
+
], [tagLibrary, canSaveTags]);
|
|
82590
|
+
const toggleTag = useCallback47((tag) => {
|
|
82127
82591
|
if (!state.activeItemId) return;
|
|
82128
|
-
|
|
82129
|
-
|
|
82130
|
-
|
|
82131
|
-
state.setTagsByItem((prev) => ({
|
|
82132
|
-
...prev,
|
|
82133
|
-
[state.activeItemId]: updated
|
|
82134
|
-
}));
|
|
82135
|
-
}, [state.activeItemId, state.tagsByItem, state.setTagsByItem]);
|
|
82136
|
-
const tagChipRow = state.activeItemId && !readOnly ? /* @__PURE__ */ jsx134(
|
|
82592
|
+
toggleItemTag(state.activeItemId, tag, state.tagsByItem[state.activeItemId] || []);
|
|
82593
|
+
}, [state.activeItemId, state.tagsByItem, toggleItemTag]);
|
|
82594
|
+
const tagChipRow = state.activeItemId && !readOnly ? /* @__PURE__ */ jsx135(
|
|
82137
82595
|
TagChipRow,
|
|
82138
82596
|
{
|
|
82139
82597
|
pinnedTags,
|
|
82598
|
+
chosenTags: state.tagsByItem?.[state.activeItemId],
|
|
82140
82599
|
activeTagIds,
|
|
82141
|
-
onToggle: (tag) => toggleTag(tag)
|
|
82600
|
+
onToggle: (tag) => toggleTag(tag),
|
|
82601
|
+
onOpenLibrary: () => setTagPickerOpen(true)
|
|
82142
82602
|
}
|
|
82143
82603
|
) : null;
|
|
82144
|
-
const handleCloneLast =
|
|
82604
|
+
const handleCloneLast = useCallback47((scope) => {
|
|
82145
82605
|
if (!state.activeItemId || !state.currentSection) return;
|
|
82146
82606
|
findings.cloneLast(
|
|
82147
82607
|
state.currentSection.id,
|
|
@@ -82150,7 +82610,7 @@ function FieldEditorInner({ data }) {
|
|
|
82150
82610
|
scope
|
|
82151
82611
|
);
|
|
82152
82612
|
}, [findings, state.activeItemId, state.currentSection, state.currentSectionItems]);
|
|
82153
|
-
|
|
82613
|
+
useEffect51(() => {
|
|
82154
82614
|
const submitting = photoUpload.busy;
|
|
82155
82615
|
const failed = photoUpload.failedSinceIdle;
|
|
82156
82616
|
if (submitting) {
|
|
@@ -82167,11 +82627,11 @@ function FieldEditorInner({ data }) {
|
|
|
82167
82627
|
}
|
|
82168
82628
|
}
|
|
82169
82629
|
}, [photoUpload.busy]);
|
|
82170
|
-
const commitRating =
|
|
82630
|
+
const commitRating = useCallback47(
|
|
82171
82631
|
(sectionId, itemId, rating) => findings.setRating(sectionId, itemId, rating),
|
|
82172
82632
|
[findings]
|
|
82173
82633
|
);
|
|
82174
|
-
const handleRating =
|
|
82634
|
+
const handleRating = useCallback47(
|
|
82175
82635
|
(rating, source = "pointer") => {
|
|
82176
82636
|
if (!state.activeItemId || !state.currentSection) return;
|
|
82177
82637
|
commitRating(state.currentSection.id, state.activeItemId, rating);
|
|
@@ -82203,14 +82663,14 @@ function FieldEditorInner({ data }) {
|
|
|
82203
82663
|
},
|
|
82204
82664
|
[state.activeItemId, state.currentSection, commitRating, state.advanceToNextUnrated, state.ratingLevels, prefsLoaded, inspectionPrefs.autoAdvance, inspectionPrefs.autoAdvanceDelayMs, notify]
|
|
82205
82665
|
);
|
|
82206
|
-
const commentLibraryItems =
|
|
82666
|
+
const commentLibraryItems = useMemo16(
|
|
82207
82667
|
() => comments.getFilteredComments(
|
|
82208
82668
|
state.commentLibraryFilter,
|
|
82209
82669
|
state.commentLibrarySearch
|
|
82210
82670
|
),
|
|
82211
82671
|
[comments, state.commentLibraryFilter, state.commentLibrarySearch]
|
|
82212
82672
|
);
|
|
82213
|
-
const buildSpeedQueue =
|
|
82673
|
+
const buildSpeedQueue = useCallback47(() => {
|
|
82214
82674
|
const flatItems = [];
|
|
82215
82675
|
for (let s = 0; s < state.sections.length; s++) {
|
|
82216
82676
|
const sec = state.sections[s];
|
|
@@ -82229,8 +82689,8 @@ function FieldEditorInner({ data }) {
|
|
|
82229
82689
|
const queue = flatItems.map((it, idx) => ({ idx, rating: it.rating })).filter((x) => !x.rating).map((x) => x.idx);
|
|
82230
82690
|
return { flatItems, queue };
|
|
82231
82691
|
}, [state.sections, state.getResult]);
|
|
82232
|
-
const speedUnrated =
|
|
82233
|
-
const toggleSpeedMode =
|
|
82692
|
+
const speedUnrated = useMemo16(() => isMobile && !readOnly ? countUnratedItems(state.sections, state.getResult) : 0, [isMobile, readOnly, state.sections, state.getResult, state.results]);
|
|
82693
|
+
const toggleSpeedMode = useCallback47(() => {
|
|
82234
82694
|
if (!state.speedMode) {
|
|
82235
82695
|
const { flatItems, queue } = buildSpeedQueue();
|
|
82236
82696
|
if (queue.length === 0) return;
|
|
@@ -82242,7 +82702,7 @@ function FieldEditorInner({ data }) {
|
|
|
82242
82702
|
state.setSpeedMode(false);
|
|
82243
82703
|
}
|
|
82244
82704
|
}, [state, buildSpeedQueue]);
|
|
82245
|
-
const openSpeedMode =
|
|
82705
|
+
const openSpeedMode = useCallback47(() => {
|
|
82246
82706
|
if (!state.speedMode) toggleSpeedMode();
|
|
82247
82707
|
}, [state.speedMode, toggleSpeedMode]);
|
|
82248
82708
|
const { speedRate, undoSpeedRating, finishedItem, pendingUndo, setPendingUndo } = useSpeedRating({
|
|
@@ -82252,23 +82712,23 @@ function FieldEditorInner({ data }) {
|
|
|
82252
82712
|
activeUnitId,
|
|
82253
82713
|
onUndoUnavailable: () => dataSource.notify(index_exports.editor_speedmode_undo_unavailable(), "error")
|
|
82254
82714
|
});
|
|
82255
|
-
const speedItem =
|
|
82715
|
+
const speedItem = useMemo16(() => {
|
|
82256
82716
|
if (!state.speedMode) return null;
|
|
82257
82717
|
const idx = state.speedQueue[state.speedCurrent];
|
|
82258
82718
|
return idx != null ? state.speedItemsRef.current[idx] || null : null;
|
|
82259
82719
|
}, [state.speedMode, state.speedQueue, state.speedCurrent]);
|
|
82260
|
-
const speedNext =
|
|
82720
|
+
const speedNext = useCallback47(() => {
|
|
82261
82721
|
if (state.speedCurrent < state.speedQueue.length - 1) {
|
|
82262
82722
|
state.setSpeedCurrent(state.speedCurrent + 1);
|
|
82263
82723
|
}
|
|
82264
82724
|
}, [state.speedCurrent, state.speedQueue.length, state.setSpeedCurrent]);
|
|
82265
|
-
const speedPrev =
|
|
82725
|
+
const speedPrev = useCallback47(() => {
|
|
82266
82726
|
if (state.speedCurrent > 0) {
|
|
82267
82727
|
state.setSpeedCurrent(state.speedCurrent - 1);
|
|
82268
82728
|
}
|
|
82269
82729
|
}, [state.speedCurrent, state.setSpeedCurrent]);
|
|
82270
82730
|
const shownSpeedItem = speedItem ?? finishedItem;
|
|
82271
|
-
const speedModeEl = state.speedMode && shownSpeedItem ? /* @__PURE__ */
|
|
82731
|
+
const speedModeEl = state.speedMode && shownSpeedItem ? /* @__PURE__ */ jsx135(
|
|
82272
82732
|
SpeedMode,
|
|
82273
82733
|
{
|
|
82274
82734
|
item: {
|
|
@@ -82306,9 +82766,9 @@ function FieldEditorInner({ data }) {
|
|
|
82306
82766
|
sections: state.sections
|
|
82307
82767
|
}
|
|
82308
82768
|
) : null;
|
|
82309
|
-
const pendingPhotoTargetRef =
|
|
82769
|
+
const pendingPhotoTargetRef = useRef62(null);
|
|
82310
82770
|
const MAX_BATCH_PHOTOS = 20;
|
|
82311
|
-
const handlePhotoUpload =
|
|
82771
|
+
const handlePhotoUpload = useCallback47(
|
|
82312
82772
|
(e) => {
|
|
82313
82773
|
const all = Array.from(e.target.files ?? []);
|
|
82314
82774
|
if (all.length === 0 || !state.activeItemId || readOnly) return;
|
|
@@ -82342,7 +82802,7 @@ function FieldEditorInner({ data }) {
|
|
|
82342
82802
|
},
|
|
82343
82803
|
[state.activeItemId, state.inspection.id, dataSource, photoUpload.submit, notify, writeDoc, readOnly, state.sectionIdForItem, state.currentSection, activeUnitId]
|
|
82344
82804
|
);
|
|
82345
|
-
const handleBurstCommit =
|
|
82805
|
+
const handleBurstCommit = useCallback47(
|
|
82346
82806
|
(blobs) => {
|
|
82347
82807
|
if (blobs.length === 0 || readOnly) return;
|
|
82348
82808
|
if (!state.burstCameraItemId) {
|
|
@@ -82363,8 +82823,8 @@ function FieldEditorInner({ data }) {
|
|
|
82363
82823
|
},
|
|
82364
82824
|
[state.burstCameraItemId, state.sectionIdForItem, state.currentSection, activeUnitId, photoUpload.submit, notify, readOnly]
|
|
82365
82825
|
);
|
|
82366
|
-
const processedUploads =
|
|
82367
|
-
|
|
82826
|
+
const processedUploads = useRef62(/* @__PURE__ */ new WeakSet());
|
|
82827
|
+
useEffect51(() => {
|
|
82368
82828
|
const settled = photoUpload.outcomes.filter((o) => !processedUploads.current.has(o));
|
|
82369
82829
|
if (settled.length === 0) return;
|
|
82370
82830
|
for (const o of settled) processedUploads.current.add(o);
|
|
@@ -82403,17 +82863,17 @@ function FieldEditorInner({ data }) {
|
|
|
82403
82863
|
}
|
|
82404
82864
|
}
|
|
82405
82865
|
}, [photoUpload.outcomes, photoUpload.consume, findings, notify]);
|
|
82406
|
-
const openSnippets =
|
|
82866
|
+
const openSnippets = useCallback47(() => {
|
|
82407
82867
|
if (!state.activeItemId) return;
|
|
82408
82868
|
state.setCommentLibraryFilter("my-snippets");
|
|
82409
82869
|
state.setCommentLibrarySearch("");
|
|
82410
82870
|
state.setCommentLibrarySelectedIdx(0);
|
|
82411
82871
|
state.setShowCommentLibrary(true);
|
|
82412
82872
|
}, [state]);
|
|
82413
|
-
const onInsert =
|
|
82873
|
+
const onInsert = useCallback47((sectionId, itemId, text) => {
|
|
82414
82874
|
findings.insertComment(sectionId, itemId, text);
|
|
82415
82875
|
}, [findings]);
|
|
82416
|
-
const keyboardHandlers =
|
|
82876
|
+
const keyboardHandlers = useMemo16(
|
|
82417
82877
|
() => ({
|
|
82418
82878
|
onRate: (level) => {
|
|
82419
82879
|
if (state.activeItemId && state.currentSection && state.ratingLevels[level - 1]) {
|
|
@@ -82557,7 +83017,7 @@ function FieldEditorInner({ data }) {
|
|
|
82557
83017
|
]
|
|
82558
83018
|
);
|
|
82559
83019
|
useKeyboard(readOnly ? readOnlyKeyboard(keyboardHandlers) : keyboardHandlers, true);
|
|
82560
|
-
const visibleItems =
|
|
83020
|
+
const visibleItems = useMemo16(() => {
|
|
82561
83021
|
return state.currentSectionItems.filter((item) => {
|
|
82562
83022
|
if (!state.itemPassesFilter(item, state.currentSection?.id)) return false;
|
|
82563
83023
|
if (state.searchNeedle && !state.itemMatchesSearch(state.currentSection, item))
|
|
@@ -82565,7 +83025,7 @@ function FieldEditorInner({ data }) {
|
|
|
82565
83025
|
return true;
|
|
82566
83026
|
});
|
|
82567
83027
|
}, [state]);
|
|
82568
|
-
const sectionRailEl = /* @__PURE__ */
|
|
83028
|
+
const sectionRailEl = /* @__PURE__ */ jsx135(
|
|
82569
83029
|
SectionRail,
|
|
82570
83030
|
{
|
|
82571
83031
|
mode: "fill",
|
|
@@ -82594,7 +83054,7 @@ function FieldEditorInner({ data }) {
|
|
|
82594
83054
|
onRenameSection: readOnly ? void 0 : structure.renameSection
|
|
82595
83055
|
}
|
|
82596
83056
|
);
|
|
82597
|
-
const itemListEl = /* @__PURE__ */
|
|
83057
|
+
const itemListEl = /* @__PURE__ */ jsx135(
|
|
82598
83058
|
ItemList,
|
|
82599
83059
|
{
|
|
82600
83060
|
mode: "fill",
|
|
@@ -82607,6 +83067,7 @@ function FieldEditorInner({ data }) {
|
|
|
82607
83067
|
if (isMobile) setMobileDrawer(null);
|
|
82608
83068
|
},
|
|
82609
83069
|
results: state.results,
|
|
83070
|
+
getRatingColor: state.getRatingColor,
|
|
82610
83071
|
activeUnitId,
|
|
82611
83072
|
batchMode: state.batchMode,
|
|
82612
83073
|
batchSelected: state.batchSelected,
|
|
@@ -82620,10 +83081,11 @@ function FieldEditorInner({ data }) {
|
|
|
82620
83081
|
onRenameItem: canEditStructure ? (itemId, label) => structure.renameItem(state.currentSection?.id || "", itemId, label) : void 0,
|
|
82621
83082
|
groups: statutoryGroups,
|
|
82622
83083
|
onAddGroupInstance: readOnly ? void 0 : (groupId) => setAddingToGroup(groupId),
|
|
82623
|
-
pane: layout === "tablet"
|
|
83084
|
+
pane: layout === "tablet",
|
|
83085
|
+
fullWidth: isPhone
|
|
82624
83086
|
}
|
|
82625
83087
|
);
|
|
82626
|
-
const itemEditorEl = state.activeItemId ? readOnly ? /* @__PURE__ */
|
|
83088
|
+
const itemEditorEl = state.activeItemId ? readOnly ? /* @__PURE__ */ jsx135(ReadOnlyItemView, { item: state.activeItem, sectionTitle: state.currentSection?.title, result: findings.getResult(state.activeItemId, state.currentSection?.id), ratingLevels: state.ratingLevels, inspectionId: String(state.inspection.id), coverKey, onOpenPhoto, videoPosterUrl, pendingPhotoUrl }) : /* @__PURE__ */ jsx135(
|
|
82627
83089
|
ItemEditor,
|
|
82628
83090
|
{
|
|
82629
83091
|
uiControl: itemUi(state.activeItemId),
|
|
@@ -82678,14 +83140,9 @@ function FieldEditorInner({ data }) {
|
|
|
82678
83140
|
);
|
|
82679
83141
|
}
|
|
82680
83142
|
},
|
|
82681
|
-
onNotesBlur: (notes) => {
|
|
82682
|
-
|
|
82683
|
-
|
|
82684
|
-
state.currentSection.id,
|
|
82685
|
-
state.activeItemId,
|
|
82686
|
-
notes
|
|
82687
|
-
);
|
|
82688
|
-
}
|
|
83143
|
+
onNotesBlur: (notes, itemId) => {
|
|
83144
|
+
const target = notesCommitTarget({ itemId, activeItemId: state.activeItemId, currentSectionId: state.currentSection?.id, sectionIdForItem: state.sectionIdForItem });
|
|
83145
|
+
if (target) findings.commitNotes(target.sectionId, target.itemId, notes);
|
|
82689
83146
|
},
|
|
82690
83147
|
onValue: (value) => {
|
|
82691
83148
|
if (state.activeItemId && state.currentSection) {
|
|
@@ -82763,7 +83220,7 @@ function FieldEditorInner({ data }) {
|
|
|
82763
83220
|
) : (
|
|
82764
83221
|
/* F12 — the pane offers the next item instead of naming two keys. Items come from the
|
|
82765
83222
|
* SECTION, not `visibleItems`: a filter emptying the list is not an empty section. */
|
|
82766
|
-
/* @__PURE__ */
|
|
83223
|
+
/* @__PURE__ */ jsx135(
|
|
82767
83224
|
ItemPaneEmptyState,
|
|
82768
83225
|
{
|
|
82769
83226
|
items: state.currentSectionItems.map((it) => ({ id: it.id, label: it.label || it.name || "" })),
|
|
@@ -82775,7 +83232,7 @@ function FieldEditorInner({ data }) {
|
|
|
82775
83232
|
}
|
|
82776
83233
|
)
|
|
82777
83234
|
);
|
|
82778
|
-
const sideRailEl = /* @__PURE__ */
|
|
83235
|
+
const sideRailEl = /* @__PURE__ */ jsx135(
|
|
82779
83236
|
SideRail,
|
|
82780
83237
|
{
|
|
82781
83238
|
fill: isMobile,
|
|
@@ -82803,9 +83260,9 @@ function FieldEditorInner({ data }) {
|
|
|
82803
83260
|
}
|
|
82804
83261
|
);
|
|
82805
83262
|
const emptyTemplateEl = state.sections.length === 0 ? /* @__PURE__ */ jsxs114("div", { className: "flex flex-col items-center justify-center h-full gap-4 text-center px-6", children: [
|
|
82806
|
-
/* @__PURE__ */
|
|
82807
|
-
/* @__PURE__ */
|
|
82808
|
-
caps.settingsSheet && !readOnly && /* @__PURE__ */
|
|
83263
|
+
/* @__PURE__ */ jsx135("p", { className: "text-[15px] font-semibold text-ih-fg-1", children: index_exports.editor_route_empty_template_title() }),
|
|
83264
|
+
/* @__PURE__ */ jsx135("p", { className: "text-[13px] text-ih-fg-3 max-w-sm", children: index_exports.editor_route_empty_template_desc() }),
|
|
83265
|
+
caps.settingsSheet && !readOnly && /* @__PURE__ */ jsx135(
|
|
82809
83266
|
Button,
|
|
82810
83267
|
{
|
|
82811
83268
|
variant: "primary",
|
|
@@ -82814,7 +83271,7 @@ function FieldEditorInner({ data }) {
|
|
|
82814
83271
|
}
|
|
82815
83272
|
)
|
|
82816
83273
|
] }) : null;
|
|
82817
|
-
const propertyOverviewEl = /* @__PURE__ */
|
|
83274
|
+
const propertyOverviewEl = /* @__PURE__ */ jsx135(
|
|
82818
83275
|
InspectionOverview,
|
|
82819
83276
|
{
|
|
82820
83277
|
inspection: state.inspection,
|
|
@@ -82833,7 +83290,7 @@ function FieldEditorInner({ data }) {
|
|
|
82833
83290
|
}
|
|
82834
83291
|
);
|
|
82835
83292
|
const photoInputsEl = /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
82836
|
-
/* @__PURE__ */
|
|
83293
|
+
/* @__PURE__ */ jsx135(
|
|
82837
83294
|
"input",
|
|
82838
83295
|
{
|
|
82839
83296
|
ref: cameraInputRef,
|
|
@@ -82844,7 +83301,7 @@ function FieldEditorInner({ data }) {
|
|
|
82844
83301
|
onChange: handlePhotoUpload
|
|
82845
83302
|
}
|
|
82846
83303
|
),
|
|
82847
|
-
/* @__PURE__ */
|
|
83304
|
+
/* @__PURE__ */ jsx135(
|
|
82848
83305
|
"input",
|
|
82849
83306
|
{
|
|
82850
83307
|
ref: libraryInputRef,
|
|
@@ -82857,7 +83314,7 @@ function FieldEditorInner({ data }) {
|
|
|
82857
83314
|
)
|
|
82858
83315
|
] });
|
|
82859
83316
|
const addMediaOverlaysEl = /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
82860
|
-
addMediaChooser && /* @__PURE__ */
|
|
83317
|
+
addMediaChooser && /* @__PURE__ */ jsx135(
|
|
82861
83318
|
AddMediaChooser,
|
|
82862
83319
|
{
|
|
82863
83320
|
onClose: () => setAddMediaChooser(null),
|
|
@@ -82876,7 +83333,7 @@ function FieldEditorInner({ data }) {
|
|
|
82876
83333
|
}
|
|
82877
83334
|
}
|
|
82878
83335
|
),
|
|
82879
|
-
videoCaptureTarget && /* @__PURE__ */
|
|
83336
|
+
videoCaptureTarget && /* @__PURE__ */ jsx135(
|
|
82880
83337
|
VideoCapture,
|
|
82881
83338
|
{
|
|
82882
83339
|
inspectionId: String(state.inspection.id),
|
|
@@ -82891,7 +83348,7 @@ function FieldEditorInner({ data }) {
|
|
|
82891
83348
|
)
|
|
82892
83349
|
] });
|
|
82893
83350
|
const finishActionsEl = /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
82894
|
-
caps.settingsSheet && /* @__PURE__ */
|
|
83351
|
+
caps.settingsSheet && /* @__PURE__ */ jsx135(
|
|
82895
83352
|
InspectionSettingsSheet,
|
|
82896
83353
|
{
|
|
82897
83354
|
open: state.settingsOpen,
|
|
@@ -82900,7 +83357,7 @@ function FieldEditorInner({ data }) {
|
|
|
82900
83357
|
onTemplateApplied: restartAfterTemplate
|
|
82901
83358
|
}
|
|
82902
83359
|
),
|
|
82903
|
-
/* @__PURE__ */
|
|
83360
|
+
/* @__PURE__ */ jsx135(
|
|
82904
83361
|
PublishModal,
|
|
82905
83362
|
{
|
|
82906
83363
|
open: state.showPublishModal,
|
|
@@ -82922,7 +83379,7 @@ function FieldEditorInner({ data }) {
|
|
|
82922
83379
|
onAutoSignToggle: handleAutoSignToggle
|
|
82923
83380
|
}
|
|
82924
83381
|
),
|
|
82925
|
-
/* @__PURE__ */
|
|
83382
|
+
/* @__PURE__ */ jsx135(
|
|
82926
83383
|
SignModal,
|
|
82927
83384
|
{
|
|
82928
83385
|
open: signModalOpen,
|
|
@@ -82931,7 +83388,7 @@ function FieldEditorInner({ data }) {
|
|
|
82931
83388
|
failed: inspectorSignature.failed
|
|
82932
83389
|
}
|
|
82933
83390
|
),
|
|
82934
|
-
/* @__PURE__ */
|
|
83391
|
+
/* @__PURE__ */ jsx135(
|
|
82935
83392
|
PublishGateModal,
|
|
82936
83393
|
{
|
|
82937
83394
|
open: showPublishGate,
|
|
@@ -82955,7 +83412,7 @@ function FieldEditorInner({ data }) {
|
|
|
82955
83412
|
}
|
|
82956
83413
|
)
|
|
82957
83414
|
] });
|
|
82958
|
-
const sharedOverlaysEl = /* @__PURE__ */
|
|
83415
|
+
const sharedOverlaysEl = /* @__PURE__ */ jsx135(
|
|
82959
83416
|
SharedOverlays,
|
|
82960
83417
|
{
|
|
82961
83418
|
state,
|
|
@@ -82992,8 +83449,8 @@ function FieldEditorInner({ data }) {
|
|
|
82992
83449
|
setCostItemsOpen
|
|
82993
83450
|
}
|
|
82994
83451
|
);
|
|
82995
|
-
const itemFilterBarEl = /* @__PURE__ */
|
|
82996
|
-
const batchBarEl = state.batchMode && state.selectedBatchCount > 0 ? /* @__PURE__ */
|
|
83452
|
+
const itemFilterBarEl = /* @__PURE__ */ jsx135(ItemFilterBar, { state, formProgress, isMobile });
|
|
83453
|
+
const batchBarEl = state.batchMode && state.selectedBatchCount > 0 ? /* @__PURE__ */ jsx135(
|
|
82997
83454
|
BatchActionBar,
|
|
82998
83455
|
{
|
|
82999
83456
|
count: state.selectedBatchCount,
|
|
@@ -83028,7 +83485,7 @@ function FieldEditorInner({ data }) {
|
|
|
83028
83485
|
}
|
|
83029
83486
|
}
|
|
83030
83487
|
) : null;
|
|
83031
|
-
const toolsDockEl = /* @__PURE__ */
|
|
83488
|
+
const toolsDockEl = /* @__PURE__ */ jsx135(
|
|
83032
83489
|
InspectorToolsDock,
|
|
83033
83490
|
{
|
|
83034
83491
|
onToggleSpeedMode: toggleSpeedMode,
|
|
@@ -83076,18 +83533,18 @@ function FieldEditorInner({ data }) {
|
|
|
83076
83533
|
sectionTitle: state.activeView === "property" ? "" : state.currentSection?.title ?? "",
|
|
83077
83534
|
itemLabel: state.activeView === "property" ? index_exports.editor_shared_inspection_details() : (state.activeItem?.label || state.activeItem?.name) ?? index_exports.editor_route_select_an_item()
|
|
83078
83535
|
};
|
|
83079
|
-
const scopeSwitcherEl = showUnitsSurface && isPerUnit ? /* @__PURE__ */
|
|
83080
|
-
const saveStatusEl = /* @__PURE__ */
|
|
83536
|
+
const scopeSwitcherEl = showUnitsSurface && isPerUnit ? /* @__PURE__ */ jsx135(BreadcrumbDropdown, { units, activeUnitId, onSelect: requestScope }) : null;
|
|
83537
|
+
const saveStatusEl = /* @__PURE__ */ jsx135(SaveStatusIndicator, { status: state.saveStatus });
|
|
83081
83538
|
const { pdf } = slots;
|
|
83082
83539
|
const mobileDrawersEl = /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
83083
|
-
/* @__PURE__ */
|
|
83540
|
+
/* @__PURE__ */ jsx135(MobileBottomDrawer, { open: mobileDrawer === "sections", onClose: () => setMobileDrawer(null), title: index_exports.editor_route_drawer_sections(), children: sectionRailEl }),
|
|
83084
83541
|
isPhone && /* @__PURE__ */ jsxs114(MobileBottomDrawer, { open: mobileDrawer === "items", onClose: () => setMobileDrawer(null), title: index_exports.editor_route_drawer_items(), children: [
|
|
83085
|
-
scopeSwitcherEl && /* @__PURE__ */
|
|
83086
|
-
speedUnrated > 0 && /* @__PURE__ */
|
|
83542
|
+
scopeSwitcherEl && /* @__PURE__ */ jsx135("div", { className: "px-2 pt-2", children: scopeSwitcherEl }),
|
|
83543
|
+
speedUnrated > 0 && /* @__PURE__ */ jsx135("div", { className: "px-2 pt-2", children: /* @__PURE__ */ jsx135(SpeedEntryButton, { unrated: speedUnrated, onOpen: openSpeedFromDrawer, className: "w-full" }) }),
|
|
83087
83544
|
itemListEl
|
|
83088
83545
|
] }),
|
|
83089
|
-
/* @__PURE__ */
|
|
83090
|
-
/* @__PURE__ */
|
|
83546
|
+
/* @__PURE__ */ jsx135(MobileBottomDrawer, { open: mobileDrawer === "preview", onClose: () => setMobileDrawer(null), title: index_exports.editor_route_drawer_preview(), children: sideRailEl }),
|
|
83547
|
+
/* @__PURE__ */ jsx135(
|
|
83091
83548
|
MobileFinishDrawer,
|
|
83092
83549
|
{
|
|
83093
83550
|
open: mobileDrawer === "actions",
|
|
@@ -83116,9 +83573,9 @@ function FieldEditorInner({ data }) {
|
|
|
83116
83573
|
onOpenCostItems: showUnitsSurface && caps.costItems && !readOnly ? () => setCostItemsOpen(true) : null
|
|
83117
83574
|
}
|
|
83118
83575
|
),
|
|
83119
|
-
/* @__PURE__ */
|
|
83576
|
+
/* @__PURE__ */ jsx135(MobileBottomDrawer, { open: mobileDrawer === "theme", onClose: () => setMobileDrawer(null), title: index_exports.nav_theme_label(), children: /* @__PURE__ */ jsx135("div", { className: "p-4 [&_button]:min-h-11 [&_button]:min-w-11 [&_button]:touch-manipulation", children: slots.renderThemeControl?.({}) }) })
|
|
83120
83577
|
] });
|
|
83121
|
-
|
|
83578
|
+
useEffect51(() => {
|
|
83122
83579
|
if (!readOnly) return;
|
|
83123
83580
|
state.setShowPublishModal(false);
|
|
83124
83581
|
setShowPublishGate(false);
|
|
@@ -83134,16 +83591,17 @@ function FieldEditorInner({ data }) {
|
|
|
83134
83591
|
addMediaOverlaysEl,
|
|
83135
83592
|
sharedOverlaysEl,
|
|
83136
83593
|
speedModeEl,
|
|
83137
|
-
!isPhone && state.showCheatsheet && /* @__PURE__ */
|
|
83594
|
+
!isPhone && state.showCheatsheet && /* @__PURE__ */ jsx135(KeyboardHud, { onClose: () => state.setShowCheatsheet(false) }),
|
|
83138
83595
|
isMobile && mobileDrawersEl,
|
|
83139
83596
|
finishActionsEl,
|
|
83597
|
+
finishDialog,
|
|
83140
83598
|
unsavedGuardEl
|
|
83141
83599
|
] });
|
|
83142
83600
|
if (isPhone) {
|
|
83143
83601
|
return /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
83144
83602
|
overlaysEl,
|
|
83145
83603
|
/* @__PURE__ */ jsxs114("div", { "data-layout": "phone", "data-collab-synced": collabSynced ? "true" : "false", className: "min-h-dvh pb-[calc(3.5rem+env(safe-area-inset-bottom))]", children: [
|
|
83146
|
-
/* @__PURE__ */
|
|
83604
|
+
/* @__PURE__ */ jsx135(
|
|
83147
83605
|
AppBar,
|
|
83148
83606
|
{
|
|
83149
83607
|
platform: dataSource.platform,
|
|
@@ -83155,19 +83613,19 @@ function FieldEditorInner({ data }) {
|
|
|
83155
83613
|
),
|
|
83156
83614
|
/* @__PURE__ */ jsxs114("main", { className: "p-4", children: [
|
|
83157
83615
|
revisionBannerEl,
|
|
83158
|
-
emptyTemplateEl ?? (state.activeView === "property" ? propertyOverviewEl : state.activeItemId ? itemEditorEl : /* @__PURE__ */
|
|
83616
|
+
emptyTemplateEl ?? (state.activeView === "property" ? propertyOverviewEl : state.activeItemId ? itemEditorEl : /* @__PURE__ */ jsx135("p", { className: "text-center text-ih-fg-3 mt-12", children: index_exports.editor_route_mobile_begin() }))
|
|
83159
83617
|
] }),
|
|
83160
|
-
/* @__PURE__ */
|
|
83618
|
+
/* @__PURE__ */ jsx135(MobileDrawerTriggers, { onOpen: (id) => setMobileDrawer(id), showTheme: caps.themeControl })
|
|
83161
83619
|
] }, "phone")
|
|
83162
83620
|
] });
|
|
83163
83621
|
}
|
|
83164
83622
|
if (layout === "tablet") {
|
|
83165
83623
|
return /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
83166
83624
|
overlaysEl,
|
|
83167
|
-
/* @__PURE__ */
|
|
83625
|
+
/* @__PURE__ */ jsx135(
|
|
83168
83626
|
TabletTree,
|
|
83169
83627
|
{
|
|
83170
|
-
appBar: /* @__PURE__ */
|
|
83628
|
+
appBar: /* @__PURE__ */ jsx135(
|
|
83171
83629
|
AppBar,
|
|
83172
83630
|
{
|
|
83173
83631
|
tablet: true,
|
|
@@ -83176,17 +83634,17 @@ function FieldEditorInner({ data }) {
|
|
|
83176
83634
|
onBack: () => goBack(false),
|
|
83177
83635
|
onOpenSections: () => setMobileDrawer("sections"),
|
|
83178
83636
|
onMore: () => setMobileDrawer("actions"),
|
|
83179
|
-
actions: /* @__PURE__ */
|
|
83637
|
+
actions: /* @__PURE__ */ jsx135(TabletActions, { onPreview: () => setMobileDrawer("preview"), onPublish: handlePublishClick }),
|
|
83180
83638
|
status: saveStatusEl
|
|
83181
83639
|
}
|
|
83182
83640
|
),
|
|
83183
83641
|
collabSynced,
|
|
83184
|
-
footer: /* @__PURE__ */
|
|
83642
|
+
footer: /* @__PURE__ */ jsx135(FooterBar, { connected: presence.connected, status: presence.status, roster: presence.roster }),
|
|
83185
83643
|
listHeader: /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
83186
|
-
/* @__PURE__ */
|
|
83187
|
-
scopeSwitcherEl && /* @__PURE__ */
|
|
83644
|
+
/* @__PURE__ */ jsx135(InspectionIdentity, { address: state.inspection.propertyAddress, id: String(state.inspection.id), date: state.formattedDate, status: String(state.inspection.status) }),
|
|
83645
|
+
scopeSwitcherEl && /* @__PURE__ */ jsx135("div", { className: "px-3 py-2 border-b border-ih-border", children: scopeSwitcherEl }),
|
|
83188
83646
|
itemFilterBarEl,
|
|
83189
|
-
speedUnrated > 0 && /* @__PURE__ */
|
|
83647
|
+
speedUnrated > 0 && /* @__PURE__ */ jsx135("div", { className: "px-3 py-2 border-b border-ih-border", children: /* @__PURE__ */ jsx135(SpeedEntryButton, { unrated: speedUnrated, onOpen: openSpeedMode, className: "w-full" }) })
|
|
83190
83648
|
] }),
|
|
83191
83649
|
sectionTitle: state.currentSection?.title ?? "",
|
|
83192
83650
|
list: itemListEl,
|
|
@@ -83211,7 +83669,7 @@ function FieldEditorInner({ data }) {
|
|
|
83211
83669
|
"data-collab-synced": collabSynced ? "true" : "false",
|
|
83212
83670
|
className: "flex h-screen bg-ih-bg-card overflow-x-auto",
|
|
83213
83671
|
children: [
|
|
83214
|
-
/* @__PURE__ */
|
|
83672
|
+
/* @__PURE__ */ jsx135(
|
|
83215
83673
|
EditorHeader,
|
|
83216
83674
|
{
|
|
83217
83675
|
state,
|
|
@@ -83226,33 +83684,33 @@ function FieldEditorInner({ data }) {
|
|
|
83226
83684
|
onSaveAsNewTemplate: () => structure.openSaveTemplate("new"),
|
|
83227
83685
|
onUpdateSourceTemplate: () => structure.openSaveTemplate("back"),
|
|
83228
83686
|
canUpdateSourceTemplate: structure.canSaveBack,
|
|
83229
|
-
perUnitControls: showUnitsSurface ? /* @__PURE__ */
|
|
83687
|
+
perUnitControls: showUnitsSurface ? /* @__PURE__ */ jsx135(UnitControls, { isPerUnit, units, activeUnitId, onSelectScope: requestScope, onOpenUnits: () => setUnitsManagerOpen(true), onOpenCostItems: () => setCostItemsOpen(true) }) : void 0
|
|
83230
83688
|
}
|
|
83231
83689
|
),
|
|
83232
|
-
/* @__PURE__ */
|
|
83690
|
+
/* @__PURE__ */ jsx135("div", { className: "flex flex-1 pt-14 pb-9 min-w-[1024px]", children: emptyTemplateEl ? /* @__PURE__ */ jsx135("div", { className: "flex-1 flex", children: emptyTemplateEl }) : /* @__PURE__ */ jsxs114(Fragment37, { children: [
|
|
83233
83691
|
!state.itemFullscreen && sectionRailEl,
|
|
83234
83692
|
!state.itemFullscreen && /* @__PURE__ */ jsxs114("div", { className: "w-[280px] flex-shrink-0 border-r border-ih-border flex flex-col overflow-hidden relative", children: [
|
|
83235
83693
|
itemFilterBarEl,
|
|
83236
83694
|
itemListEl
|
|
83237
83695
|
] }),
|
|
83238
83696
|
/* @__PURE__ */ jsxs114("div", { className: "flex-1 min-w-0 relative flex flex-col border-t-2 border-ih-primary", children: [
|
|
83239
|
-
state.activeView !== "property" && /* @__PURE__ */
|
|
83697
|
+
state.activeView !== "property" && /* @__PURE__ */ jsx135("div", { className: "absolute top-2.5 right-2.5 z-10", children: /* @__PURE__ */ jsx135(FullscreenToggle, { active: state.itemFullscreen, onToggle: () => state.setItemFullscreen(!state.itemFullscreen) }) }),
|
|
83240
83698
|
/* @__PURE__ */ jsxs114("main", { className: "flex-1 overflow-y-auto p-6", children: [
|
|
83241
83699
|
revisionBannerEl,
|
|
83242
83700
|
state.activeView === "property" ? propertyOverviewEl : itemEditorEl
|
|
83243
83701
|
] })
|
|
83244
83702
|
] }),
|
|
83245
|
-
!state.itemFullscreen && (state.sideRailCollapsed ? /* @__PURE__ */
|
|
83703
|
+
!state.itemFullscreen && (state.sideRailCollapsed ? /* @__PURE__ */ jsx135("div", { className: "w-8 flex-shrink-0 border-l border-ih-border flex flex-col items-center pt-3", children: /* @__PURE__ */ jsx135(
|
|
83246
83704
|
IconButton,
|
|
83247
83705
|
{
|
|
83248
83706
|
"aria-label": index_exports.editor_route_expand_photo_rail(),
|
|
83249
83707
|
onClick: () => state.setSideRailCollapsed(false),
|
|
83250
83708
|
size: "sm",
|
|
83251
83709
|
title: index_exports.editor_route_expand_photo_rail(),
|
|
83252
|
-
children: /* @__PURE__ */
|
|
83710
|
+
children: /* @__PURE__ */ jsx135("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx135("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
83253
83711
|
}
|
|
83254
83712
|
) }) : /* @__PURE__ */ jsxs114("div", { className: "relative flex-shrink-0", children: [
|
|
83255
|
-
/* @__PURE__ */
|
|
83713
|
+
/* @__PURE__ */ jsx135(
|
|
83256
83714
|
IconButton,
|
|
83257
83715
|
{
|
|
83258
83716
|
"aria-label": index_exports.editor_route_collapse_photo_rail(),
|
|
@@ -83260,14 +83718,14 @@ function FieldEditorInner({ data }) {
|
|
|
83260
83718
|
size: "sm",
|
|
83261
83719
|
className: "absolute top-3 left-1 z-10 w-6 h-6",
|
|
83262
83720
|
title: index_exports.editor_route_collapse_photo_rail(),
|
|
83263
|
-
children: /* @__PURE__ */
|
|
83721
|
+
children: /* @__PURE__ */ jsx135("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx135("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
83264
83722
|
}
|
|
83265
83723
|
),
|
|
83266
83724
|
sideRailEl
|
|
83267
83725
|
] }))
|
|
83268
83726
|
] }) }),
|
|
83269
83727
|
batchBarEl,
|
|
83270
|
-
/* @__PURE__ */
|
|
83728
|
+
/* @__PURE__ */ jsx135(FooterBar, { connected: presence.connected, status: presence.status, roster: presence.roster }),
|
|
83271
83729
|
toolsDockEl
|
|
83272
83730
|
]
|
|
83273
83731
|
},
|
|
@@ -83276,7 +83734,7 @@ function FieldEditorInner({ data }) {
|
|
|
83276
83734
|
] });
|
|
83277
83735
|
}
|
|
83278
83736
|
function FieldEditor({ data, readOnly = false }) {
|
|
83279
|
-
return /* @__PURE__ */
|
|
83737
|
+
return /* @__PURE__ */ jsx135(ReadOnlyScope, { readOnly, children: /* @__PURE__ */ jsx135(FieldEditorInner, { data }) });
|
|
83280
83738
|
}
|
|
83281
83739
|
|
|
83282
83740
|
// src/shared/pca-narrative.ts
|