Skip to content

Commit

Permalink
Refactor form component (#22)
Browse files Browse the repository at this point in the history
* FormItem 컴포넌트 추가 및 FormItem 기반으로 MoonForm 변경

* Form을 key 기반으로 변경

* preview 페이지에서 title, description이 없을때 기본값이 들어갈 수 있는 틀 마련

* 초기 데이터에 type 추가

* LinkPreview에서 title, description에 type 에러나던 것 수정
  • Loading branch information
hmu332233 authored Nov 21, 2022
1 parent adf5bc0 commit ede2c86
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 53 deletions.
19 changes: 19 additions & 0 deletions components/FormItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { HTMLInputTypeAttribute } from 'react';

type Props = {
label: string;
children: React.ReactNode;
};

function FormItem({ label, children }: Props) {
return (
<div className="form-control w-full max-w-xs">
<label className="label">
<span className="label-text">{label}</span>
</label>
{children}
</div>
);
}

export default FormItem;
96 changes: 61 additions & 35 deletions components/MoonForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { objectToQueryString } from 'utils/string';

import { FormProvider, useForm } from 'react-hook-form';
import ControlledLiveToggle from 'components/ControlledLiveToggle';
import FormItem from './FormItem';

const DEFAULT_VALUES: FormValues = {
const DEFAULT_FORM_KEYS: FormKeys[] = ['size', 'theme', 'rotate'];

const DEFAULT_FORM_VALUES: FormValues = {
liveMode: true,
date: '',
size: '',
Expand All @@ -16,10 +19,15 @@ const DEFAULT_VALUES: FormValues = {

type Props = {
defaultValues?: FormValues;
keys?: FormKeys[];
onChange: (v: FormValues) => void;
};

function MoonForm({ defaultValues = DEFAULT_VALUES, onChange }: Props) {
function MoonForm({
keys = DEFAULT_FORM_KEYS,
defaultValues = DEFAULT_FORM_VALUES,
onChange,
}: Props) {
const formMethods = useForm<FormValues>({
defaultValues,
});
Expand All @@ -37,25 +45,28 @@ function MoonForm({ defaultValues = DEFAULT_VALUES, onChange }: Props) {
return () => subscription.unsubscribe();
}, [watch, onChange]);

return (
<FormProvider {...formMethods}>
<ControlledLiveToggle name="liveMode" />
{!liveMode && (
<div className="form-control w-full max-w-xs">
<label className="label">
<span className="label-text">Date</span>
</label>
<input
type="date"
className="input input-bordered w-full max-w-xs"
{...register('date')}
/>
</div>
)}
<div className="form-control w-full max-w-xs">
<label className="label" htmlFor="theme">
<span className="label-text">Theme</span>
</label>
const formItemMap: { [key: string]: React.ReactNode } = {
date: (
<FormItem key="date" label="Date">
<input
type="date"
className="input input-bordered w-full max-w-xs"
{...register('date')}
/>
</FormItem>
),
size: (
<FormItem key="size" label="Size">
<input
type="number"
placeholder="100 (default)"
className="input input-bordered w-full max-w-xs"
{...register('size')}
/>
</FormItem>
),
theme: (
<FormItem key="theme" label="Theme">
<select
id="theme"
className="select input-bordered w-full max-w-xs"
Expand All @@ -64,30 +75,45 @@ function MoonForm({ defaultValues = DEFAULT_VALUES, onChange }: Props) {
<option value="basic">Basic</option>
<option value="ray">Ray</option>
</select>
</div>
<div className="form-control w-full max-w-xs">
<label className="label">
<span className="label-text">Rotate</span>
</label>
</FormItem>
),
rotate: (
<FormItem key="rotate" label="Rotate">
<input
type="range"
min="0"
max="360"
className="range"
{...register('rotate')}
/>
</div>
<div className="form-control w-full max-w-xs">
<label className="label">
<span className="label-text">Size</span>
</label>
</FormItem>
),
title: (
<FormItem key="title" label="Title">
<input
type="number"
placeholder="100 (default)"
type="text"
className="input input-bordered w-full max-w-xs"
{...register('size')}
{...register('title')}
/>
</div>
</FormItem>
),
description: (
<FormItem key="description" label="Description">
<input
type="text"
className="input input-bordered w-full max-w-xs"
{...register('description')}
/>
</FormItem>
),
};

return (
<FormProvider {...formMethods}>
{/* TODO: date도 item으로 관리할 수 있도록 변경 */}
<ControlledLiveToggle name="liveMode" />
{!liveMode && formItemMap.date}
{keys.map((key) => formItemMap[key])}
</FormProvider>
);
}
Expand Down
46 changes: 31 additions & 15 deletions pages/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,48 @@ import OgTags from 'components/OgTags';
import MoonForm from 'components/MoonForm';
import LinkPreviewCard from 'components/LinkPreviewCard';

const PREVIEW_FORM_KEYS: FormKeys[] = ['theme', 'title', 'description'];

type Props = {
query: FormValues;
};
function Preview({ query }: Props) {
const [queryString, setQueryString] = useState(objectToQueryString(query));
const [data, setData] = useState<FormValues>({
...query,
title: query.title || '기본값',
description: query.description || '기본값',
});

const queryString = objectToQueryString({
...data,
date: data.liveMode ? '' : data.date,
});

const svgUrl = `/moon.svg${queryString}`;

const handleFormChange = ({
liveMode,
date,
size,
theme,
rotate,
title,
description,
}: FormValues) => {
const queryString = objectToQueryString({
setData({
date: liveMode ? '' : date,
size,
theme,
rotate,
title,
description,
});
setQueryString(queryString);
};

const defaultValues: FormValues = {
date: query.date,
liveMode: !query.date,
rotate: query.rotate,
size: query.size,
theme: query.theme,
date: data.date,
liveMode: !data.date,
rotate: data.rotate,
size: data.size,
theme: data.theme,
title: data.title,
description: data.description,
};

useEffect(() => {
Expand All @@ -57,10 +69,14 @@ function Preview({ query }: Props) {
<p>Share Moon&apos;s Phases with your friends!</p>
<LinkPreviewCard
image={`https://moon-svg.minung.dev/moon.png${queryString}`}
title="Moon.svg"
description="테스트"
title={data.title!}
description={data.description!}
/>
<MoonForm
keys={PREVIEW_FORM_KEYS}
defaultValues={defaultValues}
onChange={handleFormChange}
/>
<MoonForm defaultValues={defaultValues} onChange={handleFormChange} />
</Layout>
);
}
Expand Down
10 changes: 7 additions & 3 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
type FormValues = {
liveMode: boolean;
date: string;
size: string;
theme: string;
rotate: string;
liveMode?: boolean;
size?: string;
rotate?: string;
title?: string;
description?: string;
};

type FormKeys = keyof FormValues;

1 comment on commit ede2c86

@vercel
Copy link

@vercel vercel bot commented on ede2c86 Nov 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.