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 | |
| parent | 3c559031623649a67825ff47f34512f0eb946861 (diff) | |
prettier
127 files changed, 1922 insertions, 2065 deletions
diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..aac13439 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": false, + "jsxSingleQuote": true, + "singleQuote": true, + "printWidth": 100, + "trailingComma": "none" +} diff --git a/package.json b/package.json index e3036b5c..d02fa878 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "format": "prettier --write \"./**/*.{js,jsx,ts,tsx}\" --config ./.prettierrc" }, "dependencies": { "@heroicons/react": "^2.0.13", diff --git a/postcss.config.js b/postcss.config.js index 33ad091d..85f717cc 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,6 @@ module.exports = { plugins: { tailwindcss: {}, - autoprefixer: {}, - }, + autoprefixer: {} + } } diff --git a/src/core/api/odooApi.js b/src/core/api/odooApi.js index 59d88faa..202c355e 100644 --- a/src/core/api/odooApi.js +++ b/src/core/api/odooApi.js @@ -25,13 +25,15 @@ const odooApi = async (method, url, data = {}, headers = {}) => { const auth = getAuth() let axiosParameter = { - method, + method, url: process.env.ODOO_HOST + url, - headers: {'Authorization': token, ...headers} + headers: { Authorization: token, ...headers } } if (auth) axiosParameter.headers['Token'] = auth.token - if (method.toUpperCase() == 'POST') axiosParameter.headers['Content-Type'] = 'application/x-www-form-urlencoded' - if (Object.keys(data).length > 0) axiosParameter.data = new URLSearchParams(Object.entries(data)).toString() + if (method.toUpperCase() == 'POST') + axiosParameter.headers['Content-Type'] = 'application/x-www-form-urlencoded' + if (Object.keys(data).length > 0) + axiosParameter.data = new URLSearchParams(Object.entries(data)).toString() let res = await axios(axiosParameter) if (res.data.status.code == 401 && connectionAttempt < maxConnectionAttempt) { @@ -44,4 +46,4 @@ const odooApi = async (method, url, data = {}, headers = {}) => { } } -export default odooApi;
\ No newline at end of file +export default odooApi diff --git a/src/core/api/searchSuggestApi.js b/src/core/api/searchSuggestApi.js index b5edebda..e4445c9a 100644 --- a/src/core/api/searchSuggestApi.js +++ b/src/core/api/searchSuggestApi.js @@ -1,7 +1,9 @@ -import axios from "axios" +import axios from 'axios' const searchSuggestApi = async ({ query }) => { - const dataSearchSuggest = await axios(`${process.env.SELF_HOST}/api/shop/suggest?q=${query.trim()}`) + const dataSearchSuggest = await axios( + `${process.env.SELF_HOST}/api/shop/suggest?q=${query.trim()}` + ) return dataSearchSuggest } @@ -9,4 +11,4 @@ searchSuggestApi.defaultProps = { query: '' } -export default searchSuggestApi
\ No newline at end of file +export default searchSuggestApi diff --git a/src/core/components/Seo.jsx b/src/core/components/Seo.jsx index bcfaa6ef..e688077e 100644 --- a/src/core/components/Seo.jsx +++ b/src/core/components/Seo.jsx @@ -1,11 +1,11 @@ -import Head from "next/head" +import Head from 'next/head' const Seo = ({ title }) => { return ( <Head> - <title>{ title }</title> + <title>{title}</title> </Head> ) } -export default Seo
\ No newline at end of file +export default Seo diff --git a/src/core/components/elements/Alert/Alert.jsx b/src/core/components/elements/Alert/Alert.jsx index 3f5584b9..695be8a3 100644 --- a/src/core/components/elements/Alert/Alert.jsx +++ b/src/core/components/elements/Alert/Alert.jsx @@ -18,4 +18,4 @@ const Alert = ({ children, className, type }) => { ) } -export default Alert
\ No newline at end of file +export default Alert diff --git a/src/core/components/elements/Appbar/Appbar.jsx b/src/core/components/elements/Appbar/Appbar.jsx index 36df9edb..4300287f 100644 --- a/src/core/components/elements/Appbar/Appbar.jsx +++ b/src/core/components/elements/Appbar/Appbar.jsx @@ -1,33 +1,31 @@ -import { useRouter } from "next/router" -import Link from "../Link/Link" -import { HomeIcon, Bars3Icon, ShoppingCartIcon, ChevronLeftIcon } from "@heroicons/react/24/outline" +import { useRouter } from 'next/router' +import Link from '../Link/Link' +import { HomeIcon, Bars3Icon, ShoppingCartIcon, ChevronLeftIcon } from '@heroicons/react/24/outline' const AppBar = ({ title }) => { const router = useRouter() return ( - <nav className="sticky top-0 z-50 bg-white border-b border-gray_r-6 flex justify-between"> - <div className="flex items-center"> - <button type="button" className="p-4" onClick={() => router.back()}> - <ChevronLeftIcon className="w-6 stroke-2" /> + <nav className='sticky top-0 z-50 bg-white border-b border-gray_r-6 flex justify-between'> + <div className='flex items-center'> + <button type='button' className='p-4' onClick={() => router.back()}> + <ChevronLeftIcon className='w-6 stroke-2' /> </button> - <div className="font-medium text-h-sm line-clamp-1"> - { title } - </div> + <div className='font-medium text-h-sm line-clamp-1'>{title}</div> </div> - <div className="flex items-center px-2"> - <Link href="/shop/cart" className="py-4 px-2"> - <ShoppingCartIcon className="w-6 text-gray_r-12" /> + <div className='flex items-center px-2'> + <Link href='/shop/cart' className='py-4 px-2'> + <ShoppingCartIcon className='w-6 text-gray_r-12' /> </Link> - <Link href="/" className="py-4 px-2"> - <HomeIcon className="w-6 text-gray_r-12" /> + <Link href='/' className='py-4 px-2'> + <HomeIcon className='w-6 text-gray_r-12' /> </Link> - <Link href="/my/menu" className="py-4 px-2"> - <Bars3Icon className="w-6 text-gray_r-12" /> + <Link href='/my/menu' className='py-4 px-2'> + <Bars3Icon className='w-6 text-gray_r-12' /> </Link> </div> </nav> ) } -export default AppBar
\ No newline at end of file +export default AppBar diff --git a/src/core/components/elements/Badge/Badge.jsx b/src/core/components/elements/Badge/Badge.jsx index 5d8ebd1c..5e22db1a 100644 --- a/src/core/components/elements/Badge/Badge.jsx +++ b/src/core/components/elements/Badge/Badge.jsx @@ -1,14 +1,7 @@ -const Badge = ({ - children, - type, - ...props -}) => { +const Badge = ({ children, type, ...props }) => { return ( - <div - { ...props } - className={`${badgeStyle(type)} ${props?.className}`} - > - { children } + <div {...props} className={`${badgeStyle(type)} ${props?.className}`}> + {children} </div> ) } @@ -30,4 +23,4 @@ const badgeStyle = (type) => { return className.join(' ') } -export default Badge
\ No newline at end of file +export default Badge diff --git a/src/core/components/elements/Divider/Divider.jsx b/src/core/components/elements/Divider/Divider.jsx index 355cd509..ce54a2ea 100644 --- a/src/core/components/elements/Divider/Divider.jsx +++ b/src/core/components/elements/Divider/Divider.jsx @@ -1,11 +1,7 @@ -const Divider = (props) => { - return ( - <div className={`h-1 bg-gray_r-4 ${props.className}`} /> - ) -} +const Divider = (props) => <div className={`h-1 bg-gray_r-4 ${props.className}`} /> Divider.defaultProps = { className: '' } -export default Divider
\ No newline at end of file +export default Divider diff --git a/src/core/components/elements/Image/Image.jsx b/src/core/components/elements/Image/Image.jsx index a6f0b00c..ac82aaaf 100644 --- a/src/core/components/elements/Image/Image.jsx +++ b/src/core/components/elements/Image/Image.jsx @@ -1,18 +1,18 @@ -import { LazyLoadImage } from "react-lazy-load-image-component" -import "react-lazy-load-image-component/src/effects/opacity.css" +import { LazyLoadImage } from 'react-lazy-load-image-component' +import 'react-lazy-load-image-component/src/effects/opacity.css' const Image = ({ ...props }) => ( <> <LazyLoadImage - { ...props } + {...props} src={props.src || '/images/noimage.jpeg'} - placeholderSrc="/images/indoteknik-placeholder.png" + placeholderSrc='/images/indoteknik-placeholder.png' alt={props.src ? props.alt : 'Image Not Found - Indoteknik'} - wrapperClassName="bg-white" + wrapperClassName='bg-white' /> </> ) Image.defaultProps = LazyLoadImage.defaultProps -export default Image
\ No newline at end of file +export default Image diff --git a/src/core/components/elements/Link/Link.jsx b/src/core/components/elements/Link/Link.jsx index 897cf6d7..dbc65338 100644 --- a/src/core/components/elements/Link/Link.jsx +++ b/src/core/components/elements/Link/Link.jsx @@ -1,9 +1,9 @@ -import NextLink from "next/link" +import NextLink from 'next/link' const Link = ({ children, ...props }) => { return ( - <NextLink - {...props} + <NextLink + {...props} scroll={false} className={`block font-medium text-red_r-11 ${props?.className || ''}`} > @@ -14,4 +14,4 @@ const Link = ({ children, ...props }) => { Link.defaultProps = NextLink.defaultProps -export default Link
\ No newline at end of file +export default Link diff --git a/src/core/components/elements/Navbar/Navbar.jsx b/src/core/components/elements/Navbar/Navbar.jsx index f10ebd63..e2caebfe 100644 --- a/src/core/components/elements/Navbar/Navbar.jsx +++ b/src/core/components/elements/Navbar/Navbar.jsx @@ -1,38 +1,38 @@ -import dynamic from "next/dynamic" -import Image from "next/image" -import IndoteknikLogo from "@/images/logo.png" -import { Bars3Icon, HeartIcon, ShoppingCartIcon } from "@heroicons/react/24/outline" -import Link from "../Link/Link" -import useSidebar from "@/core/hooks/useSidebar" +import dynamic from 'next/dynamic' +import Image from 'next/image' +import IndoteknikLogo from '@/images/logo.png' +import { Bars3Icon, HeartIcon, ShoppingCartIcon } from '@heroicons/react/24/outline' +import Link from '../Link/Link' +import useSidebar from '@/core/hooks/useSidebar' -const Search = dynamic(() => import("./Search")) +const Search = dynamic(() => import('./Search')) const Navbar = () => { const { Sidebar, open } = useSidebar() return ( <> - <nav className="px-4 py-2 pb-3 sticky top-0 z-50 bg-white shadow"> - <div className="flex justify-between items-center mb-2"> - <Link href="/"> - <Image src={IndoteknikLogo} alt="Indoteknik Logo" width={120} height={40} /> + <nav className='px-4 py-2 pb-3 sticky top-0 z-50 bg-white shadow'> + <div className='flex justify-between items-center mb-2'> + <Link href='/'> + <Image src={IndoteknikLogo} alt='Indoteknik Logo' width={120} height={40} /> </Link> - <div className="flex gap-x-3"> - <Link href="/my/wishlist"> - <HeartIcon className="w-6 text-gray_r-12" /> + <div className='flex gap-x-3'> + <Link href='/my/wishlist'> + <HeartIcon className='w-6 text-gray_r-12' /> </Link> - <Link href="/shop/cart"> - <ShoppingCartIcon className="w-6 text-gray_r-12" /> + <Link href='/shop/cart'> + <ShoppingCartIcon className='w-6 text-gray_r-12' /> </Link> - <button type="button" onClick={open}> - <Bars3Icon className="w-6 text-gray_r-12" /> + <button type='button' onClick={open}> + <Bars3Icon className='w-6 text-gray_r-12' /> </button> </div> </div> <Search /> </nav> - { Sidebar } + {Sidebar} </> ) } -export default Navbar
\ No newline at end of file +export default Navbar diff --git a/src/core/components/elements/Navbar/Search.jsx b/src/core/components/elements/Navbar/Search.jsx index cca1a97c..6f0e4dd9 100644 --- a/src/core/components/elements/Navbar/Search.jsx +++ b/src/core/components/elements/Navbar/Search.jsx @@ -1,22 +1,22 @@ -import searchSuggestApi from "@/core/api/searchSuggestApi" -import { MagnifyingGlassIcon } from "@heroicons/react/24/outline" -import { useCallback, useEffect, useRef, useState } from "react" -import Link from "../Link/Link" -import { useRouter } from "next/router" +import searchSuggestApi from '@/core/api/searchSuggestApi' +import { MagnifyingGlassIcon } from '@heroicons/react/24/outline' +import { useCallback, useEffect, useRef, useState } from 'react' +import Link from '../Link/Link' +import { useRouter } from 'next/router' const Search = () => { const router = useRouter() const queryRef = useRef() - const [ query, setQuery ] = useState('') - const [ suggestions, setSuggestions ] = useState([]) + const [query, setQuery] = useState('') + const [suggestions, setSuggestions] = useState([]) useEffect(() => { setQuery(router.query.q) }, [router.query]) - + const loadSuggestion = useCallback(() => { if (query && document.activeElement == queryRef.current) { - (async () => { + ;(async () => { const dataSuggestion = await searchSuggestApi({ query }) setSuggestions(dataSuggestion.data.suggestions) })() @@ -24,7 +24,7 @@ const Search = () => { } else { setSuggestions([]) } - }, [ query ]) + }, [query]) useEffect(() => { if (query && document.activeElement == queryRef.current) { @@ -32,7 +32,7 @@ const Search = () => { } else { setSuggestions([]) } - }, [ loadSuggestion, query ]) + }, [loadSuggestion, query]) const handleSubmit = (e) => { e.preventDefault() @@ -50,40 +50,38 @@ const Search = () => { } return ( - <form - onSubmit={handleSubmit} - className="flex relative" - > - <input - type="text" + <form onSubmit={handleSubmit} className='flex relative'> + <input + type='text' ref={queryRef} - className="form-input p-3 rounded-r-none border-r-0 focus:border-gray_r-6" - placeholder="Ketik nama, part number, merk" + className='form-input p-3 rounded-r-none border-r-0 focus:border-gray_r-6' + placeholder='Ketik nama, part number, merk' value={query} onChange={(e) => setQuery(e.target.value)} onBlur={onInputBlur} onFocus={loadSuggestion} /> - <button - type="submit" - className="rounded-r border border-l-0 border-gray_r-6 px-2" - > - <MagnifyingGlassIcon className="w-6" /> + <button type='submit' className='rounded-r border border-l-0 border-gray_r-6 px-2'> + <MagnifyingGlassIcon className='w-6' /> </button> - { suggestions.length > 1 && ( + {suggestions.length > 1 && ( <> - <div className="absolute w-full top-[50px] rounded-b bg-gray_r-1 border border-gray_r-6 divide-y divide-gray_r-6"> + <div className='absolute w-full top-[50px] rounded-b bg-gray_r-1 border border-gray_r-6 divide-y divide-gray_r-6'> {suggestions.map((suggestion, index) => ( - <Link href={`/shop/search?q=${suggestion.term}`} key={index} className="px-3 py-3 !text-gray_r-12 font-normal"> + <Link + href={`/shop/search?q=${suggestion.term}`} + key={index} + className='px-3 py-3 !text-gray_r-12 font-normal' + > {suggestion.term} </Link> ))} </div> </> - ) } + )} </form> ) } -export default Search
\ No newline at end of file +export default Search diff --git a/src/core/components/elements/Pagination/Pagination.js b/src/core/components/elements/Pagination/Pagination.js index 485295fe..c009171f 100644 --- a/src/core/components/elements/Pagination/Pagination.js +++ b/src/core/components/elements/Pagination/Pagination.js @@ -1,4 +1,4 @@ -import Link from "../Link/Link" +import Link from '../Link/Link' const Pagination = ({ pageCount, currentPage, url, className }) => { let firstPage = false @@ -6,54 +6,70 @@ const Pagination = ({ pageCount, currentPage, url, className }) => { let dotsPrevPage = false let dotsNextPage = false let urlParameterPrefix = url.includes('?') ? '&' : '?' - - return pageCount > 1 && ( - <div className={`pagination ${className}`}> - { Array.from(Array(pageCount)).map((v, i) => { - let page = i + 1 - let rangePrevPage = currentPage - 2 - let rangeNextPage = currentPage + 2 - let PageComponent = <Link key={i} href={`${url + urlParameterPrefix}page=${page}`} className={"pagination-item" + (page == currentPage ? " pagination-item--active " : "")}>{page}</Link> - let DotsComponent = <div key={i} className="pagination-dots">...</div> - if (pageCount == 7) { - return PageComponent - } + return ( + pageCount > 1 && ( + <div className={`pagination ${className}`}> + {Array.from(Array(pageCount)).map((v, i) => { + let page = i + 1 + let rangePrevPage = currentPage - 2 + let rangeNextPage = currentPage + 2 + let PageComponent = ( + <Link + key={i} + href={`${url + urlParameterPrefix}page=${page}`} + className={ + 'pagination-item' + (page == currentPage ? ' pagination-item--active ' : '') + } + > + {page} + </Link> + ) + let DotsComponent = ( + <div key={i} className='pagination-dots'> + ... + </div> + ) - if (currentPage == 1) rangeNextPage += 3 - if (currentPage == 2) rangeNextPage += 2 - if (currentPage == 3) rangeNextPage += 1 - if (currentPage == 4) rangePrevPage -= 1 - if (currentPage == pageCount) rangePrevPage -= 3 - if (currentPage == pageCount - 1) rangePrevPage -= 2 - if (currentPage == pageCount - 2) rangePrevPage -= 1 - if (currentPage == pageCount - 3) rangeNextPage += 1 + if (pageCount == 7) { + return PageComponent + } - if (page > rangePrevPage && page < rangeNextPage) { - return PageComponent - } + if (currentPage == 1) rangeNextPage += 3 + if (currentPage == 2) rangeNextPage += 2 + if (currentPage == 3) rangeNextPage += 1 + if (currentPage == 4) rangePrevPage -= 1 + if (currentPage == pageCount) rangePrevPage -= 3 + if (currentPage == pageCount - 1) rangePrevPage -= 2 + if (currentPage == pageCount - 2) rangePrevPage -= 1 + if (currentPage == pageCount - 3) rangeNextPage += 1 - if (page == 1 && rangePrevPage >= 1 && !firstPage) { - firstPage = true - return PageComponent - } + if (page > rangePrevPage && page < rangeNextPage) { + return PageComponent + } - if (page == pageCount && rangeNextPage <= pageCount && !lastPage) { - lastPage = true - return PageComponent - } + if (page == 1 && rangePrevPage >= 1 && !firstPage) { + firstPage = true + return PageComponent + } - if (page > currentPage && (pageCount - currentPage) > 1 && !dotsNextPage) { - dotsNextPage = true - return DotsComponent - } + if (page == pageCount && rangeNextPage <= pageCount && !lastPage) { + lastPage = true + return PageComponent + } - if (page < currentPage && (currentPage - 1) > 1 && !dotsPrevPage) { - dotsPrevPage = true - return DotsComponent - } - }) } - </div> + if (page > currentPage && pageCount - currentPage > 1 && !dotsNextPage) { + dotsNextPage = true + return DotsComponent + } + + if (page < currentPage && currentPage - 1 > 1 && !dotsPrevPage) { + dotsPrevPage = true + return DotsComponent + } + })} + </div> + ) ) } @@ -61,4 +77,4 @@ Pagination.defaultProps = { className: '' } -export default Pagination
\ No newline at end of file +export default Pagination diff --git a/src/core/components/elements/Popup/BottomPopup.jsx b/src/core/components/elements/Popup/BottomPopup.jsx index c3c380c0..af1149ca 100644 --- a/src/core/components/elements/Popup/BottomPopup.jsx +++ b/src/core/components/elements/Popup/BottomPopup.jsx @@ -1,15 +1,10 @@ -import { XMarkIcon } from "@heroicons/react/24/outline" -import { AnimatePresence, motion } from "framer-motion" -import { useEffect } from "react" +import { XMarkIcon } from '@heroicons/react/24/outline' +import { AnimatePresence, motion } from 'framer-motion' +import { useEffect } from 'react' const transition = { ease: 'linear', duration: 0.2 } -const BottomPopup = ({ - children, - active = false, - title, - close -}) => { +const BottomPopup = ({ children, active = false, title, close }) => { useEffect(() => { if (active) { document.querySelector('html, body').classList.add('overflow-hidden') @@ -21,10 +16,10 @@ const BottomPopup = ({ return ( <> <AnimatePresence> - { active && ( + {active && ( <> <motion.div - className="overlay" + className='overlay' initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} @@ -36,21 +31,21 @@ const BottomPopup = ({ animate={{ bottom: 0 }} exit={{ bottom: '-100%' }} transition={transition} - className="fixed left-0 w-full border-t border-gray_r-6 rounded-t-xl z-[60] p-4 pt-0 bg-white" + className='fixed left-0 w-full border-t border-gray_r-6 rounded-t-xl z-[60] p-4 pt-0 bg-white' > - <div className="flex justify-between py-4"> - <div className="font-semibold text-h-sm">{ title }</div> - <button type="button" onClick={close}> - <XMarkIcon className="w-5 stroke-2" /> + <div className='flex justify-between py-4'> + <div className='font-semibold text-h-sm'>{title}</div> + <button type='button' onClick={close}> + <XMarkIcon className='w-5 stroke-2' /> </button> </div> - { children } + {children} </motion.div> </> - ) } + )} </AnimatePresence> </> ) } -export default BottomPopup
\ No newline at end of file +export default BottomPopup diff --git a/src/core/components/elements/Select/HookFormSelect.jsx b/src/core/components/elements/Select/HookFormSelect.jsx index 45cd89b6..055a9c68 100644 --- a/src/core/components/elements/Select/HookFormSelect.jsx +++ b/src/core/components/elements/Select/HookFormSelect.jsx @@ -1,17 +1,14 @@ -import ReactSelect from "react-select" +import ReactSelect from 'react-select' -const HookFormSelect = ({ - field, - ...props -}) => ( +const HookFormSelect = ({ field, ...props }) => ( <ReactSelect - classNamePrefix="form-select" + classNamePrefix='form-select' ref={field.ref} onChange={(option) => field.onChange(option.value)} - value={field.value ? props.options.find(option => option.value === field.value) : ''} + value={field.value ? props.options.find((option) => option.value === field.value) : ''} isDisabled={props.disabled} {...props} /> ) -export default HookFormSelect
\ No newline at end of file +export default HookFormSelect diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx index 48ceacf6..08f1fed5 100644 --- a/src/core/components/elements/Sidebar/Sidebar.jsx +++ b/src/core/components/elements/Sidebar/Sidebar.jsx @@ -1,20 +1,16 @@ -import Link from "../Link/Link" -import greeting from "@/core/utils/greeting" -import useAuth from "@/core/hooks/useAuth" -import { AnimatePresence, motion } from "framer-motion" -import { CogIcon } from "@heroicons/react/24/outline" +import Link from '../Link/Link' +import greeting from '@/core/utils/greeting' +import useAuth from '@/core/hooks/useAuth' +import { AnimatePresence, motion } from 'framer-motion' +import { CogIcon } from '@heroicons/react/24/outline' -const Sidebar = ({ - active, - close -}) => { +const Sidebar = ({ active, close }) => { const auth = useAuth() const SidebarLink = ({ children, ...props }) => ( - <Link - {...props} - onClick={close} - >{ children }</Link> + <Link {...props} onClick={close}> + {children} + </Link> ) const itemClassName = 'px-4 py-3 block !text-gray_r-12/80 font-normal' @@ -23,10 +19,10 @@ const Sidebar = ({ return ( <> <AnimatePresence> - { active && ( + {active && ( <> <motion.div - className="overlay z-50" + className='overlay z-50' initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} @@ -34,55 +30,67 @@ const Sidebar = ({ onClick={close} /> <motion.div - className="fixed z-[55] top-0 h-full w-[80%] bg-white" + className='fixed z-[55] top-0 h-full w-[80%] bg-white' initial={{ left: '-80%' }} animate={{ left: 0 }} exit={{ left: '-80%' }} transition={transition} > - <div className="divide-y divide-gray_r-6"> - <div className="p-4 flex gap-x-3"> - { !auth && ( + <div className='divide-y divide-gray_r-6'> + <div className='p-4 flex gap-x-3'> + {!auth && ( <> - <Link onClick={close} href="/register" className="btn-yellow !text-gray_r-12 py-2 flex-1">Daftar</Link> - <Link onClick={close} href="/login" className="btn-solid-red !text-gray_r-1 py-2 flex-1">Masuk</Link> + <Link + onClick={close} + href='/register' + className='btn-yellow !text-gray_r-12 py-2 flex-1' + > + Daftar + </Link> + <Link + onClick={close} + href='/login' + className='btn-solid-red !text-gray_r-1 py-2 flex-1' + > + Masuk + </Link> </> - ) } - { auth && ( + )} + {auth && ( <> - <div className="text-caption-2 text-gray_r-11"> - { greeting() }, - <span className="text-body-2 text-gray_r-12 block mt-1 font-medium"> - { auth?.name } + <div className='text-caption-2 text-gray_r-11'> + {greeting()}, + <span className='text-body-2 text-gray_r-12 block mt-1 font-medium'> + {auth?.name} </span> </div> - <Link - onClick={close} - href="/my/menu" - className="!text-gray_r-11 ml-auto my-auto" + <Link + onClick={close} + href='/my/menu' + className='!text-gray_r-11 ml-auto my-auto' > - <CogIcon className="w-6" /> + <CogIcon className='w-6' /> </Link> </> - ) } + )} </div> - <SidebarLink className={itemClassName} href="/"> + <SidebarLink className={itemClassName} href='/'> Semua Brand </SidebarLink> - <SidebarLink className={itemClassName} href="/"> + <SidebarLink className={itemClassName} href='/'> Tentang Indoteknik </SidebarLink> - <SidebarLink className={itemClassName} href="/"> + <SidebarLink className={itemClassName} href='/'> Pusat Bantuan </SidebarLink> <button className={`${itemClassName} w-full text-left`}>Kategori</button> </div> </motion.div> </> - ) } + )} </AnimatePresence> </> ) } -export default Sidebar
\ No newline at end of file +export default Sidebar diff --git a/src/core/components/elements/Skeleton/BrandSkeleton.jsx b/src/core/components/elements/Skeleton/BrandSkeleton.jsx index ce5a994d..9a7a51f9 100644 --- a/src/core/components/elements/Skeleton/BrandSkeleton.jsx +++ b/src/core/components/elements/Skeleton/BrandSkeleton.jsx @@ -1,8 +1,8 @@ const BrandSkeleton = () => ( - <div role="status" className="animate-pulse"> - <div className="h-12 bg-gray-200 rounded"></div> - <span className="sr-only">Loading...</span> + <div role='status' className='animate-pulse'> + <div className='h-12 bg-gray-200 rounded'></div> + <span className='sr-only'>Loading...</span> </div> ) -export default BrandSkeleton
\ No newline at end of file +export default BrandSkeleton diff --git a/src/core/components/elements/Skeleton/ImageSkeleton.jsx b/src/core/components/elements/Skeleton/ImageSkeleton.jsx index 2cda9536..2ca6b2a3 100644 --- a/src/core/components/elements/Skeleton/ImageSkeleton.jsx +++ b/src/core/components/elements/Skeleton/ImageSkeleton.jsx @@ -1,10 +1,18 @@ const ImageSkeleton = () => ( - <div role="status" className="animate-pulse"> - <div className="flex items-center justify-center h-56 mb-4 bg-gray-300 rounded" aria-busy> - <svg className="w-12 h-12 text-gray-200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" viewBox="0 0 640 512"><path d="M480 80C480 35.82 515.8 0 560 0C604.2 0 640 35.82 640 80C640 124.2 604.2 160 560 160C515.8 160 480 124.2 480 80zM0 456.1C0 445.6 2.964 435.3 8.551 426.4L225.3 81.01C231.9 70.42 243.5 64 256 64C268.5 64 280.1 70.42 286.8 81.01L412.7 281.7L460.9 202.7C464.1 196.1 472.2 192 480 192C487.8 192 495 196.1 499.1 202.7L631.1 419.1C636.9 428.6 640 439.7 640 450.9C640 484.6 612.6 512 578.9 512H55.91C25.03 512 .0006 486.1 .0006 456.1L0 456.1z"/></svg> + <div role='status' className='animate-pulse'> + <div className='flex items-center justify-center h-56 mb-4 bg-gray-300 rounded' aria-busy> + <svg + className='w-12 h-12 text-gray-200' + xmlns='http://www.w3.org/2000/svg' + aria-hidden='true' + fill='currentColor' + viewBox='0 0 640 512' + > + <path d='M480 80C480 35.82 515.8 0 560 0C604.2 0 640 35.82 640 80C640 124.2 604.2 160 560 160C515.8 160 480 124.2 480 80zM0 456.1C0 445.6 2.964 435.3 8.551 426.4L225.3 81.01C231.9 70.42 243.5 64 256 64C268.5 64 280.1 70.42 286.8 81.01L412.7 281.7L460.9 202.7C464.1 196.1 472.2 192 480 192C487.8 192 495 196.1 499.1 202.7L631.1 419.1C636.9 428.6 640 439.7 640 450.9C640 484.6 612.6 512 578.9 512H55.91C25.03 512 .0006 486.1 .0006 456.1L0 456.1z' /> + </svg> </div> - <span className="sr-only">Loading...</span> + <span className='sr-only'>Loading...</span> </div> ) -export default ImageSkeleton
\ No newline at end of file +export default ImageSkeleton diff --git a/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx b/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx index 66b48f79..84d1c0d1 100644 --- a/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx +++ b/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx @@ -1,15 +1,26 @@ const ProductCardSkeleton = () => ( - <div role="status" className="p-4 max-w-sm rounded border border-gray-300 shadow animate-pulse md:p-6"> - <div className="flex items-center justify-center h-36 mb-4 bg-gray-300 rounded" aria-busy> - <svg className="w-12 h-12 text-gray-200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" viewBox="0 0 640 512"><path d="M480 80C480 35.82 515.8 0 560 0C604.2 0 640 35.82 640 80C640 124.2 604.2 160 560 160C515.8 160 480 124.2 480 80zM0 456.1C0 445.6 2.964 435.3 8.551 426.4L225.3 81.01C231.9 70.42 243.5 64 256 64C268.5 64 280.1 70.42 286.8 81.01L412.7 281.7L460.9 202.7C464.1 196.1 472.2 192 480 192C487.8 192 495 196.1 499.1 202.7L631.1 419.1C636.9 428.6 640 439.7 640 450.9C640 484.6 612.6 512 578.9 512H55.91C25.03 512 .0006 486.1 .0006 456.1L0 456.1z"/></svg> - </div> - <div className="h-2 bg-gray-200 rounded-full w-10 mb-1"></div> - <div className="h-2.5 bg-gray-200 rounded-full w-full mb-4"></div> - <div className="h-2 bg-gray-200 rounded-full mb-2.5"></div> - <div className="h-2 bg-gray-200 rounded-full mb-2.5"></div> - <div className="h-2 bg-gray-200 rounded-full"></div> - <span className="sr-only">Loading...</span> + <div + role='status' + className='p-4 max-w-sm rounded border border-gray-300 shadow animate-pulse md:p-6' + > + <div className='flex items-center justify-center h-36 mb-4 bg-gray-300 rounded' aria-busy> + <svg + className='w-12 h-12 text-gray-200' + xmlns='http://www.w3.org/2000/svg' + aria-hidden='true' + fill='currentColor' + viewBox='0 0 640 512' + > + <path d='M480 80C480 35.82 515.8 0 560 0C604.2 0 640 35.82 640 80C640 124.2 604.2 160 560 160C515.8 160 480 124.2 480 80zM0 456.1C0 445.6 2.964 435.3 8.551 426.4L225.3 81.01C231.9 70.42 243.5 64 256 64C268.5 64 280.1 70.42 286.8 81.01L412.7 281.7L460.9 202.7C464.1 196.1 472.2 192 480 192C487.8 192 495 196.1 499.1 202.7L631.1 419.1C636.9 428.6 640 439.7 640 450.9C640 484.6 612.6 512 578.9 512H55.91C25.03 512 .0006 486.1 .0006 456.1L0 456.1z' /> + </svg> + </div> + <div className='h-2 bg-gray-200 rounded-full w-10 mb-1'></div> + <div className='h-2.5 bg-gray-200 rounded-full w-full mb-4'></div> + <div className='h-2 bg-gray-200 rounded-full mb-2.5'></div> + <div className='h-2 bg-gray-200 rounded-full mb-2.5'></div> + <div className='h-2 bg-gray-200 rounded-full'></div> + <span className='sr-only'>Loading...</span> </div> ) -export default ProductCardSkeleton
\ No newline at end of file +export default ProductCardSkeleton diff --git a/src/core/components/elements/Spinner/Spinner.jsx b/src/core/components/elements/Spinner/Spinner.jsx index 60f88279..4639db1d 100644 --- a/src/core/components/elements/Spinner/Spinner.jsx +++ b/src/core/components/elements/Spinner/Spinner.jsx @@ -1,13 +1,25 @@ const Spinner = ({ className }) => { return ( - <div role="status"> - <svg aria-hidden="true" className={"animate-spin " + className} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/> - <path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/> - </svg> - <span className="sr-only">Loading...</span> + <div role='status'> + <svg + aria-hidden='true' + className={'animate-spin ' + className} + viewBox='0 0 100 101' + fill='none' + xmlns='http://www.w3.org/2000/svg' + > + <path + d='M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z' + fill='currentColor' + /> + <path + d='M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z' + fill='currentFill' + /> + </svg> + <span className='sr-only'>Loading...</span> </div> ) } -export default Spinner
\ No newline at end of file +export default Spinner diff --git a/src/core/components/layouts/AnimationLayout.jsx b/src/core/components/layouts/AnimationLayout.jsx index cf2b06d5..357187b2 100644 --- a/src/core/components/layouts/AnimationLayout.jsx +++ b/src/core/components/layouts/AnimationLayout.jsx @@ -1,22 +1,24 @@ import { motion } from 'framer-motion' const AnimationLayout = ({ children, ...props }) => { - const transition = { - ease: 'easeIn', + const transition = { + ease: 'easeIn', duration: 0.3 } - return children && ( - <motion.main - initial={{ opacity: 0, x: 0, y: 0 }} - animate={{ opacity: 1, x: 0, y: 0 }} - exit={{ opacity: 0, x: 30, y: 0 }} - transition={transition} - {...props} - > - { children } - </motion.main> + return ( + children && ( + <motion.main + initial={{ opacity: 0, x: 0, y: 0 }} + animate={{ opacity: 1, x: 0, y: 0 }} + exit={{ opacity: 0, x: 30, y: 0 }} + transition={transition} + {...props} + > + {children} + </motion.main> + ) ) } -export default AnimationLayout
\ No newline at end of file +export default AnimationLayout diff --git a/src/core/components/layouts/AppLayout.jsx b/src/core/components/layouts/AppLayout.jsx index 3e986477..3e3c8ee5 100644 --- a/src/core/components/layouts/AppLayout.jsx +++ b/src/core/components/layouts/AppLayout.jsx @@ -1,15 +1,15 @@ -import AppBar from "../elements/Appbar/Appbar" -import AnimationLayout from "./AnimationLayout" +import AppBar from '../elements/Appbar/Appbar' +import AnimationLayout from './AnimationLayout' const AppLayout = ({ children, title }) => { return ( <> <AnimationLayout> - <AppBar title={title}/> - { children } + <AppBar title={title} /> + {children} </AnimationLayout> </> ) } -export default AppLayout
\ No newline at end of file +export default AppLayout diff --git a/src/core/components/layouts/BasicLayout.jsx b/src/core/components/layouts/BasicLayout.jsx index 98134b32..6f176737 100644 --- a/src/core/components/layouts/BasicLayout.jsx +++ b/src/core/components/layouts/BasicLayout.jsx @@ -1,17 +1,15 @@ -import dynamic from "next/dynamic" +import dynamic from 'next/dynamic' -const Navbar = dynamic(() => import("../elements/Navbar/Navbar")) -const AnimationLayout = dynamic(() => import("./AnimationLayout")) +const Navbar = dynamic(() => import('../elements/Navbar/Navbar')) +const AnimationLayout = dynamic(() => import('./AnimationLayout')) const BasicLayout = ({ children }) => { return ( <> <Navbar /> - <AnimationLayout> - { children } - </AnimationLayout> + <AnimationLayout>{children}</AnimationLayout> </> ) } -export default BasicLayout
\ No newline at end of file +export default BasicLayout diff --git a/src/core/hooks/useActive.js b/src/core/hooks/useActive.js index e3a371cb..c39cbdca 100644 --- a/src/core/hooks/useActive.js +++ b/src/core/hooks/useActive.js @@ -1,7 +1,7 @@ -import { useState } from "react" +import { useState } from 'react' const useActive = () => { - const [ active, setActive ] = useState(false) + const [active, setActive] = useState(false) const activate = () => { setActive(true) @@ -12,8 +12,10 @@ const useActive = () => { } return { - activate, deactivate, active + activate, + deactivate, + active } } -export default useActive
\ No newline at end of file +export default useActive diff --git a/src/core/hooks/useAuth.js b/src/core/hooks/useAuth.js index 13f04454..af62e45c 100644 --- a/src/core/hooks/useAuth.js +++ b/src/core/hooks/useAuth.js @@ -1,5 +1,5 @@ -import { useEffect, useState } from "react" -import { getAuth } from "../utils/auth" +import { useEffect, useState } from 'react' +import { getAuth } from '../utils/auth' const useAuth = () => { const [auth, setAuth] = useState(null) @@ -12,4 +12,4 @@ const useAuth = () => { return auth } -export default useAuth
\ No newline at end of file +export default useAuth diff --git a/src/core/hooks/useSidebar.js b/src/core/hooks/useSidebar.js index 9388734a..c463fd81 100644 --- a/src/core/hooks/useSidebar.js +++ b/src/core/hooks/useSidebar.js @@ -1,6 +1,6 @@ -import useActive from "./useActive" -import SidebarComponent from "../components/elements/Sidebar/Sidebar" -import { useEffect } from "react" +import useActive from './useActive' +import SidebarComponent from '../components/elements/Sidebar/Sidebar' +import { useEffect } from 'react' const useSidebar = () => { const { active, activate, deactivate } = useActive() @@ -19,4 +19,4 @@ const useSidebar = () => { } } -export default useSidebar
\ No newline at end of file +export default useSidebar diff --git a/src/core/utils/address.js b/src/core/utils/address.js index b89dd924..c545d34b 100644 --- a/src/core/utils/address.js +++ b/src/core/utils/address.js @@ -25,7 +25,4 @@ const updateItemAddress = (key, value) => { return } -export { - getItemAddress, - updateItemAddress -}
\ No newline at end of file +export { getItemAddress, updateItemAddress } diff --git a/src/core/utils/auth.js b/src/core/utils/auth.js index 6aeba02b..13e0e79d 100644 --- a/src/core/utils/auth.js +++ b/src/core/utils/auth.js @@ -1,8 +1,4 @@ -import { - deleteCookie, - getCookie, - setCookie -} from 'cookies-next' +import { deleteCookie, getCookie, setCookie } from 'cookies-next' const getAuth = () => { let auth = getCookie('auth') @@ -22,8 +18,4 @@ const deleteAuth = () => { return true } -export { - getAuth, - setAuth, - deleteAuth -}
\ No newline at end of file +export { getAuth, setAuth, deleteAuth } diff --git a/src/core/utils/cart.js b/src/core/utils/cart.js index 52e157f2..fd42ee4e 100644 --- a/src/core/utils/cart.js +++ b/src/core/utils/cart.js @@ -33,9 +33,4 @@ const deleteItemCart = ({ productId }) => { return true } -export { - getCart, - getItemCart, - updateItemCart, - deleteItemCart -}
\ No newline at end of file +export { getCart, getItemCart, updateItemCart, deleteItemCart } diff --git a/src/core/utils/currencyFormat.js b/src/core/utils/currencyFormat.js index 31f4a8dc..12b68111 100644 --- a/src/core/utils/currencyFormat.js +++ b/src/core/utils/currencyFormat.js @@ -1,10 +1,10 @@ const currencyFormat = (value) => { const currency = new Intl.NumberFormat('id-ID', { - style: 'currency', + style: 'currency', currency: 'IDR', maximumFractionDigits: 0 }) return currency.format(value) } -export default currencyFormat
\ No newline at end of file +export default currencyFormat diff --git a/src/core/utils/getFileBase64.js b/src/core/utils/getFileBase64.js index 78013e43..4fa7316b 100644 --- a/src/core/utils/getFileBase64.js +++ b/src/core/utils/getFileBase64.js @@ -1,11 +1,12 @@ -const getFileBase64 = file => new Promise((resolve, reject) => { - let reader = new FileReader(); - reader.readAsBinaryString(file); - reader.onload = () => { - let result = reader.result; - resolve(btoa(result)); - }; - reader.onerror = error => reject(error); -}); +const getFileBase64 = (file) => + new Promise((resolve, reject) => { + let reader = new FileReader() + reader.readAsBinaryString(file) + reader.onload = () => { + let result = reader.result + resolve(btoa(result)) + } + reader.onerror = (error) => reject(error) + }) -export default getFileBase64;
\ No newline at end of file +export default getFileBase64 diff --git a/src/core/utils/greeting.js b/src/core/utils/greeting.js index 014c0e3c..aaaade7a 100644 --- a/src/core/utils/greeting.js +++ b/src/core/utils/greeting.js @@ -6,4 +6,4 @@ const greeting = () => { return 'Selamat Malam' } -export default greeting
\ No newline at end of file +export default greeting diff --git a/src/core/utils/slug.js b/src/core/utils/slug.js index fab37330..7010008a 100644 --- a/src/core/utils/slug.js +++ b/src/core/utils/slug.js @@ -1,15 +1,21 @@ import toTitleCase from './toTitleCase' const createSlug = (prefix, name, id) => { - let slug = name?.trim().replace(new RegExp(/[^A-Za-z0-9]/, 'g'), '-').toLowerCase() + '-' + id + let slug = + name + ?.trim() + .replace(new RegExp(/[^A-Za-z0-9]/, 'g'), '-') + .toLowerCase() + + '-' + + id let splitSlug = slug.split('-') - let filterSlugFromEmptyChar = splitSlug.filter(x => x != '') + let filterSlugFromEmptyChar = splitSlug.filter((x) => x != '') return prefix + filterSlugFromEmptyChar.join('-') } const getIdFromSlug = (slug) => { let id = slug.split('-') - return id[id.length-1] + return id[id.length - 1] } const getNameFromSlug = (slug) => { @@ -18,8 +24,4 @@ const getNameFromSlug = (slug) => { return toTitleCase(name.join(' ')) } -export { - createSlug, - getIdFromSlug, - getNameFromSlug -}
\ No newline at end of file +export { createSlug, getIdFromSlug, getNameFromSlug } diff --git a/src/core/utils/toTitleCase.js b/src/core/utils/toTitleCase.js index b2751f0b..4335824d 100644 --- a/src/core/utils/toTitleCase.js +++ b/src/core/utils/toTitleCase.js @@ -1,10 +1,7 @@ const toTitleCase = (str) => { - return str.replace( - /\w\S*/g, - function(txt) { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - } - ); + return str.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() + }) } -export default toTitleCase
\ No newline at end of file +export default toTitleCase 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 diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index 33573480..0110576a 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -2,7 +2,7 @@ import '../styles/globals.css' import NextProgress from 'next-progress' import { useRouter } from 'next/router' import { AnimatePresence } from 'framer-motion' -import { Toaster } from "react-hot-toast" +import { Toaster } from 'react-hot-toast' import { QueryClient, QueryClientProvider } from 'react-query' const queryClient = new QueryClient() @@ -13,19 +13,15 @@ function MyApp({ Component, pageProps }) { return ( <> <Toaster - position="top-center" + position='top-center' toastOptions={{ duration: 3000, className: 'border border-gray_r-8' }} /> - <NextProgress color="#F01C21" options={{ showSpinner: false }} /> + <NextProgress color='#F01C21' options={{ showSpinner: false }} /> <QueryClientProvider client={queryClient}> - <AnimatePresence - mode='wait' - initial={false} - onExitComplete={() => window.scrollTo(0, 0)} - > + <AnimatePresence mode='wait' initial={false} onExitComplete={() => window.scrollTo(0, 0)}> <Component {...pageProps} key={router.asPath} /> </AnimatePresence> </QueryClientProvider> diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index 5e5f1b6a..c1e00d16 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -1,5 +1,5 @@ -import axios from "axios" -import camelcaseObjectDeep from "camelcase-object-deep" +import axios from 'axios' +import camelcaseObjectDeep from 'camelcase-object-deep' const productResponseMap = (products) => { return products.map((product) => { @@ -11,26 +11,26 @@ const productResponseMap = (products) => { lowestPrice: { price: product.price ? product.price[0] : 0, priceDiscount: product.price_discount ? product.price_discount[0] : 0, - discountPercentage: product.discount ? product.discount[0] : 0, + discountPercentage: product.discount ? product.discount[0] : 0 }, variantTotal: product.variant_total ? product.variant_total[0] : 0, stockTotal: product.stock_total ? product.stock_total[0] : 0, weight: product.weight ? product.weight[0] : 0, manufacture: {}, - categories: [], + categories: [] } if (product.manufacture_id && product.brand) { productMapped.manufacture = { id: product.manufacture_id ? product.manufacture_id[0] : '', - name: product.brand ? product.brand[0] : '', + name: product.brand ? product.brand[0] : '' } } productMapped.categories = [ { id: product.category_id ? product.category_id[0] : '', - name: product.category_name ? product.category_name[0] : '', + name: product.category_name ? product.category_name[0] : '' } ] @@ -39,8 +39,8 @@ const productResponseMap = (products) => { } export default async function handler(req, res) { - const { - q = '*', + const { + q = '*', page = 1, brand = '', category = '', @@ -83,7 +83,7 @@ export default async function handler(req, res) { if (brand) parameter.push(`fq=brand:${brand}`) if (category) parameter.push(`fq=category_name:${category}`) - + let result = await axios(process.env.SOLR_HOST + '/solr/products/select?' + parameter.join('&')) try { result.data.response.products = productResponseMap(result.data.response.docs) @@ -95,4 +95,4 @@ export default async function handler(req, res) { } catch (error) { res.status(400).json({ error: error.message }) } -}
\ No newline at end of file +} diff --git a/src/pages/api/shop/suggest.js b/src/pages/api/shop/suggest.js index 4e373a92..cc0ff2b3 100644 --- a/src/pages/api/shop/suggest.js +++ b/src/pages/api/shop/suggest.js @@ -1,15 +1,18 @@ -import axios from "axios"; +import axios from 'axios' export default async function handler(req, res) { - const { q = '' } = req.query; + const { q = '' } = req.query - let result = await axios(process.env.SOLR_HOST + `/solr/products/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.q=${q}`); + let result = await axios( + process.env.SOLR_HOST + + `/solr/products/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.q=${q}` + ) try { - res.status(200).json(result.data.suggest.mySuggester[q]); + res.status(200).json(result.data.suggest.mySuggester[q]) } catch (error) { res.status(400).json({ numFound: 0, suggestions: [] - }); + }) } -}
\ No newline at end of file +} diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 4cb40adb..19d3e59c 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -1,36 +1,36 @@ -import dynamic from "next/dynamic" -import Seo from "@/core/components/Seo" -import ImageSkeleton from "@/core/components/elements/Skeleton/ImageSkeleton" -import PopularProductSkeleton from "@/lib/home/components/Skeleton/PopularProductSkeleton" +import dynamic from 'next/dynamic' +import Seo from '@/core/components/Seo' +import ImageSkeleton from '@/core/components/elements/Skeleton/ImageSkeleton' +import PopularProductSkeleton from '@/lib/home/components/Skeleton/PopularProductSkeleton' -const BasicLayout = dynamic(() => import("@/core/components/layouts/BasicLayout")) +const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')) -const HeroBanner = dynamic(() => import("@/lib/home/components/HeroBanner"), { +const HeroBanner = dynamic(() => import('@/lib/home/components/HeroBanner'), { loading: () => <ImageSkeleton /> }) -const PreferredBrand = dynamic(() => import("@/lib/home/components/PreferredBrand"), { +const PreferredBrand = dynamic(() => import('@/lib/home/components/PreferredBrand'), { loading: () => <PopularProductSkeleton /> }) -const PopularProduct = dynamic(() => import("@/lib/home/components/PopularProduct"), { +const PopularProduct = dynamic(() => import('@/lib/home/components/PopularProduct'), { loading: () => <PopularProductSkeleton /> }) -const CategoryHomeId = dynamic(() => import("@/lib/home/components/CategoryHomeId"), { +const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId'), { loading: () => <PopularProductSkeleton /> }) export default function Home() { return ( <BasicLayout> - <Seo title="Beranda - Indoteknik" /> + <Seo title='Beranda - Indoteknik' /> <HeroBanner /> - <div className="flex flex-col gap-y-6 my-6"> + <div className='flex flex-col gap-y-6 my-6'> <PreferredBrand /> <PopularProduct /> <CategoryHomeId /> </div> </BasicLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/login.jsx b/src/pages/login.jsx index b9009b8e..0039e6b5 100644 --- a/src/pages/login.jsx +++ b/src/pages/login.jsx @@ -1,7 +1,5 @@ -import LoginComponent from "@/lib/auth/components/Login" +import LoginComponent from '@/lib/auth/components/Login' export default function Login() { - return ( - <LoginComponent /> - ) -}
\ No newline at end of file + return <LoginComponent /> +} diff --git a/src/pages/my/address/[id]/edit.jsx b/src/pages/my/address/[id]/edit.jsx index feff85fd..a7c22147 100644 --- a/src/pages/my/address/[id]/edit.jsx +++ b/src/pages/my/address/[id]/edit.jsx @@ -1,10 +1,10 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import addressApi from "@/lib/address/api/addressApi" -import EditAddressComponent from "@/lib/address/components/EditAddress" +import AppLayout from '@/core/components/layouts/AppLayout' +import addressApi from '@/lib/address/api/addressApi' +import EditAddressComponent from '@/lib/address/components/EditAddress' export default function EditAddress({ id, defaultValues }) { return ( - <AppLayout title="Ubah Alamat"> + <AppLayout title='Ubah Alamat'> <EditAddressComponent id={id} defaultValues={defaultValues} /> </AppLayout> ) @@ -20,11 +20,11 @@ export async function getServerSideProps(context) { mobile: address.mobile, street: address.street, zip: address.zip, - city: address.city?.id || "", - oldDistrict: address.district?.id || "", - district: "", - oldSubDistrict: address.subDistrict?.id || "", - subDistrict: "", + city: address.city?.id || '', + oldDistrict: address.district?.id || '', + district: '', + oldSubDistrict: address.subDistrict?.id || '', + subDistrict: '' } return { props: { id, defaultValues } } } diff --git a/src/pages/my/address/create.jsx b/src/pages/my/address/create.jsx index dfc84444..ee905ee0 100644 --- a/src/pages/my/address/create.jsx +++ b/src/pages/my/address/create.jsx @@ -1,10 +1,10 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import CreateAddressComponent from "@/lib/address/components/CreateAddress" +import AppLayout from '@/core/components/layouts/AppLayout' +import CreateAddressComponent from '@/lib/address/components/CreateAddress' export default function CreateAddress() { return ( - <AppLayout title="Tambah Alamat"> + <AppLayout title='Tambah Alamat'> <CreateAddressComponent /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/my/address/index.jsx b/src/pages/my/address/index.jsx index 29e21c30..46a7075c 100644 --- a/src/pages/my/address/index.jsx +++ b/src/pages/my/address/index.jsx @@ -1,10 +1,10 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import AddressesComponent from "@/lib/address/components/Addresses" +import AppLayout from '@/core/components/layouts/AppLayout' +import AddressesComponent from '@/lib/address/components/Addresses' export default function Addresses() { return ( - <AppLayout title="Daftar Alamat"> + <AppLayout title='Daftar Alamat'> <AddressesComponent /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/my/invoice/[id].jsx b/src/pages/my/invoice/[id].jsx index a3cbeb5c..0d409878 100644 --- a/src/pages/my/invoice/[id].jsx +++ b/src/pages/my/invoice/[id].jsx @@ -1,13 +1,13 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import InvoiceComponent from "@/lib/invoice/components/Invoice" -import { useRouter } from "next/router" +import AppLayout from '@/core/components/layouts/AppLayout' +import InvoiceComponent from '@/lib/invoice/components/Invoice' +import { useRouter } from 'next/router' export default function Invoice() { const router = useRouter() return ( - <AppLayout title="Invoice & Faktur Pajak"> + <AppLayout title='Invoice & Faktur Pajak'> <InvoiceComponent id={router.query.id} /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/my/invoices.jsx b/src/pages/my/invoices.jsx index 04842110..fd50c3c8 100644 --- a/src/pages/my/invoices.jsx +++ b/src/pages/my/invoices.jsx @@ -1,10 +1,10 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import InvoicesComponent from "@/lib/invoice/components/Invoices" +import AppLayout from '@/core/components/layouts/AppLayout' +import InvoicesComponent from '@/lib/invoice/components/Invoices' export default function Invoices() { return ( - <AppLayout title="Invoice & Faktur Pajak"> + <AppLayout title='Invoice & Faktur Pajak'> <InvoicesComponent /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx index 3620fc36..0edc98ae 100644 --- a/src/pages/my/menu.jsx +++ b/src/pages/my/menu.jsx @@ -1,10 +1,10 @@ -import Divider from "@/core/components/elements/Divider/Divider" -import Link from "@/core/components/elements/Link/Link" -import AppLayout from "@/core/components/layouts/AppLayout" -import useAuth from "@/core/hooks/useAuth" -import { deleteAuth } from "@/core/utils/auth" -import { ChevronRightIcon, UserIcon } from "@heroicons/react/24/solid" -import { useRouter } from "next/router" +import Divider from '@/core/components/elements/Divider/Divider' +import Link from '@/core/components/elements/Link/Link' +import AppLayout from '@/core/components/layouts/AppLayout' +import useAuth from '@/core/hooks/useAuth' +import { deleteAuth } from '@/core/utils/auth' +import { ChevronRightIcon, UserIcon } from '@heroicons/react/24/solid' +import { useRouter } from 'next/router' export default function Menu() { const auth = useAuth() @@ -12,78 +12,56 @@ export default function Menu() { const logout = () => { deleteAuth() - router.push('/login') + router.push('/login') } return ( - <AppLayout title="Menu Utama"> - <Link href="/my/profile" className="p-4 flex items-center"> - <div className="rounded-full p-3 bg-gray_r-6 text-gray_r-12/80"> - <UserIcon className="w-5" /> + <AppLayout title='Menu Utama'> + <Link href='/my/profile' className='p-4 flex items-center'> + <div className='rounded-full p-3 bg-gray_r-6 text-gray_r-12/80'> + <UserIcon className='w-5' /> </div> - <div className="ml-4"> - <div className="font-semibold text-gray_r-12">{ auth?.name }</div> - { auth?.company && ( - <div className="badge-solid-red mt-1">Akun Bisnis</div> - ) } - { !auth?.company && ( - <div className="badge-gray mt-1">Akun Individu</div> - ) } + <div className='ml-4'> + <div className='font-semibold text-gray_r-12'>{auth?.name}</div> + {auth?.company && <div className='badge-solid-red mt-1'>Akun Bisnis</div>} + {!auth?.company && <div className='badge-gray mt-1'>Akun Individu</div>} </div> - <div className="ml-auto !text-gray_r-12"> - <ChevronRightIcon className="w-6" /> + <div className='ml-auto !text-gray_r-12'> + <ChevronRightIcon className='w-6' /> </div> </Link> <Divider /> - <div className="flex flex-col gap-y-6 py-6"> + <div className='flex flex-col gap-y-6 py-6'> <div> - <MenuHeader> - Aktivitas Pembelian - </MenuHeader> + <MenuHeader>Aktivitas Pembelian</MenuHeader> - <div className="divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4"> - <LinkItem href="/my/transactions"> - Daftar Transaksi - </LinkItem> - <LinkItem href="/my/invoices"> - Invoice & Faktur Pajak - </LinkItem> - <LinkItem href="/my/wishlist"> - Wishlist - </LinkItem> + <div className='divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4'> + <LinkItem href='/my/transactions'>Daftar Transaksi</LinkItem> + <LinkItem href='/my/invoices'>Invoice & Faktur Pajak</LinkItem> + <LinkItem href='/my/wishlist'>Wishlist</LinkItem> </div> </div> <div> - <MenuHeader> - Pusat Bantuan - </MenuHeader> + <MenuHeader>Pusat Bantuan</MenuHeader> - <div className="divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4"> - <LinkItem href="/"> - Customer Support - </LinkItem> - <LinkItem href="/"> - F.A.Q - </LinkItem> + <div className='divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4'> + <LinkItem href='/'>Customer Support</LinkItem> + <LinkItem href='/'>F.A.Q</LinkItem> </div> </div> <div> - <MenuHeader> - Pengaturan Akun - </MenuHeader> + <MenuHeader>Pengaturan Akun</MenuHeader> - <div className="divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4"> - <LinkItem href="/my/address"> - Daftar Alamat - </LinkItem> + <div className='divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4'> + <LinkItem href='/my/address'>Daftar Alamat</LinkItem> </div> - <div onClick={logout} className="p-4 mt-2"> - <button className="w-full btn-red">Keluar Akun</button> + <div onClick={logout} className='p-4 mt-2'> + <button className='w-full btn-red'>Keluar Akun</button> </div> </div> </div> @@ -92,17 +70,16 @@ export default function Menu() { } const MenuHeader = ({ children, ...props }) => ( - <div {...props} className="font-medium px-4 flex"> - { children } - + <div {...props} className='font-medium px-4 flex'> + {children} </div> ) const LinkItem = ({ children, ...props }) => ( - <Link {...props} className="!text-gray_r-11 !font-normal p-4 flex items-center"> - { children } - <div className="ml-auto !text-gray_r-11"> - <ChevronRightIcon className="w-5" /> + <Link {...props} className='!text-gray_r-11 !font-normal p-4 flex items-center'> + {children} + <div className='ml-auto !text-gray_r-11'> + <ChevronRightIcon className='w-5' /> </div> </Link> -)
\ No newline at end of file +) diff --git a/src/pages/my/transaction/[id].jsx b/src/pages/my/transaction/[id].jsx index 4b81b2a3..ae27ab88 100644 --- a/src/pages/my/transaction/[id].jsx +++ b/src/pages/my/transaction/[id].jsx @@ -1,13 +1,13 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import TransactionComponent from "@/lib/transaction/components/Transaction" -import { useRouter } from "next/router" +import AppLayout from '@/core/components/layouts/AppLayout' +import TransactionComponent from '@/lib/transaction/components/Transaction' +import { useRouter } from 'next/router' export default function Transaction() { const router = useRouter() return ( - <AppLayout title="Transaksi"> + <AppLayout title='Transaksi'> <TransactionComponent id={router.query.id} /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/my/transactions.jsx b/src/pages/my/transactions.jsx index a530afcc..d18a00f4 100644 --- a/src/pages/my/transactions.jsx +++ b/src/pages/my/transactions.jsx @@ -1,12 +1,12 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import dynamic from "next/dynamic" +import AppLayout from '@/core/components/layouts/AppLayout' +import dynamic from 'next/dynamic' -const TransactionsComponent = dynamic(() => import("@/lib/transaction/components/Transactions")) +const TransactionsComponent = dynamic(() => import('@/lib/transaction/components/Transactions')) export default function Transactions() { return ( - <AppLayout title="Transaksi"> + <AppLayout title='Transaksi'> <TransactionsComponent /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/my/wishlist.jsx b/src/pages/my/wishlist.jsx index b7a3e4fe..f1c0bf28 100644 --- a/src/pages/my/wishlist.jsx +++ b/src/pages/my/wishlist.jsx @@ -1,10 +1,10 @@ -import AppLayout from "@/core/components/layouts/AppLayout" -import Wishlists from "@/lib/wishlist/components/Wishlists" +import AppLayout from '@/core/components/layouts/AppLayout' +import Wishlists from '@/lib/wishlist/components/Wishlists' export default function Wishlist() { return ( - <AppLayout title="Wishlist"> + <AppLayout title='Wishlist'> <Wishlists /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/shop/brands/[slug].jsx b/src/pages/shop/brands/[slug].jsx index da3ee84d..33f81fa2 100644 --- a/src/pages/shop/brands/[slug].jsx +++ b/src/pages/shop/brands/[slug].jsx @@ -1,11 +1,11 @@ -import dynamic from "next/dynamic" -import { getIdFromSlug, getNameFromSlug } from "@/core/utils/slug" -import { useRouter } from "next/router" -import _ from "lodash" +import dynamic from 'next/dynamic' +import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug' +import { useRouter } from 'next/router' +import _ from 'lodash' -const BasicLayout = dynamic(() => import("@/core/components/layouts/BasicLayout")) -const ProductSearch = dynamic(() => import("@/lib/product/components/ProductSearch")) -const Brand = dynamic(() => import("@/lib/brand/components/Brand")) +const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')) +const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch')) +const Brand = dynamic(() => import('@/lib/brand/components/Brand')) export default function BrandDetail() { const router = useRouter() @@ -13,13 +13,13 @@ export default function BrandDetail() { return ( <BasicLayout> <Brand id={getIdFromSlug(slug)} /> - { !_.isEmpty(router.query) && ( + {!_.isEmpty(router.query) && ( <ProductSearch query={_.omit(router.query, 'slug')} prefixUrl={`/shop/brands/${slug}`} defaultBrand={getNameFromSlug(slug)} /> - ) } + )} </BasicLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/shop/cart.jsx b/src/pages/shop/cart.jsx index 735ea19f..97f98843 100644 --- a/src/pages/shop/cart.jsx +++ b/src/pages/shop/cart.jsx @@ -1,12 +1,12 @@ -import dynamic from "next/dynamic" +import dynamic from 'next/dynamic' -const AppLayout = dynamic(() => import("@/core/components/layouts/AppLayout")) -const CartComponent = dynamic(() => import("@/lib/cart/components/Cart")) +const AppLayout = dynamic(() => import('@/core/components/layouts/AppLayout')) +const CartComponent = dynamic(() => import('@/lib/cart/components/Cart')) export default function Cart() { return ( - <AppLayout title="Keranjang"> + <AppLayout title='Keranjang'> <CartComponent /> </AppLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx index 2f610afb..cc6924a3 100644 --- a/src/pages/shop/product/[slug].jsx +++ b/src/pages/shop/product/[slug].jsx @@ -1,10 +1,10 @@ -import Seo from "@/core/components/Seo" -import { getIdFromSlug } from "@/core/utils/slug" -import productApi from "@/lib/product/api/productApi" -import dynamic from "next/dynamic" +import Seo from '@/core/components/Seo' +import { getIdFromSlug } from '@/core/utils/slug' +import productApi from '@/lib/product/api/productApi' +import dynamic from 'next/dynamic' -const BasicLayout = dynamic(() => import("@/core/components/layouts/BasicLayout")) -const Product = dynamic(() => import("@/lib/product/components/Product")) +const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')) +const Product = dynamic(() => import('@/lib/product/components/Product')) export async function getServerSideProps(context) { const { slug } = context.query @@ -28,4 +28,4 @@ export default function ProductDetail({ product }) { <Product product={product} /> </BasicLayout> ) -}
\ No newline at end of file +} diff --git a/src/pages/shop/search.jsx b/src/pages/shop/search.jsx index a41c3b5f..d616f2dd 100644 --- a/src/pages/shop/search.jsx +++ b/src/pages/shop/search.jsx @@ -1,21 +1,16 @@ -import dynamic from "next/dynamic" -import { useRouter } from "next/router" -import _ from "lodash-contrib" +import dynamic from 'next/dynamic' +import { useRouter } from 'next/router' +import _ from 'lodash-contrib' -const BasicLayout = dynamic(() => import("@/core/components/layouts/BasicLayout")) -const ProductSearch = dynamic(() => import("@/lib/product/components/ProductSearch")) +const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')) +const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch')) export default function Search() { const router = useRouter() - + return ( <BasicLayout> - { !_.isEmpty(router.query) && ( - <ProductSearch - query={router.query} - prefixUrl="/shop/search" - /> - ) } + {!_.isEmpty(router.query) && <ProductSearch query={router.query} prefixUrl='/shop/search' />} </BasicLayout> ) -}
\ No newline at end of file +} diff --git a/tailwind.config.js b/tailwind.config.js index 1f71fb92..e25c9203 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,12 +1,10 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: [ - "./src/**/*.{js,ts,jsx,tsx}", - ], + content: ['./src/**/*.{js,ts,jsx,tsx}'], theme: { extend: { fontFamily: { - 'sans': ['Inter', 'sans-serif'] + sans: ['Inter', 'sans-serif'] }, fontSize: { 'display-lg': ['56px', '100%'], @@ -23,10 +21,10 @@ module.exports = { 'paragraph-1': ['15px', '140%'], 'paragraph-2': ['14px', '140%'], 'caption-1': ['13px', '121%'], - 'caption-2': ['12px', '121%'], + 'caption-2': ['12px', '121%'] }, colors: { - 'green_r': { + green_r: { 1: '#fbfefc', 2: '#f2fcf5', 3: '#e9f9ee', @@ -38,9 +36,9 @@ module.exports = { 9: '#30a46c', 10: '#299764', 11: '#18794e', - 12: '#153226', + 12: '#153226' }, - 'yellow_r': { + yellow_r: { 1: '#fdfdf9', 2: '#fffce8', 3: '#fffbd1', @@ -52,9 +50,9 @@ module.exports = { 9: '#f5d90a', 10: '#f7ce00', 11: '#946800', - 12: '#35290f', + 12: '#35290f' }, - 'gray_r': { + gray_r: { 1: '#fcfcfc', 2: '#f8f8f8', 3: '#f3f3f3', @@ -66,9 +64,9 @@ module.exports = { 9: '#8f8f8f', 10: '#858585', 11: '#6f6f6f', - 12: '#171717', + 12: '#171717' }, - 'red_r': { + red_r: { 1: '#fffcfc', 2: '#fff8f8', 3: '#ffefef', @@ -80,9 +78,9 @@ module.exports = { 9: '#e5484d', 10: '#dc3d43', 11: '#cd2b31', - 12: '#381316', + 12: '#381316' }, - 'sand_r': { + sand_r: { 1: '#fdfdfc', 2: '#f9f9f8', 3: '#f3f3f2', @@ -94,12 +92,10 @@ module.exports = { 9: '#90908c', 10: '#868682', 11: '#706f6c', - 12: '#1b1b18', + 12: '#1b1b18' } } - }, + } }, - plugins: [ - require('@tailwindcss/line-clamp'), - ], + plugins: [require('@tailwindcss/line-clamp')] } |
