diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-02-23 08:20:44 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-02-23 08:20:44 +0700 |
| commit | a553af3576985e6d14cf59177a6cca9fa108c0bb (patch) | |
| tree | 763f73dafe6cc69c913eacafdc26e972849092b1 | |
| parent | e5aea4632cb84c9d5e04024b67d149178f794ba6 (diff) | |
| parent | 404afb8b94b5d8d88f6dfd619cde0b5a122fbc42 (diff) | |
prettier
47 files changed, 913 insertions, 183 deletions
diff --git a/.prettierrc b/.prettierrc index 13d05134..b377f1b3 100644 --- a/.prettierrc +++ b/.prettierrc @@ -13,5 +13,6 @@ "tabWidth": 4 } } - ] + ], + "singleAttributePerLine": true } diff --git a/package.json b/package.json index d02fa878..20398943 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "build": "next build", "start": "next start", "lint": "next lint", - "format": "prettier --write \"./**/*.{js,jsx,ts,tsx}\" --config ./.prettierrc" + "format": "prettier --write \"./src/**/*.{js,jsx,ts,tsx}\" --config ./.prettierrc" }, "dependencies": { "@heroicons/react": "^2.0.13", diff --git a/src/core/components/elements/Appbar/Appbar.jsx b/src/core/components/elements/Appbar/Appbar.jsx index 4300287f..098d0a33 100644 --- a/src/core/components/elements/Appbar/Appbar.jsx +++ b/src/core/components/elements/Appbar/Appbar.jsx @@ -8,19 +8,32 @@ const AppBar = ({ title }) => { return ( <nav className='sticky top-0 z-50 bg-white border-b border-gray_r-6 flex justify-between'> <div className='flex items-center'> - <button type='button' className='p-4' onClick={() => router.back()}> + <button + type='button' + className='p-4' + onClick={() => router.back()} + > <ChevronLeftIcon className='w-6 stroke-2' /> </button> <div className='font-medium text-h-sm line-clamp-1'>{title}</div> </div> <div className='flex items-center px-2'> - <Link href='/shop/cart' className='py-4 px-2'> + <Link + href='/shop/cart' + className='py-4 px-2' + > <ShoppingCartIcon className='w-6 text-gray_r-12' /> </Link> - <Link href='/' className='py-4 px-2'> + <Link + href='/' + className='py-4 px-2' + > <HomeIcon className='w-6 text-gray_r-12' /> </Link> - <Link href='/my/menu' className='py-4 px-2'> + <Link + href='/my/menu' + className='py-4 px-2' + > <Bars3Icon className='w-6 text-gray_r-12' /> </Link> </div> diff --git a/src/core/components/elements/Badge/Badge.jsx b/src/core/components/elements/Badge/Badge.jsx index 5e22db1a..e50cdc78 100644 --- a/src/core/components/elements/Badge/Badge.jsx +++ b/src/core/components/elements/Badge/Badge.jsx @@ -1,6 +1,9 @@ const Badge = ({ children, type, ...props }) => { return ( - <div {...props} className={`${badgeStyle(type)} ${props?.className}`}> + <div + {...props} + className={`${badgeStyle(type)} ${props?.className}`} + > {children} </div> ) diff --git a/src/core/components/elements/Navbar/Navbar.jsx b/src/core/components/elements/Navbar/Navbar.jsx index e2caebfe..8cecee5b 100644 --- a/src/core/components/elements/Navbar/Navbar.jsx +++ b/src/core/components/elements/Navbar/Navbar.jsx @@ -14,7 +14,12 @@ const Navbar = () => { <nav className='px-4 py-2 pb-3 sticky top-0 z-50 bg-white shadow'> <div className='flex justify-between items-center mb-2'> <Link href='/'> - <Image src={IndoteknikLogo} alt='Indoteknik Logo' width={120} height={40} /> + <Image + src={IndoteknikLogo} + alt='Indoteknik Logo' + width={120} + height={40} + /> </Link> <div className='flex gap-x-3'> <Link href='/my/wishlist'> @@ -23,7 +28,10 @@ const Navbar = () => { <Link href='/shop/cart'> <ShoppingCartIcon className='w-6 text-gray_r-12' /> </Link> - <button type='button' onClick={open}> + <button + type='button' + onClick={open} + > <Bars3Icon className='w-6 text-gray_r-12' /> </button> </div> diff --git a/src/core/components/elements/Navbar/Search.jsx b/src/core/components/elements/Navbar/Search.jsx index 6f0e4dd9..ff2c7adb 100644 --- a/src/core/components/elements/Navbar/Search.jsx +++ b/src/core/components/elements/Navbar/Search.jsx @@ -50,7 +50,10 @@ const Search = () => { } return ( - <form onSubmit={handleSubmit} className='flex relative'> + <form + onSubmit={handleSubmit} + className='flex relative' + > <input type='text' ref={queryRef} @@ -61,7 +64,10 @@ const Search = () => { onBlur={onInputBlur} onFocus={loadSuggestion} /> - <button type='submit' className='rounded-r border border-l-0 border-gray_r-6 px-2'> + <button + type='submit' + className='rounded-r border border-l-0 border-gray_r-6 px-2' + > <MagnifyingGlassIcon className='w-6' /> </button> diff --git a/src/core/components/elements/Pagination/Pagination.js b/src/core/components/elements/Pagination/Pagination.js index c009171f..18964fc4 100644 --- a/src/core/components/elements/Pagination/Pagination.js +++ b/src/core/components/elements/Pagination/Pagination.js @@ -26,7 +26,10 @@ const Pagination = ({ pageCount, currentPage, url, className }) => { </Link> ) let DotsComponent = ( - <div key={i} className='pagination-dots'> + <div + key={i} + className='pagination-dots' + > ... </div> ) diff --git a/src/core/components/elements/Popup/BottomPopup.jsx b/src/core/components/elements/Popup/BottomPopup.jsx index af1149ca..24366802 100644 --- a/src/core/components/elements/Popup/BottomPopup.jsx +++ b/src/core/components/elements/Popup/BottomPopup.jsx @@ -35,7 +35,10 @@ const BottomPopup = ({ children, active = false, title, close }) => { > <div className='flex justify-between py-4'> <div className='font-semibold text-h-sm'>{title}</div> - <button type='button' onClick={close}> + <button + type='button' + onClick={close} + > <XMarkIcon className='w-5 stroke-2' /> </button> </div> diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx index 08f1fed5..cdeb3e05 100644 --- a/src/core/components/elements/Sidebar/Sidebar.jsx +++ b/src/core/components/elements/Sidebar/Sidebar.jsx @@ -8,7 +8,10 @@ const Sidebar = ({ active, close }) => { const auth = useAuth() const SidebarLink = ({ children, ...props }) => ( - <Link {...props} onClick={close}> + <Link + {...props} + onClick={close} + > {children} </Link> ) @@ -74,13 +77,22 @@ const Sidebar = ({ active, close }) => { </> )} </div> - <SidebarLink className={itemClassName} href='/'> + <SidebarLink + className={itemClassName} + href='/' + > Semua Brand </SidebarLink> - <SidebarLink className={itemClassName} href='/'> + <SidebarLink + className={itemClassName} + href='/' + > Tentang Indoteknik </SidebarLink> - <SidebarLink className={itemClassName} href='/'> + <SidebarLink + className={itemClassName} + href='/' + > Pusat Bantuan </SidebarLink> <button className={`${itemClassName} w-full text-left`}>Kategori</button> diff --git a/src/core/components/elements/Skeleton/BrandSkeleton.jsx b/src/core/components/elements/Skeleton/BrandSkeleton.jsx index 9a7a51f9..9a34fb9b 100644 --- a/src/core/components/elements/Skeleton/BrandSkeleton.jsx +++ b/src/core/components/elements/Skeleton/BrandSkeleton.jsx @@ -1,5 +1,8 @@ const BrandSkeleton = () => ( - <div role='status' className='animate-pulse'> + <div + role='status' + className='animate-pulse' + > <div className='h-12 bg-gray-200 rounded'></div> <span className='sr-only'>Loading...</span> </div> diff --git a/src/core/components/elements/Skeleton/ImageSkeleton.jsx b/src/core/components/elements/Skeleton/ImageSkeleton.jsx index 2ca6b2a3..39d06331 100644 --- a/src/core/components/elements/Skeleton/ImageSkeleton.jsx +++ b/src/core/components/elements/Skeleton/ImageSkeleton.jsx @@ -1,6 +1,12 @@ const ImageSkeleton = () => ( - <div role='status' className='animate-pulse'> - <div className='flex items-center justify-center h-56 mb-4 bg-gray-300 rounded' aria-busy> + <div + role='status' + className='animate-pulse' + > + <div + className='flex items-center justify-center h-56 mb-4 bg-gray-300 rounded' + aria-busy + > <svg className='w-12 h-12 text-gray-200' xmlns='http://www.w3.org/2000/svg' diff --git a/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx b/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx index 84d1c0d1..ddc0d3bc 100644 --- a/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx +++ b/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx @@ -3,7 +3,10 @@ const ProductCardSkeleton = () => ( role='status' className='p-4 max-w-sm rounded border border-gray-300 shadow animate-pulse md:p-6' > - <div className='flex items-center justify-center h-36 mb-4 bg-gray-300 rounded' aria-busy> + <div + className='flex items-center justify-center h-36 mb-4 bg-gray-300 rounded' + aria-busy + > <svg className='w-12 h-12 text-gray-200' xmlns='http://www.w3.org/2000/svg' diff --git a/src/core/hooks/useSidebar.js b/src/core/hooks/useSidebar.js index c463fd81..4da61ac2 100644 --- a/src/core/hooks/useSidebar.js +++ b/src/core/hooks/useSidebar.js @@ -15,7 +15,12 @@ const useSidebar = () => { return { open: activate, - Sidebar: <SidebarComponent active={active} close={deactivate} /> + Sidebar: ( + <SidebarComponent + active={active} + close={deactivate} + /> + ) } } diff --git a/src/lib/address/components/CreateAddress.jsx b/src/lib/address/components/CreateAddress.jsx index 62bb0858..849b4c01 100644 --- a/src/lib/address/components/CreateAddress.jsx +++ b/src/lib/address/components/CreateAddress.jsx @@ -88,20 +88,34 @@ const CreateAddress = () => { } return ( - <form className='p-4 flex flex-col gap-y-4' onSubmit={handleSubmit(onSubmitHandler)}> + <form + className='p-4 flex flex-col gap-y-4' + onSubmit={handleSubmit(onSubmitHandler)} + > <div> <label className='form-label mb-2'>Label Alamat</label> <Controller name='type' control={control} - render={(props) => <HookFormSelect {...props} isSearchable={false} options={types} />} + render={(props) => ( + <HookFormSelect + {...props} + isSearchable={false} + options={types} + /> + )} /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.type?.message}</div> </div> <div> <label className='form-label mb-2'>Nama</label> - <input {...register('name')} placeholder='John Doe' type='text' className='form-input' /> + <input + {...register('name')} + placeholder='John Doe' + type='text' + className='form-input' + /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.name?.message}</div> </div> @@ -118,7 +132,12 @@ const CreateAddress = () => { <div> <label className='form-label mb-2'>Mobile</label> - <input {...register('mobile')} placeholder='08xxxxxxxx' type='tel' className='form-input' /> + <input + {...register('mobile')} + placeholder='08xxxxxxxx' + type='tel' + className='form-input' + /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.mobile?.message}</div> </div> @@ -135,7 +154,12 @@ const CreateAddress = () => { <div> <label className='form-label mb-2'>Kode Pos</label> - <input {...register('zip')} placeholder='10100' type='number' className='form-input' /> + <input + {...register('zip')} + placeholder='10100' + type='number' + className='form-input' + /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.zip?.message}</div> </div> @@ -144,7 +168,12 @@ const CreateAddress = () => { <Controller name='city' control={control} - render={(props) => <HookFormSelect {...props} options={cities} />} + render={(props) => ( + <HookFormSelect + {...props} + options={cities} + /> + )} /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.city?.message}</div> </div> @@ -155,7 +184,11 @@ const CreateAddress = () => { name='district' control={control} render={(props) => ( - <HookFormSelect {...props} options={districts} disabled={!watchCity} /> + <HookFormSelect + {...props} + options={districts} + disabled={!watchCity} + /> )} /> </div> @@ -166,12 +199,19 @@ const CreateAddress = () => { name='subDistrict' control={control} render={(props) => ( - <HookFormSelect {...props} options={subDistricts} disabled={!watchDistrict} /> + <HookFormSelect + {...props} + options={subDistricts} + disabled={!watchDistrict} + /> )} /> </div> - <button type='submit' className='btn-yellow mt-2 w-full'> + <button + type='submit' + className='btn-yellow mt-2 w-full' + > Simpan </button> </form> diff --git a/src/lib/address/components/EditAddress.jsx b/src/lib/address/components/EditAddress.jsx index 0cfa013a..a832edbc 100644 --- a/src/lib/address/components/EditAddress.jsx +++ b/src/lib/address/components/EditAddress.jsx @@ -102,20 +102,34 @@ const EditAddress = ({ id, defaultValues }) => { } return ( - <form className='p-4 flex flex-col gap-y-4' onSubmit={handleSubmit(onSubmitHandler)}> + <form + className='p-4 flex flex-col gap-y-4' + onSubmit={handleSubmit(onSubmitHandler)} + > <div> <label className='form-label mb-2'>Label Alamat</label> <Controller name='type' control={control} - render={(props) => <HookFormSelect {...props} isSearchable={false} options={types} />} + render={(props) => ( + <HookFormSelect + {...props} + isSearchable={false} + options={types} + /> + )} /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.type?.message}</div> </div> <div> <label className='form-label mb-2'>Nama</label> - <input {...register('name')} placeholder='John Doe' type='text' className='form-input' /> + <input + {...register('name')} + placeholder='John Doe' + type='text' + className='form-input' + /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.name?.message}</div> </div> @@ -132,7 +146,12 @@ const EditAddress = ({ id, defaultValues }) => { <div> <label className='form-label mb-2'>Mobile</label> - <input {...register('mobile')} placeholder='08xxxxxxxx' type='tel' className='form-input' /> + <input + {...register('mobile')} + placeholder='08xxxxxxxx' + type='tel' + className='form-input' + /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.mobile?.message}</div> </div> @@ -149,7 +168,12 @@ const EditAddress = ({ id, defaultValues }) => { <div> <label className='form-label mb-2'>Kode Pos</label> - <input {...register('zip')} placeholder='10100' type='number' className='form-input' /> + <input + {...register('zip')} + placeholder='10100' + type='number' + className='form-input' + /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.zip?.message}</div> </div> @@ -158,7 +182,12 @@ const EditAddress = ({ id, defaultValues }) => { <Controller name='city' control={control} - render={(props) => <HookFormSelect {...props} options={cities} />} + render={(props) => ( + <HookFormSelect + {...props} + options={cities} + /> + )} /> <div className='text-caption-2 text-red_r-11 mt-1'>{errors.city?.message}</div> </div> @@ -169,7 +198,11 @@ const EditAddress = ({ id, defaultValues }) => { name='district' control={control} render={(props) => ( - <HookFormSelect {...props} options={districts} disabled={!watchCity} /> + <HookFormSelect + {...props} + options={districts} + disabled={!watchCity} + /> )} /> </div> @@ -180,12 +213,19 @@ const EditAddress = ({ id, defaultValues }) => { name='subDistrict' control={control} render={(props) => ( - <HookFormSelect {...props} options={subDistricts} disabled={!watchDistrict} /> + <HookFormSelect + {...props} + options={subDistricts} + disabled={!watchDistrict} + /> )} /> </div> - <button type='submit' className='btn-yellow mt-2 w-full'> + <button + type='submit' + className='btn-yellow mt-2 w-full' + > Simpan </button> </form> diff --git a/src/lib/auth/api/editPersonalProfileApi.js b/src/lib/auth/api/editPersonalProfileApi.js new file mode 100644 index 00000000..39cd44c1 --- /dev/null +++ b/src/lib/auth/api/editPersonalProfileApi.js @@ -0,0 +1,10 @@ +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' + +const editPersonalProfileApi = async ({ data }) => { + const auth = getAuth() + const dataProfile = await odooApi('PUT', `/api/v1/user/${auth.id}`, data) + return dataProfile +} + +export default editPersonalProfileApi diff --git a/src/lib/auth/components/CompanyProfile.jsx b/src/lib/auth/components/CompanyProfile.jsx new file mode 100644 index 00000000..d66a0209 --- /dev/null +++ b/src/lib/auth/components/CompanyProfile.jsx @@ -0,0 +1,97 @@ +import useAuth from '@/core/hooks/useAuth' +import addressApi from '@/lib/address/api/addressApi' +import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline' +import { useEffect, useState } from 'react' +import { useForm } from 'react-hook-form' + +const PersonalProfile = () => { + const auth = useAuth() + const [isOpen, setIsOpen] = useState(false) + const toggle = () => setIsOpen(!isOpen) + const { register, setValue } = useForm({ + defaultValues: { + email: '', + name: '', + mobile: '', + password: '' + } + }) + + useEffect(() => { + const loadProfile = async () => { + const dataProfile = await addressApi({ id: auth.partnerId }) + setValue('email', dataProfile?.email) + setValue('name', dataProfile?.name) + setValue('mobile', dataProfile?.mobile) + } + if (auth) loadProfile() + }, [auth, setValue]) + + return ( + <> + <button + type='button' + onClick={toggle} + className='p-4 flex items-center text-left' + > + <div> + <div className='font-semibold mb-2'>Informasi Akun</div> + <div className='text-gray_r-11'> + Dibawah ini adalah data diri yang anda masukkan, periksa kembali data diri anda + </div> + </div> + <div className='p-2 bg-gray_r-3 rounded'> + {!isOpen && <ChevronDownIcon className='w-6' />} + {isOpen && <ChevronUpIcon className='w-6' />} + </div> + </button> + + {isOpen && ( + <form className='p-4 border-t border-gray_r-6 flex flex-col gap-y-4'> + <div> + <label>Email</label> + <input + {...register('email')} + type='text' + disabled + className='form-input mt-3' + /> + </div> + <div> + <label>Nama Lengkap</label> + <input + {...register('name')} + type='text' + className='form-input mt-3' + /> + </div> + <div> + <label>No. Handphone</label> + <input + {...register('mobile')} + type='text' + className='form-input mt-3' + /> + </div> + <div> + <label>Kata Sandi</label> + <input + {...register('password')} + type='password' + className='form-input mt-3' + placeholder='Isi jika ingin mengubah kata sandi' + /> + </div> + <button + type='submit' + className='btn-yellow w-full' + > + Simpan + </button> + </form> + )} + </> + ) +} + +export default PersonalProfile diff --git a/src/lib/auth/components/Login.jsx b/src/lib/auth/components/Login.jsx index 01b2a571..b4e94e0a 100644 --- a/src/lib/auth/components/Login.jsx +++ b/src/lib/auth/components/Login.jsx @@ -37,7 +37,10 @@ const Login = () => { children: ( <> Email belum diaktivasi, - <Link className='text-gray-900' href={`/activate?email=${email}`}> + <Link + className='text-gray-900' + href={`/activate?email=${email}`} + > aktivasi sekarang </Link> </> @@ -51,18 +54,29 @@ const Login = () => { return ( <div className='p-6 pt-10 flex flex-col items-center'> <Link href='/'> - <Image src={IndoteknikLogo} alt='Logo Indoteknik' width={150} height={50} /> + <Image + src={IndoteknikLogo} + alt='Logo Indoteknik' + width={150} + height={50} + /> </Link> <h1 className='text-2xl mt-4 font-semibold'>Mulai Belanja Sekarang</h1> <h2 className='text-gray_r-11 font-normal mt-1 mb-4'>Masuk ke akun kamu untuk belanja</h2> {alert && ( - <Alert className='text-center' type={alert.type}> + <Alert + className='text-center' + type={alert.type} + > {alert.children} </Alert> )} - <form className='w-full mt-6 flex flex-col gap-y-4' onSubmit={handleSubmit}> + <form + className='w-full mt-6 flex flex-col gap-y-4' + onSubmit={handleSubmit} + > <div> <label htmlFor='email'>Alamat Email</label> <input @@ -96,7 +110,10 @@ const Login = () => { <div className='text-gray_r-11 mt-4'> Belum punya akun Indoteknik?{' '} - <Link href='/register' className='inline'> + <Link + href='/register' + className='inline' + > Daftar </Link> </div> diff --git a/src/lib/auth/components/PersonalProfile.jsx b/src/lib/auth/components/PersonalProfile.jsx new file mode 100644 index 00000000..0b387f2e --- /dev/null +++ b/src/lib/auth/components/PersonalProfile.jsx @@ -0,0 +1,118 @@ +import useAuth from '@/core/hooks/useAuth' +import { setAuth } from '@/core/utils/auth' +import addressApi from '@/lib/address/api/addressApi' +import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline' +import { useEffect, useState } from 'react' +import { useForm } from 'react-hook-form' +import { toast } from 'react-hot-toast' +import editPersonalProfileApi from '../api/editPersonalProfileApi' + +const PersonalProfile = () => { + const auth = useAuth() + const [isOpen, setIsOpen] = useState(false) + const toggle = () => setIsOpen(!isOpen) + const { register, setValue, handleSubmit } = useForm({ + defaultValues: { + email: '', + name: '', + mobile: '', + password: '' + } + }) + + useEffect(() => { + const loadProfile = async () => { + const dataProfile = await addressApi({ id: auth.partnerId }) + setValue('email', dataProfile?.email) + setValue('name', dataProfile?.name) + setValue('mobile', dataProfile?.mobile) + } + if (auth) loadProfile() + }, [auth, setValue]) + + const onSubmitHandler = async (values) => { + let data = values + if (!values.password) delete data.password + const isUpdated = await editPersonalProfileApi({ data }) + console.log(isUpdated) + if (isUpdated?.user) { + setAuth(isUpdated.user) + setValue('password', '') + setIsOpen(false) + toast.success('Berhasil mengubah profil', { duration: 1500 }) + return + } + toast.error('Terjadi kesalahan internal') + } + + return ( + <> + <button + type='button' + onClick={toggle} + className='p-4 flex items-center text-left' + > + <div> + <div className='font-semibold mb-2'>Informasi Akun</div> + <div className='text-gray_r-11'> + Dibawah ini adalah data diri yang anda masukan, periksa kembali data diri anda + </div> + </div> + <div className='p-2 bg-gray_r-3 rounded'> + {!isOpen && <ChevronDownIcon className='w-6' />} + {isOpen && <ChevronUpIcon className='w-6' />} + </div> + </button> + + {isOpen && ( + <form + className='p-4 border-t border-gray_r-6 flex flex-col gap-y-4' + onSubmit={handleSubmit(onSubmitHandler)} + > + <div> + <label>Email</label> + <input + {...register('email')} + type='text' + disabled + className='form-input mt-3' + /> + </div> + <div> + <label>Nama Lengkap</label> + <input + {...register('name')} + type='text' + className='form-input mt-3' + /> + </div> + <div> + <label>No. Handphone</label> + <input + {...register('mobile')} + type='tel' + className='form-input mt-3' + /> + </div> + <div> + <label>Kata Sandi</label> + <input + {...register('password')} + type='password' + className='form-input mt-3' + placeholder='Isi jika ingin mengubah kata sandi' + /> + </div> + <button + type='submit' + className='btn-yellow w-full mt-2' + > + Simpan + </button> + </form> + )} + </> + ) +} + +export default PersonalProfile diff --git a/src/lib/auth/components/Register.jsx b/src/lib/auth/components/Register.jsx index df08541d..135972d3 100644 --- a/src/lib/auth/components/Register.jsx +++ b/src/lib/auth/components/Register.jsx @@ -26,7 +26,12 @@ const Register = () => { return ( <div className='p-6 pt-10 flex flex-col items-center'> <Link href='/'> - <Image src={IndoteknikLogo} alt='Logo Indoteknik' width={150} height={50} /> + <Image + src={IndoteknikLogo} + alt='Logo Indoteknik' + width={150} + height={50} + /> </Link> <h1 className='text-2xl mt-4 font-semibold'>Daftar Akun Indoteknik</h1> @@ -34,7 +39,10 @@ const Register = () => { Buat akun sekarang lebih mudah dan terverifikasi </h2> - <form className='w-full mt-6 flex flex-col gap-y-4' onSubmit={handleSubmit}> + <form + className='w-full mt-6 flex flex-col gap-y-4' + onSubmit={handleSubmit} + > <div> <label htmlFor='companyName'> Nama Perusahaan <span className='text-gray_r-11'>(opsional)</span> @@ -95,7 +103,10 @@ const Register = () => { <div className='text-gray_r-11 mt-4'> Sudah punya akun Indoteknik?{' '} - <Link href='/login' className='inline'> + <Link + href='/login' + className='inline' + > Masuk </Link> </div> diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx index 0dbdc075..e981c0d5 100644 --- a/src/lib/brand/components/BrandCard.jsx +++ b/src/lib/brand/components/BrandCard.jsx @@ -8,7 +8,11 @@ const BrandCard = ({ brand }) => { href={createSlug('/shop/brands/', brand.name, brand.id)} className='py-1 px-2 rounded border border-gray_r-6' > - <Image src={brand.logo} alt={brand.name} className='h-10 object-contain object-center' /> + <Image + src={brand.logo} + alt={brand.name} + className='h-10 object-contain object-center' + /> </Link> ) } diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx index 2d94ac0b..6a503c0a 100644 --- a/src/lib/cart/components/Cart.jsx +++ b/src/lib/cart/components/Cart.jsx @@ -103,7 +103,7 @@ const Cart = () => { const selectedProduct = () => { if (!products) return [] - return products.filter((product) => product.selected == true) + return products?.filter((product) => product.selected == true) } const deleteProduct = (productId) => { @@ -115,27 +115,35 @@ const Cart = () => { } return ( - <div className='pt-6'> + <div className='pt-4'> <div className='flex justify-between mb-4 px-4'> <h1 className='font-semibold'>Daftar Produk Belanja</h1> <Link href='/'>Cari Produk Lain</Link> </div> - <div className='flex flex-col gap-y-4 px-4'> + <div className='flex flex-col gap-y-4 h-screen'> {cart.isLoading && ( <div className='flex justify-center my-4'> <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> )} - {!cart.isLoading && !products && ( - <Alert className='text-center my-2' type='info'> - Keranjang belanja anda masih kosong - </Alert> + {!cart.isLoading && (!products || products?.length == 0) && ( + <div className='px-4'> + <Alert + className='text-center my-2' + type='info' + > + Keranjang belanja anda masih kosong + </Alert> + </div> )} {products?.map((product) => ( - <div key={product?.id} className='flex'> + <div + key={product?.id} + className='flex mx-4' + > <button type='button' className='flex items-center mr-2' @@ -154,7 +162,7 @@ const Cart = () => { className='object-contain object-center border border-gray_r-6 h-40 w-full rounded-md' /> </Link> - <div className='flex-1 px-2 text-caption-1'> + <div className='flex-1 px-2 text-caption-2'> <Link href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} className='line-clamp-2 leading-6 !text-gray_r-12 font-normal' @@ -214,37 +222,37 @@ const Cart = () => { </div> </div> ))} - </div> - <div className='sticky bottom-0 left-0 w-full p-4 mt-6 border-t border-gray_r-6 bg-white'> - <div className='flex justify-between mb-4'> - <div className='text-gray_r-11'> - Total: - <span className='text-red_r-11 font-semibold'> - - {selectedProduct().length > 0 - ? currencyFormat(totalPriceBeforeTax - totalDiscountAmount + totalTaxAmount) - : '-'} - </span> + <div className='sticky bottom-0 left-0 w-full p-4 mt-auto border-t border-gray_r-6 bg-white'> + <div className='flex justify-between mb-4'> + <div className='text-gray_r-11'> + Total: + <span className='text-red_r-11 font-semibold'> + + {selectedProduct().length > 0 + ? currencyFormat(totalPriceBeforeTax - totalDiscountAmount + totalTaxAmount) + : '-'} + </span> + </div> + </div> + <div className='flex gap-x-3'> + <button + type='button' + className='btn-yellow flex-1' + disabled={selectedProduct().length == 0} + onClick={() => router.push('/shop/quotation')} + > + Quotation + </button> + <button + type='button' + className='btn-solid-red flex-1' + disabled={selectedProduct().length == 0} + onClick={() => router.push('/shop/checkout')} + > + Checkout + </button> </div> - </div> - <div className='flex gap-x-3'> - <button - type='button' - className='btn-yellow flex-1' - disabled={selectedProduct().length == 0} - onClick={() => router.push('/shop/quotation')} - > - Quotation - </button> - <button - type='button' - className='btn-solid-red flex-1' - disabled={selectedProduct().length == 0} - onClick={() => router.push('/shop/checkout')} - > - Checkout - </button> </div> </div> diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 8416cd9e..8048eeba 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -132,7 +132,10 @@ const Checkout = () => { return ( <> <div className='p-4'> - <Alert type='info' className='text-caption-2 flex gap-x-3'> + <Alert + type='info' + className='text-caption-2 flex gap-x-3' + > <div> <ExclamationCircleIcon className='w-7 text-blue-700' /> </div> @@ -155,7 +158,11 @@ const Checkout = () => { <div className='p-4 flex flex-col gap-y-4'> {products?.map((product) => ( - <VariantCard product={product} openOnClick={false} key={product.id} /> + <VariantCard + product={product} + openOnClick={false} + key={product.id} + /> ))} </div> @@ -195,7 +202,10 @@ const Checkout = () => { <p className='text-caption-2 text-gray_r-10 mb-2'>*) Belum termasuk biaya pengiriman</p> <p className='text-caption-2 text-gray_r-10 leading-5'> Dengan melakukan pembelian melalui website Indoteknik, saya menyetujui{' '} - <Link href='/' className='inline font-normal'> + <Link + href='/' + className='inline font-normal' + > Syarat & Ketentuan </Link>{' '} yang berlaku @@ -253,7 +263,11 @@ const Checkout = () => { </div> <div className='w-6/12'> <label className='form-label font-normal'>Nomor PO</label> - <input type='text' className='form-input mt-2 h-12' ref={poNumber} /> + <input + type='text' + className='form-input mt-2 h-12' + ref={poNumber} + /> </div> </div> <p className='text-caption-2 text-gray_r-11 mt-2'>Ukuran dokumen PO Maksimal 5MB</p> @@ -262,7 +276,11 @@ const Checkout = () => { <Divider /> <div className='flex gap-x-3 p-4'> - <button className='flex-1 btn-yellow' onClick={checkout} disabled={isLoading}> + <button + className='flex-1 btn-yellow' + onClick={checkout} + disabled={isLoading} + > {isLoading ? 'Loading...' : 'Bayar'} </button> </div> @@ -279,7 +297,10 @@ const SectionAddress = ({ address, label, url }) => ( <div className='p-4'> <div className='flex justify-between items-center'> <div className='font-medium'>{label}</div> - <Link className='text-caption-1' href={url}> + <Link + className='text-caption-1' + href={url} + > Pilih Alamat Lain </Link> </div> diff --git a/src/lib/checkout/components/FinishCheckout.jsx b/src/lib/checkout/components/FinishCheckout.jsx index f0aaba4e..a7d65dd0 100644 --- a/src/lib/checkout/components/FinishCheckout.jsx +++ b/src/lib/checkout/components/FinishCheckout.jsx @@ -1,30 +1,30 @@ -import Link from "@/core/components/elements/Link/Link" -import useTransaction from "@/lib/transaction/hooks/useTransaction" +import Link from '@/core/components/elements/Link/Link' +import useTransaction from '@/lib/transaction/hooks/useTransaction' const FinishCheckout = ({ id }) => { const { transaction } = useTransaction({ id }) return ( - <div className="p-4"> + <div className='p-4'> <div className='rounded-xl bg-yellow_r-4 text-center border border-yellow_r-7'> - <div className='px-4 py-6 text-yellow_r-12'> - <p className='font-semibold mb-2'>Terima Kasih atas Pembelian Anda</p> - <p className='text-yellow_r-11 mb-4 leading-6'> - Rincian belanja sudah kami kirimkan ke email anda. Mohon dicek kembali. jika tidak - menerima email, anda dapat menghubungi kami disini. - </p> - <p className='mb-2 font-medium'>{transaction.data?.name}</p> - <p className='text-caption-2 text-yellow_r-11'>No. Transaksi</p> - </div> - <Link - href={transaction.data?.id ? `/my/transaction/${transaction.data.id}` : '/'} - className='bg-yellow_r-6 text-yellow_r-12 rounded-b-xl py-4 block' - > - Lihat detail pembelian Anda disini - </Link> + <div className='px-4 py-6 text-yellow_r-12'> + <p className='font-semibold mb-2'>Terima Kasih atas Pembelian Anda</p> + <p className='text-yellow_r-11 mb-4 leading-6'> + Rincian belanja sudah kami kirimkan ke email anda. Mohon dicek kembali. jika tidak + menerima email, anda dapat menghubungi kami disini. + </p> + <p className='mb-2 font-medium'>{transaction.data?.name}</p> + <p className='text-caption-2 text-yellow_r-11'>No. Transaksi</p> </div> + <Link + href={transaction.data?.id ? `/my/transaction/${transaction.data.id}` : '/'} + className='bg-yellow_r-6 text-yellow_r-12 rounded-b-xl py-4 block' + > + Lihat detail pembelian Anda disini + </Link> + </div> </div> ) } -export default FinishCheckout
\ No newline at end of file +export default FinishCheckout diff --git a/src/lib/home/components/HeroBanner.jsx b/src/lib/home/components/HeroBanner.jsx index 6f39ac50..0ac14bad 100644 --- a/src/lib/home/components/HeroBanner.jsx +++ b/src/lib/home/components/HeroBanner.jsx @@ -34,7 +34,11 @@ const HeroBanner = () => { > {heroBanners.data?.map((banner, index) => ( <SwiperSlide key={index}> - <Image src={banner.image} alt={banner.name} className='w-full h-auto' /> + <Image + src={banner.image} + alt={banner.name} + className='w-full h-auto' + /> </SwiperSlide> ))} </Swiper> diff --git a/src/lib/home/components/PopularProduct.jsx b/src/lib/home/components/PopularProduct.jsx index 7e222b0a..d23275f7 100644 --- a/src/lib/home/components/PopularProduct.jsx +++ b/src/lib/home/components/PopularProduct.jsx @@ -11,7 +11,12 @@ const PopularProduct = () => { <div className='px-4'> <div className='font-medium mb-4'>Produk Populer</div> {popularProducts.isLoading && <PopularProductSkeleton />} - {!popularProducts.isLoading && <ProductSlider products={popularProducts.data} simpleTitle />} + {!popularProducts.isLoading && ( + <ProductSlider + products={popularProducts.data} + simpleTitle + /> + )} </div> ) } diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index de377031..fa0fdd0d 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -11,7 +11,11 @@ const PreferredBrand = () => { <div className='font-medium mb-4'>Brand Pilihan</div> {preferredBrands.isLoading && <PreferredBrandSkeleton />} {!preferredBrands.isLoading && ( - <Swiper slidesPerView={3.5} spaceBetween={8} freeMode> + <Swiper + slidesPerView={3.5} + spaceBetween={8} + freeMode + > {preferredBrands.data?.manufactures.map((brand) => ( <SwiperSlide key={brand.id}> <BrandCard brand={brand} /> diff --git a/src/lib/invoice/components/Invoice.jsx b/src/lib/invoice/components/Invoice.jsx index eaf7b7e0..e34ad8c2 100644 --- a/src/lib/invoice/components/Invoice.jsx +++ b/src/lib/invoice/components/Invoice.jsx @@ -86,7 +86,10 @@ const Invoice = ({ id }) => { <div className='font-medium p-4'>Detail Produk</div> <div className='p-4 pt-0 flex flex-col gap-y-3'> - <VariantGroupCard variants={invoice.data?.products} buyMore /> + <VariantGroupCard + variants={invoice.data?.products} + buyMore + /> <div className='flex justify-between mt-3 font-medium'> <p>Total Belanja</p> <p>{currencyFormat(invoice.data?.amountTotal)}</p> diff --git a/src/lib/invoice/components/Invoices.jsx b/src/lib/invoice/components/Invoices.jsx index 81521785..ab318a3c 100644 --- a/src/lib/invoice/components/Invoices.jsx +++ b/src/lib/invoice/components/Invoices.jsx @@ -45,7 +45,10 @@ const Invoices = () => { return ( <div className='p-4 flex flex-col gap-y-4'> - <form className='flex gap-x-3' onSubmit={handleSubmit}> + <form + className='flex gap-x-3' + onSubmit={handleSubmit} + > <input type='text' className='form-input' @@ -53,7 +56,10 @@ const Invoices = () => { value={inputQuery} onChange={(e) => setInputQuery(e.target.value)} /> - <button className='btn-light bg-transparent px-3' type='submit'> + <button + className='btn-light bg-transparent px-3' + type='submit' + > <MagnifyingGlassIcon className='w-6' /> </button> </form> @@ -65,13 +71,19 @@ const Invoices = () => { )} {!invoices.isLoading && invoices.data?.invoices?.length === 0 && ( - <Alert type='info' className='text-center'> + <Alert + type='info' + className='text-center' + > Tidak ada data invoice </Alert> )} {invoices.data?.invoices?.map((invoice, index) => ( - <div className='p-4 shadow border border-gray_r-3 rounded-md' key={index}> + <div + className='p-4 shadow border border-gray_r-3 rounded-md' + key={index} + > <div className='grid grid-cols-2'> <Link href={`/my/invoice/${invoice.id}`}> <span className='text-caption-2 text-gray_r-11'>No. Invoice</span> @@ -83,7 +95,10 @@ const Invoices = () => { ) : ( <div className='badge-solid-green h-fit ml-auto'>Lunas</div> )} - <EllipsisVerticalIcon className='w-5 h-5' onClick={() => setToOthers(invoice)} /> + <EllipsisVerticalIcon + className='w-5 h-5' + onClick={() => setToOthers(invoice)} + /> </div> </div> <Link href={`/my/invoice/${invoice.id}`}> @@ -128,7 +143,11 @@ const Invoices = () => { className='mt-2 mb-2' /> - <BottomPopup title='Lainnya' active={toOthers} close={() => setToOthers(null)}> + <BottomPopup + title='Lainnya' + active={toOthers} + close={() => setToOthers(null)} + > <div className='flex flex-col gap-y-4 mt-2'> <button className='text-left disabled:opacity-60' diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 2181c38e..9e33316c 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -9,6 +9,11 @@ import ProductSimilar from './ProductSimilar' import LazyLoad from 'react-lazy-load' import { toast } from 'react-hot-toast' import { updateItemCart } from '@/core/utils/cart' +import useWishlist from '@/lib/wishlist/hooks/useWishlist' +import { HeartIcon } from '@heroicons/react/24/outline' +import useAuth from '@/core/hooks/useAuth' +import { useRouter } from 'next/router' +import createOrDeleteWishlistApi from '@/lib/wishlist/api/createOrDeleteWishlistApi' const informationTabOptions = [ { value: 'specification', label: 'Spesifikasi' }, @@ -17,6 +22,9 @@ const informationTabOptions = [ ] const Product = ({ product }) => { + const auth = useAuth() + const router = useRouter() + const { wishlist } = useWishlist({ productId: product?.id }) const [quantity, setQuantity] = useState('1') const [selectedVariant, setSelectedVariant] = useState(null) const [informationTab, setInformationTab] = useState(null) @@ -82,6 +90,21 @@ const Product = ({ product }) => { toast.success('Berhasil menambahkan ke keranjang') } + const toggleWishlist = async () => { + if (!auth) { + router.push('/login') + return + } + const data = { product_id: product.id } + await createOrDeleteWishlistApi({ data }) + if (wishlist.data.productTotal > 0) { + toast.success('Berhasil menghapus dari wishlist') + } else { + toast.success('Berhasil menambahkan ke wishlist') + } + wishlist.refetch() + } + return ( <> <Image @@ -91,9 +114,24 @@ const Product = ({ product }) => { /> <div className='p-4'> - <Link href='/' className='mb-2'> - {product.manufacture?.name} - </Link> + <div className='flex items-end mb-2'> + {product.manufacture?.name ? ( + <Link href='/'>{product.manufacture?.name}</Link> + ) : ( + <div>-</div> + )} + <button + type='button' + className='ml-auto' + onClick={toggleWishlist} + > + {wishlist.data?.productTotal > 0 ? ( + <HeartIcon className='w-6 fill-red_r-11 text-red_r-11' /> + ) : ( + <HeartIcon className='w-6' /> + )} + </button> + </div> <h1 className='leading-6 font-medium'>{activeVariant?.name}</h1> {activeVariant?.price?.discountPercentage > 0 && ( <div className='flex gap-x-1 items-center mt-2'> @@ -109,7 +147,10 @@ const Product = ({ product }) => { ) : ( <span className='text-gray_r-11 leading-6 font-normal'> Hubungi kami untuk dapatkan harga terbaik, - <a href='https://wa.me/' className='text-red_r-11 underline'> + <a + href='https://wa.me/' + className='text-red_r-11 underline' + > klik disini </a> </span> @@ -146,10 +187,17 @@ const Product = ({ product }) => { onChange={(e) => setQuantity(e.target.value)} /> </div> - <button type='button' className='btn-yellow flex-1' onClick={handleClickCart}> + <button + type='button' + className='btn-yellow flex-1' + onClick={handleClickCart} + > Keranjang </button> - <button type='button' className='btn-solid-red flex-1'> + <button + type='button' + className='btn-solid-red flex-1' + > Beli </button> </div> @@ -193,7 +241,10 @@ const Product = ({ product }) => { </span> )} {activeVariant?.stock == 0 && ( - <a href='https://wa.me' className='text-red_r-11 font-medium'> + <a + href='https://wa.me' + className='text-red_r-11 font-medium' + > Tanya Stok </a> )} @@ -201,7 +252,10 @@ const Product = ({ product }) => { <SpecificationContent label='Berat Barang'> {activeVariant?.weight > 0 && <span>{activeVariant?.weight} KG</span>} {activeVariant?.weight == 0 && ( - <a href='https://wa.me' className='text-red_r-11 font-medium'> + <a + href='https://wa.me' + className='text-red_r-11 font-medium' + > Tanya Berat </a> )} @@ -232,14 +286,21 @@ const Product = ({ product }) => { const TabButton = ({ children, active, ...props }) => { const activeClassName = active ? 'text-red_r-11 underline underline-offset-4' : 'text-gray_r-11' return ( - <button {...props} type='button' className={`font-medium pb-1 ${activeClassName}`}> + <button + {...props} + type='button' + className={`font-medium pb-1 ${activeClassName}`} + > {children} </button> ) } const TabContent = ({ children, active, className, ...props }) => ( - <div {...props} className={`${active ? 'block' : 'hidden'} ${className}`}> + <div + {...props} + className={`${active ? 'block' : 'hidden'} ${className}`} + > {children} </div> ) diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index dd221e4f..6b88a3bd 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -23,12 +23,20 @@ const ProductCard = ({ product, simpleTitle }) => { )} </Link> <div className='p-2 pb-3 text-caption-2 leading-5'> - <Link - href={createSlug('/shop/brands/', product?.manufacture?.name, product?.manufacture.id)} - className='mb-1' - > - {product?.manufacture?.name} - </Link> + {product?.manufacture?.name ? ( + <Link + href={createSlug( + '/shop/brands/', + product?.manufacture?.name, + product?.manufacture.id + )} + className='mb-1' + > + {product.manufacture.name} + </Link> + ) : ( + <div>-</div> + )} <Link href={createSlug('/shop/product/', product?.name, product?.id)} className={`font-medium mb-2 !text-gray_r-12 ${ diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx index d920cfb8..eca95f74 100644 --- a/src/lib/product/components/ProductFilter.jsx +++ b/src/lib/product/components/ProductFilter.jsx @@ -35,7 +35,11 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr } return ( - <BottomPopup active={active} close={close} title='Filter Produk'> + <BottomPopup + active={active} + close={close} + title='Filter Produk' + > <div className='flex flex-col gap-y-4'> {!defaultBrand && ( <div> @@ -48,7 +52,10 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr > <option value=''>Pilih Brand...</option> {brands.map((brand, index) => ( - <option value={brand} key={index}> + <option + value={brand} + key={index} + > {brand} </option> ))} @@ -65,7 +72,10 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr > <option value=''>Pilih Kategori...</option> {categories.map((category, index) => ( - <option value={category} key={index}> + <option + value={category} + key={index} + > {category} </option> ))} @@ -107,7 +117,11 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr /> </div> </div> - <button type='button' className='btn-solid-red w-full mt-2' onClick={handleSubmit}> + <button + type='button' + className='btn-solid-red w-full mt-2' + onClick={handleSubmit} + > Terapkan Filter </button> </div> diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 25d0278f..52bd5119 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -77,12 +77,21 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { )} </div> - <button className='btn-light mb-6 py-2 px-5' onClick={popup.activate}> + <button + className='btn-light mb-6 py-2 px-5' + onClick={popup.activate} + > Filter </button> <div className='grid grid-cols-2 gap-3'> - {products && products.map((product) => <ProductCard product={product} key={product.id} />)} + {products && + products.map((product) => ( + <ProductCard + product={product} + key={product.id} + /> + ))} </div> <Pagination diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index 0dab2f6b..060d4638 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -42,12 +42,18 @@ const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => > {bannerMode && ( <SwiperSlide> - <Link href={products.banner.url} className='w-full h-full block'></Link> + <Link + href={products.banner.url} + className='w-full h-full block' + ></Link> </SwiperSlide> )} {products?.products?.map((product, index) => ( <SwiperSlide key={index}> - <ProductCard product={product} simpleTitle={simpleTitle} /> + <ProductCard + product={product} + simpleTitle={simpleTitle} + /> </SwiperSlide> ))} </Swiper> diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index 17eacd45..7da33551 100644 --- a/src/lib/transaction/components/Transaction.jsx +++ b/src/lib/transaction/components/Transaction.jsx @@ -120,7 +120,10 @@ const Transaction = ({ id }) => { <div className='font-medium p-4'>Detail Produk</div> <div className='p-4 pt-0 flex flex-col gap-y-3'> - <VariantGroupCard variants={transaction.data?.products} buyMore /> + <VariantGroupCard + variants={transaction.data?.products} + buyMore + /> <div className='flex justify-between mt-3 font-medium'> <p>Total Belanja</p> <p>{currencyFormat(transaction.data?.amountTotal)}</p> @@ -137,7 +140,10 @@ const Transaction = ({ id }) => { <p className='font-medium'>Invoice</p> <div className='flex flex-col gap-y-3 mt-4'> {transaction.data?.invoices?.map((invoice, index) => ( - <Link href={`/my/invoice/${invoice.id}`} key={index}> + <Link + href={`/my/invoice/${invoice.id}`} + key={index} + > <div className='shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between'> <div> <p className='mb-2'>{invoice?.name}</p> @@ -157,7 +163,10 @@ const Transaction = ({ id }) => { </Link> ))} {transaction.data?.invoices?.length === 0 && ( - <Alert type='info' className='text-center'> + <Alert + type='info' + className='text-center' + > Belum ada Invoice </Alert> )} @@ -168,7 +177,10 @@ const Transaction = ({ id }) => { <div className='p-4 pt-0'> {transaction.data?.status == 'draft' && ( - <button className='btn-yellow w-full mt-4' onClick={checkout}> + <button + className='btn-yellow w-full mt-4' + onClick={checkout} + > Lanjutkan Transaksi </button> )} @@ -207,26 +219,50 @@ const Transaction = ({ id }) => { > Ya, Batalkan </button> - <button className='btn-light flex-1' type='button' onClick={closeCancelTransaction}> + <button + className='btn-light flex-1' + type='button' + onClick={closeCancelTransaction} + > Batal </button> </div> </BottomPopup> - <BottomPopup title='Upload PO' close={closeUploadPo} active={uploadPo}> + <BottomPopup + title='Upload PO' + close={closeUploadPo} + active={uploadPo} + > <div> <label>Nomor PO</label> - <input type='text' className='form-input mt-3' ref={poNumber} /> + <input + type='text' + className='form-input mt-3' + ref={poNumber} + /> </div> <div className='mt-4'> <label>Dokumen PO</label> - <input type='file' className='form-input mt-3 py-2' ref={poFile} /> + <input + type='file' + className='form-input mt-3 py-2' + ref={poFile} + /> </div> <div className='grid grid-cols-2 gap-x-3 mt-6'> - <button type='button' className='btn-light w-full' onClick={closeUploadPo}> + <button + type='button' + className='btn-light w-full' + onClick={closeUploadPo} + > Batal </button> - <button type='button' className='btn-solid-red w-full' onClick={submitUploadPo}> + <button + type='button' + className='btn-solid-red w-full' + onClick={submitUploadPo} + > Upload </button> </div> @@ -279,7 +315,10 @@ const SectionAddress = ({ address }) => { } const SectionButton = ({ label, active, toggle }) => ( - <button className='p-4 font-medium flex justify-between w-full' onClick={toggle}> + <button + className='p-4 font-medium flex justify-between w-full' + onClick={toggle} + > <span>{label}</span> {active ? <ChevronUpIcon className='w-5' /> : <ChevronDownIcon className='w-5' />} </button> diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx index f582319d..ccbdede2 100644 --- a/src/lib/transaction/components/Transactions.jsx +++ b/src/lib/transaction/components/Transactions.jsx @@ -56,7 +56,10 @@ const Transactions = () => { return ( <div className='p-4 flex flex-col gap-y-4'> - <form className='flex gap-x-3' onSubmit={handleSubmit}> + <form + className='flex gap-x-3' + onSubmit={handleSubmit} + > <input type='text' className='form-input' @@ -64,7 +67,10 @@ const Transactions = () => { value={inputQuery} onChange={(e) => setInputQuery(e.target.value)} /> - <button className='btn-light bg-transparent px-3' type='submit'> + <button + className='btn-light bg-transparent px-3' + type='submit' + > <MagnifyingGlassIcon className='w-6' /> </button> </form> @@ -76,13 +82,19 @@ const Transactions = () => { )} {!transactions.isLoading && transactions.data?.saleOrders?.length === 0 && ( - <Alert type='info' className='text-center'> + <Alert + type='info' + className='text-center' + > Tidak ada data transaksi </Alert> )} {transactions.data?.saleOrders?.map((saleOrder, index) => ( - <div className='p-4 shadow border border-gray_r-3 rounded-md' key={index}> + <div + className='p-4 shadow border border-gray_r-3 rounded-md' + key={index} + > <div className='grid grid-cols-2'> <Link href={`/my/transaction/${saleOrder.id}`}> <span className='text-caption-2 text-gray_r-11'>No. Transaksi</span> @@ -90,7 +102,10 @@ const Transactions = () => { </Link> <div className='flex gap-x-1 justify-end'> <TransactionStatusBadge status={saleOrder.status} /> - <EllipsisVerticalIcon className='w-5 h-5' onClick={() => setToOthers(saleOrder)} /> + <EllipsisVerticalIcon + className='w-5 h-5' + onClick={() => setToOthers(saleOrder)} + /> </div> </div> <Link href={`/my/transaction/${saleOrder.id}`}> @@ -129,7 +144,11 @@ const Transactions = () => { className='mt-2 mb-2' /> - <BottomPopup title='Lainnya' active={toOthers} close={() => setToOthers(null)}> + <BottomPopup + title='Lainnya' + active={toOthers} + close={() => setToOthers(null)} + > <div className='flex flex-col gap-y-4 mt-2'> <button className='text-left disabled:opacity-60' @@ -164,16 +183,28 @@ const Transactions = () => { </div> </BottomPopup> - <BottomPopup active={toCancel} close={() => setToCancel(null)} title='Batalkan Transaksi'> + <BottomPopup + active={toCancel} + close={() => setToCancel(null)} + title='Batalkan Transaksi' + > <div className='leading-7 text-gray_r-12/80'> Apakah anda yakin membatalkan transaksi{' '} <span className='underline'>{toCancel?.name}</span>? </div> <div className='flex mt-6 gap-x-4'> - <button className='btn-solid-red flex-1' type='button' onClick={submitCancelTransaction}> + <button + className='btn-solid-red flex-1' + type='button' + onClick={submitCancelTransaction} + > Ya, Batalkan </button> - <button className='btn-light flex-1' type='button' onClick={() => setToCancel(null)}> + <button + className='btn-light flex-1' + type='button' + onClick={() => setToCancel(null)} + > Batal </button> </div> diff --git a/src/lib/variant/components/VariantGroupCard.jsx b/src/lib/variant/components/VariantGroupCard.jsx index 8cb1eec4..e5f5c7fc 100644 --- a/src/lib/variant/components/VariantGroupCard.jsx +++ b/src/lib/variant/components/VariantGroupCard.jsx @@ -8,7 +8,11 @@ const VariantGroupCard = ({ variants, ...props }) => { return ( <> {variantsToShow?.map((variant, index) => ( - <VariantCard key={index} product={variant} {...props} /> + <VariantCard + key={index} + product={variant} + {...props} + /> ))} {variants.length > 2 && ( <button diff --git a/src/lib/wishlist/api/createOrDeleteWishlistApi.js b/src/lib/wishlist/api/createOrDeleteWishlistApi.js new file mode 100644 index 00000000..617d139d --- /dev/null +++ b/src/lib/wishlist/api/createOrDeleteWishlistApi.js @@ -0,0 +1,14 @@ +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' + +const createOrDeleteWishlistApi = async ({ data }) => { + const auth = getAuth() + const dataWishlist = await odooApi( + 'POST', + `/api/v1/user/${auth.id}/wishlist/create-or-delete`, + data + ) + return dataWishlist +} + +export default createOrDeleteWishlistApi diff --git a/src/lib/wishlist/api/wishlistApi.js b/src/lib/wishlist/api/wishlistApi.js new file mode 100644 index 00000000..a8906dd4 --- /dev/null +++ b/src/lib/wishlist/api/wishlistApi.js @@ -0,0 +1,14 @@ +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' + +const wishlistApi = async ({ productId }) => { + const auth = getAuth() + if (!auth) return { productTotal: 0, products: [] } + const dataWishlist = await odooApi( + 'GET', + `/api/v1/user/${auth.id}/wishlist?product_id=${productId}` + ) + return dataWishlist +} + +export default wishlistApi diff --git a/src/lib/wishlist/components/Wishlists.jsx b/src/lib/wishlist/components/Wishlists.jsx index 71ac095e..e61efcc3 100644 --- a/src/lib/wishlist/components/Wishlists.jsx +++ b/src/lib/wishlist/components/Wishlists.jsx @@ -24,19 +24,29 @@ const Wishlists = () => { return ( <div className='px-4 py-6'> {wishlists.data?.products?.length == 0 && ( - <Alert type='info' className='text-center'> + <Alert + type='info' + className='text-center' + > Wishlist anda masih kosong </Alert> )} <div className='grid grid-cols-2 gap-3'> {wishlists.data?.products.map((product) => ( - <ProductCard key={product.id} product={product} /> + <ProductCard + key={product.id} + product={product} + /> ))} </div> <div className='mt-6'> - <Pagination currentPage={page} pageCount={pageCount} url={`/my/wishlist`} /> + <Pagination + currentPage={page} + pageCount={pageCount} + url={`/my/wishlist`} + /> </div> </div> ) diff --git a/src/lib/wishlist/hooks/useWishlist.js b/src/lib/wishlist/hooks/useWishlist.js new file mode 100644 index 00000000..8580a19d --- /dev/null +++ b/src/lib/wishlist/hooks/useWishlist.js @@ -0,0 +1,13 @@ +import { useQuery } from 'react-query' +import wishlistApi from '../api/wishlistApi' + +const useWishlist = ({ productId }) => { + const fetchWishlist = async () => await wishlistApi({ productId }) + const { data, isLoading, refetch } = useQuery(`wishlist-${productId}`, fetchWishlist) + + return { + wishlist: { data, isLoading, refetch } + } +} + +export default useWishlist diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index 0110576a..e32efc19 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -19,10 +19,20 @@ function MyApp({ Component, pageProps }) { className: 'border border-gray_r-8' }} /> - <NextProgress color='#F01C21' options={{ showSpinner: false }} /> + <NextProgress + color='#F01C21' + options={{ showSpinner: false }} + /> <QueryClientProvider client={queryClient}> - <AnimatePresence mode='wait' initial={false} onExitComplete={() => window.scrollTo(0, 0)}> - <Component {...pageProps} key={router.asPath} /> + <AnimatePresence + mode='wait' + initial={false} + onExitComplete={() => window.scrollTo(0, 0)} + > + <Component + {...pageProps} + key={router.asPath} + /> </AnimatePresence> </QueryClientProvider> </> diff --git a/src/pages/my/address/[id]/edit.jsx b/src/pages/my/address/[id]/edit.jsx index a7c22147..65d7cf9b 100644 --- a/src/pages/my/address/[id]/edit.jsx +++ b/src/pages/my/address/[id]/edit.jsx @@ -5,7 +5,10 @@ import EditAddressComponent from '@/lib/address/components/EditAddress' export default function EditAddress({ id, defaultValues }) { return ( <AppLayout title='Ubah Alamat'> - <EditAddressComponent id={id} defaultValues={defaultValues} /> + <EditAddressComponent + id={id} + defaultValues={defaultValues} + /> </AppLayout> ) } diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx index 0edc98ae..576919ae 100644 --- a/src/pages/my/menu.jsx +++ b/src/pages/my/menu.jsx @@ -17,7 +17,10 @@ export default function Menu() { return ( <AppLayout title='Menu Utama'> - <Link href='/my/profile' className='p-4 flex items-center'> + <Link + href='/my/profile' + className='p-4 flex items-center' + > <div className='rounded-full p-3 bg-gray_r-6 text-gray_r-12/80'> <UserIcon className='w-5' /> </div> @@ -60,7 +63,10 @@ export default function Menu() { <LinkItem href='/my/address'>Daftar Alamat</LinkItem> </div> - <div onClick={logout} className='p-4 mt-2'> + <div + onClick={logout} + className='p-4 mt-2' + > <button className='w-full btn-red'>Keluar Akun</button> </div> </div> @@ -70,13 +76,19 @@ export default function Menu() { } const MenuHeader = ({ children, ...props }) => ( - <div {...props} className='font-medium px-4 flex'> + <div + {...props} + className='font-medium px-4 flex' + > {children} </div> ) const LinkItem = ({ children, ...props }) => ( - <Link {...props} className='!text-gray_r-11 !font-normal p-4 flex items-center'> + <Link + {...props} + className='!text-gray_r-11 !font-normal p-4 flex items-center' + > {children} <div className='ml-auto !text-gray_r-11'> <ChevronRightIcon className='w-5' /> diff --git a/src/pages/my/profile.jsx b/src/pages/my/profile.jsx new file mode 100644 index 00000000..f69d4303 --- /dev/null +++ b/src/pages/my/profile.jsx @@ -0,0 +1,10 @@ +import AppLayout from '@/core/components/layouts/AppLayout' +import PersonalProfile from '@/lib/auth/components/PersonalProfile' + +export default function Profile() { + return ( + <AppLayout title='Akun Saya'> + <PersonalProfile /> + </AppLayout> + ) +} diff --git a/src/pages/shop/checkout/finish.jsx b/src/pages/shop/checkout/finish.jsx index 7a1aa05d..fb6970f6 100644 --- a/src/pages/shop/checkout/finish.jsx +++ b/src/pages/shop/checkout/finish.jsx @@ -1,6 +1,6 @@ -import BasicLayout from "@/core/components/layouts/BasicLayout"; -import FinishCheckoutComponent from "@/lib/checkout/components/FinishCheckout"; -import { useRouter } from "next/router"; +import BasicLayout from '@/core/components/layouts/BasicLayout' +import FinishCheckoutComponent from '@/lib/checkout/components/FinishCheckout' +import { useRouter } from 'next/router' export default function Finish() { const router = useRouter() @@ -10,4 +10,4 @@ export default function Finish() { <FinishCheckoutComponent id={router.query.id || 0} /> </BasicLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/shop/search.jsx b/src/pages/shop/search.jsx index d616f2dd..345b715a 100644 --- a/src/pages/shop/search.jsx +++ b/src/pages/shop/search.jsx @@ -10,7 +10,12 @@ export default function Search() { return ( <BasicLayout> - {!_.isEmpty(router.query) && <ProductSearch query={router.query} prefixUrl='/shop/search' />} + {!_.isEmpty(router.query) && ( + <ProductSearch + query={router.query} + prefixUrl='/shop/search' + /> + )} </BasicLayout> ) } |
