feat: 권한등록 작업
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
import { CreatePage } from "@/pages/role";
|
||||
export default CreatePage;
|
||||
@@ -1,9 +1,10 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
RoleService,
|
||||
RoleList,
|
||||
RoleParams,
|
||||
RoleService,
|
||||
RoleFormData,
|
||||
} from "../model/role-interface";
|
||||
|
||||
export class RoleApiService implements RoleService {
|
||||
@@ -13,6 +14,18 @@ export class RoleApiService implements RoleService {
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createRole(data: RoleFormData): Promise<void> {
|
||||
await client.post(ENDPOINT.USER_SERVICE.ROLES, data);
|
||||
}
|
||||
|
||||
public async checkDuplicateRoleId(roleId: string): Promise<boolean> {
|
||||
const response = await client.get(
|
||||
`${ENDPOINT.USER_SERVICE.ROLES}/check/dup`,
|
||||
{ params: { roleId } },
|
||||
);
|
||||
return response.data as boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export const RoleApi = new RoleApiService();
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { RolePage } from "./ui/role-page";
|
||||
export { CreatePage } from "./ui/create-page";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface RoleParams extends PageableParams {
|
||||
@@ -15,8 +16,19 @@ export interface Role {
|
||||
mngrYn: string;
|
||||
}
|
||||
|
||||
export const roleFormSchema = z.object({
|
||||
roleId: z.string(),
|
||||
roleName: z.string(),
|
||||
roleContent: z.string(),
|
||||
useYn: z.string(),
|
||||
mngrYn: z.string(),
|
||||
});
|
||||
|
||||
export type RoleList = PageableList<Role>;
|
||||
export type RoleFormData = z.infer<typeof roleFormSchema>;
|
||||
|
||||
export interface RoleService {
|
||||
getRoles: (params: RoleParams) => Promise<RoleList>;
|
||||
createRole: (data: RoleFormData) => Promise<void>;
|
||||
checkDuplicateRoleId: (roleId: string) => Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { RoleForm } from "./role-form";
|
||||
import { RoleApi } from "../api/role-service";
|
||||
import { roleFormSchema, type RoleFormData } from "../model/role-interface";
|
||||
|
||||
function CreatePage() {
|
||||
const router = useRouter();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const { mutateAsync: createRole } = useMutation({
|
||||
mutationFn: (data: RoleFormData) => RoleApi.createRole(data),
|
||||
onSuccess: () => {
|
||||
alert("등록되었습니다.", router.back);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<RoleFormData>({
|
||||
resolver: zodResolver(roleFormSchema),
|
||||
defaultValues: {
|
||||
mngrYn: "Y",
|
||||
useYn: "Y",
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">권한 등록</h3>
|
||||
</div>
|
||||
<RoleForm form={form} handleSave={createRole} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { CreatePage };
|
||||
@@ -0,0 +1,200 @@
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Label,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
} from "@common/components";
|
||||
import { FormWrapper } from "@/widgets/form-wrapper";
|
||||
import { FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
import { RoleApi } from "../api/role-service";
|
||||
import type { RoleFormData } from "../model/role-interface";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { useState } from "react";
|
||||
|
||||
type RoleFormProps = {
|
||||
roleId?: string;
|
||||
form: UseFormReturn<RoleFormData>;
|
||||
handleSave: (data: RoleFormData) => Promise<void>;
|
||||
};
|
||||
|
||||
function RoleForm({ form, roleId, ...props }: RoleFormProps) {
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const [isValidRoleId, setIsValidRoleId] = useState(false);
|
||||
|
||||
const { mutateAsync: checkDuplicateRoleId } = useMutation({
|
||||
mutationFn: (roleId: string) => RoleApi.checkDuplicateRoleId(roleId),
|
||||
onSuccess: (duplicate) => {
|
||||
if (!duplicate) {
|
||||
alert("사용가능한 권한ID입니다.");
|
||||
setIsValidRoleId(true);
|
||||
return;
|
||||
}
|
||||
alert("중복된 권한ID입니다.");
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<FormWrapper form={form} isModifyMode={!!roleId} {...props}>
|
||||
<div className="card">
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="85%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>권한ID</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="roleId"
|
||||
render={({ field }) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
onChange={(e) => {
|
||||
field.onChange(e);
|
||||
setIsValidRoleId(false);
|
||||
}}
|
||||
className="w-[20rem] !text-[1.3rem]"
|
||||
placeholder="권한ID를 입력하세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
<Button
|
||||
color="green"
|
||||
className="px-6"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
checkDuplicateRoleId(field.value);
|
||||
}}
|
||||
disabled={!field.value || isValidRoleId}
|
||||
>
|
||||
{isValidRoleId && <i className="diveicon di-check" />}
|
||||
중복확인
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>권한명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="roleName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="권한명을 입력하세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>권한내용</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="roleContent"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="권한내용을 입력하세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>관리권한여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="mngrYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<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>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="useYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<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>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</FormWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export { RoleForm };
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
@@ -14,6 +15,8 @@ import { columns } from "../model/table-columns";
|
||||
import type { Role, RoleParams } from "../model/role-interface";
|
||||
|
||||
function RolePage() {
|
||||
const router = useRouter();
|
||||
|
||||
const [roleQuery, setRoleQuery] = useState<RoleParams>({
|
||||
keyword: "",
|
||||
});
|
||||
@@ -76,7 +79,9 @@ function RolePage() {
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h3 className="text-2xl font-medium text-label">권한 목록</h3>
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={() => {}}>등록</Button>
|
||||
<Button onClick={() => router.push("/role/register")}>
|
||||
등록
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,12 +43,7 @@ function FormWrapper<T extends FieldValues>({
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
{children}
|
||||
<div className="flex justify-center gap-4 pb-12 pt-10">
|
||||
<Button
|
||||
size="lg"
|
||||
color="white"
|
||||
type="button"
|
||||
onClick={() => router.back()}
|
||||
>
|
||||
<Button size="lg" color="white" type="button" onClick={router.back}>
|
||||
목록
|
||||
</Button>
|
||||
<Button size="lg" type="submit">
|
||||
|
||||
Reference in New Issue
Block a user