SearchPanel 작업 진행 중 - chw
This commit is contained in:
@@ -10,6 +10,7 @@ import { getHomeMenu } from "../features/home/homeSlice";
|
|||||||
import { getOnSaleInfo } from "../features/onSale/onSaleSlice";
|
import { getOnSaleInfo } from "../features/onSale/onSaleSlice";
|
||||||
import MainView from "../views/MainView/MainView";
|
import MainView from "../views/MainView/MainView";
|
||||||
import css from "./App.module.less";
|
import css from "./App.module.less";
|
||||||
|
import { getMyRecommandedKeyword } from "../features/mypage/myPageSlice";
|
||||||
|
|
||||||
function AppBase(props) {
|
function AppBase(props) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -19,6 +20,7 @@ function AppBase(props) {
|
|||||||
dispatch(getHomeMenu());
|
dispatch(getHomeMenu());
|
||||||
dispatch(getOnSaleInfo({ categoryIncFlag: "Y", lgCatCd: "" }));
|
dispatch(getOnSaleInfo({ categoryIncFlag: "Y", lgCatCd: "" }));
|
||||||
dispatch(getBrandList());
|
dispatch(getBrandList());
|
||||||
|
dispatch(getMyRecommandedKeyword());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
return <MainView />;
|
return <MainView />;
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ export const URLS = {
|
|||||||
|
|
||||||
//on-sale controller
|
//on-sale controller
|
||||||
GET_ON_SALE_INFO: "/lgsp/v1/onsale/onsale.lge",
|
GET_ON_SALE_INFO: "/lgsp/v1/onsale/onsale.lge",
|
||||||
|
|
||||||
|
//my-page controller
|
||||||
|
GET_MY_RECOMMANDED_KEYWORD: "/lgsp/v1/mypage/reckeyword.lge",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getUrl = (endStr) => {
|
export const getUrl = (endStr) => {
|
||||||
|
|||||||
37
com.twin.app.shoptime/src/components/TInput/TInput.jsx
Normal file
37
com.twin.app.shoptime/src/components/TInput/TInput.jsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
import css from "./TInput.module.less";
|
||||||
|
import { InputField } from "@enact/sandstone/Input";
|
||||||
|
import { $L } from "../../utils/helperMethods";
|
||||||
|
|
||||||
|
const KINDS = { withIcon: "withIcon" };
|
||||||
|
const ICONS = { search: "search" };
|
||||||
|
const BORDER = { none: "none" };
|
||||||
|
const COLOR = { transparent: "transparent" };
|
||||||
|
|
||||||
|
export default function TInput({
|
||||||
|
kind = "",
|
||||||
|
icon = null,
|
||||||
|
border = null,
|
||||||
|
color = null,
|
||||||
|
className = null,
|
||||||
|
spotlightDisabled,
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<InputField
|
||||||
|
{...rest}
|
||||||
|
className={classNames(
|
||||||
|
css.input,
|
||||||
|
icon && css[icon],
|
||||||
|
css[kind],
|
||||||
|
css[border],
|
||||||
|
css[color],
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
spotlightDisabled={spotlightDisabled}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { KINDS, ICONS, BORDER, COLOR };
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@import "../../style/CommonStyle.module.less";
|
||||||
|
@import "../../style/utils.module.less";
|
||||||
|
|
||||||
|
.input {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
height: 100px !important;
|
||||||
|
padding: 20px 40px 20px 50px !important;
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 5px solid #ccc;
|
||||||
|
background-color: #fff !important;
|
||||||
|
|
||||||
|
&:focus-within,
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 0 2px #fefefe inset;
|
||||||
|
border: 5px solid @PRIMARY_COLOR_RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> input {
|
||||||
|
font-family: @baseFont;
|
||||||
|
color: @COLOR_GRAY07 !important;
|
||||||
|
height: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
com.twin.app.shoptime/src/components/TInput/package.json
Normal file
6
com.twin.app.shoptime/src/components/TInput/package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"main": "TInput.jsx",
|
||||||
|
"styles": [
|
||||||
|
"TInput.module.less"
|
||||||
|
]
|
||||||
|
}
|
||||||
52
com.twin.app.shoptime/src/features/mypage/myPageSlice.js
Normal file
52
com.twin.app.shoptime/src/features/mypage/myPageSlice.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
import { URLS } from "../../api/apiConfig";
|
||||||
|
import { TAxios } from "../../api/TAxios";
|
||||||
|
|
||||||
|
// 추천 Keyword 목록 조회 IF-LGSP-055
|
||||||
|
export const getMyRecommandedKeyword = createAsyncThunk(
|
||||||
|
"myPage/getMyRecommandedKeyword",
|
||||||
|
|
||||||
|
async (_, thunkAPI) => {
|
||||||
|
const onSuccess = (response) => {
|
||||||
|
console.log("getMyRecommandedKeyword onSuccess ", response.data);
|
||||||
|
|
||||||
|
thunkAPI.dispatch(
|
||||||
|
myPageSlice.actions.updateRecommandedKeywordData(response.data)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFail = (error) => {
|
||||||
|
console.error("getMyRecommandedKeyword onFail ", error);
|
||||||
|
};
|
||||||
|
|
||||||
|
TAxios(
|
||||||
|
thunkAPI.dispatch,
|
||||||
|
thunkAPI.getState,
|
||||||
|
"get",
|
||||||
|
URLS.GET_MY_RECOMMANDED_KEYWORD,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
onSuccess,
|
||||||
|
onFail
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
recommandedKeywordData: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const myPageSlice = createSlice({
|
||||||
|
name: "myPage",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
updateRecommandedKeywordData: (state, action) => {
|
||||||
|
state.recommandedKeywordData = action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { updateRecommandedKeywordData } = myPageSlice.actions;
|
||||||
|
|
||||||
|
export default myPageSlice.reducer;
|
||||||
@@ -7,6 +7,7 @@ import deviceReducer from "../features/device/deviceSlice";
|
|||||||
import homeReducer from "../features/home/homeSlice";
|
import homeReducer from "../features/home/homeSlice";
|
||||||
import onSaleReducer from "../features/onSale/onSaleSlice";
|
import onSaleReducer from "../features/onSale/onSaleSlice";
|
||||||
import panelsReducer from "../features/panels/panelsSlice";
|
import panelsReducer from "../features/panels/panelsSlice";
|
||||||
|
import myPageReducer from "../features/mypage/myPageSlice";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
@@ -17,5 +18,6 @@ export const store = configureStore({
|
|||||||
home: homeReducer,
|
home: homeReducer,
|
||||||
onSale: onSaleReducer,
|
onSale: onSaleReducer,
|
||||||
featuredBrands: featuredBrandsReducer,
|
featuredBrands: featuredBrandsReducer,
|
||||||
|
myPage: myPageReducer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,59 @@
|
|||||||
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import TInput from "../../components/TInput/TInput";
|
||||||
import TPanel from "../../components/TPanel/TPanel";
|
import TPanel from "../../components/TPanel/TPanel";
|
||||||
|
import TButton from "../../components/TButton/TButton";
|
||||||
|
import { $L } from "../../utils/helperMethods";
|
||||||
|
import css from "./SearchPanel.module.less";
|
||||||
|
|
||||||
|
const ITEMS_PER_PAGE = 9;
|
||||||
|
|
||||||
export default function SearchPanel() {
|
export default function SearchPanel() {
|
||||||
return <TPanel>Search</TPanel>;
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const recommandedKeywords = useSelector(
|
||||||
|
(state) => state.myPage.recommandedKeywordData.data?.keywords
|
||||||
|
);
|
||||||
|
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const [paginatedKeywords, setPaginatedKeywords] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (recommandedKeywords) {
|
||||||
|
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
|
||||||
|
const endIndex = startIndex + ITEMS_PER_PAGE;
|
||||||
|
|
||||||
|
setPaginatedKeywords(recommandedKeywords.slice(startIndex, endIndex));
|
||||||
|
}
|
||||||
|
}, [recommandedKeywords, currentPage]);
|
||||||
|
|
||||||
|
const handleNext = useCallback(() => {
|
||||||
|
setCurrentPage((prev) => prev + 1);
|
||||||
|
}, [currentPage]);
|
||||||
|
|
||||||
|
const handlePrev = useCallback(() => {
|
||||||
|
setCurrentPage((prev) => (prev > 1 ? prev - 1 : prev));
|
||||||
|
}, [currentPage]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TPanel className={css.panel}>
|
||||||
|
<TInput className={css.input} autoFocus />
|
||||||
|
<div>
|
||||||
|
{paginatedKeywords.map((keyword, index) => (
|
||||||
|
<div key={index}>{keyword.keywd}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TButton onClick={handlePrev} disabled={currentPage === 1}>
|
||||||
|
PREV
|
||||||
|
</TButton>
|
||||||
|
<TButton
|
||||||
|
onClick={handleNext}
|
||||||
|
disabled={currentPage * ITEMS_PER_PAGE >= recommandedKeywords?.length}
|
||||||
|
>
|
||||||
|
NEXT
|
||||||
|
</TButton>
|
||||||
|
</div>
|
||||||
|
</TPanel>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@import "../../style/CommonStyle.module.less";
|
||||||
|
@import "../../style/utils.module.less";
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
background-color: @BG_COLOR_01;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
.flex(@direction: row);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user