search result

This commit is contained in:
VividTruthKeeper 2023-02-20 16:29:59 +05:00
parent 4b8a42f2a1
commit cd0594f25b
10 changed files with 166 additions and 4 deletions

View File

@ -15,6 +15,7 @@ import "./styles/style.scss";
import Main from "./pages/Main";
import NewsArticle from "./pages/NewsArticle";
import Category from "./pages/Category";
import SearchResult from "./pages/SearchResult";
// Components
import Header from "./components/header/Header";
@ -31,6 +32,7 @@ const App = () => {
<Route path="/" element={<Main />} />
<Route path="/category/:category" element={<Category />} />
<Route path="/news/:id" element={<NewsArticle />} />
<Route path="/search/:word" element={<SearchResult />} />
</Routes>
</AnimatePresence>
<Footer />

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.999 22L19.999 20M11.499 21C12.7466 21 13.9819 20.7543 15.1345 20.2769C16.2871 19.7994 17.3344 19.0997 18.2165 18.2175C19.0987 17.3354 19.7985 16.2881 20.2759 15.1355C20.7533 13.9829 20.999 12.7476 20.999 11.5C20.999 10.2524 20.7533 9.0171 20.2759 7.86451C19.7985 6.71191 19.0987 5.66464 18.2165 4.78249C17.3344 3.90033 16.2871 3.20056 15.1345 2.72314C13.9819 2.24572 12.7466 2 11.499 2C8.97947 2 6.56311 3.00089 4.78151 4.78249C2.99991 6.56408 1.99902 8.98044 1.99902 11.5C1.99902 14.0196 2.99991 16.4359 4.78151 18.2175C6.56311 19.9991 8.97947 21 11.499 21V21Z" stroke="#272727" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 764 B

View File

@ -0,0 +1,52 @@
// Modules
import { v4 as uuidv4 } from "uuid";
// Components
import News from "../news/News";
import Loader from "./Loader";
// Types
import { IPostsData } from "../../types/data.types";
interface IProps {
data: IPostsData[];
word: string | undefined;
}
const CustomNewsScroll = ({ data, word }: IProps) => {
return (
<div className="news-scroll">
<div className="news-scroll-wrapper">
<div className="news-scroll-inner">
{data.length > 0 ? (
data[0].id > -1 ? (
data.map((dataEl) => {
return (
<News
key={uuidv4()}
id={dataEl.id}
title={dataEl.title}
text={dataEl.excerpt}
date={dataEl.published_at}
categories={dataEl.categories}
img={
dataEl.featured_images[0]
? dataEl.featured_images[0].path
: ""
}
/>
);
})
) : (
<Loader />
)
) : (
<p className="scroll-empty">Нет новостей для "{word || ""}" </p>
)}
</div>
</div>
</div>
);
};
export default CustomNewsScroll;

View File

@ -2,6 +2,7 @@
import { Dispatch, SetStateAction } from "react";
import { motion } from "framer-motion";
import { useSelector, useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
// Animations
import {
@ -32,12 +33,15 @@ const Search = ({ isSmall, isInputFocused, setIsInputFocused }: IProps) => {
(state) => state.search.value
);
const navigate = useNavigate();
return (
<motion.form
className="search"
onSubmit={(event: React.FormEvent<HTMLFormElement>) =>
event.preventDefault()
}
onSubmit={(event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
navigate(`/search/${inputValue}`);
}}
variants={searchMobileMotion}
initial={isSmall ? "borderRest" : {}}
animate={isSmall ? (isInputFocused ? "borderActive" : "borderRest") : {}}
@ -53,6 +57,7 @@ const Search = ({ isSmall, isInputFocused, setIsInputFocused }: IProps) => {
}}
onBlur={() => {
setIsInputFocused(false);
onInputChange("");
}}
/>
<motion.div

View File

@ -0,0 +1,63 @@
// Modules
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { Api } from "../api/Api";
import { useSelector, useDispatch } from "react-redux";
import { IPostData, RootState } from "../types/store.types";
// Icons
import { ReactComponent as LoopBlack } from "../assets/icons/loop-black.svg";
import { IurlParamAdder } from "../types/api.types";
import { setNewsScroll } from "../actions/setData";
// Components
import CustomNewsScroll from "../components/global/CustomNewsScroll";
import { IPostsData } from "../types/data.types";
const SearchResult = () => {
const { word } = useParams();
const [params, setParams] = useState<IurlParamAdder[]>([
{
name: "s",
value: word || "",
},
{
name: "count",
value: 10,
},
{
name: "page",
value: 1,
},
]);
const api = new Api("/post", params);
const language = api.language;
const [lastLanguage, setLastLanguage] = useState(language);
// redux
const data = useSelector<RootState, RootState["searchData"]["data"]>(
(state) => state.searchData.data
);
const dispatch = useDispatch();
useEffect(() => {
api.get(data, (data: IPostsData[]) => dispatch(setNewsScroll(data)));
}, [params]);
return (
<main className="sresult">
<div className="container">
<div className="sresult-inner">
<div className="sresult-title">
<LoopBlack />
<h1>Результаты по поиску "{word}"</h1>
</div>
<div className="sresult-content">
<CustomNewsScroll data={data as any} word={word} />
</div>
</div>
</div>
</main>
);
};
export default SearchResult;

View File

@ -127,3 +127,17 @@ export const postReducer = (
}
}
};
export const searchDataReducer = (
state: IPostData = postInitialState,
action: IPostDataAction
) => {
switch (action.type) {
case "SET_POST": {
return { ...state, data: action.payload };
}
default: {
return state;
}
}
};

View File

@ -4,7 +4,11 @@ import { combineReducers, configureStore } from "@reduxjs/toolkit";
// Reducers
import { activeLinkReducer } from "../reducers/activeLink.reducer";
import { languageReducer } from "../reducers/language.reducer";
import { newsScrollReducer, postReducer } from "../reducers/dataReducer";
import {
newsScrollReducer,
postReducer,
searchDataReducer,
} from "../reducers/dataReducer";
import { searchReducer } from "../reducers/searchReducer";
export const allReducers = combineReducers({
@ -13,6 +17,7 @@ export const allReducers = combineReducers({
newsScroll: newsScrollReducer,
post: postReducer,
search: searchReducer,
searchData: searchDataReducer,
});
export const functionalityStore = configureStore({

View File

@ -57,6 +57,7 @@
span {
width: fit-content;
white-space: nowrap;
}
}
}

View File

@ -0,0 +1,16 @@
.sresult-inner {
display: flex;
flex-direction: column;
gap: 5.6rem;
padding: 5.6rem 0;
}
.sresult-title {
display: flex;
align-items: center;
gap: 2.4rem;
h1 {
font-size: 2.4rem;
}
}

View File

@ -14,3 +14,4 @@
@import "./category";
@import "./calendar";
@import "./loader";
@import "./search-result";