C. Integrasi Create Book
1. Integrasi endpoint tambah buku
request endpoint create
http://localhost:5002/book/create
{
"title" : "Nextjs",
"author" : "ihsan",
"year" : 2020
}
book/interface/index.ts
import {
BaseResponsePagination,
} from "@/lib/axiosClient";
interface Book {
id: number;
title: string;
author: string;
year: number | undefined | string;
created_at: string;
updated_at: string;
}
export interface BookListResponse extends BaseResponsePagination {
data: Book[];
}
export interface BookListFilter extends Partial<Book> {
from_year?: string;
to_year?: string;
page : number ,
pageSize : number
}
export interface BookCreatePayload extends Pick<Book, "author" | "title" | "year"> {}
book/page.ts
"use client";
import Button from "@/components/Button";
import { Pagination } from "../../components/Pagination";
import { Table, Th, Thead, Tr, Tbody, Td } from "../../components/Table";
import useBookModule from "./lib";
import { Drawer } from "@/components/Drawer";
import Filter from "./module/Filter";
import { useClosure } from "@/hook";
import { useRouter } from "next/navigation";
const Book = () => {
const { useBookList} = useBookModule();
const router = useRouter()
const {
data,
isFetching,
isError,
params,
setParams,
handleFilter,
handleClear,
handlePageSize,
handlePage,
} = useBookList();
const { isOpen, onOpen, onClose } = useClosure();
return (
<>
<Drawer
onClose={onClose}
onClear={handleClear}
onSubmit={handleFilter}
title="Filter Buku"
isOpen={isOpen}
>
<Filter params={params} setParams={setParams} />
</Drawer>
<section className=" p-10 overflow-auto ">
<section className="flex items-center justify-between ">
<Button
width="sm"
onClick={onOpen}
colorSchema="blue"
title="Filter"
/>
<Button onClick={()=> {
router.push('/book/tambah')
}} width="sm" colorSchema="red" title="tambah" />
</section>
...
</>
);
};
export default Book;
book/lib/index.ts
import { useMutation, useQuery } from "@tanstack/react-query";
import { axiosClient } from "@/lib/axiosClient";
import Swal from "sweetalert2";
import {
BookCreatePayload,
BookListFilter,
BookListResponse,
} from "../interface";
import { usePagination } from "@/hook/usePagination";
const useBookModule = () => {
...
const useCreateBook = () => {
const { mutate, isLoading } = useMutation(
(payload: BookCreatePayload) => {
return axiosClient.post("/book/create", payload);
},
{
onSuccess: (response) => {
Swal.fire({
position: "top-end",
icon: "success",
title: response.data.message,
showConfirmButton: false,
timer: 1500,
});
},
onError: (error) => {
alert("ok");
},
}
);
return { mutate, isLoading };
};
return { useBookList, useCreateBook };
};
export default useBookModule;
Membuat Komponenn Create Book
book/tambah/page.ts
"use client";
import Button from "@/components/Button";
import InputText from "@/components/InputText";
import Label from "@/components/Label";
import Select from "@/components/Select";
import { useFormik, Form, FormikProvider } from "formik";
import * as yup from "yup";
import { BookCreatePayload } from "../interface";
import useBookModule from "../lib";
import Link from "next/link";
import { ArrowLongLeftIcon } from "@heroicons/react/20/solid";
const createBookSchema = yup.object().shape({
title: yup.string().nullable().default("").required("Wajib isi"),
author: yup.string().nullable().default("").required("Wajib isi"),
year: yup.number().nullable().default(undefined).required("Wajib pilih"),
});
const option = [
{
value: 2020,
label: "2020",
},
{
value: 2021,
label: "2021",
},
{
value: 2022,
label: "2022",
},
{
value: 2023,
label: "2023",
},
];
const CreateBook = () => {
const formik = useFormik<BookCreatePayload>({
initialValues: {},
validationSchema: createBookSchema,
enableReinitialize: true,
onSubmit: () => {
console.log("ok");
},
});
return (
<section className="flex items-center justify-center w-full h-full">
<section className="w-1/2">
<Link href={"/book"}>
<span className="flex items-center">
{" "}
<ArrowLongLeftIcon className="h-5 w-5 mr-2" />
Kembali
</span>
</Link>
<h2 className="text-xl font-bold text-gray-500">Tambah Buku</h2>
<FormikProvider value={formik}>
<Form className="space-y-5">
<section>
<Label htmlFor="title" title="Title" />
<InputText
value={"123"}
placeholder="Judul Buku"
id="title"
name="title"
/>
</section>
<section>
<Label htmlFor="author" title="Auhtor" />
<InputText
value={"123"}
placeholder="Penulis Buku"
id="author"
name="author"
/>
</section>
<section>
<Label htmlFor="year" title="Year" />
<Select value={"123"} id="year" name="year" options={option} />
</section>
<section>
<Button height="md" title="Simpan" colorSchema="blue" />
</section>
</Form>
</FormikProvider>
</section>
</section>
);
};
export default CreateBook;
book/tambah/page.ts
"use client";
import Button from "@/components/Button";
import InputText from "@/components/InputText";
import Label from "@/components/Label";
import Select from "@/components/Select";
import { useFormik, Form, FormikProvider } from "formik";
import * as yup from "yup";
import { BookCreatePayload } from "../interface";
import useBookModule from "../lib";
import Link from "next/link";
import { ArrowLongLeftIcon } from "@heroicons/react/20/solid";
const createBookSchema = yup.object().shape({
title: yup.string().nullable().default("").required("Wajib isi"),
author: yup.string().nullable().default("").required("Wajib isi"),
year: yup.number().nullable().default(undefined).required("Wajib pilih"),
});
const option = [
{
value: 2020,
label: "2020",
},
{
value: 2021,
label: "2021",
},
{
value: 2022,
label: "2022",
},
{
value: 2023,
label: "2023",
},
];
const CreateBook = () => {
const { useCreateBook } = useBookModule();
const { mutate, isLoading } = useCreateBook();
const onSubmit = async (values: BookCreatePayload) => {
mutate(values, {
onSuccess: () => {
resetForm();
setValues(createBookSchema.getDefault());
},
});
};
const formik = useFormik<BookCreatePayload>({
initialValues: createBookSchema.getDefault(),
validationSchema: createBookSchema,
enableReinitialize: true,
onSubmit: onSubmit,
});
const {
handleChange,
handleSubmit,
setFieldValue,
handleBlur,
values,
errors,
resetForm,
setValues,
} = formik;
return (
<section className="flex items-center justify-center w-full h-full">
<section className="w-1/2">
<Link href={"/book"}>
<span className="flex items-center" > <ArrowLongLeftIcon className="h-5 w-5 mr-2"/>Kembali</span>
</Link>
<h2 className="text-xl font-bold text-gray-500">Tambah Buku</h2>
<FormikProvider value={formik}>
<Form className="space-y-5" onSubmit={handleSubmit}>
<section>
<Label htmlFor="title" title="Title" />
<InputText
value={values.title}
placeholder="Judul Buku"
id="title"
name="title"
onChange={handleChange}
onBlur={handleBlur}
isError={!!errors.title}
messageError={errors.title}
/>
</section>
<section>
<Label htmlFor="author" title="Auhtor" />
<InputText
value={values.author}
placeholder="Penulis Buku"
id="author"
name="author"
onChange={handleChange}
onBlur={handleBlur}
isError={!!errors.author}
messageError={errors.author}
/>
</section>
<section>
<Label htmlFor="year" title="Year" />
<Select
value={values.year}
id="year"
name="year"
onChange={handleChange}
onBlur={handleBlur}
options={option}
isError={!!errors.year}
messageError={errors.year}
/>
</section>
<section>
<Button
height="md"
title="Simpan"
colorSchema="blue"
isLoading={isLoading}
isDisabled={isLoading}
/>
</section>
</Form>
</FormikProvider>
</section>
</section>
);
};
export default CreateBook;