summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/Filter.js83
-rw-r--r--src/components/Header.js2
-rw-r--r--src/pages/api/shop/search.js6
-rw-r--r--src/pages/shop/brands.js15
-rw-r--r--src/pages/shop/search.js80
5 files changed, 119 insertions, 67 deletions
diff --git a/src/components/Filter.js b/src/components/Filter.js
index cb8fd626..a07beff3 100644
--- a/src/components/Filter.js
+++ b/src/components/Filter.js
@@ -1,28 +1,78 @@
+import { useRouter } from "next/router";
+import { useEffect, useState } from "react";
import CloseIcon from "../icons/close.svg";
const Filter = ({
- selectedBrand,
- onChangeBrand,
- selectedCategory,
- onChangeCategory,
- brands,
- categories,
- isActiveFilter,
+ isActive,
closeFilter,
- onSubmit
+ defaultRoute,
+ defaultPriceFrom,
+ defaultPriceTo,
+ defaultCategory,
+ defaultBrand,
+ searchResults
}) => {
+ const router = useRouter();
+
+ const [priceFrom, setPriceFrom] = useState(defaultPriceFrom);
+ const [priceTo, setPriceTo] = useState(defaultPriceTo);
+ const [selectedCategory, setSelectedCategory] = useState(defaultCategory);
+ const [selectedBrand, setSelectedBrand] = useState(defaultBrand);
+ const [categories, setCategories] = useState([]);
+ const [brands, setBrands] = useState([]);
+
+ const filterRoute = () => {
+ let filterRoute = defaultRoute;
+ if (selectedBrand) filterRoute += `&brand=${selectedBrand}`;
+ if (selectedCategory) filterRoute += `&category=${selectedCategory}`;
+ if (priceFrom > 0) filterRoute += `&price_from=${priceFrom}`;
+ if (priceTo > 0) filterRoute += `&price_to=${priceTo}`;
+ return 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(0);
+ setPriceTo(0);
+ }
+
return (
- <div className={`fixed w-full z-[60] py-8 px-4 ring ring-gray-300 bg-white rounded-t-3xl idt-transition ${isActiveFilter ? 'bottom-0' : 'bottom-[-100%]'}`}>
+ <div className={`fixed w-full z-[60] py-8 px-4 ring ring-gray-300 bg-white rounded-t-3xl idt-transition ${isActive ? 'bottom-0' : 'bottom-[-100%]'}`}>
<div className="flex justify-between items-center mb-5">
<h2 className="text-xl font-semibold">Filter Produk</h2>
<button onClick={closeFilter}>
<CloseIcon className="w-7" />
</button>
</div>
- <form className="flex flex-col gap-y-4" onSubmit={onSubmit}>
+ <form className="flex flex-col gap-y-4" onSubmit={submit}>
<div>
<label>Kategori</label>
- <select className="form-input mt-2" value={selectedCategory} onChange={onChangeCategory}>
+ <select className="form-input mt-2" value={selectedCategory} onChange={(e) => setSelectedCategory(e.target.value)}>
<option value="">Pilih kategori...</option>
{categories?.map((category, index) => (
<option key={index} value={category}>{category}</option>
@@ -31,7 +81,7 @@ const Filter = ({
</div>
<div>
<label>Brand</label>
- <select className="form-input mt-2" value={selectedBrand} onChange={onChangeBrand}>
+ <select className="form-input mt-2" value={selectedBrand} onChange={(e) => setSelectedBrand(e.target.value)}>
<option value="">Pilih brand...</option>
{brands?.map((brand, index) => (
<option key={index} value={brand}>{brand}</option>
@@ -41,14 +91,19 @@ const Filter = ({
<div>
<label>Harga</label>
<div className="flex gap-x-4 mt-2 items-center">
- <input className="form-input"/>
+ <input className="form-input" value={priceFrom} onChange={(e) => setPriceFrom(e.target.value)}/>
<span>-</span>
- <input className="form-input"/>
+ <input className="form-input" value={priceTo} onChange={(e) => setPriceTo(e.target.value)}/>
</div>
</div>
<button type="submit" className="btn-yellow font-semibold mt-4 w-full">
Terapkan Filter
</button>
+ {selectedBrand || selectedCategory || priceFrom > 0 || priceTo > 0 ? (
+ <button type="button" className="btn-light font-semibold w-full" onClick={reset}>
+ Reset Filter
+ </button>
+ ) : ''}
</form>
</div>
)
diff --git a/src/components/Header.js b/src/components/Header.js
index f5eb22f4..2a33df63 100644
--- a/src/components/Header.js
+++ b/src/components/Header.js
@@ -108,7 +108,7 @@ export default function Header({ title }) {
name="q"
onChange={(e) => setSearchQuery(e.target.value)}
value={searchQuery}
- className="form-input rounded-r-none border-r-0"
+ className="form-input rounded-r-none border-r-0 focus:ring-0"
placeholder="Ketikan nama, merek, part number"
/>
<button
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index 3f13f56c..9cd3d4ba 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -43,11 +43,12 @@ export default async function handler(req, res) {
page = 1,
brand = '',
category = '',
+ price_from = 0,
+ price_to = 0
} = req.query;
let limit = 30;
let offset = (page - 1) * limit;
-
let parameter = [
`facet.query=${q}`,
'facet=true',
@@ -58,7 +59,8 @@ export default async function handler(req, res) {
'facet.field=category_name_str',
`start=${offset}`,
`rows=${limit}`,
- 'sort=product_rating desc'
+ 'sort=product_rating desc',
+ `fq=price_discount:[${price_from == 0 ? '*' : price_from} TO ${price_to == 0 ? '*' : price_to}]`
];
if (brand) parameter.push(`fq=brand:${brand}`);
diff --git a/src/pages/shop/brands.js b/src/pages/shop/brands.js
index 8a7b7684..5d93bf4b 100644
--- a/src/pages/shop/brands.js
+++ b/src/pages/shop/brands.js
@@ -5,7 +5,7 @@ import "react-lazy-load-image-component/src/effects/blur.css";
import Link from "../../components/Link";
import { createSlug } from "../../helpers/slug";
import InfiniteScroll from "react-infinite-scroll-component";
-import { useCallback, useEffect, useState } from "react";
+import { useEffect, useState } from "react";
import Spinner from "../../components/Spinner";
import Layout from "../../components/Layout";
@@ -22,12 +22,13 @@ export default function Brands({ initialManufactures }) {
const alpha = Array.from(Array(26)).map((e, i) => i + 65);
const alphabets = alpha.map((x) => String.fromCharCode(x));
- const getMoreManufactures = useCallback(async () => {
+ const getMoreManufactures = async () => {
const name = manufactureStartwith != '' ? `${manufactureStartwith}%` : '';
+ console.log(manufactures, manufactures.length);
const result = await apiOdoo('GET', `/api/v1/manufacture?limit=30&offset=${manufactures.length}&name=${name}`);
setHasMoreManufacture(manufactures.length + 30 < result.manufacture_total)
setManufactures((manufactures) => [...manufactures, ...result.manufactures]);
- }, [manufactureStartwith]);
+ };
const filterManufactureStartWith = (character) => {
setManufactures([]);
@@ -40,7 +41,7 @@ export default function Brands({ initialManufactures }) {
useEffect(() => {
getMoreManufactures();
- }, [getMoreManufactures]);
+ }, [manufactureStartwith]);
return (
<>
@@ -48,9 +49,9 @@ export default function Brands({ initialManufactures }) {
<Layout>
<div className="p-4">
<h1>Semua Brand di Indoteknik</h1>
- <div className="flex overflow-x-auto gap-x-4 py-2">
+ <div className="flex overflow-x-auto gap-x-2 py-2">
{alphabets.map((alphabet, index) => (
- <button key={index} className={"p-2 py-1 border bg-white border-gray-300 rounded" + (manufactureStartwith == alphabet ? ' bg-yellow-900 border-yellow-900 ' : '')} onClick={() => filterManufactureStartWith(alphabet)}>
+ <button key={index} className={"p-2 py-1 border bg-white border-gray-300 rounded w-10 flex-shrink-0" + (manufactureStartwith == alphabet ? ' bg-yellow-900 border-yellow-900 ' : '')} onClick={() => filterManufactureStartWith(alphabet)}>
{alphabet}
</button>
))}
@@ -59,7 +60,7 @@ export default function Brands({ initialManufactures }) {
dataLength={manufactures.length}
next={getMoreManufactures}
hasMore={hasMoreManufacture}
- className="grid grid-cols-3 gap-4 mt-6 !overflow-x-hidden"
+ className="grid grid-cols-4 gap-4 mt-6 !overflow-x-hidden"
loader={
<div className="flex justify-center items-center border border-gray-300 p-2 rounded h-14">
<Spinner className="w-6 h-6 text-gray-600 fill-gray-900"/>
diff --git a/src/pages/shop/search.js b/src/pages/shop/search.js
index f41adf3e..29c5b106 100644
--- a/src/pages/shop/search.js
+++ b/src/pages/shop/search.js
@@ -4,18 +4,33 @@ import Layout from "../../components/Layout";
import Pagination from "../../components/Pagination";
import ProductCard from "../../components/ProductCard";
import FilterIcon from "../../icons/filter.svg";
-import { useEffect, useState } from "react";
+import { useState } from "react";
import Filter from "../../components/Filter";
import { useRouter } from "next/router";
export async function getServerSideProps(context) {
- const { q, page = 1, brand = '', category = '' } = context.query;
- let searchResults = await axios(`${process.env.SELF_HOST}/api/shop/search?q=${q}&page=${page}&brand=${brand}&category=${category}`);
+ const {
+ q,
+ page = 1,
+ brand = '',
+ category = '',
+ price_from = '0',
+ price_to = '0'
+ } = context.query;
+
+ let urlParameter = [
+ `page=${page}`,
+ `brand=${brand}`,
+ `category=${category}`,
+ `price_from=${price_from}`,
+ `price_to=${price_to}`,
+ ].join('&');
+ let searchResults = await axios(`${process.env.SELF_HOST}/api/shop/search?q=${q}&${urlParameter}`);
searchResults = searchResults.data;
- return { props: { searchResults, q, page, brand, category } };
+ return { props: { searchResults, q, page, brand, category, price_from, price_to } };
}
-export default function ShopSearch({ searchResults, q, page, brand, category }) {
+export default function ShopSearch({ searchResults, q, page, brand, category, price_from, price_to }) {
const router = useRouter();
const pageCount = Math.ceil(searchResults.response.numFound / searchResults.responseHeader.params.rows);
@@ -23,51 +38,30 @@ export default function ShopSearch({ searchResults, q, page, brand, category })
const productRows = searchResults.responseHeader.params.rows;
const productFound = searchResults.response.numFound;
+ // Variable for <Filter/> props state
const [activeFilter, setActiveFilter] = useState(false);
- const [selectedCategory, setSelectedCategory] = useState(category);
- const [selectedBrand, setSelectedBrand] = useState(brand);
- const [categories, setCategories] = useState([]);
- const [brands, setBrands] = useState([]);
- const filterSubmit = (e) => {
- e.preventDefault();
- setActiveFilter(false);
- let filterRoute = `/shop/search?q=${q}`;
- if (selectedBrand) filterRoute += `&brand=${selectedBrand}`;
- if (selectedCategory) filterRoute += `&category=${selectedCategory}`;
- router.push(filterRoute, undefined, { scroll: false });
+ const route = () => {
+ let route = `/shop/search?q=${q}`;
+ if (brand) route += `&brand=${brand}`;
+ if (category) route += `&category=${category}`;
+ if (price_from > 0) route += `&price_from=${price_from}`;
+ if (price_to > 0) route += `&price_to=${price_to}`;
+ return route;
}
- 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]);
return (
<>
<Header title={`Jual ${q} - Indoteknik`} />
<Filter
- selectedBrand={selectedBrand}
- onChangeBrand={(e) => setSelectedBrand(e.target.value)}
- selectedCategory={selectedCategory}
- onChangeCategory={(e) => setSelectedCategory(e.target.value)}
- brands={brands}
- categories={categories}
- isActiveFilter={activeFilter}
- closeFilter={() => setActiveFilter(false)}
- onSubmit={filterSubmit}
+ defaultRoute={`/shop/search?q=${q}`}
+ isActive={activeFilter}
+ closeFilter={() => setActiveFilter(false)}
+ defaultPriceFrom={price_from}
+ defaultPriceTo={price_to}
+ defaultBrand={brand}
+ defaultCategory={category}
+ searchResults={searchResults}
/>
<Layout>
<div className="p-4">
@@ -99,7 +93,7 @@ export default function ShopSearch({ searchResults, q, page, brand, category })
</div>
<div className="mt-4">
- <Pagination pageCount={pageCount} currentPage={parseInt(page)} url={`/shop/search?q=${q}`} />
+ <Pagination pageCount={pageCount} currentPage={parseInt(page)} url={route()} />
</div>
</div>
</Layout>