Make board edit fields use a form layout

This commit is contained in:
Mike Cao
2026-03-06 23:54:44 -08:00
parent acfd4462e3
commit 07ff25bf7e
3 changed files with 84 additions and 79 deletions
@@ -0,0 +1,67 @@
import { Form, FormField, TextField } from '@umami/react-zen';
import { Panel } from '@/components/common/Panel';
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
import { WebsiteSelect } from '@/components/input/WebsiteSelect';
export function BoardEditForm() {
const { board, updateBoard, saveBoard } = useBoard();
const { t, labels } = useMessages();
const { teamId } = useNavigation();
const handleNameChange = (name: string) => {
updateBoard({ name });
};
const handleDescriptionChange = (description: string) => {
updateBoard({ description });
};
const handleWebsiteChange = (websiteId: string) => {
updateBoard({
parameters: {
...board.parameters,
websiteId,
},
});
};
return (
<Panel title={t(labels.details)} marginBottom="6">
<Form
onSubmit={saveBoard}
values={{
name: board?.name ?? '',
description: board?.description ?? '',
websiteId: board?.parameters?.websiteId ?? '',
}}
>
<FormField name="name" label={t(labels.name)} rules={{ required: t(labels.required) }}>
<TextField
autoComplete="off"
autoFocus={!board?.id}
value={board?.name ?? ''}
placeholder={t(labels.untitled)}
onChange={handleNameChange}
/>
</FormField>
<FormField name="description" label={t(labels.description)}>
<TextField
autoComplete="off"
asTextArea
resize="vertical"
value={board?.description ?? ''}
placeholder={t(labels.addDescription)}
onChange={handleDescriptionChange}
/>
</FormField>
<FormField name="websiteId" label={t(labels.website)}>
<WebsiteSelect
websiteId={board?.parameters?.websiteId}
teamId={teamId}
onChange={handleWebsiteChange}
/>
</FormField>
</Form>
</Panel>
);
}
@@ -1,33 +1,13 @@
import {
Button,
Column,
Grid,
Heading,
LoadingButton,
Row,
Text,
TextField,
} from '@umami/react-zen';
import { Button, LoadingButton, Row } from '@umami/react-zen';
import { PageHeader } from '@/components/common/PageHeader';
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
import { WebsiteSelect } from '@/components/input/WebsiteSelect';
export function BoardEditHeader() {
const { board, updateBoard, saveBoard, isPending } = useBoard();
const { board, saveBoard, isPending } = useBoard();
const { t, labels } = useMessages();
const { router, renderUrl, teamId } = useNavigation();
const { router, renderUrl } = useNavigation();
const defaultName = t(labels.untitled);
const handleNameChange = (value: string) => {
updateBoard({ name: value });
};
const handleDescriptionChange = (value: string) => {
updateBoard({ description: value });
};
const handleWebsiteChange = (websiteId: string) => {
updateBoard({ parameters: { ...board.parameters, websiteId } });
};
const title = board?.id ? board?.name || defaultName : t(labels.addBoard);
const handleSave = async () => {
await saveBoard();
@@ -45,59 +25,15 @@ export function BoardEditHeader() {
};
return (
<Grid
columns={{ base: '1fr', md: '1fr 1fr' }}
paddingY="4"
marginBottom="6"
border="bottom"
gapX="6"
>
<Column>
<Row>
<TextField
variant="quiet"
name="name"
value={board?.name ?? ''}
placeholder={defaultName}
onChange={handleNameChange}
autoComplete="off"
style={{ fontSize: '2rem', fontWeight: 700, width: '100%' }}
>
<Heading size="xl">{board?.name}</Heading>
</TextField>
</Row>
<Row>
<TextField
variant="quiet"
name="description"
value={board?.description ?? ''}
placeholder={`+ ${t(labels.addDescription)}`}
autoComplete="off"
onChange={handleDescriptionChange}
style={{ width: '100%' }}
>
{board?.description}
</TextField>
</Row>
<Row alignItems="center" gap="3">
<Text>{t(labels.website)}</Text>
<WebsiteSelect
websiteId={board?.parameters?.websiteId}
teamId={teamId}
onChange={handleWebsiteChange}
/>
</Row>
</Column>
<Column justifyContent="center" alignItems="flex-end">
<Row gap="3">
<Button variant="quiet" onPress={handleCancel}>
{t(labels.cancel)}
</Button>
<LoadingButton variant="primary" onPress={handleSave} isLoading={isPending}>
{t(labels.save)}
</LoadingButton>
</Row>
</Column>
</Grid>
<PageHeader title={title}>
<Row gap="3">
<Button variant="quiet" onPress={handleCancel}>
{t(labels.cancel)}
</Button>
<LoadingButton variant="primary" onPress={handleSave} isLoading={isPending}>
{t(labels.save)}
</LoadingButton>
</Row>
</PageHeader>
);
}
@@ -4,6 +4,7 @@ import { BoardProvider } from '@/app/(main)/boards/BoardProvider';
import { PageBody } from '@/components/common/PageBody';
import { BoardControls } from './BoardControls';
import { BoardEditBody } from './BoardEditBody';
import { BoardEditForm } from './BoardEditForm';
import { BoardEditHeader } from './BoardEditHeader';
export function BoardEditPage({ boardId }: { boardId?: string }) {
@@ -12,6 +13,7 @@ export function BoardEditPage({ boardId }: { boardId?: string }) {
<PageBody>
<Column>
<BoardEditHeader />
<BoardEditForm />
<BoardControls />
<BoardEditBody />
</Column>