From 9c2c365da1edb2e2835d19303cdee81e53f3deb8 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 10 Apr 2023 14:43:30 +0700 Subject: fix reset password, register, search, suggest --- src/lib/auth/api/registerApi.js | 2 +- src/lib/auth/components/PersonalProfile.jsx | 2 +- src/lib/checkout/components/Checkout.jsx | 2 +- .../product/components/Product/ProductDesktop.jsx | 2 +- .../product/components/Product/ProductMobile.jsx | 2 +- src/pages/api/shop/search.js | 30 ++++++++++++++-------- src/pages/api/shop/suggest.js | 2 +- src/pages/reset-password.jsx | 7 +++-- 8 files changed, 31 insertions(+), 18 deletions(-) (limited to 'src') 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/PersonalProfile.jsx b/src/lib/auth/components/PersonalProfile.jsx index 0b387f2e..4f606ed4 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', '') diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 17ac20e1..37a67d88 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -270,7 +270,7 @@ const Checkout = () => { {products?.map((product) => ( -
+
{product?.name} { } const productSimilarQuery = [ - product?.name.replace(/[()/"&]/g, ''), + product?.name, `fq=-product_id_i:${product.id}`, `fq=-manufacture_id_i:${product.manufacture?.id || 0}` ].join('&') diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx index 493fcbf7..19b4c4b2 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('&') 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/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 = '' -- cgit v1.2.3 From 8dea9e9242aca8bf003a7c2f69c96abafbf77e6d Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 10 Apr 2023 16:29:48 +0700 Subject: page loader --- src/core/components/elements/Link/Link.jsx | 8 ------- src/images/LOGO-INDOTEKNIK-GEAR-GREY.png | Bin 0 -> 14190 bytes src/images/LOGO-INDOTEKNIK-GEAR.png | Bin 0 -> 18304 bytes src/lib/invoice/components/Invoice.jsx | 2 +- src/lib/product/components/ProductCard.jsx | 4 ++-- src/lib/transaction/components/Transaction.jsx | 2 +- src/pages/_app.jsx | 29 +++++++++++++++++++++++-- src/styles/globals.css | 21 ++++++++++++++++-- 8 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 src/images/LOGO-INDOTEKNIK-GEAR-GREY.png create mode 100644 src/images/LOGO-INDOTEKNIK-GEAR.png (limited to 'src') diff --git a/src/core/components/elements/Link/Link.jsx b/src/core/components/elements/Link/Link.jsx index 360444a6..b2dbd02f 100644 --- a/src/core/components/elements/Link/Link.jsx +++ b/src/core/components/elements/Link/Link.jsx @@ -1,14 +1,6 @@ import NextLink from 'next/link' -import { useRouter } from 'next/router' -import { useEffect } from 'react' const Link = ({ children, ...props }) => { - const router = useRouter() - - useEffect(() => { - router.events.on('routeChangeComplete', () => window.scrollTo({ top: 0, behavior: 'smooth' })) - }, [router]) - return ( { product?.parent.name, product?.parent.id )} - className='w-[30%] flex-shrink-0' + className='w-[25%] flex-shrink-0' > { )} {product?.name} diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index ad59f8dd..7dfb13fb 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' > { + 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 +44,17 @@ function MyApp({ Component, pageProps }) { return ( <> + {animateLoader && ( +
+ Indoteknik Logo +
+ )} window.scrollTo(0, 0)} > - + {!animateLoader && } 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; +} -- cgit v1.2.3 From 62bebc1d33fd090d7666e18e7a0326ef7ef36897 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 10 Apr 2023 16:49:16 +0700 Subject: fix --- src/core/components/elements/Spinner/LogoSpinner.jsx | 15 +++++++++++++++ src/lib/brand/components/Brands.jsx | 14 +++----------- src/lib/product/components/Product/ProductDesktop.jsx | 4 ++-- src/pages/_app.jsx | 11 ++--------- 4 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 src/core/components/elements/Spinner/LogoSpinner.jsx (limited to 'src') 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 }) => ( + Indoteknik Logo +) + +export default LogoSpinner 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 ( <>
- +
) @@ -68,13 +66,7 @@ const Brands = () => {
{manufactures?.map( - (manufacture, index) => - manufacture.name && ( - - ) + (manufacture, index) => manufacture.name && )}
diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx index 751c0014..f926f171 100644 --- a/src/lib/product/components/Product/ProductDesktop.jsx +++ b/src/lib/product/components/Product/ProductDesktop.jsx @@ -170,7 +170,7 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => { Lihat Varian ) : ( - +
{ > Beli - +
)}
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index 6906cb92..3c93d27f 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -6,8 +6,7 @@ import { Toaster } from 'react-hot-toast' import { QueryClient, QueryClientProvider } from 'react-query' import useDevice from '@/core/hooks/useDevice' import { useEffect, useState } from 'react' -import Image from 'next/image' -import IndoteknikLogo from '@/images/LOGO-INDOTEKNIK-GEAR.png' +import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner' const queryClient = new QueryClient() @@ -46,13 +45,7 @@ function MyApp({ Component, pageProps }) { <> {animateLoader && (
- Indoteknik Logo +
)} Date: Tue, 11 Apr 2023 09:47:25 +0700 Subject: Documentation and refactor code --- src/core/api/odooApi.js | 11 ++++ src/core/components/elements/Alert/Alert.jsx | 10 ++++ src/core/components/elements/Appbar/Appbar.jsx | 29 +++++------ src/core/components/elements/Divider/Divider.jsx | 8 +++ src/core/components/elements/Image/Image.jsx | 8 +++ src/core/components/elements/Link/Link.jsx | 8 +++ .../components/elements/Navbar/NavbarMobile.jsx | 12 +---- src/core/components/elements/Navbar/Search.jsx | 10 +--- .../components/elements/Pagination/Pagination.js | 5 +- .../components/elements/Skeleton/BrandSkeleton.jsx | 5 +- .../components/elements/Skeleton/ImageSkeleton.jsx | 10 +--- .../elements/Skeleton/ProductCardSkeleton.jsx | 5 +- src/core/hooks/useDevice.js | 1 - src/core/hooks/useSidebar.js | 7 +-- src/core/utils/address.js | 35 +++++++++++-- src/core/utils/auth.js | 20 ++++++-- src/core/utils/cart.js | 41 +++++++++++++-- src/core/utils/currencyFormat.js | 6 +++ src/core/utils/getFileBase64.js | 13 ++++- src/core/utils/greeting.js | 10 ++++ src/core/utils/slug.js | 24 +++++++++ src/core/utils/toTitleCase.js | 9 ++++ src/lib/address/components/Addresses.jsx | 5 +- src/lib/address/components/EditAddress.jsx | 2 +- src/lib/auth/components/Activate.jsx | 52 ++++++------------- src/lib/auth/components/CompanyProfile.jsx | 37 +++----------- src/lib/auth/components/Login.jsx | 4 +- src/lib/auth/components/PersonalProfile.jsx | 32 +++--------- src/lib/auth/components/RegisterDesktop.jsx | 20 ++++++-- src/lib/auth/components/RegisterMobile.jsx | 2 +- src/lib/auth/hooks/useRegister.js | 2 +- src/lib/brand/components/BrandCard.jsx | 9 ++-- src/lib/cart/components/Cart.jsx | 24 +++++---- src/lib/checkout/components/Checkout.jsx | 4 +- src/lib/content/components/PageContent.jsx | 2 +- src/lib/home/components/PopularProduct.jsx | 15 ++---- src/lib/home/components/PreferredBrand.jsx | 11 +--- src/lib/invoice/components/Invoice.jsx | 2 +- src/lib/product/api/productSearchApi.js | 4 +- .../product/components/Product/ProductMobile.jsx | 8 +-- src/lib/product/components/ProductFilter.jsx | 22 ++------ src/lib/product/components/ProductSearch.jsx | 14 +++--- src/lib/product/components/ProductSlider.jsx | 10 +--- src/lib/transaction/components/Transaction.jsx | 4 +- src/lib/variant/components/VariantGroupCard.jsx | 6 +-- src/pages/forgot-password.jsx | 6 ++- src/pages/my/menu.jsx | 20 ++------ src/pages/shop/brands/[slug].jsx | 5 +- src/pages/shop/checkout/[status].jsx | 2 +- src/pages/shop/quotation/finish.jsx | 58 +++++++++++----------- src/pages/shop/search.jsx | 7 +-- src/pages/sitemap/products/[id].xml.js | 2 +- 52 files changed, 359 insertions(+), 319 deletions(-) (limited to 'src') 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 (