redux-toolkit -> redux 마이그레이션 및 TAxios 로직 수정

This commit is contained in:
hyunwoo93.cha
2024-02-01 01:44:12 +09:00
parent a812c70ebe
commit 1c9ce1c5b8
90 changed files with 2228 additions and 1943 deletions

View File

@@ -0,0 +1,2 @@
ES5='true'
DISABLE_NEW_JSX_TRANSFORM='true'

File diff suppressed because it is too large Load Diff

View File

@@ -6,8 +6,8 @@
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {
"serve": "enact serve", "serve": "enact serve",
"pack": "enact pack", "pack": "enact clean && enact pack",
"pack-p": "enact pack -p", "build": "enact pack --production --locales=tv --verbose",
"watch": "enact pack --watch", "watch": "enact pack --watch",
"clean": "enact clean", "clean": "enact clean",
"lint": "enact lint .", "lint": "enact lint .",
@@ -27,9 +27,6 @@
"baseSize": 24 "baseSize": 24
} }
}, },
"eslintConfig": {
"extends": "enact-proxy"
},
"eslintIgnore": [ "eslintIgnore": [
"node_modules/*", "node_modules/*",
"build/*", "build/*",
@@ -42,15 +39,16 @@
"@enact/spotlight": "^3.3.0", "@enact/spotlight": "^3.3.0",
"@enact/ui": "^3.3.0", "@enact/ui": "^3.3.0",
"@enact/webos": "^3.3.0", "@enact/webos": "^3.3.0",
"@reduxjs/toolkit": "^2.0.1", "axios": "^0.21.1",
"axios": "^1.6.5",
"ilib": "^14.3.0", "ilib": "^14.3.0",
"prop-types": "^15.8.1", "prop-types": "^15.6.2",
"react": "^18.2.0", "react": "^16.7.0",
"react-dom": "^18.2.0", "react-dom": "^16.7.0",
"react-redux": "^9.1.0" "react-redux": "^7.2.3",
"redux": "^3.7.2",
"redux-thunk": "^2.3.0"
}, },
"devDependencies": { "browserslist": [
"eslint-config-enact-proxy": "^1.0.7" "chrome 38"
} ]
} }

Binary file not shown.

View File

@@ -4,18 +4,18 @@ import { useDispatch } from "react-redux";
import ThemeDecorator from "@enact/sandstone/ThemeDecorator"; import ThemeDecorator from "@enact/sandstone/ThemeDecorator";
import { getBrandList } from "../features/brand/brandsSlice"; import { getBrandList } from "../actions/brandActions";
import { getAuthenticationCode } from "../features/device/deviceSlice"; import { getAuthenticationCode } from "../actions/deviceActions";
import { import {
getHomeMenu,
getHomeLayout, getHomeLayout,
getHomeMainContents, getHomeMainContents,
getHomeMenu,
getThemeCurationInfo, getThemeCurationInfo,
} from "../features/home/homeSlice"; } from "../actions/homeActions";
import { getMyRecommandedKeyword } from "../features/mypage/myPageSlice"; import { getSubCategory, getTop20Show } from "../actions/mainActions";
import { getOnSaleInfo } from "../features/onSale/onSaleSlice"; import { getMyRecommandedKeyword } from "../actions/myPageActions";
import { getSubCategory, getTop20Show } from "../features/main/mainSlice"; import { getOnSaleInfo } from "../actions/onSaleActions";
import { getBestSeller } from "../features/product/productSlice"; import { getBestSeller } from "../actions/productActions";
import MainView from "../views/MainView/MainView"; import MainView from "../views/MainView/MainView";
import css from "./App.module.less"; import css from "./App.module.less";

View File

@@ -0,0 +1,49 @@
export const types = {
// panel actions
PUSH_PANEL: "PUSH_PANEL",
POP_PANEL: "POP_PANEL",
UPDATE_PANEL: "UPDATE_PANEL",
UPDATE_MODAL_STATUS: "UPDATE_MODAL_STATUS",
RESET_PANELS: "RESET_PANELS",
// device actions
GET_AUTHENTICATION_CODE: "GET_AUTHENTICATION_CODE",
// common actions
CHANGE_APP_STATUS: "CHANGE_APP_STATUS",
// appData actions
ADD_MAIN_INDEX: "ADD_MAIN_INDEX",
// home actions
GET_HOME_TERMS: "GET_HOME_TERMS",
GET_HOME_MENU: "GET_HOME_MENU",
GET_HOME_LAYOUT: "GET_HOME_LAYOUT",
GET_HOME_MAIN_CONTENTS: "GET_HOME_MAIN_CONTENTS",
GET_THEME_CURATION_INFO: "GET_THEME_CURATION_INFO",
// brand actions
GET_BRAND_LIST: "GET_BRAND_LIST",
GET_BRAND_LAYOUT_INFO: "GET_BRAND_LAYOUT_INFO",
GET_BRAND_LIVE_CHANNEL_INFO: "GET_BRAND_LIVE_CHANNEL_INFO",
// main actions
GET_SUB_CATEGORY: "GET_SUB_CATEGORY",
GET_TOP_20_SHOW: "GET_TOP_20_SHOW",
// myPage actions
GET_MY_RECOMMANDED_KEYWORD: "GET_MY_RECOMMANDED_KEYWORD",
// onSale actions
GET_ON_SALE_INFO: "GET_ON_SALE_INFO",
// product actions
GET_BEST_SELLER: "GET_BEST_SELLER",
// search actions
GET_SEARCH: "GET_SEARCH",
RESET_SEARCH: "RESET_SEARCH",
// event actions
GET_WELCOME_EVENT_INFO: "GET_WELCOME_EVENT_INFO",
};

View File

@@ -0,0 +1,6 @@
import { types } from "./actionTypes";
export const addMainIndex = (index) => ({
type: types.ADD_MAIN_INDEX,
payload: index,
});

View File

@@ -0,0 +1,89 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// Featured Brands 정보 조회 IF-LGSP-304
// @@pyh Todo, 기존의 key가 brandList에서 brandInfo로 변경 됨에 따라 함수명 또한 바뀔 수 있음 (문서 확인 후 변경 처리)
export const getBrandList = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("@@ getBrandList onSuccess ", response.data);
dispatch({
type: types.GET_BRAND_LIST,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("@@ getBrandList onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_BRAND_LIST,
{},
{},
onSuccess,
onFail
);
};
// Featured Brands LAYOUT (shelf) 정보 조회 IF-LGSP-305
export const getBrandLayoutInfo = (props) => (dispatch, getState) => {
const { patnrId } = props;
const onSuccess = (response) => {
console.log("@@ getBrandLayoutInfo onSuccess ", response.data);
dispatch({
type: types.GET_BRAND_LAYOUT_INFO,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("@@ getBrandLayoutInfo onFail ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_BRAND_LAYOUT_INFO,
{ patnrId },
{},
onSuccess,
onFail
);
};
// Featured Brands Live 채널 정보 조회 IF-LGSP-306
export const getBrandLiveChannelInfo = (props) => (dispatch, getState) => {
const { patnrId } = props;
const onSuccess = (response) => {
console.log("@@ getBrandLiveChannelInfo onSuccess ", response.data);
dispatch({
type: types.GET_BRAND_LIVE_CHANNEL_INFO,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("@@ getBrandLiveChannelInfo onFail ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_BRAND_LIVE_CHANNEL_INFO,
{ patnrId },
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,6 @@
import { types } from "./actionTypes";
export const changeAppStatus = (status) => ({
type: types.CHANGE_APP_STATUS,
payload: status,
});

View File

@@ -0,0 +1,29 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
export const getAuthenticationCode = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getAuthenticationCode onSuccess: ", response.data);
dispatch({
type: types.GET_AUTHENTICATION_CODE,
payload: response.data.data.accessToken,
});
};
const onFail = (error) => {
console.error("getAuthenticationCode onFail: ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_AUTHENTICATION_CODE,
{},
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,29 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// 이벤트 정보 조회 IF-LGSP-070
export const getWelcomeEventInfo = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getWelcomeEventInfo onSuccess ", response.data);
dispatch({
type: types.GET_WELCOME_EVENT_INFO,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getWelcomeEventInfo onFail ", error);
};
TAxios(
dispatch,
getState,
URLS.GET_WELCOME_EVENT_INFO,
{},
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,140 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// 약관 정보 조회 IF-LGSP-005
export const getHomeTerms = (props) => (dispatch, getState) => {
const { trmsTpCdList, mbrNo } = props;
const onSuccess = (response) => {
console.log("getHomeTerms onSuccess ", response.data);
dispatch({
type: types.GET_HOME_TERMS,
payload: response.data,
});
};
const onFail = (error) => {
console.error("getHomeTerms onFail ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_HOME_TERMS,
{ trmsTpCdList, mbrNo },
{},
onSuccess,
onFail
);
};
// 메뉴 목록 조회 IF-LGSP-044
export const getHomeMenu = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getHomeMenu onSuccess ", response.data);
dispatch({
type: types.GET_HOME_MENU,
payload: response.data,
});
};
const onFail = (error) => {
console.error("getHomeMenu onFail ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_HOME_MENU,
{},
{},
onSuccess,
onFail
);
};
// HOME LAYOUT 정보 조회 IF-LGSP-300
export const getHomeLayout = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getHomeLayout onSuccess", response.data);
dispatch({
type: types.GET_HOME_LAYOUT,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getHomeLayout onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_HOME_LAYOUT,
{},
{},
onSuccess,
onFail
);
};
// HOME Main Contents Banner 정보 조회 IF-LGSP-301
export const getHomeMainContents = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getHomeMainContents onSuccess", response.data);
dispatch({
type: types.GET_HOME_MAIN_CONTENTS,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getHomeMainContents onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_HOME_MAIN_CONTENTS,
{},
{},
onSuccess,
onFail
);
};
// Theme 전시 정보 조회 : IF-LGSP-045
export const getThemeCurationInfo = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getThemeCurationInfo onSuccess", response.data);
dispatch({
type: types.GET_THEME_CURATION_INFO,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getThemeCurationInfo onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_THEME_CURATION_INFO,
{},
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,59 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// 서브카테고리 조회 IF-LGSP-051
export const getSubCategory = (props) => (dispatch, getState) => {
const { lgCatCd, patnrIdList, pageSize, tabType, filterType } = props;
const onSuccess = (response) => {
console.log("getSubCategory onSuccess ", response.data);
dispatch({
type: types.GET_SUB_CATEGORY,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getSubCategory onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_SUB_CATEGORY,
{ lgCatCd, patnrIdList, pageSize, tabType, filterType },
{},
onSuccess,
onFail
);
};
// TOP20 영상 목록 조회 IF-LGSP-069
export const getTop20Show = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getTop20Show onSuccess ", response.data);
dispatch({
type: types.GET_TOP_20_SHOW,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getTop20Show onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_TOP20_SHOW,
{},
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,30 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// 추천 Keyword 목록 조회 IF-LGSP-055
export const getMyRecommandedKeyword = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getMyRecommandedKeyword onSuccess ", response.data);
dispatch({
type: types.GET_MY_RECOMMANDED_KEYWORD,
payload: response.data,
});
};
const onFail = (error) => {
console.error("getMyRecommandedKeyword onFail ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_MY_RECOMMANDED_KEYWORD,
{},
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,32 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// On Sale 조회 IF-LGSP-086
export const getOnSaleInfo = (props) => (dispatch, getState) => {
const { categoryIncFlag, lgCatCd } = props;
const onSuccess = (response) => {
console.log("getOnSaleInfo onSuccess ", response.data);
dispatch({
type: types.GET_ON_SALE_INFO,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getOnSaleInfo onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_ON_SALE_INFO,
{ categoryIncFlag, lgCatCd },
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,26 @@
import { types } from "./actionTypes";
export const pushPanel = (panel) => ({
type: types.PUSH_PANEL,
payload: panel,
});
export const popPanel = (panelName) => ({
type: types.POP_PANEL,
payload: panelName,
});
export const updatePanel = (panelInfo) => ({
type: types.UPDATE_PANEL,
payload: panelInfo,
});
export const updateModalStatus = (status) => ({
type: types.UPDATE_MODAL_STATUS,
payload: status,
});
export const resetPanels = (panels) => ({
type: types.RESET_PANELS,
payload: panels,
});

View File

@@ -0,0 +1,30 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// Best Seller 상품 목록 조회 IF-LGSP-303
export const getBestSeller = () => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("getBestSeller onSuccess", response.data);
dispatch({
type: types.GET_BEST_SELLER,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getBestSeller onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_PRODUCT_BESTSELLER,
{},
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,37 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// Search 통합검색 (IBS) 데이터 조회 IF-LGSP-090
export const getSearch = (params) => (dispatch, getState) => {
const { service, query, startIndex, maxResults, domain } = params;
const onSuccess = (response) => {
console.log("getSearch onSuccess: ", response.data);
dispatch({
type: types.GET_SEARCH,
payload: response.data,
});
};
const onFail = (error) => {
console.error("getSearch onFail: ", error);
};
TAxios(
dispatch,
getState,
"post",
URLS.GET_SEARCH,
{},
{ service, query, startIndex, maxResults, domain },
onSuccess,
onFail
);
};
export const resetSearch = (status) => ({
type: types.RESET_SEARCH,
payload: status,
});

View File

@@ -1,12 +1,12 @@
import { getUrl, URLS } from "./apiConfig";
import { addPanels, resetPanels } from "../features/panels/panelsSlice";
import * as HelperMethods from "../utils/helperMethods";
import * as Config from "../utils/Config";
import axios from "axios"; import axios from "axios";
import * as HelperMethods from "../utils/helperMethods";
import { getUrl, URLS } from "./apiConfig";
// refresh-token 구현 필요 // refresh-token 구현 필요
let tokenRefreshing = false; let tokenRefreshing = false;
export const tokenRefresh = async (dispatch, getState, autoLogin, callback) => { export const tokenRefresh = (dispatch, getState, autoLogin, callback) => {
return new Promise((resolve, reject) => {
// console.log('getState ', getState()); // console.log('getState ', getState());
// const {serverType} = getState().common.localSettings; // const {serverType} = getState().common.localSettings;
// const url = getUrl(URLS.TOKEN_REFRESH, serverType); // const url = getUrl(URLS.TOKEN_REFRESH, serverType);
@@ -71,9 +71,11 @@ export const tokenRefresh = async (dispatch, getState, autoLogin, callback) => {
// } // }
// }; // };
tokenRefreshing = false; tokenRefreshing = false;
resolve();
});
}; };
export const TAxios = async ( export const TAxios = (
dispatch, dispatch,
getState, getState,
type, type,
@@ -84,8 +86,24 @@ export const TAxios = async (
onFail, onFail,
noTokenRefresh = false noTokenRefresh = false
) => { ) => {
let accessToken = getState().device.accessToken; const checkAccessToken = () => {
return new Promise((resolve) => {
const accessToken = getState().device.accessToken;
if (
accessToken ||
baseUrl === URLS.GET_AUTHENTICATION_CODE ||
noTokenRefresh
) {
resolve(accessToken);
} else {
HelperMethods.wait(100).then(() => {
resolve(checkAccessToken());
});
}
});
};
const executeRequest = (accessToken) => {
const AUTHORIZATION = { headers: {} }; const AUTHORIZATION = { headers: {} };
AUTHORIZATION.headers["app_id"] = "com.lgshop.app"; AUTHORIZATION.headers["app_id"] = "com.lgshop.app";
@@ -116,102 +134,52 @@ export const TAxios = async (
"additionalDataAllowed,takeOnAllowed,networkAllowed,generalTermsAllowed,chpAllowed,customAdAllowed,acrOnAllowed,voice2Allowed,voiceAllowed,acrAdAllowed"; "additionalDataAllowed,takeOnAllowed,networkAllowed,generalTermsAllowed,chpAllowed,customAdAllowed,acrOnAllowed,voice2Allowed,voiceAllowed,acrAdAllowed";
AUTHORIZATION.headers["X-Device-Personalization"] = "Y"; AUTHORIZATION.headers["X-Device-Personalization"] = "Y";
if (
baseUrl !== URLS.GET_AUTHENTICATION_CODE &&
!accessToken &&
!noTokenRefresh
) {
console.log("Waiting for access token...");
while (!accessToken) {
await HelperMethods.wait(100);
accessToken = getState().device.accessToken;
}
}
if (accessToken) { if (accessToken) {
AUTHORIZATION.headers["lgsp_auth"] = accessToken; AUTHORIZATION.headers["lgsp_auth"] = accessToken;
} }
if (typeof window === "object") { if (typeof window === "object") {
let url = ""; let url = Array.isArray(baseUrl) ? getUrl(baseUrl[0]) : getUrl(baseUrl);
if (Array.isArray(baseUrl)) { if (type === "get") {
url = getUrl(baseUrl[0]);
} else {
url = getUrl(baseUrl);
}
switch (type) {
case "get": {
const _urlparams = HelperMethods.createQueryString(urlParams); const _urlparams = HelperMethods.createQueryString(urlParams);
url += url ? `?${_urlparams}` : ""; url += url ? `?${_urlparams}` : "";
break;
}
} }
console.log("TAxios ", type + ": " + url, params); let axiosInstance;
if (!noTokenRefresh) {
await tokenRefresh(dispatch, getState);
}
while (tokenRefreshing) {
await HelperMethods.wait(100);
}
let axiosInstance = null;
switch (type) { switch (type) {
case "get": case "get":
AUTHORIZATION.headers = { ...AUTHORIZATION.headers, ...params }; axiosInstance = axios.get(url, AUTHORIZATION);
axiosInstance = axios[type](url, AUTHORIZATION);
break; break;
case "put":
// put이 있다면 구현 필요
case "post": case "post":
axiosInstance = axios[type](url, params, AUTHORIZATION); axiosInstance = axios.post(url, params, AUTHORIZATION);
break; break;
// TODO: 다른 HTTP 메소드 있다면 처리 (chw)
case "delete":
// delete가 있다면 구현 필요
} }
if (axiosInstance) { if (axiosInstance) {
axiosInstance axiosInstance
.then((res) => { .then((res) => {
console.log("TAxios response", url, res); console.log("TAxios response", url, res);
if (onSuccess) onSuccess(res);
if (onSuccess) {
onSuccess(res);
}
}) })
.catch((res) => { .catch((error) => {
const error = res && res.toJSON ? res.toJSON() : {};
console.error("TAxios ", url, error); console.error("TAxios ", url, error);
if (onFail) onFail(error);
if (error.message === "Network Error") {
dispatch(resetPanels());
dispatch(
addPanels({
name: Config.panel_names.ERROR_PANEL,
panelInfo: { reason: "server Error" },
})
);
} else {
// todo
}
if (onFail) {
onFail(res);
}
}); });
} else {
console.warn("TAxios invalid case type ", type);
} }
} }
}; };
checkAccessToken().then((accessToken) => {
if (!noTokenRefresh) {
tokenRefresh(dispatch, getState)
.then(() => executeRequest(accessToken))
.catch(() => {
/* 토큰 갱신 실패 처리 */
});
} else {
executeRequest(accessToken);
}
});
};

View File

@@ -1,41 +0,0 @@
/* ----------------------
삭제 예정
---------------------- */
import axios from "axios";
import { store } from "../store/store";
import { SHOPTIME_BASE_URL } from "./apiConfig";
const api = axios.create({
baseURL: SHOPTIME_BASE_URL,
});
api.defaults.headers.common["app_id"] = "com.lgshop.app";
api.defaults.headers.common["app_ver"] = "1.0.0";
api.defaults.headers.common["dvc_id"] = "testdeviceid";
api.defaults.headers.common["cntry_cd"] = "US";
api.defaults.headers.common["prod_cd"] = "webOSTV 5.0";
api.defaults.headers.common["plat_cd"] = "W20H";
api.defaults.headers.common["lang_cd"] = "en-US";
api.defaults.headers.common["os_ver"] = "3.0";
api.defaults.headers.common["sdk_ver"] = "1.0.0";
api.defaults.headers.common["publish_flag"] = "Y";
api.interceptors.request.use(
(config) => {
const accessToken = store.getState().auth.accessToken;
if (accessToken) {
config.headers["lgsp_auth"] = accessToken;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
export default api;

View File

@@ -1,43 +0,0 @@
/* ----------------------
삭제 예정
---------------------- */
import { URLS } from "./apiConfig";
import api from "./axiosConfig";
// 광고주 AD 정보 상세 조회 - Multiple 전시 IF-LGSP-082
export async function getAdDetailAMD() {}
// 광고주 AD 정보 상세 조회 - Single 전시 IF-LGSP-083
export async function getAdDetailAPD() {}
// 광고주 AD 정보 상세 조회 - Theme 전시 IF-LGSP-081
export async function getAdDetailATD() {}
// HOME Main Contents Banner 정보 조회 IF-LGSP-301
export async function getHomeMainContents() {}
// HOME LAYOUT 정보 조회 IF-LGSP-300
export async function getHomeLayout() {}
// 메뉴 목록 조회 IF-LGSP-044
export async function getHomeMenu() {}
// 약관 정보 조회 IF-LGSP-005
export async function getHomeTerms() {}
// Theme 전시 정보 상세 조회 IF-LGSP-060
export async function getThemeCurationDetailInfo() {}
export default {
getAdDetailAMD,
getAdDetailAPD,
getAdDetailATD,
getHomeMainContents,
getHomeLayout,
getHomeMenu,
getHomeTerms,
getThemeCurationDetailInfo,
};

View File

@@ -1,33 +0,0 @@
/* ----------------------
삭제 예정
---------------------- */
import { URLS } from "./apiConfig";
import api from "./axiosConfig";
// Onsale 조회 IF-LGSP-086
export async function getOnSaleInfo(props) {
const { lgCatCd, categoryIncFlag } = props;
try {
const response = await api.get(URLS.GET_ON_SALE_INFO, {
params: {
categoryIncFlag,
lgCatCd,
},
});
return response.data.data;
} catch (error) {
const { response } = error;
if (response) {
const statusCode = response.status;
const statusText = response.statusText;
console.error(`Error: ${statusCode} ${statusText}`);
}
}
}

View File

@@ -1,4 +1,4 @@
import React, { useMemo, useEffect, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
/* eslint-disable */ /* eslint-disable */
export default function SmoodShowingAnimation(WrappedComponent) { export default function SmoodShowingAnimation(WrappedComponent) {

View File

@@ -1,11 +1,14 @@
import React, { useCallback, useRef, useState } from "react"; import React, { useCallback, useRef, useState } from "react";
import css from "./TIconButton.module.less";
import Spottable from "@enact/spotlight/Spottable";
import classNames from "classnames"; import classNames from "classnames";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { Job } from "@enact/core/util"; import { Job } from "@enact/core/util";
import Spottable from "@enact/spotlight/Spottable";
import { popPanel, resetPanels } from "../../actions/panelActions";
import * as Config from "../../utils/Config"; import * as Config from "../../utils/Config";
import { popPanel, resetPanels } from "../../features/panels/panelsSlice"; import css from "./TIconButton.module.less";
const SpottableComponent = Spottable("div"); const SpottableComponent = Spottable("div");

View File

@@ -12,6 +12,7 @@
.leftArrow { .leftArrow {
background-image: url("../../../assets/searchpanel/sch-arr-l.png"); background-image: url("../../../assets/searchpanel/sch-arr-l.png");
background-position: center top; background-position: center top;
background-size: cover;
width: 47px; width: 47px;
height: 92px; height: 92px;
@@ -24,6 +25,7 @@
.rightArrow { .rightArrow {
background-image: url("../../../assets/searchpanel/sch-arr-r.png"); background-image: url("../../../assets/searchpanel/sch-arr-r.png");
background-position: center top; background-position: center top;
background-size: cover;
width: 47px; width: 47px;
height: 92px; height: 92px;

View File

@@ -1,10 +1,12 @@
import React, { forwardRef, useCallback, useRef, useEffect } from "react"; import React from "react";
import css from "./TInput.module.less";
import { InputField } from "@enact/sandstone/Input";
import Spottable from "@enact/spotlight/Spottable";
import classNames from "classnames"; import classNames from "classnames";
import { InputField } from "@enact/sandstone/Input";
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator"; import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
import TIconButton from "../TIconButton/TIconButton"; import TIconButton from "../TIconButton/TIconButton";
import css from "./TInput.module.less";
const Container = SpotlightContainerDecorator("div"); const Container = SpotlightContainerDecorator("div");
@@ -43,4 +45,4 @@ export default function TInput({
); );
} }
export { KINDS, ICONS, BORDER, COLOR }; export { BORDER, COLOR, ICONS, KINDS };

View File

@@ -44,6 +44,7 @@
position: absolute; position: absolute;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center top; background-position: center top;
background-size: cover;
width: 41px; width: 41px;
height: 41px; height: 41px;
top: 50%; top: 50%;

View File

@@ -1,11 +1,14 @@
import React, { useCallback } from "react";
import classNames from "classnames"; import classNames from "classnames";
import React, { useCallback, useEffect } from "react"; import { useDispatch } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { Panel } from "@enact/sandstone/Panels"; import { Panel } from "@enact/sandstone/Panels";
import { Cancelable } from "@enact/ui/Cancelable"; import { Cancelable } from "@enact/ui/Cancelable";
import css from "./TPanel.module.less";
import { popPanel } from "../../actions/panelActions";
import SmoodShowingAnimation from "../SmoodShowingAnimation/SmoodShowingAnimation"; import SmoodShowingAnimation from "../SmoodShowingAnimation/SmoodShowingAnimation";
import { popPanel } from "../../features/panels/panelsSlice"; import css from "./TPanel.module.less";
const CancelablePanel = Cancelable( const CancelablePanel = Cancelable(
{ modal: true, onCancel: "handleCancel" }, { modal: true, onCancel: "handleCancel" },
@@ -37,8 +40,6 @@ const TPanel = ({
[dispatch, handleCancel, isTabActivated] [dispatch, handleCancel, isTabActivated]
); );
console.log(isTabActivated);
return ( return (
<CancelablePanel <CancelablePanel
{...rest} {...rest}

View File

@@ -1,8 +1,10 @@
import classNames from "classnames";
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import Scroller from "@enact/sandstone/Scroller";
import classNames from "classnames";
import { off, on } from "@enact/core/dispatcher";
import { Job } from "@enact/core/util"; import { Job } from "@enact/core/util";
import { on, off } from "@enact/core/dispatcher"; import Scroller from "@enact/sandstone/Scroller";
import css from "./TScroller.module.less"; import css from "./TScroller.module.less";

View File

@@ -1,4 +1,10 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import classNames from "classnames"; import classNames from "classnames";
import compose from "ramda/src/compose"; import compose from "ramda/src/compose";

View File

@@ -20,7 +20,7 @@ import { Cancelable } from "@enact/ui/Cancelable";
//이미지 //이미지
import shoptimeFullIcon from "../../../assets/icons/ic-lnb-logo-shoptime@3x.png"; import shoptimeFullIcon from "../../../assets/icons/ic-lnb-logo-shoptime@3x.png";
import shopTimeIcon from "../../../assets/icons/ic-lnb-shoptime-symbol@3x.png"; import shopTimeIcon from "../../../assets/icons/ic-lnb-shoptime-symbol@3x.png";
import { resetPanels } from "../../features/panels/panelsSlice"; import { resetPanels } from "../../actions/panelActions";
import { panel_names } from "../../utils/Config"; import { panel_names } from "../../utils/Config";
import CartIcon from "./iconComponents/CartIcon"; import CartIcon from "./iconComponents/CartIcon";
import CategoryIcon from "./iconComponents/CategoryIcon"; import CategoryIcon from "./iconComponents/CategoryIcon";
@@ -34,6 +34,8 @@ import TrendingNowIcon from "./iconComponents/TrendingNowIcon";
import TabItem from "./TabItem"; import TabItem from "./TabItem";
import css from "./TabLayout.module.less"; import css from "./TabLayout.module.less";
//이미지
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(
{ enterTo: "default-element" }, { enterTo: "default-element" },
"div" "div"
@@ -430,6 +432,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
<TabItem <TabItem
key={"tabitem" + index} key={"tabitem" + index}
expanded={false} expanded={false}
selected={mainSelectedIndex === index}
index={index} index={index}
onClick={handleNavigation} onClick={handleNavigation}
icons={item.icons} icons={item.icons}

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const CartIcon = ({ iconType = "normal" }) => { const CartIcon = ({ iconType = "normal" }) => {

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const CategoryIcon = ({ iconType = "normal" }) => { const CategoryIcon = ({ iconType = "normal" }) => {

View File

@@ -1,4 +1,7 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const FeaturedBrandIcon = ({ iconType = "normal" }) => { const FeaturedBrandIcon = ({ iconType = "normal" }) => {
return ( return (
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const HomeIcon = ({ iconType = "normal" }) => { const HomeIcon = ({ iconType = "normal" }) => {

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const HotPicksIcon = ({ iconType = "normal" }) => { const HotPicksIcon = ({ iconType = "normal" }) => {

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const MyPageIcon = ({ iconType = "normal" }) => { const MyPageIcon = ({ iconType = "normal" }) => {

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const OnSaleIcon = ({ iconType = "normal" }) => { const OnSaleIcon = ({ iconType = "normal" }) => {

View File

@@ -1,3 +1,5 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const SearchIcon = ({ iconType = "normal" }) => { const SearchIcon = ({ iconType = "normal" }) => {

View File

@@ -1,4 +1,7 @@
import React from "react";
import { convertThemeColor } from "./convertThemeColor"; import { convertThemeColor } from "./convertThemeColor";
const TrendingNowIcon = ({ iconType = "normal" }) => { const TrendingNowIcon = ({ iconType = "normal" }) => {
return ( return (
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">

View File

@@ -3,9 +3,7 @@ export const convertThemeColor = (iconType) => {
const theme = { const theme = {
light: { light: {
normal: "#353535", normal: "#353535",
expanded: "#353535", expanded: "#FEFEFE",
selected: "#FEFEFE",
focused: "#FEFEFE",
}, },
}; };

Binary file not shown.

View File

@@ -1,19 +0,0 @@
import { createSlice } from "@reduxjs/toolkit";
export const appDataSlice = createSlice({
name: "appData",
initialState: {
mainIndex: null,
},
reducers: {
addMainIndex: (state, action) => {
state.mainIndex = action.payload;
},
},
});
// Action creators are generated for each case reducer function
export const { addMainIndex, decrement, incrementByAmount } =
appDataSlice.actions;
export default appDataSlice.reducer;

View File

@@ -1,122 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// Featured Brands 정보 조회 IF-LGSP-304
// @@pyh Todo, 기존의 key가 brandList에서 brandInfo로 변경 됨에 따라 함수명 또한 바뀔 수 있음 (문서 확인 후 변경 처리)
export const getBrandList = createAsyncThunk(
"brand/getBrandList",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("@@ getBrandList onSuccess ", response.data);
thunkAPI.dispatch(brandSlice.actions.updateBrandInfo(response.data.data));
};
const onFail = (error) => {
console.log("@@ getBrandList onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_BRAND_LIST,
{},
{},
onSuccess,
onFail
);
}
);
// Featured Brands LAYOUT (shelf) 정보 조회 IF-LGSP-305
export const getBrandLayoutInfo = createAsyncThunk(
"brand/getBrandLayoutInfo",
async (props, thunkAPI) => {
const { patnrId } = props;
const onSuccess = (response) => {
console.log("@@ getBrandLayoutInfo onSuccess ", response.data);
thunkAPI.dispatch(brandSlice.actions.updateLayoutBrandInfo(response.data.data));
};
const onFail = (error) => {
console.log("@@ getBrandLayoutInfo onFail ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_BRAND_LAYOUT_INFO,
{ patnrId },
{},
onSuccess,
onFail
);
}
);
// Featured Brands Live 채널 정보 조회 IF-LGSP-306
export const getBrandLiveChannelInfo = createAsyncThunk(
"brand/getBrandLiveChannelInfo",
async (props, thunkAPI) => {
const { patnrId } = props;
const onSuccess = (response) => {
console.log("@@ getBrandLiveChannelInfo onSuccess ", response.data);
thunkAPI.dispatch(brandSlice.actions.updateBrandLiveChannelInfo(response.data.data));
};
const onFail = (error) => {
console.log("@@ getBrandLiveChannelInfo onFail ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_BRAND_LIVE_CHANNEL_INFO,
{ patnrId },
{},
onSuccess,
onFail
);
}
);
const initialState = {
brandInfoData: {},
brandLayoutInfoData: {},
brandLiveChannelInfoData: {},
};
export const brandSlice = createSlice({
name: "brand",
initialState,
reducers: {
updateBrandInfo: (state, action) => {
state.brandInfoData = action.payload;
},
updateLayoutBrandInfo: (state, action) => {
state.brandLayoutInfoData = action.payload;
},
updateBrandLiveChannelInfo: (state, action) => {
state.brandLiveChannelInfoData = action.payload;
},
},
});
export const { updateBrandInfo, updateLayoutBrandInfo, updateBrandLiveChannelInfo } =
brandSlice.actions;
export default brandSlice.reducer;

View File

@@ -1,51 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// 인증코드 요청 IF-LGSP-000
export const getAuthenticationCode = createAsyncThunk(
"auth/getAuthenticationCode",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getAuthenticationCode onSuccess ", response.data);
thunkAPI.dispatch(
deviceSlice.actions.updateAccessToken(response.data.data.accessToken)
);
};
const onFail = (error) => {
console.error("getAuthenticationCode onFail ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_AUTHENTICATION_CODE,
{},
{},
onSuccess,
onFail
);
}
);
const initialState = {
accessToken: null,
};
export const deviceSlice = createSlice({
name: "device",
initialState,
reducers: {
updateAccessToken: (state, action) => {
state.accessToken = action.payload;
},
},
});
export const { updateAccessToken } = deviceSlice.actions;
export default deviceSlice.reducer;

View File

@@ -1,51 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// 이벤트 정보 조회 IF-LGSP-070 :
export const getWelcomeEventInfo = createAsyncThunk(
"event/getWelcomeEventInfo",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getWelcomeEventInfo onSuccess ", response.data);
thunkAPI.dispatch(eventSlice.actions.updateEventData(response.data.data));
};
const onFail = (error) => {
console.error("getWelcomeEventInfo onFail ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_WELCOME_EVENT_INFO,
{},
{},
onSuccess,
onFail
);
}
);
const initialState = {
eventData: {},
};
export const eventSlice = createSlice({
name: "event",
initialState,
reducers: {
updateEventData: (state, action) => {
// console.log("#action", action);
state.eventData = action.payload;
// console.log("#state", state.eventData);
},
},
});
export const { updateEventData } = eventSlice.actions;
export default eventSlice.reducer;

View File

@@ -1,186 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// 약관 정보 조회 IF-LGSP-005
export const getHomeTerms = createAsyncThunk(
"home/getHomeTerms",
async (props, thunkAPI) => {
const { trmsTpCdList, mbrNo } = props;
const onSuccess = (response) => {
console.log("getHomeTerms onSuccess ", response.data);
thunkAPI.dispatch(homeSlice.actions.updateTermsData(response.data));
};
const onFail = (error) => {
console.error("getHomeTerms onFail ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_HOME_TERMS,
{ trmsTpCdList, mbrNo },
{},
onSuccess,
onFail
);
}
);
// 메뉴 목록 조회 IF-LGSP-044
export const getHomeMenu = createAsyncThunk(
"home/getHomeMenu",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getHomeMenu onSuccess ", response.data);
thunkAPI.dispatch(homeSlice.actions.updateMenuData(response.data));
};
const onFail = (error) => {
console.error("getHomeMenu onFail ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_HOME_MENU,
{},
{},
onSuccess,
onFail
);
}
);
// HOME LAYOUT 정보 조회 IF-LGSP-300
export const getHomeLayout = createAsyncThunk(
"home/getHomeLayout",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getHomeLayout onSuccess", response.data);
thunkAPI.dispatch(homeSlice.actions.updateLayoutData(response.data.data));
};
const onFail = (error) => {
console.error("getHomeLayout onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_HOME_LAYOUT,
{},
{},
onSuccess,
onFail
);
}
);
// HOME Main Contents Banner 정보 조회 IF-LGSP-301
export const getHomeMainContents = createAsyncThunk(
"home/getHomeMainContents",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getHomeMainContents onSuccess", response.data);
thunkAPI.dispatch(homeSlice.actions.updateMainContentsData(response.data.data));
};
const onFail = (error) => {
console.error("getHomeMainContents onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_HOME_MAIN_CONTENTS,
{},
{},
onSuccess,
onFail
);
}
);
// Theme 전시 정보 조회 : IF-LGSP-045
export const getThemeCurationInfo = createAsyncThunk(
"home/getThemeCurationInfo",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getThemeCurationInfo onSuccess", response.data);
thunkAPI.dispatch(homeSlice.actions.updateThemeCurationInfoDataData(response.data.data));
};
const onFail = (error) => {
console.error("getThemeCurationInfo onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_THEME_CURATION_INFO,
{},
{},
onSuccess,
onFail
);
}
);
const initialState = {
termsData: {},
menuData: {},
layoutData: {},
mainContentsData: {},
themeCurationInfoData: {},
};
export const homeSlice = createSlice({
name: "home",
initialState,
reducers: {
updateTermsData: (state, action) => {
state.termsData = action.payload;
},
updateMenuData: (state, action) => {
//임시코드
state.menuData = action.payload;
},
updateLayoutData: (state, action) => {
state.layoutData = action.payload;
},
updateMainContentsData: (state, action) => {
state.mainContentsData = action.payload;
},
updateThemeCurationInfoDataData: (state, action) => {
state.themeCurationInfoData = action.payload;
},
},
});
export const {
updateTermsData,
updateMenuData,
updateLayoutData,
updateMainContentsData,
updateThemeCurationInfoDataData,
} = homeSlice.actions;
export default homeSlice.reducer;

View File

@@ -1,87 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
//서브카테고리 조회 IF-LGSP-051
export const getSubCategory = createAsyncThunk(
"main/getSubCategory",
async (props, thunkAPI) => {
const { lgCatCd, patnrIdList, pageSize, tabType, filterType } = props;
const onSuccess = (response) => {
console.log("getSubCategory onSuccess ", response.data);
thunkAPI.dispatch(
mainSlice.actions.updateSubCategoryData(response.data.data)
);
};
const onFail = (error) => {
console.log("getSubCategory onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_SUB_CATEGORY,
{ lgCatCd, patnrIdList, pageSize, tabType, filterType },
{},
onSuccess,
onFail
);
}
);
//TOP20 영상 목록 조회 IF-LGSP-069
export const getTop20Show = createAsyncThunk(
"main/getTop20Show",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getTop20Show onSuccess ", response.data);
thunkAPI.dispatch(
mainSlice.actions.updateTop20ShowData(response.data.data)
);
};
const onFail = (error) => {
console.log("getTop20Show onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_TOP20_SHOW,
{},
{},
onSuccess,
onFail
);
}
);
const initialState = {
subCategoryData: {},
top20ShowData: {},
};
export const mainSlice = createSlice({
name: "mainSlice",
initialState,
reducers: {
updateSubCategoryData: (state, action) => {
state.subCategoryData = action.payload;
},
updateTop20ShowData: (state, action) => {
state.top20ShowData = action.payload;
},
},
});
export const { updateSubCategoryData, updateTop20Show } = mainSlice.actions;
export default mainSlice.reducer;

View File

@@ -1,52 +0,0 @@
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;

View File

@@ -1,51 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// On Sale 조회 IF-LGSP-086
export const getOnSaleInfo = createAsyncThunk(
"onSale/getOnSaleInfo",
async (props, thunkAPI) => {
const { categoryIncFlag, lgCatCd } = props;
const onSuccess = (response) => {
console.log("getOnSaleInfo onSuccess ", response.data);
thunkAPI.dispatch(onSaleSlice.actions.updateOnSaleData(response.data.data));
};
const onFail = (error) => {
console.log("getOnSaleInfo onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_ON_SALE_INFO,
{ categoryIncFlag, lgCatCd },
{},
onSuccess,
onFail
);
}
);
const initialState = {
onSaleData: {},
};
export const onSaleSlice = createSlice({
name: "onSale",
initialState,
reducers: {
updateOnSaleData: (state, action) => {
state.onSaleData = action.payload;
},
},
});
export const { updateOnSaleData } = onSaleSlice.actions;
export default onSaleSlice.reducer;

View File

@@ -1,118 +0,0 @@
import { createSlice } from "@reduxjs/toolkit";
import { panel_names } from "../../utils/Config";
const initialState = {
panels: [],
isModalOpen: false,
};
const forceTopPanels = [
panel_names.ERROR_PANEL,
panel_names.DEBUG_PANEL,
panel_names.INTRO_PANEL,
];
export const panels = createSlice({
name: "panels",
initialState,
reducers: {
addPanels: (state, action) => {
if (!action.payload.panelInfo) {
action.payload.panelInfo = {};
}
const forceTopPanelsInfo = [];
const newState = [];
let forceTopIndex;
for (let index in state.panels) {
forceTopIndex = forceTopPanels.indexOf(state.panels[index].name);
if (forceTopIndex >= 0) {
forceTopPanelsInfo[forceTopIndex] = state.panels[index];
} else if (state.panels[index].name !== action.payload.name) {
newState.push(state.panels[index]);
}
}
forceTopIndex = forceTopPanels.indexOf(action.payload.name);
if (forceTopIndex >= 0) {
forceTopPanelsInfo[forceTopIndex] = action.payload;
} else {
newState.push(action.payload);
}
for (let i = 0; i < forceTopPanels.length; i++) {
if (forceTopPanelsInfo[i]) {
newState.push(forceTopPanelsInfo[i]);
}
}
state.panels = newState;
},
popPanel: (state, action) => {
let existIndex = -1;
if (action?.payload) {
for (let index in state.panels) {
if (state.panels[index].name === action.payload) {
existIndex = index;
break;
}
}
}
if (existIndex >= 0) {
// exist
state.panels = [
...state.panels.filter((value) => value.name !== action.payload),
];
}
if (!action.payload) {
state.panels = [...state.panels.slice(0, state.panels.length - 1)];
}
},
updatePanel: (state, action) => {
let existIndex = -1;
for (let index in state.panels) {
if (state.panels[index].name === action.payload.name) {
existIndex = index;
break;
}
}
if (existIndex >= 0 && action.payload.panelInfo) {
state.panels[existIndex].panelInfo = Object.assign(
{},
state.panels[existIndex].panelInfo,
action.payload.panelInfo
);
}
},
updateModalStatus: (state, action) => {
state.isModalOpen = action.payload;
},
resetPanels: (state, action) => {
state.isModalOpen = false;
if (action.payload) {
action.payload.forEach(function (panel) {
if (!panel.panelInfo) {
panel.panelInfo = {};
}
});
}
state.panels = action.payload ? action.payload : [];
},
},
});
export const {
addPanels,
popPanel,
updatePanel,
updateModalStatus,
resetPanels,
} = panels.actions;
export default panels.reducer;

View File

@@ -1,49 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// Best Seller 상품 목록 조회 IF-LGSP-303
export const getBestSeller = createAsyncThunk(
"bestSeller/getBestSeller",
async (_, thunkAPI) => {
const onSuccess = (response) => {
console.log("getBestSeller onSuccess", response.data);
thunkAPI.dispatch(
productSlice.actions.updateBestSellerData(response.data.data)
);
};
const onFail = (error) => {
console.log("getBestSeller onFail", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"get",
URLS.GET_PRODUCT_BESTSELLER,
{},
{},
onSuccess,
onFail
);
}
);
const initialState = {
bestSellerData: {},
};
export const productSlice = createSlice({
name: "product",
initialState,
reducers: {
updateBestSellerData: (state, action) => {
state.bestSellerData = action.payload;
},
},
});
export const { updateBestSellerData } = productSlice.actions;
export default productSlice.reducer;

View File

@@ -1,51 +0,0 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { URLS } from "../../api/apiConfig";
import { TAxios } from "../../api/TAxios";
// Search 통합검색 (IBS) 데이터 조회 IF-LGSP-090
export const getSearch = createAsyncThunk(
"search/getSearch",
async (params, thunkAPI) => {
const { service, query, startIndex, maxResults, domain } = params;
const onSuccess = (response) => {
console.log("getSearch onSuccess: ", response.data);
thunkAPI.dispatch(updateSearchData(response.data));
};
const onFail = (error) => {
console.error("getSearch onFail: ", error);
};
TAxios(
thunkAPI.dispatch,
thunkAPI.getState,
"post",
URLS.GET_SEARCH,
{},
{ service, query, startIndex, maxResults, domain },
onSuccess,
onFail
);
}
);
const initialState = {
searchDatas: {},
};
export const searchSlice = createSlice({
name: "search",
initialState,
reducers: {
updateSearchData: (state, action) => {
state.searchDatas = action.payload;
},
},
});
export const { updateSearchData } = searchSlice.actions;
export default searchSlice.reducer;

View File

@@ -1,8 +1,10 @@
import { createRoot } from "react-dom/client"; import React from "react";
import { store } from "./store/store"; import { render } from "react-dom";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import App from "./App"; import App from "./App";
import { store } from "./store/store";
let appElement = ( let appElement = (
<Provider store={store}> <Provider store={store}>
@@ -10,11 +12,12 @@ let appElement = (
</Provider> </Provider>
); );
// In a browser environment, render instead of exporting
if (typeof window === "object") { if (typeof window === "object") {
createRoot(document.getElementById("root")).render(appElement);
appElement = null;
window.store = store; window.store = store;
render(appElement, document.getElementById("root"));
appElement = null;
} }
export default appElement; export default appElement;

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
mainIndex: null,
};
export const appDataReducer = (state = initialState, action) => {
switch (action.type) {
case types.ADD_MAIN_INDEX:
return {
...state,
mainIndex: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,32 @@
import { types } from "../actions/actionTypes";
const initialState = {
brandInfoData: {},
brandLayoutInfoData: {},
brandLiveChannelInfoData: {},
};
export const brandReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_BRAND_LIST:
return {
...state,
brandInfoData: action.payload,
};
case types.GET_BRAND_LAYOUT_INFO:
return {
...state,
brandLayoutInfoData: action.payload,
};
case types.GET_BRAND_LIVE_CHANNEL_INFO:
return {
...state,
brandLiveChannelInfoData: action.payload,
};
default:
return state;
}
};

View File

@@ -1,7 +1,6 @@
import { createSlice } from "@reduxjs/toolkit"; import { types } from "../actions/actionTypes";
const initialState = { const initialState = {
// TODO: 각종 Status 추가
appStatus: { appStatus: {
showLoadingPanel: { show: true, type: "launching" }, showLoadingPanel: { show: true, type: "launching" },
isLoading: true, isLoading: true,
@@ -9,12 +8,11 @@ const initialState = {
}, },
}; };
export const commonSlice = createSlice({ export const commonReducer = (state = initialState, action) => {
name: "common", switch (action.type) {
initialState, case types.CHANGE_APP_STATUS: {
reducers: {
changeAppStatus: (state, action) => {
let isUpdated = false; let isUpdated = false;
for (let i in action.payload) { for (let i in action.payload) {
if (typeof action.payload[i] === "object") { if (typeof action.payload[i] === "object") {
if ( if (
@@ -22,20 +20,28 @@ export const commonSlice = createSlice({
JSON.stringify(state.appStatus[i]) JSON.stringify(state.appStatus[i])
) { ) {
isUpdated = true; isUpdated = true;
break; break;
} }
} else if (state.appStatus[i] !== action.payload[i]) { } else if (state.appStatus[i] !== action.payload[i]) {
isUpdated = true; isUpdated = true;
break; break;
} }
} }
if (isUpdated) { if (isUpdated) {
state.appStatus = { ...state.appStatus, ...action.payload }; return {
...state,
appStatus: { ...state.appStatus, ...action.payload },
};
}
return state;
} }
},
},
});
export const { changeAppStatus } = commonSlice.actions; default:
return state;
}
};
export default commonSlice.reducer; export default commonReducer;

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
accessToken: null,
};
export const deviceReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_AUTHENTICATION_CODE:
return {
...state,
accessToken: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
eventData: {},
};
export const eventReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_WELCOME_EVENT_INFO:
return {
...state,
eventData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,46 @@
import { types } from "../actions/actionTypes";
const initialState = {
termsData: {},
menuData: {},
layoutData: {},
mainContentsData: {},
themeCurationInfoData: {},
};
export const homeReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_HOME_TERMS:
return {
...state,
termsData: action.payload,
};
case types.GET_HOME_MENU:
return {
...state,
menuData: action.payload,
};
case types.GET_HOME_LAYOUT:
return {
...state,
layoutData: action.payload,
};
case types.GET_HOME_MAIN_CONTENTS:
return {
...state,
mainContentsData: action.payload,
};
case types.GET_THEME_CURATION_INFO:
return {
...state,
themeCurationInfoData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,25 @@
import { types } from "../actions/actionTypes";
const initialState = {
subCategoryData: {},
top20ShowData: {},
};
export const mainReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_SUB_CATEGORY:
return {
...state,
subCategoryData: action.payload,
};
case types.GET_TOP_20_SHOW:
return {
...state,
top20ShowData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
recommandedKeywordData: {},
};
export const myPageReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_MY_RECOMMANDED_KEYWORD:
return {
...state,
recommandedKeywordData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
onSaleData: {},
};
export const onSaleReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_ON_SALE_INFO:
return {
...state,
onSaleData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,105 @@
import { types } from "../actions/actionTypes";
import { panel_names } from "../utils/Config";
const initialState = {
panels: [],
isModalOpen: false,
};
const forceTopPanels = [
panel_names.ERROR_PANEL,
panel_names.DEBUG_PANEL,
panel_names.INTRO_PANEL,
];
export const panelsReducer = (state = initialState, action) => {
switch (action.type) {
case types.PUSH_PANEL: {
const panelInfo = action.payload.panelInfo || {};
const forceTopPanelsInfo = [];
const newState = [];
state.panels.forEach((panel) => {
const forceTopIndex = forceTopPanels.indexOf(panel.name);
if (forceTopIndex >= 0) {
forceTopPanelsInfo[forceTopIndex] = panel;
} else if (panel.name !== action.payload.name) {
newState.push(panel);
}
});
const newPanelForceTopIndex = forceTopPanels.indexOf(action.payload.name);
if (newPanelForceTopIndex >= 0) {
forceTopPanelsInfo[newPanelForceTopIndex] = {
...action.payload,
panelInfo,
};
} else {
newState.push({ ...action.payload, panelInfo });
}
forceTopPanels.forEach((_, index) => {
if (forceTopPanelsInfo[index]) {
newState.push(forceTopPanelsInfo[index]);
}
});
return {
...state,
panels: newState,
};
}
case types.POP_PANEL:
if (action.payload) {
return {
...state,
panels: state.panels.filter((panel) => panel.name !== action.payload),
};
} else {
return {
...state,
panels: state.panels.slice(0, state.panels.length - 1),
};
}
case types.UPDATE_PANEL:
return {
...state,
panels: state.panels.map((panel) =>
panel.name === action.payload.name
? {
...panel,
panelInfo: { ...panel.panelInfo, ...action.payload.panelInfo },
}
: panel
),
};
case types.UPDATE_MODAL_STATUS:
return {
...state,
isModalOpen: action.payload,
};
case types.RESET_PANELS: {
const updatedPanels = action.payload
? action.payload.map((panel) => ({
...panel,
panelInfo: panel.panelInfo || {},
}))
: [];
return {
...state,
panels: updatedPanels,
isModalOpen: false,
};
}
default:
return state;
}
};

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
bestSellerData: {},
};
export const productReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_BEST_SELLER:
return {
...state,
bestSellerData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,25 @@
import { types } from "../actions/actionTypes";
const initialState = {
searchDatas: {},
searchPerformed: false,
};
export const searchReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_SEARCH:
return {
...state,
searchDatas: action.payload,
searchPerformed: true,
};
case types.RESET_SEARCH:
return {
...initialState,
};
default:
return state;
}
};

View File

@@ -1,31 +1,32 @@
import { configureStore } from "@reduxjs/toolkit"; import { applyMiddleware, combineReducers, createStore } from "redux";
import thunk from "redux-thunk";
import appDataReducer from "../features/appData/appDataSlice"; import { appDataReducer } from "../reducers/appDataReducer";
import brandReducer from "../features/brand/brandsSlice"; import { brandReducer } from "../reducers/brandReducer";
import commonReducer from "../features/common/commonSlice"; import { commonReducer } from "../reducers/commonReducer";
import deviceReducer from "../features/device/deviceSlice"; import { deviceReducer } from "../reducers/deviceReducer";
import eventReducer from "../features/event/eventSlice"; import { eventReducer } from "../reducers/eventReducer";
import homeReducer from "../features/home/homeSlice"; import { homeReducer } from "../reducers/homeReducer";
import mainReducer from "../features/main/mainSlice"; import { mainReducer } from "../reducers/mainReducer";
import myPageReducer from "../features/mypage/myPageSlice"; import { myPageReducer } from "../reducers/myPageReducer";
import onSaleReducer from "../features/onSale/onSaleSlice"; import { onSaleReducer } from "../reducers/onSaleReducer";
import panelsReducer from "../features/panels/panelsSlice"; import { panelsReducer } from "../reducers/panelReducer";
import productReducer from "../features/product/productSlice"; import { productReducer } from "../reducers/productReducer";
import searchReducer from "../features/search/searchSlice"; import { searchReducer } from "../reducers/searchReducer";
export const store = configureStore({ const rootReducer = combineReducers({
reducer: {
panels: panelsReducer, panels: panelsReducer,
device: deviceReducer, device: deviceReducer,
appData: appDataReducer,
common: commonReducer, common: commonReducer,
appData: appDataReducer,
home: homeReducer, home: homeReducer,
onSale: onSaleReducer,
brand: brandReducer, brand: brandReducer,
myPage: myPageReducer,
search: searchReducer,
product: productReducer,
main: mainReducer, main: mainReducer,
event: eventReducer, myPage: myPageReducer,
}, onSale: onSaleReducer,
product: productReducer,
search: searchReducer,
evemt: eventReducer,
}); });
export const store = createStore(rootReducer, applyMiddleware(thunk));

View File

@@ -39,6 +39,7 @@
@BG_COLOR_01: #f8f8f8; @BG_COLOR_01: #f8f8f8;
@BG_COLOR_02: #f2f2f2; @BG_COLOR_02: #f2f2f2;
@BG_COLOR_03: #f2f6fb; @BG_COLOR_03: #f2f6fb;
@BG_COLOR_04: #f5f5f5;
/* MAIN COLOR */ /* MAIN COLOR */
@PRIMARY_COLOR_RED: #c70850; @PRIMARY_COLOR_RED: #c70850;
@@ -54,6 +55,7 @@
@COLOR_GRAY06: #333333; @COLOR_GRAY06: #333333;
@COLOR_GRAY07: #222222; @COLOR_GRAY07: #222222;
@COLOR_GRAY08: #1a1a1a; @COLOR_GRAY08: #1a1a1a;
@COLOR_GRAY09: #999999;
@COLOR_BLACK: #000000; @COLOR_BLACK: #000000;
@COLOR_NAVY: #2c343f; @COLOR_NAVY: #2c343f;

View File

@@ -1,4 +1,5 @@
import Enact_$L from "@enact/i18n/$L"; import Enact_$L from "@enact/i18n/$L";
import stringReSource from "../../resources/de/strings.json"; import stringReSource from "../../resources/de/strings.json";
export const $L = (str) => { export const $L = (str) => {
@@ -70,3 +71,17 @@ export const wait = (time) => {
}, time); }, time);
}); });
}; };
export const scaleW = (value) => {
if (typeof window === "object") {
return value * (window.innerWidth / 1920);
}
return value;
};
export const scaleH = (value) => {
if (typeof window === "object") {
return value * (window.innerHeight / 1080);
}
return value;
};

View File

@@ -1,3 +1,5 @@
import React from "react";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
export default function CartPanel() { export default function CartPanel() {

View File

@@ -2,11 +2,11 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import TPanel from "../../components/TPanel/TPanel";
import { import {
getBrandLayoutInfo, getBrandLayoutInfo,
getBrandLiveChannelInfo, getBrandLiveChannelInfo,
} from "../../features/brand/brandsSlice"; } from "../../actions/brandActions";
import TPanel from "../../components/TPanel/TPanel";
import Banner from "./Banner/Banner"; import Banner from "./Banner/Banner";
import css from "./FeaturedBrandsPanel.module.less"; import css from "./FeaturedBrandsPanel.module.less";
import LiveChannels from "./LiveChannels/LiveChannels"; import LiveChannels from "./LiveChannels/LiveChannels";

View File

@@ -1,20 +1,12 @@
import React, { import React, { useEffect } from "react";
useCallback,
useEffect,
useState,
useMemo,
useRef,
} from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import classNames from "classnames";
import { $L } from "../../../utils/helperMethods";
import { Job } from "@enact/core/util";
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator"; import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
import Spotlight from "@enact/spotlight";
import Spottable from "@enact/spotlight/Spottable"; import Spottable from "@enact/spotlight/Spottable";
import { getOnSaleInfo } from "../../../features/onSale/onSaleSlice"; import { getOnSaleInfo } from "../../../actions/onSaleActions";
import { $L } from "../../../utils/helperMethods";
import css from "./OnSale.module.less"; import css from "./OnSale.module.less";
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(

View File

@@ -1,13 +1,13 @@
import React, { useEffect, useState } from "react"; import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { $L } from "../../../utils/helperMethods";
import { Job } from "@enact/core/util";
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import Scroller from "@enact/sandstone/Scroller";
import { getTop20Show } from "../../../features/main/mainSlice";
import classNames from "classnames"; import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import { getTop20Show } from "../../../actions/mainActions";
import { $L } from "../../../utils/helperMethods";
import css from "../PopularShow/PopularShow.module.less"; import css from "../PopularShow/PopularShow.module.less";
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(

View File

@@ -2,19 +2,14 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { Job } from "@enact/core/util";
import Spotlight from "@enact/spotlight";
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator"; import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable"; import Spottable from "@enact/spotlight/Spottable";
import { getSubCategory } from "../../../actions/mainActions";
import { getOnSaleInfo } from "../../../actions/onSaleActions";
import TGrid from "../../../components/TGrid/TGrid"; import TGrid from "../../../components/TGrid/TGrid";
import TItemCard from "../../../components/TItemCard/TItemCard"; import TItemCard from "../../../components/TItemCard/TItemCard";
import TScroller from "../../../components/TScroller/TScroller";
import { getSubCategory } from "../../../features/main/mainSlice";
import { getOnSaleInfo } from "../../../features/onSale/onSaleSlice";
import { $L } from "../../../utils/helperMethods";
import CategoryNav from "../../OnSalePanel/CategoryNav/CategoryNav"; import CategoryNav from "../../OnSalePanel/CategoryNav/CategoryNav";
import css from "./SubCategory.module.less";
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(
{ {

View File

@@ -1,3 +1,5 @@
import React from "react";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
export default function HotPicksPanel() { export default function HotPicksPanel() {

View File

@@ -1,19 +1,18 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import * as Config from "../../utils/Config";
import TButton, { TYPES, SIZES } from "../../components/TButton/TButton";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import { getHomeTerms } from "../../actions/homeActions";
import { popPanel } from "../../actions/panelActions";
import TButton, { TYPES } from "../../components/TButton/TButton";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
import TPopUp from "../../components/TPopUp/TPopUp"; import TPopUp from "../../components/TPopUp/TPopUp";
import * as Config from "../../utils/Config";
import css from "./IntroPanel.module.less";
import classNames from "classnames";
import { $L } from "../../utils/helperMethods"; import { $L } from "../../utils/helperMethods";
import { addPanels, popPanel } from "../../features/panels/panelsSlice"; import css from "./IntroPanel.module.less";
import { getHomeTerms } from "../../features/home/homeSlice";
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" }, { enterTo: "last-focused" },

View File

@@ -1,17 +1,17 @@
import { useState, useEffect, useCallback } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { Job } from "@enact/core/util"; import { Job } from "@enact/core/util";
import { Panel } from "@enact/sandstone/Panels";
import Cancelable from "@enact/ui/Cancelable";
import LoadingAnimation from "../../../assets/intro/splash_03_end.webp"; import LoadingAnimation from "../../../assets/intro/splash_03_end.webp";
import css from "./LoadingPanel.module.less"; import { changeAppStatus } from "../../actions/commonActions";
import classNames from "classnames";
import Cancelable from "@enact/ui/Cancelable";
import { Panel } from "@enact/sandstone/Panels";
import { changeAppStatus } from "../../features/common/commonSlice";
import { $L } from "../../utils/helperMethods";
import PreloadImage from "../../components/PreloadImage/PreloadImage";
import CustomImage from "../../components/CustomImage/CustomImage"; import CustomImage from "../../components/CustomImage/CustomImage";
import PreloadImage from "../../components/PreloadImage/PreloadImage";
import { $L } from "../../utils/helperMethods";
import css from "./LoadingPanel.module.less";
const MIN_SHOWING_TIME = { launching: 2000, wait: 1000, default: 1000 }; const MIN_SHOWING_TIME = { launching: 2000, wait: 1000, default: 1000 };
const MAX_SHOWING_TIME = 20000; const MAX_SHOWING_TIME = 20000;

View File

@@ -1,35 +1,32 @@
import Panels from "@enact/sandstone/Panels";
import platform from "@enact/core/platform";
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addPanels, popPanel } from "../../features/panels/panelsSlice";
import css from "./MainView.module.less";
import classNames from "classnames"; import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";
import * as Config from "../../utils/Config"; import platform from "@enact/core/platform";
import LoadingPanel from "../LoadingPanel/LoadingPanel";
import IntroPanel from "../IntroPanel/IntroPanel";
import HomePanel from "../HomePanel/HomePanel";
import MyPagePanel from "../MyPagePanel/MyPagePanel";
import CategoryPanel from "../CategoryPanel/CategoryPanel";
import SearchPanel from "../SearchPanel/SearchPanel";
import OnSalePanel from "../OnSalePanel/OnSalePanel";
import TrendingNowPanel from "../TrendingNowPanel/TrendingNowPanel";
import HotPicksPanel from "../HotPicksPanel/HotPicksPanel";
import FeaturedBrandsPanel from "../FeaturedBrandsPanel/FeaturedBrandsPanel";
import ErrorPanel from "../ErrorPanel/ErrorPanel";
import DebugPanel from "../DebugPanel/DebugPanel";
import TabLayout from "../../components/TabLayout/TabLayout";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
import { changeAppStatus } from "../../features/common/commonSlice";
// 테스트용 - TODO: 메인 홈 화면에 나와야 하는 이미지들 추가 후 preloadImages에 추가 // 테스트용 - TODO: 메인 홈 화면에 나와야 하는 이미지들 추가 후 preloadImages에 추가
import testImage from "../../../assets/img-banner-myinfo-login@3x.png"; import testImage from "../../../assets/img-banner-myinfo-login@3x.png";
import { changeAppStatus } from "../../actions/commonActions";
import { pushPanel } from "../../actions/panelActions";
import PreloadImage from "../../components/PreloadImage/PreloadImage"; import PreloadImage from "../../components/PreloadImage/PreloadImage";
import TabLayout from "../../components/TabLayout/TabLayout";
import * as Config from "../../utils/Config";
import CartPanel from "../CartPanel/CartPanel";
import CategoryPanel from "../CategoryPanel/CategoryPanel";
import DebugPanel from "../DebugPanel/DebugPanel";
import ErrorPanel from "../ErrorPanel/ErrorPanel";
import FeaturedBrandsPanel from "../FeaturedBrandsPanel/FeaturedBrandsPanel";
import HomePanel from "../HomePanel/HomePanel";
import HotPicksPanel from "../HotPicksPanel/HotPicksPanel";
import IntroPanel from "../IntroPanel/IntroPanel";
import LoadingPanel from "../LoadingPanel/LoadingPanel";
import MyPagePanel from "../MyPagePanel/MyPagePanel";
import OnSalePanel from "../OnSalePanel/OnSalePanel";
import SearchPanel from "../SearchPanel/SearchPanel";
import TrendingNowPanel from "../TrendingNowPanel/TrendingNowPanel";
import css from "./MainView.module.less";
const preloadImages = [testImage]; const preloadImages = [testImage];
@@ -43,6 +40,7 @@ const panelMap = {
[Config.panel_names.TRENDING_NOW_PANEL]: TrendingNowPanel, [Config.panel_names.TRENDING_NOW_PANEL]: TrendingNowPanel,
[Config.panel_names.HOT_PICKS_PANEL]: HotPicksPanel, [Config.panel_names.HOT_PICKS_PANEL]: HotPicksPanel,
[Config.panel_names.FEATURED_BRANDS_PANEL]: FeaturedBrandsPanel, [Config.panel_names.FEATURED_BRANDS_PANEL]: FeaturedBrandsPanel,
[Config.panel_names.CART_PANEL]: CartPanel,
[Config.panel_names.ERROR_PANEL]: ErrorPanel, [Config.panel_names.ERROR_PANEL]: ErrorPanel,
[Config.panel_names.DEBUG_PANEL]: DebugPanel, [Config.panel_names.DEBUG_PANEL]: DebugPanel,
}; };
@@ -106,7 +104,7 @@ export default function MainView() {
if (isTermAgreed) { if (isTermAgreed) {
} else { } else {
dispatch( dispatch(
addPanels({ name: Config.panel_names.INTRO_PANEL, panelInfo: {} }) pushPanel({ name: Config.panel_names.INTRO_PANEL, panelInfo: {} })
); );
} }
} }

View File

@@ -2,10 +2,10 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { getOnSaleInfo } from "../../actions/onSaleActions";
import TBody from "../../components/TBody/TBody"; import TBody from "../../components/TBody/TBody";
import TItemCard from "../../components/TItemCard/TItemCard"; import TItemCard from "../../components/TItemCard/TItemCard";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
import { getOnSaleInfo } from "../../features/onSale/onSaleSlice";
import CategoryNav from "../OnSalePanel/CategoryNav/CategoryNav"; import CategoryNav from "../OnSalePanel/CategoryNav/CategoryNav";
import OnSaleProductsGrid from "../OnSalePanel/OnSaleProductsGrid/OnSaleProductsGrid"; import OnSaleProductsGrid from "../OnSalePanel/OnSaleProductsGrid/OnSaleProductsGrid";
import css from "./OnSalePanel.module.less"; import css from "./OnSalePanel.module.less";

View File

@@ -1,3 +1,5 @@
import React from "react";
import Scroller from "@enact/sandstone/Scroller"; import Scroller from "@enact/sandstone/Scroller";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";

View File

@@ -0,0 +1,44 @@
import React from "react";
import { useSelector } from "react-redux";
import NoSearchResultsImage from "../../../../assets/searchpanel/img-search-nodata.png";
import SectionTitle from "../../../components/SectionTitle/SectionTitle";
import TGrid from "../../../components/TGrid/TGrid";
import TItemCard from "../../../components/TItemCard/TItemCard";
import { $L } from "../../../utils/helperMethods";
import css from "./NoSearchResults.module.less";
export default function NoSearchResults() {
const bestSellerDatas = useSelector(
(state) => state.product.bestSellerData.bestSeller
);
return (
<div className={css.container}>
<div className={css.info}>
<img src={NoSearchResultsImage} 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>
</div>
);
}

View File

@@ -0,0 +1,24 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.container {
margin-top: 30px;
.info {
text-align: center;
> p {
.font (@fontFamily: @baseFontBold, @fontSize: 36px);
color: #a3a3a3;
margin-top: 6px;
}
}
.bestSellerWrap {
padding: 60px 60px 78px;
> h2 {
margin: 134px 0 34px;
}
}
}

View File

@@ -0,0 +1,56 @@
import React from "react";
import classNames from "classnames";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import TButton from "../../../components/TButton/TButton";
import TIconButton, {
ICON_TYPES,
} from "../../../components/TIconButton/TIconButton";
import css from "./RecommendedKeywords.module.less";
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
export default function RecommendedKeywords({
keywords,
onPrev,
onNext,
hasPrevPage,
hasNextPage,
handleSearchSubmit,
}) {
return (
<div className={css.container}>
{hasPrevPage && (
<TIconButton
iconType={ICON_TYPES.leftArrow}
className={classNames(css.arrow, css.arrowLeft)}
onClick={onPrev}
/>
)}
<Container className={css.keywordsGrid}>
{keywords.map((keyword, index) => (
<TButton
key={index}
spotlightId={index === 0 ? "first-keyword-button" : undefined}
className={classNames(css.keywordBox)}
onClick={() => handleSearchSubmit(keyword.keywd)}
>
{keyword.keywd}
</TButton>
))}
</Container>
{hasNextPage && (
<TIconButton
iconType={ICON_TYPES.rightArrow}
className={classNames(css.arrow, css.arrowRight)}
onClick={onNext}
/>
)}
</div>
);
}

View File

@@ -0,0 +1,53 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.container {
margin-top: 180px;
position: relative;
.arrow {
position: absolute;
top: 140px;
}
.arrowLeft {
left: 60px;
}
.arrowRight {
right: 60px;
}
.keywordsGrid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 40px 80px;
width: 100%;
place-items: center;
padding: 0 233px;
.keywordBox {
width: 390px;
height: 97px;
line-height: 97px;
letter-spacing: -1px;
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(2, 3, 3, 0.2);
border: 1px solid @COLOR_GRAY09;
background-color: @BG_COLOR_04;
color: #333;
.font(@fontFamily: @baseFontBold, @fontSize: 40px);
> div {
overflow: unset;
}
&:focus-within {
box-shadow: inset 0 0 0 4px @PRIMARY_COLOR_RED,
0 0 50px 0 rgba(11, 8, 8, 0.5);
color: @PRIMARY_COLOR_RED;
background-color: @BG_COLOR_04;
}
}
}
}

View File

@@ -1,43 +1,40 @@
import React, { useCallback, useEffect, useState, useRef } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import TInput, { KINDS, ICONS } from "../../components/TInput/TInput"; import { useDispatch, useSelector } from "react-redux";
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 SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
import { changeAppStatus } from "../../features/common/commonSlice"; import { getSearch, resetSearch } from "../../actions/searchActions";
import { getSearch } from "../../features/search/searchSlice"; import TBody from "../../components/TBody/TBody";
import TInput, { ICONS, KINDS } from "../../components/TInput/TInput";
import SearchNoDataImage from "../../../assets/searchpanel/img-search-nodata.png"; import TPanel from "../../components/TPanel/TPanel";
import TGrid from "../../components/TGrid/TGrid"; import NoSearchResults from "./NoSearchResults/NoSearchResults";
import TItemCard from "../../components/TItemCard/TItemCard"; import RecommendedKeywords from "./RecommendedKeywords/RecommendedKeywords";
import SectionTitle from "../../components/SectionTitle/SectionTitle"; import css from "./SearchPanel.module.less";
import SearchResults from "./SearchResults/SearchResults";
const Container = SpotlightContainerDecorator({ enterTo: "last-focused" }, "div");
const ITEMS_PER_PAGE = 9; const ITEMS_PER_PAGE = 9;
export default function SearchPanel() { export default function SearchPanel() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { showLoadingPanel } = useSelector((state) => state.common.appStatus);
const recommandedKeywords = useSelector( const recommandedKeywords = useSelector(
(state) => state.myPage.recommandedKeywordData.data?.keywords (state) => state.myPage.recommandedKeywordData.data?.keywords
); );
const searchDatas = useSelector((state) => state.search.searchDatas.data?.result.results); const searchDatas = useSelector(
const bestSellerDatas = useSelector((state) => state.product.bestSellerData.bestSeller); (state) => state.search.searchDatas.data?.result.results
);
const searchPerformed = useSelector((state) => state.search.searchPerformed);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [paginatedKeywords, setPaginatedKeywords] = useState([]); const [paginatedKeywords, setPaginatedKeywords] = useState([]);
const [pageChanged, setPageChanged] = useState(false); const [pageChanged, setPageChanged] = useState(false);
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [searchPerformed, setSearchPerformed] = useState(false);
useEffect(() => {
dispatch(resetSearch());
}, [dispatch]);
useEffect(() => { useEffect(() => {
if (recommandedKeywords) { if (recommandedKeywords) {
@@ -66,17 +63,10 @@ export default function SearchPanel() {
} }
}, []); }, []);
const performSearch = useCallback( const handleSearchSubmit = useCallback(
async (query) => { (query) => {
if (!query || query.trim() === "") { if (query.trim()) {
setSearchPerformed(false); dispatch(
return;
}
setSearchPerformed(true);
try {
await dispatch(
getSearch({ getSearch({
service: "com.lgshop.app", service: "com.lgshop.app",
query: query, query: query,
@@ -84,23 +74,12 @@ export default function SearchPanel() {
maxResults: 10, maxResults: 10,
domain: "theme,show,item", domain: "theme,show,item",
}) })
).unwrap(); );
} catch (error) { } else {
console.error("Search request failed: ", error); dispatch(resetSearch());
} }
}, },
[dispatch] [dispatch, searchQuery]
);
const handleSearchSubmit = useCallback(() => {
performSearch(searchQuery);
}, [searchQuery, dispatch]);
const handleKeywordSearch = useCallback(
(keyword) => {
performSearch(keyword);
},
[performSearch]
); );
const handleNext = useCallback(() => { const handleNext = useCallback(() => {
@@ -114,76 +93,12 @@ export default function SearchPanel() {
}, [currentPage]); }, [currentPage]);
const hasPrevPage = currentPage > 1; 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 ( return (
<Container className={css.noDataWrap}> <TPanel className={css.container}>
<div className={css.noDataResult}> <TBody className={css.tBody}>
<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 <TInput
className={css.input} className={css.input}
autoFocus autoFocus
@@ -191,9 +106,25 @@ export default function SearchPanel() {
icon={ICONS.search} icon={ICONS.search}
value={searchQuery} value={searchQuery}
onChange={handleSearchChange} onChange={handleSearchChange}
onIconClick={handleSearchSubmit} onIconClick={() => handleSearchSubmit(searchQuery)}
/> />
{renderContents()} {searchPerformed ? (
searchDatas && searchDatas.length > 0 ? (
<SearchResults contents={searchDatas} />
) : (
<NoSearchResults />
)
) : (
<RecommendedKeywords
keywords={paginatedKeywords}
onPrev={handlePrev}
onNext={handleNext}
hasPrevPage={hasPrevPage}
hasNextPage={hasNextPage}
handleSearchSubmit={handleSearchSubmit}
/>
)}
</TBody>
</TPanel> </TPanel>
); );
} }

View File

@@ -1,82 +1,15 @@
@import "../../style/CommonStyle.module.less"; @import "../../style/CommonStyle.module.less";
@import "../../style/utils.module.less"; @import "../../style/utils.module.less";
.panel { .container {
background-color: @BG_COLOR_01; background-color: @BG_COLOR_01;
width: 100%;
.tBody {
height: 100%; height: 100%;
}
.input { .input {
width: 880px;
margin: 180px auto 0; margin: 180px auto 0;
} width: 880px;
.keywordWrap {
position: relative;
margin: 180px 0 0 0;
display: flex;
justify-content: space-between;
.arrow {
position: absolute;
top: 140px;
}
.arrowLeft {
left: 60px;
}
.arrowRight {
right: 60px;
}
.keywordsGrid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 40px 80px;
width: 100%;
place-items: center;
padding: 0 233px;
.keywordBox {
width: 390px;
height: 97px;
line-height: 97px;
letter-spacing: -1px;
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(2, 3, 3, 0.2);
border: 1px solid #999;
background-color: #f5f5f5;
color: #333;
.font (@fontFamily: @baseFontBold, @fontSize: 40px);
> div {
overflow: unset;
}
&:focus-within {
box-shadow: inset 0 0 0 4px @PRIMARY_COLOR_RED,
0 0 50px 0 rgba(11, 8, 8, 0.5);
color: #c70850;
background-color: #f5f5f5;
}
}
}
}
.noDataWrap {
margin-top: 30px;
> .noDataResult {
text-align: center;
> p {
.font (@fontFamily:@baseFontBold, @fontSize:36px);
color: #a3a3a3;
margin-top: 6px;
}
}
.bestSellerWrap {
padding: 60px 60px 78px;
> h2 {
margin: 134px 0 34px;
}
}
} }
} }

View File

@@ -0,0 +1,5 @@
import React from "react";
export default function SearchResults({ datas }) {
return <p>data</p>;
}

View File

@@ -0,0 +1,19 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.container {
background-color: yellowgreen;
&:focus-within {
border: 1px solid red;
}
}
.container2 {
height: 240px;
}
.itemList {
width: 100%;
height: 100%;
}

View File

@@ -1,3 +1,5 @@
import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
@@ -9,10 +11,15 @@ import TPanel from "../../components/TPanel/TPanel";
import { $L } from "../../utils/helperMethods"; import { $L } from "../../utils/helperMethods";
import css from "./TrendingNowPanel.module.less"; import css from "./TrendingNowPanel.module.less";
const Container = SpotlightContainerDecorator({ enterTo: "last-focused" }, "div"); const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
export default function TrendingNowPanel() { export default function TrendingNowPanel() {
const bestSellerDatas = useSelector((state) => state.product.bestSellerData.bestSeller); const bestSellerDatas = useSelector(
(state) => state.product.bestSellerData.bestSeller
);
return ( return (
<TPanel> <TPanel>

View File

@@ -5,9 +5,9 @@ import { useDispatch, useSelector } from "react-redux";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import { getWelcomeEventInfo } from "../../actions/eventActions";
import TButton, { TYPES } from "../../components/TButton/TButton"; import TButton, { TYPES } from "../../components/TButton/TButton";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
import { getWelcomeEventInfo } from "../../features/event/eventSlice";
import { $L } from "../../utils/helperMethods"; import { $L } from "../../utils/helperMethods";
import css from "../WelcomeEventPanel/WelcomeEventPanel.module.less"; import css from "../WelcomeEventPanel/WelcomeEventPanel.module.less";