refactor: fix validation for add gacha roll item
- Pisahkan type dan schema untuk gacha roll item - Perbaiki validasi gacha roll item - Parsing angka pada component ControlledInputField - Update type number untuk component Input dan InputField
This commit is contained in:
@@ -78,7 +78,8 @@ const StepOne = ({ nextStep }: IStepOneProps) => {
|
|||||||
control={form.control}
|
control={form.control}
|
||||||
label="Quantity"
|
label="Quantity"
|
||||||
name="quantity"
|
name="quantity"
|
||||||
type="text"
|
type="number"
|
||||||
|
min={1}
|
||||||
placeholder="Masukkan Kuantitas Item"
|
placeholder="Masukkan Kuantitas Item"
|
||||||
size="lg"
|
size="lg"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
@@ -87,8 +88,12 @@ const StepOne = ({ nextStep }: IStepOneProps) => {
|
|||||||
control={form.control}
|
control={form.control}
|
||||||
label="Chance Rate"
|
label="Chance Rate"
|
||||||
name="chanceRate"
|
name="chanceRate"
|
||||||
type="text"
|
type="number"
|
||||||
placeholder="Masukkan Chance Rate (0.1 - 1)"
|
value={0.1}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={1}
|
||||||
|
placeholder="Masukkan Chance Rate (0,1 - 1)"
|
||||||
size="lg"
|
size="lg"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,27 +1,13 @@
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import {
|
||||||
const addItemSchema = z.object({
|
gachaRollItemSchema,
|
||||||
itemName: z.string().min(1, 'Item name is required'),
|
TGachaRollItem
|
||||||
quantity: z.string().min(1, 'Quantity is required'),
|
} from '@imphnen-frontend-service/service';
|
||||||
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) => {
|
export const useAddItem = (nextStep: () => void) => {
|
||||||
const form = useForm<TAddItemForm>({
|
const form = useForm<TGachaRollItem>({
|
||||||
resolver: zodResolver(addItemSchema),
|
resolver: zodResolver(gachaRollItemSchema),
|
||||||
mode: 'all',
|
mode: 'all',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const gachaRollItemSchema = z.object({
|
||||||
|
itemName: z
|
||||||
|
.string({
|
||||||
|
required_error: 'Nama item tidak boleh kosong',
|
||||||
|
invalid_type_error: 'Nama item harus berupa string',
|
||||||
|
})
|
||||||
|
.min(1, 'Nama item tidak boleh kosong'),
|
||||||
|
quantity: z
|
||||||
|
.number({
|
||||||
|
required_error: 'Quantity tidak boleh kosong',
|
||||||
|
invalid_type_error: 'Quantity harus berupa angka',
|
||||||
|
})
|
||||||
|
.min(1, 'Quantity paling sedikit adalah 1'),
|
||||||
|
chanceRate: z
|
||||||
|
.number({
|
||||||
|
required_error: 'Chance rate tidak boleh kosong',
|
||||||
|
invalid_type_error: 'Chance rate harus berupa angka',
|
||||||
|
})
|
||||||
|
.min(0.1, 'Chance rate paling sedikit adalah 0,1')
|
||||||
|
.max(1, 'Chance rate paling banyak adalah 1'),
|
||||||
|
});
|
||||||
@@ -1 +1,2 @@
|
|||||||
export * from './auth';
|
export * from './auth';
|
||||||
|
export * from './gacha';
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
export {};
|
export type TGachaRollItem = {
|
||||||
|
itemName: string;
|
||||||
|
quantity: number;
|
||||||
|
chanceRate: number;
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; // Import
|
|||||||
import { cn } from '@imphnen-frontend-service/utils';
|
import { cn } from '@imphnen-frontend-service/utils';
|
||||||
import { Button } from '../button';
|
import { Button } from '../button';
|
||||||
|
|
||||||
type TInputType = 'text' | 'email' | 'password' | 'file';
|
type TInputType = 'text' | 'email' | 'number' | 'password' | 'file';
|
||||||
type TInputSize = 'sm' | 'md' | 'lg';
|
type TInputSize = 'sm' | 'md' | 'lg';
|
||||||
|
|
||||||
type TInputProps = Omit<
|
type TInputProps = Omit<
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
import { Input } from '../../atoms';
|
import { Input } from '../../atoms';
|
||||||
import { cn } from '@imphnen-frontend-service/utils';
|
import { cn } from '@imphnen-frontend-service/utils';
|
||||||
|
|
||||||
export type TInputType = 'text' | 'email' | 'password' | 'file';
|
export type TInputType = 'text' | 'email' | 'number' | 'password' | 'file';
|
||||||
export type TInputSize = 'sm' | 'md' | 'lg';
|
export type TInputSize = 'sm' | 'md' | 'lg';
|
||||||
export type TInputFieldProps = Omit<
|
export type TInputFieldProps = Omit<
|
||||||
DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
|
DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
|
||||||
|
|||||||
@@ -15,7 +15,19 @@ export const ControlledInputField = <T extends FieldValues>(
|
|||||||
props: TControlledInputFieldProps<T>
|
props: TControlledInputFieldProps<T>
|
||||||
) => {
|
) => {
|
||||||
const { field, fieldState } = useController<T>(props);
|
const { field, fieldState } = useController<T>(props);
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const value =
|
||||||
|
props.type === 'number' ? Number(e.target.value) : e.target.value;
|
||||||
|
field.onChange(value);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputField error={fieldState.error?.message} {...{ ...props, ...field }} />
|
<InputField
|
||||||
|
error={fieldState.error?.message}
|
||||||
|
{...props}
|
||||||
|
{...field}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user