Skip to content

Commit 39ac93a

Browse files
Attach floating IP modal and prop tweaks
1 parent e918849 commit 39ac93a

File tree

3 files changed

+44
-41
lines changed

3 files changed

+44
-41
lines changed

app/components/AttachFloatingIpModal.tsx

+36-36
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import { ListboxField } from '~/components/form/fields/ListboxField'
1313
import { HL } from '~/components/HL'
1414
import { addToast } from '~/stores/toast'
1515
import { Message } from '~/ui/lib/Message'
16-
import { Modal } from '~/ui/lib/Modal'
1716
import { Slash } from '~/ui/lib/Slash'
1817

18+
import { ModalForm } from './form/ModalForm'
19+
1920
function FloatingIpLabel({ fip }: { fip: FloatingIp }) {
2021
return (
2122
<div className="text-secondary selected:text-accent-secondary">
@@ -60,40 +61,39 @@ export const AttachFloatingIpModal = ({
6061
const floatingIp = form.watch('floatingIp')
6162

6263
return (
63-
<Modal isOpen title="Attach floating IP" onDismiss={onDismiss}>
64-
<Modal.Body>
65-
<Modal.Section>
66-
<Message
67-
variant="info"
68-
content={`Instance ‘${instance.name}’ will be reachable at the selected IP address`}
69-
/>
70-
<form>
71-
<ListboxField
72-
control={form.control}
73-
name="floatingIp"
74-
label="Floating IP"
75-
placeholder="Select a floating IP"
76-
items={floatingIps.map((ip) => ({
77-
value: ip.id,
78-
label: <FloatingIpLabel fip={ip} />,
79-
selectedLabel: ip.name,
80-
}))}
81-
required
82-
/>
83-
</form>
84-
</Modal.Section>
85-
</Modal.Body>
86-
<Modal.Footer
87-
actionText="Attach"
88-
disabled={!floatingIp}
89-
onAction={() =>
90-
floatingIpAttach.mutate({
91-
path: { floatingIp }, // note that this is an ID!
92-
body: { kind: 'instance', parent: instance.id },
93-
})
94-
}
95-
onDismiss={onDismiss}
96-
></Modal.Footer>
97-
</Modal>
64+
<ModalForm
65+
form={form}
66+
onDismiss={onDismiss}
67+
submitLabel="Attach floating IP"
68+
submitError={floatingIpAttach.error}
69+
loading={floatingIpAttach.isPending}
70+
title="Attach floating IP"
71+
onSubmit={() =>
72+
floatingIpAttach.mutate({
73+
path: { floatingIp }, // note that this is an ID!
74+
body: { kind: 'instance', parent: instance.id },
75+
})
76+
}
77+
submitDisabled={!floatingIp}
78+
>
79+
<Message
80+
variant="info"
81+
content={`Instance ‘${instance.name}’ will be reachable at the selected IP address`}
82+
/>
83+
<form>
84+
<ListboxField
85+
control={form.control}
86+
name="floatingIp"
87+
label="Floating IP"
88+
placeholder="Select a floating IP"
89+
items={floatingIps.map((ip) => ({
90+
value: ip.id,
91+
label: <FloatingIpLabel fip={ip} />,
92+
selectedLabel: ip.name,
93+
}))}
94+
required
95+
/>
96+
</form>
97+
</ModalForm>
9898
)
9999
}

app/components/form/ModalForm.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import { Modal, type ModalProps } from '~/ui/lib/Modal'
1717
type ModalFormProps<TFieldValues extends FieldValues> = {
1818
form: UseFormReturn<TFieldValues>
1919
children: ReactNode
20+
2021
/** Must be provided with a reason describing why it's disabled */
21-
submitDisabled?: string
22+
submitDisabled?: boolean
2223
onSubmit: (values: TFieldValues) => void
2324
submitLabel: string
25+
2426
// require loading and error so we can't forget to hook them up. there are a
2527
// few forms that don't need them, so we'll use dummy values
2628

@@ -33,7 +35,7 @@ export function ModalForm<TFieldValues extends FieldValues>({
3335
form,
3436
children,
3537
onDismiss,
36-
submitDisabled,
38+
submitDisabled = false,
3739
submitError,
3840
title,
3941
onSubmit,
@@ -44,6 +46,7 @@ export function ModalForm<TFieldValues extends FieldValues>({
4446
}: ModalFormProps<TFieldValues>) {
4547
const id = useId()
4648
const { isSubmitting } = form.formState
49+
4750
return (
4851
<Modal isOpen onDismiss={onDismiss} title={title} width={width} overlay={overlay}>
4952
<Modal.Body>
@@ -74,7 +77,7 @@ export function ModalForm<TFieldValues extends FieldValues>({
7477
onDismiss={onDismiss}
7578
formId={id}
7679
actionText={submitLabel}
77-
disabled={!!submitDisabled}
80+
disabled={submitDisabled}
7881
actionLoading={loading || isSubmitting}
7982
/>
8083
</Modal>

app/ui/lib/Modal.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Modal.Footer = ({
123123
actionText,
124124
actionLoading,
125125
cancelText,
126-
disabled = false,
126+
disabled,
127127
formId,
128128
}: FooterProps) => (
129129
<footer className="flex items-center justify-between border-t px-4 py-3 border-secondary">
@@ -138,7 +138,7 @@ Modal.Footer = ({
138138
size="sm"
139139
variant={actionType}
140140
onClick={onAction}
141-
disabled={disabled}
141+
disabled={!!disabled}
142142
loading={actionLoading}
143143
>
144144
{actionText}

0 commit comments

Comments
 (0)