feat: custom hook for add gacha roll item

- Buat custom hook untuk add item
This commit is contained in:
Hafid Nur
2025-04-05 06:41:11 +07:00
parent 2746af0b3f
commit 885d156833
2 changed files with 133 additions and 81 deletions
@@ -1,6 +1,7 @@
import { Button } from '@imphnen-frontend-service/ui/atoms'; import { Button } from '@imphnen-frontend-service/ui/atoms';
import { InputField, Modal } from '@imphnen-frontend-service/ui/molecules'; import { Modal } from '@imphnen-frontend-service/ui/molecules';
import { useState } from 'react'; import { ControlledInputField } from '@imphnen-frontend-service/ui/organisms';
import { useAddItem, useConfirmAddItem } from '../_hook/use-add-item';
interface IModalAddItem { interface IModalAddItem {
isOpen: boolean; isOpen: boolean;
@@ -49,9 +50,7 @@ interface IStepOneProps {
} }
const StepOne = ({ nextStep }: IStepOneProps) => { const StepOne = ({ nextStep }: IStepOneProps) => {
const [itemName, setItemName] = useState(''); const { form, onSubmit } = useAddItem(nextStep);
const [quantity, setQuantity] = useState('');
const [chanceRate, setChanceRate] = useState('');
return ( return (
<> <>
@@ -63,45 +62,42 @@ const StepOne = ({ nextStep }: IStepOneProps) => {
Lengkapi detal di bawah ini, untuk menambahkan item gacha Lengkapi detal di bawah ini, untuk menambahkan item gacha
</p> </p>
</Modal.Header> </Modal.Header>
<Modal.Content className="flex flex-col gap-8"> <Modal.Content>
<div className="flex flex-col gap-4"> <form onSubmit={onSubmit} className="flex flex-col gap-8">
<InputField <div className="flex flex-col gap-4">
label="Pilih Item" <ControlledInputField
type="text" control={form.control}
placeholder="Pilih item yang dimasukkan ke roll" label="Pilih Item"
value={itemName} name="itemName"
onChange={(e) => setItemName(e.target.value)} type="text"
size="lg" placeholder="Pilih item yang dimasukkan ke roll"
className="w-full" size="lg"
/> className="w-full"
<InputField />
label="Quantity" <ControlledInputField
type="text" control={form.control}
placeholder="Masukkan Kuantitas Item" label="Quantity"
value={quantity} name="quantity"
onChange={(e) => setQuantity(e.target.value)} type="text"
size="lg" placeholder="Masukkan Kuantitas Item"
className="w-full" size="lg"
/> className="w-full"
<InputField />
label="Chance Rate" <ControlledInputField
type="text" control={form.control}
placeholder="Masukkan Chance Rate (0.1 - 1)" label="Chance Rate"
value={chanceRate} name="chanceRate"
onChange={(e) => setChanceRate(e.target.value)} type="text"
size="lg" placeholder="Masukkan Chance Rate (0.1 - 1)"
className="w-full" size="lg"
/> className="w-full"
</div> />
</div>
<Button <Button variant="primary" size="lg" className="w-full" type="submit">
variant="primary" Tambahkan Item
size="lg" </Button>
className="w-full" </form>
onClick={nextStep}
>
Tambahkan Item
</Button>
</Modal.Content> </Modal.Content>
</> </>
); );
@@ -113,43 +109,40 @@ interface IStepTwoProps {
resetStep: () => void; resetStep: () => void;
} }
const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => ( const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => {
<> const { onConfirm, onCancel } = useConfirmAddItem(onClose, resetStep);
<Modal.Header className="mb-0 text-center items-center">
<h2 className="text-p1 font-semibold text-primary-500 mb-3"> return (
Tambah ke Roll Gacha <>
</h2> <Modal.Header className="mb-0 text-center items-center">
<p className="text-p3 text-neutral-400"> <h2 className="text-p1 font-semibold text-primary-500 mb-3">
Apakah kamu yakin ingin Tambah ke Roll Gacha
<br /> menambahkan item ini ke roll gacha? </h2>
</p> <p className="text-p3 text-neutral-400">
</Modal.Header> Apakah kamu yakin ingin
<Modal.Content className="flex gap-4"> <br /> menambahkan item ini ke roll gacha?
<Button </p>
variant="bordered" </Modal.Header>
size="lg" <Modal.Content className="flex gap-4">
className="w-full" <Button
onClick={() => { variant="bordered"
onClose(); size="lg"
resetStep(); className="w-full"
}} onClick={onCancel}
> >
Batal Batal
</Button> </Button>
<Button <Button
variant="primary" variant="primary"
size="lg" size="lg"
className="w-full" className="w-full"
onClick={() => { onClick={onConfirm}
handleAddItem && handleAddItem(); >
onClose(); Tambahkan
resetStep(); </Button>
}} </Modal.Content>
> </>
Tambahkan );
</Button> };
</Modal.Content>
</>
);
export default ModalAddItem; export default ModalAddItem;
@@ -0,0 +1,59 @@
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
const addItemSchema = z.object({
itemName: z.string().min(1, 'Item name is required'),
quantity: z.string().min(1, 'Quantity is required'),
chanceRate: z
.string()
.min(1, 'Chance rate is required')
.refine(
(val) => {
const num = parseFloat(val);
return num >= 0.1 && num <= 1;
},
{ message: 'Chance rate must be between 0.1 and 1' }
),
});
type TAddItemForm = z.infer<typeof addItemSchema>;
export const useAddItem = (nextStep: () => void) => {
const form = useForm<TAddItemForm>({
resolver: zodResolver(addItemSchema),
mode: 'all',
});
const onSubmit = form.handleSubmit((data) => {
console.log('Form data:', data);
nextStep();
});
return {
form,
onSubmit,
};
};
export const useConfirmAddItem = (
onClose: () => void,
resetStep: () => void,
handleAddItem?: () => void,
) => {
const onConfirm = () => {
handleAddItem?.();
onClose();
resetStep();
};
const onCancel = () => {
onClose();
resetStep();
};
return {
onConfirm,
onCancel,
};
};