diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-02-22 11:03:34 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-02-22 11:03:34 +0700 |
| commit | f66b12fd1d0b83af0d7230d7b1565fbe00afbe3c (patch) | |
| tree | 253dcf854a3c92e09ca846e86a09e5b4c5d16be1 /src/lib | |
| parent | 3c559031623649a67825ff47f34512f0eb946861 (diff) | |
prettier
Diffstat (limited to 'src/lib')
72 files changed, 1399 insertions, 1539 deletions
diff --git a/src/lib/address/api/addressApi.js b/src/lib/address/api/addressApi.js index f2fc6c9e..f99d81c0 100644 --- a/src/lib/address/api/addressApi.js +++ b/src/lib/address/api/addressApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const addressApi = async ({ id }) => { const dataAddress = await odooApi('GET', `/api/v1/partner/${id}/address`) return dataAddress } -export default addressApi
\ No newline at end of file +export default addressApi diff --git a/src/lib/address/api/addressesApi.js b/src/lib/address/api/addressesApi.js index 1edfc077..96f9e9d9 100644 --- a/src/lib/address/api/addressesApi.js +++ b/src/lib/address/api/addressesApi.js @@ -1,5 +1,5 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const addressesApi = async () => { const auth = getAuth() @@ -7,4 +7,4 @@ const addressesApi = async () => { return dataAddresses } -export default addressesApi
\ No newline at end of file +export default addressesApi diff --git a/src/lib/address/api/cityApi.js b/src/lib/address/api/cityApi.js index 8cf1bedd..7873435b 100644 --- a/src/lib/address/api/cityApi.js +++ b/src/lib/address/api/cityApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const cityApi = async () => { const dataCities = await odooApi('GET', '/api/v1/city') return dataCities } -export default cityApi
\ No newline at end of file +export default cityApi diff --git a/src/lib/address/api/createAddressApi.js b/src/lib/address/api/createAddressApi.js index 29804d1c..b33b7ae1 100644 --- a/src/lib/address/api/createAddressApi.js +++ b/src/lib/address/api/createAddressApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const createAddressApi = async ({ data }) => { const dataAddress = await odooApi('POST', '/api/v1/partner/address', data) return dataAddress } -export default createAddressApi
\ No newline at end of file +export default createAddressApi diff --git a/src/lib/address/api/districtApi.js b/src/lib/address/api/districtApi.js index 120757e9..b0bcff16 100644 --- a/src/lib/address/api/districtApi.js +++ b/src/lib/address/api/districtApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const districtApi = async ({ cityId }) => { const dataDistricts = await odooApi('GET', `/api/v1/district?city_id=${cityId}`) return dataDistricts } -export default districtApi
\ No newline at end of file +export default districtApi diff --git a/src/lib/address/api/editAddressApi.js b/src/lib/address/api/editAddressApi.js index e01f6015..ba383ef0 100644 --- a/src/lib/address/api/editAddressApi.js +++ b/src/lib/address/api/editAddressApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const editAddressApi = async ({ id, data }) => { const dataAddress = await odooApi('PUT', `/api/v1/partner/${id}/address`, data) return dataAddress } -export default editAddressApi
\ No newline at end of file +export default editAddressApi diff --git a/src/lib/address/api/subDistrictApi.js b/src/lib/address/api/subDistrictApi.js index 64230838..3f834420 100644 --- a/src/lib/address/api/subDistrictApi.js +++ b/src/lib/address/api/subDistrictApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const subDistrictApi = async ({ districtId }) => { const dataSubDistricts = await odooApi('GET', `/api/v1/sub_district?district_id=${districtId}`) return dataSubDistricts } -export default subDistrictApi
\ No newline at end of file +export default subDistrictApi diff --git a/src/lib/address/components/Addresses.jsx b/src/lib/address/components/Addresses.jsx index 7a82c0da..c4855f8f 100644 --- a/src/lib/address/components/Addresses.jsx +++ b/src/lib/address/components/Addresses.jsx @@ -1,15 +1,13 @@ -import Link from "@/core/components/elements/Link/Link" -import Spinner from "@/core/components/elements/Spinner/Spinner" -import useAuth from "@/core/hooks/useAuth" -import { getItemAddress, updateItemAddress } from "@/core/utils/address" -import { useRouter } from "next/router" -import useAddresses from "../hooks/useAddresses" +import Link from '@/core/components/elements/Link/Link' +import Spinner from '@/core/components/elements/Spinner/Spinner' +import useAuth from '@/core/hooks/useAuth' +import { getItemAddress, updateItemAddress } from '@/core/utils/address' +import { useRouter } from 'next/router' +import useAddresses from '../hooks/useAddresses' const Addresses = () => { const router = useRouter() - const { - select = null - } = router.query + const { select = null } = router.query const auth = useAuth() const { addresses } = useAddresses() const selectedAdress = getItemAddress(select || '') @@ -21,48 +19,60 @@ const Addresses = () => { if (addresses.isLoading) { return ( - <div className="flex justify-center my-6"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + <div className='flex justify-center my-6'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> ) } return ( - <div className="p-4"> - <div className="text-right"> - <Link href="/my/address/create">Tambah Alamat</Link> + <div className='p-4'> + <div className='text-right'> + <Link href='/my/address/create'>Tambah Alamat</Link> </div> - <div className="grid gap-y-4 mt-4"> - { addresses.data?.map((address, index) => { - let type = address.type.charAt(0).toUpperCase() + address.type.slice(1) + ' Address'; + <div className='grid gap-y-4 mt-4'> + {addresses.data?.map((address, index) => { + let type = address.type.charAt(0).toUpperCase() + address.type.slice(1) + ' Address' return ( - <div - key={index} - className={"p-4 rounded-md border " + (selectedAdress && selectedAdress == address.id ? "border-gray_r-7 bg-gray_r-2" : "border-gray_r-7") } + <div + key={index} + className={ + 'p-4 rounded-md border ' + + (selectedAdress && selectedAdress == address.id + ? 'border-gray_r-7 bg-gray_r-2' + : 'border-gray_r-7') + } > <div onClick={() => changeSelectedAddress(address.id)}> - <div className="flex gap-x-2" > - <div className="badge-red">{ type }</div> - { auth?.partnerId == address.id && ( - <div className="badge-green">Utama</div> - ) } + <div className='flex gap-x-2'> + <div className='badge-red'>{type}</div> + {auth?.partnerId == address.id && <div className='badge-green'>Utama</div>} </div> - <p className="font-medium mt-2">{ address.name }</p> - { address.mobile && ( - <p className="mt-2 text-gray_r-11">{ address.mobile }</p> - ) } - <p className={`mt-1 leading-6 ${selectedAdress && selectedAdress == address.id ? "text-gray_r-12" : "text-gray_r-11"}`}> - { address.street } + <p className='font-medium mt-2'>{address.name}</p> + {address.mobile && <p className='mt-2 text-gray_r-11'>{address.mobile}</p>} + <p + className={`mt-1 leading-6 ${ + selectedAdress && selectedAdress == address.id + ? 'text-gray_r-12' + : 'text-gray_r-11' + }`} + > + {address.street} </p> </div> - <Link href={`/my/address/${address.id}/edit`} className="btn-light bg-white mt-3 w-full !text-gray_r-11">Ubah Alamat</Link> + <Link + href={`/my/address/${address.id}/edit`} + className='btn-light bg-white mt-3 w-full !text-gray_r-11' + > + Ubah Alamat + </Link> </div> - ); - }) } + ) + })} </div> </div> ) } -export default Addresses
\ No newline at end of file +export default Addresses diff --git a/src/lib/address/components/CreateAddress.jsx b/src/lib/address/components/CreateAddress.jsx index 4ba99820..62bb0858 100644 --- a/src/lib/address/components/CreateAddress.jsx +++ b/src/lib/address/components/CreateAddress.jsx @@ -1,34 +1,34 @@ -import HookFormSelect from "@/core/components/elements/Select/HookFormSelect" -import useAuth from "@/core/hooks/useAuth" -import { useRouter } from "next/router" -import { Controller, useForm } from "react-hook-form" -import * as Yup from "yup" -import cityApi from "../api/cityApi" -import districtApi from "../api/districtApi" -import subDistrictApi from "../api/subDistrictApi" -import { useEffect, useState } from "react" -import createAddressApi from "../api/createAddressApi" -import { toast } from "react-hot-toast" -import { yupResolver } from "@hookform/resolvers/yup" +import HookFormSelect from '@/core/components/elements/Select/HookFormSelect' +import useAuth from '@/core/hooks/useAuth' +import { useRouter } from 'next/router' +import { Controller, useForm } from 'react-hook-form' +import * as Yup from 'yup' +import cityApi from '../api/cityApi' +import districtApi from '../api/districtApi' +import subDistrictApi from '../api/subDistrictApi' +import { useEffect, useState } from 'react' +import createAddressApi from '../api/createAddressApi' +import { toast } from 'react-hot-toast' +import { yupResolver } from '@hookform/resolvers/yup' const CreateAddress = () => { const auth = useAuth() const router = useRouter() - const { - register, - formState: { errors }, + const { + register, + formState: { errors }, handleSubmit, watch, setValue, - control, - } = useForm({ + control + } = useForm({ resolver: yupResolver(validationSchema), defaultValues }) - const [ cities, setCities ] = useState([]) - const [ districts, setDistricts ] = useState([]) - const [ subDistricts, setSubDistricts ] = useState([]) + const [cities, setCities] = useState([]) + const [districts, setDistricts] = useState([]) + const [subDistricts, setSubDistricts] = useState([]) useEffect(() => { const loadCities = async () => { @@ -45,12 +45,15 @@ const CreateAddress = () => { if (watchCity) { const loadDistricts = async () => { let dataDistricts = await districtApi({ cityId: watchCity }) - dataDistricts = dataDistricts.map((district) => ({ value: district.id, label: district.name })) + dataDistricts = dataDistricts.map((district) => ({ + value: district.id, + label: district.name + })) setDistricts(dataDistricts) } loadDistricts() } - }, [ watchCity, setValue ]) + }, [watchCity, setValue]) const watchDistrict = watch('district') useEffect(() => { @@ -58,14 +61,17 @@ const CreateAddress = () => { if (watchDistrict) { const loadSubDistricts = async () => { let dataSubDistricts = await subDistrictApi({ districtId: watchDistrict }) - dataSubDistricts = dataSubDistricts.map((district) => ({ value: district.id, label: district.name })) + dataSubDistricts = dataSubDistricts.map((district) => ({ + value: district.id, + label: district.name + })) setSubDistricts(dataSubDistricts) } loadSubDistricts() } - }, [ watchDistrict, setValue ]) + }, [watchDistrict, setValue]) - const onSubmitHandler = async (values) => { + const onSubmitHandler = async (values) => { const data = { ...values, city_id: values.city, @@ -79,119 +85,93 @@ const CreateAddress = () => { toast.success('Berhasil menambahkan alamat') router.back() } - } + } 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> + <label className='form-label mb-2'>Label Alamat</label> <Controller - name="type" + 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 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" - /> - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.name?.message }</div> + <label className='form-label mb-2'>Nama</label> + <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> <div> - <label className="form-label mb-2">Email</label> + <label className='form-label mb-2'>Email</label> <input {...register('email')} - placeholder="contoh@email.com" - type="email" - className="form-input" + placeholder='contoh@email.com' + type='email' + className='form-input' /> - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.email?.message }</div> + <div className='text-caption-2 text-red_r-11 mt-1'>{errors.email?.message}</div> </div> <div> - <label className="form-label mb-2">Mobile</label> - <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> + <label className='form-label mb-2'>Mobile</label> + <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> <div> - <label className="form-label mb-2">Alamat</label> + <label className='form-label mb-2'>Alamat</label> <input {...register('street')} - placeholder="Jl. Bandengan Utara 85A" - type="text" - className="form-input" + placeholder='Jl. Bandengan Utara 85A' + type='text' + className='form-input' /> - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.street?.message }</div> + <div className='text-caption-2 text-red_r-11 mt-1'>{errors.street?.message}</div> </div> <div> - <label className="form-label mb-2">Kode Pos</label> - <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> + <label className='form-label mb-2'>Kode Pos</label> + <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> <div> - <label className="form-label mb-2">Kota</label> + <label className='form-label mb-2'>Kota</label> <Controller - name="city" + 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 className='text-caption-2 text-red_r-11 mt-1'>{errors.city?.message}</div> </div> <div> - <label className="form-label mb-2">Kecamatan</label> + <label className='form-label mb-2'>Kecamatan</label> <Controller - name="district" + name='district' control={control} - render={props => ( - <HookFormSelect - {...props} - options={districts} - disabled={!watchCity} - /> + render={(props) => ( + <HookFormSelect {...props} options={districts} disabled={!watchCity} /> )} /> </div> <div> - <label className="form-label mb-2">Kelurahan</label> + <label className='form-label mb-2'>Kelurahan</label> <Controller - name="subDistrict" + name='subDistrict' control={control} - render={props => ( - <HookFormSelect - {...props} - options={subDistricts} - disabled={!watchDistrict} - /> + render={(props) => ( + <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> @@ -205,7 +185,7 @@ const validationSchema = Yup.object().shape({ mobile: Yup.string().required('Harus di-isi'), street: Yup.string().required('Harus di-isi'), zip: Yup.string().required('Harus di-isi'), - city: Yup.string().required('Harus di-pilih'), + city: Yup.string().required('Harus di-pilih') }) const defaultValues = { @@ -217,14 +197,14 @@ const defaultValues = { city: '', district: '', subDistrict: '', - zip: '', + zip: '' } const types = [ { value: 'contact', label: 'Contact Address' }, { value: 'invoice', label: 'Invoice Address' }, { value: 'delivery', label: 'Delivery Address' }, - { value: 'other', label: 'Other Address' }, + { value: 'other', label: 'Other Address' } ] -export default CreateAddress
\ No newline at end of file +export default CreateAddress diff --git a/src/lib/address/components/EditAddress.jsx b/src/lib/address/components/EditAddress.jsx index b866a1e6..0cfa013a 100644 --- a/src/lib/address/components/EditAddress.jsx +++ b/src/lib/address/components/EditAddress.jsx @@ -1,14 +1,14 @@ -import { yupResolver } from "@hookform/resolvers/yup" -import { useRouter } from "next/router" -import { useEffect, useState } from "react" -import * as Yup from "yup" -import cityApi from "../api/cityApi" -import { Controller, useForm } from "react-hook-form" -import districtApi from "../api/districtApi" -import subDistrictApi from "../api/subDistrictApi" -import editAddressApi from "../api/editAddressApi" -import HookFormSelect from "@/core/components/elements/Select/HookFormSelect" -import { toast } from "react-hot-toast" +import { yupResolver } from '@hookform/resolvers/yup' +import { useRouter } from 'next/router' +import { useEffect, useState } from 'react' +import * as Yup from 'yup' +import cityApi from '../api/cityApi' +import { Controller, useForm } from 'react-hook-form' +import districtApi from '../api/districtApi' +import subDistrictApi from '../api/subDistrictApi' +import editAddressApi from '../api/editAddressApi' +import HookFormSelect from '@/core/components/elements/Select/HookFormSelect' +import { toast } from 'react-hot-toast' const EditAddress = ({ id, defaultValues }) => { const router = useRouter() @@ -19,10 +19,10 @@ const EditAddress = ({ id, defaultValues }) => { watch, setValue, getValues, - control, + control } = useForm({ resolver: yupResolver(validationSchema), - defaultValues, + defaultValues }) const [cities, setCities] = useState([]) @@ -34,52 +34,52 @@ const EditAddress = ({ id, defaultValues }) => { let dataCities = await cityApi() dataCities = dataCities.map((city) => ({ value: city.id, - label: city.name, + label: city.name })) setCities(dataCities) } loadCities() }, []) - const watchCity = watch("city") + const watchCity = watch('city') useEffect(() => { - setValue("district", "") + setValue('district', '') if (watchCity) { const loadDistricts = async () => { let dataDistricts = await districtApi({ cityId: watchCity }) dataDistricts = dataDistricts.map((district) => ({ value: district.id, - label: district.name, + label: district.name })) setDistricts(dataDistricts) - let oldDistrict = getValues("oldDistrict") + let oldDistrict = getValues('oldDistrict') if (oldDistrict) { - setValue("district", oldDistrict) - setValue("oldDistrict", "") + setValue('district', oldDistrict) + setValue('oldDistrict', '') } } loadDistricts() } }, [watchCity, setValue, getValues]) - const watchDistrict = watch("district") + const watchDistrict = watch('district') useEffect(() => { - setValue("subDistrict", "") + setValue('subDistrict', '') if (watchDistrict) { const loadSubDistricts = async () => { let dataSubDistricts = await subDistrictApi({ - districtId: watchDistrict, + districtId: watchDistrict }) dataSubDistricts = dataSubDistricts.map((district) => ({ value: district.id, - label: district.name, + label: district.name })) setSubDistricts(dataSubDistricts) - let oldSubDistrict = getValues("oldSubDistrict") + let oldSubDistrict = getValues('oldSubDistrict') if (oldSubDistrict) { - setValue("subDistrict", oldSubDistrict) - setValue("oldSubDistrict", "") + setValue('subDistrict', oldSubDistrict) + setValue('oldSubDistrict', '') } } loadSubDistricts() @@ -91,143 +91,101 @@ const EditAddress = ({ id, defaultValues }) => { ...values, city_id: values.city, district_id: values.district, - sub_district_id: values.subDistrict, + sub_district_id: values.subDistrict } const address = await editAddressApi({ id, data }) if (address?.id) { - toast.success("Berhasil mengubah alamat") + toast.success('Berhasil mengubah alamat') router.back() } } 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> + <label className='form-label mb-2'>Label Alamat</label> <Controller - name="type" + 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 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" - /> - <div className="text-caption-2 text-red_r-11 mt-1"> - {errors.name?.message} - </div> + <label className='form-label mb-2'>Nama</label> + <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> <div> - <label className="form-label mb-2">Email</label> + <label className='form-label mb-2'>Email</label> <input - {...register("email")} - placeholder="johndoe@example.com" - type="email" - className="form-input" + {...register('email')} + placeholder='johndoe@example.com' + type='email' + className='form-input' /> - <div className="text-caption-2 text-red_r-11 mt-1"> - {errors.email?.message} - </div> + <div className='text-caption-2 text-red_r-11 mt-1'>{errors.email?.message}</div> </div> <div> - <label className="form-label mb-2">Mobile</label> - <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> + <label className='form-label mb-2'>Mobile</label> + <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> <div> - <label className="form-label mb-2">Alamat</label> + <label className='form-label mb-2'>Alamat</label> <input - {...register("street")} - placeholder="Jl. Bandengan Utara 85A" - type="text" - className="form-input" + {...register('street')} + placeholder='Jl. Bandengan Utara 85A' + type='text' + className='form-input' /> - <div className="text-caption-2 text-red_r-11 mt-1"> - {errors.street?.message} - </div> + <div className='text-caption-2 text-red_r-11 mt-1'>{errors.street?.message}</div> </div> <div> - <label className="form-label mb-2">Kode Pos</label> - <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> + <label className='form-label mb-2'>Kode Pos</label> + <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> <div> - <label className="form-label mb-2">Kota</label> + <label className='form-label mb-2'>Kota</label> <Controller - name="city" + name='city' control={control} render={(props) => <HookFormSelect {...props} options={cities} />} /> - <div className="text-caption-2 text-red_r-11 mt-1"> - {errors.city?.message} - </div> + <div className='text-caption-2 text-red_r-11 mt-1'>{errors.city?.message}</div> </div> <div> - <label className="form-label mb-2">Kecamatan</label> + <label className='form-label mb-2'>Kecamatan</label> <Controller - name="district" + name='district' control={control} render={(props) => ( - <HookFormSelect - {...props} - options={districts} - disabled={!watchCity} - /> + <HookFormSelect {...props} options={districts} disabled={!watchCity} /> )} /> </div> <div> - <label className="form-label mb-2">Kelurahan</label> + <label className='form-label mb-2'>Kelurahan</label> <Controller - name="subDistrict" + 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> @@ -235,22 +193,20 @@ const EditAddress = ({ id, defaultValues }) => { } const validationSchema = Yup.object().shape({ - type: Yup.string().required("Harus di-pilih"), - name: Yup.string().min(3, "Minimal 3 karakter").required("Harus di-isi"), - email: Yup.string() - .email("Format harus seperti johndoe@example.com") - .required("Harus di-isi"), - mobile: Yup.string().required("Harus di-isi"), - street: Yup.string().required("Harus di-isi"), - zip: Yup.string().required("Harus di-isi"), - city: Yup.string().required("Harus di-pilih"), + type: Yup.string().required('Harus di-pilih'), + name: Yup.string().min(3, 'Minimal 3 karakter').required('Harus di-isi'), + email: Yup.string().email('Format harus seperti johndoe@example.com').required('Harus di-isi'), + mobile: Yup.string().required('Harus di-isi'), + street: Yup.string().required('Harus di-isi'), + zip: Yup.string().required('Harus di-isi'), + city: Yup.string().required('Harus di-pilih') }) const types = [ - { value: "contact", label: "Contact Address" }, - { value: "invoice", label: "Invoice Address" }, - { value: "delivery", label: "Delivery Address" }, - { value: "other", label: "Other Address" }, + { value: 'contact', label: 'Contact Address' }, + { value: 'invoice', label: 'Invoice Address' }, + { value: 'delivery', label: 'Delivery Address' }, + { value: 'other', label: 'Other Address' } ] export default EditAddress diff --git a/src/lib/address/hooks/useAddresses.js b/src/lib/address/hooks/useAddresses.js index 9968d790..629e367c 100644 --- a/src/lib/address/hooks/useAddresses.js +++ b/src/lib/address/hooks/useAddresses.js @@ -1,13 +1,13 @@ -import { useQuery } from "react-query" -import addressesApi from "../api/addressesApi" +import { useQuery } from 'react-query' +import addressesApi from '../api/addressesApi' const useAddresses = () => { const fetchAddresses = async () => await addressesApi() const { data, isLoading } = useQuery('addresses', fetchAddresses) - + return { addresses: { data, isLoading } } } -export default useAddresses
\ No newline at end of file +export default useAddresses diff --git a/src/lib/auth/api/loginApi.js b/src/lib/auth/api/loginApi.js index 4782680c..e393309c 100644 --- a/src/lib/auth/api/loginApi.js +++ b/src/lib/auth/api/loginApi.js @@ -1,12 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' -const loginApi = async ({email, password}) => { - let result = await odooApi( - 'POST', - '/api/v1/user/login', - {email, password} - ) +const loginApi = async ({ email, password }) => { + let result = await odooApi('POST', '/api/v1/user/login', { email, password }) return result } -export default loginApi
\ No newline at end of file +export default loginApi diff --git a/src/lib/auth/components/Login.jsx b/src/lib/auth/components/Login.jsx index acb6e8c3..971188a2 100644 --- a/src/lib/auth/components/Login.jsx +++ b/src/lib/auth/components/Login.jsx @@ -1,18 +1,18 @@ -import Image from "next/image" -import IndoteknikLogo from "@/images/logo.png" -import Link from "@/core/components/elements/Link/Link" -import { useState } from "react" -import loginApi from "../api/loginApi" -import { useRouter } from "next/router" -import Alert from "@/core/components/elements/Alert/Alert" -import { setAuth } from "@/core/utils/auth" +import Image from 'next/image' +import IndoteknikLogo from '@/images/logo.png' +import Link from '@/core/components/elements/Link/Link' +import { useState } from 'react' +import loginApi from '../api/loginApi' +import { useRouter } from 'next/router' +import Alert from '@/core/components/elements/Alert/Alert' +import { setAuth } from '@/core/utils/auth' const Login = () => { const router = useRouter() - const [ email, setEmail ] = useState('') - const [ password, setPassword ] = useState('') - const [ isLoading, setIsLoading ] = useState(false) - const [ alert, setAlert ] = useState(null) + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [isLoading, setIsLoading] = useState(false) + const [alert, setAlert] = useState(null) const handleSubmit = async (e) => { e.preventDefault() @@ -36,8 +36,10 @@ const Login = () => { setAlert({ children: ( <> - Email belum diaktivasi, - <Link className="text-gray-900" href={`/activate?email=${email}`}>aktivasi sekarang</Link> + Email belum diaktivasi, + <Link className='text-gray-900' href={`/activate?email=${email}`}> + aktivasi sekarang + </Link> </> ), type: 'info' @@ -47,53 +49,58 @@ 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} /> + <div className='p-6 pt-10 flex flex-col items-center'> + <Link href='/'> + <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.children } + <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.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 - type="email" - id="email" - className="form-input w-full mt-3" + <label htmlFor='email'>Alamat Email</label> + <input + type='email' + id='email' + className='form-input w-full mt-3' value={email} onChange={(e) => setEmail(e.target.value)} - placeholder="contoh@email.com" + placeholder='contoh@email.com' /> </div> <div> - <label htmlFor="password">Kata Sandi</label> - <input - type="password" - id="password" - className="form-input w-full mt-3" + <label htmlFor='password'>Kata Sandi</label> + <input + type='password' + id='password' + className='form-input w-full mt-3' value={password} onChange={(e) => setPassword(e.target.value)} - placeholder="••••••••••••" + placeholder='••••••••••••' /> </div> - <button - type="submit" - className="btn-solid-red w-full mt-2" + <button + type='submit' + className='btn-solid-red w-full mt-2' disabled={!email || !password || isLoading} > - { !isLoading ? 'Masuk' : 'Loading...'} + {!isLoading ? 'Masuk' : 'Loading...'} </button> </form> - <p className="text-gray_r-11 mt-4">Belum punya akun Indoteknik? <Link href="/register" className="inline">Daftar</Link></p> + <p className='text-gray_r-11 mt-4'> + Belum punya akun Indoteknik?{' '} + <Link href='/register' className='inline'> + Daftar + </Link> + </p> </div> ) } -export default Login
\ No newline at end of file +export default Login diff --git a/src/lib/brand/api/BrandApi.js b/src/lib/brand/api/BrandApi.js index 15634cc4..79801774 100644 --- a/src/lib/brand/api/BrandApi.js +++ b/src/lib/brand/api/BrandApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const BrandApi = async ({ id }) => { const dataBrand = await odooApi('GET', `/api/v1/manufacture/${id}`) return dataBrand } -export default BrandApi
\ No newline at end of file +export default BrandApi diff --git a/src/lib/brand/components/Brand.jsx b/src/lib/brand/components/Brand.jsx index c1215976..c338c4c4 100644 --- a/src/lib/brand/components/Brand.jsx +++ b/src/lib/brand/components/Brand.jsx @@ -1,13 +1,13 @@ -import useBrand from "../hooks/useBrand" -import Image from "@/core/components/elements/Image/Image" +import useBrand from '../hooks/useBrand' +import Image from '@/core/components/elements/Image/Image' -import { Swiper, SwiperSlide } from "swiper/react" -import { Pagination, Autoplay } from "swiper" -import "swiper/css" -import "swiper/css/pagination" -import "swiper/css/autoplay" -import Divider from "@/core/components/elements/Divider/Divider" -import ImageSkeleton from "@/core/components/elements/Skeleton/ImageSkeleton" +import { Swiper, SwiperSlide } from 'swiper/react' +import { Pagination, Autoplay } from 'swiper' +import 'swiper/css' +import 'swiper/css/pagination' +import 'swiper/css/autoplay' +import Divider from '@/core/components/elements/Divider/Divider' +import ImageSkeleton from '@/core/components/elements/Skeleton/ImageSkeleton' const swiperBanner = { pagination: { dynamicBullets: true }, @@ -20,51 +20,51 @@ const swiperBanner = { const Brand = ({ id }) => { const { brand } = useBrand({ id }) - + return ( <> - <div className="min-h-[150px]"> - { brand.isLoading && <ImageSkeleton /> } - { brand.data && ( + <div className='min-h-[150px]'> + {brand.isLoading && <ImageSkeleton />} + {brand.data && ( <> <Swiper slidesPerView={1} - pagination={swiperBanner.pagination} + pagination={swiperBanner.pagination} modules={swiperBanner.modules} autoplay={swiperBanner.autoplay} - className="border-b border-gray_r-6" + className='border-b border-gray_r-6' > - { brand.data?.banners?.map((banner, index) => ( + {brand.data?.banners?.map((banner, index) => ( <SwiperSlide key={index}> - <Image + <Image src={banner} alt={`Brand ${brand.data?.name} - Indoteknik`} - className="w-full h-auto" + className='w-full h-auto' /> </SwiperSlide> - )) } + ))} </Swiper> - <div className="p-4"> - <div className="text-caption-1 text-gray_r-11 mb-2">Produk dari brand:</div> - { brand?.data?.logo && ( - <Image - src={brand?.data?.logo} - alt={brand?.data?.name} - className="w-32 p-2 border borde-gray_r-6 rounded" + <div className='p-4'> + <div className='text-caption-1 text-gray_r-11 mb-2'>Produk dari brand:</div> + {brand?.data?.logo && ( + <Image + src={brand?.data?.logo} + alt={brand?.data?.name} + className='w-32 p-2 border borde-gray_r-6 rounded' /> - ) } - { !brand?.data?.logo && ( - <div className="bg-red_r-10 text-white text-center text-caption-1 py-2 px-4 rounded w-fit"> - { brand?.data?.name } + )} + {!brand?.data?.logo && ( + <div className='bg-red_r-10 text-white text-center text-caption-1 py-2 px-4 rounded w-fit'> + {brand?.data?.name} </div> - ) } + )} </div> </> - ) } + )} </div> <Divider /> </> ) } -export default Brand
\ No newline at end of file +export default Brand diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx index 8783010e..0dbdc075 100644 --- a/src/lib/brand/components/BrandCard.jsx +++ b/src/lib/brand/components/BrandCard.jsx @@ -1,20 +1,16 @@ -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import { createSlug } from "@/core/utils/slug" +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import { createSlug } from '@/core/utils/slug' const BrandCard = ({ brand }) => { return ( - <Link - href={createSlug('/shop/brands/', brand.name, brand.id)} - className="py-1 px-2 rounded border border-gray_r-6" + <Link + 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> ) } -export default BrandCard
\ No newline at end of file +export default BrandCard diff --git a/src/lib/brand/hooks/useBrand.js b/src/lib/brand/hooks/useBrand.js index be42a44c..3ba65a97 100644 --- a/src/lib/brand/hooks/useBrand.js +++ b/src/lib/brand/hooks/useBrand.js @@ -1,5 +1,5 @@ -import { useQuery } from "react-query" -import BrandApi from "../api/BrandApi" +import { useQuery } from 'react-query' +import BrandApi from '../api/BrandApi' const useBrand = ({ id }) => { const fetchBrand = async () => await BrandApi({ id }) @@ -10,4 +10,4 @@ const useBrand = ({ id }) => { } } -export default useBrand
\ No newline at end of file +export default useBrand diff --git a/src/lib/cart/api/CartApi.js b/src/lib/cart/api/CartApi.js index 9a5b5053..33b61891 100644 --- a/src/lib/cart/api/CartApi.js +++ b/src/lib/cart/api/CartApi.js @@ -1,4 +1,4 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const CartApi = async ({ variantIds }) => { if (variantIds) { @@ -8,4 +8,4 @@ const CartApi = async ({ variantIds }) => { return null } -export default CartApi
\ No newline at end of file +export default CartApi diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx index e7606582..df74bed6 100644 --- a/src/lib/cart/components/Cart.jsx +++ b/src/lib/cart/components/Cart.jsx @@ -1,26 +1,26 @@ -import Link from "@/core/components/elements/Link/Link" -import useCart from "../hooks/useCart" -import Image from "@/core/components/elements/Image/Image" -import currencyFormat from "@/core/utils/currencyFormat" -import { useEffect, useState } from "react" -import { deleteItemCart, getItemCart, updateItemCart } from "@/core/utils/cart" -import { CheckIcon, RectangleGroupIcon, TrashIcon } from "@heroicons/react/24/outline" -import { createSlug } from "@/core/utils/slug" -import { useRouter } from "next/router" -import BottomPopup from "@/core/components/elements/Popup/BottomPopup" -import { toast } from "react-hot-toast" -import Spinner from "@/core/components/elements/Spinner/Spinner" +import Link from '@/core/components/elements/Link/Link' +import useCart from '../hooks/useCart' +import Image from '@/core/components/elements/Image/Image' +import currencyFormat from '@/core/utils/currencyFormat' +import { useEffect, useState } from 'react' +import { deleteItemCart, getItemCart, updateItemCart } from '@/core/utils/cart' +import { CheckIcon, RectangleGroupIcon, TrashIcon } from '@heroicons/react/24/outline' +import { createSlug } from '@/core/utils/slug' +import { useRouter } from 'next/router' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import { toast } from 'react-hot-toast' +import Spinner from '@/core/components/elements/Spinner/Spinner' const Cart = () => { const router = useRouter() - const [ products, setProducts ] = useState(null) + const [products, setProducts] = useState(null) const { cart } = useCart({ enabled: !products }) - const [ totalPriceBeforeTax, setTotalPriceBeforeTax ] = useState(0) - const [ totalTaxAmount, setTotalTaxAmount ] = useState(0) - const [ totalDiscountAmount, setTotalDiscountAmount ] = useState(0) + const [totalPriceBeforeTax, setTotalPriceBeforeTax] = useState(0) + const [totalTaxAmount, setTotalTaxAmount] = useState(0) + const [totalDiscountAmount, setTotalDiscountAmount] = useState(0) - const [ deleteConfirmation, setDeleteConfirmation ] = useState(null) + const [deleteConfirmation, setDeleteConfirmation] = useState(null) useEffect(() => { if (cart.data && !products) { @@ -38,7 +38,7 @@ const Cart = () => { }, [cart, products]) useEffect(() => { - if (!products) return + if (!products) return let calculateTotalPriceBeforeTax = 0 let calculateTotalTaxAmount = 0 @@ -50,12 +50,13 @@ const Cart = () => { quantity: product.quantity, selected: product.selected }) - + if (!product.selected) continue - let priceBeforeTax = product.price.price / 1.11 + let priceBeforeTax = product.price.price / 1.11 calculateTotalPriceBeforeTax += priceBeforeTax * product.quantity calculateTotalTaxAmount += (product.price.price - priceBeforeTax) * product.quantity - calculateTotalDiscountAmount += (product.price.price - product.price.priceDiscount) * product.quantity + calculateTotalDiscountAmount += + (product.price.price - product.price.priceDiscount) * product.quantity } setTotalPriceBeforeTax(calculateTotalPriceBeforeTax) setTotalTaxAmount(calculateTotalTaxAmount) @@ -75,7 +76,7 @@ const Cart = () => { quantity += value break case 'MINUS': - if ((quantity - value) < 1) return + if (quantity - value < 1) return quantity -= value break case 'BLUR': @@ -87,7 +88,7 @@ const Cart = () => { break } productsToUpdate[productIndex].quantity = quantity - setProducts([ ...productsToUpdate ]) + setProducts([...productsToUpdate]) } const toggleSelected = (productId) => { @@ -96,7 +97,7 @@ const Cart = () => { let productsToUpdate = products productsToUpdate[productIndex].selected = !productsToUpdate[productIndex].selected - setProducts([ ...productsToUpdate ]) + setProducts([...productsToUpdate]) } const selectedProduct = () => { @@ -111,124 +112,126 @@ const Cart = () => { setProducts([...productsToUpdate]) toast.success('Berhasil menghapus barang dari keranjang') } - + return ( - <div className="pt-6"> - <div className="flex justify-between mb-4 px-4"> - <h1 className="font-semibold">Daftar Produk Belanja</h1> - <Link href="/">Cari Produk Lain</Link> + <div className='pt-6'> + <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"> - { cart.isLoading && ( - <div className="flex justify-center my-4"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + <div className='flex flex-col gap-y-4 px-4'> + {cart.isLoading && ( + <div className='flex justify-center my-4'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> - ) } - { products?.map((product) => ( - <div key={product?.id} className="flex"> + )} + {products?.map((product) => ( + <div key={product?.id} className='flex'> <button - type="button" - className="flex items-center mr-2" + type='button' + className='flex items-center mr-2' onClick={() => toggleSelected(product.id)} > - { !product?.selected && ( - <div className="w-5 h-5 border border-gray_r-11 rounded" /> - ) } - { product?.selected && ( - <CheckIcon className="border bg-red_r-10 w-5 text-white" /> - ) } + {!product?.selected && <div className='w-5 h-5 border border-gray_r-11 rounded' />} + {product?.selected && <CheckIcon className='border bg-red_r-10 w-5 text-white' />} </button> - <Link - href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} - className="w-[30%] flex-shrink-0" + <Link + href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} + className='w-[30%] flex-shrink-0' > - <Image src={product?.parent?.image} alt={product?.name} className="object-contain object-center border border-gray_r-6 h-40 w-full rounded-md" /> + <Image + src={product?.parent?.image} + alt={product?.name} + 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"> - <Link - href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} - className="line-clamp-2 leading-6 !text-gray_r-12 font-normal" + <div className='flex-1 px-2 text-caption-1'> + <Link + href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} + className='line-clamp-2 leading-6 !text-gray_r-12 font-normal' > - { product?.parent?.name } + {product?.parent?.name} </Link> - <div className="text-gray_r-11 mt-1"> - { product?.code } {product?.attributes.length > 0 ? `| ${product?.attributes.join(', ')}` : ''} + <div className='text-gray_r-11 mt-1'> + {product?.code}{' '} + {product?.attributes.length > 0 ? `| ${product?.attributes.join(', ')}` : ''} </div> - { product?.price?.discountPercentage > 0 && ( - <div className="flex gap-x-1 items-center mt-3"> - <div className="text-gray_r-11 line-through text-caption-2"> + {product?.price?.discountPercentage > 0 && ( + <div className='flex gap-x-1 items-center mt-3'> + <div className='text-gray_r-11 line-through text-caption-2'> {currencyFormat(product?.price?.price)} </div> - <div className="badge-solid-red"> - {product?.price?.discountPercentage}% - </div> + <div className='badge-solid-red'>{product?.price?.discountPercentage}%</div> </div> - ) } - <div className="font-normal mt-1"> - { currencyFormat(product?.price?.priceDiscount) } + )} + <div className='font-normal mt-1'> + {currencyFormat(product?.price?.priceDiscount)} </div> - <div className="flex justify-between items-center mt-1"> - <div className="text-red_r-11 font-medium"> - { currencyFormat(product?.price?.priceDiscount * product?.quantity) } + <div className='flex justify-between items-center mt-1'> + <div className='text-red_r-11 font-medium'> + {currencyFormat(product?.price?.priceDiscount * product?.quantity)} </div> - <div className="flex gap-x-1"> - <button - type="button" - className="btn-light px-2 py-1" + <div className='flex gap-x-1'> + <button + type='button' + className='btn-light px-2 py-1' onClick={() => updateQuantity(1, product?.id, 'MINUS')} disabled={product?.quantity == 1} > - </button> - <input - className="form-input w-6 border-0 border-b rounded-none py-1 px-0 text-center" - type="number" - value={product?.quantity} + <input + className='form-input w-6 border-0 border-b rounded-none py-1 px-0 text-center' + type='number' + value={product?.quantity} onChange={(e) => updateQuantity(e.target.value, product?.id)} onBlur={(e) => updateQuantity(e.target.value, product?.id, 'BLUR')} /> - <button - type="button" - className="btn-light px-2 py-1" + <button + type='button' + className='btn-light px-2 py-1' onClick={() => updateQuantity(1, product?.id, 'PLUS')} > + </button> - <button - className="btn-red p-1 ml-1" + <button + className='btn-red p-1 ml-1' onClick={() => setDeleteConfirmation(product)} > - <TrashIcon className="w-4" /> + <TrashIcon className='w-4' /> </button> </div> </div> </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) : '-' } + <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> </div> - <div className="flex gap-x-3"> - <button - type="button" - className="btn-yellow flex-1" + <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" + <button + type='button' + className='btn-solid-red flex-1' disabled={selectedProduct().length == 0} onClick={() => router.push('/shop/checkout')} > @@ -240,22 +243,23 @@ const Cart = () => { <BottomPopup active={deleteConfirmation} close={() => setDeleteConfirmation(null)} - title="Hapus dari Keranjang" + title='Hapus dari Keranjang' > - <div className="leading-7 text-gray_r-12/80"> - Apakah anda yakin menghapus barang <span className="underline">{deleteConfirmation?.name}</span> dari keranjang? + <div className='leading-7 text-gray_r-12/80'> + Apakah anda yakin menghapus barang{' '} + <span className='underline'>{deleteConfirmation?.name}</span> dari keranjang? </div> - <div className="flex mt-6 gap-x-4"> - <button - className="btn-solid-red flex-1" - type="button" + <div className='flex mt-6 gap-x-4'> + <button + className='btn-solid-red flex-1' + type='button' onClick={() => deleteProduct(deleteConfirmation?.id)} > Ya, Hapus </button> - <button - className="btn-light flex-1" - type="button" + <button + className='btn-light flex-1' + type='button' onClick={() => setDeleteConfirmation(null)} > Batal @@ -266,4 +270,4 @@ const Cart = () => { ) } -export default Cart
\ No newline at end of file +export default Cart diff --git a/src/lib/cart/hooks/useCart.js b/src/lib/cart/hooks/useCart.js index 9eb01e74..bc1ea7ea 100644 --- a/src/lib/cart/hooks/useCart.js +++ b/src/lib/cart/hooks/useCart.js @@ -1,7 +1,7 @@ -import { getCart } from "@/core/utils/cart" -import { useQuery } from "react-query" -import _ from "lodash" -import CartApi from "../api/CartApi" +import { getCart } from '@/core/utils/cart' +import { useQuery } from 'react-query' +import _ from 'lodash' +import CartApi from '../api/CartApi' const useCart = ({ enabled }) => { const cart = getCart() @@ -14,4 +14,4 @@ const useCart = ({ enabled }) => { } } -export default useCart
\ No newline at end of file +export default useCart diff --git a/src/lib/home/api/categoryHomeApi.js b/src/lib/home/api/categoryHomeApi.js index efb31240..81909d7b 100644 --- a/src/lib/home/api/categoryHomeApi.js +++ b/src/lib/home/api/categoryHomeApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const categoryHomeIdApi = async ({ id }) => { const dataCategoryHomeId = await odooApi('GET', `/api/v1/categories_homepage?id=${id}`) return dataCategoryHomeId } -export default categoryHomeIdApi
\ No newline at end of file +export default categoryHomeIdApi diff --git a/src/lib/home/api/categoryHomeIdApi.js b/src/lib/home/api/categoryHomeIdApi.js index d5612195..6b820fd3 100644 --- a/src/lib/home/api/categoryHomeIdApi.js +++ b/src/lib/home/api/categoryHomeIdApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const categoryHomeIdApi = async () => { const dataCategoryHomeIds = await odooApi('GET', '/api/v1/categories_homepage/ids') return dataCategoryHomeIds } -export default categoryHomeIdApi
\ No newline at end of file +export default categoryHomeIdApi diff --git a/src/lib/home/api/heroBannerApi.js b/src/lib/home/api/heroBannerApi.js index 7ba84bc6..60a0702a 100644 --- a/src/lib/home/api/heroBannerApi.js +++ b/src/lib/home/api/heroBannerApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const heroBannerApi = async () => { const dataHeroBanners = await odooApi('GET', '/api/v1/banner?type=index-a-1') return dataHeroBanners } -export default heroBannerApi
\ No newline at end of file +export default heroBannerApi diff --git a/src/lib/home/api/popularProductApi.js b/src/lib/home/api/popularProductApi.js index d7adca83..5a6d3212 100644 --- a/src/lib/home/api/popularProductApi.js +++ b/src/lib/home/api/popularProductApi.js @@ -1,8 +1,10 @@ -import axios from "axios" +import axios from 'axios' const popularProductApi = async () => { - const dataPopularProducts = await axios(`${process.env.SELF_HOST}/api/shop/search?q=*&page=1&orderBy=popular`) + const dataPopularProducts = await axios( + `${process.env.SELF_HOST}/api/shop/search?q=*&page=1&orderBy=popular` + ) return dataPopularProducts.data.response } -export default popularProductApi
\ No newline at end of file +export default popularProductApi diff --git a/src/lib/home/api/preferredBrandApi.js b/src/lib/home/api/preferredBrandApi.js index f289f387..0e3200e0 100644 --- a/src/lib/home/api/preferredBrandApi.js +++ b/src/lib/home/api/preferredBrandApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const preferredBrandApi = async () => { const dataPreferredBrands = await odooApi('GET', '/api/v1/manufacture?level=prioritas') return dataPreferredBrands } -export default preferredBrandApi
\ No newline at end of file +export default preferredBrandApi diff --git a/src/lib/home/components/CategoryHome.jsx b/src/lib/home/components/CategoryHome.jsx index 0bca9846..ac43e2bc 100644 --- a/src/lib/home/components/CategoryHome.jsx +++ b/src/lib/home/components/CategoryHome.jsx @@ -1,14 +1,14 @@ -import ProductSlider from "@/lib/product/components/ProductSlider" -import useCategoryHome from "../hooks/useCategoryHome" -import PopularProductSkeleton from "./Skeleton/PopularProductSkeleton" +import ProductSlider from '@/lib/product/components/ProductSlider' +import useCategoryHome from '../hooks/useCategoryHome' +import PopularProductSkeleton from './Skeleton/PopularProductSkeleton' const CategoryHome = ({ id }) => { const { categoryHome } = useCategoryHome({ id }) - + return ( - <div className="p-4 relative bg-yellow_r-2"> - { categoryHome.data ? ( - <ProductSlider + <div className='p-4 relative bg-yellow_r-2'> + {categoryHome.data ? ( + <ProductSlider products={{ products: categoryHome.data?.[0].products, banner: { @@ -16,13 +16,15 @@ const CategoryHome = ({ id }) => { name: categoryHome.data?.[0].name, url: `/shop/search?category=${categoryHome.data?.[0].name}` } - }} + }} simpleTitle bannerMode /> - ) : <PopularProductSkeleton /> } + ) : ( + <PopularProductSkeleton /> + )} </div> ) } -export default CategoryHome
\ No newline at end of file +export default CategoryHome diff --git a/src/lib/home/components/CategoryHomeId.jsx b/src/lib/home/components/CategoryHomeId.jsx index 4cbbd1fc..c37a6af7 100644 --- a/src/lib/home/components/CategoryHomeId.jsx +++ b/src/lib/home/components/CategoryHomeId.jsx @@ -1,19 +1,19 @@ -import { LazyLoadComponent } from "react-lazy-load-image-component" -import useCategoryHomeId from "../hooks/useCategoryHomeId" -import CategoryHome from "./CategoryHome" +import { LazyLoadComponent } from 'react-lazy-load-image-component' +import useCategoryHomeId from '../hooks/useCategoryHomeId' +import CategoryHome from './CategoryHome' const CategoryHomeId = () => { const { categoryHomeIds } = useCategoryHomeId() return ( - <div className="flex flex-col gap-y-6"> - { categoryHomeIds.data?.map((id) => ( + <div className='flex flex-col gap-y-6'> + {categoryHomeIds.data?.map((id) => ( <LazyLoadComponent key={id}> <CategoryHome id={id} /> </LazyLoadComponent> - )) } + ))} </div> ) } -export default CategoryHomeId
\ No newline at end of file +export default CategoryHomeId diff --git a/src/lib/home/components/HeroBanner.jsx b/src/lib/home/components/HeroBanner.jsx index 604ca8ac..6f39ac50 100644 --- a/src/lib/home/components/HeroBanner.jsx +++ b/src/lib/home/components/HeroBanner.jsx @@ -1,13 +1,13 @@ -import ImageSkeleton from "@/core/components/elements/Skeleton/ImageSkeleton" -import useHeroBanner from "../hooks/useHeroBanner" -import Image from "@/core/components/elements/Image/Image" +import ImageSkeleton from '@/core/components/elements/Skeleton/ImageSkeleton' +import useHeroBanner from '../hooks/useHeroBanner' +import Image from '@/core/components/elements/Image/Image' // Swiper -import { Swiper, SwiperSlide } from "swiper/react" -import { Pagination, Autoplay } from "swiper" -import "swiper/css" -import "swiper/css/pagination" -import "swiper/css/autoplay" +import { Swiper, SwiperSlide } from 'swiper/react' +import { Pagination, Autoplay } from 'swiper' +import 'swiper/css' +import 'swiper/css/pagination' +import 'swiper/css/autoplay' const swiperBanner = { pagination: { dynamicBullets: true }, @@ -20,31 +20,27 @@ const swiperBanner = { const HeroBanner = () => { const { heroBanners } = useHeroBanner() - + return ( - <div className="min-h-[200px]"> - { heroBanners.isLoading && <ImageSkeleton /> } - { !heroBanners.isLoading && ( + <div className='min-h-[200px]'> + {heroBanners.isLoading && <ImageSkeleton />} + {!heroBanners.isLoading && ( <Swiper slidesPerView={1} - pagination={swiperBanner.pagination} + pagination={swiperBanner.pagination} modules={swiperBanner.modules} autoplay={swiperBanner.autoplay} - className="border-b border-gray_r-6" + className='border-b border-gray_r-6' > - { heroBanners.data?.map((banner, index) => ( + {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> - ) } + )} </div> ) } -export default HeroBanner
\ No newline at end of file +export default HeroBanner diff --git a/src/lib/home/components/PopularProduct.jsx b/src/lib/home/components/PopularProduct.jsx index 87e47218..7e222b0a 100644 --- a/src/lib/home/components/PopularProduct.jsx +++ b/src/lib/home/components/PopularProduct.jsx @@ -1,24 +1,19 @@ -import { Swiper, SwiperSlide } from "swiper/react" -import usePopularProduct from "../hooks/usePopularProduct" -import ProductCard from "@/lib/product/components/ProductCard" -import PopularProductSkeleton from "./Skeleton/PopularProductSkeleton" -import ProductSlider from "@/lib/product/components/ProductSlider" +import { Swiper, SwiperSlide } from 'swiper/react' +import usePopularProduct from '../hooks/usePopularProduct' +import ProductCard from '@/lib/product/components/ProductCard' +import PopularProductSkeleton from './Skeleton/PopularProductSkeleton' +import ProductSlider from '@/lib/product/components/ProductSlider' const PopularProduct = () => { const { popularProducts } = usePopularProduct() - + return ( - <div className="px-4"> - <div className="font-medium mb-4">Produk Populer</div> - { popularProducts.isLoading && <PopularProductSkeleton /> } - { !popularProducts.isLoading && ( - <ProductSlider - products={popularProducts.data} - simpleTitle - /> - ) } + <div className='px-4'> + <div className='font-medium mb-4'>Produk Populer</div> + {popularProducts.isLoading && <PopularProductSkeleton />} + {!popularProducts.isLoading && <ProductSlider products={popularProducts.data} simpleTitle />} </div> ) } -export default PopularProduct
\ No newline at end of file +export default PopularProduct diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index 3d3b1b69..de377031 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -1,30 +1,26 @@ -import { Swiper, SwiperSlide } from "swiper/react" -import usePreferredBrand from "../hooks/usePreferredBrand" -import PreferredBrandSkeleton from "./Skeleton/PreferredBrandSkeleton" -import BrandCard from "@/lib/brand/components/BrandCard" +import { Swiper, SwiperSlide } from 'swiper/react' +import usePreferredBrand from '../hooks/usePreferredBrand' +import PreferredBrandSkeleton from './Skeleton/PreferredBrandSkeleton' +import BrandCard from '@/lib/brand/components/BrandCard' const PreferredBrand = () => { const { preferredBrands } = usePreferredBrand() - + return ( - <div className="px-4"> - <div className="font-medium mb-4">Brand Pilihan</div> - { preferredBrands.isLoading && <PreferredBrandSkeleton /> } - { !preferredBrands.isLoading && ( - <Swiper - slidesPerView={3.5} - spaceBetween={8} - freeMode - > - { preferredBrands.data?.manufactures.map((brand) => ( + <div className='px-4'> + <div className='font-medium mb-4'>Brand Pilihan</div> + {preferredBrands.isLoading && <PreferredBrandSkeleton />} + {!preferredBrands.isLoading && ( + <Swiper slidesPerView={3.5} spaceBetween={8} freeMode> + {preferredBrands.data?.manufactures.map((brand) => ( <SwiperSlide key={brand.id}> <BrandCard brand={brand} /> </SwiperSlide> - )) } + ))} </Swiper> - ) } + )} </div> ) } -export default PreferredBrand
\ No newline at end of file +export default PreferredBrand diff --git a/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx b/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx index c5b0fcaa..18a1b3d3 100644 --- a/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx +++ b/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx @@ -1,10 +1,10 @@ -import ProductCardSkeleton from "@/core/components/elements/Skeleton/ProductCardSkeleton" +import ProductCardSkeleton from '@/core/components/elements/Skeleton/ProductCardSkeleton' const PopularProductSkeleton = () => ( - <div className="grid grid-cols-2 gap-x-3"> + <div className='grid grid-cols-2 gap-x-3'> <ProductCardSkeleton /> <ProductCardSkeleton /> </div> ) -export default PopularProductSkeleton
\ No newline at end of file +export default PopularProductSkeleton diff --git a/src/lib/home/components/Skeleton/PreferredBrandSkeleton.jsx b/src/lib/home/components/Skeleton/PreferredBrandSkeleton.jsx index 6bdd3c82..00589342 100644 --- a/src/lib/home/components/Skeleton/PreferredBrandSkeleton.jsx +++ b/src/lib/home/components/Skeleton/PreferredBrandSkeleton.jsx @@ -1,7 +1,7 @@ -import BrandSkeleton from "@/core/components/elements/Skeleton/BrandSkeleton" +import BrandSkeleton from '@/core/components/elements/Skeleton/BrandSkeleton' const PreferredBrandSkeleton = () => ( - <div className="grid grid-cols-4 gap-x-3"> + <div className='grid grid-cols-4 gap-x-3'> <BrandSkeleton /> <BrandSkeleton /> <BrandSkeleton /> @@ -9,4 +9,4 @@ const PreferredBrandSkeleton = () => ( </div> ) -export default PreferredBrandSkeleton
\ No newline at end of file +export default PreferredBrandSkeleton diff --git a/src/lib/home/hooks/useCategoryHome.js b/src/lib/home/hooks/useCategoryHome.js index 14ef2a0f..cfaa3d9c 100644 --- a/src/lib/home/hooks/useCategoryHome.js +++ b/src/lib/home/hooks/useCategoryHome.js @@ -1,13 +1,13 @@ -import categoryHomeApi from "../api/categoryHomeApi" -import { useQuery } from "react-query" +import categoryHomeApi from '../api/categoryHomeApi' +import { useQuery } from 'react-query' const useCategoryHome = ({ id }) => { const fetchCategoryHome = async () => await categoryHomeApi({ id }) - const { isLoading, data } = useQuery(`categoryHome-${id}`, fetchCategoryHome) - + const { isLoading, data } = useQuery(`categoryHome-${id}`, fetchCategoryHome) + return { categoryHome: { data, isLoading } } } -export default useCategoryHome
\ No newline at end of file +export default useCategoryHome diff --git a/src/lib/home/hooks/useCategoryHomeId.js b/src/lib/home/hooks/useCategoryHomeId.js index bb61b655..c6953db7 100644 --- a/src/lib/home/hooks/useCategoryHomeId.js +++ b/src/lib/home/hooks/useCategoryHomeId.js @@ -1,13 +1,13 @@ -import categoryHomeIdApi from "../api/categoryHomeIdApi" -import { useQuery } from "react-query" +import categoryHomeIdApi from '../api/categoryHomeIdApi' +import { useQuery } from 'react-query' const useCategoryHomeId = () => { const fetchCategoryHomeId = async () => await categoryHomeIdApi() - const { isLoading, data } = useQuery("categoryHomeId", fetchCategoryHomeId) - + const { isLoading, data } = useQuery('categoryHomeId', fetchCategoryHomeId) + return { categoryHomeIds: { data, isLoading } } } -export default useCategoryHomeId
\ No newline at end of file +export default useCategoryHomeId diff --git a/src/lib/home/hooks/useHeroBanner.js b/src/lib/home/hooks/useHeroBanner.js index a15dda60..5d2b0512 100644 --- a/src/lib/home/hooks/useHeroBanner.js +++ b/src/lib/home/hooks/useHeroBanner.js @@ -1,13 +1,13 @@ -import heroBannerApi from "../api/heroBannerApi" -import { useQuery } from "react-query" +import heroBannerApi from '../api/heroBannerApi' +import { useQuery } from 'react-query' const useHeroBanner = () => { const fetchHeroBanner = async () => await heroBannerApi() - const { isLoading, data } = useQuery("heroBanner", fetchHeroBanner) - + const { isLoading, data } = useQuery('heroBanner', fetchHeroBanner) + return { heroBanners: { data, isLoading } } } -export default useHeroBanner
\ No newline at end of file +export default useHeroBanner diff --git a/src/lib/home/hooks/usePopularProduct.js b/src/lib/home/hooks/usePopularProduct.js index f69c2f71..d0c34bb0 100644 --- a/src/lib/home/hooks/usePopularProduct.js +++ b/src/lib/home/hooks/usePopularProduct.js @@ -1,5 +1,5 @@ -import popularProductApi from "../api/popularProductApi" -import { useQuery } from "react-query" +import popularProductApi from '../api/popularProductApi' +import { useQuery } from 'react-query' const usePopularProduct = () => { const fetchPopularProduct = async () => await popularProductApi() @@ -10,4 +10,4 @@ const usePopularProduct = () => { } } -export default usePopularProduct
\ No newline at end of file +export default usePopularProduct diff --git a/src/lib/home/hooks/usePreferredBrand.js b/src/lib/home/hooks/usePreferredBrand.js index 4be9793e..e56d361f 100644 --- a/src/lib/home/hooks/usePreferredBrand.js +++ b/src/lib/home/hooks/usePreferredBrand.js @@ -1,5 +1,5 @@ -import preferredBrandApi from "../api/preferredBrandApi" -import { useQuery } from "react-query" +import preferredBrandApi from '../api/preferredBrandApi' +import { useQuery } from 'react-query' const usePreferredBrand = () => { const fetchPreferredBrand = async () => await preferredBrandApi() @@ -10,4 +10,4 @@ const usePreferredBrand = () => { } } -export default usePreferredBrand
\ No newline at end of file +export default usePreferredBrand diff --git a/src/lib/invoice/api/invoiceApi.js b/src/lib/invoice/api/invoiceApi.js index f9bacf8e..056df6c6 100644 --- a/src/lib/invoice/api/invoiceApi.js +++ b/src/lib/invoice/api/invoiceApi.js @@ -1,5 +1,5 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const invoiceApi = async ({ id }) => { const auth = getAuth() @@ -7,4 +7,4 @@ const invoiceApi = async ({ id }) => { return dataInvoice } -export default invoiceApi
\ No newline at end of file +export default invoiceApi diff --git a/src/lib/invoice/api/invoicesApi.js b/src/lib/invoice/api/invoicesApi.js index 4e842f55..622fe6ee 100644 --- a/src/lib/invoice/api/invoicesApi.js +++ b/src/lib/invoice/api/invoicesApi.js @@ -1,5 +1,5 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const invoicesApi = async ({ query }) => { const auth = getAuth() @@ -7,4 +7,4 @@ const invoicesApi = async ({ query }) => { return dataInvoices } -export default invoicesApi
\ No newline at end of file +export default invoicesApi diff --git a/src/lib/invoice/components/Invoice.jsx b/src/lib/invoice/components/Invoice.jsx index aee4a498..eaf7b7e0 100644 --- a/src/lib/invoice/components/Invoice.jsx +++ b/src/lib/invoice/components/Invoice.jsx @@ -1,17 +1,17 @@ -import Spinner from "@/core/components/elements/Spinner/Spinner" -import useInvoice from "../hooks/useInvoice" -import { downloadInvoice, downloadTaxInvoice } from "../utils/invoices" -import Divider from "@/core/components/elements/Divider/Divider" -import VariantGroupCard from "@/lib/variant/components/VariantGroupCard" -import currencyFormat from "@/core/utils/currencyFormat" +import Spinner from '@/core/components/elements/Spinner/Spinner' +import useInvoice from '../hooks/useInvoice' +import { downloadInvoice, downloadTaxInvoice } from '../utils/invoices' +import Divider from '@/core/components/elements/Divider/Divider' +import VariantGroupCard from '@/lib/variant/components/VariantGroupCard' +import currencyFormat from '@/core/utils/currencyFormat' const Invoice = ({ id }) => { const { invoice } = useInvoice({ id }) if (invoice.isLoading) { return ( - <div className="flex justify-center my-6"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + <div className='flex justify-center my-6'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> ) } @@ -24,103 +24,84 @@ const Invoice = ({ id }) => { if (address?.city?.name) fullAddress.push(address.city.name) fullAddress = fullAddress.join(', ') - return invoice.data?.name && ( - <> - <div className="flex flex-col gap-y-4 p-4"> - <DescriptionRow label="No Invoice"> - { invoice.data?.name } - </DescriptionRow> - <DescriptionRow label="Status Transaksi"> - { invoice.data?.amountResidual > 0 ? ( - <span className="badge-solid-red">Belum Lunas</span> + return ( + invoice.data?.name && ( + <> + <div className='flex flex-col gap-y-4 p-4'> + <DescriptionRow label='No Invoice'>{invoice.data?.name}</DescriptionRow> + <DescriptionRow label='Status Transaksi'> + {invoice.data?.amountResidual > 0 ? ( + <span className='badge-solid-red'>Belum Lunas</span> ) : ( - <span className="badge-solid-green">Lunas</span> - ) } - </DescriptionRow> - <DescriptionRow label="Purchase Order"> - { invoice.data?.purchaseOrderName || '-' } - </DescriptionRow> - <DescriptionRow label="Ketentuan Pembayaran"> - { invoice.data?.paymentTerm } - </DescriptionRow> - { invoice.data?.amountResidual > 0 && invoice.invoiceDate != invoice.invoiceDateDue && ( - <DescriptionRow label="Tanggal Jatuh Tempo"> - { invoice.data?.invoiceDateDue } + <span className='badge-solid-green'>Lunas</span> + )} </DescriptionRow> - ) } - <DescriptionRow label="Nama Sales"> - { invoice.data?.sales } - </DescriptionRow> - <DescriptionRow label="Tanggal Invoice"> - { invoice.data?.invoiceDate } - </DescriptionRow> - <div className="flex items-center"> - <p className="text-gray_r-11 leading-none">Invoice</p> - <button - type="button" - className="btn-light py-1.5 px-3 ml-auto" - onClick={() => downloadInvoice(invoice.data)} - > - Download - </button> - </div> - <div className="flex items-center"> - <p className="text-gray_r-11 leading-none">Faktur Pajak</p> - <button - type="button" - className="btn-light py-1.5 px-3 ml-auto" - onClick={() => downloadTaxInvoice(invoice.data)} - disabled={!invoice.data?.efaktur} - > - Download - </button> + <DescriptionRow label='Purchase Order'> + {invoice.data?.purchaseOrderName || '-'} + </DescriptionRow> + <DescriptionRow label='Ketentuan Pembayaran'>{invoice.data?.paymentTerm}</DescriptionRow> + {invoice.data?.amountResidual > 0 && invoice.invoiceDate != invoice.invoiceDateDue && ( + <DescriptionRow label='Tanggal Jatuh Tempo'> + {invoice.data?.invoiceDateDue} + </DescriptionRow> + )} + <DescriptionRow label='Nama Sales'>{invoice.data?.sales}</DescriptionRow> + <DescriptionRow label='Tanggal Invoice'>{invoice.data?.invoiceDate}</DescriptionRow> + <div className='flex items-center'> + <p className='text-gray_r-11 leading-none'>Invoice</p> + <button + type='button' + className='btn-light py-1.5 px-3 ml-auto' + onClick={() => downloadInvoice(invoice.data)} + > + Download + </button> + </div> + <div className='flex items-center'> + <p className='text-gray_r-11 leading-none'>Faktur Pajak</p> + <button + type='button' + className='btn-light py-1.5 px-3 ml-auto' + onClick={() => downloadTaxInvoice(invoice.data)} + disabled={!invoice.data?.efaktur} + > + Download + </button> + </div> </div> - </div> - <Divider /> + <Divider /> - <div className="p-4 font-medium"> - Detail Penagihan - </div> - - <div className="flex flex-col gap-y-4 p-4 border-t border-gray_r-6"> - <DescriptionRow label="Nama"> - { address?.name } - </DescriptionRow> - <DescriptionRow label="Email"> - { address?.email || '-' } - </DescriptionRow> - <DescriptionRow label="No Telepon"> - { address?.mobile || '-' } - </DescriptionRow> - <DescriptionRow label="Alamat"> - { fullAddress } - </DescriptionRow> - </div> + <div className='p-4 font-medium'>Detail Penagihan</div> - <Divider /> + <div className='flex flex-col gap-y-4 p-4 border-t border-gray_r-6'> + <DescriptionRow label='Nama'>{address?.name}</DescriptionRow> + <DescriptionRow label='Email'>{address?.email || '-'}</DescriptionRow> + <DescriptionRow label='No Telepon'>{address?.mobile || '-'}</DescriptionRow> + <DescriptionRow label='Alamat'>{fullAddress}</DescriptionRow> + </div> + + <Divider /> - <div className="font-medium p-4">Detail Produk</div> + <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 - /> - <div className="flex justify-between mt-3 font-medium"> - <p>Total Belanja</p> - <p>{ currencyFormat(invoice.data?.amountTotal) }</p> + <div className='p-4 pt-0 flex flex-col gap-y-3'> + <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> + </div> </div> - </div> - </> + </> + ) ) } const DescriptionRow = ({ children, label }) => ( - <div className="grid grid-cols-2"> - <span className="text-gray_r-11">{ label }</span> - <span className="text-right">{ children }</span> + <div className='grid grid-cols-2'> + <span className='text-gray_r-11'>{label}</span> + <span className='text-right'>{children}</span> </div> ) -export default Invoice
\ No newline at end of file +export default Invoice diff --git a/src/lib/invoice/components/Invoices.jsx b/src/lib/invoice/components/Invoices.jsx index 37944e33..81521785 100644 --- a/src/lib/invoice/components/Invoices.jsx +++ b/src/lib/invoice/components/Invoices.jsx @@ -1,23 +1,25 @@ -import { CheckIcon, ClockIcon, EllipsisVerticalIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline" -import { toQuery } from "lodash-contrib" -import _ from "lodash" -import { useRouter } from "next/router" -import { useState } from "react" -import useInvoices from "../hooks/useInvoices" -import Spinner from "@/core/components/elements/Spinner/Spinner" -import Alert from "@/core/components/elements/Alert/Alert" -import Pagination from "@/core/components/elements/Pagination/Pagination" -import Link from "@/core/components/elements/Link/Link" -import currencyFormat from "@/core/utils/currencyFormat" -import BottomPopup from "@/core/components/elements/Popup/BottomPopup" -import { downloadInvoice, downloadTaxInvoice } from "../utils/invoices" +import { + CheckIcon, + ClockIcon, + EllipsisVerticalIcon, + MagnifyingGlassIcon +} from '@heroicons/react/24/outline' +import { toQuery } from 'lodash-contrib' +import _ from 'lodash' +import { useRouter } from 'next/router' +import { useState } from 'react' +import useInvoices from '../hooks/useInvoices' +import Spinner from '@/core/components/elements/Spinner/Spinner' +import Alert from '@/core/components/elements/Alert/Alert' +import Pagination from '@/core/components/elements/Pagination/Pagination' +import Link from '@/core/components/elements/Link/Link' +import currencyFormat from '@/core/utils/currencyFormat' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import { downloadInvoice, downloadTaxInvoice } from '../utils/invoices' const Invoices = () => { const router = useRouter() - const { - q = '', - page = 1 - } = router.query + const { q = '', page = 1 } = router.query const limit = 10 @@ -28,8 +30,8 @@ const Invoices = () => { } const { invoices } = useInvoices({ query }) - const [ inputQuery, setInputQuery ] = useState(q) - const [ toOthers, setToOthers ] = useState(null) + const [inputQuery, setInputQuery] = useState(q) + const [toOthers, setToOthers] = useState(null) const pageCount = Math.ceil(invoices?.data?.saleOrderTotal / limit) let pageQuery = _.omit(query, ['limit', 'offset']) @@ -39,112 +41,111 @@ const Invoices = () => { const handleSubmit = (e) => { e.preventDefault() router.push(`/my/invoices?q=${inputQuery}`) - } + } return ( - <div className="p-4 flex flex-col gap-y-4"> - <form className="flex gap-x-3" onSubmit={handleSubmit}> - <input - type="text" - className="form-input" - placeholder="Cari Invoice..." + <div className='p-4 flex flex-col gap-y-4'> + <form className='flex gap-x-3' onSubmit={handleSubmit}> + <input + type='text' + className='form-input' + placeholder='Cari Invoice...' value={inputQuery} onChange={(e) => setInputQuery(e.target.value)} /> - <button - className="btn-light bg-transparent px-3" - type="submit" - > - <MagnifyingGlassIcon className="w-6" /> + <button className='btn-light bg-transparent px-3' type='submit'> + <MagnifyingGlassIcon className='w-6' /> </button> </form> - { invoices.isLoading && ( - <div className="flex justify-center my-4"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + {invoices.isLoading && ( + <div className='flex justify-center my-4'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> - ) } + )} - { !invoices.isLoading && invoices.data?.invoices?.length === 0 && ( - <Alert type="info" className="text-center"> + {!invoices.isLoading && invoices.data?.invoices?.length === 0 && ( + <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="grid grid-cols-2"> + {invoices.data?.invoices?.map((invoice, 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> - <h2 className="text-red_r-11 mt-1">{ invoice.name }</h2> + <span className='text-caption-2 text-gray_r-11'>No. Invoice</span> + <h2 className='text-red_r-11 mt-1'>{invoice.name}</h2> </Link> - <div className="flex gap-x-1 justify-end"> - { invoice.amountResidual > 0 ? ( - <div className="badge-solid-red h-fit ml-auto">Belum Lunas</div> - ) : ( - <div className="badge-solid-green h-fit ml-auto">Lunas</div> - ) } - <EllipsisVerticalIcon className="w-5 h-5" onClick={() => setToOthers(invoice)} /> + <div className='flex gap-x-1 justify-end'> + {invoice.amountResidual > 0 ? ( + <div className='badge-solid-red h-fit ml-auto'>Belum Lunas</div> + ) : ( + <div className='badge-solid-green h-fit ml-auto'>Lunas</div> + )} + <EllipsisVerticalIcon className='w-5 h-5' onClick={() => setToOthers(invoice)} /> </div> </div> <Link href={`/my/invoice/${invoice.id}`}> - <div className="grid grid-cols-2 text-caption-2 text-gray_r-11 mt-2 font-normal"> - <p> - { invoice.invoiceDate } - </p> - <p className="text-right"> - { invoice.paymentTerm } - </p> + <div className='grid grid-cols-2 text-caption-2 text-gray_r-11 mt-2 font-normal'> + <p>{invoice.invoiceDate}</p> + <p className='text-right'>{invoice.paymentTerm}</p> </div> - <hr className="my-3"/> - <div className="grid grid-cols-2"> + <hr className='my-3' /> + <div className='grid grid-cols-2'> <div> - <span className="text-caption-2 text-gray_r-11">No. Purchase Order</span> - <p className="mt-1 font-medium text-gray_r-12">{ invoice.purchaseOrderName || '-' }</p> + <span className='text-caption-2 text-gray_r-11'>No. Purchase Order</span> + <p className='mt-1 font-medium text-gray_r-12'> + {invoice.purchaseOrderName || '-'} + </p> </div> - <div className="text-right"> - <span className="text-caption-2 text-gray_r-11">Total Invoice</span> - <p className="mt-1 font-medium text-gray_r-12">{ currencyFormat(invoice.amountTotal) }</p> + <div className='text-right'> + <span className='text-caption-2 text-gray_r-11'>Total Invoice</span> + <p className='mt-1 font-medium text-gray_r-12'> + {currencyFormat(invoice.amountTotal)} + </p> </div> </div> </Link> - { invoice.efaktur ? ( - <div className="badge-green h-fit mt-3 ml-auto flex items-center gap-x-0.5"> - <CheckIcon className="w-4 stroke-2" /> + {invoice.efaktur ? ( + <div className='badge-green h-fit mt-3 ml-auto flex items-center gap-x-0.5'> + <CheckIcon className='w-4 stroke-2' /> Faktur Pajak </div> - ) : ( - <div className="badge-red h-fit mt-3 ml-auto flex items-center gap-x-0.5"> - <ClockIcon className="w-4 stroke-2" /> + ) : ( + <div className='badge-red h-fit mt-3 ml-auto flex items-center gap-x-0.5'> + <ClockIcon className='w-4 stroke-2' /> Faktur Pajak </div> - ) } + )} </div> - )) } + ))} <Pagination pageCount={pageCount} - currentPage={parseInt(page)} + currentPage={parseInt(page)} url={`/my/invoices${pageQuery}`} - className="mt-2 mb-2" + className='mt-2 mb-2' /> - <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" - onClick={() => { downloadInvoice(toOthers); 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' + onClick={() => { + downloadInvoice(toOthers) + setToOthers(null) + }} > Download Invoice </button> - <button - className="text-left disabled:opacity-60" + <button + className='text-left disabled:opacity-60' disabled={!toOthers?.efaktur} - onClick={() => { downloadTaxInvoice(toOthers); setToOthers(null) }} + onClick={() => { + downloadTaxInvoice(toOthers) + setToOthers(null) + }} > Download Faktur Pajak </button> @@ -154,4 +155,4 @@ const Invoices = () => { ) } -export default Invoices
\ No newline at end of file +export default Invoices diff --git a/src/lib/invoice/hooks/useInvoice.js b/src/lib/invoice/hooks/useInvoice.js index 0e612f2f..2de5e91e 100644 --- a/src/lib/invoice/hooks/useInvoice.js +++ b/src/lib/invoice/hooks/useInvoice.js @@ -1,5 +1,5 @@ -import { useQuery } from "react-query" -import invoiceApi from "../api/invoiceApi" +import { useQuery } from 'react-query' +import invoiceApi from '../api/invoiceApi' const useInvoice = ({ id }) => { const fetchInvoice = async () => await invoiceApi({ id }) @@ -10,4 +10,4 @@ const useInvoice = ({ id }) => { } } -export default useInvoice
\ No newline at end of file +export default useInvoice diff --git a/src/lib/invoice/hooks/useInvoices.js b/src/lib/invoice/hooks/useInvoices.js index 7bcdc952..061626e4 100644 --- a/src/lib/invoice/hooks/useInvoices.js +++ b/src/lib/invoice/hooks/useInvoices.js @@ -1,6 +1,6 @@ -import { useQuery } from "react-query" -import invoicesApi from "../api/invoicesApi" -import _ from "lodash-contrib" +import { useQuery } from 'react-query' +import invoicesApi from '../api/invoicesApi' +import _ from 'lodash-contrib' const useInvoices = ({ query }) => { const queryString = _.toQuery(query) @@ -12,4 +12,4 @@ const useInvoices = ({ query }) => { } } -export default useInvoices
\ No newline at end of file +export default useInvoices diff --git a/src/lib/invoice/utils/invoices.js b/src/lib/invoice/utils/invoices.js index c152191d..221e53cf 100644 --- a/src/lib/invoice/utils/invoices.js +++ b/src/lib/invoice/utils/invoices.js @@ -8,7 +8,4 @@ const downloadTaxInvoice = (invoice) => { window.open(url, 'download') } -export { - downloadInvoice, - downloadTaxInvoice -}
\ No newline at end of file +export { downloadInvoice, downloadTaxInvoice } diff --git a/src/lib/product/api/productApi.js b/src/lib/product/api/productApi.js index a543f086..6fe8901e 100644 --- a/src/lib/product/api/productApi.js +++ b/src/lib/product/api/productApi.js @@ -1,8 +1,8 @@ -import odooApi from "@/core/api/odooApi" +import odooApi from '@/core/api/odooApi' const productApi = async ({ id }) => { const dataProduct = await odooApi('GET', `/api/v1/product/${id}`) return dataProduct } -export default productApi
\ No newline at end of file +export default productApi diff --git a/src/lib/product/api/productSearchApi.js b/src/lib/product/api/productSearchApi.js index 86b2914f..b9acd94b 100644 --- a/src/lib/product/api/productSearchApi.js +++ b/src/lib/product/api/productSearchApi.js @@ -1,9 +1,9 @@ -import _ from "lodash-contrib" -import axios from "axios" +import _ from 'lodash-contrib' +import axios from 'axios' const productSearchApi = async ({ query }) => { const dataProductSearch = await axios(`${process.env.SELF_HOST}/api/shop/search?${query}`) return dataProductSearch.data } -export default productSearchApi
\ No newline at end of file +export default productSearchApi diff --git a/src/lib/product/api/productSimilarApi.js b/src/lib/product/api/productSimilarApi.js index 1449d9ca..7142fab4 100644 --- a/src/lib/product/api/productSimilarApi.js +++ b/src/lib/product/api/productSimilarApi.js @@ -1,8 +1,10 @@ -import axios from "axios" +import axios from 'axios' const productSimilarApi = async ({ query }) => { - const dataProductSimilar = await axios(`${process.env.SELF_HOST}/api/shop/search?q=${query}&page=1&orderBy=popular`) + const dataProductSimilar = await axios( + `${process.env.SELF_HOST}/api/shop/search?q=${query}&page=1&orderBy=popular` + ) return dataProductSimilar.data.response } -export default productSimilarApi
\ No newline at end of file +export default productSimilarApi diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 92f4e37d..2181c38e 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -1,41 +1,40 @@ -import Badge from "@/core/components/elements/Badge/Badge" -import Divider from "@/core/components/elements/Divider/Divider" -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import currencyFormat from "@/core/utils/currencyFormat" -import { useEffect, useState } from "react" -import Select from "react-select" -import ProductSimilar from "./ProductSimilar" -import LazyLoad from "react-lazy-load" -import { toast } from "react-hot-toast" -import { updateItemCart } from "@/core/utils/cart" +import Badge from '@/core/components/elements/Badge/Badge' +import Divider from '@/core/components/elements/Divider/Divider' +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import currencyFormat from '@/core/utils/currencyFormat' +import { useEffect, useState } from 'react' +import Select from 'react-select' +import ProductSimilar from './ProductSimilar' +import LazyLoad from 'react-lazy-load' +import { toast } from 'react-hot-toast' +import { updateItemCart } from '@/core/utils/cart' const informationTabOptions = [ { value: 'specification', label: 'Spesifikasi' }, { value: 'description', label: 'Deskripsi' }, - { value: 'important', label: 'Info Penting' }, + { value: 'important', label: 'Info Penting' } ] const Product = ({ product }) => { - const [ quantity, setQuantity ] = useState('1') - const [ selectedVariant, setSelectedVariant ] = useState(null) - const [ informationTab, setInformationTab ] = useState(null) + const [quantity, setQuantity] = useState('1') + const [selectedVariant, setSelectedVariant] = useState(null) + const [informationTab, setInformationTab] = useState(null) - const [ activeVariant, setActiveVariant ] = useState({ + const [activeVariant, setActiveVariant] = useState({ id: product.id, code: product.code, name: product.name, price: product.lowestPrice, stock: product.stockTotal, - weight: product.weight, + weight: product.weight }) - + const variantOptions = product.variants?.map((variant) => ({ value: variant.id, - label: - (variant.code ? `[${variant.code}] ` : '') - + - (variant.attributes.length > 0 ? variant.attributes.join(', ') : product.name) + label: + (variant.code ? `[${variant.code}] ` : '') + + (variant.attributes.length > 0 ? variant.attributes.join(', ') : product.name) })) useEffect(() => { @@ -46,9 +45,10 @@ const Product = ({ product }) => { useEffect(() => { if (selectedVariant) { - const variant = product.variants.find(variant => variant.id == selectedVariant.value) - const variantAttributes = variant.attributes.length > 0 ? ' - ' + variant.attributes.join(', ') : '' - + const variant = product.variants.find((variant) => variant.id == selectedVariant.value) + const variantAttributes = + variant.attributes.length > 0 ? ' - ' + variant.attributes.join(', ') : '' + setActiveVariant({ id: variant.id, code: variant.code, @@ -87,76 +87,69 @@ const Product = ({ product }) => { <Image src={product.image} alt={product.name} - className="h-72 object-contain object-center w-full border-b border-gray_r-4" + className='h-72 object-contain object-center w-full border-b border-gray_r-4' /> - <div className="p-4"> - <Link href="/" className="mb-2">{ product.manufacture?.name }</Link> - <h1 className="leading-6 font-medium"> - {activeVariant?.name} - </h1> - { activeVariant?.price?.discountPercentage > 0 && ( - <div className="flex gap-x-1 items-center mt-2"> - <div className="text-gray_r-11 line-through text-caption-1"> + <div className='p-4'> + <Link href='/' className='mb-2'> + {product.manufacture?.name} + </Link> + <h1 className='leading-6 font-medium'>{activeVariant?.name}</h1> + {activeVariant?.price?.discountPercentage > 0 && ( + <div className='flex gap-x-1 items-center mt-2'> + <div className='text-gray_r-11 line-through text-caption-1'> {currencyFormat(activeVariant?.price?.price)} </div> - <Badge type="solid-red"> - {activeVariant?.price?.discountPercentage}% - </Badge> + <Badge type='solid-red'>{activeVariant?.price?.discountPercentage}%</Badge> </div> - ) } - <h3 className="text-red_r-11 font-semibold mt-1"> - { activeVariant?.price?.priceDiscount > 0 ? currencyFormat(activeVariant?.price?.priceDiscount) : ( - <span className="text-gray_r-11 leading-6 font-normal"> + )} + <h3 className='text-red_r-11 font-semibold mt-1'> + {activeVariant?.price?.priceDiscount > 0 ? ( + currencyFormat(activeVariant?.price?.priceDiscount) + ) : ( + <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">klik disini</a> + <a href='https://wa.me/' className='text-red_r-11 underline'> + klik disini + </a> </span> - ) } + )} </h3> </div> <Divider /> - <div className="p-4"> + <div className='p-4'> <div> - <label className="flex justify-between"> + <label className='flex justify-between'> Pilih Varian: - <span className="text-gray_r-11"> - { product?.variantTotal } Varian - </span> + <span className='text-gray_r-11'>{product?.variantTotal} Varian</span> </label> <Select - name="variant" - classNamePrefix="form-select" + name='variant' + classNamePrefix='form-select' options={variantOptions} - className="mt-2" + className='mt-2' value={selectedVariant} onChange={(option) => setSelectedVariant(option)} isSearchable={product.variantTotal > 10} /> </div> - <div className="mt-4 mb-2">Jumlah</div> - <div className="flex gap-x-3"> - <div className="w-2/12"> - <input - name="quantity" - type="number" - className="form-input" + <div className='mt-4 mb-2'>Jumlah</div> + <div className='flex gap-x-3'> + <div className='w-2/12'> + <input + name='quantity' + type='number' + className='form-input' value={quantity} 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> @@ -164,78 +157,70 @@ const Product = ({ product }) => { <Divider /> - <div className="p-4"> - <h2 className="font-semibold">Informasi Produk</h2> - <div className="flex gap-x-4 mt-4 mb-3"> - { informationTabOptions.map((option) => ( - <TabButton - value={option.value} + <div className='p-4'> + <h2 className='font-semibold'>Informasi Produk</h2> + <div className='flex gap-x-4 mt-4 mb-3'> + {informationTabOptions.map((option) => ( + <TabButton + value={option.value} key={option.value} active={informationTab == option.value} onClick={() => setInformationTab(option.value)} > {option.label} </TabButton> - )) } + ))} </div> - <TabContent - active={informationTab == 'specification'} - className="rounded border border-gray_r-6 divide-y divide-gray_r-6" + <TabContent + active={informationTab == 'specification'} + className='rounded border border-gray_r-6 divide-y divide-gray_r-6' > - <SpecificationContent label="Jumlah Varian"> + <SpecificationContent label='Jumlah Varian'> <span>{product?.variantTotal} Varian</span> </SpecificationContent> - <SpecificationContent label="Nomor SKU"> + <SpecificationContent label='Nomor SKU'> <span>SKU-{product?.id}</span> </SpecificationContent> - <SpecificationContent label="Part Number"> + <SpecificationContent label='Part Number'> <span>{activeVariant?.code || '-'}</span> - </SpecificationContent> - <SpecificationContent label="Stok"> - { activeVariant?.stock > 0 && ( - <span className="flex gap-x-1.5"> - <div className="badge-solid-red">Ready Stock</div> - <div className="badge-gray"> - { activeVariant?.stock > 5 ? '> 5' : '< 5' } - </div> + </SpecificationContent> + <SpecificationContent label='Stok'> + {activeVariant?.stock > 0 && ( + <span className='flex gap-x-1.5'> + <div className='badge-solid-red'>Ready Stock</div> + <div className='badge-gray'>{activeVariant?.stock > 5 ? '> 5' : '< 5'}</div> </span> - ) } - { activeVariant?.stock == 0 && ( - <a - href="https://wa.me" - className="text-red_r-11 font-medium" - > + )} + {activeVariant?.stock == 0 && ( + <a href='https://wa.me' className='text-red_r-11 font-medium'> Tanya Stok </a> - ) } - </SpecificationContent> - <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" - > + )} + </SpecificationContent> + <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'> Tanya Berat </a> - ) } - </SpecificationContent> + )} + </SpecificationContent> </TabContent> <TabContent active={informationTab == 'description'} - className="leading-6 text-gray_r-11" - dangerouslySetInnerHTML={{__html: (product.description != '' ? product.description : 'Belum ada deskripsi produk.')}} + className='leading-6 text-gray_r-11' + dangerouslySetInnerHTML={{ + __html: product.description != '' ? product.description : 'Belum ada deskripsi produk.' + }} /> </div> <Divider /> - <div className="p-4"> - <h2 className="font-semibold mb-4">Kamu Mungkin Juga Suka</h2> + <div className='p-4'> + <h2 className='font-semibold mb-4'>Kamu Mungkin Juga Suka</h2> <LazyLoad> <ProductSimilar query={product?.name.split(' ').slice(1, 3).join(' ')} /> </LazyLoad> @@ -247,30 +232,23 @@ 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}`} - > - { children } + <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}`} - > - { children } + <div {...props} className={`${active ? 'block' : 'hidden'} ${className}`}> + {children} </div> ) const SpecificationContent = ({ children, label }) => ( - <div className="flex justify-between p-3"> - <span className="text-gray_r-11">{ label }</span> - { children } + <div className='flex justify-between p-3'> + <span className='text-gray_r-11'>{label}</span> + {children} </div> ) -export default Product
\ No newline at end of file +export default Product diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 9eb00ae0..8a2f1d7f 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -1,68 +1,68 @@ -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import currencyFormat from "@/core/utils/currencyFormat" -import { createSlug } from "@/core/utils/slug" +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import currencyFormat from '@/core/utils/currencyFormat' +import { createSlug } from '@/core/utils/slug' const ProductCard = ({ product, simpleTitle }) => { return ( <> - <div className="rounded shadow-sm border border-gray_r-4"> - <Link - href={createSlug('/shop/product/', product?.name, product?.id)} - className="border-b border-gray_r-4 relative" + <div className='rounded shadow-sm border border-gray_r-4'> + <Link + href={createSlug('/shop/product/', product?.name, product?.id)} + className='border-b border-gray_r-4 relative' > - <Image + <Image src={product?.image} alt={product?.name} - className="w-full object-contain object-center h-36" + className='w-full object-contain object-center h-36' /> - { product.variantTotal > 1 && ( - <div className="absolute badge-gray bottom-1.5 left-1.5">{ product.variantTotal } Varian</div> - ) } + {product.variantTotal > 1 && ( + <div className='absolute badge-gray bottom-1.5 left-1.5'> + {product.variantTotal} Varian + </div> + )} </Link> - <div className="p-2 pb-3 text-caption-2 leading-5 bg-white"> - <Link - href={createSlug('/shop/brands/', product?.manufacture?.name, product?.manufacture.id)} - className="mb-1" + <div className='p-2 pb-3 text-caption-2 leading-5 bg-white'> + <Link + href={createSlug('/shop/brands/', product?.manufacture?.name, product?.manufacture.id)} + className='mb-1' > {product?.manufacture?.name} </Link> - <Link + <Link href={createSlug('/shop/product/', product?.name, product?.id)} - className={`font-medium mb-2 !text-gray_r-12 ${simpleTitle ? 'line-clamp-2' : 'line-clamp-3'}`} + className={`font-medium mb-2 !text-gray_r-12 ${ + simpleTitle ? 'line-clamp-2' : 'line-clamp-3' + }`} > {product?.name} </Link> - { product?.lowestPrice?.discountPercentage > 0 && ( - <div className="flex gap-x-1 mb-1 items-center"> - <div className="text-gray_r-11 line-through text-[11px]"> + {product?.lowestPrice?.discountPercentage > 0 && ( + <div className='flex gap-x-1 mb-1 items-center'> + <div className='text-gray_r-11 line-through text-[11px]'> {currencyFormat(product?.lowestPrice?.price)} </div> - <div className="badge-solid-red"> - {product?.lowestPrice?.discountPercentage}% - </div> + <div className='badge-solid-red'>{product?.lowestPrice?.discountPercentage}%</div> </div> - ) } + )} - <div className="text-red_r-11 font-semibold mb-2"> - { product?.lowestPrice?.priceDiscount > 0 ? currencyFormat(product?.lowestPrice?.priceDiscount) : ( - <a href="https://wa.me/">Call for price</a> - ) } + <div className='text-red_r-11 font-semibold mb-2'> + {product?.lowestPrice?.priceDiscount > 0 ? ( + currencyFormat(product?.lowestPrice?.priceDiscount) + ) : ( + <a href='https://wa.me/'>Call for price</a> + )} </div> - { product?.stockTotal > 0 && ( - <div className="flex gap-x-1"> - <div className="badge-solid-red"> - Ready Stock - </div> - <div className="badge-gray"> - { product?.stockTotal > 5 ? '> 5' : '< 5' } - </div> + {product?.stockTotal > 0 && ( + <div className='flex gap-x-1'> + <div className='badge-solid-red'>Ready Stock</div> + <div className='badge-gray'>{product?.stockTotal > 5 ? '> 5' : '< 5'}</div> </div> - ) } + )} </div> </div> </> ) } -export default ProductCard
\ No newline at end of file +export default ProductCard diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx index 023b6a8b..d920cfb8 100644 --- a/src/lib/product/components/ProductFilter.jsx +++ b/src/lib/product/components/ProductFilter.jsx @@ -1,31 +1,24 @@ -import BottomPopup from "@/core/components/elements/Popup/BottomPopup" -import { useRouter } from "next/router" -import { useState } from "react" -import _ from "lodash" -import { toQuery } from "lodash-contrib" +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import { useRouter } from 'next/router' +import { useState } from 'react' +import _ from 'lodash' +import { toQuery } from 'lodash-contrib' const orderOptions = [ { value: 'price-asc', label: 'Harga Terendah' }, { value: 'price-desc', label: 'Harga Tertinggi' }, { value: 'popular', label: 'Populer' }, - { value: 'stock', label: 'Ready Stock' }, + { value: 'stock', label: 'Ready Stock' } ] -const ProductFilter = ({ - active, - close, - brands, - categories, - prefixUrl, - defaultBrand = null -}) => { +const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBrand = null }) => { const router = useRouter() const { query } = router - const [ order, setOrder ] = useState(query?.orderBy) - const [ brand, setBrand ] = useState(query?.brand) - const [ category, setCategory ] = useState(query?.category) - const [ priceFrom, setPriceFrom ] = useState(query?.priceFrom) - const [ priceTo, setPriceTo ] = useState(query?.priceTo) + const [order, setOrder] = useState(query?.orderBy) + const [brand, setBrand] = useState(query?.brand) + const [category, setCategory] = useState(query?.category) + const [priceFrom, setPriceFrom] = useState(query?.priceFrom) + const [priceTo, setPriceTo] = useState(query?.priceTo) const handleSubmit = () => { let params = { @@ -42,85 +35,79 @@ const ProductFilter = ({ } return ( - <BottomPopup - active={active} - close={close} - title="Filter Produk" - > - <div className="flex flex-col gap-y-4"> - { !defaultBrand && ( + <BottomPopup active={active} close={close} title='Filter Produk'> + <div className='flex flex-col gap-y-4'> + {!defaultBrand && ( <div> <label>Brand</label> - <select - name="brand" - className="form-input mt-2" + <select + name='brand' + className='form-input mt-2' value={brand} onChange={(e) => setBrand(e.target.value)} > - <option value="">Pilih Brand...</option> - { brands.map((brand, index) => ( + <option value=''>Pilih Brand...</option> + {brands.map((brand, index) => ( <option value={brand} key={index}> {brand} </option> - )) } + ))} </select> </div> - ) } + )} <div> <label>Kategori</label> - <select - name="category" - className="form-input mt-2" + <select + name='category' + className='form-input mt-2' value={category} onChange={(e) => setCategory(e.target.value)} > - <option value="">Pilih Kategori...</option> - { categories.map((category, index) => ( + <option value=''>Pilih Kategori...</option> + {categories.map((category, index) => ( <option value={category} key={index}> {category} </option> - )) } + ))} </select> </div> <div> <label>Urutkan</label> - <div className="flex mt-2 gap-x-2 overflow-x-auto"> - { orderOptions.map((orderOption) => ( - <button + <div className='flex mt-2 gap-x-2 overflow-x-auto'> + {orderOptions.map((orderOption) => ( + <button key={orderOption.value} - className={`btn-light px-3 font-normal flex-shrink-0 ${order == orderOption.value ? 'bg-yellow_r-10' : 'bg-transparent'}`} + className={`btn-light px-3 font-normal flex-shrink-0 ${ + order == orderOption.value ? 'bg-yellow_r-10' : 'bg-transparent' + }`} onClick={() => setOrder(orderOption.value)} > - { orderOption.label } + {orderOption.label} </button> - )) } + ))} </div> </div> <div> <label>Harga</label> - <div className="flex mt-2 gap-x-4 items-center"> - <input - type="number" - className="form-input" - placeholder="Dari" + <div className='flex mt-2 gap-x-4 items-center'> + <input + type='number' + className='form-input' + placeholder='Dari' value={priceFrom} onChange={(e) => setPriceFrom(e.target.value)} /> <span>—</span> - <input - type="number" - className="form-input" - placeholder="Sampai" + <input + type='number' + className='form-input' + placeholder='Sampai' value={priceTo} onChange={(e) => setPriceTo(e.target.value)} /> </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> @@ -128,4 +115,4 @@ const ProductFilter = ({ ) } -export default ProductFilter
\ No newline at end of file +export default ProductFilter diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 14df9864..25d0278f 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -1,21 +1,23 @@ -import { useEffect, useState } from "react" -import useProductSearch from "../hooks/useProductSearch" -import ProductCard from "./ProductCard" -import Pagination from "@/core/components/elements/Pagination/Pagination" -import { toQuery } from "lodash-contrib" -import _ from "lodash" -import ProductSearchSkeleton from "./Skeleton/ProductSearchSkeleton" -import ProductFilter from "./ProductFilter" -import useActive from "@/core/hooks/useActive" +import { useEffect, useState } from 'react' +import useProductSearch from '../hooks/useProductSearch' +import ProductCard from './ProductCard' +import Pagination from '@/core/components/elements/Pagination/Pagination' +import { toQuery } from 'lodash-contrib' +import _ from 'lodash' +import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton' +import ProductFilter from './ProductFilter' +import useActive from '@/core/hooks/useActive' const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const { page = 1 } = query if (defaultBrand) query.brand = defaultBrand.toLowerCase() const { productSearch } = useProductSearch({ query }) - const [ products, setProducts ] = useState(null) + const [products, setProducts] = useState(null) const popup = useActive() - const pageCount = Math.ceil(productSearch.data?.response.numFound / productSearch.data?.responseHeader.params.rows) + const pageCount = Math.ceil( + productSearch.data?.response.numFound / productSearch.data?.responseHeader.params.rows + ) const productStart = productSearch.data?.responseHeader.params.start const productRows = productSearch.data?.responseHeader.params.rows const productFound = productSearch.data?.response.numFound @@ -25,11 +27,13 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { return true } }) - const categories = productSearch.data?.facetCounts?.facetFields?.categoryNameStr?.filter((value, index) => { - if (index % 2 === 0) { - return true + const categories = productSearch.data?.facetCounts?.facetFields?.categoryNameStr?.filter( + (value, index) => { + if (index % 2 === 0) { + return true + } } - }) + ) useEffect(() => { if (!products) { @@ -40,47 +44,55 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { if (productSearch.isLoading) { return <ProductSearchSkeleton /> } - + return ( - <div className="p-4"> - <h1 className="mb-2 font-semibold text-h-sm">Produk</h1> - - <div className="mb-2 leading-6 text-gray_r-11"> - { productFound > 0 ? ( + <div className='p-4'> + <h1 className='mb-2 font-semibold text-h-sm'>Produk</h1> + + <div className='mb-2 leading-6 text-gray_r-11'> + {productFound > 0 ? ( <> Menampilkan {pageCount > 1 ? ( <> - {productStart + 1}-{ - (productStart + productRows) > productFound ? productFound : productStart + productRows - } + {productStart + 1}- + {productStart + productRows > productFound + ? productFound + : productStart + productRows} dari </> - ) : ''} - { productFound } - produk { query.q && (<>untuk pencarian <span className="font-semibold">{ query.q }</span></>) } + ) : ( + '' + )} + {productFound} + produk{' '} + {query.q && ( + <> + untuk pencarian <span className='font-semibold'>{query.q}</span> + </> + )} </> - ) : 'Mungkin yang anda cari'} + ) : ( + 'Mungkin yang anda cari' + )} </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} /> - )) } + <div className='grid grid-cols-2 gap-3'> + {products && products.map((product) => <ProductCard product={product} key={product.id} />)} </div> <Pagination pageCount={pageCount} - currentPage={parseInt(page)} + currentPage={parseInt(page)} url={`${prefixUrl}?${toQuery(_.omit(query, ['page']))}`} - className="mt-6 mb-2" + className='mt-6 mb-2' /> - <ProductFilter + <ProductFilter active={popup.active} close={popup.deactivate} brands={brands || []} @@ -92,4 +104,4 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { ) } -export default ProductSearch
\ No newline at end of file +export default ProductSearch diff --git a/src/lib/product/components/ProductSimilar.jsx b/src/lib/product/components/ProductSimilar.jsx index 89cab536..63a33089 100644 --- a/src/lib/product/components/ProductSimilar.jsx +++ b/src/lib/product/components/ProductSimilar.jsx @@ -1,6 +1,6 @@ -import PopularProductSkeleton from "@/lib/home/components/Skeleton/PopularProductSkeleton" -import useProductSimilar from "../hooks/useProductSimilar" -import ProductSlider from "./ProductSlider" +import PopularProductSkeleton from '@/lib/home/components/Skeleton/PopularProductSkeleton' +import useProductSimilar from '../hooks/useProductSimilar' +import ProductSlider from './ProductSlider' const ProductSimilar = ({ query }) => { const { productSimilar } = useProductSimilar({ query }) @@ -12,4 +12,4 @@ const ProductSimilar = ({ query }) => { return <ProductSlider products={productSimilar.data} /> } -export default ProductSimilar
\ No newline at end of file +export default ProductSimilar diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index 8d677547..aafd3cf1 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -1,51 +1,48 @@ -import { Swiper, SwiperSlide } from "swiper/react" -import ProductCard from "./ProductCard" -import "swiper/css" -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import { useState } from "react" +import { Swiper, SwiperSlide } from 'swiper/react' +import ProductCard from './ProductCard' +import 'swiper/css' +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import { useState } from 'react' -const bannerClassName = 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' +const bannerClassName = + 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' -const ProductSlider = ({ - products, - simpleTitle = false, - bannerMode = false -}) => { - const [ activeIndex, setActiveIndex ] = useState(0) +const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => { + const [activeIndex, setActiveIndex] = useState(0) const swiperSliderFirstMove = (swiper) => { setActiveIndex(swiper.activeIndex) } return ( <> - { bannerMode && ( - <Image - src={products.banner.image} - alt={products.banner.name} - className={`${bannerClassName} ${activeIndex > 0 ? 'opacity-0' : 'opacity-100'}`} + {bannerMode && ( + <Image + src={products.banner.image} + alt={products.banner.name} + className={`${bannerClassName} ${activeIndex > 0 ? 'opacity-0' : 'opacity-100'}`} /> - ) } - <Swiper - freeMode={true} - slidesPerView={2.2} - spaceBetween={8} - onSlideChange={swiperSliderFirstMove} - prefix="product" + )} + <Swiper + freeMode={true} + slidesPerView={2.2} + spaceBetween={8} + onSlideChange={swiperSliderFirstMove} + prefix='product' > - { bannerMode && ( + {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) => ( + )} + {products?.products?.map((product, index) => ( <SwiperSlide key={index}> <ProductCard product={product} simpleTitle={simpleTitle} /> </SwiperSlide> - )) } + ))} </Swiper> </> ) } -export default ProductSlider
\ No newline at end of file +export default ProductSlider diff --git a/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx b/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx index e51a565c..fa1e175d 100644 --- a/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx +++ b/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx @@ -1,7 +1,7 @@ -import ProductCardSkeleton from "@/core/components/elements/Skeleton/ProductCardSkeleton" +import ProductCardSkeleton from '@/core/components/elements/Skeleton/ProductCardSkeleton' const ProductSearchSkeleton = () => ( - <div className="p-4 grid grid-cols-2 gap-4"> + <div className='p-4 grid grid-cols-2 gap-4'> <ProductCardSkeleton /> <ProductCardSkeleton /> <ProductCardSkeleton /> @@ -11,4 +11,4 @@ const ProductSearchSkeleton = () => ( </div> ) -export default ProductSearchSkeleton
\ No newline at end of file +export default ProductSearchSkeleton diff --git a/src/lib/product/hooks/useProductSearch.js b/src/lib/product/hooks/useProductSearch.js index d23a8098..0396caec 100644 --- a/src/lib/product/hooks/useProductSearch.js +++ b/src/lib/product/hooks/useProductSearch.js @@ -1,6 +1,6 @@ -import { useQuery } from "react-query" -import productSearchApi from "../api/productSearchApi" -import _ from "lodash-contrib" +import { useQuery } from 'react-query' +import productSearchApi from '../api/productSearchApi' +import _ from 'lodash-contrib' const useProductSearch = ({ query }) => { const queryString = _.toQuery(query) @@ -12,4 +12,4 @@ const useProductSearch = ({ query }) => { } } -export default useProductSearch
\ No newline at end of file +export default useProductSearch diff --git a/src/lib/product/hooks/useProductSimilar.js b/src/lib/product/hooks/useProductSimilar.js index 444fec0b..d16e4c58 100644 --- a/src/lib/product/hooks/useProductSimilar.js +++ b/src/lib/product/hooks/useProductSimilar.js @@ -1,5 +1,5 @@ -import productSimilarApi from "../api/productSimilarApi" -import { useQuery } from "react-query" +import productSimilarApi from '../api/productSimilarApi' +import { useQuery } from 'react-query' const useProductSimilar = ({ query }) => { const fetchProductSimilar = async () => await productSimilarApi({ query }) @@ -10,4 +10,4 @@ const useProductSimilar = ({ query }) => { } } -export default useProductSimilar
\ No newline at end of file +export default useProductSimilar diff --git a/src/lib/transaction/api/cancelTransactionApi.js b/src/lib/transaction/api/cancelTransactionApi.js index cd1798b5..1bba2bde 100644 --- a/src/lib/transaction/api/cancelTransactionApi.js +++ b/src/lib/transaction/api/cancelTransactionApi.js @@ -1,10 +1,13 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const cancelTransactionApi = async ({ transaction }) => { const auth = getAuth() - const dataCancelTransaction = await odooApi('POST', `/api/v1/partner/${auth.partnerId}/sale_order/${transaction.id}/cancel`) + const dataCancelTransaction = await odooApi( + 'POST', + `/api/v1/partner/${auth.partnerId}/sale_order/${transaction.id}/cancel` + ) return dataCancelTransaction } -export default cancelTransactionApi
\ No newline at end of file +export default cancelTransactionApi diff --git a/src/lib/transaction/api/checkoutPoApi.js b/src/lib/transaction/api/checkoutPoApi.js index aed43cff..04421368 100644 --- a/src/lib/transaction/api/checkoutPoApi.js +++ b/src/lib/transaction/api/checkoutPoApi.js @@ -1,10 +1,13 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const checkoutPoApi = async ({ id }) => { const auth = getAuth() - const dataCheckout = await odooApi('POST', `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout`) + const dataCheckout = await odooApi( + 'POST', + `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout` + ) return dataCheckout } -export default checkoutPoApi
\ No newline at end of file +export default checkoutPoApi diff --git a/src/lib/transaction/api/transactionApi.js b/src/lib/transaction/api/transactionApi.js index 7186f847..e7c4c23f 100644 --- a/src/lib/transaction/api/transactionApi.js +++ b/src/lib/transaction/api/transactionApi.js @@ -1,5 +1,5 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const transactionApi = async ({ id }) => { const auth = getAuth() @@ -7,4 +7,4 @@ const transactionApi = async ({ id }) => { return dataTransaction } -export default transactionApi
\ No newline at end of file +export default transactionApi diff --git a/src/lib/transaction/api/transactionsApi.js b/src/lib/transaction/api/transactionsApi.js index 995b4c5c..f4e36e6f 100644 --- a/src/lib/transaction/api/transactionsApi.js +++ b/src/lib/transaction/api/transactionsApi.js @@ -1,10 +1,13 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const transactionsApi = async ({ query }) => { const auth = getAuth() - const dataTransactions = await odooApi('GET', `/api/v1/partner/${auth.partnerId}/sale_order?${query}`) + const dataTransactions = await odooApi( + 'GET', + `/api/v1/partner/${auth.partnerId}/sale_order?${query}` + ) return dataTransactions } -export default transactionsApi
\ No newline at end of file +export default transactionsApi diff --git a/src/lib/transaction/api/uploadPoApi.js b/src/lib/transaction/api/uploadPoApi.js index 00ad1d8d..7feeff66 100644 --- a/src/lib/transaction/api/uploadPoApi.js +++ b/src/lib/transaction/api/uploadPoApi.js @@ -1,10 +1,14 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const uploadPoApi = async ({ id, data }) => { const auth = getAuth() - const dataUploadPo = await odooApi('POST', `/api/v1/partner/${auth.partnerId}/sale_order/${id}/upload_po`, data) + const dataUploadPo = await odooApi( + 'POST', + `/api/v1/partner/${auth.partnerId}/sale_order/${id}/upload_po`, + data + ) return dataUploadPo } -export default uploadPoApi
\ No newline at end of file +export default uploadPoApi diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index 0017afba..2220f3be 100644 --- a/src/lib/transaction/components/Transaction.jsx +++ b/src/lib/transaction/components/Transaction.jsx @@ -1,27 +1,27 @@ -import Spinner from "@/core/components/elements/Spinner/Spinner" -import useTransaction from "../hooks/useTransaction" -import TransactionStatusBadge from "./TransactionStatusBadge" -import Divider from "@/core/components/elements/Divider/Divider" -import { useRef, useState } from "react" -import { downloadPurchaseOrder, downloadQuotation } from "../utils/transactions" -import BottomPopup from "@/core/components/elements/Popup/BottomPopup" -import uploadPoApi from "../api/uploadPoApi" -import { toast } from "react-hot-toast" -import getFileBase64 from "@/core/utils/getFileBase64" -import currencyFormat from "@/core/utils/currencyFormat" -import VariantGroupCard from "@/lib/variant/components/VariantGroupCard" -import { ChevronDownIcon, ChevronRightIcon, ChevronUpIcon } from "@heroicons/react/24/outline" -import Link from "@/core/components/elements/Link/Link" -import Alert from "@/core/components/elements/Alert/Alert" -import checkoutPoApi from "../api/checkoutPoApi" -import cancelTransactionApi from "../api/cancelTransactionApi" +import Spinner from '@/core/components/elements/Spinner/Spinner' +import useTransaction from '../hooks/useTransaction' +import TransactionStatusBadge from './TransactionStatusBadge' +import Divider from '@/core/components/elements/Divider/Divider' +import { useRef, useState } from 'react' +import { downloadPurchaseOrder, downloadQuotation } from '../utils/transactions' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import uploadPoApi from '../api/uploadPoApi' +import { toast } from 'react-hot-toast' +import getFileBase64 from '@/core/utils/getFileBase64' +import currencyFormat from '@/core/utils/currencyFormat' +import VariantGroupCard from '@/lib/variant/components/VariantGroupCard' +import { ChevronDownIcon, ChevronRightIcon, ChevronUpIcon } from '@heroicons/react/24/outline' +import Link from '@/core/components/elements/Link/Link' +import Alert from '@/core/components/elements/Alert/Alert' +import checkoutPoApi from '../api/checkoutPoApi' +import cancelTransactionApi from '../api/cancelTransactionApi' const Transaction = ({ id }) => { const { transaction } = useTransaction({ id }) const poNumber = useRef('') const poFile = useRef('') - const [ uploadPo, setUploadPo ] = useState(false) + const [uploadPo, setUploadPo] = useState(false) const openUploadPo = () => setUploadPo(true) const closeUploadPo = () => setUploadPo(false) const submitUploadPo = async () => { @@ -46,7 +46,7 @@ const Transaction = ({ id }) => { toast.error('Terjadi kesalahan internal, coba lagi nanti atau hubungi kami') } - const [ cancelTransaction, setCancelTransaction ] = useState(false) + const [cancelTransaction, setCancelTransaction] = useState(false) const openCancelTransaction = () => setCancelTransaction(true) const closeCancelTransaction = () => setCancelTransaction(false) const submitCancelTransaction = async () => { @@ -70,191 +70,174 @@ const Transaction = ({ id }) => { if (transaction.isLoading) { return ( - <div className="flex justify-center my-6"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + <div className='flex justify-center my-6'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> ) } - return transaction.data?.name && ( - <> - <div className="flex flex-col gap-y-4 p-4"> - <DescriptionRow label="Status Transaksi"> - <div className="flex justify-end"> - <TransactionStatusBadge status={transaction.data?.status} /> - </div> - </DescriptionRow> - <DescriptionRow label="No Transaksi"> - { transaction.data?.name } - </DescriptionRow> - <DescriptionRow label="Ketentuan Pembayaran"> - { transaction.data?.paymentTerm } - </DescriptionRow> - <DescriptionRow label="Nama Sales"> - { transaction.data?.sales } - </DescriptionRow> - <DescriptionRow label="Waktu Transaksi"> - { transaction.data?.dateOrder } - </DescriptionRow> - </div> - - <Divider /> + return ( + transaction.data?.name && ( + <> + <div className='flex flex-col gap-y-4 p-4'> + <DescriptionRow label='Status Transaksi'> + <div className='flex justify-end'> + <TransactionStatusBadge status={transaction.data?.status} /> + </div> + </DescriptionRow> + <DescriptionRow label='No Transaksi'>{transaction.data?.name}</DescriptionRow> + <DescriptionRow label='Ketentuan Pembayaran'> + {transaction.data?.paymentTerm} + </DescriptionRow> + <DescriptionRow label='Nama Sales'>{transaction.data?.sales}</DescriptionRow> + <DescriptionRow label='Waktu Transaksi'>{transaction.data?.dateOrder}</DescriptionRow> + </div> - <div className="p-4 flex flex-col gap-y-4"> - <DescriptionRow label="Purchase Order"> - { transaction.data?.purchaseOrderName || '-' } - </DescriptionRow> - <div className="flex items-center"> - <p className="text-gray_r-11 leading-none">Dokumen PO</p> - <button - type="button" - className="btn-light py-1.5 px-3 ml-auto" - onClick={transaction.data?.purchaseOrderFile ? () => downloadPurchaseOrder(transaction.data) : openUploadPo} - > - { transaction.data?.purchaseOrderFile ? 'Download' : 'Upload' } - </button> + <Divider /> + + <div className='p-4 flex flex-col gap-y-4'> + <DescriptionRow label='Purchase Order'> + {transaction.data?.purchaseOrderName || '-'} + </DescriptionRow> + <div className='flex items-center'> + <p className='text-gray_r-11 leading-none'>Dokumen PO</p> + <button + type='button' + className='btn-light py-1.5 px-3 ml-auto' + onClick={ + transaction.data?.purchaseOrderFile + ? () => downloadPurchaseOrder(transaction.data) + : openUploadPo + } + > + {transaction.data?.purchaseOrderFile ? 'Download' : 'Upload'} + </button> + </div> </div> - </div> - <Divider /> + <Divider /> - <div className="font-medium p-4">Detail Produk</div> + <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 - /> - <div className="flex justify-between mt-3 font-medium"> - <p>Total Belanja</p> - <p>{ currencyFormat(transaction.data?.amountTotal) }</p> + <div className='p-4 pt-0 flex flex-col gap-y-3'> + <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> + </div> </div> - </div> - <Divider /> - - <SectionAddress address={transaction.data?.address} /> + <Divider /> - <Divider /> + <SectionAddress address={transaction.data?.address} /> + + <Divider /> - <div className="p-4"> - <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}> - <div className="shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between"> - <div> - <p className="mb-2">{ invoice?.name }</p> - <div className="flex items-center gap-x-1"> - { invoice.amountResidual > 0 ? ( - <div className="badge-red">Belum Lunas</div> + <div className='p-4'> + <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}> + <div className='shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between'> + <div> + <p className='mb-2'>{invoice?.name}</p> + <div className='flex items-center gap-x-1'> + {invoice.amountResidual > 0 ? ( + <div className='badge-red'>Belum Lunas</div> ) : ( - <div className="badge-green">Lunas</div> - ) } - <p className="text-caption-2 text-gray_r-11"> - { currencyFormat(invoice.amountTotal) } - </p> + <div className='badge-green'>Lunas</div> + )} + <p className='text-caption-2 text-gray_r-11'> + {currencyFormat(invoice.amountTotal)} + </p> + </div> </div> + <ChevronRightIcon className='w-5 stroke-2' /> </div> - <ChevronRightIcon className="w-5 stroke-2" /> - </div> - </Link> - )) } - { transaction.data?.invoices?.length === 0 && ( - <Alert type='info' className='text-center'> - Belum ada Invoice - </Alert> - ) } + </Link> + ))} + {transaction.data?.invoices?.length === 0 && ( + <Alert type='info' className='text-center'> + Belum ada Invoice + </Alert> + )} + </div> </div> - </div> - <Divider /> + <Divider /> - <div className="p-4 pt-0"> - { transaction.data?.status == 'draft' && ( - <button - className="btn-yellow w-full mt-4" - onClick={checkout} + <div className='p-4 pt-0'> + {transaction.data?.status == 'draft' && ( + <button className='btn-yellow w-full mt-4' onClick={checkout}> + Lanjutkan Transaksi + </button> + )} + <button + className='btn-light w-full mt-4' + disabled={transaction.data?.status != 'draft'} + onClick={downloadQuotation} > - Lanjutkan Transaksi + Download Quotation </button> - ) } - <button - className="btn-light w-full mt-4" - disabled={transaction.data?.status != 'draft'} - onClick={downloadQuotation} + {transaction.data?.status != 'draft' && ( + <button + className='btn-light w-full mt-4' + disabled={transaction.data?.status != 'waiting'} + onClick={openCancelTransaction} + > + Batalkan Transaksi + </button> + )} + </div> + + <BottomPopup + active={cancelTransaction} + close={closeCancelTransaction} + title='Batalkan Transaksi' > - Download Quotation - </button> - { transaction.data?.status != 'draft' && ( - <button - className="btn-light w-full mt-4" - disabled={transaction.data?.status != 'waiting'} - onClick={openCancelTransaction} - > - Batalkan Transaksi - </button> - ) } - </div> + <div className='leading-7 text-gray_r-12/80'> + Apakah anda yakin membatalkan transaksi{' '} + <span className='underline'>{transaction.data?.name}</span>? + </div> + <div className='flex mt-6 gap-x-4'> + <button + className='btn-solid-red flex-1' + type='button' + onClick={submitCancelTransaction} + > + Ya, Batalkan + </button> + <button className='btn-light flex-1' type='button' onClick={closeCancelTransaction}> + Batal + </button> + </div> + </BottomPopup> - <BottomPopup - active={cancelTransaction} - close={closeCancelTransaction} - title="Batalkan Transaksi" - > - <div className="leading-7 text-gray_r-12/80"> - Apakah anda yakin membatalkan transaksi <span className="underline">{transaction.data?.name}</span>? - </div> - <div className="flex mt-6 gap-x-4"> - <button - className="btn-solid-red flex-1" - type="button" - onClick={submitCancelTransaction} - > - Ya, Batalkan - </button> - <button - className="btn-light flex-1" - type="button" - onClick={closeCancelTransaction} - > - Batal - </button> - </div> - </BottomPopup> - - <BottomPopup - title="Upload PO" - close={closeUploadPo} - active={uploadPo} - > - <div> - <label>Nomor PO</label> - <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} /> - </div> - <div className="grid grid-cols-2 gap-x-3 mt-6"> - <button - type="button" - className="btn-light w-full" - onClick={closeUploadPo} - >Batal</button> - <button - type="button" - className="btn-solid-red w-full" - onClick={submitUploadPo} - >Upload</button> - </div> - </BottomPopup> - </> + <BottomPopup title='Upload PO' close={closeUploadPo} active={uploadPo}> + <div> + <label>Nomor PO</label> + <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} /> + </div> + <div className='grid grid-cols-2 gap-x-3 mt-6'> + <button type='button' className='btn-light w-full' onClick={closeUploadPo}> + Batal + </button> + <button type='button' className='btn-solid-red w-full' onClick={submitUploadPo}> + Upload + </button> + </div> + </BottomPopup> + </> + ) ) } const SectionAddress = ({ address }) => { - const [ section, setSection ] = useState({ + const [section, setSection] = useState({ customer: false, invoice: false, shipping: false @@ -265,44 +248,40 @@ const SectionAddress = ({ address }) => { return ( <> - <SectionButton - label="Detail Pelanggan" + <SectionButton + label='Detail Pelanggan' active={section.customer} toggle={() => toggleSection('customer')} /> - { section.customer && <SectionContent address={address?.customer} /> } + {section.customer && <SectionContent address={address?.customer} />} <Divider /> - - <SectionButton - label="Detail Pengiriman" + + <SectionButton + label='Detail Pengiriman' active={section.shipping} toggle={() => toggleSection('shipping')} /> - { section.shipping && <SectionContent address={address?.shipping} /> } + {section.shipping && <SectionContent address={address?.shipping} />} <Divider /> - - <SectionButton - label="Detail Penagihan" + + <SectionButton + label='Detail Penagihan' active={section.invoice} toggle={() => toggleSection('invoice')} /> - { section.invoice && <SectionContent address={address?.invoice} /> } + {section.invoice && <SectionContent address={address?.invoice} />} </> ) } 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" /> - ) } + {active ? <ChevronUpIcon className='w-5' /> : <ChevronDownIcon className='w-5' />} </button> ) @@ -315,28 +294,20 @@ const SectionContent = ({ address }) => { fullAddress = fullAddress.join(', ') return ( - <div className="flex flex-col gap-y-4 p-4 border-t border-gray_r-6"> - <DescriptionRow label="Nama"> - { address.name } - </DescriptionRow> - <DescriptionRow label="Email"> - { address.email || '-' } - </DescriptionRow> - <DescriptionRow label="No Telepon"> - { address.mobile || '-' } - </DescriptionRow> - <DescriptionRow label="Alamat"> - { fullAddress } - </DescriptionRow> + <div className='flex flex-col gap-y-4 p-4 border-t border-gray_r-6'> + <DescriptionRow label='Nama'>{address.name}</DescriptionRow> + <DescriptionRow label='Email'>{address.email || '-'}</DescriptionRow> + <DescriptionRow label='No Telepon'>{address.mobile || '-'}</DescriptionRow> + <DescriptionRow label='Alamat'>{fullAddress}</DescriptionRow> </div> ) } const DescriptionRow = ({ children, label }) => ( - <div className="grid grid-cols-2"> - <span className="text-gray_r-11">{ label }</span> - <span className="text-right">{ children }</span> + <div className='grid grid-cols-2'> + <span className='text-gray_r-11'>{label}</span> + <span className='text-right'>{children}</span> </div> ) -export default Transaction
\ No newline at end of file +export default Transaction diff --git a/src/lib/transaction/components/TransactionStatusBadge.jsx b/src/lib/transaction/components/TransactionStatusBadge.jsx index 28fe714a..7372e4da 100644 --- a/src/lib/transaction/components/TransactionStatusBadge.jsx +++ b/src/lib/transaction/components/TransactionStatusBadge.jsx @@ -35,11 +35,7 @@ const TransactionStatusBadge = ({ status }) => { } badgeProps.className = badgeProps.className.join(' ') - return ( - <div className={badgeProps.className}> - { badgeProps.text } - </div> - ) + return <div className={badgeProps.className}>{badgeProps.text}</div> } -export default TransactionStatusBadge
\ No newline at end of file +export default TransactionStatusBadge diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx index 280e8fc5..f582319d 100644 --- a/src/lib/transaction/components/Transactions.jsx +++ b/src/lib/transaction/components/Transactions.jsx @@ -1,27 +1,24 @@ -import { useRouter } from "next/router" -import { useState } from "react" -import { toast } from "react-hot-toast" -import { EllipsisVerticalIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline" - -import { downloadPurchaseOrder, downloadQuotation } from "../utils/transactions" -import useTransactions from "../hooks/useTransactions" -import currencyFormat from "@/core/utils/currencyFormat" -import cancelTransactionApi from "../api/cancelTransactionApi" -import TransactionStatusBadge from "./TransactionStatusBadge" -import Spinner from "@/core/components/elements/Spinner/Spinner" -import Link from "@/core/components/elements/Link/Link" -import BottomPopup from "@/core/components/elements/Popup/BottomPopup" -import Pagination from "@/core/components/elements/Pagination/Pagination" -import { toQuery } from "lodash-contrib" -import _ from "lodash" -import Alert from "@/core/components/elements/Alert/Alert" +import { useRouter } from 'next/router' +import { useState } from 'react' +import { toast } from 'react-hot-toast' +import { EllipsisVerticalIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline' + +import { downloadPurchaseOrder, downloadQuotation } from '../utils/transactions' +import useTransactions from '../hooks/useTransactions' +import currencyFormat from '@/core/utils/currencyFormat' +import cancelTransactionApi from '../api/cancelTransactionApi' +import TransactionStatusBadge from './TransactionStatusBadge' +import Spinner from '@/core/components/elements/Spinner/Spinner' +import Link from '@/core/components/elements/Link/Link' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import Pagination from '@/core/components/elements/Pagination/Pagination' +import { toQuery } from 'lodash-contrib' +import _ from 'lodash' +import Alert from '@/core/components/elements/Alert/Alert' const Transactions = () => { const router = useRouter() - const { - q = '', - page = 1 - } = router.query + const { q = '', page = 1 } = router.query const limit = 10 @@ -32,9 +29,9 @@ const Transactions = () => { } const { transactions } = useTransactions({ query }) - const [ inputQuery, setInputQuery ] = useState(q) - const [ toOthers, setToOthers ] = useState(null) - const [ toCancel, setToCancel ] = useState(null) + const [inputQuery, setInputQuery] = useState(q) + const [toOthers, setToOthers] = useState(null) + const [toCancel, setToCancel] = useState(null) const submitCancelTransaction = async () => { const isCancelled = await cancelTransactionApi({ @@ -55,129 +52,128 @@ const Transactions = () => { const handleSubmit = (e) => { e.preventDefault() router.push(`/my/transactions?q=${inputQuery}`) - } + } return ( - <div className="p-4 flex flex-col gap-y-4"> - <form className="flex gap-x-3" onSubmit={handleSubmit}> - <input - type="text" - className="form-input" - placeholder="Cari Transaksi..." + <div className='p-4 flex flex-col gap-y-4'> + <form className='flex gap-x-3' onSubmit={handleSubmit}> + <input + type='text' + className='form-input' + placeholder='Cari Transaksi...' value={inputQuery} onChange={(e) => setInputQuery(e.target.value)} /> - <button - className="btn-light bg-transparent px-3" - type="submit" - > - <MagnifyingGlassIcon className="w-6" /> + <button className='btn-light bg-transparent px-3' type='submit'> + <MagnifyingGlassIcon className='w-6' /> </button> </form> - - { transactions.isLoading && ( - <div className="flex justify-center my-4"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + + {transactions.isLoading && ( + <div className='flex justify-center my-4'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> - ) } + )} - { !transactions.isLoading && transactions.data?.saleOrders?.length === 0 && ( - <Alert type="info" className="text-center"> + {!transactions.isLoading && transactions.data?.saleOrders?.length === 0 && ( + <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="grid grid-cols-2"> + {transactions.data?.saleOrders?.map((saleOrder, 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> - <h2 className="text-red_r-11 mt-1">{ saleOrder.name }</h2> + <span className='text-caption-2 text-gray_r-11'>No. Transaksi</span> + <h2 className='text-red_r-11 mt-1'>{saleOrder.name}</h2> </Link> - <div className="flex gap-x-1 justify-end"> + <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}`}> - <div className="grid grid-cols-2 mt-3"> + <div className='grid grid-cols-2 mt-3'> <div> - <span className="text-caption-2 text-gray_r-11">No. Purchase Order</span> - <p className="mt-1 font-medium text-gray_r-12">{ saleOrder.purchaseOrderName || '-' }</p> + <span className='text-caption-2 text-gray_r-11'>No. Purchase Order</span> + <p className='mt-1 font-medium text-gray_r-12'> + {saleOrder.purchaseOrderName || '-'} + </p> </div> - <div className="text-right"> - <span className="text-caption-2 text-gray_r-11">Total Invoice</span> - <p className="mt-1 font-medium text-gray_r-12">{ saleOrder.invoiceCount } Invoice</p> + <div className='text-right'> + <span className='text-caption-2 text-gray_r-11'>Total Invoice</span> + <p className='mt-1 font-medium text-gray_r-12'>{saleOrder.invoiceCount} Invoice</p> </div> </div> - <div className="grid grid-cols-2 mt-3"> + <div className='grid grid-cols-2 mt-3'> <div> - <span className="text-caption-2 text-gray_r-11">Sales</span> - <p className="mt-1 font-medium text-gray_r-12">{ saleOrder.sales }</p> + <span className='text-caption-2 text-gray_r-11'>Sales</span> + <p className='mt-1 font-medium text-gray_r-12'>{saleOrder.sales}</p> </div> - <div className="text-right"> - <span className="text-caption-2 text-gray_r-11">Total Harga</span> - <p className="mt-1 font-medium text-gray_r-12">{ currencyFormat(saleOrder.amountTotal) }</p> + <div className='text-right'> + <span className='text-caption-2 text-gray_r-11'>Total Harga</span> + <p className='mt-1 font-medium text-gray_r-12'> + {currencyFormat(saleOrder.amountTotal)} + </p> </div> </div> </Link> </div> - )) } - + ))} + <Pagination pageCount={pageCount} - currentPage={parseInt(page)} + currentPage={parseInt(page)} url={`/my/transactions${pageQuery}`} - className="mt-2 mb-2" + className='mt-2 mb-2' /> - <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" + <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' disabled={!toOthers?.purchaseOrderFile} - onClick={() => { downloadPurchaseOrder(toOthers); setToOthers(null) }} + onClick={() => { + downloadPurchaseOrder(toOthers) + setToOthers(null) + }} > Download PO </button> - <button - className="text-left disabled:opacity-60" + <button + className='text-left disabled:opacity-60' disabled={toOthers?.status != 'draft'} - onClick={() => { downloadQuotation(toOthers); setToOthers(null) }} + onClick={() => { + downloadQuotation(toOthers) + setToOthers(null) + }} > Download Quotation </button> - <button - className="text-left disabled:opacity-60" - disabled={ toOthers?.status != 'waiting' } - onClick={() => { setToCancel(toOthers); setToOthers(null) }} + <button + className='text-left disabled:opacity-60' + disabled={toOthers?.status != 'waiting'} + onClick={() => { + setToCancel(toOthers) + setToOthers(null) + }} > Batalkan Transaksi </button> </div> </BottomPopup> - <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>? + <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} - > + <div className='flex mt-6 gap-x-4'> + <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> @@ -186,4 +182,4 @@ const Transactions = () => { ) } -export default Transactions
\ No newline at end of file +export default Transactions diff --git a/src/lib/transaction/hooks/useTransaction.js b/src/lib/transaction/hooks/useTransaction.js index f2b493ee..6dda0573 100644 --- a/src/lib/transaction/hooks/useTransaction.js +++ b/src/lib/transaction/hooks/useTransaction.js @@ -1,5 +1,5 @@ -import { useQuery } from "react-query" -import transactionApi from "../api/transactionApi" +import { useQuery } from 'react-query' +import transactionApi from '../api/transactionApi' const useTransaction = ({ id }) => { const fetchTransaction = async () => await transactionApi({ id }) @@ -10,4 +10,4 @@ const useTransaction = ({ id }) => { } } -export default useTransaction
\ No newline at end of file +export default useTransaction diff --git a/src/lib/transaction/hooks/useTransactions.js b/src/lib/transaction/hooks/useTransactions.js index 3f67fd3e..5b40a05a 100644 --- a/src/lib/transaction/hooks/useTransactions.js +++ b/src/lib/transaction/hooks/useTransactions.js @@ -1,6 +1,6 @@ -import { useQuery } from "react-query" -import transactionsApi from "../api/transactionsApi" -import _ from "lodash-contrib" +import { useQuery } from 'react-query' +import transactionsApi from '../api/transactionsApi' +import _ from 'lodash-contrib' const useTransactions = ({ query }) => { const queryString = _.toQuery(query) @@ -12,4 +12,4 @@ const useTransactions = ({ query }) => { } } -export default useTransactions
\ No newline at end of file +export default useTransactions diff --git a/src/lib/transaction/utils/transactions.js b/src/lib/transaction/utils/transactions.js index 03d4dbd4..4c7522be 100644 --- a/src/lib/transaction/utils/transactions.js +++ b/src/lib/transaction/utils/transactions.js @@ -1,4 +1,4 @@ -import { getAuth } from "@/core/utils/auth" +import { getAuth } from '@/core/utils/auth' const downloadPurchaseOrder = (transaction) => { const auth = getAuth() @@ -12,7 +12,4 @@ const downloadQuotation = (transaction) => { window.open(url, 'download') } -export { - downloadPurchaseOrder, - downloadQuotation -}
\ No newline at end of file +export { downloadPurchaseOrder, downloadQuotation } diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx index 6c7ab22f..6e7ea871 100644 --- a/src/lib/variant/components/VariantCard.jsx +++ b/src/lib/variant/components/VariantCard.jsx @@ -1,17 +1,13 @@ -import { useRouter } from "next/router" -import { toast } from "react-hot-toast" +import { useRouter } from 'next/router' +import { toast } from 'react-hot-toast' -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import { createSlug } from "@/core/utils/slug" -import currencyFormat from "@/core/utils/currencyFormat" -import { updateItemCart } from "@/core/utils/cart" +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import { createSlug } from '@/core/utils/slug' +import currencyFormat from '@/core/utils/currencyFormat' +import { updateItemCart } from '@/core/utils/cart' -const VariantCard = ({ - product, - openOnClick = true, - buyMore = false -}) => { +const VariantCard = ({ product, openOnClick = true, buyMore = false }) => { const router = useRouter() const addItemToCart = () => { @@ -22,41 +18,43 @@ const VariantCard = ({ }) return } - + const checkoutItem = () => { router.push(`/shop/checkout?product_id=${product.id}&qty=${product.quantity}`) } const Card = () => ( - <div className="flex gap-x-3"> - <div className="w-4/12 flex items-center gap-x-2"> + <div className='flex gap-x-3'> + <div className='w-4/12 flex items-center gap-x-2'> <Image - src={product.parent.image} - alt={product.parent.name} - className="object-contain object-center border border-gray_r-6 h-32 w-full rounded-md" + src={product.parent.image} + alt={product.parent.name} + className='object-contain object-center border border-gray_r-6 h-32 w-full rounded-md' /> </div> - <div className="w-8/12 flex flex-col"> - <p className="product-card__title wrap-line-ellipsis-2"> - {product.parent.name} - </p> - <p className="text-caption-2 text-gray_r-11 mt-1"> + <div className='w-8/12 flex flex-col'> + <p className='product-card__title wrap-line-ellipsis-2'>{product.parent.name}</p> + <p className='text-caption-2 text-gray_r-11 mt-1'> {product.code || '-'} {product.attributes.length > 0 ? ` ・ ${product.attributes.join(', ')}` : ''} </p> - <div className="flex flex-wrap gap-x-1 items-center mt-auto"> + <div className='flex flex-wrap gap-x-1 items-center mt-auto'> {product.price.discountPercentage > 0 && ( <> - <p className="text-caption-2 text-gray_r-11 line-through">{currencyFormat(product.price.price)}</p> - <span className="badge-red">{product.price.discountPercentage}%</span> + <p className='text-caption-2 text-gray_r-11 line-through'> + {currencyFormat(product.price.price)} + </p> + <span className='badge-red'>{product.price.discountPercentage}%</span> </> )} - <p className="text-caption-2 text-gray_r-12">{currencyFormat(product.price.priceDiscount)}</p> + <p className='text-caption-2 text-gray_r-12'> + {currencyFormat(product.price.priceDiscount)} + </p> </div> - <p className="text-caption-2 text-gray_r-11 mt-1"> + <p className='text-caption-2 text-gray_r-11 mt-1'> {currencyFormat(product.price.priceDiscount)} × {product.quantity} Barang </p> - <p className="text-caption-2 text-gray_r-12 font-bold mt-2"> + <p className='text-caption-2 text-gray_r-12 font-bold mt-2'> {currencyFormat(product.quantity * product.price.priceDiscount)} </p> </div> @@ -69,29 +67,29 @@ const VariantCard = ({ <Link href={createSlug('/shop/product/', product.parent.name, product.parent.id)}> <Card /> </Link> - { buyMore && ( - <div className="flex justify-end gap-x-2 mb-2"> - <button - type="button" - onClick={addItemToCart} - className="btn-yellow text-gray_r-12 py-2 px-3 text-caption-1" + {buyMore && ( + <div className='flex justify-end gap-x-2 mb-2'> + <button + type='button' + onClick={addItemToCart} + className='btn-yellow text-gray_r-12 py-2 px-3 text-caption-1' > Tambah Keranjang </button> - <button - type="button" - onClick={checkoutItem} - className="btn-solid-red py-2 px-3 text-caption-1" + <button + type='button' + onClick={checkoutItem} + className='btn-solid-red py-2 px-3 text-caption-1' > Beli Lagi </button> </div> - ) } + )} </> ) } - return <Card/> + return <Card /> } -export default VariantCard
\ No newline at end of file +export default VariantCard diff --git a/src/lib/variant/components/VariantGroupCard.jsx b/src/lib/variant/components/VariantGroupCard.jsx index fd4f9b4d..8cb1eec4 100644 --- a/src/lib/variant/components/VariantGroupCard.jsx +++ b/src/lib/variant/components/VariantGroupCard.jsx @@ -1,33 +1,26 @@ -import { useState } from "react" -import VariantCard from "./VariantCard" +import { useState } from 'react' +import VariantCard from './VariantCard' -const VariantGroupCard = ({ - variants, - ...props -}) => { - const [ showAll, setShowAll ] = useState(false) +const VariantGroupCard = ({ variants, ...props }) => { + const [showAll, setShowAll] = useState(false) const variantsToShow = showAll ? variants : variants.slice(0, 2) return ( <> - { variantsToShow?.map((variant, index) => ( - <VariantCard - key={index} - product={variant} - {...props} - /> - )) } - { variants.length > 2 && ( - <button - type="button" - className="btn-light py-2 w-full" + {variantsToShow?.map((variant, index) => ( + <VariantCard key={index} product={variant} {...props} /> + ))} + {variants.length > 2 && ( + <button + type='button' + className='btn-light py-2 w-full' onClick={() => setShowAll(!showAll)} > - { !showAll ? `Lihat Semua +${variants.length - variantsToShow.length}` : 'Tutup' } + {!showAll ? `Lihat Semua +${variants.length - variantsToShow.length}` : 'Tutup'} </button> - ) } + )} </> ) } -export default VariantGroupCard
\ No newline at end of file +export default VariantGroupCard diff --git a/src/lib/wishlist/api/wishlistsApi.js b/src/lib/wishlist/api/wishlistsApi.js index 49ef56ee..dfcce028 100644 --- a/src/lib/wishlist/api/wishlistsApi.js +++ b/src/lib/wishlist/api/wishlistsApi.js @@ -1,10 +1,13 @@ -import odooApi from "@/core/api/odooApi" -import { getAuth } from "@/core/utils/auth" +import odooApi from '@/core/api/odooApi' +import { getAuth } from '@/core/utils/auth' const wishlistsApi = async ({ limit, offset }) => { const auth = getAuth() - const dataWishlists = await odooApi('GET', `/api/v1/user/${auth.id}/wishlist?limit=${limit}&offset=${offset}`) + const dataWishlists = await odooApi( + 'GET', + `/api/v1/user/${auth.id}/wishlist?limit=${limit}&offset=${offset}` + ) return dataWishlists } -export default wishlistsApi
\ No newline at end of file +export default wishlistsApi diff --git a/src/lib/wishlist/components/Wishlists.jsx b/src/lib/wishlist/components/Wishlists.jsx index 8cbbb0a2..71ac095e 100644 --- a/src/lib/wishlist/components/Wishlists.jsx +++ b/src/lib/wishlist/components/Wishlists.jsx @@ -1,15 +1,13 @@ -import Alert from "@/core/components/elements/Alert/Alert" -import Pagination from "@/core/components/elements/Pagination/Pagination" -import Spinner from "@/core/components/elements/Spinner/Spinner" -import ProductCard from "@/lib/product/components/ProductCard" -import { useRouter } from "next/router" -import useWishlists from "../hooks/useWishlists" +import Alert from '@/core/components/elements/Alert/Alert' +import Pagination from '@/core/components/elements/Pagination/Pagination' +import Spinner from '@/core/components/elements/Spinner/Spinner' +import ProductCard from '@/lib/product/components/ProductCard' +import { useRouter } from 'next/router' +import useWishlists from '../hooks/useWishlists' const Wishlists = () => { const router = useRouter() - const { - page = 1 - } = router.query + const { page = 1 } = router.query const limit = 30 const { wishlists } = useWishlists({ page, limit }) @@ -17,31 +15,31 @@ const Wishlists = () => { if (wishlists.isLoading) { return ( - <div className="flex justify-center my-6"> - <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" /> + <div className='flex justify-center my-6'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> </div> ) } return ( - <div className="px-4 py-6"> - { wishlists.data?.products?.length == 0 && ( + <div className='px-4 py-6'> + {wishlists.data?.products?.length == 0 && ( <Alert type='info' className='text-center'> Wishlist anda masih kosong </Alert> - ) } - - <div className="grid grid-cols-2 gap-3"> + )} + + <div className='grid grid-cols-2 gap-3'> {wishlists.data?.products.map((product) => ( <ProductCard key={product.id} product={product} /> ))} </div> - <div className="mt-6"> + <div className='mt-6'> <Pagination currentPage={page} pageCount={pageCount} url={`/my/wishlist`} /> </div> </div> ) } -export default Wishlists
\ No newline at end of file +export default Wishlists diff --git a/src/lib/wishlist/hooks/useWishlists.js b/src/lib/wishlist/hooks/useWishlists.js index a219ab69..169fdf46 100644 --- a/src/lib/wishlist/hooks/useWishlists.js +++ b/src/lib/wishlist/hooks/useWishlists.js @@ -1,5 +1,5 @@ -import { useQuery } from "react-query" -import wishlistsApi from "../api/wishlistsApi" +import { useQuery } from 'react-query' +import wishlistsApi from '../api/wishlistsApi' const useWishlists = ({ page, limit }) => { const offset = (page - 1) * limit @@ -11,4 +11,4 @@ const useWishlists = ({ page, limit }) => { } } -export default useWishlists
\ No newline at end of file +export default useWishlists |
