@@ -41,6 +41,8 @@ import {
4141 AccordionItem ,
4242 AccordionTrigger ,
4343} from "@usesend/ui/src/accordion" ;
44+ import ScheduleCampaign from "../../schedule-campaign" ;
45+ import { useRouter } from "next/navigation" ;
4446
4547const sendSchema = z . object ( {
4648 confirmation : z . string ( ) ,
@@ -63,7 +65,7 @@ export default function EditCampaignPage({
6365 { campaignId } ,
6466 {
6567 enabled : ! ! campaignId ,
66- } ,
68+ }
6769 ) ;
6870
6971 if ( isLoading ) {
@@ -94,38 +96,33 @@ function CampaignEditor({
9496} : {
9597 campaign : Campaign & { imageUploadSupported : boolean } ;
9698} ) {
99+ const router = useRouter ( ) ;
97100 const contactBooksQuery = api . contacts . getContactBooks . useQuery ( { } ) ;
98101 const utils = api . useUtils ( ) ;
99102
100103 const [ json , setJson ] = useState < Record < string , any > | undefined > (
101- campaign . content ? JSON . parse ( campaign . content ) : undefined ,
104+ campaign . content ? JSON . parse ( campaign . content ) : undefined
102105 ) ;
103106 const [ isSaving , setIsSaving ] = useState ( false ) ;
104107 const [ name , setName ] = useState ( campaign . name ) ;
105108 const [ subject , setSubject ] = useState ( campaign . subject ) ;
106109 const [ from , setFrom ] = useState ( campaign . from ) ;
107110 const [ contactBookId , setContactBookId ] = useState ( campaign . contactBookId ) ;
108111 const [ replyTo , setReplyTo ] = useState < string | undefined > (
109- campaign . replyTo [ 0 ] ,
112+ campaign . replyTo [ 0 ]
110113 ) ;
111114 const [ previewText , setPreviewText ] = useState < string | null > (
112- campaign . previewText ,
115+ campaign . previewText
113116 ) ;
114- const [ openSendDialog , setOpenSendDialog ] = useState ( false ) ;
115117
116118 const updateCampaignMutation = api . campaign . updateCampaign . useMutation ( {
117119 onSuccess : ( ) => {
118120 utils . campaign . getCampaign . invalidate ( ) ;
119121 setIsSaving ( false ) ;
120122 } ,
121123 } ) ;
122- const sendCampaignMutation = api . campaign . sendCampaign . useMutation ( ) ;
123124 const getUploadUrl = api . campaign . generateImagePresignedUrl . useMutation ( ) ;
124125
125- const sendForm = useForm < z . infer < typeof sendSchema > > ( {
126- resolver : zodResolver ( sendSchema ) ,
127- } ) ;
128-
129126 function updateEditorContent ( ) {
130127 updateCampaignMutation . mutate ( {
131128 campaignId : campaign . id ,
@@ -135,39 +132,13 @@ function CampaignEditor({
135132
136133 const deboucedUpdateCampaign = useDebouncedCallback (
137134 updateEditorContent ,
138- 1000 ,
135+ 1000
139136 ) ;
140137
141- async function onSendCampaign ( values : z . infer < typeof sendSchema > ) {
142- if (
143- values . confirmation ?. toLocaleLowerCase ( ) !== "Send" . toLocaleLowerCase ( )
144- ) {
145- sendForm . setError ( "confirmation" , {
146- message : "Please type 'Send' to confirm" ,
147- } ) ;
148- return ;
149- }
150-
151- sendCampaignMutation . mutate (
152- {
153- campaignId : campaign . id ,
154- } ,
155- {
156- onSuccess : ( ) => {
157- setOpenSendDialog ( false ) ;
158- toast . success ( `Campaign sent successfully` ) ;
159- } ,
160- onError : ( error ) => {
161- toast . error ( `Failed to send campaign: ${ error . message } ` ) ;
162- } ,
163- } ,
164- ) ;
165- }
166-
167138 const handleFileChange = async ( file : File ) => {
168139 if ( file . size > IMAGE_SIZE_LIMIT ) {
169140 throw new Error (
170- `File should be less than ${ IMAGE_SIZE_LIMIT / 1024 / 1024 } MB` ,
141+ `File should be less than ${ IMAGE_SIZE_LIMIT / 1024 / 1024 } MB`
171142 ) ;
172143 }
173144
@@ -191,10 +162,8 @@ function CampaignEditor({
191162 return imageUrl ;
192163 } ;
193164
194- const confirmation = sendForm . watch ( "confirmation" ) ;
195-
196165 const contactBook = contactBooksQuery . data ?. find (
197- ( book ) => book . id === contactBookId ,
166+ ( book ) => book . id === contactBookId
198167 ) ;
199168
200169 return (
@@ -220,7 +189,7 @@ function CampaignEditor({
220189 toast . error ( `${ e . message } . Reverting changes.` ) ;
221190 setName ( campaign . name ) ;
222191 } ,
223- } ,
192+ }
224193 ) ;
225194 } }
226195 />
@@ -235,56 +204,13 @@ function CampaignEditor({
235204 ? "just now"
236205 : `${ formatDistanceToNow ( campaign . updatedAt ) } ago` }
237206 </ div >
238- < Dialog open = { openSendDialog } onOpenChange = { setOpenSendDialog } >
239- < DialogTrigger asChild >
240- < Button variant = "default" > Send Campaign</ Button >
241- </ DialogTrigger >
242- < DialogContent >
243- < DialogHeader >
244- < DialogTitle > Send Campaign</ DialogTitle >
245- < DialogDescription >
246- Are you sure you want to send this campaign? This action
247- cannot be undone.
248- </ DialogDescription >
249- </ DialogHeader >
250- < div className = "py-2" >
251- < Form { ...sendForm } >
252- < form
253- onSubmit = { sendForm . handleSubmit ( onSendCampaign ) }
254- className = "space-y-4"
255- >
256- < FormField
257- control = { sendForm . control }
258- name = "confirmation"
259- render = { ( { field } ) => (
260- < FormItem >
261- < FormLabel > Type 'Send' to confirm</ FormLabel >
262- < FormControl >
263- < Input { ...field } />
264- </ FormControl >
265- < FormMessage />
266- </ FormItem >
267- ) }
268- />
269- < div className = "flex justify-end" >
270- < Button
271- type = "submit"
272- disabled = {
273- sendCampaignMutation . isPending ||
274- confirmation ?. toLocaleLowerCase ( ) !==
275- "Send" . toLocaleLowerCase ( )
276- }
277- >
278- { sendCampaignMutation . isPending
279- ? "Sending..."
280- : "Send" }
281- </ Button >
282- </ div >
283- </ form >
284- </ Form >
285- </ div >
286- </ DialogContent >
287- </ Dialog >
207+
208+ < ScheduleCampaign
209+ campaign = { campaign }
210+ onScheduled = { ( ) => {
211+ router . push ( `/campaigns/${ campaign . id } ` ) ;
212+ } }
213+ />
288214 </ div >
289215 </ div >
290216
@@ -315,7 +241,7 @@ function CampaignEditor({
315241 toast . error ( `${ e . message } . Reverting changes.` ) ;
316242 setSubject ( campaign . subject ) ;
317243 } ,
318- } ,
244+ }
319245 ) ;
320246 } }
321247 className = "mt-1 py-1 text-sm block w-full outline-none border-b border-transparent focus:border-border bg-transparent"
@@ -350,7 +276,7 @@ function CampaignEditor({
350276 toast . error ( `${ e . message } . Reverting changes.` ) ;
351277 setFrom ( campaign . from ) ;
352278 } ,
353- } ,
279+ }
354280 ) ;
355281 } }
356282 />
@@ -381,7 +307,7 @@ function CampaignEditor({
381307 toast . error ( `${ e . message } . Reverting changes.` ) ;
382308 setReplyTo ( campaign . replyTo [ 0 ] ) ;
383309 } ,
384- } ,
310+ }
385311 ) ;
386312 } }
387313 />
@@ -414,7 +340,7 @@ function CampaignEditor({
414340 toast . error ( `${ e . message } . Reverting changes.` ) ;
415341 setPreviewText ( campaign . previewText ?? "" ) ;
416342 } ,
417- } ,
343+ }
418344 ) ;
419345 } }
420346 className = "mt-1 py-1 text-sm block w-full outline-none border-b border-transparent bg-transparent focus:border-border"
@@ -440,7 +366,7 @@ function CampaignEditor({
440366 onError : ( ) => {
441367 setContactBookId ( campaign . contactBookId ) ;
442368 } ,
443- } ,
369+ }
444370 ) ;
445371 setContactBookId ( val ) ;
446372 } }
0 commit comments