continuous search logic
This commit is contained in:
@@ -5,10 +5,14 @@ import { types } from "./actionTypes";
|
||||
|
||||
// Search 통합검색 (IBS) 데이터 조회 IF-LGSP-090
|
||||
let getSearchKey = null;
|
||||
let lastSearchedParams = {};
|
||||
export const getSearch =
|
||||
(params, startIndex = 1, key) =>
|
||||
(dispatch, getState) => {
|
||||
const { service, query, domain } = params;
|
||||
if(startIndex === 1){
|
||||
lastSearchedParams = params;
|
||||
}
|
||||
const maxResults = SEARCH_DATA_MAX_RESULTS_LIMIT;
|
||||
|
||||
let currentKey = key;
|
||||
@@ -28,26 +32,9 @@ export const getSearch =
|
||||
type: types.GET_SEARCH,
|
||||
payload: response.data,
|
||||
append: true,
|
||||
startIndex: startIndex-1
|
||||
});
|
||||
}
|
||||
|
||||
const stateBeforeLoop = getState();
|
||||
const nextStartIndex = response.data.data.result.results.reduce(
|
||||
(acc, category) => {
|
||||
const { type, total_count } = category;
|
||||
const fetchedCount =
|
||||
stateBeforeLoop.search.searchDatas[type]?.length ||
|
||||
0 + category.docs.length;
|
||||
const remainingData = total_count - fetchedCount;
|
||||
|
||||
return remainingData > 0 ? Math.max(acc, fetchedCount + 1) : acc;
|
||||
},
|
||||
startIndex
|
||||
);
|
||||
|
||||
if (nextStartIndex > startIndex && getSearchKey === currentKey) {
|
||||
dispatch(getSearch(params, nextStartIndex, currentKey));
|
||||
}
|
||||
};
|
||||
|
||||
const onFail = (error) => {
|
||||
@@ -65,6 +52,16 @@ export const getSearch =
|
||||
onFail
|
||||
);
|
||||
};
|
||||
export const continueSearch =(key, startIndex=1) =>
|
||||
(dispatch, getState) => {
|
||||
const searchDatas = getState().search.searchDatas;
|
||||
const totalCount = getState().search.totalCount;
|
||||
if(startIndex<=1 && !searchDatas[key] || searchDatas[key][startIndex-1] || !totalCount[key] || totalCount[key] < startIndex){
|
||||
//ignore search
|
||||
return;
|
||||
}
|
||||
dispatch(getSearch({...lastSearchedParams, domain: key}, startIndex, getSearchKey));
|
||||
};
|
||||
|
||||
export const resetSearch = (status) => {
|
||||
getSearchKey = null;
|
||||
|
||||
@@ -14,12 +14,14 @@ export const searchReducer = (state = initialState, action) => {
|
||||
|
||||
const updatedSearchDatas = action.append ? { ...state.searchDatas } : {};
|
||||
newResults.forEach(({ type, docs }) => {
|
||||
updatedSearchDatas[type] =
|
||||
action.append && updatedSearchDatas[type]
|
||||
? updatedSearchDatas[type].concat(docs)
|
||||
: docs;
|
||||
if(action.append && updatedSearchDatas[type]){
|
||||
for(let i=0; i< docs.length;i++){
|
||||
updatedSearchDatas[type][action.startIndex+i] = docs[i];
|
||||
}
|
||||
}else{
|
||||
updatedSearchDatas[type] = docs;
|
||||
}
|
||||
});
|
||||
|
||||
const updatedTotalCount = action.append ? { ...state.totalCount } : {};
|
||||
newResults.forEach(({ type, total_count }) => {
|
||||
updatedTotalCount[type] = total_count;
|
||||
|
||||
@@ -29,6 +29,7 @@ export default memo(function SearchItemCard({
|
||||
thumbnail,
|
||||
title,
|
||||
contentId,
|
||||
spotlightId,
|
||||
patnrId,
|
||||
prdtId,
|
||||
idx,
|
||||
@@ -110,7 +111,7 @@ export default memo(function SearchItemCard({
|
||||
onClick={(e) => {
|
||||
handleItemClick(e, contentId);
|
||||
}}
|
||||
spotlightId={"search-item-" + contentId.replace(" ", "")}
|
||||
spotlightId={spotlightId}
|
||||
>
|
||||
<div className={css.imageBox}>
|
||||
<img src={thumbnail} alt={title} />
|
||||
|
||||
@@ -24,6 +24,7 @@ export default memo(function SearchShowCard({
|
||||
thumbnail,
|
||||
title,
|
||||
contentId,
|
||||
spotlightId,
|
||||
idx,
|
||||
...rest
|
||||
}) {
|
||||
@@ -81,7 +82,7 @@ export default memo(function SearchShowCard({
|
||||
onClick={(e) => {
|
||||
handleShowClick(e, contentId);
|
||||
}}
|
||||
spotlightId={"search-show-" + contentId.replace(" ", "")}
|
||||
spotlightId={spotlightId}
|
||||
{...rest}
|
||||
>
|
||||
<div className={css.imageBox}>
|
||||
|
||||
@@ -21,6 +21,7 @@ export default memo(function SearchThemeCard({
|
||||
startTime,
|
||||
title,
|
||||
contentId,
|
||||
spotlightId,
|
||||
type,
|
||||
idx,
|
||||
...rest
|
||||
@@ -80,7 +81,7 @@ export default memo(function SearchThemeCard({
|
||||
onClick={(e) => {
|
||||
handleThemeClick(e, contentId);
|
||||
}}
|
||||
spotlightId={"search-theme-" + contentId.replace(" ", "")}
|
||||
spotlightId={spotlightId}
|
||||
{...rest}
|
||||
>
|
||||
<h2 className={css.title}>{title}</h2>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
|
||||
import classNames from "classnames";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { Job } from "@enact/core/util";
|
||||
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||
@@ -12,7 +12,11 @@ import useScrollTo from "../../../hooks/useScrollTo";
|
||||
import SearchItemCard from "./SearchCard/SearchItemCard";
|
||||
import SearchShowCard from "./SearchCard/SearchShowCard";
|
||||
import SearchThemeCard from "./SearchCard/SearchThemeCard";
|
||||
import usePrevious from "../../../hooks/usePrevious";
|
||||
import { SEARCH_DATA_MAX_RESULTS_LIMIT } from "../../../utils/Config";
|
||||
import css from "./SearchResultsType.module.less";
|
||||
import { continueSearch } from "../../../actions/searchActions";
|
||||
|
||||
|
||||
const Container = SpotlightContainerDecorator(
|
||||
{ leaveFor: { right: "" }, enterTo: "last-focused" },
|
||||
@@ -46,11 +50,13 @@ export default function SearchResultsType({
|
||||
category,
|
||||
idx,
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
const { getScrollTo, scrollLeft } = useScrollTo();
|
||||
const initPerformed = useSelector((state) => state.search.initPerformed);
|
||||
const scrollLeftJob = useRef(new Job((func) => func(), 200));
|
||||
|
||||
const panelInfo = useSelector((state) => state.panels.panels[0]?.panelInfo);
|
||||
const searchAppendJob = useRef(new Job((func) => func(), 1000));
|
||||
const dataRef = usePrevious(data);
|
||||
|
||||
useEffect(() => {
|
||||
if (initPerformed) {
|
||||
@@ -74,8 +80,21 @@ export default function SearchResultsType({
|
||||
return () => scrollLeftJobValue.stop();
|
||||
}, [panelInfo, scrollLeft, idx]);
|
||||
|
||||
const onScroll = useCallback((ev)=>{
|
||||
const {lastVisibleIndex} = ev.moreInfo;
|
||||
if(dataRef.current.length >= SEARCH_DATA_MAX_RESULTS_LIMIT){
|
||||
const nextSearchIndex = (Math.floor(lastVisibleIndex/SEARCH_DATA_MAX_RESULTS_LIMIT)+1)*SEARCH_DATA_MAX_RESULTS_LIMIT+1;
|
||||
if(!dataRef.current[nextSearchIndex]){
|
||||
searchAppendJob.current.throttle(()=>{
|
||||
dispatch(continueSearch(category, nextSearchIndex));
|
||||
});
|
||||
}
|
||||
}
|
||||
},[category, count]);
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ index, ...rest }) => {
|
||||
const targetItem = data[index] ? data[index]: {};
|
||||
switch (category) {
|
||||
case "theme": {
|
||||
const {
|
||||
@@ -87,14 +106,15 @@ export default function SearchResultsType({
|
||||
startTime,
|
||||
title,
|
||||
type,
|
||||
} = data[index];
|
||||
} = targetItem;
|
||||
|
||||
return (
|
||||
<SearchThemeCard
|
||||
key={contentId}
|
||||
key={'theme'+index}
|
||||
title={title}
|
||||
keyword={keyword}
|
||||
contentId={contentId}
|
||||
contentId={contentId ? contentId: ""}
|
||||
spotlightId={'searchThemeItem'+index}
|
||||
type={"theme"}
|
||||
idx={idx}
|
||||
{...rest}
|
||||
@@ -113,15 +133,16 @@ export default function SearchResultsType({
|
||||
startTime,
|
||||
thumbnail,
|
||||
title,
|
||||
} = data[index];
|
||||
} = targetItem;
|
||||
|
||||
return (
|
||||
<SearchShowCard
|
||||
key={contentId}
|
||||
key={"show"+index}
|
||||
liveFlag={liveFlag}
|
||||
thumbnail={thumbnail}
|
||||
title={title}
|
||||
contentId={contentId}
|
||||
contentId={contentId ? contentId: ""}
|
||||
spotlightId={'searchShowItem'+index}
|
||||
idx={idx}
|
||||
{...rest}
|
||||
/>
|
||||
@@ -141,18 +162,19 @@ export default function SearchResultsType({
|
||||
patnrId,
|
||||
prdtId,
|
||||
title,
|
||||
} = data[index];
|
||||
} = targetItem;
|
||||
|
||||
return (
|
||||
<SearchItemCard
|
||||
key={contentId}
|
||||
key={"item"+index}
|
||||
thumbnail={thumbnail}
|
||||
title={title}
|
||||
price={price}
|
||||
patnrId={patnrId}
|
||||
prdtId={prdtId}
|
||||
dcPrice={dcPrice}
|
||||
contentId={contentId}
|
||||
contentId={contentId ? contentId: ""}
|
||||
spotlightId={'searchItem'+index}
|
||||
idx={idx}
|
||||
{...rest}
|
||||
/>
|
||||
@@ -182,13 +204,14 @@ export default function SearchResultsType({
|
||||
key={title}
|
||||
cbScrollTo={getScrollTo}
|
||||
className={css.grid}
|
||||
dataSize={data.length}
|
||||
dataSize={count ? count : 0}
|
||||
renderItem={renderItem}
|
||||
direction="horizontal"
|
||||
itemWidth={itemWidth}
|
||||
itemHeight={itemHeight}
|
||||
spacing={spacing}
|
||||
idx={idx}
|
||||
onScroll={onScroll}
|
||||
/>
|
||||
</Container>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user