feat: update Dashboard page

- Perubahan tampilan dan modal pada halaman Dashboard
- Tambah schema dan type untuk Gacha Item
- Gunakan form dan Toast
This commit is contained in:
Hafid Nur
2025-04-05 09:36:49 +07:00
parent e805e5fd41
commit 0e3dc101d5
8 changed files with 327 additions and 198 deletions
+26
View File
@@ -1,5 +1,31 @@
import { z } from 'zod';
export const gachaItemSchema = 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'),
foto: z
.instanceof(File)
.optional()
.refine(
(file) => !file || file.size <= 5000000, // 5MB in bytes
'Ukuran file maksimal 5MB'
)
.refine(
(file) => !file || ['image/jpeg', 'image/png', 'image/webp'].includes(file.type),
'Format file harus JPG, PNG, atau WEBP'
)
});
export const gachaRollItemSchema = z.object({
itemName: z
.string({
+6
View File
@@ -1,3 +1,9 @@
export type TGachaItem = {
itemName: string;
quantity: number;
foto?: File;
};
export type TGachaRollItem = {
itemName: string;
quantity: number;
@@ -17,16 +17,27 @@ export const ControlledInputField = <T extends FieldValues>(
const { field, fieldState } = useController<T>(props);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value =
props.type === 'number' ? Number(e.target.value) : e.target.value;
let value;
if (props.type === 'number') {
value = Number(e.target.value);
} else if (props.type === 'file') {
value = e.target.files?.[0];
} else {
value = e.target.value;
}
field.onChange(value);
};
const inputProps =
props.type === 'file'
? { ...props, ...field, value: undefined }
: { ...props, ...field };
return (
<InputField
error={fieldState.error?.message}
{...props}
{...field}
{...inputProps}
onChange={handleChange}
/>
);