diff --git a/app/apis/admin/upload-file.ts b/app/apis/admin/upload-file.ts
index e94f376..f96471a 100644
--- a/app/apis/admin/upload-file.ts
+++ b/app/apis/admin/upload-file.ts
@@ -1,6 +1,6 @@
import { z } from 'zod'
-import type { TUploadSchema } from '~/layouts/admin/form-upload'
+import type { TUploadSchema } from '~/layouts/admin/dialog-upload'
import { HttpServer, type THttpServer } from '~/libs/http-server'
const uploadResponseSchema = z.object({
diff --git a/app/layouts/admin/dashboard.tsx b/app/layouts/admin/dashboard.tsx
index 642918b..8c9c3a4 100644
--- a/app/layouts/admin/dashboard.tsx
+++ b/app/layouts/admin/dashboard.tsx
@@ -1,15 +1,11 @@
-import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react'
import type { PropsWithChildren } from 'react'
-import { useAdminContext } from '~/contexts/admin'
-
-import { FormUpload } from './form-upload'
+import { DialogUpload } from './dialog-upload'
import { Navbar } from './navbar'
import { Sidebar } from './sidebar'
export const AdminDashboardLayout = (properties: PropsWithChildren) => {
const { children } = properties
- const { isUploadOpen, setIsUploadOpen } = useAdminContext()
return (
@@ -18,27 +14,7 @@ export const AdminDashboardLayout = (properties: PropsWithChildren) => {
{children}
-
+
)
}
diff --git a/app/layouts/admin/dialog-upload.tsx b/app/layouts/admin/dialog-upload.tsx
new file mode 100644
index 0000000..2ff72c0
--- /dev/null
+++ b/app/layouts/admin/dialog-upload.tsx
@@ -0,0 +1,143 @@
+import { Dialog, DialogBackdrop, DialogPanel, Input } from '@headlessui/react'
+import { zodResolver } from '@hookform/resolvers/zod'
+import { useEffect, useState, type ChangeEvent } from 'react'
+import { useFetcher } from 'react-router'
+import { RemixFormProvider, useRemixForm } from 'remix-hook-form'
+import { z } from 'zod'
+
+import { Button } from '~/components/ui/button'
+import { uploadCategorySchema, useAdminContext } from '~/contexts/admin'
+
+export const uploadSchema = z.object({
+ file: z.instanceof(File),
+ category: uploadCategorySchema,
+})
+
+export type TUploadSchema = z.infer
+
+export const DialogUpload = () => {
+ const { isUploadOpen, setUploadedFile, setIsUploadOpen } = useAdminContext()
+ const fetcher = useFetcher()
+ const [error, setError] = useState()
+ const maxFileSize = 10 * 1024 // 10MB
+
+ const formMethods = useRemixForm({
+ mode: 'onSubmit',
+ fetcher,
+ resolver: zodResolver(uploadSchema),
+ })
+
+ const { handleSubmit, register, setValue } = formMethods
+
+ useEffect(() => {
+ if (!fetcher.data?.success) {
+ setError(fetcher.data?.message)
+ return
+ }
+
+ setUploadedFile(fetcher.data.uploadData.data.file_url)
+
+ setError(undefined)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [fetcher])
+
+ const handleChange = async function (event: ChangeEvent) {
+ event.preventDefault()
+ if (event.target.files && event.target.files[0]) {
+ const files: File[] = [...event.target.files]
+
+ onChange(files, event)
+ }
+ }
+
+ const onChange = async function (
+ files: File[],
+ event: ChangeEvent,
+ ) {
+ const file = files[0]
+ const img = new Image()
+
+ if (!file.type.startsWith('image/')) {
+ setError('Please upload an image file.')
+ return
+ }
+
+ if (file.size > maxFileSize * 1024) {
+ setError(`File size is too big!`)
+ return
+ }
+
+ img.addEventListener('load', () => {
+ handleFiles(event)
+ })
+
+ img.src = URL.createObjectURL(file)
+ }
+
+ const handleFiles = (event: ChangeEvent) => {
+ const files = event.target.files
+ if (files && files.length > 0) {
+ const file = files[0]
+ setValue('file', file)
+ }
+ }
+
+ return (
+
+ )
+}
diff --git a/app/layouts/admin/form-upload.tsx b/app/layouts/admin/form-upload.tsx
deleted file mode 100644
index 0d24d42..0000000
--- a/app/layouts/admin/form-upload.tsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import { Input } from '@headlessui/react'
-import { zodResolver } from '@hookform/resolvers/zod'
-import { useEffect, useState, type ChangeEvent } from 'react'
-import { useFetcher } from 'react-router'
-import { RemixFormProvider, useRemixForm } from 'remix-hook-form'
-import { z } from 'zod'
-
-import { Button } from '~/components/ui/button'
-import { uploadCategorySchema, useAdminContext } from '~/contexts/admin'
-
-export const uploadSchema = z.object({
- file: z.instanceof(File),
- category: uploadCategorySchema,
-})
-
-export type TUploadSchema = z.infer
-
-export const FormUpload = () => {
- const { isUploadOpen, setUploadedFile } = useAdminContext()
- const fetcher = useFetcher()
- const [error, setError] = useState()
- const maxFileSize = 10 * 1024 // 10MB
-
- const formMethods = useRemixForm({
- mode: 'onSubmit',
- fetcher,
- resolver: zodResolver(uploadSchema),
- })
-
- const { handleSubmit, register, setValue } = formMethods
-
- useEffect(() => {
- if (!fetcher.data?.success) {
- setError(fetcher.data?.message)
- return
- }
-
- setUploadedFile(fetcher.data.uploadData.data.file_url)
-
- setError(undefined)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [fetcher])
-
- const handleChange = async function (event: ChangeEvent) {
- event.preventDefault()
- if (event.target.files && event.target.files[0]) {
- const files: File[] = [...event.target.files]
-
- onChange(files, event)
- }
- }
-
- const onChange = async function (
- files: File[],
- event: ChangeEvent,
- ) {
- const file = files[0]
- const img = new Image()
-
- if (!file.type.startsWith('image/')) {
- setError('Please upload an image file.')
- return
- }
-
- if (file.size > maxFileSize * 1024) {
- setError(`File size is too big!`)
- return
- }
-
- img.addEventListener('load', () => {
- handleFiles(event)
- })
-
- img.src = URL.createObjectURL(file)
- }
-
- const handleFiles = (event: ChangeEvent) => {
- const files = event.target.files
- if (files && files.length > 0) {
- const file = files[0]
- setValue('file', file)
- }
- }
-
- return (
-
-
- {error && (
- {error}
- )}
-
-
-
-
-
- )
-}
diff --git a/app/routes/actions.admin.upload.tsx b/app/routes/actions.admin.upload.tsx
index 6faa5d9..e31310f 100644
--- a/app/routes/actions.admin.upload.tsx
+++ b/app/routes/actions.admin.upload.tsx
@@ -4,7 +4,7 @@ import { getValidatedFormData } from 'remix-hook-form'
import { XiorError } from 'xior'
import { uploadFileRequest } from '~/apis/admin/upload-file'
-import { uploadSchema, type TUploadSchema } from '~/layouts/admin/form-upload'
+import { uploadSchema, type TUploadSchema } from '~/layouts/admin/dialog-upload'
import { handleCookie } from '~/libs/cookies'
import type { Route } from './+types/actions.register'