feat: 메뉴 유형별 폼 작업

This commit is contained in:
2025-03-24 17:42:59 +09:00
parent 791098e0c0
commit 8aa6d20c63
10 changed files with 438 additions and 203 deletions
@@ -0,0 +1,122 @@
import { type UseFormReturn } from "react-hook-form";
import {
IconFinder,
Input,
Label,
RadioGroup,
RadioGroupItem,
TableCell,
TableHead,
TableRow,
} from "@common/components";
import {
FormItem,
FormControl,
FormField,
FormMessage,
} from "@/shared/ui/form";
import type { MenuFormData } from "../model/menu-interface";
export function BaseBottomMenuForm({
form,
}: {
form: UseFormReturn<MenuFormData>;
}) {
const handleIconClick = (icon: string) => {
form.setValue("iconNm", icon);
};
return (
<>
<TableRow>
<TableHead>메뉴 서브명</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="menuSubKornNm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
placeholder="메뉴 서브명을 입력하십시오."
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>메뉴 아이콘</TableHead>
<TableCell className="border">
<div className="flex gap-2">
<div className="h-[3.2rem] w-[21.5rem] cursor-not-allowed rounded-md border border-input bg-form px-3 py-2 text-[1.3rem] opacity-50">
{form.watch("iconNm")}
</div>
<IconFinder handleClick={handleIconClick} />
</div>
</TableCell>
</TableRow>
<TableRow>
<TableHead>출력 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="otptYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup {...field} onValueChange={field.onChange}>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="otptY" />
<Label htmlFor="otptY">출력</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="otptN" />
<Label htmlFor="otptN">출력안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>사용 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="useYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup {...field} onValueChange={field.onChange}>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="useY" />
<Label htmlFor="useY">사용</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="useN" />
<Label htmlFor="useN">사용안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
</>
);
}
@@ -0,0 +1,144 @@
import { type UseFormReturn } from "react-hook-form";
import {
Label,
RadioGroup,
RadioGroupItem,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from "@common/components";
import {
FormItem,
FormControl,
FormField,
FormMessage,
} from "@/shared/ui/form";
import type { MenuFormData } from "../model/menu-interface";
import { BaseBottomMenuForm } from "./base-bottom-menu-form";
export function BoardMenuForm({ form }: { form: UseFormReturn<MenuFormData> }) {
return (
<Table variant="secondary">
<colgroup>
<col width="20%" />
<col width="80%" />
</colgroup>
<TableBody>
<TableRow>
<TableHead>게시판</TableHead>
<TableCell className="border">
<div className="h-[3.2rem] w-[21.5rem] cursor-not-allowed rounded-md border border-input bg-form px-3 py-2 text-[1.3rem] opacity-50">
{form.watch("menuLnkgSn")}
</div>
</TableCell>
</TableRow>
<TableRow>
<TableHead>연결 형태</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="evlUseYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
value={field.value ?? ""}
onValueChange={field.onChange}
>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="self" id="self" />
<Label htmlFor="self">현재창</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="blank" id="blank" />
<Label htmlFor="blank">새창</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>메뉴 평가 사용 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="evlUseYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
value={field.value ?? ""}
onValueChange={field.onChange}
>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="evlUseY" />
<Label htmlFor="evlUseY">사용</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="evlUseN" />
<Label htmlFor="evlUseN">사용안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<BaseBottomMenuForm form={form} />
<TableRow>
<TableHead>QR코드</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="qrcd"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
value={field.value ?? ""}
onValueChange={field.onChange}
>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="qrcdY" />
<Label htmlFor="qrcdY">사용</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="qrcdN" />
<Label htmlFor="qrcdN">사용안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>담당자</TableHead>
<TableCell className="border">
<div className="h-[3.2rem] w-[21.5rem] cursor-not-allowed rounded-md border border-input bg-form px-3 py-2 text-[1.3rem] opacity-50">
{form.watch("menuLnkgSn")}
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
@@ -0,0 +1,22 @@
import { type UseFormReturn } from "react-hook-form";
import { Table, TableBody } from "@common/components";
import type { MenuFormData } from "../model/menu-interface";
import { BaseBottomMenuForm } from "./base-bottom-menu-form";
export function BottomMenuForm({
form,
}: {
form: UseFormReturn<MenuFormData>;
}) {
return (
<Table variant="secondary">
<colgroup>
<col width="20%" />
<col width="80%" />
</colgroup>
<TableBody>
<BaseBottomMenuForm form={form} />
</TableBody>
</Table>
);
}
+43 -93
View File
@@ -1,6 +1,5 @@
import { type UseFormReturn } from "react-hook-form";
import {
Input,
Label,
RadioGroup,
RadioGroupItem,
@@ -17,6 +16,7 @@ import {
FormMessage,
} from "@/shared/ui/form";
import type { MenuFormData } from "../model/menu-interface";
import { BaseBottomMenuForm } from "./base-bottom-menu-form";
export function ContentMenuForm({
form,
@@ -38,6 +38,37 @@ export function ContentMenuForm({
</div>
</TableCell>
</TableRow>
<TableRow>
<TableHead>연결 형태</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="evlUseYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
value={field.value ?? ""}
onValueChange={field.onChange}
>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="self" id="self" />
<Label htmlFor="self">현재창</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="blank" id="blank" />
<Label htmlFor="blank">새창</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>메뉴 평가 사용 여부</TableHead>
<TableCell className="border">
@@ -69,98 +100,9 @@ export function ContentMenuForm({
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>메뉴 서브명</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="menuSubKornNm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
placeholder="메뉴 서브명을 입력하십시오."
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>메뉴 아이콘</TableHead>
<TableCell className="border">
<div className="h-[3.2rem] w-[21.5rem] cursor-not-allowed rounded-md border border-input bg-form px-3 py-2 text-[1.3rem] opacity-50">
{form.watch("iconNm")}
</div>
</TableCell>
</TableRow>
<TableRow>
<TableHead>출력 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="otptYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
value={field.value ?? ""}
onValueChange={field.onChange}
>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="otptY" />
<Label htmlFor="otptY">출력</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="otptN" />
<Label htmlFor="otptN">출력안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>사용 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="useYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
value={field.value ?? ""}
onValueChange={field.onChange}
>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="useY" />
<Label htmlFor="useY">사용</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="useN" />
<Label htmlFor="useN">사용안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<BaseBottomMenuForm form={form} />
<TableRow>
<TableHead>QR코드</TableHead>
<TableCell className="border">
@@ -192,6 +134,14 @@ export function ContentMenuForm({
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>담당자</TableHead>
<TableCell className="border">
<div className="h-[3.2rem] w-[21.5rem] cursor-not-allowed rounded-md border border-input bg-form px-3 py-2 text-[1.3rem] opacity-50">
{form.watch("menuLnkgSn")}
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
);
+3 -103
View File
@@ -1,22 +1,7 @@
import { type UseFormReturn } from "react-hook-form";
import {
Input,
Label,
RadioGroup,
RadioGroupItem,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from "@common/components";
import {
FormItem,
FormControl,
FormField,
FormMessage,
} from "@/shared/ui/form";
import { Table, TableBody } from "@common/components";
import type { MenuFormData } from "../model/menu-interface";
import { BaseBottomMenuForm } from "./base-bottom-menu-form";
export function EmptyMenuForm({ form }: { form: UseFormReturn<MenuFormData> }) {
return (
@@ -26,92 +11,7 @@ export function EmptyMenuForm({ form }: { form: UseFormReturn<MenuFormData> }) {
<col width="80%" />
</colgroup>
<TableBody>
<TableRow>
<TableHead>메뉴 서브명</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="menuSubKornNm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
placeholder="메뉴 서브명을 입력하십시오."
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>메뉴 아이콘</TableHead>
<TableCell className="border">
<div className="h-[3.2rem] w-[21.5rem] cursor-not-allowed rounded-md border border-input bg-form px-3 py-2 text-[1.3rem] opacity-50">
{form.watch("iconNm")}
</div>
</TableCell>
</TableRow>
<TableRow>
<TableHead>출력 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="otptYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup {...field} onValueChange={field.onChange}>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="otptY" />
<Label htmlFor="otptY">출력</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="otptN" />
<Label htmlFor="otptN">출력안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>사용 여부</TableHead>
<TableCell className="border">
<FormField
control={form.control}
name="useYn"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup {...field} onValueChange={field.onChange}>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="useY" />
<Label htmlFor="useY">사용</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="useN" />
<Label htmlFor="useN">사용안함</Label>
</div>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
</TableRow>
<BaseBottomMenuForm form={form} />
</TableBody>
</Table>
);
@@ -0,0 +1,22 @@
import { type UseFormReturn } from "react-hook-form";
import { Table, TableBody } from "@common/components";
import type { MenuFormData } from "../model/menu-interface";
import { BaseBottomMenuForm } from "./base-bottom-menu-form";
export function InsideMenuForm({
form,
}: {
form: UseFormReturn<MenuFormData>;
}) {
return (
<Table variant="secondary">
<colgroup>
<col width="20%" />
<col width="80%" />
</colgroup>
<TableBody>
<BaseBottomMenuForm form={form} />
</TableBody>
</Table>
);
}
+12
View File
@@ -8,6 +8,10 @@ import { MENU_TYPE, type MenuFormData } from "../model/menu-interface";
import { BaseMenuForm } from "./base-menu-form";
import { EmptyMenuForm } from "./empty-menu-form";
import { ContentMenuForm } from "./content-menu-form";
import { BoardMenuForm } from "./board-menu-form";
import { InsideMenuForm } from "./inside-menu-form";
import { OutsideMenuForm } from "./outside-menu-form";
import { BottomMenuForm } from "./bottom-menu-form";
interface MenuFormProps {
form: UseFormReturn<MenuFormData>;
@@ -93,6 +97,14 @@ function renderMenuTypeComponent(
return <EmptyMenuForm form={form} />;
case MENU_TYPE.CONTENTS:
return <ContentMenuForm form={form} />;
case MENU_TYPE.BOARD:
return <BoardMenuForm form={form} />;
case MENU_TYPE.INSIDE:
return <InsideMenuForm form={form} />;
case MENU_TYPE.OUTSIDE:
return <OutsideMenuForm form={form} />;
case MENU_TYPE.BOTTOM:
return <BottomMenuForm form={form} />;
default:
return null;
}
@@ -0,0 +1,22 @@
import { type UseFormReturn } from "react-hook-form";
import { Table, TableBody } from "@common/components";
import type { MenuFormData } from "../model/menu-interface";
import { BaseBottomMenuForm } from "./base-bottom-menu-form";
export function OutsideMenuForm({
form,
}: {
form: UseFormReturn<MenuFormData>;
}) {
return (
<Table variant="secondary">
<colgroup>
<col width="20%" />
<col width="80%" />
</colgroup>
<TableBody>
<BaseBottomMenuForm form={form} />
</TableBody>
</Table>
);
}
@@ -1,18 +1,39 @@
import { useState } from "react";
import { Button } from "../button";
import { Dialog, DialogContent, DialogTrigger } from "../dialog";
import { cn } from "../../lib";
import iconNames from "./data";
const IconFinder = () => {
type IconFinderProps = {
handleClick: (icon: string) => void;
};
const IconFinder = ({ handleClick }: IconFinderProps) => {
const [selectedIcon, setSelectedIcon] = useState("");
const handleIconClick = (icon: string) => {
setSelectedIcon(icon);
handleClick(icon);
};
return (
<Dialog>
<DialogTrigger asChild>
<Button>아이콘 찾기</Button>
<Button className="leading-none">
<i className="diveicon di-search" />
아이콘 찾기
</Button>
</DialogTrigger>
<DialogContent className="max-h-[65rem] max-w-[65rem] overflow-y-auto p-12">
<div className="py-4">
<div className="grid grid-cols-5 gap-10 text-[2.4rem]">
<div className="grid grid-cols-5 gap-6 text-[2.4rem]">
{iconNames.map((icon) => (
<IconItem key={icon} icon={icon} />
<IconItem
key={icon}
icon={icon}
selectedIcon={selectedIcon}
handleClick={handleIconClick}
/>
))}
</div>
</div>
@@ -21,9 +42,29 @@ const IconFinder = () => {
);
};
const IconItem = ({ icon }: { icon: string }) => {
const IconItem = ({
icon,
selectedIcon,
handleClick,
}: {
icon: string;
selectedIcon: string;
handleClick: (icon: string) => void;
}) => {
return (
<div className="flex flex-col items-center gap-2">
<div
className={cn(
"relative flex cursor-pointer flex-col items-center gap-2 rounded-md p-4",
selectedIcon === icon && "bg-accent",
)}
onClick={() => handleClick(icon)}
>
<i
className={cn(
"diveicon di-check absolute left-4 top-4 text-[1rem] text-primary",
selectedIcon !== icon && "hidden",
)}
/>
<i className={`diveicon di-${icon}`} />
<span className="text-center text-[1.2rem]">{icon}</span>
</div>
+1 -1
View File
@@ -7,8 +7,8 @@ export * from "./data-table";
export * from "./date-picker";
export * from "./dialog";
export * from "./dropdown-menu";
export * from "./input";
export * from "./file-search";
export * from "./icon-finder";
export * from "./input";
export * from "./label";
export * from "./layout";