메뉴 즐겨찾기

This commit is contained in:
focp212@naver.com
2025-09-30 15:15:02 +09:00
parent f3d028da85
commit 31b9c3682d
7 changed files with 141 additions and 125 deletions

View File

@@ -16,37 +16,46 @@ const items: Array<UserFavorite> = [
]; ];
*/ */
export interface FavoriteWrapperProps { export interface FavoriteWrapperProps {
usingType: 'home' | 'menu' usingType: 'home' | 'menu',
editMode?: boolean,
setEditMode?: (editMode: boolean) => void;
changeMenuId?: string;
}; };
export const FavoriteWrapper = ({ export const FavoriteWrapper = ({
usingType usingType,
editMode,
setEditMode,
changeMenuId
}: FavoriteWrapperProps) => { }: FavoriteWrapperProps) => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const [edit, setEdit] = useState<boolean>(false);
const [favoriteItems, setFavoriteItems] = useState<Array<UserFavorite>>([]); const [favoriteItems, setFavoriteItems] = useState<Array<UserFavorite>>([]);
const itemAdd: UserFavorite = { const itemAdd: UserFavorite = {
img: IMAGE_ROOT + '/ico_menu_plus.svg', img: IMAGE_ROOT + '/ico_menu_plus.svg',
title: '편집하기' title: '편집하기'
}; };
const onClickToFavoriteEdit = () => { const onClickToFavoriteEdit = () => {
setEdit(true); if(usingType === 'menu' && setEditMode){
setEditMode(true);
}
}; };
//useSetFavoriteEdit(true);
//useSetMenuOn(true);
const onClickToNavigate = (path?: string) => { const onClickToNavigate = (path?: string) => {
if(!!path){ if(!!path){
navigate(path); navigate(path);
} }
}; };
const getFavoriteItems = () => { const getFavoriteList = () => {
console.log('1111')
let userFavorite = useStore.getState().UserStore.userFavorite;
setFavoriteItems(userFavorite);
};
const makeFavoriteItems = () => {
let rs = []; let rs = [];
for(let i=0;i<favoriteItems.length;i++){ for(let i=0;i<favoriteItems.length;i++){
rs.push( rs.push(
@@ -66,33 +75,45 @@ export const FavoriteWrapper = ({
</SwiperSlide> </SwiperSlide>
); );
} }
return rs;
rs.push( };
<SwiperSlide key={ `favorite-item-add-slide-key` }> const makeAddFavoriteItem = () => {
<div let rs = [];
className="swiper-item" if(!editMode){
onClick={ onClickToFavoriteEdit } rs.push(
> <SwiperSlide key={ `favorite-item-add-slide-key` }>
<div className="swiper-icon coin-icon"> <div
<img className="swiper-item"
src={ itemAdd.img } onClick={ onClickToFavoriteEdit }
alt={ itemAdd.title } >
/> <div className="swiper-icon coin-icon">
<img
src={ itemAdd.img }
alt={ itemAdd.title }
/>
</div>
<span className="swiper-text">{ itemAdd.title }</span>
</div> </div>
<span className="swiper-text">{ itemAdd.title }</span> </SwiperSlide>
</div> );
</SwiperSlide> }
);
return rs; return rs;
}; };
useEffect(() => {
getFavoriteList();
}, [changeMenuId]);
return ( return (
<> <>
<Swiper <Swiper
spaceBetween={ 9 } spaceBetween={ 9 }
slidesPerView={ 4 } slidesPerView={ 4 }
>{ getFavoriteItems() }</Swiper> >
{ (favoriteItems.length > 0) && makeFavoriteItems() }
{ makeAddFavoriteItem() }
</Swiper>
</> </>
); );
}; };

View File

@@ -12,5 +12,6 @@ export interface MenuCategoryProps {
menuName?: string; menuName?: string;
subMenu?: Array<MenuItem>; subMenu?: Array<MenuItem>;
setMenuOn?: (menuOn: boolean) => void; setMenuOn?: (menuOn: boolean) => void;
favoriteEdit?: boolean; editMode?: boolean;
setChangeMenuId?: (menuId?: string) => void;
}; };

View File

@@ -2,6 +2,8 @@ import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { MenuCategoryProps } from '../model/types'; import { MenuCategoryProps } from '../model/types';
import { useStore } from '@/shared/model/store'; import { useStore } from '@/shared/model/store';
import { IMAGE_ROOT } from '@/shared/constants/common'; import { IMAGE_ROOT } from '@/shared/constants/common';
import { UserFavorite } from '@/entities/user/model/types';
import { useEffect, useState } from 'react';
export const MenuCategory = ({ export const MenuCategory = ({
menuId, menuId,
@@ -9,12 +11,16 @@ export const MenuCategory = ({
menuName, menuName,
subMenu, subMenu,
setMenuOn, setMenuOn,
favoriteEdit editMode,
setChangeMenuId
}: MenuCategoryProps) => { }: MenuCategoryProps) => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const [favoriteItems, setFavoriteItems] = useState<Array<UserFavorite>>([]);
const [menuIds, setMenuIds] = useState<Array<string | undefined>>([]);
const onClickToNavigate = (path?: string) => { const onClickToNavigate = (path?: string) => {
if(!!path && !!setMenuOn && !favoriteEdit){ if(!!path && !!setMenuOn && !editMode){
setMenuOn(false); setMenuOn(false);
navigate(path); navigate(path);
} }
@@ -23,20 +29,53 @@ export const MenuCategory = ({
const favoriteSetting = ( const favoriteSetting = (
checked: boolean, checked: boolean,
title?: string, title?: string,
path?: string path?: string,
menuId?: string
) => { ) => {
useStore.getState().UserStore.setUserFavorite([{ console.log(checked, title, path, menuId)
title: title, let userFavorite = useStore.getState().UserStore.userFavorite;
img: IMAGE_ROOT + '/ico_menu_01.svg', if(checked){
path: path, userFavorite = [
}]); ...userFavorite,
{
title: title,
img: IMAGE_ROOT + '/ico_menu_01.svg',
path: path,
menuId: menuId
}
];
}
else{
userFavorite = userFavorite.filter((value, index) => {
return value.menuId !== menuId
});
}
useStore.getState().UserStore.setUserFavorite(userFavorite);
callFavoiteItems();
if(setChangeMenuId){
setChangeMenuId(menuId);
}
}; };
const callFavoiteItems = () => {
let userFavorite = useStore.getState().UserStore.userFavorite;
console.log(userFavorite)
setFavoriteItems(userFavorite);
let newArr: Array<string | undefined> = userFavorite.map((value, index) => {
return value.menuId;
});
setMenuIds(newArr);
};
useEffect(() => {
callFavoiteItems();
}, []);
const getMenuItems = () => { const getMenuItems = () => {
let rs = []; let rs = [];
if(subMenu){ if(subMenu){
for(let i=0;i<subMenu.length;i++){ for(let i=0;i<subMenu.length;i++){
if(!!favoriteEdit){ if(!!editMode){
rs.push( rs.push(
<li <li
key={ `menu-item-key-${menuId}-${i}` } key={ `menu-item-key-${menuId}-${i}` }
@@ -45,14 +84,20 @@ export const MenuCategory = ({
<span>{ subMenu[i]?.menuName }</span> <span>{ subMenu[i]?.menuName }</span>
<div className="check_box_scrap"> <div className="check_box_scrap">
<input <input
id={ `menu-item-checkbox-${menuId}-${i}` } id={ `menu-item-checkbox-${subMenu[i]?.menuId}-${i}` }
className="checkbox" className="checkbox"
type="checkbox" type="checkbox"
onChange={ (e) => favoriteSetting(e.target.checked, subMenu[i]?.menuName, subMenu[i]?.path) } checked={ menuIds.includes(subMenu[i]?.menuId)? true: false }
onChange={ (e) => favoriteSetting(
e.target.checked,
subMenu[i]?.menuName,
subMenu[i]?.path,
subMenu[i]?.menuId
)}
/> />
<label <label
className="gtr" className="gtr"
htmlFor={ `menu-item-checkbox-${menuId}-${i}` } htmlFor={ `menu-item-checkbox-${subMenu[i]?.menuId}-${i}` }
></label> ></label>
</div> </div>
</li> </li>

View File

@@ -56,7 +56,6 @@ export const createUserInfoStore = lens<UserInfoState>((set, get) => ({
return { return {
...state, ...state,
userFavorite: [ userFavorite: [
...state.userFavorite,
...newUserFavorite ...newUserFavorite
], ],
}; };

View File

@@ -32,6 +32,7 @@ export interface UserFavorite {
title?: string; title?: string;
img?: string; img?: string;
path?: string; path?: string;
menuId?: string;
}; };
export interface UserInfo extends LoginResponse { export interface UserInfo extends LoginResponse {
status: boolean; status: boolean;

View File

@@ -84,31 +84,6 @@ const AdditionalServicePages = lazyLoad('/src/pages/additional-service/addition
const SupportPages = lazyLoad('/src/pages/support/support-pages'); const SupportPages = lazyLoad('/src/pages/support/support-pages');
const SettingPage = lazyLoad('/src/pages/setting/setting-page'); const SettingPage = lazyLoad('/src/pages/setting/setting-page');
const AlarmPages = lazyLoad('/src/pages/alarm/alarm-pages'); const AlarmPages = lazyLoad('/src/pages/alarm/alarm-pages');
/*
const IntroPage = lazyLoad('/src/pages/intro/intro-page');
const StartPage = lazyLoad('/src/pages/sign-up/start/start-page');
const AppAuthPage = lazyLoad('/src/pages/sign-up/app-auth/app-auth-page');
const MobileVerificationPage = lazyLoad('/src/pages/sign-up/mobile-verification/mobile-verification-page');
const SignUpPages = lazyLoad('/src/pages/sign-up/sign-up-pages');
const IssueWalletPages = lazyLoad('/src/pages/issue-wallet/issue-wallet-pages');
const MyWalletPages = lazyLoad('/src/pages/my-wallet/my-wallet-pages');
const ExchangePages = lazyLoad('/src/pages/exchange/exchange-pages');
const MyBankAccountPage = lazyLoad('/src/pages/my-bank-account/my-bank-account-page');
const SecurityPage = lazyLoad('/src/pages/security/security-page');
const AppVersionPage = lazyLoad('/src/pages/app-version/app-version-page');
const SettingFontSizePage = lazyLoad('/src/pages/setting-font-size/setting-font-size-page');
const CommunityPages = lazyLoad('/src/pages/community/community-pages');
const MenuPage = lazyLoad('/src/pages/menu/menu-page');
const LoginPage = lazyLoad('/src/pages/login/login-page');
const ReLoginPage = lazyLoad('/src/pages/login/re-login-page');
const HomePage = lazyLoad('/src/pages/home/home-page');
const ShopListPage = lazyLoad('/src/pages/shop-list/shop-list-page');
const NotificationPages = lazyLoad('/src/pages/notification/notification-pages');
const PaymentPages = lazyLoad('/src/pages/payment/payment-pages');
const VoucherPages = lazyLoad('/src/pages/voucher/voucher-pages');
const PaymentGuidePage = lazyLoad('/src/pages/payment/payment-guide-page');
const InputShopWalletAddressPage = lazyLoad('/src/pages/payment/input-shop-wallet-address-page');
*/
export const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes); export const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);
const Pages = () => { const Pages = () => {
@@ -139,45 +114,6 @@ const Pages = () => {
</Route> </Route>
</Route> </Route>
{
/*
<Route path={ROUTE_NAMES.intro} element={<IntroPage />} />
<Route path={ROUTE_NAMES.start} element={<StartPage />} />
<Route path={ROUTE_NAMES.appAuth} element={<AppAuthPage />} />
<Route element={<SubLayout />}>
<Route path={ROUTE_NAMES.mobileVerification} element={<MobileVerificationPage />} />
<Route path={ROUTE_NAMES.signUp.base} element={<SignUpPages />} />
<Route element={<ProtectedRoute />}>
<Route path={ROUTE_NAMES.issueWallet.base} element={<IssueWalletPages />} />
<Route path={ROUTE_NAMES.myWallet.base} element={<MyWalletPages />} />
<Route path={ROUTE_NAMES.exchange.base} element={<ExchangePages />} />
<Route path={ROUTE_NAMES.myBankAccount} element={<MyBankAccountPage />} />
<Route path={ROUTE_NAMES.security} element={<SecurityPage />} />
<Route path={ROUTE_NAMES.appVersion} element={<AppVersionPage />} />
<Route path={ROUTE_NAMES.settingFontSize} element={<SettingFontSizePage />} />
<Route path={ROUTE_NAMES.community.base} element={<CommunityPages />} />
<Route path={ROUTE_NAMES.shopList} element={<ShopListPage />} />
<Route path={ROUTE_NAMES.notification.base} element={<NotificationPages />} />
<Route path={ROUTE_NAMES.payment.base} element={<PaymentPages />} />
<Route path={ROUTE_NAMES.menu} element={<MenuPage />} />
<Route path={ROUTE_NAMES.voucher.base} element={<VoucherPages />} />
</Route>
<Route path="*" element={<NotFoundError />} />
</Route>
<Route path={ROUTE_NAMES.login} element={<LoginPage />} />
<Route path={ROUTE_NAMES.reLogin} element={<ReLoginPage />} />
<Route element={<PullToRefreshRoute />}>
<Route element={<ProtectedRoute />}>
<Route path={ROUTE_NAMES.home} element={<HomePage />} />
</Route>
</Route>
<Route path={ROUTE_NAMES.paymentGuide} element={<PaymentGuidePage />} />
<Route path={ROUTE_NAMES.inputShopWalletAddr} element={<InputShopWalletAddressPage />} />
*/
}
</SentryRoutes> </SentryRoutes>
</GlobalAPIErrorBoundary> </GlobalAPIErrorBoundary>
</OverlayProvider> </OverlayProvider>

View File

@@ -24,14 +24,21 @@ export const Menu = ({
const userInfo = useStore((state) => state.UserStore.userInfo); const userInfo = useStore((state) => state.UserStore.userInfo);
const [shortBtns, setShortBtns] = useState<Array<Record<string, any>>>([]); const [shortBtns, setShortBtns] = useState<Array<Record<string, any>>>([]);
const [editMode, setEditMode] = useState<boolean>(false);
const [changeMenuId, setChangeMenuId] = useState<string | undefined>();
const onClickToNavigate = (path: string) => { const onClickToNavigate = (path: string) => {
onClickToMenuClose(); onClickToMenuClose();
navigate(path); navigate(path);
}; };
const onClickToMenuClose = () => { const onClickToMenuClose = () => {
setMenuOn(false); if(editMode){
}; setEditMode(false);
}
else{
setMenuOn(false);
}
};
const getMenuCategory = () => { const getMenuCategory = () => {
let rs = []; let rs = [];
@@ -44,7 +51,8 @@ export const Menu = ({
menuName={ MenuItems[i]?.menuName } menuName={ MenuItems[i]?.menuName }
subMenu={ MenuItems[i]?.subMenu } subMenu={ MenuItems[i]?.subMenu }
setMenuOn={ setMenuOn } setMenuOn={ setMenuOn }
favoriteEdit={ favoriteEdit } editMode={ editMode }
setChangeMenuId= { setChangeMenuId }
/> />
); );
} }
@@ -86,15 +94,17 @@ export const Menu = ({
<span style={{marginLeft: '4px'}}>(madzoneviper)</span> <span style={{marginLeft: '4px'}}>(madzoneviper)</span>
</div> </div>
<div className="full-menu-actions"> <div className="full-menu-actions">
<button { !editMode &&
className="full-menu-settings" <button
onClick={ () => onClickToNavigate(PATHS.setting) } className="full-menu-settings"
> onClick={ () => onClickToNavigate(PATHS.setting) }
<img >
src={ IMAGE_ROOT + '/ico_set.svg' } <img
alt="설정" src={ IMAGE_ROOT + '/ico_set.svg' }
/> alt="설정"
</button> />
</button>
}
<button <button
className="full-menu-close" className="full-menu-close"
onClick={ () => onClickToMenuClose() } onClick={ () => onClickToMenuClose() }
@@ -108,11 +118,14 @@ export const Menu = ({
</div> </div>
<div className="full-menu-top-nav"> <div className="full-menu-top-nav">
{ {
<FavoriteWrapper <FavoriteWrapper
usingType='menu' usingType='menu'
></FavoriteWrapper> editMode={ editMode }
} setEditMode={ setEditMode }
changeMenuId={ changeMenuId }
></FavoriteWrapper>
}
</div> </div>
<div className="full-menu-keywords-wrap"> <div className="full-menu-keywords-wrap">