continuous search logic

This commit is contained in:
yonghyon
2024-05-03 16:42:07 +09:00
parent fc56fe30a1
commit 818b835796
6 changed files with 63 additions and 38 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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} />

View File

@@ -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}>

View File

@@ -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>

View File

@@ -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>
</>