@@ -7,65 +7,61 @@ import {
77 theme ,
88 Text ,
99 Grid ,
10+ toast ,
1011} from "@webstudio-is/design-system" ;
1112import { validateDomain } from "@webstudio-is/domain" ;
1213import type { Project } from "@webstudio-is/project" ;
13- import { useId , useState } from "react" ;
14+ import { useId , useOptimistic , useRef , useState } from "react" ;
1415import { CustomCodeIcon } from "@webstudio-is/icons" ;
15- import { trpcClient } from "~/shared/trpc/trpc-client" ;
16+ import { nativeClient } from "~/shared/trpc/trpc-client" ;
1617
1718type DomainsAddProps = {
1819 projectId : Project [ "id" ] ;
1920 onCreate : ( domain : string ) => void ;
2021 onExportClick : ( ) => void ;
21- refreshDomainResult : (
22- input : { projectId : Project [ "id" ] } ,
23- onSuccess : ( ) => void
24- ) => void ;
25- domainState : "idle" | "submitting" ;
26- isPublishing : boolean ;
22+ refresh : ( ) => Promise < void > ;
2723} ;
2824
2925export const AddDomain = ( {
3026 projectId,
3127 onCreate,
32- refreshDomainResult,
33- domainState,
34- isPublishing,
28+ refresh,
3529 onExportClick,
3630} : DomainsAddProps ) => {
3731 const id = useId ( ) ;
38- const {
39- send : create ,
40- state : сreateState ,
41- error : сreateSystemError ,
42- } = trpcClient . domain . create . useMutation ( ) ;
4332 const [ isOpen , setIsOpen ] = useState ( false ) ;
44- const [ domain , setDomain ] = useState ( "" ) ;
4533 const [ error , setError ] = useState < string > ( ) ;
34+ const buttonRef = useRef < HTMLButtonElement > ( null ) ;
35+ const [ isPending , setIsPendingOptimistic ] = useOptimistic ( false ) ;
4636
47- const handleCreate = ( ) => {
48- setError ( undefined ) ;
37+ const handleCreateDomain = async ( formData : FormData ) => {
38+ // Will be automatically reset on action end
39+ setIsPendingOptimistic ( true ) ;
4940
41+ const domain = formData . get ( "domain" ) ?. toString ( ) ?? "" ;
5042 const validationResult = validateDomain ( domain ) ;
5143
5244 if ( validationResult . success === false ) {
5345 setError ( validationResult . error ) ;
5446 return ;
5547 }
5648
57- create ( { domain : validationResult . domain , projectId } , ( data ) => {
58- if ( data . success === false ) {
59- setError ( data . error ) ;
60- return ;
61- }
62-
63- refreshDomainResult ( { projectId } , ( ) => {
64- setDomain ( "" ) ;
65- setIsOpen ( false ) ;
66- onCreate ( validationResult . domain ) ;
67- } ) ;
49+ const result = await nativeClient . domain . create . mutate ( {
50+ domain,
51+ projectId,
6852 } ) ;
53+
54+ if ( result . success === false ) {
55+ toast . error ( result . error ) ;
56+ setError ( result . error ) ;
57+ return ;
58+ }
59+
60+ onCreate ( domain ) ;
61+
62+ await refresh ( ) ;
63+
64+ setIsOpen ( false ) ;
6965 } ;
7066
7167 return (
@@ -81,7 +77,6 @@ export const AddDomain = ({
8177 direction = { "column" }
8278 onKeyDown = { ( event ) => {
8379 if ( event . key === "Escape" ) {
84- setDomain ( "" ) ;
8580 setIsOpen ( false ) ;
8681 event . preventDefault ( ) ;
8782 }
@@ -94,56 +89,43 @@ export const AddDomain = ({
9489 </ Label >
9590 < InputField
9691 id = { id }
92+ name = "domain"
9793 autoFocus
9894 placeholder = "your-domain.com"
99- value = { domain }
100- disabled = {
101- isPublishing || сreateState !== "idle" || domainState !== "idle"
102- }
95+ disabled = { isPending }
10396 onKeyDown = { ( event ) => {
10497 if ( event . key === "Enter" ) {
105- handleCreate ( ) ;
98+ buttonRef . current
99+ ?. closest ( "form" )
100+ ?. requestSubmit ( buttonRef . current ) ;
106101 }
107102 if ( event . key === "Escape" ) {
108- setDomain ( "" ) ;
109103 setIsOpen ( false ) ;
110104 event . preventDefault ( ) ;
111105 }
112106 } }
113- onChange = { ( event ) => {
114- setError ( undefined ) ;
115- setDomain ( event . target . value ) ;
116- } }
117107 color = { error !== undefined ? "error" : undefined }
118108 />
119109 { error !== undefined && (
120110 < >
121111 < Text color = "destructive" > { error } </ Text >
122112 </ >
123113 ) }
124- { сreateSystemError !== undefined && (
125- < >
126- { /* Something happened with network, api etc */ }
127- < Text color = "destructive" > { сreateSystemError } </ Text >
128- < Text color = "subtle" > Please try again later</ Text >
129- </ >
130- ) }
131114 </ >
132115 ) }
133116
134117 < Grid gap = { 2 } columns = { 2 } >
135118 < Button
136- disabled = {
137- isPublishing || сreateState !== "idle" || domainState !== "idle"
138- }
119+ ref = { buttonRef }
120+ formAction = { handleCreateDomain }
121+ state = { isPending ? "pending" : undefined }
139122 color = { isOpen ? "primary" : "neutral" }
140- onClick = { ( ) => {
123+ onClick = { ( event ) => {
141124 if ( isOpen === false ) {
142125 setIsOpen ( true ) ;
126+ event . preventDefault ( ) ;
143127 return ;
144128 }
145-
146- handleCreate ( ) ;
147129 } }
148130 >
149131 { isOpen ? "Add domain" : "Add a new domain" }
@@ -152,6 +134,7 @@ export const AddDomain = ({
152134 < Button
153135 color = { "dark" }
154136 prefix = { < CustomCodeIcon /> }
137+ type = "button"
155138 onClick = { onExportClick }
156139 >
157140 Export
0 commit comments