@@ -2,6 +2,7 @@ import { Spinner } from "@/components/ui/Spinner/Spinner";
22import { Alert , AlertDescription , AlertTitle } from "@/components/ui/alert" ;
33import { Badge } from "@/components/ui/badge" ;
44import { Button } from "@/components/ui/button" ;
5+ import { Checkbox , CheckboxWithLabel } from "@/components/ui/checkbox" ;
56import {
67 Dialog ,
78 DialogContent ,
@@ -13,12 +14,12 @@ import { Input } from "@/components/ui/input";
1314import { Textarea } from "@/components/ui/textarea" ;
1415import { ToolTipLabel } from "@/components/ui/tooltip" ;
1516import {
17+ type DeleteCloudHostedInput ,
1618 type EditEngineInstanceInput ,
1719 type EngineInstance ,
18- type RemoveCloudHostedInput ,
20+ useEngineDeleteCloudHosted ,
1921 useEngineEditInstance ,
2022 type useEngineInstances ,
21- useEngineRemoveCloudHosted ,
2223 useEngineRemoveFromDashboard ,
2324} from "@3rdweb-sdk/react/hooks/useEngine" ;
2425import { FormControl , Radio , RadioGroup } from "@chakra-ui/react" ;
@@ -28,7 +29,7 @@ import { TWTable } from "components/shared/TWTable";
2829import { useTrack } from "hooks/analytics/useTrack" ;
2930import {
3031 CircleAlertIcon ,
31- SendIcon ,
32+ InfoIcon ,
3233 Trash2Icon ,
3334 TriangleAlertIcon ,
3435} from "lucide-react" ;
@@ -38,6 +39,7 @@ import { useForm } from "react-hook-form";
3839import { BiPencil } from "react-icons/bi" ;
3940import { FiTrash } from "react-icons/fi" ;
4041import { toast } from "sonner" ;
42+ import invariant from "tiny-invariant" ;
4143import { FormLabel } from "tw-components" ;
4244
4345interface EngineInstancesTableProps {
@@ -258,7 +260,7 @@ const EditModal = (props: {
258260
259261 < DialogFooter className = "mt-10 gap-2" >
260262 < Button onClick = { ( ) => onOpenChange ( false ) } variant = "outline" >
261- Cancel
263+ Close
262264 </ Button >
263265 < Button
264266 type = "submit"
@@ -295,7 +297,7 @@ const RemoveModal = (props: {
295297 close = { ( ) => onOpenChange ( false ) }
296298 />
297299 ) : (
298- < CancelSubscriptionModalContent
300+ < DeleteSubscriptionModalContent
299301 refetch = { refetch }
300302 instance = { instance }
301303 close = { ( ) => onOpenChange ( false ) }
@@ -318,18 +320,22 @@ function RemoveFromDashboardModalContent(props: {
318320 < >
319321 < DialogHeader >
320322 < DialogTitle className = "mb-3 font-semibold text-2xl tracking-tight" >
321- Remove Engine Instance
323+ Remove Engine
322324 </ DialogTitle >
323325 < DialogDescription className = "text-muted-foreground" >
324326 < span className = "mb-2 block" >
325- Are you sure you want to remove
326- < em className = "font-semibold not-italic" > " { instance . name } " </ em > from
327+ Are you sure you want to remove{ " " }
328+ < em className = "font-semibold not-italic" > { instance . name } </ em > from
327329 your dashboard?
328330 </ span >
329- < span className = "block" >
330- This action does not modify your Engine infrastructure. You can
331- re-add it at any time.
332- </ span >
331+
332+ < Alert variant = "info" >
333+ < InfoIcon className = "size-5" />
334+ < AlertTitle >
335+ This action does not modify your Engine infrastructure.
336+ </ AlertTitle >
337+ < AlertDescription > You can re-add it at any time.</ AlertDescription >
338+ </ Alert >
333339 </ DialogDescription >
334340 </ DialogHeader >
335341
@@ -367,17 +373,22 @@ function RemoveFromDashboardModalContent(props: {
367373 ) ;
368374}
369375
370- function CancelSubscriptionModalContent ( props : {
376+ function DeleteSubscriptionModalContent ( props : {
371377 refetch : ( ) => void ;
372378 instance : EngineInstance ;
373379 close : ( ) => void ;
374380} ) {
375381 const { refetch, instance, close } = props ;
376- const removeCloudHosted = useEngineRemoveCloudHosted ( ) ;
382+ invariant (
383+ instance . deploymentId ,
384+ "Instance must have a deploymentId to be cancelled." ,
385+ ) ;
377386
378- const form = useForm < RemoveCloudHostedInput > ( {
387+ const deleteCloudHosted = useEngineDeleteCloudHosted ( ) ;
388+ const [ ackDeletion , setAckDeletion ] = useState ( false ) ;
389+ const form = useForm < DeleteCloudHostedInput > ( {
379390 defaultValues : {
380- instanceId : instance . id ,
391+ deploymentId : instance . deploymentId ,
381392 } ,
382393 reValidateMode : "onChange" ,
383394 } ) ;
@@ -386,33 +397,25 @@ function CancelSubscriptionModalContent(props: {
386397 < div >
387398 < DialogHeader >
388399 < DialogTitle className = "mb-1 font-semibold text-2xl tracking-tight" >
389- Cancel Engine Subscription
400+ Permanently Delete Engine
390401 </ DialogTitle >
391- < DialogDescription className = "text-muted-foreground" >
392- Complete this form to request to cancel your Engine subscription. This
393- may take up to 2 business days.
394- </ DialogDescription >
395402 </ DialogHeader >
396403
397- < div className = "h-3 " />
404+ < div className = "h-4 " />
398405
399- < Alert variant = "destructive" >
400- < TriangleAlertIcon className = "!text-destructive-text size-5" />
401- < AlertTitle > This action is irreversible!</ AlertTitle >
402- < AlertDescription >
403- You will no longer be able to access this Engine's local backend
404- wallets. < strong > Any remaining mainnet funds will be lost.</ strong >
405- </ AlertDescription >
406- </ Alert >
406+ < p className = "text-muted-foreground" >
407+ This step will cancel your monthly subscription and immediately delete
408+ all data and infrastructure for this Engine.
409+ </ p >
407410
408- < div className = "h-5 " />
411+ < div className = "h-4 " />
409412
410413 < form
411414 onSubmit = { form . handleSubmit ( ( data ) =>
412- removeCloudHosted . mutate ( data , {
415+ deleteCloudHosted . mutate ( data , {
413416 onSuccess : ( ) => {
414417 toast . success (
415- "Submitted a request to cancel your Engine subscription. This may take up to 2 business days ." ,
418+ "Deleting Engine. Please check again in a few minutes ." ,
416419 {
417420 dismissible : true ,
418421 duration : 10000 ,
@@ -424,16 +427,16 @@ function CancelSubscriptionModalContent(props: {
424427 } ,
425428 onError : ( ) => {
426429 toast . error (
427- "Error requesting to cancel your Engine subscription " ,
430+ "Error deleting Engine. Please visit https://thirdweb.com/support. " ,
428431 ) ;
429432 } ,
430433 } ) ,
431434 ) }
432435 >
433- { /* Form */ }
436+ { /* Reason */ }
434437 < FormControl isRequired >
435438 < FormLabel className = "!text-base" >
436- Please share any feedback to help us improve
439+ Please share your feedback to help us improve Engine.
437440 </ FormLabel >
438441 < RadioGroup >
439442 < div className = "flex flex-col gap-2" >
@@ -467,13 +470,32 @@ function CancelSubscriptionModalContent(props: {
467470
468471 < div className = "h-2" />
469472
473+ { /* Feedback */ }
470474 < Textarea
471475 className = "mt-3"
472476 placeholder = "Provide additional feedback"
473477 { ...form . register ( "feedback" ) }
474478 />
475479
476- < div className = "h-8" />
480+ < div className = "h-4" />
481+
482+ < Alert variant = "destructive" >
483+ < TriangleAlertIcon className = "!text-destructive-text size-5" />
484+ < AlertTitle > This action is irreversible!</ AlertTitle >
485+
486+ < AlertDescription className = "!pl-0 pt-2" >
487+ < CheckboxWithLabel >
488+ < Checkbox
489+ checked = { ackDeletion }
490+ onCheckedChange = { ( checked ) => setAckDeletion ( ! ! checked ) }
491+ />
492+ I understand that access to my local backend wallets and any
493+ remaining funds will be lost.
494+ </ CheckboxWithLabel >
495+ </ AlertDescription >
496+ </ Alert >
497+
498+ < div className = "h-4" />
477499
478500 < DialogFooter className = "gap-2" >
479501 < Button onClick = { close } variant = "outline" >
@@ -482,15 +504,15 @@ function CancelSubscriptionModalContent(props: {
482504 < Button
483505 type = "submit"
484506 variant = "destructive"
485- disabled = { ! form . formState . isValid }
507+ disabled = {
508+ ! ackDeletion ||
509+ deleteCloudHosted . isPending ||
510+ ! form . formState . isValid
511+ }
486512 className = "gap-2"
487513 >
488- { removeCloudHosted . isPending ? (
489- < Spinner className = "size-4" />
490- ) : (
491- < SendIcon className = "size-4" />
492- ) }
493- Request to cancel
514+ { deleteCloudHosted . isPending && < Spinner className = "size-4" /> }
515+ Yes, delete this Engine
494516 </ Button >
495517 </ DialogFooter >
496518 </ form >
0 commit comments