feat: 메뉴 폼 작업
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const MENU_TYPE = {
|
||||
EMPTY: "EMPTY",
|
||||
CONTENTS: "CONTENTS",
|
||||
BOARD: "BOARD",
|
||||
INSIDE: "INSIDE",
|
||||
OUTSIDE: "OUTSIDE",
|
||||
BOTTOM: "BOTTOM",
|
||||
} as const;
|
||||
|
||||
export type MenuType = (typeof MENU_TYPE)[keyof typeof MENU_TYPE];
|
||||
|
||||
export interface Menu {
|
||||
menuCd: number;
|
||||
menuKornNm: string;
|
||||
@@ -19,6 +30,7 @@ export interface Menu {
|
||||
}
|
||||
|
||||
export const menuFormSchema = z.object({
|
||||
siteId: z.string(),
|
||||
menuKornNm: z.string(),
|
||||
menuSubKornNm: z.string().nullish(),
|
||||
menuEngNm: z.string().nullish(),
|
||||
@@ -26,14 +38,21 @@ export const menuFormSchema = z.object({
|
||||
levelNo: z.number(),
|
||||
urlPath: z.string().nullish(),
|
||||
iconNm: z.string().nullish(),
|
||||
menuLnkgTypeCd: z.string().nullish(),
|
||||
menuLnkgTypeCd: z.enum([
|
||||
MENU_TYPE.EMPTY,
|
||||
MENU_TYPE.CONTENTS,
|
||||
MENU_TYPE.BOARD,
|
||||
MENU_TYPE.INSIDE,
|
||||
MENU_TYPE.OUTSIDE,
|
||||
MENU_TYPE.BOTTOM,
|
||||
]),
|
||||
menuLnkgSn: z.number().nullish(),
|
||||
otptYn: z.string().nullish(),
|
||||
otptYn: z.enum(["Y", "N"]).default("Y"),
|
||||
prntMenuCd: z.number().nullish(),
|
||||
sortSeq: z.number(),
|
||||
evlUseYn: z.string().nullish(),
|
||||
evlUseYn: z.enum(["Y", "N"]).nullish(),
|
||||
qrcd: z.string().nullish(),
|
||||
useYn: z.string().nullish(),
|
||||
useYn: z.enum(["Y", "N"]).default("Y"),
|
||||
});
|
||||
|
||||
export type MenuFormData = z.infer<typeof menuFormSchema>;
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
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 { MENU_TYPE, type MenuFormData } from "../model/menu-interface";
|
||||
|
||||
interface BaseMenuFormProps {
|
||||
form: UseFormReturn<MenuFormData>;
|
||||
}
|
||||
|
||||
export function BaseMenuForm({ form }: BaseMenuFormProps) {
|
||||
return (
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="20%" />
|
||||
<col width="80%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>메뉴명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="menuKornNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="메뉴명을 입력하십시오."
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>메뉴 영문명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="menuEngNm"
|
||||
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">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="menuLnkgTypeCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<div className="flex items-center space-x-4">
|
||||
{Object.entries(MENU_TYPE).map(([key, value]) => (
|
||||
<div
|
||||
key={key}
|
||||
className="flex items-center space-x-2"
|
||||
>
|
||||
<RadioGroupItem
|
||||
value={value}
|
||||
id={`menuType${key}`}
|
||||
/>
|
||||
<Label htmlFor={`menuType${key}`}>
|
||||
{key === "EMPTY" && "빈메뉴"}
|
||||
{key === "CONTENTS" && "콘텐츠"}
|
||||
{key === "BOARD" && "게시판"}
|
||||
{key === "INSIDE" && "내부링크"}
|
||||
{key === "OUTSIDE" && "외부링크"}
|
||||
{key === "BOTTOM" && "하단메뉴"}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
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 type { MenuFormData } from "../model/menu-interface";
|
||||
|
||||
export function ContentMenuForm({
|
||||
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="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>
|
||||
<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>
|
||||
<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>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
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 type { MenuFormData } from "../model/menu-interface";
|
||||
|
||||
export function EmptyMenuForm({ form }: { form: UseFormReturn<MenuFormData> }) {
|
||||
return (
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="20%" />
|
||||
<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>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { useState } from "react";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { type UseFormReturn } from "react-hook-form";
|
||||
import { Button } from "@common/components";
|
||||
import { Form } from "@/shared/ui/form";
|
||||
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
|
||||
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";
|
||||
|
||||
interface MenuFormProps {
|
||||
form: UseFormReturn<MenuFormData>;
|
||||
menuId?: string;
|
||||
handleSave: (data: MenuFormData) => Promise<void>;
|
||||
handleDelete?: () => Promise<void>;
|
||||
}
|
||||
|
||||
export function MenuForm({
|
||||
form,
|
||||
menuId,
|
||||
handleSave,
|
||||
handleDelete,
|
||||
}: MenuFormProps) {
|
||||
const isModifyMode = !!menuId;
|
||||
const { confirm } = useConfirm();
|
||||
const [onConfirm, setOnConfirm] = useState(false);
|
||||
|
||||
const menuType = form.watch("menuLnkgTypeCd");
|
||||
|
||||
const onSubmit = async (data: MenuFormData) => {
|
||||
const confirmMessage = isModifyMode
|
||||
? "수정하시겠습니까?"
|
||||
: "저장하시겠습니까?";
|
||||
|
||||
setOnConfirm(true);
|
||||
if (await confirm(confirmMessage)) {
|
||||
setOnConfirm(false);
|
||||
handleSave(data);
|
||||
}
|
||||
setOnConfirm(false);
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
setOnConfirm(true);
|
||||
if (await confirm("삭제하시겠습니까?")) {
|
||||
setOnConfirm(false);
|
||||
handleDelete?.();
|
||||
}
|
||||
setOnConfirm(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">
|
||||
메뉴 등록/수정
|
||||
</h3>
|
||||
</div>
|
||||
<div className="card">
|
||||
<BaseMenuForm form={form} />
|
||||
<div className="-mt-[0.1rem]">
|
||||
{renderMenuTypeComponent(menuType, form)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center gap-4 pb-12 pt-10">
|
||||
<Button size="lg" type="submit">
|
||||
저장
|
||||
</Button>
|
||||
{isModifyMode && (
|
||||
<Button size="lg" color="red" type="button" onClick={onDelete}>
|
||||
삭제
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
<ConfirmDialog open={onConfirm} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderMenuTypeComponent(
|
||||
menuType: string,
|
||||
form: UseFormReturn<MenuFormData>,
|
||||
) {
|
||||
switch (menuType) {
|
||||
case MENU_TYPE.EMPTY:
|
||||
return <EmptyMenuForm form={form} />;
|
||||
case MENU_TYPE.CONTENTS:
|
||||
return <ContentMenuForm form={form} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import {
|
||||
Button,
|
||||
Select,
|
||||
@@ -10,11 +12,13 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@common/components/ui";
|
||||
import { PageLayout } from "@/shared/ui/page-layout";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { SiteApi } from "@/entities/site";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { PageLayout } from "@/shared/ui/page-layout";
|
||||
import { MenuApi } from "../api/menu-service";
|
||||
import { menuFormSchema, type MenuFormData } from "../model/menu-interface";
|
||||
import { MenuTree } from "./menu-tree";
|
||||
import { MenuForm } from "./menu-form";
|
||||
|
||||
function MenuPage() {
|
||||
const [siteId, setSiteId] = useState("");
|
||||
@@ -22,15 +26,14 @@ function MenuPage() {
|
||||
const { data: treeData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.MENUS, siteId],
|
||||
queryFn: () => MenuApi.getMenuList(siteId),
|
||||
select: (data) => {
|
||||
return data.map((menu) => ({
|
||||
select: (data) =>
|
||||
data.map((menu) => ({
|
||||
id: menu.menuCd,
|
||||
parent: menu.parentId ?? 0,
|
||||
text: menu.menuKornNm,
|
||||
droppable: true,
|
||||
data: menu,
|
||||
}));
|
||||
},
|
||||
})),
|
||||
enabled: !!siteId,
|
||||
});
|
||||
|
||||
@@ -44,9 +47,19 @@ function MenuPage() {
|
||||
})),
|
||||
});
|
||||
|
||||
const form = useForm<MenuFormData>({
|
||||
resolver: zodResolver(menuFormSchema),
|
||||
});
|
||||
|
||||
const handleSave = async (data: MenuFormData) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {};
|
||||
|
||||
return (
|
||||
<PageLayout pageTitle="메뉴 관리">
|
||||
<div className="flex gap-4">
|
||||
<div className="card flex gap-2">
|
||||
<div className="card card-border">
|
||||
<Select value={siteId} onValueChange={setSiteId}>
|
||||
<SelectTrigger className="w-[18rem]">
|
||||
@@ -76,7 +89,13 @@ function MenuPage() {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="card card-border"></div>
|
||||
<div className="card card-border flex-1">
|
||||
<MenuForm
|
||||
form={form}
|
||||
handleSave={handleSave}
|
||||
handleDelete={handleDelete}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user