@@ -2,7 +2,7 @@ import { createFileRoute } from '@tanstack/react-router'
22import { useQuery , useMutation } from '@tanstack/react-query'
33import { publicApi } from '@/lib/api'
44import { useState } from 'react'
5- import { Hourglass , CheckCircle , Mail , User , Zap , Gift , Copy , Check } from 'lucide-react'
5+ import { Hourglass , CheckCircle , Mail , User , Zap , Gift , Copy , Check , Tag } from 'lucide-react'
66import toast from 'react-hot-toast'
77import { getDaysLeft } from '@/lib/utils'
88
@@ -16,6 +16,11 @@ function WaitlistPage() {
1616 const [ form , setForm ] = useState < Record < string , any > > ( { name : '' , email : '' } )
1717 const [ coupon , setCoupon ] = useState < any > ( null )
1818 const [ codeCopied , setCodeCopied ] = useState ( false )
19+ const [ showPromo , setShowPromo ] = useState ( false )
20+
21+ // Read promo code from URL: /w/my-project?promo=get5
22+ const urlPromo = new URLSearchParams ( window . location . search ) . get ( 'promo' ) || ''
23+ const [ promo , setPromo ] = useState ( urlPromo )
1924
2025 const { data, isLoading, error } = useQuery ( {
2126 queryKey : [ 'public-project' , slug ] ,
@@ -38,6 +43,7 @@ function WaitlistPage() {
3843 } )
3944 return publicApi . subscribe ( slug , {
4045 name : form . name , email : form . email ,
46+ ...( promo ? { promo } : { } ) ,
4147 ...( Object . keys ( customData ) . length > 0 ? { custom_data : customData } : { } ) ,
4248 } )
4349 } ,
@@ -247,6 +253,35 @@ function WaitlistPage() {
247253 </ div >
248254
249255 { /* Custom fields */ }
256+
257+ { /* Promo code */ }
258+ { urlPromo ? (
259+ < div style = { {
260+ display : 'flex' , alignItems : 'center' , gap : 8 , padding : '8px 12px' ,
261+ background : `rgba(${ hexToRgb ( themeColor ) } ,0.06)` , borderRadius : 8 ,
262+ border : `1px solid rgba(${ hexToRgb ( themeColor ) } ,0.15)` ,
263+ } } >
264+ < Tag size = { 13 } color = { themeColor } />
265+ < span style = { { fontSize : 13 , color : '#94a3b8' } } > Promo: < strong style = { { color : themeColor } } > { urlPromo } </ strong > </ span >
266+ </ div >
267+ ) : (
268+ < div >
269+ { ! showPromo ? (
270+ < button type = "button" onClick = { ( ) => setShowPromo ( true ) }
271+ style = { { background : 'none' , border : 'none' , cursor : 'pointer' , fontSize : 13 , color : '#475569' , padding : 0 } } >
272+ Have a promo code?
273+ </ button >
274+ ) : (
275+ < div style = { { position : 'relative' } } >
276+ < Tag size = { 14 } style = { { position : 'absolute' , left : 12 , top : '50%' , transform : 'translateY(-50%)' , color : '#475569' } } />
277+ < input className = "input" placeholder = "Enter promo code"
278+ value = { promo } onChange = { e => setPromo ( e . target . value . toLowerCase ( ) ) }
279+ style = { { paddingLeft : 34 } } />
280+ </ div >
281+ ) }
282+ </ div >
283+ ) }
284+
250285 { customFields . map ( ( cf : any ) => (
251286 < div key = { cf . key } >
252287 { cf . type === 'text' && (
0 commit comments