@@ -12,23 +12,32 @@ import {
1212import { Input } from "@/components/ui/input" ;
1313import { Label } from "@/components/ui/label" ;
1414import { Spinner } from "@/components/ui/spinner" ;
15+ import { getApiBaseUrl } from "@/config/api" ;
1516import { createDiscordBot } from "@/services/bot-service" ;
1617
17- import { DiscordBotSetupInfo } from "./discord-setup-info " ;
18+ import { CopyableValue } from "./copyable-value " ;
1819
19- type Step = "application" | "bot-token" | "webhook" | "command" | "invite" ;
20+ type Step =
21+ | "name"
22+ | "application"
23+ | "bot-token"
24+ | "webhook"
25+ | "command"
26+ | "invite" ;
2027
2128const STEP_TITLES : Record < Step , string > = {
22- application : "Create a Discord Application" ,
29+ name : "Create a Discord Bot" ,
30+ application : "Application Info" ,
2331 "bot-token" : "Bot Token" ,
2432 webhook : "Interactions Endpoint" ,
2533 command : "Slash Command" ,
2634 invite : "Add Bot to Server" ,
2735} ;
2836
2937const STEP_DESCRIPTIONS : Record < Step , string > = {
38+ name : "Choose a display name to identify this Discord bot in Dafthunk." ,
3039 application :
31- "Create a new application in the Discord Developer Portal, then copy the Application ID and Public Key from the General Information page." ,
40+ "Copy the Application ID and Public Key from the General Information page in the Discord Developer Portal ." ,
3241 "bot-token" :
3342 "Copy the token from the Bot page in the Discord Developer Portal." ,
3443 webhook :
@@ -54,7 +63,7 @@ export function DiscordBotCreateDialog({
5463 showCommandStep = true ,
5564} : DiscordBotCreateDialogProps ) {
5665 const { organization } = useAuth ( ) ;
57- const [ step , setStep ] = useState < Step > ( "application " ) ;
66+ const [ step , setStep ] = useState < Step > ( "name " ) ;
5867 const [ name , setName ] = useState ( "" ) ;
5968 const [ applicationId , setApplicationId ] = useState ( "" ) ;
6069 const [ publicKey , setPublicKey ] = useState ( "" ) ;
@@ -65,7 +74,7 @@ export function DiscordBotCreateDialog({
6574 const [ createdBotId , setCreatedBotId ] = useState < string | null > ( null ) ;
6675
6776 const resetForm = ( ) => {
68- setStep ( "application " ) ;
77+ setStep ( "name " ) ;
6978 setName ( "" ) ;
7079 setApplicationId ( "" ) ;
7180 setPublicKey ( "" ) ;
@@ -116,15 +125,14 @@ export function DiscordBotCreateDialog({
116125 ? `https://discord.com/developers/applications/${ applicationId } /bot`
117126 : "https://discord.com/developers/applications" ;
118127
128+ const webhookUrl = createdBotId
129+ ? `${ getApiBaseUrl ( ) . replace ( / \/ $ / , "" ) } /discord/webhook/${ createdBotId } `
130+ : "" ;
131+
119132 const inviteUrl = applicationId
120133 ? `https://discord.com/oauth2/authorize?client_id=${ applicationId } &scope=bot+applications.commands&permissions=2048`
121134 : null ;
122135
123- const canAdvanceToToken =
124- name . trim ( ) !== "" &&
125- applicationId . trim ( ) !== "" &&
126- publicKey . trim ( ) !== "" ;
127-
128136 return (
129137 < Dialog open = { isOpen } onOpenChange = { ( open ) => ! open && handleClose ( ) } >
130138 < DialogContent className = "max-w-[450px]" >
@@ -134,7 +142,7 @@ export function DiscordBotCreateDialog({
134142 </ DialogTitle >
135143 < DialogDescription className = "text-sm text-muted-foreground mt-1" >
136144 { STEP_DESCRIPTIONS [ step ] }
137- { step === "application" && (
145+ { ( step === "application" || step === "webhook" ) && (
138146 < >
139147 { " " }
140148 < a
@@ -148,10 +156,24 @@ export function DiscordBotCreateDialog({
148156 </ a >
149157 </ >
150158 ) }
159+ { step === "bot-token" && (
160+ < >
161+ { " " }
162+ < a
163+ href = { botSettingsUrl }
164+ target = "_blank"
165+ rel = "noopener noreferrer"
166+ className = "text-primary hover:underline inline-flex items-center gap-0.5"
167+ >
168+ Open Discord Developer Portal
169+ < ExternalLink className = "w-2.5 h-2.5" />
170+ </ a >
171+ </ >
172+ ) }
151173 </ DialogDescription >
152174 </ div >
153175
154- { step === "application " && (
176+ { step === "name " && (
155177 < div className = "space-y-3" >
156178 < div className = "space-y-1.5" >
157179 < Label htmlFor = "discord-name" > Name</ Label >
@@ -162,10 +184,27 @@ export function DiscordBotCreateDialog({
162184 placeholder = "My Discord Bot"
163185 />
164186 < p className = "text-xs text-muted-foreground" >
165- A display name for this bot in Dafthunk.
187+ A display name for this bot in Dafthunk. This is not visible to
188+ your Discord users.
166189 </ p >
167190 </ div >
168191
192+ < div className = "flex justify-end gap-2 pt-1" >
193+ < Button type = "button" variant = "outline" onClick = { handleClose } >
194+ Cancel
195+ </ Button >
196+ < Button
197+ onClick = { ( ) => setStep ( "application" ) }
198+ disabled = { name . trim ( ) === "" }
199+ >
200+ Next
201+ </ Button >
202+ </ div >
203+ </ div >
204+ ) }
205+
206+ { step === "application" && (
207+ < div className = "space-y-3" >
169208 < div className = "space-y-1.5" >
170209 < Label htmlFor = "discord-app-id" > Application ID</ Label >
171210 < Input
@@ -176,15 +215,9 @@ export function DiscordBotCreateDialog({
176215 />
177216 < p className = "text-xs text-muted-foreground" >
178217 Copy from the{ " " }
179- < a
180- href = { generalInfoUrl }
181- target = "_blank"
182- rel = "noopener noreferrer"
183- className = "text-primary hover:underline inline-flex items-center gap-0.5"
184- >
218+ < span className = "font-medium text-foreground" >
185219 General Information
186- < ExternalLink className = "w-2.5 h-2.5" />
187- </ a > { " " }
220+ </ span > { " " }
188221 page in the Discord Developer Portal.
189222 </ p >
190223 </ div >
@@ -199,26 +232,26 @@ export function DiscordBotCreateDialog({
199232 />
200233 < p className = "text-xs text-muted-foreground" >
201234 Copy from the same{ " " }
202- < a
203- href = { generalInfoUrl }
204- target = "_blank"
205- rel = "noopener noreferrer"
206- className = "text-primary hover:underline inline-flex items-center gap-0.5"
207- >
235+ < span className = "font-medium text-foreground" >
208236 General Information
209- < ExternalLink className = "w-2.5 h-2.5" />
210- </ a > { " " }
237+ </ span > { " " }
211238 page. Used to verify interaction signatures.
212239 </ p >
213240 </ div >
214241
215242 < div className = "flex justify-end gap-2 pt-1" >
216- < Button type = "button" variant = "outline" onClick = { handleClose } >
217- Cancel
243+ < Button
244+ type = "button"
245+ variant = "outline"
246+ onClick = { ( ) => setStep ( "name" ) }
247+ >
248+ Back
218249 </ Button >
219250 < Button
220251 onClick = { ( ) => setStep ( "bot-token" ) }
221- disabled = { ! canAdvanceToToken }
252+ disabled = {
253+ applicationId . trim ( ) === "" || publicKey . trim ( ) === ""
254+ }
222255 >
223256 Next
224257 </ Button >
@@ -235,20 +268,12 @@ export function DiscordBotCreateDialog({
235268 type = "password"
236269 value = { botToken }
237270 onChange = { ( e ) => setBotToken ( e . target . value ) }
238- placeholder = "•••••••• "
271+ placeholder = "Paste your bot token here "
239272 />
240273 < p className = "text-xs text-muted-foreground" >
241274 Copy the token from the{ " " }
242- < a
243- href = { botSettingsUrl }
244- target = "_blank"
245- rel = "noopener noreferrer"
246- className = "text-primary hover:underline inline-flex items-center gap-0.5"
247- >
248- Bot
249- < ExternalLink className = "w-2.5 h-2.5" />
250- </ a > { " " }
251- page in the Discord Developer Portal.
275+ < span className = "font-medium text-foreground" > Bot</ span > page in
276+ the Discord Developer Portal.
252277 </ p >
253278 </ div >
254279
@@ -277,10 +302,10 @@ export function DiscordBotCreateDialog({
277302 { isSubmitting ? (
278303 < >
279304 < Spinner className = "h-4 w-4 mr-1" />
280- Creating ...
305+ Connecting ...
281306 </ >
282307 ) : (
283- "Create Bot "
308+ "Next "
284309 ) }
285310 </ Button >
286311 </ div >
@@ -296,12 +321,27 @@ export function DiscordBotCreateDialog({
296321 < span className = "font-medium" > { name } </ span >
297322 </ div >
298323
299- { createdBotId && (
300- < DiscordBotSetupInfo
301- botId = { createdBotId }
302- applicationId = { applicationId }
303- />
304- ) }
324+ < div className = "space-y-2 text-sm" >
325+ < div className = "space-y-1" >
326+ < p className = "font-medium text-foreground" >
327+ Interactions Endpoint URL
328+ </ p >
329+ < CopyableValue value = { webhookUrl } />
330+ < p className = "text-muted-foreground text-xs" >
331+ Paste this as the Interactions Endpoint URL in the{ " " }
332+ < a
333+ href = { generalInfoUrl }
334+ target = "_blank"
335+ rel = "noopener noreferrer"
336+ className = "text-primary hover:underline inline-flex items-center gap-0.5"
337+ >
338+ General Information
339+ < ExternalLink className = "w-2.5 h-2.5" />
340+ </ a > { " " }
341+ page of your Discord application.
342+ </ p >
343+ </ div >
344+ </ div >
305345
306346 < div className = "flex justify-end" >
307347 < Button
0 commit comments