redux-toolkit -> redux 마이그레이션 및 TAxios 로직 수정
This commit is contained in:
@@ -1,43 +1,40 @@
|
||||
import React, { useCallback, useEffect, useState, useRef } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import TInput, { KINDS, ICONS } from "../../components/TInput/TInput";
|
||||
import TPanel from "../../components/TPanel/TPanel";
|
||||
import TButton from "../../components/TButton/TButton";
|
||||
import { $L } from "../../utils/helperMethods";
|
||||
import css from "./SearchPanel.module.less";
|
||||
import TIconButton, { ICON_TYPES, SIZES } from "../../components/TIconButton/TIconButton";
|
||||
import classNames from "classnames";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||
import Spotlight from "@enact/spotlight";
|
||||
|
||||
import { changeAppStatus } from "../../features/common/commonSlice";
|
||||
import { getSearch } from "../../features/search/searchSlice";
|
||||
|
||||
import SearchNoDataImage from "../../../assets/searchpanel/img-search-nodata.png";
|
||||
import TGrid from "../../components/TGrid/TGrid";
|
||||
import TItemCard from "../../components/TItemCard/TItemCard";
|
||||
import SectionTitle from "../../components/SectionTitle/SectionTitle";
|
||||
|
||||
const Container = SpotlightContainerDecorator({ enterTo: "last-focused" }, "div");
|
||||
import { getSearch, resetSearch } from "../../actions/searchActions";
|
||||
import TBody from "../../components/TBody/TBody";
|
||||
import TInput, { ICONS, KINDS } from "../../components/TInput/TInput";
|
||||
import TPanel from "../../components/TPanel/TPanel";
|
||||
import NoSearchResults from "./NoSearchResults/NoSearchResults";
|
||||
import RecommendedKeywords from "./RecommendedKeywords/RecommendedKeywords";
|
||||
import css from "./SearchPanel.module.less";
|
||||
import SearchResults from "./SearchResults/SearchResults";
|
||||
|
||||
const ITEMS_PER_PAGE = 9;
|
||||
|
||||
export default function SearchPanel() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { showLoadingPanel } = useSelector((state) => state.common.appStatus);
|
||||
const recommandedKeywords = useSelector(
|
||||
(state) => state.myPage.recommandedKeywordData.data?.keywords
|
||||
);
|
||||
const searchDatas = useSelector((state) => state.search.searchDatas.data?.result.results);
|
||||
const bestSellerDatas = useSelector((state) => state.product.bestSellerData.bestSeller);
|
||||
const searchDatas = useSelector(
|
||||
(state) => state.search.searchDatas.data?.result.results
|
||||
);
|
||||
const searchPerformed = useSelector((state) => state.search.searchPerformed);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [paginatedKeywords, setPaginatedKeywords] = useState([]);
|
||||
const [pageChanged, setPageChanged] = useState(false);
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [searchPerformed, setSearchPerformed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(resetSearch());
|
||||
}, [dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (recommandedKeywords) {
|
||||
@@ -66,17 +63,10 @@ export default function SearchPanel() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const performSearch = useCallback(
|
||||
async (query) => {
|
||||
if (!query || query.trim() === "") {
|
||||
setSearchPerformed(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setSearchPerformed(true);
|
||||
|
||||
try {
|
||||
await dispatch(
|
||||
const handleSearchSubmit = useCallback(
|
||||
(query) => {
|
||||
if (query.trim()) {
|
||||
dispatch(
|
||||
getSearch({
|
||||
service: "com.lgshop.app",
|
||||
query: query,
|
||||
@@ -84,23 +74,12 @@ export default function SearchPanel() {
|
||||
maxResults: 10,
|
||||
domain: "theme,show,item",
|
||||
})
|
||||
).unwrap();
|
||||
} catch (error) {
|
||||
console.error("Search request failed: ", error);
|
||||
);
|
||||
} else {
|
||||
dispatch(resetSearch());
|
||||
}
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const handleSearchSubmit = useCallback(() => {
|
||||
performSearch(searchQuery);
|
||||
}, [searchQuery, dispatch]);
|
||||
|
||||
const handleKeywordSearch = useCallback(
|
||||
(keyword) => {
|
||||
performSearch(keyword);
|
||||
},
|
||||
[performSearch]
|
||||
[dispatch, searchQuery]
|
||||
);
|
||||
|
||||
const handleNext = useCallback(() => {
|
||||
@@ -114,86 +93,38 @@ export default function SearchPanel() {
|
||||
}, [currentPage]);
|
||||
|
||||
const hasPrevPage = currentPage > 1;
|
||||
const hasNextPage = currentPage * ITEMS_PER_PAGE < recommandedKeywords?.length;
|
||||
const hasNextPage =
|
||||
currentPage * ITEMS_PER_PAGE < recommandedKeywords?.length;
|
||||
|
||||
const renderContents = () => {
|
||||
if (searchPerformed) {
|
||||
if (searchDatas && searchDatas.length > 0) {
|
||||
return <div>data!!</div>;
|
||||
} else {
|
||||
return (
|
||||
<Container className={css.noDataWrap}>
|
||||
<div className={css.noDataResult}>
|
||||
<img src={SearchNoDataImage} alt="No Datas" />
|
||||
<p>{$L("SORRY, NO RESULTS MATCHING YOUR SEARCH")}</p>
|
||||
</div>
|
||||
<div className={css.bestSellerWrap}>
|
||||
<SectionTitle title={$L(`BEST SELLER`)} />
|
||||
<TGrid>
|
||||
{bestSellerDatas &&
|
||||
bestSellerDatas
|
||||
.slice(0, 5)
|
||||
.map((bestSeller) => (
|
||||
<TItemCard
|
||||
key={bestSeller.rankOrd}
|
||||
imageSource={bestSeller.imgUrl}
|
||||
imageAlt={bestSeller.prdtNm}
|
||||
productName={bestSeller.prdtNm}
|
||||
priceInfo={bestSeller.priceInfo}
|
||||
rank={bestSeller.rankOrd}
|
||||
isBestSeller
|
||||
/>
|
||||
))}
|
||||
</TGrid>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<div className={css.keywordWrap}>
|
||||
{hasPrevPage && (
|
||||
<TIconButton
|
||||
iconType={ICON_TYPES.leftArrow}
|
||||
className={classNames(css.arrow, css.arrowLeft)}
|
||||
onClick={handlePrev}
|
||||
/>
|
||||
)}
|
||||
<Container className={css.keywordsGrid}>
|
||||
{paginatedKeywords.map((keyword, index) => (
|
||||
<TButton
|
||||
key={index}
|
||||
spotlightId={index === 0 ? "first-keyword-button" : undefined}
|
||||
className={classNames(css.keywordBox)}
|
||||
onClick={() => handleKeywordSearch(keyword.keywd)}
|
||||
>
|
||||
{keyword.keywd}
|
||||
</TButton>
|
||||
))}
|
||||
</Container>
|
||||
{hasNextPage && (
|
||||
<TIconButton
|
||||
iconType={ICON_TYPES.rightArrow}
|
||||
className={classNames(css.arrow, css.arrowRight)}
|
||||
onClick={handleNext}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<TPanel className={css.panel}>
|
||||
<TInput
|
||||
className={css.input}
|
||||
autoFocus
|
||||
kind={KINDS.withIcon}
|
||||
icon={ICONS.search}
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
onIconClick={handleSearchSubmit}
|
||||
/>
|
||||
{renderContents()}
|
||||
<TPanel className={css.container}>
|
||||
<TBody className={css.tBody}>
|
||||
<TInput
|
||||
className={css.input}
|
||||
autoFocus
|
||||
kind={KINDS.withIcon}
|
||||
icon={ICONS.search}
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
onIconClick={() => handleSearchSubmit(searchQuery)}
|
||||
/>
|
||||
{searchPerformed ? (
|
||||
searchDatas && searchDatas.length > 0 ? (
|
||||
<SearchResults contents={searchDatas} />
|
||||
) : (
|
||||
<NoSearchResults />
|
||||
)
|
||||
) : (
|
||||
<RecommendedKeywords
|
||||
keywords={paginatedKeywords}
|
||||
onPrev={handlePrev}
|
||||
onNext={handleNext}
|
||||
hasPrevPage={hasPrevPage}
|
||||
hasNextPage={hasNextPage}
|
||||
handleSearchSubmit={handleSearchSubmit}
|
||||
/>
|
||||
)}
|
||||
</TBody>
|
||||
</TPanel>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user