summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-04-11 09:47:25 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-04-11 09:47:25 +0700
commit92c2a229d9c9b510d71b928978872a8b107e9d5a (patch)
tree8d8161a49a0bdc46d4c28d3f2682bb485314a41d /src/core
parent62bebc1d33fd090d7666e18e7a0326ef7ef36897 (diff)
Documentation and refactor code
Diffstat (limited to 'src/core')
-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.jsx8
-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/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/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
22 files changed, 212 insertions, 75 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 b2dbd02f..f6b39d45 100644
--- a/src/core/components/elements/Link/Link.jsx
+++ b/src/core/components/elements/Link/Link.jsx
@@ -1,5 +1,13 @@
import NextLink from 'next/link'
+/**
+ * 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 }) => {
return (
<NextLink
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/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/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()