Skip to content

F. Integrasi Create Bulk

1. Integrasi CreateBulk

Membuat Interface

Alt text

request endpoint create bulk
http://localhost:5002/book/create/bulk
payload endpoint create bulk
{
    "data" : [
    {
        "title": "NestJS For Backend",
        "author": "Ihsan",
        "year": 2023
    },
    {
        "title": "Become Network Engineer",
        "author": "Fathi",
        "year": 2021
    }  
]
}

response endpoint create bulk
{
    "status": "Success",
    "message": "Berhasil menyimpan 8 dan gagal 0",
    "data": {}
}
book/interface/index.ts
import { BaseResponsePagination } from "@/lib/axiosClient";

interface Book {
  id: number | undefined;
  title: string;
  author: string;
  year: number | undefined | string 
  created_at: string;
  updated_at: string;
}

...

export interface BookCreatePayload
  extends Pick<Book, "author" | "title" | "year"> {}

...

export interface BookCreateArrayPayload {
  data: BookCreatePayload[];
}

Membuat Service Create Bulk

book/lib/index.ts
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { axiosClient } from "@/lib/axiosClient";
import Swal from "sweetalert2";
import {
  BookCreateArrayPayload,
  BookCreatePayload,
  BookDetail,
  BookListFilter,
  BookListResponse,
  BookUpdatePayload,
} from "../interface";
import { usePagination } from "@/hook/usePagination";

const useBookModule = () => {

...

  const useCreateBulkBook = () => {
    const { mutate, isLoading } = useMutation(
      (payload: BookCreateArrayPayload) => {
        return axiosClient.post("/book/create/bulk", payload);
      },
      {
        onSuccess: (response) => {
          Swal.fire({
            position: "top-end",
            icon: "success",
            title: response.data.message,
            showConfirmButton: false,
            timer: 1000,
          });
        },
        onError: (error) => {
          Swal.fire({
            position: "top",
            icon: "error",
            title: "Ada Kesalahan",
            showConfirmButton: false,
            timer: 1000,
          });
        },
      }
    );
    return { mutate, isLoading };
  };


  return {
    useBookList,
    useCreateBook,
    useDetailBook,
    useUpdateBook,
    useDeleteBook,
    useCreateBulkBook
  };
};

export default useBookModule;

Menambahkan Navigati Create Bulk

app/book/oage.tsx
"use client";


const Book = () => {


  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"
          />
        <div className="space-x-5">
        <Button
            onClick={() => {
              router.push("/book/tambah");
            }}
            width="sm"
            colorSchema="red"
            title="tambah"
          />
          <Button
            onClick={() => {
              router.push("/book/tambah-bulk");
            }}
            width="sm"
            colorSchema="green"
            title="tambah bulk"
          />
        </div>
        </section>

  ...

export default Book;

Alt text

Membuat Halaman Create Bulk

Alt text

app/book/tambah-bulk/page.tsx
"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,
  FieldArray,
  ArrayHelpers,
  getIn
} from "formik";
import * as yup from "yup";
import { BookCreateArrayPayload } from "../interface";
import useBookModule from "../lib";
import Link from "next/link";
import { ArrowLongLeftIcon } from "@heroicons/react/20/solid";
import { createBookSchema } from "../tambah/page";
import { option } from "../tambah/page";
import { AddButton, DeleteButton } from "@/components/ButtonAction";

const defaultCatatanArray = {
  data: [
    {
      title: "",
      author: "",
      year: undefined,
    },
  ],
};

const createBookArraySchema = yup
  .object()
  .shape({
    data: yup.array().of(createBookSchema),
  })
  .default(defaultCatatanArray);

const CreateBook = () => {
  const { useCreateBulkBook } = useBookModule();
  const { mutate, isLoading } = useCreateBulkBook();
  const onSubmit = async (values: BookCreateArrayPayload) => {
    mutate(values, {
      onSuccess: () => {
        resetForm();
        setValues(defaultCatatanArray);
      },
    });
  };

  const formik = useFormik<BookCreateArrayPayload>({
    initialValues: createBookArraySchema.getDefault(),
    validationSchema: createBookArraySchema,
    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 overflow-auto py-10">
      <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>
        {JSON.stringify(errors)}
        <FormikProvider value={formik}>
          <Form className="space-y-5" onSubmit={handleSubmit}>
            <FieldArray
              name={"data"}
              render={(arrayHelpers: ArrayHelpers) => (
                <>
                  {values &&
                    values?.data?.map((value, index) => (
                      <section
                        key={index}
                        className="space-y-2 shadow-lg p-5 relative"
                      >
                        <section className="flex items-center justify-end">
                          <DeleteButton
                            onClick={() => arrayHelpers.remove(index)}
                          />
                        </section>
                        <section>
                          <Label htmlFor="title" title="Title" />
                          <InputText
                            value={value.title}
                            placeholder="Judul Buku"
                            id={`data[${index}]title`}
                            name={`data[${index}]title`}
                            onChange={handleChange}
                            onBlur={handleBlur}
                            isError={
                              getIn(errors?.data?.[index], "title")
                            }
                            messageError={ getIn(errors?.data?.[index], "title")}
                          />
                        </section>
                        <section>
                          <Label htmlFor="author" title="Auhtor" />
                          <InputText
                            value={value.author}
                            placeholder="Penulis Buku"
                            id={`data[${index}]author`}
                            name={`data[${index}]author`}
                            onChange={(e) => {
                              setFieldValue(
                                `data[${index}]author`,
                                e.target.value
                              );
                            }}
                            onBlur={handleBlur}
                            isError={
                              getIn(errors?.data?.[index], "author")
                            }
                            messageError={ getIn(errors?.data?.[index], "author")}
                          />
                        </section>
                        <section>
                          <Label htmlFor="year" title="Year" />
                          <Select
                            value={value.year}
                            id={`data[${index}]year`}
                            name={`data[${index}]year`}
                            onChange={handleChange}
                            onBlur={handleBlur}
                            options={option}
                            isError={
                              getIn(errors?.data?.[index], "year")
                            }
                            messageError={ getIn(errors?.data?.[index], "year")}
                          />
                        </section>
                      </section>
                    ))}

                  <section>
                    <AddButton
                      onClick={() =>
                        arrayHelpers.push(createBookSchema.getDefault())
                      }
                    />
                  </section>
                </>
              )}
            />

            <section>
              <Button
                height="md"
                title="Simpan"
                colorSchema="blue"
                isLoading={isLoading}
                isDisabled={isLoading}
              />
            </section>
          </Form>
        </FormikProvider>
      </section>
    </section>
  );
};

export default CreateBook;

Alt text Alt text