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>
<form onSubmit={onSubmit} className="flex flex-col gap-8">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<InputField <ControlledInputField
control={form.control}
label="Pilih Item" label="Pilih Item"
name="itemName"
type="text" type="text"
placeholder="Pilih item yang dimasukkan ke roll" placeholder="Pilih item yang dimasukkan ke roll"
value={itemName}
onChange={(e) => setItemName(e.target.value)}
size="lg" size="lg"
className="w-full" className="w-full"
/> />
<InputField <ControlledInputField
control={form.control}
label="Quantity" label="Quantity"
name="quantity"
type="text" type="text"
placeholder="Masukkan Kuantitas Item" placeholder="Masukkan Kuantitas Item"
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
size="lg" size="lg"
className="w-full" className="w-full"
/> />
<InputField <ControlledInputField
control={form.control}
label="Chance Rate" label="Chance Rate"
name="chanceRate"
type="text" type="text"
placeholder="Masukkan Chance Rate (0.1 - 1)" placeholder="Masukkan Chance Rate (0.1 - 1)"
value={chanceRate}
onChange={(e) => setChanceRate(e.target.value)}
size="lg" size="lg"
className="w-full" className="w-full"
/> />
</div> </div>
<Button <Button variant="primary" size="lg" className="w-full" type="submit">
variant="primary"
size="lg"
className="w-full"
onClick={nextStep}
>
Tambahkan Item Tambahkan Item
</Button> </Button>
</form>
</Modal.Content> </Modal.Content>
</> </>
); );
@@ -113,7 +109,10 @@ interface IStepTwoProps {
resetStep: () => void; resetStep: () => void;
} }
const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => ( const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => {
const { onConfirm, onCancel } = useConfirmAddItem(onClose, resetStep);
return (
<> <>
<Modal.Header className="mb-0 text-center items-center"> <Modal.Header className="mb-0 text-center items-center">
<h2 className="text-p1 font-semibold text-primary-500 mb-3"> <h2 className="text-p1 font-semibold text-primary-500 mb-3">
@@ -129,10 +128,7 @@ const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => (
variant="bordered" variant="bordered"
size="lg" size="lg"
className="w-full" className="w-full"
onClick={() => { onClick={onCancel}
onClose();
resetStep();
}}
> >
Batal Batal
</Button> </Button>
@@ -140,16 +136,13 @@ const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => (
variant="primary" variant="primary"
size="lg" size="lg"
className="w-full" className="w-full"
onClick={() => { onClick={onConfirm}
handleAddItem && handleAddItem();
onClose();
resetStep();
}}
> >
Tambahkan Tambahkan
</Button> </Button>
</Modal.Content> </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,
};
};