From a45a6fb87e0a5656bc178e6d29373296f914e496 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 05:51:16 +0800 Subject: [PATCH 1/9] fix: update button styles and variants for consistency across forms --- .vscode/settings.json | 4 +++- app/components/ui/button.tsx | 11 +++++++---- app/layouts/news/form-forgot-password.tsx | 2 +- app/layouts/news/form-login.tsx | 4 +--- app/layouts/news/form-register.tsx | 3 +-- app/layouts/news/form-subscription.tsx | 2 +- app/layouts/news/header-menu-mobile.tsx | 4 ++-- app/layouts/news/header-menu.tsx | 9 ++++++--- 8 files changed, 22 insertions(+), 17 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 990a0ee..d57e2f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,6 +25,8 @@ "labelClassName", "buttonClassName", "leftNodeClassName", - "rightNodeClassName" + "rightNodeClassName", + "buttonVariants", + "cva" ] } diff --git a/app/components/ui/button.tsx b/app/components/ui/button.tsx index f2f9eba..5356358 100644 --- a/app/components/ui/button.tsx +++ b/app/components/ui/button.tsx @@ -8,11 +8,14 @@ const buttonVariants = cva( { variants: { variant: { - newsPrimary: 'bg-[#2E2F7C] text-white text-lg', - newsPrimaryOutline: 'border-[3px] border-white text-white text-lg', - newsSecondary: 'border-[3px] border-[#2E2F7C] text-[#2E2F7C] text-lg', + newsPrimary: + 'bg-[#2E2F7C] text-white text-lg hover:bg-[#4C5CA0] hover:shadow transition active:bg-[#6970B4]', + newsPrimaryOutline: + 'border-[3px] bg-[#2E2F7C] border-white text-white text-lg hover:bg-[#4C5CA0] hover:shadow-lg active:shadow-2xl transition active:bg-[#6970B4]', + newsSecondary: + 'border-[3px] bg-white hover:shadow-lg active:shadow-2xl border-[#2E2F7C] text-[#2E2F7C] hover:text-[#4C5CA0] active:text-[#6970B4] text-lg hover:border-[#4C5CA0] transition active:border-[#6970B4]', icon: '', - link: '', + link: 'font-semibold text-[#2E2F7C] hover:text-[#4C5CA0] active:text-[#6970B4] transition', }, size: { default: 'h-[50px] w-[150px]', diff --git a/app/layouts/news/form-forgot-password.tsx b/app/layouts/news/form-forgot-password.tsx index a465631..20bfd97 100644 --- a/app/layouts/news/form-forgot-password.tsx +++ b/app/layouts/news/form-forgot-password.tsx @@ -22,7 +22,7 @@ export const FormForgotPassword = () => { {/* Tombol Masuk */} - diff --git a/app/layouts/news/form-login.tsx b/app/layouts/news/form-login.tsx index fc7d128..bd31a6b 100644 --- a/app/layouts/news/form-login.tsx +++ b/app/layouts/news/form-login.tsx @@ -87,7 +87,6 @@ export const FormLogin = () => { setIsLoginOpen(false) setIsForgetOpen(true) }} - className="font-semibold text-[#2E2F7C]" variant="link" size="fit" > @@ -98,7 +97,7 @@ export const FormLogin = () => { @@ -113,7 +112,6 @@ export const FormLogin = () => { setIsLoginOpen(false) setIsRegisterOpen(true) }} - className="font-semibold text-[#2E2F7C]" variant="link" size="fit" > diff --git a/app/layouts/news/form-register.tsx b/app/layouts/news/form-register.tsx index cc64940..15470b6 100644 --- a/app/layouts/news/form-register.tsx +++ b/app/layouts/news/form-register.tsx @@ -122,7 +122,7 @@ export const FormRegister = () => { @@ -137,7 +137,6 @@ export const FormRegister = () => { setIsLoginOpen(true) setIsRegisterOpen(false) }} - className="font-semibold text-[#2E2F7C]" variant="link" size="fit" > diff --git a/app/layouts/news/form-subscription.tsx b/app/layouts/news/form-subscription.tsx index 6491dff..7ea083f 100644 --- a/app/layouts/news/form-subscription.tsx +++ b/app/layouts/news/form-subscription.tsx @@ -79,7 +79,7 @@ export default function FormSubscription() { diff --git a/app/layouts/news/header-menu-mobile.tsx b/app/layouts/news/header-menu-mobile.tsx index 78829a7..edbde65 100644 --- a/app/layouts/news/header-menu-mobile.tsx +++ b/app/layouts/news/header-menu-mobile.tsx @@ -71,7 +71,7 @@ export default function HeaderMenuMobile(properties: THeaderMenuMobile) { > ))} From 8cddc8203173038db968e9887c922f145d5dd828 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 06:00:49 +0800 Subject: [PATCH 2/9] fix: add loading state to buttons in forms and update button styles --- app/components/ui/button.tsx | 25 ++++++++++++++++--------- app/layouts/news/form-login.tsx | 6 ++---- app/layouts/news/form-register.tsx | 6 ++---- app/layouts/news/form-subscription.tsx | 6 ++---- app/layouts/news/header-top.tsx | 4 +++- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/app/components/ui/button.tsx b/app/components/ui/button.tsx index 5356358..798fa4f 100644 --- a/app/components/ui/button.tsx +++ b/app/components/ui/button.tsx @@ -1,4 +1,5 @@ import { Button as HeadlessButton } from '@headlessui/react' +import { ArrowPathIcon } from '@heroicons/react/20/solid' import { cva, type VariantProps } from 'class-variance-authority' import type { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react' import { twMerge } from 'tailwind-merge' @@ -38,6 +39,7 @@ type ButtonBaseProperties = { variant?: VariantProps['variant'] size?: VariantProps['size'] className?: string + isLoading?: boolean } type PolymorphicReference = @@ -48,22 +50,27 @@ type ButtonProperties = ButtonBaseProperties & { ref?: PolymorphicReference } & Omit, keyof ButtonBaseProperties> -export const Button = ({ - as, - children, - variant, - size, - className, - ...properties -}: ButtonProperties) => { +export const Button = ( + properties: ButtonProperties, +) => { + const { + as, + children, + variant, + size, + className, + isLoading = false, + ...restProperties + } = properties const Component = as || HeadlessButton const classes = twMerge(buttonVariants({ variant, size, className })) return ( + {isLoading && } {children} ) diff --git a/app/layouts/news/form-login.tsx b/app/layouts/news/form-login.tsx index bd31a6b..131d249 100644 --- a/app/layouts/news/form-login.tsx +++ b/app/layouts/news/form-login.tsx @@ -24,7 +24,6 @@ export const FormLogin = () => { } = useNewsContext() const fetcher = useFetcher() const [error, setError] = useState() - const [disabled, setDisabled] = useState(false) const formMethods = useRemixForm({ mode: 'onSubmit', @@ -37,11 +36,9 @@ export const FormLogin = () => { useEffect(() => { if (!fetcher.data?.success) { setError(fetcher.data?.message) - setDisabled(false) return } - setDisabled(true) setError(undefined) setIsLoginOpen(false) @@ -95,7 +92,8 @@ export const FormLogin = () => { From 66bc731b075edd2e2b75364be1a5bddb09e61569 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 06:08:20 +0800 Subject: [PATCH 3/9] fix: update button components to include loading state and improve styling in navbar and login page --- app/layouts/admin/navbar.tsx | 7 +++++-- app/pages/staff-login/index.tsx | 15 ++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/layouts/admin/navbar.tsx b/app/layouts/admin/navbar.tsx index 740bcb4..6944b92 100644 --- a/app/layouts/admin/navbar.tsx +++ b/app/layouts/admin/navbar.tsx @@ -1,8 +1,9 @@ -import { Button, Popover, PopoverButton, PopoverPanel } from '@headlessui/react' +import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react' import { Link, useFetcher, useRouteLoaderData } from 'react-router' import { ChevronIcon } from '~/components/icons/chevron' import { ProfileIcon } from '~/components/icons/profile' +import { Button } from '~/components/ui/button' import { APP } from '~/configs/meta' import type { loader } from '~/routes/_admin.lg-admin' @@ -52,8 +53,10 @@ export const Navbar = () => { className="grid" > diff --git a/app/pages/staff-login/index.tsx b/app/pages/staff-login/index.tsx index 0bf0ba9..9a02ed8 100644 --- a/app/pages/staff-login/index.tsx +++ b/app/pages/staff-login/index.tsx @@ -23,14 +23,12 @@ export const AdminLoginPage = () => { resolver: zodResolver(loginSchema), }) const [error, setError] = useState() - const [disabled, setDisabled] = useState(false) const { handleSubmit } = formMethods useEffect(() => { if (!fetcher.data?.success) { setError(fetcher.data?.message) - setDisabled(false) return } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -81,18 +79,21 @@ export const AdminLoginPage = () => { {/* Lupa Kata Sandi */}
Lupa Kata Sandi? - Reset Kata Sandi - +
From 6ec8e5f2a23ef13e36827c7d92a1a14cf8aae012 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 06:13:03 +0800 Subject: [PATCH 4/9] fix: replace disabled state with loading state for buttons in upload and category forms --- app/layouts/admin/form-upload.tsx | 11 +++++------ app/pages/form-category/index.tsx | 6 ++---- app/pages/form-contents/index.tsx | 6 ++---- app/pages/form-subscriptions-plan/index.tsx | 6 ++---- app/pages/form-tag/index.tsx | 6 ++---- 5 files changed, 13 insertions(+), 22 deletions(-) diff --git a/app/layouts/admin/form-upload.tsx b/app/layouts/admin/form-upload.tsx index 425e6c7..0d24d42 100644 --- a/app/layouts/admin/form-upload.tsx +++ b/app/layouts/admin/form-upload.tsx @@ -1,10 +1,11 @@ -import { Button, Input } from '@headlessui/react' +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({ @@ -17,7 +18,6 @@ export type TUploadSchema = z.infer export const FormUpload = () => { const { isUploadOpen, setUploadedFile } = useAdminContext() const fetcher = useFetcher() - const [disabled, setDisabled] = useState(false) const [error, setError] = useState() const maxFileSize = 10 * 1024 // 10MB @@ -32,13 +32,11 @@ export const FormUpload = () => { useEffect(() => { if (!fetcher.data?.success) { setError(fetcher.data?.message) - setDisabled(false) return } setUploadedFile(fetcher.data.uploadData.data.file_url) - setDisabled(true) setError(undefined) // eslint-disable-next-line react-hooks/exhaustive-deps }, [fetcher]) @@ -110,9 +108,10 @@ export const FormUpload = () => { {...register('category')} /> diff --git a/app/pages/form-category/index.tsx b/app/pages/form-category/index.tsx index 1dce834..b5a60e7 100644 --- a/app/pages/form-category/index.tsx +++ b/app/pages/form-category/index.tsx @@ -39,7 +39,6 @@ export const FormCategoryPage = (properties: TProperties) => { }, }) const [error, setError] = useState() - const [disabled, setDisabled] = useState(false) const { handleSubmit, watch, setValue } = formMethods const watchName = watch('name') @@ -47,11 +46,9 @@ export const FormCategoryPage = (properties: TProperties) => { useEffect(() => { if (!fetcher.data?.success) { setError(fetcher.data?.message) - setDisabled(false) return } navigate('/lg-admin/categories') - setDisabled(true) setError(undefined) // eslint-disable-next-line react-hooks/exhaustive-deps }, [fetcher]) @@ -96,7 +93,8 @@ export const FormCategoryPage = (properties: TProperties) => { containerClassName="flex-1" /> + ) } From dfd1a46694c91c79de207fd743e9c3855b7eda11 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 06:30:47 +0800 Subject: [PATCH 6/9] fix: update sidebar button styles for improved active state indication --- app/layouts/admin/sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/layouts/admin/sidebar.tsx b/app/layouts/admin/sidebar.tsx index 4d7c0e2..f59cef4 100644 --- a/app/layouts/admin/sidebar.tsx +++ b/app/layouts/admin/sidebar.tsx @@ -22,7 +22,7 @@ export const Sidebar = () => { key={`${group}-${title}`} className={twMerge( path === url ? 'bg-[#707FDD]/10 font-bold' : '', - 'group/menu flex h-[42px] w-[200px] items-center gap-x-3 rounded-md px-5 transition-all hover:bg-[#707FDD]/10', + 'group/menu flex h-[42px] w-[200px] items-center gap-x-3 rounded-md px-5 transition hover:bg-[#707FDD]/10 active:bg-[#707FDD]/20', )} > Date: Tue, 11 Mar 2025 10:15:56 +0800 Subject: [PATCH 7/9] fix: update ID display to show author's ID instead of content ID --- app/pages/dashboard-contents/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/pages/dashboard-contents/index.tsx b/app/pages/dashboard-contents/index.tsx index 487ac0c..3a01704 100644 --- a/app/pages/dashboard-contents/index.tsx +++ b/app/pages/dashboard-contents/index.tsx @@ -60,7 +60,9 @@ export const ContentsPage = () => { 2: (_value: unknown, _type: unknown, data: TNewsResponse) => (
{data.author.name}
-
ID: {data.id.slice(0, 8)}
+
+ ID: {data.author.id.slice(0, 8)} +
), 3: (value: string) => {value}, From 07cced218e436eaa40624d02c5bcc3a0e33c91fe Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 10:28:48 +0800 Subject: [PATCH 8/9] fix: update icon sizes in text editor menu bar for consistency --- app/components/text-editor/editor-menubar.tsx | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/app/components/text-editor/editor-menubar.tsx b/app/components/text-editor/editor-menubar.tsx index 09395f2..34ba522 100644 --- a/app/components/text-editor/editor-menubar.tsx +++ b/app/components/text-editor/editor-menubar.tsx @@ -127,7 +127,7 @@ export const EditorMenuBar = (properties: TProperties) => { isActive={editor.isActive('bold')} title="Bold" > - + editor.chain().focus().toggleItalic().run()} @@ -137,7 +137,7 @@ export const EditorMenuBar = (properties: TProperties) => { isActive={editor.isActive('italic')} title="Italic" > - + editor.chain().focus().toggleStrike().run()} @@ -147,7 +147,7 @@ export const EditorMenuBar = (properties: TProperties) => { isActive={editor.isActive('strike')} title="Strike" > - +
{ isActive={true} disabled={disabled} > - + {isOpenColor && (
{ isActive={editor.isActive({ textAlign: 'left' })} title="Align Left" > - + editor.chain().focus().setTextAlign('center').run()} @@ -202,7 +202,7 @@ export const EditorMenuBar = (properties: TProperties) => { isActive={editor.isActive({ textAlign: 'center' })} title="Align Center" > - + editor.chain().focus().setTextAlign('right').run()} @@ -213,7 +213,7 @@ export const EditorMenuBar = (properties: TProperties) => { isActive={editor.isActive({ textAlign: 'right' })} title="Align Right" > - + editor.chain().focus().setTextAlign('justify').run()} @@ -224,7 +224,7 @@ export const EditorMenuBar = (properties: TProperties) => { isActive={editor.isActive({ textAlign: 'justify' })} title="Align Justify" > - +
@@ -236,7 +236,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Heading 1" disabled={disabled} > - + @@ -246,7 +246,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Heading 2" disabled={disabled} > - + @@ -256,7 +256,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Heading 3" disabled={disabled} > - + {/* editor.chain().focus().setParagraph().run()} @@ -272,7 +272,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Bullet List" disabled={disabled} > - + editor.chain().focus().toggleOrderedList().run()} @@ -280,7 +280,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Ordered List" disabled={disabled} > - + editor.chain().focus().toggleCodeBlock().run()} @@ -288,7 +288,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Code Block" disabled={disabled} > - +
{/*
@@ -334,7 +334,7 @@ export const EditorMenuBar = (properties: TProperties) => { title="Insert Image" disabled={disabled} > - + {isOpenImage && (
{ isActive={editor.isActive('link')} title="Set Link" > - + editor.chain().focus().unsetLink().run()} disabled={disabled || !editor.isActive('link')} title="Unset Link" > - +
@@ -396,14 +396,14 @@ export const EditorMenuBar = (properties: TProperties) => { disabled={disabled || !editor.can().chain().focus().undo().run()} title="Undo" > - + editor.chain().focus().redo().run()} disabled={disabled || !editor.can().chain().focus().redo().run()} title="Redo" > - +
@@ -413,7 +413,7 @@ export const EditorMenuBar = (properties: TProperties) => { onClick={() => setIsPlainHTML(true)} title="Switch to Plain Text" > - +
From 6f0a21dde6aeb9607b4329eb75970d82e1f6a729 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Tue, 11 Mar 2025 10:42:33 +0800 Subject: [PATCH 9/9] refactor: replace FormUpload with DialogUpload component for file uploads --- app/apis/admin/upload-file.ts | 2 +- app/layouts/admin/dashboard.tsx | 28 +----- app/layouts/admin/dialog-upload.tsx | 143 ++++++++++++++++++++++++++++ app/layouts/admin/form-upload.tsx | 121 ----------------------- app/routes/actions.admin.upload.tsx | 2 +- 5 files changed, 147 insertions(+), 149 deletions(-) create mode 100644 app/layouts/admin/dialog-upload.tsx delete mode 100644 app/layouts/admin/form-upload.tsx 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}
- { - setIsUploadOpen(undefined) - }} - className="relative z-50" - transition - > - -
- - - -
-
+ ) } 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 ( + { + if (fetcher.state === 'idle') { + setIsUploadOpen(undefined) + } + }} + className="relative z-50" + transition + > + +
+ + + + {error && ( +
{error}
+ )} + + + +
+
+
+
+
+ ) +} 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'