feat: 모듈 API 등록 페이지 작업
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
import { CreatePage } from "@/pages/module";
|
||||
export default CreatePage;
|
||||
@@ -113,7 +113,6 @@ function BannerForm({ form, bnrSn, ...props }: BannerFormProps) {
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
upCd="BNRTYPE"
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
|
||||
@@ -128,7 +128,7 @@ function ImageForm({ form, imgSn, ...props }: ImageFormProps) {
|
||||
field.onChange(Number(value));
|
||||
}}
|
||||
className="w-[12rem] !text-[1.3rem]"
|
||||
placeholder="정렬순서를 입력해주세요"
|
||||
placeholder="정렬순서 입력"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
@@ -147,7 +147,6 @@ function ImageForm({ form, imgSn, ...props }: ImageFormProps) {
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
upCd="IMGTYPE"
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,8 @@ import type {
|
||||
AuthorizationsService,
|
||||
AuthorizationsParams,
|
||||
AuthorizationsList,
|
||||
AuthorizationFormData,
|
||||
WithRoleAuthorizations,
|
||||
} from "../model/authorizations-interface";
|
||||
|
||||
export class AuthorizationsApiService implements AuthorizationsService {
|
||||
@@ -16,6 +18,16 @@ export class AuthorizationsApiService implements AuthorizationsService {
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createAuthorization(
|
||||
data: AuthorizationFormData,
|
||||
): Promise<WithRoleAuthorizations> {
|
||||
const response = await client.post<WithRoleAuthorizations>(
|
||||
`${ENDPOINT.USER_SERVICE.AUTHORIZATIONS}`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const AuthorizationsApi = new AuthorizationsApiService();
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { ModulePage } from "./ui/module-page";
|
||||
export { CreatePage } from "./ui/create-page";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface AuthorizationsParams extends PageableParams {
|
||||
@@ -16,10 +17,34 @@ export interface Authorizations {
|
||||
mdfcnDt: string;
|
||||
}
|
||||
|
||||
export interface WithRoleAuthorizations extends Authorizations {
|
||||
roleAuthorizations: {
|
||||
roleId: string;
|
||||
authorizationNo: number;
|
||||
authorizationName: string;
|
||||
urlPatternValue: string;
|
||||
httpMethodCode: string;
|
||||
sortSeq: number;
|
||||
createdAt: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export const authorizationFormSchema = z.object({
|
||||
authorizationName: z.string(),
|
||||
urlPatternValue: z.string(),
|
||||
httpMethodCode: z.string(),
|
||||
sortSeq: z.number(),
|
||||
useYn: z.string(),
|
||||
});
|
||||
|
||||
export type AuthorizationsList = PageableList<Authorizations>;
|
||||
export type AuthorizationFormData = z.infer<typeof authorizationFormSchema>;
|
||||
|
||||
export interface AuthorizationsService {
|
||||
getAuthorizationsList(
|
||||
getAuthorizationsList: (
|
||||
params: AuthorizationsParams,
|
||||
): Promise<AuthorizationsList>;
|
||||
) => Promise<AuthorizationsList>;
|
||||
createAuthorization: (
|
||||
data: AuthorizationFormData,
|
||||
) => Promise<WithRoleAuthorizations>;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export const columns: ColumnDef<Authorizations>[] = [
|
||||
},
|
||||
{
|
||||
accessorKey: "authorizationName",
|
||||
header: "API 명",
|
||||
header: "API명",
|
||||
},
|
||||
{
|
||||
accessorKey: "urlPatternValue",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
"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 {
|
||||
authorizationFormSchema,
|
||||
type AuthorizationFormData,
|
||||
} from "../model/authorizations-interface";
|
||||
import { AuthorizationsApi } from "../api/authorization-service";
|
||||
import { ModuleForm } from "./module-form";
|
||||
|
||||
function CreatePage() {
|
||||
const router = useRouter();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const { mutateAsync: createAuthorization } = useMutation({
|
||||
mutationFn: (data: AuthorizationFormData) =>
|
||||
AuthorizationsApi.createAuthorization(data),
|
||||
onSuccess: () => {
|
||||
alert("등록되었습니다.", router.back);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<AuthorizationFormData>({
|
||||
resolver: zodResolver(authorizationFormSchema),
|
||||
defaultValues: {
|
||||
sortSeq: 0,
|
||||
useYn: "Y",
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">모듈API 등록</h3>
|
||||
</div>
|
||||
<ModuleForm form={form} handleSave={createAuthorization} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { CreatePage };
|
||||
@@ -0,0 +1,166 @@
|
||||
"use client";
|
||||
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
import {
|
||||
Input,
|
||||
Label,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
} from "@common/components";
|
||||
import { FormWrapper } from "@/widgets/form-wrapper";
|
||||
import { CodeSelect } from "@/entities/code";
|
||||
import { FormControl, FormField, FormItem } from "@/shared/ui/form";
|
||||
import type {
|
||||
AuthorizationFormData,
|
||||
WithRoleAuthorizations,
|
||||
} from "../model/authorizations-interface";
|
||||
|
||||
type BannerFormProps = {
|
||||
form: UseFormReturn<AuthorizationFormData>;
|
||||
authorizationNo?: number;
|
||||
handleSave: (data: AuthorizationFormData) => Promise<WithRoleAuthorizations>;
|
||||
handleDelete?: () => Promise<void>;
|
||||
};
|
||||
|
||||
function ModuleForm({ form, authorizationNo, ...props }: BannerFormProps) {
|
||||
return (
|
||||
<FormWrapper form={form} isModifyMode={!!authorizationNo} {...props}>
|
||||
<div className="card">
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="85%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>API명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="authorizationName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="API명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>API URL</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="urlPatternValue"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="API URL을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>요청 메소드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="httpMethodCode"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
{...field}
|
||||
upCd="HTTPMHD"
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>정렬순서</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="sortSeq"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
min={0}
|
||||
value={field.value ?? ""}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
if (isNaN(Number(value))) return;
|
||||
field.onChange(Number(value));
|
||||
}}
|
||||
className="w-[12rem] !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="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 { ModuleForm };
|
||||
@@ -9,14 +9,14 @@ import {
|
||||
type PaginationState,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button, DataTable, Input, Label } from "@common/components";
|
||||
import { CodeSelect } from "@/entities/code";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { AuthorizationsApi } from "../api/authorization-service";
|
||||
import type {
|
||||
Authorizations,
|
||||
AuthorizationsParams,
|
||||
} from "../model/authorizations-interface";
|
||||
import { columns } from "../model/table-columns";
|
||||
import { CodeSelect } from "@/entities/code";
|
||||
import { AuthorizationsApi } from "../api/authorization-service";
|
||||
|
||||
function ModulePage() {
|
||||
const router = useRouter();
|
||||
@@ -89,7 +89,7 @@ function ModulePage() {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="keyword" className="text-label">
|
||||
API 명
|
||||
API명
|
||||
</Label>
|
||||
<Input
|
||||
id="keyword"
|
||||
@@ -108,10 +108,8 @@ function ModulePage() {
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">콘텐츠 목록</h3>
|
||||
<Button onClick={() => router.push("/contents/register")}>
|
||||
등록
|
||||
</Button>
|
||||
<h3 className="text-2xl font-medium text-label">모듈API 목록</h3>
|
||||
<Button onClick={() => router.push("/module/register")}>등록</Button>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] h-[49.5rem] overflow-auto !p-0">
|
||||
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
|
||||
|
||||
@@ -110,8 +110,8 @@ function SiteForm({ form, siteId, ...props }: SiteFormProps) {
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
upCd="SITESKINCD"
|
||||
value={field.value ?? ""}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -8,8 +8,8 @@ type FormWrapperProps<T extends FieldValues> = {
|
||||
form: UseFormReturn<T>;
|
||||
children: React.ReactNode;
|
||||
isModifyMode?: boolean;
|
||||
handleSave: (data: T) => Promise<void>;
|
||||
handleDelete?: () => Promise<void>;
|
||||
handleSave: (data: T) => Promise<unknown>;
|
||||
handleDelete?: () => Promise<unknown>;
|
||||
};
|
||||
|
||||
function FormWrapper<T extends FieldValues>({
|
||||
|
||||
Reference in New Issue
Block a user