From 745a2d28734beb9791ccbc1cea86fa1d34dbc449 Mon Sep 17 00:00:00 2001 From: Hafid Nur Date: Sat, 5 Apr 2025 06:07:26 +0700 Subject: [PATCH] feat: slicing Gacha Roll page --- .../gacha-roll/_components/modal-add-item.tsx | 155 +++++++++++++ .../_components/modal-delete-item.tsx | 62 +++++ .../_components/modal-update-item.tsx | 152 ++++++++++++ apps/backoffice/src/app/gacha-roll/layout.tsx | 18 ++ apps/backoffice/src/app/gacha-roll/page.tsx | 216 ++++++++++++++++++ 5 files changed, 603 insertions(+) create mode 100644 apps/backoffice/src/app/gacha-roll/_components/modal-add-item.tsx create mode 100644 apps/backoffice/src/app/gacha-roll/_components/modal-delete-item.tsx create mode 100644 apps/backoffice/src/app/gacha-roll/_components/modal-update-item.tsx create mode 100644 apps/backoffice/src/app/gacha-roll/layout.tsx create mode 100644 apps/backoffice/src/app/gacha-roll/page.tsx diff --git a/apps/backoffice/src/app/gacha-roll/_components/modal-add-item.tsx b/apps/backoffice/src/app/gacha-roll/_components/modal-add-item.tsx new file mode 100644 index 0000000..b077c94 --- /dev/null +++ b/apps/backoffice/src/app/gacha-roll/_components/modal-add-item.tsx @@ -0,0 +1,155 @@ +import { Button } from '@imphnen-frontend-service/ui/atoms'; +import { InputField, Modal } from '@imphnen-frontend-service/ui/molecules'; +import { useState } from 'react'; + +interface IModalAddItem { + isOpen: boolean; + onClose: () => void; + handleAddItem?: () => void; + currentStep?: number; + nextStep: () => void; + prevStep: () => void; + resetStep: () => void; +} + +const ModalAddItem = ({ + isOpen, + onClose, + currentStep, + nextStep, + prevStep, + resetStep, + handleAddItem, +}: IModalAddItem) => { + return ( + { + onClose(); + resetStep(); + }} + disableEscapeKeyDown={true} + > + {currentStep === 1 && } + {currentStep === 2 && ( + + )} + + ); +}; + +interface IStepOneProps { + nextStep: () => void; + onClose: () => void; +} + +const StepOne = ({ nextStep }: IStepOneProps) => { + const [itemName, setItemName] = useState(''); + const [quantity, setQuantity] = useState(''); + const [chanceRate, setChanceRate] = useState(''); + + return ( + <> + +

+ Tambah Item Roll Gacha +

+

+ Lengkapi detal di bawah ini, untuk menambahkan item gacha +

+
+ +
+ setItemName(e.target.value)} + size="lg" + className="w-full" + /> + setQuantity(e.target.value)} + size="lg" + className="w-full" + /> + setChanceRate(e.target.value)} + size="lg" + className="w-full" + /> +
+ + +
+ + ); +}; + +interface IStepTwoProps { + onClose: () => void; + handleAddItem?: () => void; + resetStep: () => void; +} + +const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => ( + <> + +

+ Tambah ke Roll Gacha +

+

+ Apakah kamu yakin ingin +
menambahkan item ini ke roll gacha? +

+
+ + + + + +); + +export default ModalAddItem; diff --git a/apps/backoffice/src/app/gacha-roll/_components/modal-delete-item.tsx b/apps/backoffice/src/app/gacha-roll/_components/modal-delete-item.tsx new file mode 100644 index 0000000..3663ee0 --- /dev/null +++ b/apps/backoffice/src/app/gacha-roll/_components/modal-delete-item.tsx @@ -0,0 +1,62 @@ +import { Button } from '@imphnen-frontend-service/ui/atoms'; +import { Modal } from '@imphnen-frontend-service/ui/molecules'; + +interface IModalDeleteItem { + isOpen: boolean; + onClose: () => void; + handleDeleteItem?: () => void; +} + +const ModalDeleteItem = ({ + isOpen, + onClose, + handleDeleteItem, +}: IModalDeleteItem) => { + return ( + + + Delete item? +
+

+ Delete Item +

+

+ Apakah kamu yakin untuk menghapus item ini? +

+
+
+ + + + +
+ ); +}; + +export default ModalDeleteItem; diff --git a/apps/backoffice/src/app/gacha-roll/_components/modal-update-item.tsx b/apps/backoffice/src/app/gacha-roll/_components/modal-update-item.tsx new file mode 100644 index 0000000..f9dee1c --- /dev/null +++ b/apps/backoffice/src/app/gacha-roll/_components/modal-update-item.tsx @@ -0,0 +1,152 @@ +import { Button } from '@imphnen-frontend-service/ui/atoms'; +import { InputField, Modal } from '@imphnen-frontend-service/ui/molecules'; +import { useState } from 'react'; + +interface IModalUpdateItem { + isOpen: boolean; + onClose: () => void; + handleUpdateItem?: () => void; + currentStep?: number; + nextStep: () => void; + prevStep: () => void; + resetStep: () => void; +} + +const ModalUpdateItem = ({ + isOpen, + onClose, + currentStep, + nextStep, + prevStep, + resetStep, + handleUpdateItem, +}: IModalUpdateItem) => { + return ( + { + onClose(); + resetStep(); + }} + disableEscapeKeyDown={true} + > + {currentStep === 1 && } + {currentStep === 2 && ( + + )} + + ); +}; + +interface IStepOneProps { + nextStep: () => void; + onClose: () => void; +} + +const StepOne = ({ nextStep }: IStepOneProps) => { + const [itemName, setItemName] = useState('Hoodie IMPHNEN Official 2025'); + const [quantity, setQuantity] = useState('10'); + const [chanceRate, setChanceRate] = useState('0.1'); + + return ( + <> + +

+ Update Item Roll Gacha +

+
+ +
+ setItemName(e.target.value)} + size="lg" + className="w-full" + /> + setQuantity(e.target.value)} + size="lg" + className="w-full" + /> + setChanceRate(e.target.value)} + size="lg" + className="w-full" + /> +
+ + +
+ + ); +}; + +interface IStepTwoProps { + onClose: () => void; + handleUpdateItem?: () => void; + resetStep: () => void; +} + +const StepTwo = ({ onClose, handleUpdateItem, resetStep }: IStepTwoProps) => ( + <> + +

+ Update Item +

+

+ Apakah kamu yakin dengan +
perubahan yang dilakukan? +

+
+ + + + + +); + +export default ModalUpdateItem; diff --git a/apps/backoffice/src/app/gacha-roll/layout.tsx b/apps/backoffice/src/app/gacha-roll/layout.tsx new file mode 100644 index 0000000..a770c99 --- /dev/null +++ b/apps/backoffice/src/app/gacha-roll/layout.tsx @@ -0,0 +1,18 @@ +import { FC, ReactElement } from 'react'; +import { Outlet } from 'react-router-dom'; +import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms'; + +export const AppLayout: FC = (): ReactElement => { + return ( +
+
+ +
+ +
+
+
+ ); +}; + +export default AppLayout; diff --git a/apps/backoffice/src/app/gacha-roll/page.tsx b/apps/backoffice/src/app/gacha-roll/page.tsx new file mode 100644 index 0000000..0bc7499 --- /dev/null +++ b/apps/backoffice/src/app/gacha-roll/page.tsx @@ -0,0 +1,216 @@ +import * as React from 'react'; + +import { FC, Fragment, ReactElement, useState } from 'react'; +import { + SearchOutlined, + EditOutlined, + DeleteOutlined, + PlusOutlined, +} from '@ant-design/icons'; +import { Button, Input } from '@imphnen-frontend-service/ui/atoms'; +import { DataTable } from '@imphnen-frontend-service/ui/organisms'; + +import { + ColumnDef, + getCoreRowModel, + getPaginationRowModel, + PaginationState, + useReactTable, + RowSelectionState, +} from '@tanstack/react-table'; +import ModalAddItem from './_components/modal-add-item'; +import ModalUpdateItem from './_components/modal-update-item'; +import ModalDeleteItem from './_components/modal-delete-item'; +import { useQueryState } from '@imphnen-frontend-service/utils'; + +interface GachaItem { + id: number; + name: string; + chanceRate: number; + quantity: number; +} + +const mockData: GachaItem[] = Array.from({ length: 90 }, (_, i) => ({ + id: i + 1, + name: 'Hoodie IMPHNEN Official 2025', + chanceRate: 0.1, + quantity: 10, +})); + +export const Components: FC = (): ReactElement => { + const [showModalAddItem, setShowModalAddItem] = useState(false); + const [showModalUpdateItem, setShowModalUpdateItem] = useState(false); + const [showModalDeleteItem, setShowModalDeleteItem] = useState(false); + + const { + step: currentStep, + nextStep, + prevStep, + resetStep, + } = useQueryState('step', { + defaultValue: 1, + maxValue: 2, + minValue: 1, + }); + + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: 9, + }); + + const [rowSelection, setRowSelection] = React.useState({}); + + const columns: ColumnDef[] = [ + { + id: 'select', + header: ({ table }) => ( + + ), + cell: ({ row }) => ( + + ), + }, + { + header: 'No', + accessorKey: 'id', + }, + { + header: 'Nama Item', + accessorKey: 'name', + }, + { + header: 'Chance Rate', + accessorKey: 'chanceRate', + }, + { + header: 'Quantity', + accessorKey: 'quantity', + }, + { + header: 'Action', + cell: () => ( +
+ + +
+ ), + }, + ]; + + const table = useReactTable({ + data: mockData, + columns, + state: { + pagination, + rowSelection, + }, + enableRowSelection: true, + onRowSelectionChange: setRowSelection, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onPaginationChange: setPagination, + pageCount: Math.ceil(mockData.length / pagination.pageSize), + manualPagination: false, + }); + + return ( + +
+
+

Gacha Roll

+
+ +
+
+
+ +
+ +
+
+
+ +
+
+ + +
+
+ + setShowModalAddItem(false)} + handleAddItem={() => { + console.log('Item added'); + }} + nextStep={nextStep} + prevStep={prevStep} + resetStep={resetStep} + /> + setShowModalUpdateItem(false)} + handleUpdateItem={() => { + console.log('Item updated'); + }} + nextStep={nextStep} + prevStep={prevStep} + resetStep={resetStep} + /> + setShowModalDeleteItem(false)} + handleDeleteItem={() => { + console.log('Item deleted'); + }} + /> +
+ ); +}; + +export default Components;