88} from '@geotab/zenith' ;
99import { useGeotab } from '@/contexts' ;
1010import { useRequests } from '@/hooks' ;
11+ import { loadUnmergedSubmissions , SubmissionRecord } from '@/services' ;
12+ import { DriverSubmission } from '@/types' ;
1113
1214interface NewRequestModalProps {
1315 isOpen : boolean ;
@@ -112,7 +114,7 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
112114 onSubmit,
113115 toast
114116} ) => {
115- const { devices, loadDevices } = useGeotab ( ) ;
117+ const { api , devices, loadDevices } = useGeotab ( ) ;
116118 const { submit } = useRequests ( ) ;
117119
118120 const [ selectedDeviceId , setSelectedDeviceId ] = useState < string > ( '' ) ;
@@ -125,13 +127,32 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
125127 const [ forceReport , setForceReport ] = useState ( false ) ;
126128 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
127129 const [ activePreset , setActivePreset ] = useState < 'hour' | '24h' | null > ( 'hour' ) ;
130+
131+ // Driver submissions state
132+ const [ submissions , setSubmissions ] = useState < SubmissionRecord [ ] > ( [ ] ) ;
133+ const [ selectedSubmissionId , setSelectedSubmissionId ] = useState < string > ( '' ) ;
134+ const [ loadingSubmissions , setLoadingSubmissions ] = useState ( false ) ;
128135
129136 // Load devices when modal opens
130137 useEffect ( ( ) => {
131138 if ( isOpen && devices . length === 0 ) {
132139 loadDevices ( ) ;
133140 }
134141 } , [ isOpen , devices . length , loadDevices ] ) ;
142+
143+ // Load unmerged submissions when modal opens
144+ useEffect ( ( ) => {
145+ if ( isOpen && api ) {
146+ setLoadingSubmissions ( true ) ;
147+ loadUnmergedSubmissions ( api )
148+ . then ( setSubmissions )
149+ . catch ( err => {
150+ console . warn ( 'Failed to load submissions:' , err ) ;
151+ setSubmissions ( [ ] ) ;
152+ } )
153+ . finally ( ( ) => setLoadingSubmissions ( false ) ) ;
154+ }
155+ } , [ isOpen , api ] ) ;
135156
136157 const deviceOptions = useMemo ( ( ) =>
137158 devices . map ( d => ( {
@@ -145,6 +166,32 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
145166 devices . find ( d => d . id === selectedDeviceId ) ,
146167 [ devices , selectedDeviceId ]
147168 ) ;
169+
170+ // Filter submissions for selected device
171+ const deviceSubmissions = useMemo ( ( ) => {
172+ if ( ! selectedDeviceId ) return submissions ;
173+ return submissions . filter ( s => s . submission . deviceId === selectedDeviceId ) ;
174+ } , [ submissions , selectedDeviceId ] ) ;
175+
176+ // Format submission for dropdown
177+ const submissionOptions = useMemo ( ( ) =>
178+ deviceSubmissions . map ( s => {
179+ const date = new Date ( s . submission . incidentTimestamp ) ;
180+ const dateStr = date . toLocaleDateString ( ) + ' ' + date . toLocaleTimeString ( [ ] , { hour : '2-digit' , minute : '2-digit' } ) ;
181+ const driver = s . submission . driverName || 'Unknown driver' ;
182+ const vehicle = s . submission . deviceName || 'Unknown vehicle' ;
183+ return {
184+ id : s . submission . id ,
185+ name : `${ dateStr } - ${ driver } (${ vehicle } )`
186+ } ;
187+ } ) ,
188+ [ deviceSubmissions ]
189+ ) ;
190+
191+ const selectedSubmission = useMemo ( ( ) =>
192+ submissions . find ( s => s . submission . id === selectedSubmissionId ) ?. submission ,
193+ [ submissions , selectedSubmissionId ]
194+ ) ;
148195
149196 const handleSubmit = useCallback ( async ( ) => {
150197 if ( ! selectedDeviceId ) {
@@ -165,15 +212,16 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
165212 selectedDevice ?. name || 'Unknown' ,
166213 rangeStart ,
167214 rangeEnd ,
168- forceReport
215+ forceReport ,
216+ selectedSubmissionId || undefined
169217 ) ;
170218 onSubmit ( ) ;
171219 } catch ( err ) {
172220 toast . error ( err instanceof Error ? err . message : 'Failed to submit request' ) ;
173221 } finally {
174222 setIsSubmitting ( false ) ;
175223 }
176- } , [ selectedDeviceId , selectedDevice , rangeStart , rangeEnd , forceReport , submit , onSubmit , toast ] ) ;
224+ } , [ selectedDeviceId , selectedDevice , rangeStart , rangeEnd , forceReport , selectedSubmissionId , submit , onSubmit , toast ] ) ;
177225
178226 const handleSetLastHour = useCallback ( ( ) => {
179227 const end = new Date ( ) ;
@@ -194,6 +242,25 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
194242 const handleCustomDateChange = useCallback ( ( ) => {
195243 setActivePreset ( null ) ;
196244 } , [ ] ) ;
245+
246+ // When a submission is selected, auto-fill device and time range
247+ const handleSubmissionSelect = useCallback ( ( submissionId : string ) => {
248+ setSelectedSubmissionId ( submissionId ) ;
249+ const submission = submissions . find ( s => s . submission . id === submissionId ) ?. submission ;
250+ if ( submission ) {
251+ // Set device
252+ setSelectedDeviceId ( submission . deviceId ) ;
253+ // Set time range: 30 min before to 30 min after incident
254+ const incidentTime = new Date ( submission . incidentTimestamp ) ;
255+ const start = new Date ( incidentTime . getTime ( ) - 30 * 60 * 1000 ) ;
256+ const end = new Date ( incidentTime . getTime ( ) + 30 * 60 * 1000 ) ;
257+ setRangeStart ( start ) ;
258+ setRangeEnd ( end ) ;
259+ setActivePreset ( null ) ;
260+ // Force report since we're linking to a submission
261+ setForceReport ( true ) ;
262+ }
263+ } , [ submissions ] ) ;
197264
198265 if ( ! isOpen ) return null ;
199266
@@ -204,6 +271,48 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
204271 title = "New Report Request"
205272 >
206273 < Modal . Content >
274+ { /* Driver Submission Section - shown if there are unmerged submissions */ }
275+ { submissions . length > 0 && (
276+ < div style = { styles . formField } >
277+ < label style = { styles . label } > Link to Driver Submission (Optional)</ label >
278+ < Dropdown
279+ dataItems = { submissionOptions }
280+ value = { selectedSubmissionId ? [ selectedSubmissionId ] : [ ] }
281+ onChange = { ( selected : any [ ] ) => {
282+ const id = selected ?. [ 0 ] ?. id || '' ;
283+ if ( id ) {
284+ handleSubmissionSelect ( id ) ;
285+ } else {
286+ setSelectedSubmissionId ( '' ) ;
287+ }
288+ } }
289+ placeholder = { loadingSubmissions ? "Loading submissions..." : "Select a driver submission to link..." }
290+ searchField = { true }
291+ multiselect = { false }
292+ errorHandler = { ( e ) => console . error ( 'Dropdown error:' , e ) }
293+ />
294+ { selectedSubmission && (
295+ < div style = { {
296+ marginTop : '8px' ,
297+ padding : '12px' ,
298+ backgroundColor : 'var(--zen-color-background-secondary, #f0f9ff)' ,
299+ borderRadius : '6px' ,
300+ border : '1px solid var(--zen-color-info, #0ea5e9)' ,
301+ fontSize : '13px'
302+ } } >
303+ < strong > Driver submission selected</ strong >
304+ < div style = { { marginTop : '4px' , color : 'var(--zen-color-text-secondary, #6b7280)' } } >
305+ { selectedSubmission . description || 'No description' }
306+ { selectedSubmission . driverName && ` — ${ selectedSubmission . driverName } ` }
307+ </ div >
308+ < div style = { { marginTop : '4px' , fontSize : '12px' , color : 'var(--zen-color-text-tertiary, #9ca3af)' } } >
309+ The vehicle, time range, and force report options have been auto-filled.
310+ </ div >
311+ </ div >
312+ ) }
313+ </ div >
314+ ) }
315+
207316 < div style = { styles . formField } >
208317 < label style = { styles . label } > Vehicle</ label >
209318 < Dropdown
@@ -212,6 +321,10 @@ export const NewRequestModal: React.FC<NewRequestModalProps> = ({
212321 onChange = { ( selected : any [ ] ) => {
213322 const id = selected ?. [ 0 ] ?. id || '' ;
214323 setSelectedDeviceId ( id ) ;
324+ // Clear submission if device changes
325+ if ( selectedSubmissionId && id !== selectedSubmission ?. deviceId ) {
326+ setSelectedSubmissionId ( '' ) ;
327+ }
215328 } }
216329 placeholder = "Select a vehicle..."
217330 searchField = { true }
0 commit comments