5
5
*
6
6
* Copyright Oxide Computer Company
7
7
*/
8
- import { useEffect , type ReactNode } from 'react'
8
+ import { useEffect , useId , type ReactNode } from 'react'
9
9
import type { FieldValues , UseFormReturn } from 'react-hook-form'
10
10
import { useNavigationType } from 'react-router-dom'
11
11
@@ -14,8 +14,19 @@ import type { ApiError } from '@oxide/api'
14
14
import { Button } from '~/ui/lib/Button'
15
15
import { SideModal } from '~/ui/lib/SideModal'
16
16
17
+ type CreateFormProps = {
18
+ formType : 'create'
19
+ /** Only needed if you need to override the default button text (`Create ${resourceName}`) */
20
+ submitLabel ?: string
21
+ }
22
+
23
+ type EditFormProps = {
24
+ formType : 'edit'
25
+ /** Not permitted, as all edit form buttons should read `Update ${resourceName}` */
26
+ submitLabel ?: never
27
+ }
28
+
17
29
type SideModalFormProps < TFieldValues extends FieldValues > = {
18
- id : string
19
30
form : UseFormReturn < TFieldValues >
20
31
/**
21
32
* A function that returns the fields.
@@ -27,16 +38,17 @@ type SideModalFormProps<TFieldValues extends FieldValues> = {
27
38
*/
28
39
children : ReactNode
29
40
onDismiss : ( ) => void
41
+ resourceName : string
30
42
/** Must be provided with a reason describing why it's disabled */
31
43
submitDisabled ?: string
32
44
/** Error from the API call */
33
45
submitError : ApiError | null
34
46
loading ?: boolean
35
- title : string
47
+ /** Only needed if you need to override the default title (Create/Edit ${resourceName}) */
48
+ title ?: string
36
49
subtitle ?: ReactNode
37
50
onSubmit ?: ( values : TFieldValues ) => void
38
- submitLabel ?: string
39
- }
51
+ } & ( CreateFormProps | EditFormProps )
40
52
41
53
/**
42
54
* Only animate the modal in when we're navigating by a client-side click.
@@ -49,10 +61,11 @@ export function useShouldAnimateModal() {
49
61
}
50
62
51
63
export function SideModalForm < TFieldValues extends FieldValues > ( {
52
- id,
53
64
form,
65
+ formType,
54
66
children,
55
67
onDismiss,
68
+ resourceName,
56
69
submitDisabled,
57
70
submitError,
58
71
title,
@@ -61,6 +74,7 @@ export function SideModalForm<TFieldValues extends FieldValues>({
61
74
loading,
62
75
subtitle,
63
76
} : SideModalFormProps < TFieldValues > ) {
77
+ const id = useId ( )
64
78
const { isSubmitting } = form . formState
65
79
66
80
useEffect ( ( ) => {
@@ -70,11 +84,16 @@ export function SideModalForm<TFieldValues extends FieldValues>({
70
84
}
71
85
} , [ submitError , form ] )
72
86
87
+ const label =
88
+ formType === 'edit'
89
+ ? `Update ${ resourceName } `
90
+ : submitLabel || title || `Create ${ resourceName } `
91
+
73
92
return (
74
93
< SideModal
75
94
onDismiss = { onDismiss }
76
95
isOpen
77
- title = { title }
96
+ title = { title || ` ${ formType === 'edit' ? 'Edit' : 'Create' } ${ resourceName } ` }
78
97
animate = { useShouldAnimateModal ( ) }
79
98
subtitle = { subtitle }
80
99
errors = { submitError ? [ submitError . message ] : [ ] }
@@ -111,7 +130,7 @@ export function SideModalForm<TFieldValues extends FieldValues>({
111
130
loading = { loading || isSubmitting }
112
131
form = { id }
113
132
>
114
- { submitLabel || title }
133
+ { label }
115
134
</ Button >
116
135
) }
117
136
</ SideModal . Footer >
0 commit comments