From f99e0aba70efad0deb907d8e27f09fc9f527c8a4 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 17 Feb 2023 17:07:50 +0700 Subject: Refactor --- src2/components/elements/Alert.js | 19 ++++ src2/components/elements/BottomPopup.js | 25 ++++ src2/components/elements/ConfirmAlert.js | 27 +++++ src2/components/elements/DescriptionRow.js | 10 ++ src2/components/elements/Disclosure.js | 14 +++ src2/components/elements/Fields.js | 21 ++++ src2/components/elements/Filter.js | 176 +++++++++++++++++++++++++++++ src2/components/elements/Image.js | 17 +++ src2/components/elements/LineDivider.js | 7 ++ src2/components/elements/Link.js | 13 +++ src2/components/elements/Pagination.js | 58 ++++++++++ src2/components/elements/ProgressBar.js | 25 ++++ src2/components/elements/Skeleton.js | 48 ++++++++ src2/components/elements/Spinner.js | 13 +++ 14 files changed, 473 insertions(+) create mode 100644 src2/components/elements/Alert.js create mode 100644 src2/components/elements/BottomPopup.js create mode 100644 src2/components/elements/ConfirmAlert.js create mode 100644 src2/components/elements/DescriptionRow.js create mode 100644 src2/components/elements/Disclosure.js create mode 100644 src2/components/elements/Fields.js create mode 100644 src2/components/elements/Filter.js create mode 100644 src2/components/elements/Image.js create mode 100644 src2/components/elements/LineDivider.js create mode 100644 src2/components/elements/Link.js create mode 100644 src2/components/elements/Pagination.js create mode 100644 src2/components/elements/ProgressBar.js create mode 100644 src2/components/elements/Skeleton.js create mode 100644 src2/components/elements/Spinner.js (limited to 'src2/components/elements') diff --git a/src2/components/elements/Alert.js b/src2/components/elements/Alert.js new file mode 100644 index 00000000..914d1590 --- /dev/null +++ b/src2/components/elements/Alert.js @@ -0,0 +1,19 @@ +const Alert = ({ children, className, type }) => { + let typeClass = ''; + switch (type) { + case 'info': + typeClass = ' bg-blue-100 text-blue-900 border-blue-400 ' + break; + case 'success': + typeClass = ' bg-green-100 text-green-900 border-green-400 ' + break; + case 'warning': + typeClass = ' bg-yellow-100 text-yellow-900 border-yellow-400 ' + break; + } + return ( +
{children}
+ ); +} + +export default Alert; \ No newline at end of file diff --git a/src2/components/elements/BottomPopup.js b/src2/components/elements/BottomPopup.js new file mode 100644 index 00000000..c1a56e10 --- /dev/null +++ b/src2/components/elements/BottomPopup.js @@ -0,0 +1,25 @@ +import CloseIcon from "@/icons/close.svg"; + +const BottomPopup = ({ + active = false, + title, + children, + closePopup = () => {} +}) => { + return ( + <> +
+
+
+

{ title }

+ +
+ { children } +
+ + ); +}; + +export default BottomPopup; \ No newline at end of file diff --git a/src2/components/elements/ConfirmAlert.js b/src2/components/elements/ConfirmAlert.js new file mode 100644 index 00000000..d33abb89 --- /dev/null +++ b/src2/components/elements/ConfirmAlert.js @@ -0,0 +1,27 @@ +const ConfirmAlert = ({ + title, + caption, + show, + onClose, + onSubmit, + closeText, + submitText +}) => { + return ( + <> + {show && ( +
+ )} +
+

{title}

+

{caption}

+
+ + +
+
+ + ); +}; + +export default ConfirmAlert; \ No newline at end of file diff --git a/src2/components/elements/DescriptionRow.js b/src2/components/elements/DescriptionRow.js new file mode 100644 index 00000000..7fe9e3a1 --- /dev/null +++ b/src2/components/elements/DescriptionRow.js @@ -0,0 +1,10 @@ +const DescriptionRow = ({ label, children }) => ( +
+

{ label }

+
+ { children } +
+
+); + +export default DescriptionRow; \ No newline at end of file diff --git a/src2/components/elements/Disclosure.js b/src2/components/elements/Disclosure.js new file mode 100644 index 00000000..1f334be3 --- /dev/null +++ b/src2/components/elements/Disclosure.js @@ -0,0 +1,14 @@ +const { ChevronUpIcon, ChevronDownIcon } = require("@heroicons/react/24/outline"); + +const Disclosure = ({ label, active, onClick }) => ( +
+

{ label }

+ { onClick && ( active ? ( + + ) : ( + + ) ) } +
+); + +export default Disclosure; \ No newline at end of file diff --git a/src2/components/elements/Fields.js b/src2/components/elements/Fields.js new file mode 100644 index 00000000..586a6a22 --- /dev/null +++ b/src2/components/elements/Fields.js @@ -0,0 +1,21 @@ +import ReactSelect from "react-select"; + +const Select = ({ + field, + ...props +}) => ( + <> + field.onChange(option.value)} + value={field.value ? props.options.find(option => option.value === field.value) : ''} + isDisabled={props.disabled} + {...props} + /> + +); + +export { + Select +}; \ No newline at end of file diff --git a/src2/components/elements/Filter.js b/src2/components/elements/Filter.js new file mode 100644 index 00000000..f2051ba8 --- /dev/null +++ b/src2/components/elements/Filter.js @@ -0,0 +1,176 @@ +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import BottomPopup from "./BottomPopup"; + +const Filter = ({ + isActive, + closeFilter, + defaultRoute, + defaultPriceFrom, + defaultPriceTo, + defaultCategory, + defaultBrand, + defaultOrderBy, + searchResults, + disableFilter = [] +}) => { + const router = useRouter(); + + const [priceFrom, setPriceFrom] = useState(defaultPriceFrom); + const [priceTo, setPriceTo] = useState(defaultPriceTo); + const [orderBy, setOrderBy] = useState(defaultOrderBy); + const [selectedCategory, setSelectedCategory] = useState(defaultCategory); + const [selectedBrand, setSelectedBrand] = useState(defaultBrand); + const [categories, setCategories] = useState([]); + const [brands, setBrands] = useState([]); + + const filterRoute = () => { + let filterRoute = []; + let filterRoutePrefix = '?'; + if (selectedBrand) filterRoute.push(`brand=${selectedBrand}`); + if (selectedCategory) filterRoute.push(`category=${selectedCategory}`); + if (priceFrom) filterRoute.push(`price_from=${priceFrom}`); + if (priceTo) filterRoute.push(`price_to=${priceTo}`); + if (orderBy) filterRoute.push(`order_by=${orderBy}`); + + if (defaultRoute.includes('?')) filterRoutePrefix = '&'; + if (filterRoute.length > 0) { + filterRoute = filterRoutePrefix + filterRoute.join('&'); + } else { + filterRoute = ''; + } + + return defaultRoute + filterRoute; + } + + useEffect(() => { + const filterCategory = searchResults.facet_counts.facet_fields.category_name_str.filter((category, index) => { + if (index % 2 == 0) { + const productCountInCategory = searchResults.facet_counts.facet_fields.category_name_str[index + 1]; + if (productCountInCategory > 0) return category; + } + }); + setCategories(filterCategory); + + const filterBrand = searchResults.facet_counts.facet_fields.brand_str.filter((brand, index) => { + if (index % 2 == 0) { + const productCountInBrand = searchResults.facet_counts.facet_fields.brand_str[index + 1]; + if (productCountInBrand > 0) return brand; + } + }); + setBrands(filterBrand); + }, [searchResults]); + + const submit = (e) => { + e.preventDefault(); + closeFilter(); + router.push(filterRoute(), undefined, { scroll: false }); + } + + const reset = () => { + setSelectedBrand(''); + setSelectedCategory(''); + setPriceFrom(''); + setPriceTo(''); + setOrderBy(''); + } + + const changeOrderBy = (value) => { + if (orderBy == value) { + setOrderBy(''); + } else { + setOrderBy(value); + } + } + + const sortOptions = [ + { + name: 'Harga Terendah', + value: 'price-asc', + }, + { + name: 'Harga Tertinggi', + value: 'price-desc', + }, + { + name: 'Populer', + value: 'popular', + }, + { + name: 'Ready Stock', + value: 'stock', + }, + ]; + + return ( + <> + +
+ {(selectedBrand || selectedCategory || priceFrom || priceTo || orderBy) && ( + + )} + + {!disableFilter.includes('orderBy') && ( +
+ +
+ {sortOptions.map((sortOption, index) => ( + + ))} +
+
+ )} + + {!disableFilter.includes('category') && ( +
+ + +
+ )} + + {!disableFilter.includes('brand') && ( +
+ + +
+ )} + + {!disableFilter.includes('price') && ( +
+ +
+ setPriceFrom(e.target.value)}/> + + setPriceTo(e.target.value)}/> +
+
+ )} + +
+
+ + ) +}; + +export default Filter; \ No newline at end of file diff --git a/src2/components/elements/Image.js b/src2/components/elements/Image.js new file mode 100644 index 00000000..60e249b9 --- /dev/null +++ b/src2/components/elements/Image.js @@ -0,0 +1,17 @@ +import { LazyLoadImage } from "react-lazy-load-image-component" +import "react-lazy-load-image-component/src/effects/opacity.css" + +const Image = ({ ...props }) => { + return ( + + ) +} + +Image.defaultProps = LazyLoadImage.defaultProps + +export default Image \ No newline at end of file diff --git a/src2/components/elements/LineDivider.js b/src2/components/elements/LineDivider.js new file mode 100644 index 00000000..4e8c7b52 --- /dev/null +++ b/src2/components/elements/LineDivider.js @@ -0,0 +1,7 @@ +const LineDivider = () => { + return ( +
+ ); +}; + +export default LineDivider; \ No newline at end of file diff --git a/src2/components/elements/Link.js b/src2/components/elements/Link.js new file mode 100644 index 00000000..065b5c9e --- /dev/null +++ b/src2/components/elements/Link.js @@ -0,0 +1,13 @@ +import NextLink from "next/link"; + +const Link = ({ children, ...props }) => { + return ( + + {children} + + ) +} + +Link.defaultProps = NextLink.defaultProps + +export default Link \ No newline at end of file diff --git a/src2/components/elements/Pagination.js b/src2/components/elements/Pagination.js new file mode 100644 index 00000000..ff2a8462 --- /dev/null +++ b/src2/components/elements/Pagination.js @@ -0,0 +1,58 @@ +import Link from "./Link"; + +export default function Pagination({ pageCount, currentPage, url }) { + let firstPage = false; + let lastPage = false; + let dotsPrevPage = false; + let dotsNextPage = false; + let urlParameterPrefix = url.includes('?') ? '&' : '?'; + + return pageCount > 1 && ( +
+ {Array.from(Array(pageCount)).map((v, i) => { + let page = i + 1; + let rangePrevPage = currentPage - 2; + let rangeNextPage = currentPage + 2; + let PageComponent = {page}; + let DotsComponent =
...
; + + if (pageCount == 7) { + return PageComponent; + } + + if (currentPage == 1) rangeNextPage += 3; + if (currentPage == 2) rangeNextPage += 2; + if (currentPage == 3) rangeNextPage += 1; + if (currentPage == 4) rangePrevPage -= 1; + if (currentPage == pageCount) rangePrevPage -= 3; + if (currentPage == pageCount - 1) rangePrevPage -= 2; + if (currentPage == pageCount - 2) rangePrevPage -= 1; + if (currentPage == pageCount - 3) rangeNextPage += 1; + + if (page > rangePrevPage && page < rangeNextPage) { + return PageComponent; + } + + if (page == 1 && rangePrevPage >= 1 && !firstPage) { + firstPage = true; + return PageComponent; + } + + if (page == pageCount && rangeNextPage <= pageCount && !lastPage) { + lastPage = true; + return PageComponent; + } + + if (page > currentPage && (pageCount - currentPage) > 1 && !dotsNextPage) { + dotsNextPage = true; + return DotsComponent; + } + + if (page < currentPage && (currentPage - 1) > 1 && !dotsPrevPage) { + dotsPrevPage = true; + return DotsComponent; + } + })} +
+ ) +} \ No newline at end of file diff --git a/src2/components/elements/ProgressBar.js b/src2/components/elements/ProgressBar.js new file mode 100644 index 00000000..0adedcdf --- /dev/null +++ b/src2/components/elements/ProgressBar.js @@ -0,0 +1,25 @@ +import { Fragment } from "react"; + +const ProgressBar = ({ current, labels }) => { + return ( +
+ {labels.map((label, index) => ( + +
+
+ { index + 1 } +
+

{ label }

+
+ { index < (labels.length - 1) && ( +
+
+
+ ) } +
+ ))} +
+ ) +} + +export default ProgressBar; \ No newline at end of file diff --git a/src2/components/elements/Skeleton.js b/src2/components/elements/Skeleton.js new file mode 100644 index 00000000..fbdbc245 --- /dev/null +++ b/src2/components/elements/Skeleton.js @@ -0,0 +1,48 @@ +import ImagePlaceholderIcon from "../../icons/image-placeholder.svg"; + +const SkeletonList = ({ number }) => ( +
+ { Array.from(Array(number), (e, i) => ( +
+
+
+
+
+
+
+ )) } + Loading... +
+); + +const SkeletonProduct = () => ( +
+
+
+ +
+
+
+
+
+
+ Loading... +
+
+
+ +
+
+
+
+
+
+ Loading... +
+
+); + +export { + SkeletonList, + SkeletonProduct +}; \ No newline at end of file diff --git a/src2/components/elements/Spinner.js b/src2/components/elements/Spinner.js new file mode 100644 index 00000000..21006ecd --- /dev/null +++ b/src2/components/elements/Spinner.js @@ -0,0 +1,13 @@ +const Spinner = ({ className }) => { + return ( +
+ + Loading... +
+ ) +} + +export default Spinner; \ No newline at end of file -- cgit v1.2.3