@@ -16,20 +16,27 @@ import { createWhatsAppAccount } from "@/services/whatsapp-account-service";
1616
1717import { WhatsAppSetupInfo } from "./whatsapp-setup-info" ;
1818
19- type Step = "credentials" | "setup" ;
19+ type Step = "name" | "app-secret" | "api- credentials" | "setup" ;
2020
2121const STEP_TITLES : Record < Step , string > = {
22- credentials : "Add WhatsApp Account" ,
22+ name : "Add WhatsApp Account" ,
23+ "app-secret" : "App Secret" ,
24+ "api-credentials" : "WhatsApp API Credentials" ,
2325 setup : "Account Created" ,
2426} ;
2527
2628const STEP_DESCRIPTIONS : Record < Step , string > = {
27- credentials :
28- "Enter your WhatsApp Business API credentials from the Meta Developer Portal." ,
29+ name : "Choose a display name to identify this WhatsApp account in Dafthunk." ,
30+ "app-secret" :
31+ "Copy the App Secret from your Meta app. Navigate to App Settings > Basic in the Meta Developer Portal." ,
32+ "api-credentials" :
33+ "Copy your Access Token and Phone Number ID from the WhatsApp API Setup page in the Meta Developer Portal." ,
2934 setup :
30- "Your account is ready. Configure the webhook URL in the Meta Developer Portal ." ,
35+ "Your account is ready. Follow these steps to complete the setup ." ,
3136} ;
3237
38+ const META_PORTAL_URL = "https://developers.facebook.com/apps/" ;
39+
3340interface WhatsAppAccountCreateDialogProps {
3441 isOpen : boolean ;
3542 onClose : ( ) => void ;
@@ -42,22 +49,22 @@ export function WhatsAppAccountCreateDialog({
4249 onCreated,
4350} : WhatsAppAccountCreateDialogProps ) {
4451 const { organization } = useAuth ( ) ;
45- const [ step , setStep ] = useState < Step > ( "credentials " ) ;
52+ const [ step , setStep ] = useState < Step > ( "name " ) ;
4653 const [ name , setName ] = useState ( "" ) ;
54+ const [ appSecret , setAppSecret ] = useState ( "" ) ;
4755 const [ accessToken , setAccessToken ] = useState ( "" ) ;
4856 const [ phoneNumberId , setPhoneNumberId ] = useState ( "" ) ;
4957 const [ wabaId , setWabaId ] = useState ( "" ) ;
50- const [ appSecret , setAppSecret ] = useState ( "" ) ;
5158 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
5259 const [ error , setError ] = useState < string | null > ( null ) ;
5360
5461 const resetForm = ( ) => {
55- setStep ( "credentials " ) ;
62+ setStep ( "name " ) ;
5663 setName ( "" ) ;
64+ setAppSecret ( "" ) ;
5765 setAccessToken ( "" ) ;
5866 setPhoneNumberId ( "" ) ;
5967 setWabaId ( "" ) ;
60- setAppSecret ( "" ) ;
6168 setError ( null ) ;
6269 } ;
6370
@@ -101,11 +108,11 @@ export function WhatsAppAccountCreateDialog({
101108 </ DialogTitle >
102109 < DialogDescription className = "text-sm text-muted-foreground mt-1" >
103110 { STEP_DESCRIPTIONS [ step ] }
104- { step === "credentials" && (
111+ { ( step === "app-secret" || step === "api- credentials") && (
105112 < >
106113 { " " }
107114 < a
108- href = "https://developers.facebook.com/apps/"
115+ href = { META_PORTAL_URL }
109116 target = "_blank"
110117 rel = "noopener noreferrer"
111118 className = "text-primary hover:underline inline-flex items-center gap-0.5"
@@ -118,33 +125,104 @@ export function WhatsAppAccountCreateDialog({
118125 </ DialogDescription >
119126 </ div >
120127
121- { step === "credentials " && (
128+ { step === "name " && (
122129 < div className = "space-y-3" >
123130 < div className = "space-y-1.5" >
124131 < Label htmlFor = "whatsapp-name" > Name</ Label >
125132 < Input
126133 id = "whatsapp-name"
127134 value = { name }
128135 onChange = { ( e ) => setName ( e . target . value ) }
129- placeholder = "My WhatsApp Account"
136+ placeholder = "My WhatsApp Bot"
137+ />
138+ < p className = "text-xs text-muted-foreground" >
139+ A display name for this account in Dafthunk. This is not visible
140+ to your WhatsApp users.
141+ </ p >
142+ </ div >
143+
144+ < div className = "flex justify-end gap-2 pt-1" >
145+ < Button type = "button" variant = "outline" onClick = { handleClose } >
146+ Cancel
147+ </ Button >
148+ < Button
149+ onClick = { ( ) => setStep ( "app-secret" ) }
150+ disabled = { name . trim ( ) === "" }
151+ >
152+ Next
153+ </ Button >
154+ </ div >
155+ </ div >
156+ ) }
157+
158+ { step === "app-secret" && (
159+ < div className = "space-y-3" >
160+ < div className = "space-y-1.5" >
161+ < Label htmlFor = "whatsapp-app-secret" > App Secret</ Label >
162+ < Input
163+ id = "whatsapp-app-secret"
164+ type = "password"
165+ value = { appSecret }
166+ onChange = { ( e ) => setAppSecret ( e . target . value ) }
167+ placeholder = "Paste your App Secret here"
130168 />
131169 < p className = "text-xs text-muted-foreground" >
132- A display name for this account in Dafthunk.
170+ Find this at{ " " }
171+ < span className = "font-medium text-foreground" >
172+ App Settings > Basic
173+ </ span > { " " }
174+ in the Meta Developer Portal. Click{ " " }
175+ < span className = "font-medium text-foreground" > Show</ span > next
176+ to the App Secret field. Used to verify that incoming webhook
177+ messages are genuinely from Meta.
133178 </ p >
134179 </ div >
135180
181+ < div className = "flex justify-end gap-2 pt-1" >
182+ < Button
183+ type = "button"
184+ variant = "outline"
185+ onClick = { ( ) => setStep ( "name" ) }
186+ >
187+ Back
188+ </ Button >
189+ < Button
190+ onClick = { ( ) => setStep ( "api-credentials" ) }
191+ disabled = { appSecret . trim ( ) === "" }
192+ >
193+ Next
194+ </ Button >
195+ </ div >
196+ </ div >
197+ ) }
198+
199+ { step === "api-credentials" && (
200+ < div className = "space-y-3" >
136201 < div className = "space-y-1.5" >
137202 < Label htmlFor = "whatsapp-token" > Access Token</ Label >
138203 < Input
139204 id = "whatsapp-token"
140205 type = "password"
141206 value = { accessToken }
142207 onChange = { ( e ) => setAccessToken ( e . target . value ) }
143- placeholder = "•••••••• "
208+ placeholder = "Paste your access token here "
144209 />
145210 < p className = "text-xs text-muted-foreground" >
146- Your WhatsApp Business API access token from the Meta Developer
147- Portal.
211+ Find this at{ " " }
212+ < span className = "font-medium text-foreground" >
213+ WhatsApp > API Setup
214+ </ span > { " " }
215+ under the temporary access token section, or generate a
216+ permanent token via{ " " }
217+ < span className = "font-medium text-foreground" >
218+ Business Settings > System Users
219+ </ span >
220+ .
221+ </ p >
222+ < p className = "text-xs text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 px-3 py-2 rounded-md" >
223+ Temporary tokens from API Setup expire in 24 hours. For
224+ production use, generate a permanent token from a System User in
225+ Business Settings.
148226 </ p >
149227 </ div >
150228
@@ -157,35 +235,31 @@ export function WhatsAppAccountCreateDialog({
157235 placeholder = "123456789012345"
158236 />
159237 < p className = "text-xs text-muted-foreground" >
160- The Phone Number ID from your WhatsApp Business account.
238+ Find this at{ " " }
239+ < span className = "font-medium text-foreground" >
240+ WhatsApp > API Setup
241+ </ span >
242+ . Select your phone number from the dropdown — the numeric ID
243+ appears below it. This is not the phone number itself.
161244 </ p >
162245 </ div >
163246
164247 < div className = "space-y-1.5" >
165248 < Label htmlFor = "whatsapp-waba-id" >
166249 WABA ID{ " " }
167- < span className = "text-muted-foreground" > (optional)</ span >
250+ < span className = "text-muted-foreground font-normal" >
251+ (optional)
252+ </ span >
168253 </ Label >
169254 < Input
170255 id = "whatsapp-waba-id"
171256 value = { wabaId }
172257 onChange = { ( e ) => setWabaId ( e . target . value ) }
173258 placeholder = "WhatsApp Business Account ID"
174259 />
175- </ div >
176-
177- < div className = "space-y-1.5" >
178- < Label htmlFor = "whatsapp-app-secret" > App Secret</ Label >
179- < Input
180- id = "whatsapp-app-secret"
181- type = "password"
182- value = { appSecret }
183- onChange = { ( e ) => setAppSecret ( e . target . value ) }
184- placeholder = "••••••••"
185- />
186260 < p className = "text-xs text-muted-foreground" >
187- Required to verify incoming webhook signatures. Find it in App
188- Settings > Basic in the Meta Developer Portal .
261+ The WhatsApp Business Account ID, found on the same page. Stored
262+ for reference only .
189263 </ p >
190264 </ div >
191265
@@ -199,19 +273,20 @@ export function WhatsAppAccountCreateDialog({
199273 < Button
200274 type = "button"
201275 variant = "outline"
202- onClick = { handleClose }
276+ onClick = { ( ) => {
277+ setError ( null ) ;
278+ setStep ( "app-secret" ) ;
279+ } }
203280 disabled = { isSubmitting }
204281 >
205- Cancel
282+ Back
206283 </ Button >
207284 < Button
208285 onClick = { handleSubmit }
209286 disabled = {
210287 isSubmitting ||
211- name . trim ( ) === "" ||
212288 accessToken . trim ( ) === "" ||
213- phoneNumberId . trim ( ) === "" ||
214- appSecret . trim ( ) === ""
289+ phoneNumberId . trim ( ) === ""
215290 }
216291 >
217292 { isSubmitting ? (
0 commit comments