summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHATEC\SPVDEV001 <tri.susilo@altama.co.id>2023-04-11 11:06:38 +0700
committerHATEC\SPVDEV001 <tri.susilo@altama.co.id>2023-04-11 11:06:38 +0700
commit3df233e0c23e7d4503931ab6ec8ffc41642ac104 (patch)
treeccc032defe422f5fafc4a08af672833b2fe41835 /src
parent006c77a85786c24199db157d1d70f48b47311d35 (diff)
parentf0a720441def88187b3913268238c379362fb9d3 (diff)
Merge branch 'master' into development_tri/feedback_UAT
Diffstat (limited to 'src')
-rw-r--r--src/core/api/odooApi.js11
-rw-r--r--src/core/components/elements/Alert/Alert.jsx10
-rw-r--r--src/core/components/elements/Appbar/Appbar.jsx29
-rw-r--r--src/core/components/elements/Divider/Divider.jsx8
-rw-r--r--src/core/components/elements/Image/Image.jsx8
-rw-r--r--src/core/components/elements/Link/Link.jsx16
-rw-r--r--src/core/components/elements/Navbar/NavbarMobile.jsx12
-rw-r--r--src/core/components/elements/Navbar/Search.jsx10
-rw-r--r--src/core/components/elements/Pagination/Pagination.js5
-rw-r--r--src/core/components/elements/Popup/BottomPopup.jsx6
-rw-r--r--src/core/components/elements/Skeleton/BrandSkeleton.jsx5
-rw-r--r--src/core/components/elements/Skeleton/ImageSkeleton.jsx10
-rw-r--r--src/core/components/elements/Skeleton/ProductCardSkeleton.jsx5
-rw-r--r--src/core/components/elements/Spinner/LogoSpinner.jsx15
-rw-r--r--src/core/hooks/useDevice.js1
-rw-r--r--src/core/hooks/useSidebar.js7
-rw-r--r--src/core/utils/address.js35
-rw-r--r--src/core/utils/auth.js20
-rw-r--r--src/core/utils/cart.js41
-rw-r--r--src/core/utils/currencyFormat.js6
-rw-r--r--src/core/utils/getFileBase64.js13
-rw-r--r--src/core/utils/greeting.js10
-rw-r--r--src/core/utils/slug.js24
-rw-r--r--src/core/utils/toTitleCase.js9
-rw-r--r--src/images/LOGO-INDOTEKNIK-GEAR-GREY.pngbin0 -> 14190 bytes
-rw-r--r--src/images/LOGO-INDOTEKNIK-GEAR.pngbin0 -> 18304 bytes
-rw-r--r--src/lib/address/components/Addresses.jsx5
-rw-r--r--src/lib/address/components/EditAddress.jsx2
-rw-r--r--src/lib/auth/api/registerApi.js2
-rw-r--r--src/lib/auth/components/Activate.jsx52
-rw-r--r--src/lib/auth/components/CompanyProfile.jsx37
-rw-r--r--src/lib/auth/components/Login.jsx4
-rw-r--r--src/lib/auth/components/PersonalProfile.jsx32
-rw-r--r--src/lib/auth/components/RegisterDesktop.jsx20
-rw-r--r--src/lib/auth/components/RegisterMobile.jsx2
-rw-r--r--src/lib/auth/hooks/useRegister.js2
-rw-r--r--src/lib/brand/components/BrandCard.jsx9
-rw-r--r--src/lib/brand/components/Brands.jsx14
-rw-r--r--src/lib/cart/components/Cart.jsx24
-rw-r--r--src/lib/checkout/components/Checkout.jsx6
-rw-r--r--src/lib/content/components/PageContent.jsx2
-rw-r--r--src/lib/home/components/PopularProduct.jsx15
-rw-r--r--src/lib/home/components/PreferredBrand.jsx11
-rw-r--r--src/lib/invoice/components/Invoice.jsx4
-rw-r--r--src/lib/product/api/productSearchApi.js4
-rw-r--r--src/lib/product/components/Product/ProductDesktop.jsx6
-rw-r--r--src/lib/product/components/Product/ProductMobile.jsx10
-rw-r--r--src/lib/product/components/ProductCard.jsx4
-rw-r--r--src/lib/product/components/ProductFilter.jsx22
-rw-r--r--src/lib/product/components/ProductSearch.jsx14
-rw-r--r--src/lib/product/components/ProductSlider.jsx10
-rw-r--r--src/lib/transaction/components/Transaction.jsx6
-rw-r--r--src/lib/variant/components/VariantGroupCard.jsx6
-rw-r--r--src/pages/_app.jsx22
-rw-r--r--src/pages/api/shop/search.js30
-rw-r--r--src/pages/api/shop/suggest.js2
-rw-r--r--src/pages/forgot-password.jsx6
-rw-r--r--src/pages/my/menu.jsx20
-rw-r--r--src/pages/reset-password.jsx7
-rw-r--r--src/pages/shop/brands/[slug].jsx5
-rw-r--r--src/pages/shop/checkout/[status].jsx2
-rw-r--r--src/pages/shop/quotation/finish.jsx58
-rw-r--r--src/pages/shop/search.jsx7
-rw-r--r--src/pages/sitemap/products/[id].xml.js2
-rw-r--r--src/styles/globals.css21
65 files changed, 455 insertions, 368 deletions
diff --git a/src/core/api/odooApi.js b/src/core/api/odooApi.js
index 25ee9adf..fe9fcdd2 100644
--- a/src/core/api/odooApi.js
+++ b/src/core/api/odooApi.js
@@ -18,6 +18,17 @@ const getToken = async () => {
const maxConnectionAttempt = 15
let connectionAttempt = 0
+/**
+ * The `odooApi` function is used to make API requests to an Odoo backend with customizable parameters such as `method`, `url`, `data`, and `headers`.
+ *
+ * @async
+ * @function
+ * @param {string} method - HTTP method for the API request (e.g., GET, POST, PUT, DELETE).
+ * @param {string} url - URL endpoint for the API request.
+ * @param {Object} data - Data to be sent in the request payload.
+ * @param {Object} headers - Custom headers to be sent in the request.
+ * @returns {Promise} - A Promise that resolves to the API response data or an empty array.
+ */
const odooApi = async (method, url, data = {}, headers = {}) => {
connectionAttempt++
try {
diff --git a/src/core/components/elements/Alert/Alert.jsx b/src/core/components/elements/Alert/Alert.jsx
index 695be8a3..cf84b591 100644
--- a/src/core/components/elements/Alert/Alert.jsx
+++ b/src/core/components/elements/Alert/Alert.jsx
@@ -1,3 +1,13 @@
+/**
+ * The Alert component is used to display different types of alerts or notifications
+ * with different styles based on the provided type prop.
+ *
+ * @param {Object} props - Props received by the component.
+ * @param {ReactNode} props.children - The content to be displayed inside the alert.
+ * @param {string} props.className - Additional CSS class names for the alert.
+ * @param {string} props.type - The type of the alert ('info', 'success', or 'warning').
+ * @returns {JSX.Element} - Rendered Alert component.
+ */
const Alert = ({ children, className, type }) => {
let typeClass = ''
switch (type) {
diff --git a/src/core/components/elements/Appbar/Appbar.jsx b/src/core/components/elements/Appbar/Appbar.jsx
index 098d0a33..f1456a7c 100644
--- a/src/core/components/elements/Appbar/Appbar.jsx
+++ b/src/core/components/elements/Appbar/Appbar.jsx
@@ -2,38 +2,33 @@ import { useRouter } from 'next/router'
import Link from '../Link/Link'
import { HomeIcon, Bars3Icon, ShoppingCartIcon, ChevronLeftIcon } from '@heroicons/react/24/outline'
+/**
+ * The AppBar component is a navigation component used to display a header or toolbar
+ * in a web application.
+ *
+ * @param {Object} props - Props received by the component.
+ * @param {string} props.title - The title to be displayed on the AppBar.
+ * @returns {JSX.Element} - Rendered AppBar component.
+ */
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()}
- >
+ <button type='button' className='p-4' onClick={() => router.back()}>
<ChevronLeftIcon className='w-6 stroke-2' />
</button>
<div className='font-medium text-h-sm line-clamp-1'>{title}</div>
</div>
<div className='flex items-center px-2'>
- <Link
- href='/shop/cart'
- className='py-4 px-2'
- >
+ <Link href='/shop/cart' className='py-4 px-2'>
<ShoppingCartIcon className='w-6 text-gray_r-12' />
</Link>
- <Link
- href='/'
- className='py-4 px-2'
- >
+ <Link href='/' className='py-4 px-2'>
<HomeIcon className='w-6 text-gray_r-12' />
</Link>
- <Link
- href='/my/menu'
- className='py-4 px-2'
- >
+ <Link href='/my/menu' className='py-4 px-2'>
<Bars3Icon className='w-6 text-gray_r-12' />
</Link>
</div>
diff --git a/src/core/components/elements/Divider/Divider.jsx b/src/core/components/elements/Divider/Divider.jsx
index ce54a2ea..f3650b00 100644
--- a/src/core/components/elements/Divider/Divider.jsx
+++ b/src/core/components/elements/Divider/Divider.jsx
@@ -1,3 +1,11 @@
+/**
+ * The Divider component is used to create a horizontal line or divider with a specific
+ * background color based on the provided className prop.
+ *
+ * @param {Object} props - Props that are passed to the Divider component.
+ * @param {string} props.className - Additional CSS classes to apply to the divider.
+ * @returns {JSX.Element} - Rendered Divider component.
+ */
const Divider = (props) => <div className={`h-1 bg-gray_r-4 ${props.className}`} />
Divider.defaultProps = {
diff --git a/src/core/components/elements/Image/Image.jsx b/src/core/components/elements/Image/Image.jsx
index ac82aaaf..ba6bf50d 100644
--- a/src/core/components/elements/Image/Image.jsx
+++ b/src/core/components/elements/Image/Image.jsx
@@ -1,6 +1,14 @@
import { LazyLoadImage } from 'react-lazy-load-image-component'
import 'react-lazy-load-image-component/src/effects/opacity.css'
+/**
+ * The `Image` component is used to display lazy-loaded images.
+ *
+ * @param {Object} props - Props passed to the `Image` component.
+ * @param {string} props.src - URL of the image to be displayed.
+ * @param {string} props.alt - Alternative text to be displayed if the image is not found.
+ * @returns {JSX.Element} - Rendered `Image` component.
+ */
const Image = ({ ...props }) => (
<>
<LazyLoadImage
diff --git a/src/core/components/elements/Link/Link.jsx b/src/core/components/elements/Link/Link.jsx
index 360444a6..f6b39d45 100644
--- a/src/core/components/elements/Link/Link.jsx
+++ b/src/core/components/elements/Link/Link.jsx
@@ -1,14 +1,14 @@
import NextLink from 'next/link'
-import { useRouter } from 'next/router'
-import { useEffect } from 'react'
+/**
+ * The `Link` component is used to render Next.js links with customizable properties such as `children`, `scroll`, and `className`.
+ *
+ * @param {Object} props - Props passed to the `Link` component.
+ * @param {ReactNode} props.children - Child elements to be rendered as link content.
+ * @param {string} props.className - Additional CSS class to be applied to the link.
+ * @returns {JSX.Element} - Rendered `Link` component.
+ */
const Link = ({ children, ...props }) => {
- const router = useRouter()
-
- useEffect(() => {
- router.events.on('routeChangeComplete', () => window.scrollTo({ top: 0, behavior: 'smooth' }))
- }, [router])
-
return (
<NextLink
{...props}
diff --git a/src/core/components/elements/Navbar/NavbarMobile.jsx b/src/core/components/elements/Navbar/NavbarMobile.jsx
index 3998875b..24ff3a51 100644
--- a/src/core/components/elements/Navbar/NavbarMobile.jsx
+++ b/src/core/components/elements/Navbar/NavbarMobile.jsx
@@ -16,12 +16,7 @@ const NavbarMobile = () => {
<nav className='px-4 py-2 pb-3 sticky top-0 z-50 bg-white shadow'>
<div className='flex justify-between items-center mb-2'>
<Link href='/'>
- <Image
- src={IndoteknikLogo}
- alt='Indoteknik Logo'
- width={120}
- height={40}
- />
+ <Image src={IndoteknikLogo} alt='Indoteknik Logo' width={120} height={40} />
</Link>
<div className='flex gap-x-3'>
<Link href='/my/wishlist'>
@@ -30,10 +25,7 @@ const NavbarMobile = () => {
<Link href='/shop/cart'>
<ShoppingCartIcon className='w-6 text-gray_r-12' />
</Link>
- <button
- type='button'
- onClick={open}
- >
+ <button type='button' onClick={open}>
<Bars3Icon className='w-6 text-gray_r-12' />
</button>
</div>
diff --git a/src/core/components/elements/Navbar/Search.jsx b/src/core/components/elements/Navbar/Search.jsx
index d0627b24..3046782b 100644
--- a/src/core/components/elements/Navbar/Search.jsx
+++ b/src/core/components/elements/Navbar/Search.jsx
@@ -45,10 +45,7 @@ const Search = () => {
return (
<>
- <form
- onSubmit={handleSubmit}
- className='flex-1 flex relative'
- >
+ <form onSubmit={handleSubmit} className='flex-1 flex relative'>
<input
type='text'
ref={queryRef}
@@ -59,10 +56,7 @@ const Search = () => {
onBlur={onInputBlur}
onFocus={loadSuggestion}
/>
- <button
- type='submit'
- className='rounded-r border border-l-0 border-gray_r-6 px-2'
- >
+ <button type='submit' className='rounded-r border border-l-0 border-gray_r-6 px-2'>
<MagnifyingGlassIcon className='w-6' />
</button>
diff --git a/src/core/components/elements/Pagination/Pagination.js b/src/core/components/elements/Pagination/Pagination.js
index 18964fc4..c009171f 100644
--- a/src/core/components/elements/Pagination/Pagination.js
+++ b/src/core/components/elements/Pagination/Pagination.js
@@ -26,10 +26,7 @@ const Pagination = ({ pageCount, currentPage, url, className }) => {
</Link>
)
let DotsComponent = (
- <div
- key={i}
- className='pagination-dots'
- >
+ <div key={i} className='pagination-dots'>
...
</div>
)
diff --git a/src/core/components/elements/Popup/BottomPopup.jsx b/src/core/components/elements/Popup/BottomPopup.jsx
index 1d65c7a3..80afa8d9 100644
--- a/src/core/components/elements/Popup/BottomPopup.jsx
+++ b/src/core/components/elements/Popup/BottomPopup.jsx
@@ -7,7 +7,7 @@ import ReactDOM from 'react-dom'
const transition = { ease: 'linear', duration: 0.2 }
-const BottomPopup = ({ children, active = false, title, close }) => {
+const BottomPopup = ({ children, active = false, title, close, className = '' }) => {
useEffect(() => {
if (active) {
document.querySelector('html, body').classList.add('overflow-hidden')
@@ -35,7 +35,7 @@ const BottomPopup = ({ children, active = false, title, close }) => {
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 max-h-[80vh] overflow-auto'
+ className={`fixed left-0 w-full border-t border-gray_r-6 rounded-t-xl z-[60] p-4 pt-0 bg-white max-h-[80vh] overflow-auto ${className}`}
>
<div className='flex justify-between py-4'>
<div className='font-semibold text-h-sm'>{title}</div>
@@ -53,7 +53,7 @@ const BottomPopup = ({ children, active = false, title, close }) => {
animate={{ bottom: '50%', opacity: 1 }}
exit={{ bottom: '45%', opacity: 0 }}
transition={transition}
- className='fixed left-1/2 -translate-x-1/2 translate-y-1/2 md:w-1/4 lg:w-1/3 border border-gray_r-6 rounded-xl z-[60] p-4 pt-0 bg-white max-h-[80vh] overflow-auto'
+ className={`fixed left-1/2 -translate-x-1/2 translate-y-1/2 md:w-1/4 lg:w-1/3 border border-gray_r-6 rounded-xl z-[60] p-4 pt-0 bg-white max-h-[80vh] overflow-auto ${className}`}
>
<div className='flex justify-between py-4'>
<div className='font-semibold text-h-sm'>{title}</div>
diff --git a/src/core/components/elements/Skeleton/BrandSkeleton.jsx b/src/core/components/elements/Skeleton/BrandSkeleton.jsx
index 9a34fb9b..9a7a51f9 100644
--- a/src/core/components/elements/Skeleton/BrandSkeleton.jsx
+++ b/src/core/components/elements/Skeleton/BrandSkeleton.jsx
@@ -1,8 +1,5 @@
const BrandSkeleton = () => (
- <div
- role='status'
- className='animate-pulse'
- >
+ <div role='status' className='animate-pulse'>
<div className='h-12 bg-gray-200 rounded'></div>
<span className='sr-only'>Loading...</span>
</div>
diff --git a/src/core/components/elements/Skeleton/ImageSkeleton.jsx b/src/core/components/elements/Skeleton/ImageSkeleton.jsx
index 39d06331..2ca6b2a3 100644
--- a/src/core/components/elements/Skeleton/ImageSkeleton.jsx
+++ b/src/core/components/elements/Skeleton/ImageSkeleton.jsx
@@ -1,12 +1,6 @@
const ImageSkeleton = () => (
- <div
- role='status'
- className='animate-pulse'
- >
- <div
- className='flex items-center justify-center h-56 mb-4 bg-gray-300 rounded'
- aria-busy
- >
+ <div role='status' className='animate-pulse'>
+ <div className='flex items-center justify-center h-56 mb-4 bg-gray-300 rounded' aria-busy>
<svg
className='w-12 h-12 text-gray-200'
xmlns='http://www.w3.org/2000/svg'
diff --git a/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx b/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx
index ddc0d3bc..84d1c0d1 100644
--- a/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx
+++ b/src/core/components/elements/Skeleton/ProductCardSkeleton.jsx
@@ -3,10 +3,7 @@ const ProductCardSkeleton = () => (
role='status'
className='p-4 max-w-sm rounded border border-gray-300 shadow animate-pulse md:p-6'
>
- <div
- className='flex items-center justify-center h-36 mb-4 bg-gray-300 rounded'
- aria-busy
- >
+ <div className='flex items-center justify-center h-36 mb-4 bg-gray-300 rounded' aria-busy>
<svg
className='w-12 h-12 text-gray-200'
xmlns='http://www.w3.org/2000/svg'
diff --git a/src/core/components/elements/Spinner/LogoSpinner.jsx b/src/core/components/elements/Spinner/LogoSpinner.jsx
new file mode 100644
index 00000000..73b84e84
--- /dev/null
+++ b/src/core/components/elements/Spinner/LogoSpinner.jsx
@@ -0,0 +1,15 @@
+import Image from 'next/image'
+import IndoteknikLogo from '@/images/LOGO-INDOTEKNIK-GEAR.png'
+
+const LogoSpinner = ({ ...props }) => (
+ <Image
+ src={IndoteknikLogo}
+ alt='Indoteknik Logo'
+ width={64}
+ height={64}
+ className='page-loader'
+ {...props}
+ />
+)
+
+export default LogoSpinner
diff --git a/src/core/hooks/useDevice.js b/src/core/hooks/useDevice.js
index a8584692..7ecf5a31 100644
--- a/src/core/hooks/useDevice.js
+++ b/src/core/hooks/useDevice.js
@@ -22,7 +22,6 @@ const useDevice = () => {
}
}, [])
-
return {
isMobile,
isDesktop
diff --git a/src/core/hooks/useSidebar.js b/src/core/hooks/useSidebar.js
index 4da61ac2..c463fd81 100644
--- a/src/core/hooks/useSidebar.js
+++ b/src/core/hooks/useSidebar.js
@@ -15,12 +15,7 @@ const useSidebar = () => {
return {
open: activate,
- Sidebar: (
- <SidebarComponent
- active={active}
- close={deactivate}
- />
- )
+ Sidebar: <SidebarComponent active={active} close={deactivate} />
}
}
diff --git a/src/core/utils/address.js b/src/core/utils/address.js
index c545d34b..b20feba3 100644
--- a/src/core/utils/address.js
+++ b/src/core/utils/address.js
@@ -1,28 +1,53 @@
+/**
+ * Gets the address data from local storage.
+ *
+ * @returns {object} - Returns the address data as an object, or an empty object if not found.
+ */
const getAddress = () => {
- if (typeof window !== 'undefined') {
+ if (typeof window !== 'undefined' && window.localStorage) {
const address = localStorage.getItem('address')
if (address) return JSON.parse(address)
}
return {}
}
+/**
+ * Sets the address data to local storage.
+ *
+ * @param {object} address - The address data to be stored as an object.
+ * @returns {boolean} - Returns `true` if the address data is successfully stored, `false` otherwise.
+ */
const setAddress = (address) => {
- if (typeof window !== 'undefined') {
+ if (typeof window !== 'undefined' && window.localStorage) {
localStorage.setItem('address', JSON.stringify(address))
+ return true
}
- return
+ return false
}
+/**
+ * Gets the value of a specific key from the address data.
+ *
+ * @param {string} key - The key of the address data to be retrieved.
+ * @returns {*} - The value of the specified key, or false if the key does not exist.
+ */
const getItemAddress = (key) => {
let address = getAddress()
- return address[key]
+ return address[key] || false
}
+/**
+ * Updates the value of a specific key in the address data.
+ *
+ * @param {string} key - The key of the address data to be updated.
+ * @param {*} value - The new value to be set for the specified key.
+ * @returns {boolean} - Returns `true`
+ */
const updateItemAddress = (key, value) => {
let address = getAddress()
address[key] = value
setAddress(address)
- return
+ return true
}
export { getItemAddress, updateItemAddress }
diff --git a/src/core/utils/auth.js b/src/core/utils/auth.js
index 13e0e79d..cddff2b8 100644
--- a/src/core/utils/auth.js
+++ b/src/core/utils/auth.js
@@ -1,18 +1,32 @@
import { deleteCookie, getCookie, setCookie } from 'cookies-next'
+/**
+ * Retrieves authentication data from cookie and returns it as an object.
+ *
+ * @returns {Object|boolean} - Returns the authentication data as an object if available in cookie, otherwise `false`.
+ */
const getAuth = () => {
let auth = getCookie('auth')
- if (auth) {
- return JSON.parse(auth)
- }
+ if (auth) return JSON.parse(auth)
return false
}
+/**
+ * Sets the authentication data in cookie with the given user data.
+ *
+ * @param {Object} user - The user data to be set as authentication data in cookie.
+ * @returns {boolean} - Returns `true`.
+ */
const setAuth = (user) => {
setCookie('auth', JSON.stringify(user))
return true
}
+/**
+ * Deletes the authentication data stored in cookie.
+ *
+ * @returns {boolean} - Returns `true`.
+ */
const deleteAuth = () => {
deleteCookie('auth')
return true
diff --git a/src/core/utils/cart.js b/src/core/utils/cart.js
index fd42ee4e..2bdffb1c 100644
--- a/src/core/utils/cart.js
+++ b/src/core/utils/cart.js
@@ -1,23 +1,51 @@
+/**
+ * Retrieves cart data from localStorage, if available.
+ *
+ * @returns {Object} - The cart data as an object, or an empty object if not found.
+ */
const getCart = () => {
- if (typeof window !== 'undefined') {
+ if (typeof window !== 'undefined' && window.localStorage) {
const cart = localStorage.getItem('cart')
if (cart) return JSON.parse(cart)
}
return {}
}
+/**
+ * Saves cart data to localStorage, if available.
+ *
+ * @param {Object} cart - The cart data to be saved.
+ * @returns {boolean} - Returns `true` if cart data is saved successfully, `false` otherwise.
+ */
const setCart = (cart) => {
- if (typeof window !== 'undefined') {
+ if (typeof window !== 'undefined' && window.localStorage) {
localStorage.setItem('cart', JSON.stringify(cart))
+ return true
}
- return true
+ return false
}
+/**
+ * Retrieves an item from the cart data based on the given product ID.
+ *
+ * @param {Object} options - The options object containing the productId.
+ * @param {string} options.productId - The ID of the product to be retrieved from the cart.
+ * @returns {Object} - Returns the item object from the cart data, or `undefined` if not found.
+ */
const getItemCart = ({ productId }) => {
let cart = getCart()
return cart[productId]
}
+/**
+ * Updates an item in the cart data with the given productId, quantity, and selected status.
+ *
+ * @param {Object} options - The options object containing the productId, quantity, and selected status.
+ * @param {string} options.productId - The ID of the product to be updated in the cart.
+ * @param {number} options.quantity - The new quantity of the product in the cart.
+ * @param {boolean} [options.selected=false] - The new selected status of the product in the cart. Default is `false`.
+ * @returns {boolean} - Returns `true`.
+ */
const updateItemCart = ({ productId, quantity, selected = false }) => {
let cart = getCart()
quantity = parseInt(quantity)
@@ -26,6 +54,13 @@ const updateItemCart = ({ productId, quantity, selected = false }) => {
return true
}
+/**
+ * Deletes an item from the cart data with the given productId.
+ *
+ * @param {Object} options - The options object containing the productId.
+ * @param {string} options.productId - The ID of the product to be deleted from the cart.
+ * @returns {boolean} - Returns `true`.
+ */
const deleteItemCart = ({ productId }) => {
let cart = getCart()
delete cart[productId]
diff --git a/src/core/utils/currencyFormat.js b/src/core/utils/currencyFormat.js
index 12b68111..d0eba4c4 100644
--- a/src/core/utils/currencyFormat.js
+++ b/src/core/utils/currencyFormat.js
@@ -1,3 +1,9 @@
+/**
+ * Formats a numeric value as a currency string in Indonesian Rupiah (IDR) format.
+ *
+ * @param {number} value - The numeric value to be formatted as currency.
+ * @returns {string} - The currency string in IDR format.
+ */
const currencyFormat = (value) => {
const currency = new Intl.NumberFormat('id-ID', {
style: 'currency',
diff --git a/src/core/utils/getFileBase64.js b/src/core/utils/getFileBase64.js
index 4fa7316b..ed6ae000 100644
--- a/src/core/utils/getFileBase64.js
+++ b/src/core/utils/getFileBase64.js
@@ -1,5 +1,13 @@
-const getFileBase64 = (file) =>
- new Promise((resolve, reject) => {
+/**
+ * Converts a File object to base64 string using FileReader.
+ *
+ * @param {File} file - The File object to be converted.
+ * @returns {Promise<string>} - A Promise that resolves with the base64 string
+ * representing the contents of the File, or rejects with an error if there's
+ * any issue with the file reading process.
+ */
+const getFileBase64 = (file) => {
+ return new Promise((resolve, reject) => {
let reader = new FileReader()
reader.readAsBinaryString(file)
reader.onload = () => {
@@ -8,5 +16,6 @@ const getFileBase64 = (file) =>
}
reader.onerror = (error) => reject(error)
})
+}
export default getFileBase64
diff --git a/src/core/utils/greeting.js b/src/core/utils/greeting.js
index aaaade7a..d349033e 100644
--- a/src/core/utils/greeting.js
+++ b/src/core/utils/greeting.js
@@ -1,3 +1,13 @@
+/**
+ * Generates a greeting based on the current time of day.
+ * The greeting is determined by the hour of the day:
+ * - "Selamat Pagi" for hours before 11:00
+ * - "Selamat Siang" for hours between 11:00 and 15:00
+ * - "Selamat Sore" for hours between 15:00 and 18:00
+ * - "Selamat Malam" for hours after 18:00
+ *
+ * @returns {string} - The generated greeting message.
+ */
const greeting = () => {
let hours = new Date().getHours()
if (hours < 11) return 'Selamat Pagi'
diff --git a/src/core/utils/slug.js b/src/core/utils/slug.js
index 7010008a..d5eecd3e 100644
--- a/src/core/utils/slug.js
+++ b/src/core/utils/slug.js
@@ -1,5 +1,14 @@
import toTitleCase from './toTitleCase'
+/**
+ * Creates a slug from input parameters by converting the name and appending it with an ID.
+ * The slug is generated by removing special characters, converting to lowercase, and joining with hyphens.
+ *
+ * @param {string} prefix - The prefix to be added to the generated slug.
+ * @param {string} name - The name used to generate the slug.
+ * @param {number} id - The ID to be appended to the slug.
+ * @returns {string} - The generated slug with the prefix, name, and ID.
+ */
const createSlug = (prefix, name, id) => {
let slug =
name
@@ -13,11 +22,26 @@ const createSlug = (prefix, name, id) => {
return prefix + filterSlugFromEmptyChar.join('-')
}
+/**
+ * Extracts the ID from a slug.
+ * The ID is retrieved from the last segment of the slug, separated by hyphens.
+ *
+ * @param {string} slug - The slug from which to extract the ID.
+ * @returns {string} - The extracted ID from the slug.
+ */
const getIdFromSlug = (slug) => {
let id = slug.split('-')
return id[id.length - 1]
}
+/**
+ * Extracts the name from a slug.
+ * The name is retrieved from all segments of the slug, except for the last one, separated by hyphens.
+ * The retrieved name is then converted to title case.
+ *
+ * @param {string} slug - The slug from which to extract the name.
+ * @returns {string} - The extracted name from the slug in title case.
+ */
const getNameFromSlug = (slug) => {
let name = slug.split('-')
name.pop()
diff --git a/src/core/utils/toTitleCase.js b/src/core/utils/toTitleCase.js
index 4335824d..dab1dc33 100644
--- a/src/core/utils/toTitleCase.js
+++ b/src/core/utils/toTitleCase.js
@@ -1,3 +1,12 @@
+/**
+ * Converts a string to title case.
+ * Title case capitalizes the first character of each word in the string,
+ * and sets the remaining characters to lowercase.
+ *
+ * @param {string} str - The input string to be converted to title case.
+ * @returns {string} - The string in title case.
+ */
+
const toTitleCase = (str) => {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
diff --git a/src/images/LOGO-INDOTEKNIK-GEAR-GREY.png b/src/images/LOGO-INDOTEKNIK-GEAR-GREY.png
new file mode 100644
index 00000000..2ab07ff5
--- /dev/null
+++ b/src/images/LOGO-INDOTEKNIK-GEAR-GREY.png
Binary files differ
diff --git a/src/images/LOGO-INDOTEKNIK-GEAR.png b/src/images/LOGO-INDOTEKNIK-GEAR.png
new file mode 100644
index 00000000..89f749ec
--- /dev/null
+++ b/src/images/LOGO-INDOTEKNIK-GEAR.png
Binary files differ
diff --git a/src/lib/address/components/Addresses.jsx b/src/lib/address/components/Addresses.jsx
index db338983..a610d371 100644
--- a/src/lib/address/components/Addresses.jsx
+++ b/src/lib/address/components/Addresses.jsx
@@ -61,7 +61,10 @@ const Addresses = () => {
<div className='w-9/12 p-4 bg-white border border-gray_r-6 rounded'>
<div className='flex items-center mb-6'>
<h1 className='text-title-sm font-semibold'>Daftar Alamat</h1>
- <Link href='/my/address/create' className='btn-solid-red py-2 px-3 !text-gray_r-1 h-fit ml-auto'>
+ <Link
+ href='/my/address/create'
+ className='btn-solid-red py-2 px-3 !text-gray_r-1 h-fit ml-auto'
+ >
Tambah Alamat
</Link>
</div>
diff --git a/src/lib/address/components/EditAddress.jsx b/src/lib/address/components/EditAddress.jsx
index 30555ecd..520bba51 100644
--- a/src/lib/address/components/EditAddress.jsx
+++ b/src/lib/address/components/EditAddress.jsx
@@ -197,7 +197,7 @@ const EditAddress = ({ id, defaultValues }) => {
<HookFormSelect {...props} options={districts} disabled={!watchCity} />
)}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.district?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.district?.message}</div>
</div>
<div>
diff --git a/src/lib/auth/api/registerApi.js b/src/lib/auth/api/registerApi.js
index f3d75ce8..f9413f8c 100644
--- a/src/lib/auth/api/registerApi.js
+++ b/src/lib/auth/api/registerApi.js
@@ -1,6 +1,6 @@
import odooApi from '@/core/api/odooApi'
-const registerApi = async ({ data }) => {
+const registerApi = async ({ ...data }) => {
const dataRegister = await odooApi('POST', '/api/v1/user/register', data)
return dataRegister
}
diff --git a/src/lib/auth/components/Activate.jsx b/src/lib/auth/components/Activate.jsx
index 717e178b..c81bcbbd 100644
--- a/src/lib/auth/components/Activate.jsx
+++ b/src/lib/auth/components/Activate.jsx
@@ -27,10 +27,7 @@ const Activate = () => {
children: (
<>
Selamat, akun anda berhasil diaktifkan,{' '}
- <Link
- className='text-gray_r-12'
- href='/'
- >
+ <Link className='text-gray_r-12' href='/'>
kembali ke beranda
</Link>
.
@@ -43,10 +40,7 @@ const Activate = () => {
children: (
<>
Mohon maaf token sudah tidak aktif, lakukan permintaan aktivasi akun kembali atau{' '}
- <Link
- className='text-gray_r-12'
- href='/login'
- >
+ <Link className='text-gray_r-12' href='/login'>
masuk
</Link>{' '}
jika sudah memiliki akun.
@@ -67,9 +61,12 @@ const Activate = () => {
const activationRequest = async (e) => {
e.preventDefault()
setIsLoading(true)
- let activationRequest = await axios.post(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/activation-request`, {
- email
- })
+ let activationRequest = await axios.post(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/activation-request`,
+ {
+ email
+ }
+ )
if (activationRequest.data.activationRequest) {
setAlert({
children: <>Mohon cek email anda untuk aktivasi akun Indoteknik</>,
@@ -82,10 +79,7 @@ const Activate = () => {
children: (
<>
Email tersebut belum terdaftar,{' '}
- <Link
- className='text-gray_r-12'
- href='/register'
- >
+ <Link className='text-gray_r-12' href='/register'>
daftar sekarang
</Link>
.
@@ -99,10 +93,7 @@ const Activate = () => {
children: (
<>
Email tersebut sudah terdaftar dan sudah aktif,{' '}
- <Link
- className='text-gray_r-12'
- href='/login'
- >
+ <Link className='text-gray_r-12' href='/login'>
masuk sekarang
</Link>
.
@@ -119,29 +110,18 @@ const Activate = () => {
return (
<div className='p-6 pt-10 flex flex-col items-center min-h-screen'>
<Link href='/'>
- <Image
- src={IndoteknikLogo}
- alt='Logo Indoteknik'
- width={150}
- height={50}
- />
+ <Image src={IndoteknikLogo} alt='Logo Indoteknik' width={150} height={50} />
</Link>
<h1 className='text-2xl mt-4 font-semibold text-center'>Aktivasi Akun Indoteknik</h1>
{alert && (
- <Alert
- className='text-center mt-4'
- type={alert.type}
- >
+ <Alert className='text-center mt-4' type={alert.type}>
{alert.children}
</Alert>
)}
- <form
- onSubmit={activationRequest}
- className='mt-6 w-full'
- >
+ <form onSubmit={activationRequest} className='mt-6 w-full'>
<input
type='email'
id='email'
@@ -151,11 +131,7 @@ const Activate = () => {
placeholder='Masukan alamat email'
autoFocus
/>
- <button
- type='submit'
- disabled={!email}
- className='btn-yellow font-semibold mt-4 w-full'
- >
+ <button type='submit' disabled={!email} className='btn-yellow font-semibold mt-4 w-full'>
{isLoading ? 'Loading...' : 'Aktivasi'}
</button>
</form>
diff --git a/src/lib/auth/components/CompanyProfile.jsx b/src/lib/auth/components/CompanyProfile.jsx
index 1b25551e..854aa246 100644
--- a/src/lib/auth/components/CompanyProfile.jsx
+++ b/src/lib/auth/components/CompanyProfile.jsx
@@ -69,11 +69,7 @@ const CompanyProfile = () => {
return (
<>
- <button
- type='button'
- onClick={toggle}
- className='p-4 flex items-center text-left'
- >
+ <button type='button' onClick={toggle} className='p-4 flex items-center text-left'>
<div>
<div className='font-semibold mb-2'>Informasi Usaha</div>
<div className='text-gray_r-11'>
@@ -96,12 +92,7 @@ const CompanyProfile = () => {
<Controller
name='industry'
control={control}
- render={(props) => (
- <HookFormSelect
- {...props}
- options={industries}
- />
- )}
+ render={(props) => <HookFormSelect {...props} options={industries} />}
/>
</div>
<div className='flex flex-wrap'>
@@ -110,12 +101,7 @@ const CompanyProfile = () => {
<Controller
name='companyType'
control={control}
- render={(props) => (
- <HookFormSelect
- {...props}
- options={companyTypes}
- />
- )}
+ render={(props) => <HookFormSelect {...props} options={companyTypes} />}
/>
</div>
<div className='w-9/12 pl-1'>
@@ -129,24 +115,13 @@ const CompanyProfile = () => {
</div>
<div>
<label>Nama Wajib Pajak</label>
- <input
- {...register('taxName')}
- type='text'
- className='form-input mt-3'
- />
+ <input {...register('taxName')} type='text' className='form-input mt-3' />
</div>
<div>
<label>Nomor NPWP</label>
- <input
- {...register('npwp')}
- type='text'
- className='form-input mt-3'
- />
+ <input {...register('npwp')} type='text' className='form-input mt-3' />
</div>
- <button
- type='submit'
- className='btn-yellow w-full mt-2'
- >
+ <button type='submit' className='btn-yellow w-full mt-2'>
Simpan
</button>
</form>
diff --git a/src/lib/auth/components/Login.jsx b/src/lib/auth/components/Login.jsx
index 171ff4c8..cbcfd07b 100644
--- a/src/lib/auth/components/Login.jsx
+++ b/src/lib/auth/components/Login.jsx
@@ -1,5 +1,5 @@
-import LoginDesktop from "./LoginDesktop"
-import LoginMobile from "./LoginMobile"
+import LoginDesktop from './LoginDesktop'
+import LoginMobile from './LoginMobile'
const Login = () => {
return (
diff --git a/src/lib/auth/components/PersonalProfile.jsx b/src/lib/auth/components/PersonalProfile.jsx
index 0b387f2e..4a533ae9 100644
--- a/src/lib/auth/components/PersonalProfile.jsx
+++ b/src/lib/auth/components/PersonalProfile.jsx
@@ -34,7 +34,7 @@ const PersonalProfile = () => {
let data = values
if (!values.password) delete data.password
const isUpdated = await editPersonalProfileApi({ data })
- console.log(isUpdated)
+
if (isUpdated?.user) {
setAuth(isUpdated.user)
setValue('password', '')
@@ -47,11 +47,7 @@ const PersonalProfile = () => {
return (
<>
- <button
- type='button'
- onClick={toggle}
- className='p-4 flex items-center text-left'
- >
+ <button type='button' onClick={toggle} className='p-4 flex items-center text-left'>
<div>
<div className='font-semibold mb-2'>Informasi Akun</div>
<div className='text-gray_r-11'>
@@ -71,28 +67,15 @@ const PersonalProfile = () => {
>
<div>
<label>Email</label>
- <input
- {...register('email')}
- type='text'
- disabled
- className='form-input mt-3'
- />
+ <input {...register('email')} type='text' disabled className='form-input mt-3' />
</div>
<div>
<label>Nama Lengkap</label>
- <input
- {...register('name')}
- type='text'
- className='form-input mt-3'
- />
+ <input {...register('name')} type='text' className='form-input mt-3' />
</div>
<div>
<label>No. Handphone</label>
- <input
- {...register('mobile')}
- type='tel'
- className='form-input mt-3'
- />
+ <input {...register('mobile')} type='tel' className='form-input mt-3' />
</div>
<div>
<label>Kata Sandi</label>
@@ -103,10 +86,7 @@ const PersonalProfile = () => {
placeholder='Isi jika ingin mengubah kata sandi'
/>
</div>
- <button
- type='submit'
- className='btn-yellow w-full mt-2'
- >
+ <button type='submit' className='btn-yellow w-full mt-2'>
Simpan
</button>
</form>
diff --git a/src/lib/auth/components/RegisterDesktop.jsx b/src/lib/auth/components/RegisterDesktop.jsx
index ac6ac960..482a9ce3 100644
--- a/src/lib/auth/components/RegisterDesktop.jsx
+++ b/src/lib/auth/components/RegisterDesktop.jsx
@@ -89,9 +89,19 @@ const RegisterDesktop = () => {
placeholder='••••••••••••'
/>
</div>
- <div class="flex items-center mt-4 ">
- <input type="checkbox" id='sdk' className='form-input flex items-start w-fit mr-2' required />
- <label onClick={() => setTnd(true)} className='inline cursor-pointer text-danger-500'>Syarat dan Ketentuan</label>
+ <div class='flex items-center mt-4 '>
+ <input
+ type='checkbox'
+ id='sdk'
+ className='form-input flex items-start w-fit mr-2'
+ required
+ />
+ <label
+ onClick={() => setTnd(true)}
+ className='inline cursor-pointer text-danger-500'
+ >
+ Syarat dan Ketentuan
+ </label>
</div>
<button
type='submit'
@@ -103,7 +113,9 @@ const RegisterDesktop = () => {
</form>
<div>
- <BottomPopup active={tnd} close={() => setTnd(false)}><PageContent path='/register#tnd'></PageContent></BottomPopup>
+ <BottomPopup active={tnd} close={() => setTnd(false)}>
+ <PageContent path='/register#tnd'></PageContent>
+ </BottomPopup>
</div>
<div className='text-gray_r-11 mt-10'>
diff --git a/src/lib/auth/components/RegisterMobile.jsx b/src/lib/auth/components/RegisterMobile.jsx
index 214584f4..f5c818e7 100644
--- a/src/lib/auth/components/RegisterMobile.jsx
+++ b/src/lib/auth/components/RegisterMobile.jsx
@@ -114,7 +114,7 @@ const RegisterMobile = () => {
<PageContent path='/register#tnd'></PageContent>
</BottomPopup>
</div>
-
+
<div className='text-gray_r-11 mt-4'>
Sudah punya akun Indoteknik?{' '}
<Link href='/login' className='inline'>
diff --git a/src/lib/auth/hooks/useRegister.js b/src/lib/auth/hooks/useRegister.js
index 2375cf19..4b0b0d60 100644
--- a/src/lib/auth/hooks/useRegister.js
+++ b/src/lib/auth/hooks/useRegister.js
@@ -38,7 +38,7 @@ const useRegister = () => {
setAlert(null)
setIsLoading(true)
const { fullname, email, password, companyName } = inputVal()
-
+
const isRegistered = await registerApi({
name: fullname,
company: companyName,
diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx
index f8c01e6d..bb1a17f7 100644
--- a/src/lib/brand/components/BrandCard.jsx
+++ b/src/lib/brand/components/BrandCard.jsx
@@ -8,7 +8,9 @@ const BrandCard = ({ brand }) => {
return (
<Link
href={createSlug('/shop/brands/', brand.name, brand.id)}
- className={`py-1 px-2 rounded border border-gray_r-6 flex justify-center items-center ${isMobile ? 'h-16' : 'h-24'}`}
+ className={`py-1 px-2 rounded border border-gray_r-6 flex justify-center items-center ${
+ isMobile ? 'h-16' : 'h-24'
+ }`}
>
{brand.logo && (
<Image
@@ -18,10 +20,7 @@ const BrandCard = ({ brand }) => {
/>
)}
{!brand.logo && (
- <span
- className='text-center'
- style={{ fontSize: `${16 - brand.name.length * 0.5}px` }}
- >
+ <span className='text-center' style={{ fontSize: `${16 - brand.name.length * 0.5}px` }}>
{brand.name}
</span>
)}
diff --git a/src/lib/brand/components/Brands.jsx b/src/lib/brand/components/Brands.jsx
index 25fb1c67..c7483e40 100644
--- a/src/lib/brand/components/Brands.jsx
+++ b/src/lib/brand/components/Brands.jsx
@@ -1,9 +1,7 @@
import odooApi from '@/core/api/odooApi'
-import Spinner from '@/core/components/elements/Spinner/Spinner'
-import DesktopView from '@/core/components/views/DesktopView'
-import MobileView from '@/core/components/views/MobileView'
import { useCallback, useEffect, useState } from 'react'
import BrandCard from './BrandCard'
+import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner'
const Brands = () => {
const alpha = Array.from(Array(26)).map((e, i) => i + 65)
@@ -41,7 +39,7 @@ const Brands = () => {
return (
<>
<div className='container flex justify-center my-4'>
- <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12 md:w-20 md:mt-28' />
+ <LogoSpinner width={48} height={48} />
</div>
</>
)
@@ -68,13 +66,7 @@ const Brands = () => {
<div className='grid grid-cols-4 gap-4 mt-4 md:grid-cols-7 !overflow-x-hidden'>
{manufactures?.map(
- (manufacture, index) =>
- manufacture.name && (
- <BrandCard
- brand={manufacture}
- key={index}
- />
- )
+ (manufacture, index) => manufacture.name && <BrandCard brand={manufacture} key={index} />
)}
</div>
</div>
diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx
index e2173268..d18b1a28 100644
--- a/src/lib/cart/components/Cart.jsx
+++ b/src/lib/cart/components/Cart.jsx
@@ -28,7 +28,7 @@ const Cart = () => {
const [deleteConfirmation, setDeleteConfirmation] = useState(null)
- const [productRecomendation, setProductRecomendation] = useState(null);
+ const [productRecomendation, setProductRecomendation] = useState(null)
useEffect(() => {
if (cart.data && !products) {
@@ -74,13 +74,14 @@ const Cart = () => {
useEffect(() => {
const LoadProductSImilar = async () => {
const randProductIndex = Math.floor(Math.random() * products.length)
- const productLoad = await productSearchApi({ query: `q=${products?.[randProductIndex].parent.name}&limit=10` })
-
- setProductRecomendation(productLoad);
+ const productLoad = await productSearchApi({
+ query: `q=${products?.[randProductIndex].parent.name}&limit=10`
+ })
+ setProductRecomendation(productLoad)
}
- if(products?.length > 0) LoadProductSImilar()
- },[products])
+ if (products?.length > 0) LoadProductSImilar()
+ }, [products])
const updateQuantity = (value, productId, operation = '') => {
let productIndex = products.findIndex((product) => product.id == productId)
@@ -424,7 +425,13 @@ const Cart = () => {
height={60}
/>
<div className='text-gray_r-12/90'>
- Tanya stock untuk pembelian anda sebelum melanjutkan pembayaran!<span> <a href='https://wa.me/628128080622' className='text-danger-500'>Hubungi Kami</a></span>
+ Tanya stock untuk pembelian anda sebelum melanjutkan pembayaran!
+ <span>
+ {' '}
+ <a href='https://wa.me/628128080622' className='text-danger-500'>
+ Hubungi Kami
+ </a>
+ </span>
</div>
</div>
</div>
@@ -465,7 +472,7 @@ const Cart = () => {
</div>
<div className='col-span-9 pt-2 pb-6 mt-6'>
- <h1 className='text-title-sm font-semibold mb-6'>Product Yang Mungkin Kamu Suka</h1>
+ <h1 className='text-title-sm font-semibold mb-6'>Product Yang Mungkin Kamu Suka</h1>
<div className='grid grid-cols-5 gap-x-3 gap-y-6'>
{productRecomendation &&
productRecomendation.response.products.map((product) => (
@@ -474,7 +481,6 @@ const Cart = () => {
</div>
</div>
</div>
-
</DesktopView>
</>
)
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index ba45e862..cb96b995 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -270,7 +270,7 @@ const Checkout = () => {
{products?.map((product) => (
<tr key={product.id}>
<td className='flex'>
- <div className='w-[30%] flex-shrink-0'>
+ <div className='w-[20%] flex-shrink-0'>
<Image
src={product?.parent?.image}
alt={product?.name}
@@ -444,9 +444,7 @@ const PickupAddress = ({ label }) => (
</p>
<p className='mt-1 text-gray_r-11'>Telp : 021-2933 8828/29</p>
<p className='mt-1 text-gray_r-11'>Mobile : 0813 9000 7430</p>
- <p className='mt-5 text-caption-2 text-gray_r-11 mb-2'>
- *) Belum termasuk biaya pengiriman
- </p>
+ <p className='mt-5 text-caption-2 text-gray_r-11 mb-2'>*) Belum termasuk biaya pengiriman</p>
</div>
</div>
)
diff --git a/src/lib/content/components/PageContent.jsx b/src/lib/content/components/PageContent.jsx
index 8b07cbfb..61e5381d 100644
--- a/src/lib/content/components/PageContent.jsx
+++ b/src/lib/content/components/PageContent.jsx
@@ -5,7 +5,7 @@ import Spinner from '@/core/components/elements/Spinner/Spinner'
const PageContent = ({ path }) => {
const fetchContent = async () => await pageContentApi({ path })
const content = useQuery(`content-${path}`, fetchContent)
-
+
if (content.data?.id) {
let parsedContent = content.data.content
parsedContent = parsedContent.replaceAll(
diff --git a/src/lib/home/components/PopularProduct.jsx b/src/lib/home/components/PopularProduct.jsx
index 78dc5d49..3ce7527e 100644
--- a/src/lib/home/components/PopularProduct.jsx
+++ b/src/lib/home/components/PopularProduct.jsx
@@ -15,10 +15,7 @@ const PopularProduct = () => {
<div className='font-medium mb-4'>Produk Banyak Dilihat</div>
{popularProducts.isLoading && <PopularProductSkeleton />}
{!popularProducts.isLoading && (
- <ProductSlider
- products={popularProducts.data}
- simpleTitle
- />
+ <ProductSlider products={popularProducts.data} simpleTitle />
)}
</div>
</MobileView>
@@ -31,14 +28,8 @@ const PopularProduct = () => {
<div className='h-full divide-y divide-gray_r-6'>
{popularProducts.data &&
popularProducts.data.products.map((product) => (
- <div
- className='py-2'
- key={product.id}
- >
- <ProductCard
- product={product}
- variant='horizontal'
- />
+ <div className='py-2' key={product.id}>
+ <ProductCard product={product} variant='horizontal' />
</div>
))}
</div>
diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx
index 7edd0730..f97943cb 100644
--- a/src/lib/home/components/PreferredBrand.jsx
+++ b/src/lib/home/components/PreferredBrand.jsx
@@ -14,21 +14,14 @@ const PreferredBrand = () => {
<div className='flex justify-between items-center mb-4'>
<div className='font-medium sm:text-h-lg'>Brand Pilihan</div>
{isDesktop && (
- <Link
- href='/'
- className='btn-yellow !text-gray_r-12'
- >
+ <Link href='/' className='btn-yellow !text-gray_r-12'>
Lihat Semua
</Link>
)}
</div>
{preferredBrands.isLoading && <PreferredBrandSkeleton />}
{!preferredBrands.isLoading && (
- <Swiper
- slidesPerView={isMobile ? 3.5 : 7.5}
- spaceBetween={isMobile ? 12 : 24}
- freeMode
- >
+ <Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 24} freeMode>
{preferredBrands.data?.manufactures.map((brand) => (
<SwiperSlide key={brand.id}>
<BrandCard brand={brand} />
diff --git a/src/lib/invoice/components/Invoice.jsx b/src/lib/invoice/components/Invoice.jsx
index 1094e2e4..81202b1c 100644
--- a/src/lib/invoice/components/Invoice.jsx
+++ b/src/lib/invoice/components/Invoice.jsx
@@ -200,7 +200,7 @@ const Invoice = ({ id }) => {
product?.parent.name,
product?.parent.id
)}
- className='w-[30%] flex-shrink-0'
+ className='w-[25%] flex-shrink-0'
>
<Image
src={product?.parent?.image}
@@ -254,7 +254,7 @@ const Invoice = ({ id }) => {
<div className='text-right font-medium text-gray_r-12'>
{currencyFormat(invoice.data?.amountTotal)}
</div>
-
+
<div className='text-right'>PPN 11% (Incl.)</div>
<div className='text-right font-medium'>{currencyFormat(totalAmount * 0.11)}</div>
</div>
diff --git a/src/lib/product/api/productSearchApi.js b/src/lib/product/api/productSearchApi.js
index f626e8cc..71fb72e6 100644
--- a/src/lib/product/api/productSearchApi.js
+++ b/src/lib/product/api/productSearchApi.js
@@ -2,7 +2,9 @@ import _ from 'lodash-contrib'
import axios from 'axios'
const productSearchApi = async ({ query }) => {
- const dataProductSearch = await axios(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/search?${query}&operation=OR`)
+ const dataProductSearch = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/search?${query}&operation=OR`
+ )
return dataProductSearch.data
}
diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx
index 0ff904af..73d072e8 100644
--- a/src/lib/product/components/Product/ProductDesktop.jsx
+++ b/src/lib/product/components/Product/ProductDesktop.jsx
@@ -80,7 +80,7 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
}
const productSimilarQuery = [
- product?.name.replace(/[()/"&]/g, ''),
+ product?.name,
`fq=-product_id_i:${product.id}`,
`fq=-manufacture_id_i:${product.manufacture?.id || 0}`
].join('&')
@@ -175,7 +175,7 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
Lihat Varian
</button>
) : (
- <td className='flex gap-x-3 mt-4'>
+ <div className='flex gap-x-3 mt-4'>
<input
type='number'
className='form-input w-16 py-2 text-center bg-gray_r-1'
@@ -196,7 +196,7 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
>
Beli
</button>
- </td>
+ </div>
)}
<div className='flex mt-4'>
diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx
index 493fcbf7..1194419e 100644
--- a/src/lib/product/components/Product/ProductMobile.jsx
+++ b/src/lib/product/components/Product/ProductMobile.jsx
@@ -96,7 +96,7 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
}
const productSimilarQuery = [
- product?.name.replace(/[()/"&]/g, ''),
+ product?.name,
`fq=-product_id_i:${product.id}`,
`fq=-manufacture_id_i:${product.manufacture?.id || 0}`
].join('&')
@@ -130,9 +130,11 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
</div>
<h1 className='leading-6 font-medium mb-3'>{activeVariant?.name}</h1>
- {product.variants.length > 1 && activeVariant.price.priceDiscount > 0 && !selectedVariant && (
- <div className='text-gray_r-12/80 text-caption-2 mt-2 mb-1'>Harga mulai dari: </div>
- )}
+ {product.variants.length > 1 &&
+ activeVariant.price.priceDiscount > 0 &&
+ !selectedVariant && (
+ <div className='text-gray_r-12/80 text-caption-2 mt-2 mb-1'>Harga mulai dari: </div>
+ )}
{activeVariant?.price?.discountPercentage > 0 && (
<div className='flex gap-x-1 items-center'>
diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx
index f85a0b03..a1c30d00 100644
--- a/src/lib/product/components/ProductCard.jsx
+++ b/src/lib/product/components/ProductCard.jsx
@@ -39,8 +39,8 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
)}
<Link
href={createSlug('/shop/product/', product?.name, product?.id)}
- className={`font-normal mb-2 !text-gray_r-12 leading-6 ${
- simpleTitle ? 'line-clamp-2' : 'line-clamp-3'
+ className={`font-normal mb-2 !text-gray_r-12 leading-6 block ${
+ simpleTitle ? 'line-clamp-2 h-12' : 'line-clamp-3 h-[64px]'
}`}
>
{product?.name}
diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx
index be1edd18..34357526 100644
--- a/src/lib/product/components/ProductFilter.jsx
+++ b/src/lib/product/components/ProductFilter.jsx
@@ -35,11 +35,7 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr
}
return (
- <BottomPopup
- active={active}
- close={close}
- title='Filter Produk'
- >
+ <BottomPopup active={active} close={close} title='Filter Produk'>
<div className='flex flex-col gap-y-4'>
{!defaultBrand && (
<div>
@@ -52,10 +48,7 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr
>
<option value=''>Pilih Brand...</option>
{brands.map((brand, index) => (
- <option
- value={brand}
- key={index}
- >
+ <option value={brand} key={index}>
{brand}
</option>
))}
@@ -72,10 +65,7 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr
>
<option value=''>Pilih Kategori...</option>
{categories.map((category, index) => (
- <option
- value={category}
- key={index}
- >
+ <option value={category} key={index}>
{category}
</option>
))}
@@ -117,11 +107,7 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr
/>
</div>
</div>
- <button
- type='button'
- className='btn-solid-red w-full mt-2'
- onClick={handleSubmit}
- >
+ <button type='button' className='btn-solid-red w-full mt-2' onClick={handleSubmit}>
Terapkan Filter
</button>
</div>
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index 0010a88a..81e7948b 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -26,13 +26,15 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
)
const productStart = productSearch.data?.responseHeader.params.start
const productRows = productSearch.data?.responseHeader.params.rows
- const productFound = productSearch.data?.response.numFound
-
- const brands = productSearch.data?.facetCounts?.facetFields?.manufactureName?.filter((value, index) => {
- if (index % 2 === 0) {
- return true
+ const productFound = productSearch.data?.response.numFound
+
+ const brands = productSearch.data?.facetCounts?.facetFields?.manufactureName?.filter(
+ (value, index) => {
+ if (index % 2 === 0) {
+ return true
+ }
}
- })
+ )
const categories = productSearch.data?.facetCounts?.facetFields?.categoryName?.filter(
(value, index) => {
if (index % 2 === 0) {
diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx
index ed7db486..c8bd3a82 100644
--- a/src/lib/product/components/ProductSlider.jsx
+++ b/src/lib/product/components/ProductSlider.jsx
@@ -44,18 +44,12 @@ const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) =>
>
{bannerMode && (
<SwiperSlide>
- <Link
- href={products.banner.url}
- className='w-full h-full block'
- ></Link>
+ <Link href={products.banner.url} className='w-full h-full block'></Link>
</SwiperSlide>
)}
{products?.products?.map((product, index) => (
<SwiperSlide key={index}>
- <ProductCard
- product={product}
- simpleTitle={simpleTitle}
- />
+ <ProductCard product={product} simpleTitle={simpleTitle} />
</SwiperSlide>
))}
</Swiper>
diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx
index ad59f8dd..b4e050c6 100644
--- a/src/lib/transaction/components/Transaction.jsx
+++ b/src/lib/transaction/components/Transaction.jsx
@@ -368,7 +368,7 @@ const Transaction = ({ id }) => {
product?.parent.name,
product?.parent.id
)}
- className='w-[30%] flex-shrink-0'
+ className='w-[25%] flex-shrink-0'
>
<Image
src={product?.parent?.image}
@@ -426,7 +426,9 @@ const Transaction = ({ id }) => {
</div>
<div className='text-right'>PPN 11%</div>
- <div className='text-right font-medium'>{currencyFormat(transaction.data?.amountTax)}</div>
+ <div className='text-right font-medium'>
+ {currencyFormat(transaction.data?.amountTax)}
+ </div>
<div className='text-right'>Grand Total</div>
<div className='text-right font-medium text-gray_r-12'>
diff --git a/src/lib/variant/components/VariantGroupCard.jsx b/src/lib/variant/components/VariantGroupCard.jsx
index e5f5c7fc..8cb1eec4 100644
--- a/src/lib/variant/components/VariantGroupCard.jsx
+++ b/src/lib/variant/components/VariantGroupCard.jsx
@@ -8,11 +8,7 @@ const VariantGroupCard = ({ variants, ...props }) => {
return (
<>
{variantsToShow?.map((variant, index) => (
- <VariantCard
- key={index}
- product={variant}
- {...props}
- />
+ <VariantCard key={index} product={variant} {...props} />
))}
{variants.length > 2 && (
<button
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index 634e631f..3c93d27f 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -1,11 +1,12 @@
import '../styles/globals.css'
import NextProgress from 'next-progress'
-import { useRouter } from 'next/router'
+import { useRouter, Router } from 'next/router'
import { AnimatePresence } from 'framer-motion'
import { Toaster } from 'react-hot-toast'
import { QueryClient, QueryClientProvider } from 'react-query'
import useDevice from '@/core/hooks/useDevice'
import { useEffect, useState } from 'react'
+import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner'
const queryClient = new QueryClient()
@@ -13,6 +14,18 @@ function MyApp({ Component, pageProps }) {
const router = useRouter()
const { isMobile } = useDevice()
+ const [animateLoader, setAnimateLoader] = useState(false)
+
+ useEffect(() => {
+ Router.events.on('routeChangeStart', () => setAnimateLoader(true))
+ Router.events.on('routeChangeComplete', () => setAnimateLoader(false))
+
+ return () => {
+ Router.events.off('routeChangeStart', () => setAnimateLoader(true))
+ Router.events.off('routeChangeComplete', () => setAnimateLoader(false))
+ }
+ }, [])
+
const [toasterStyle, setToasterStyle] = useState({})
useEffect(() => {
@@ -30,6 +43,11 @@ function MyApp({ Component, pageProps }) {
return (
<>
+ {animateLoader && (
+ <div className='w-screen h-screen z-[500] flex justify-center items-center backdrop-blur'>
+ <LogoSpinner />
+ </div>
+ )}
<Toaster
position='top-center'
containerStyle={toasterStyle}
@@ -45,7 +63,7 @@ function MyApp({ Component, pageProps }) {
initial={false}
onExitComplete={() => window.scrollTo(0, 0)}
>
- <Component {...pageProps} key={router.asPath} />
+ {!animateLoader && <Component {...pageProps} key={router.asPath} />}
</AnimatePresence>
</QueryClientProvider>
</>
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index ef070dcd..bab96237 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -15,19 +15,19 @@ export default async function handler(req, res) {
limit = 30
} = req.query
- let paramOrderBy = ''
+ let paramOrderBy = 'product_rating_f DESC'
switch (orderBy) {
case 'price-asc':
- paramOrderBy = ', price_discount_f ASC'
+ paramOrderBy += ', price_discount_f ASC'
break
case 'price-desc':
- paramOrderBy = ', price_discount_f DESC'
+ paramOrderBy += ', price_discount_f DESC'
break
case 'popular':
- paramOrderBy = ', search_rank_i DESC'
+ paramOrderBy += ', search_rank_i DESC'
break
case 'stock':
- paramOrderBy = ', stock_total_f DESC'
+ paramOrderBy += ', stock_total_f DESC'
break
}
@@ -37,12 +37,13 @@ export default async function handler(req, res) {
'facet.field=category_name',
'facet=true',
'indent=true',
- `facet.query=${q}`,
+ `facet.query=${escapeSolrQuery(q)}`,
`q.op=${operation}`,
`q=${escapeSolrQuery(q)}`,
+ 'qf=name_s',
`start=${offset}`,
`rows=${limit}`,
- `sort=product_rating_f DESC ${paramOrderBy}`,
+ `sort=${paramOrderBy}`,
`fq=price_discount_f:[${priceFrom == '' ? '*' : priceFrom} TO ${priceTo == '' ? '*' : priceTo}]`
]
@@ -68,9 +69,18 @@ export default async function handler(req, res) {
}
const escapeSolrQuery = (query) => {
- const specialChars = /[\]\[{}()"\\]/g
- const escapedQuery = query.replace(specialChars, '\\$&')
- return escapedQuery
+ if (query == '*') return query
+
+ const specialChars = /([\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/])/g
+ const words = query.split(/\s+/)
+ const escapedWords = words.map((word) => {
+ if (specialChars.test(word)) {
+ return `"${word.replace(specialChars, '\\$1')}"`
+ }
+ return word
+ })
+
+ return escapedWords.join(' ')
}
const productResponseMap = (products) => {
diff --git a/src/pages/api/shop/suggest.js b/src/pages/api/shop/suggest.js
index 5a1b559a..83ab69d4 100644
--- a/src/pages/api/shop/suggest.js
+++ b/src/pages/api/shop/suggest.js
@@ -5,7 +5,7 @@ export default async function handler(req, res) {
let result = await axios(
process.env.SOLR_HOST +
- `/solr/product/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.q=${q}`
+ `/solr/product/suggest?suggest=true&suggest.dictionary=mySuggester&q=${q}`
)
try {
res.status(200).json(result.data.suggest.mySuggester[q])
diff --git a/src/pages/forgot-password.jsx b/src/pages/forgot-password.jsx
index 6211d237..23239363 100644
--- a/src/pages/forgot-password.jsx
+++ b/src/pages/forgot-password.jsx
@@ -91,7 +91,11 @@ const FormComponent = () => {
placeholder='Masukan alamat email'
autoFocus
/>
- <button type='submit' disabled={!email || isLoading} className='btn-yellow font-semibold mt-4 w-full'>
+ <button
+ type='submit'
+ disabled={!email || isLoading}
+ className='btn-yellow font-semibold mt-4 w-full'
+ >
{isLoading ? 'Loading...' : 'Kirim Permintaan'}
</button>
</form>
diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx
index 851bcf56..e7ae27fd 100644
--- a/src/pages/my/menu.jsx
+++ b/src/pages/my/menu.jsx
@@ -19,10 +19,7 @@ export default function Menu() {
return (
<IsAuth>
<AppLayout title='Menu Utama'>
- <Link
- href='/my/profile'
- className='p-4 flex items-center'
- >
+ <Link href='/my/profile' className='p-4 flex items-center'>
<div className='rounded-full p-3 bg-gray_r-6 text-gray_r-12/80'>
<UserIcon className='w-5' />
</div>
@@ -64,10 +61,7 @@ export default function Menu() {
<LinkItem href='/my/address'>Daftar Alamat</LinkItem>
</div>
- <div
- onClick={logout}
- className='p-4 mt-2'
- >
+ <div onClick={logout} className='p-4 mt-2'>
<button className='w-full btn-red'>Keluar Akun</button>
</div>
</div>
@@ -78,19 +72,13 @@ export default function Menu() {
}
const MenuHeader = ({ children, ...props }) => (
- <div
- {...props}
- className='font-medium px-4 flex'
- >
+ <div {...props} className='font-medium px-4 flex'>
{children}
</div>
)
const LinkItem = ({ children, ...props }) => (
- <Link
- {...props}
- className='!text-gray_r-12/70 !font-normal p-4 flex items-center'
- >
+ <Link {...props} className='!text-gray_r-12/70 !font-normal p-4 flex items-center'>
{children}
<div className='ml-auto !text-gray_r-11'>
<ChevronRightIcon className='w-5' />
diff --git a/src/pages/reset-password.jsx b/src/pages/reset-password.jsx
index a4aa2201..0bf6f31e 100644
--- a/src/pages/reset-password.jsx
+++ b/src/pages/reset-password.jsx
@@ -46,7 +46,7 @@ const FormComponent = () => {
const checkValidPassword = () => {
const passwordVal = password.current.value
const retypePasswordVal = retypePassword.current.value
- if (passwordVal == retypePasswordVal) {
+ if (passwordVal && passwordVal == retypePasswordVal) {
setIsValidPassword(true)
} else {
setIsValidPassword(false)
@@ -56,7 +56,10 @@ const FormComponent = () => {
const resetPasswordRequest = async (e) => {
e.preventDefault()
setIsLoading(true)
- const result = await odooApi('POST', '/api/v1/user/reset-password', { token })
+ const result = await odooApi('POST', '/api/v1/user/reset-password', {
+ token,
+ password: password.current.value
+ })
setIsLoading(false)
password.current.value = ''
retypePassword.current.value = ''
diff --git a/src/pages/shop/brands/[slug].jsx b/src/pages/shop/brands/[slug].jsx
index 9c5193ad..88f19bc0 100644
--- a/src/pages/shop/brands/[slug].jsx
+++ b/src/pages/shop/brands/[slug].jsx
@@ -11,7 +11,7 @@ const Brand = dynamic(() => import('@/lib/brand/components/Brand'))
export default function BrandDetail() {
const router = useRouter()
const { slug = '' } = router.query
-
+
const brandName = getNameFromSlug(slug)
return (
<BasicLayout>
@@ -21,8 +21,7 @@ export default function BrandDetail() {
additionalMetaTags={[
{
property: 'keywords',
- content:
- `Jual ${brandName}, beli ${brandName}, Distributor ${brandName} Indonesia, cari ${brandName}, produk ${brandName}, ${brandName} Indonesia, harga ${brandName}`
+ content: `Jual ${brandName}, beli ${brandName}, Distributor ${brandName} Indonesia, cari ${brandName}, produk ${brandName}, ${brandName} Indonesia, harga ${brandName}`
}
]}
/>
diff --git a/src/pages/shop/checkout/[status].jsx b/src/pages/shop/checkout/[status].jsx
index 7c39718c..2c3bebcf 100644
--- a/src/pages/shop/checkout/[status].jsx
+++ b/src/pages/shop/checkout/[status].jsx
@@ -21,7 +21,7 @@ export default function Finish() {
return (
<>
<Seo title='Checkout Indoteknik.com' />
-
+
<IsAuth>
<BasicLayout>
<FinishCheckoutComponent query={router.query || {}} />
diff --git a/src/pages/shop/quotation/finish.jsx b/src/pages/shop/quotation/finish.jsx
index f6c0ac6b..0e9c5672 100644
--- a/src/pages/shop/quotation/finish.jsx
+++ b/src/pages/shop/quotation/finish.jsx
@@ -12,37 +12,37 @@ export default function FinishQuotation() {
const { id } = router.query
return (
<>
- <Seo title='Quotation Indoteknik.com' />
-
- <IsAuth>
- <BasicLayout>
- <div className='mx-auto container'>
- <div className='m-4 md:m-0 md:mt-10 px-4 py-6 shadow-md border border-gray_r-3'>
- <div className='flex'>
- <span className='p-3 mx-auto bg-warning-100 border border-warning-300 rounded'>
- <EnvelopeIcon className='w-8 text-warning-800' />
- </span>
- </div>
- <p className='h2 text-center mt-6'>Terima Kasih {auth?.name}</p>
- <p className='text-center mt-3 leading-6 text-gray_r-11'>
- Penawaran harga kamu di Indoteknik.com berhasil dikirimkan, tim kami akan segera
- menghubungi anda.
- </p>
- {id && (
- <Link
- href={`/my/transaction/${id}`}
- className='btn-yellow !text-gray_r-12 mt-6 w-full md:w-1/3 md:mx-auto'
- >
- Lihat Penawaran
+ <Seo title='Quotation Indoteknik.com' />
+
+ <IsAuth>
+ <BasicLayout>
+ <div className='mx-auto container'>
+ <div className='m-4 md:m-0 md:mt-10 px-4 py-6 shadow-md border border-gray_r-3'>
+ <div className='flex'>
+ <span className='p-3 mx-auto bg-warning-100 border border-warning-300 rounded'>
+ <EnvelopeIcon className='w-8 text-warning-800' />
+ </span>
+ </div>
+ <p className='h2 text-center mt-6'>Terima Kasih {auth?.name}</p>
+ <p className='text-center mt-3 leading-6 text-gray_r-11'>
+ Penawaran harga kamu di Indoteknik.com berhasil dikirimkan, tim kami akan segera
+ menghubungi anda.
+ </p>
+ {id && (
+ <Link
+ href={`/my/transaction/${id}`}
+ className='btn-yellow !text-gray_r-12 mt-6 w-full md:w-1/3 md:mx-auto'
+ >
+ Lihat Penawaran
+ </Link>
+ )}
+ <Link href='/' className='btn-light !text-gray_r-12 mt-2 w-full md:w-1/3 md:mx-auto'>
+ Ke Halaman Utama
</Link>
- )}
- <Link href='/' className='btn-light !text-gray_r-12 mt-2 w-full md:w-1/3 md:mx-auto'>
- Ke Halaman Utama
- </Link>
+ </div>
</div>
- </div>
- </BasicLayout>
- </IsAuth>
+ </BasicLayout>
+ </IsAuth>
</>
)
}
diff --git a/src/pages/shop/search.jsx b/src/pages/shop/search.jsx
index bf38d0bc..907465b7 100644
--- a/src/pages/shop/search.jsx
+++ b/src/pages/shop/search.jsx
@@ -13,12 +13,7 @@ export default function Search() {
<BasicLayout>
<Seo title={`Cari produk ${router.query.q || ''} di Indoteknik.com`} />
- {!_.isEmpty(router.query) && (
- <ProductSearch
- query={router.query}
- prefixUrl='/shop/search'
- />
- )}
+ {!_.isEmpty(router.query) && <ProductSearch query={router.query} prefixUrl='/shop/search' />}
</BasicLayout>
)
}
diff --git a/src/pages/sitemap/products/[id].xml.js b/src/pages/sitemap/products/[id].xml.js
index e9caaa00..98c2bf40 100644
--- a/src/pages/sitemap/products/[id].xml.js
+++ b/src/pages/sitemap/products/[id].xml.js
@@ -8,7 +8,7 @@ export async function getServerSideProps({ res }) {
const limit = 2500
const query = { limit }
const products = await productSearchApi({ query: _.toQuery(query) })
- console.log(products);
+ console.log(products)
// const sitemap = create('urlset', { encoding: 'UTF-8' })
// const date = new Date()
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 551ff057..d97843a9 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -133,7 +133,7 @@ button {
.btn-yellow {
@apply bg-warning-500
border-warning-500
- hover:bg-warning-600
+ hover:bg-warning-500/80
disabled:text-gray_r-10
disabled:bg-warning-200
disabled:border-warning-200;
@@ -151,7 +151,7 @@ button {
@apply bg-danger-500
border-danger-500
text-gray_r-1
- hover:bg-danger-600
+ hover:bg-danger-500/80
disabled:text-gray_r-1
disabled:bg-danger-200
disabled:border-danger-200;
@@ -602,3 +602,20 @@ button {
duration-100
font-normal;
}
+
+@keyframes page-loader {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.page-loader {
+ animation-name: page-loader;
+ animation-duration: 1000ms;
+ animation-delay: 50ms;
+ animation-timing-function: ease-in-out;
+ animation-iteration-count: infinite;
+}