@@ -20,6 +20,10 @@ import { Topic } from '@/lib/topic/types'
2020import { extractSpeakerIds } from '@/lib/proposal/utils'
2121import { validateProposalForAdmin } from '@/lib/proposal/validation'
2222import { SpeakerMultiSelect } from '@/components/admin/SpeakerMultiSelect'
23+ import { ProposalCoSpeaker } from '@/components/cfp/ProposalCoSpeaker'
24+ import { CoSpeakerInvitationMinimal } from '@/lib/cospeaker/types'
25+ import { Speaker } from '@/lib/speaker/types'
26+ import { extractSpeakersFromProposal } from '@/lib/proposal/utils'
2327import { api } from '@/lib/trpc/client'
2428import { useQueryClient } from '@tanstack/react-query'
2529import { ProposalDetailsForm } from '@/components/proposal/ProposalDetailsForm'
@@ -105,6 +109,19 @@ export function ProposalManagementModal({
105109 Record < string , string >
106110 > ( { } )
107111
112+ const getInitialCoSpeakers = ( ) : Speaker [ ] => {
113+ if ( ! editingProposal ) return [ ]
114+ const allSpeakers = extractSpeakersFromProposal ( editingProposal )
115+ return allSpeakers . slice ( 1 )
116+ }
117+
118+ const [ coSpeakers , setCoSpeakers ] = useState < Speaker [ ] > (
119+ getInitialCoSpeakers ( ) ,
120+ )
121+ const [ invitations , setInvitations ] = useState < CoSpeakerInvitationMinimal [ ] > (
122+ editingProposal ?. coSpeakerInvitations || [ ] ,
123+ )
124+
108125 // Validate that topics are properly expanded - this will throw a helpful error
109126 // if the parent page forgot to pass `topics: true` to getConferenceForCurrentDomain
110127 useEffect ( ( ) => {
@@ -186,32 +203,37 @@ export function ProposalManagementModal({
186203 setProposalData (
187204 editingProposal
188205 ? {
189- title : editingProposal . title || '' ,
190- description : editingProposal . description || [ ] ,
191- language : editingProposal . language || Language . norwegian ,
192- format :
193- editingProposal . format ||
194- conference . formats ?. [ 0 ] ||
195- Format . lightning_10 ,
196- level : editingProposal . level || Level . beginner ,
197- audiences : editingProposal . audiences || [ ] ,
198- topics : validTopics ,
199- outline : editingProposal . outline || '' ,
200- tos : true ,
201- }
206+ title : editingProposal . title || '' ,
207+ description : editingProposal . description || [ ] ,
208+ language : editingProposal . language || Language . norwegian ,
209+ format :
210+ editingProposal . format ||
211+ conference . formats ?. [ 0 ] ||
212+ Format . lightning_10 ,
213+ level : editingProposal . level || Level . beginner ,
214+ audiences : editingProposal . audiences || [ ] ,
215+ topics : validTopics ,
216+ outline : editingProposal . outline || '' ,
217+ tos : true ,
218+ }
202219 : {
203- title : '' ,
204- description : [ ] ,
205- language : Language . norwegian ,
206- format : conference . formats ?. [ 0 ] || Format . lightning_10 ,
207- level : Level . beginner ,
208- audiences : [ ] ,
209- topics : [ ] ,
210- outline : '' ,
211- tos : false ,
212- } ,
220+ title : '' ,
221+ description : [ ] ,
222+ language : Language . norwegian ,
223+ format : conference . formats ?. [ 0 ] || Format . lightning_10 ,
224+ level : Level . beginner ,
225+ audiences : [ ] ,
226+ topics : [ ] ,
227+ outline : '' ,
228+ tos : false ,
229+ } ,
213230 )
214231 setSelectedSpeakerIds ( extractSpeakerIds ( editingProposal ?. speakers ) || [ ] )
232+ const allSpeakers = editingProposal
233+ ? extractSpeakersFromProposal ( editingProposal )
234+ : [ ]
235+ setCoSpeakers ( allSpeakers . slice ( 1 ) )
236+ setInvitations ( editingProposal ?. coSpeakerInvitations || [ ] )
215237 }
216238 // eslint-disable-next-line react-hooks/exhaustive-deps -- conference.formats and editingProposal are stable, isOpen triggers reset
217239 } , [ isOpen ] )
@@ -379,6 +401,32 @@ export function ProposalManagementModal({
379401 />
380402 </ div >
381403
404+ { editingProposal && (
405+ < div className = "mb-6" >
406+ < ProposalCoSpeaker
407+ selectedSpeakers = { coSpeakers }
408+ onSpeakersChange = { ( speakers ) => {
409+ setCoSpeakers ( speakers )
410+ const primaryId = selectedSpeakerIds [ 0 ]
411+ const allIds = [
412+ primaryId ,
413+ ...speakers . map ( ( s ) => s . _id ) ,
414+ ] . filter ( Boolean )
415+ setSelectedSpeakerIds ( allIds )
416+ } }
417+ format = { proposalData . format }
418+ proposalId = { editingProposal . _id }
419+ pendingInvitations = { invitations }
420+ onInvitationSent = { ( inv ) =>
421+ setInvitations ( ( prev ) => [ ...prev , inv ] )
422+ }
423+ onInvitationCanceled = { ( id ) =>
424+ setInvitations ( ( prev ) => prev . filter ( ( inv ) => inv . _id !== id ) )
425+ }
426+ />
427+ </ div >
428+ ) }
429+
382430 { /* Proposal Details Section */ }
383431 < ProposalDetailsForm
384432 proposal = { proposalData }
0 commit comments