diff --git a/src/components/inputs/SearchInput.tsx b/src/components/inputs/SearchInput.tsx index d38f1ec0..cef40b5e 100644 --- a/src/components/inputs/SearchInput.tsx +++ b/src/components/inputs/SearchInput.tsx @@ -1,23 +1,29 @@ /* eslint-disable */ -import React from "react"; +import React, { useState } from "react"; import { FiSearch } from "react-icons/fi"; import "../../styles/SearchInput.scss"; - +import { useNavigate } from "react-router-dom"; interface SearchInputProps { className: string; placeholder?: string; } - function SearchInput({ className, placeholder }: SearchInputProps) { + const [search,setSearch] = useState('') +const navigate = useNavigate() return ( + <>
- - + setSearch(e.target.value)}/> +
+
+
+ + ); } diff --git a/src/pages/Search.tsx b/src/pages/Search.tsx new file mode 100644 index 00000000..3db2480f --- /dev/null +++ b/src/pages/Search.tsx @@ -0,0 +1,42 @@ +/* eslint-disable */ +import React, { useEffect, useState } from 'react'; +import { useAppDispatch, useAppSelector } from '../store/store'; +import { searchProduct, selectSearchResults, selectSearchError } from '../store/features/ProductSlice'; +import { useLocation } from 'react-router-dom'; + +const SearchBar: React.FC = () => { + const location = useLocation() + const params = new URLSearchParams(location.search); + const name = params.get("name") + const category = params.get("category") + const maxPrice = params.get("maxPrice") + const minPrice = params.get("minPrice") + + const dispatch = useAppDispatch(); + const searchResults = useAppSelector(selectSearchResults); + const searchError = useAppSelector(selectSearchError); +useEffect(()=>{ +dispatch(searchProduct({name:name?name:undefined,category:category?category:undefined,maxPrice:maxPrice?parseInt(maxPrice):undefined,minPrice:minPrice?parseInt(minPrice):undefined})) +},[]) + return ( +
+

+ search +

+ {searchError &&

Error: {searchError}

} +
+ {searchResults.length > 0 ? ( + + ) : ( +

No products found.

+ )} +
+
+ ); +}; + +export default SearchBar; diff --git a/src/router.tsx b/src/router.tsx index 18d7297e..7a637c96 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -5,6 +5,7 @@ import { Route, Routes } from "react-router-dom"; import LandingPage from "./pages/LandingPage"; import Login from "./pages/Login"; import NotFound from "./pages/NotFound"; +import Search from "./pages/Search"; const AppRouter: React.FC = () => { return ( @@ -12,7 +13,9 @@ const AppRouter: React.FC = () => { } /> } /> + }/> } /> + ); diff --git a/src/store/features/ProductSlice.tsx b/src/store/features/ProductSlice.tsx new file mode 100644 index 00000000..e3f984ae --- /dev/null +++ b/src/store/features/ProductSlice.tsx @@ -0,0 +1,55 @@ +/* eslint-disable */ +import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import axiosInstance from '../../utils/axios/axiosInstance'; +import { IProducts } from '../../utils/types/Product'; + +const initialState: IProducts = { + nextPage: 0, + currentPage: 0, + previousPage: 0, + limit: 0, + data: [], +}; + +interface SearchCriteria { + name?: string; + category?: string; + minPrice?: number; + maxPrice?: number; +} + +export const searchProduct = createAsyncThunk( + 'searchProduct', + async (criteria) => { + const response = await axiosInstance.get('/api/shop/user-search-products', { + params: criteria, + }); + return response.data; + } +); + +const productSlice = createSlice({ + name: 'product', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(searchProduct.fulfilled, (state, action: PayloadAction) => { + state.nextPage = action.payload.nextPage; + state.currentPage = action.payload.currentPage; + state.previousPage = action.payload.previousPage; + state.limit = action.payload.limit; + state.data = action.payload.data; + state.error = undefined; + }) + .addCase(searchProduct.rejected, (state, action) => { + state.currentPage = -1; + state.error = action.error.message; + }); + }, +}); + +export const selectSearchResults = (state:any) => state.searchProduct.data; +export const selectSearchError = (state:any) => state.searchProduct.error; + +export default productSlice.reducer; diff --git a/src/store/store.ts b/src/store/store.ts index ea36a199..d6dff94a 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -3,10 +3,12 @@ import { configureStore } from "@reduxjs/toolkit"; import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"; import welcomeReducer from "./features/welcomeSlice"; +import productReducer from "./features/ProductSlice"; export const store = configureStore({ reducer: { initialMessage: welcomeReducer, + searchProduct:productReducer }, }); diff --git a/src/utils/axios/axiosInstance.ts b/src/utils/axios/axiosInstance.ts index a3345fd2..227d02e6 100644 --- a/src/utils/axios/axiosInstance.ts +++ b/src/utils/axios/axiosInstance.ts @@ -3,7 +3,7 @@ import axios from "axios"; const axiosInstance = axios.create({ - baseURL: "https://e-commerce-ninjas-platform-backend.onrender.com/", + baseURL: "http://localhost:8000", headers: { "Content-Type": "application/json", }, diff --git a/src/utils/types/Product.d.ts b/src/utils/types/Product.d.ts new file mode 100644 index 00000000..892b1c7c --- /dev/null +++ b/src/utils/types/Product.d.ts @@ -0,0 +1,11 @@ +export interface IProducts { + nextPage:number; + currentPage: number; + previousPage:number; + limit:number; + data:[]; + error?:string +} +export interface IProductsState { + searchProduct: searchProduct; +}