Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
31fd421
chore: 자산 내역 관련 아이콘 추가
wupe1001 Jan 13, 2026
74f10af
refactor: BackPageGNB 수정
wupe1001 Jan 13, 2026
c61fa36
feat: 자산 목록 및 단일 자산 내역 페이지 구현
wupe1001 Jan 13, 2026
f887d95
refactor: 자산 상세 페이지 UI 컴포넌트 분리
wupe1001 Jan 13, 2026
800dff3
refactor: 자산 상세 내역 로직을 커스텀 훅으로 분리
wupe1001 Jan 14, 2026
157c4bc
chore: 디자인 시스템 설정에 은행 컬러 추가
wupe1001 Jan 14, 2026
4855063
refactor: 하드코딩된 색상을 디자인 토큰으로 교체
wupe1001 Jan 14, 2026
418edec
refactor: 총 거래 내역 건수의 출처를 커스텀 훅으로 이동
wupe1001 Jan 14, 2026
c7e5c07
feat: 분야별 내역 UI 구현
seunghee0321 Jan 15, 2026
d8b6962
refactor: 상세 페이지 진입 시 중복 연산 제거 및 데이터 전달 로직 최적화
seunghee0321 Jan 15, 2026
1a3e016
refactor: 월별 조회 기능 구현
seunghee0321 Jan 15, 2026
8413de0
feat: 비교 분석 페이지 UI 구현
seunghee0321 Jan 15, 2026
bd0ce0d
refactor: 분석 페이지 컴포넌트 구조화 및 UI 최적화
seunghee0321 Jan 15, 2026
7f8b598
chore: 분야별 분석 및 비교 분석 기능 통합
seunghee0321 Jan 15, 2026
b95941a
chore: feat/sector-analysis 작업 내용 병합 및 충돌 해결
seunghee0321 Jan 22, 2026
30142e9
chore: 머지 충돌 해결 및 최신 main 반영
seunghee0321 Jan 22, 2026
a864fc5
refactor: 비교 내역 페이지 UI 개선
seunghee0321 Jan 22, 2026
01c11a1
chore: main 브랜치 충돌 해결
seunghee0321 Jan 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/assets/icons/Add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/icons/menu/asset.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/assets/icons/menu/connection.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/menu/goal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/assets/icons/menu/ledger.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/assets/icons/menu/mbti.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icons/menu/recommend.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/menu/setting.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/assets/icons/menu/trophy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icons/warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/common/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ const BottomSheet = ({ isOpen, onClose, title, children }: BottomSheetProps) =>
);
};

export default BottomSheet;
export default BottomSheet;
29 changes: 29 additions & 0 deletions src/components/common/Toast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// src/components/common/Toast.tsx
import { Typography } from '@/components/typography';
import WarningIcon from '@/assets/icons/warning.svg';
import { cn } from '@/utils/cn';

export const Toast = ({ message, isOpen }: { message: string; isOpen: boolean }) => {
if (!isOpen) return null;

return (
<div className="fixed bottom-[34px] w-full px-5 z-[9999]">
<div
className={cn(
'flex items-center shadow-lg',
'w-[320px] h-[48px] rounded-[8px] gap-2 px-[10px] py-3',
'backdrop-blur-[8px]'
)}
style={{
backgroundColor: 'rgba(23, 23, 20, 0.45)',
}}
>
<img src={WarningIcon} alt="경고" className="w-6 h-6 flex-shrink-0" />

<Typography variant="body-2" className="text-white flex-1 leading-[20px] text-[14px]">
{message}
</Typography>
</div>
</div>
);
};
12 changes: 2 additions & 10 deletions src/components/goal/GoalBottonSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,13 @@ const GoalBottomSheet = ({ isOpen, item, onClose }: GoalBottomSheetProps) => {
placeholder="메모를 남겨주세요 (최대 20자)"
className="w-full text-base outline-none placeholder:text-gray-400"
/>
<img
src={WriteIcon}
alt="edit memo"
className="absolute w-5 h-5 right-4 top-4 opacity-40"
/>
<img src={WriteIcon} alt="edit memo" className="absolute w-5 h-5 right-4 top-4 opacity-40" />
</div>

<div className="mb-12 space-y-6">
<DetailRow label="거래시간" value={item.time} />
<DetailRow label="거래구분" value={item.category} />
<DetailRow
label="거래금액"
value={item.amount.replace(/[-+]/g, '').trim()}
isBold
/>
<DetailRow label="거래금액" value={item.amount.replace(/[-+]/g, '').trim()} isBold />
<DetailRow label="거래 후 잔액" value={item.balanceAfter} isBold />
<DetailRow label="입금계좌" value={item.account} />
</div>
Expand Down
8 changes: 2 additions & 6 deletions src/components/goal/GoalGNB.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,15 @@ const GoalGNB = () => {
<button
onClick={() => navigate(paths.goal.current)}
className={`flex-1 py-4 text-center text-base transition-all ${
isCurrentActive
? 'font-bold text-gray-900 border-b-2 border-gray-900'
: 'font-medium text-gray-400'
isCurrentActive ? 'font-bold text-gray-900 border-b-2 border-gray-900' : 'font-medium text-gray-400'
}`}
>
현재 목표
</button>
<button
onClick={() => navigate(paths.goal.past)}
className={`flex-1 py-4 text-center text-base transition-all ${
isPastActive
? 'font-bold text-gray-900 border-b-2 border-gray-900'
: 'font-medium text-gray-400'
isPastActive ? 'font-bold text-gray-900 border-b-2 border-gray-900' : 'font-medium text-gray-400'
}`}
>
지난 목표
Expand Down
4 changes: 1 addition & 3 deletions src/components/goal/TotalSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ const TotalSection = ({ goal }: GoalSummaryProps) => (
<img src={goal.bankIcon} alt="bank icon" className="w- h-9" />
</div>

<div className="text-[15px] text-gray-500 font-semibold whitespace-nowrap">
하나카드 | 1213190120-42-12233
</div>
<div className="text-[15px] text-gray-500 font-semibold whitespace-nowrap">하나카드 | 1213190120-42-12233</div>
</div>

{/* 달성 게이지 */}
Expand Down
114 changes: 114 additions & 0 deletions src/components/mypage/MenuGNB.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { useNavigate } from 'react-router-dom';
import { MobileLayout } from '@/components/layout/MobileLayout';
import BackPageGNB from '@/components/gnb/BackPageGNB';
import { Typography } from '@/components/typography';
import { MoreViewButton } from '@/components/buttons/MoreViewButton';

import SettingIcon from '@/assets/icons/menu/setting.svg';
import MBTIIcon from '@/assets/icons/menu/mbti.svg';
import TrophyIcon from '@/assets/icons/menu/trophy.svg';
import LedgerIcon from '@/assets/icons/menu/ledger.svg';
import ConnectionIcon from '@/assets/icons/menu/connection.svg';

import AssetIcon from '@/assets/icons/menu/asset.svg';
import GoalIcon from '@/assets/icons/menu/goal.svg';
import RecommendIcon from '@/assets/icons/menu/recommend.svg';

export const MenuGNB = () => {
const navigate = useNavigate();

return (
<MobileLayout className="bg-white">
<BackPageGNB
title="전체"
onBack={() => navigate(-1)}
text={<img src={SettingIcon} alt="설정" />}
onSkip={() => navigate('/mypage/settings')}
className="bg-white border-b border-neutral-5"
titleColor="text-neutral-90"
/>

<div className="flex-1 overflow-y-auto pb-10">
{/* 1. 상단 퀵 메뉴 그리드 */}
<div className="grid grid-cols-4 gap-y-6 px-5 py-8">
<QuickMenuButton label="MBTI" icon={MBTIIcon} onClick={() => navigate('/mbti')} />
<QuickMenuButton label="트로피" icon={TrophyIcon} />
<QuickMenuButton label="가계부" icon={LedgerIcon} />
<QuickMenuButton label="연결관리" icon={ConnectionIcon} />
</div>

{/* 💡 2. 리스트 섹션 영역 시작 */}
<div className="flex flex-col">
{/* 자산 섹션 (위에 선 생김) */}
<MenuSection title="자산" icon={AssetIcon}>
<MenuItem label="나의 자산내역" onClick={() => navigate('/asset')} />
<MenuItem label="분야별 내역" onClick={() => navigate('/asset/sector')} />
<MenuItem label="또래별 비교분석" onClick={() => navigate('/asset/compare')} />
</MenuSection>

{/* 목표 섹션 (위에 선 생김) */}
<MenuSection title="목표" icon={GoalIcon}>
<MenuItem label="현재 목표" onClick={() => navigate('/goal/current')} />
<MenuItem label="지난 목표" onClick={() => navigate('/goal/past')} />
<MenuItem label="목표 새로 추가하기" />
</MenuSection>

{/* 추천 섹션 (위에 선 생김) */}
<MenuSection title="추천" icon={RecommendIcon}>
<MenuItem label="추천 적금 바로가기" onClick={() => navigate('/recommend')} />
</MenuSection>
</div>
</div>
</MobileLayout>
);
};

/**
* 💡 퀵 메뉴 버튼: 52x52 사이즈와 Neutrals/10 배경 적용
*/
const QuickMenuButton = ({ label, icon, onClick }: { label: string; icon?: string; onClick?: () => void }) => (
<button onClick={onClick} className="flex flex-col items-center gap-2">
<div className="w-[52px] h-[52px] bg-neutral-10 rounded-xl flex items-center justify-center">
{icon ? (
<img src={icon} alt={label} className="justify-center" />
) : (
<div className="w-6 h-6 bg-neutral-20 rounded" />
)}
</div>
<Typography variant="caption-1" className="text-neutral-70">
{label}
</Typography>
</button>
);

/**
* 💡 메뉴 섹션 (자산, 목표 등 그룹)
*/
const MenuSection = ({ title, children, icon }: { title: string; children: React.ReactNode; icon: string }) => (
<div className="flex flex-col border-t border-neutral-5">
{' '}
{/* 💡 border-b 대신 border-t 사용! */}
<div className="px-5 pt-8 pb-4 flex items-center gap-2">
<img src={icon} alt={title} className="w-5 h-5 object-contain" />
<Typography variant="body-1" weight="bold" className="text-neutral-90">
{title}
</Typography>
</div>
<div className="flex flex-col pb-4">{children}</div>
</div>
);

/**
* 💡 MenuItem: div로 감싸서 중첩 버튼 에러 해결
*/
const MenuItem = ({ label, onClick }: { label: string; onClick?: () => void }) => (
<div
onClick={onClick}
className="w-full px-5 py-4 flex items-center justify-between active:bg-neutral-3 transition-colors text-left cursor-pointer"
>
<Typography variant="body-2" className="text-neutral-70">
{label}
</Typography>
<MoreViewButton className="opacity-50 pointer-events-none" />
</div>
);
2 changes: 1 addition & 1 deletion src/features/asset/constants/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ export interface TransactionGroup {
totalIncome: number;
totalExpense: number;
items: TransactionItem[];
}
}
2 changes: 1 addition & 1 deletion src/features/asset/constants/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ export const CATEGORY_STYLES: Record<string, CategoryStyle> = {
living: { bgColor: 'bg-atomic-purple-90', barColor: 'bg-atomic-purple-50', icon: LivingIcon }, // 주거
cafe: { bgColor: 'bg-atomic-green-90', barColor: 'bg-atomic-green-50', icon: CafeIcon }, // 카페
others: { bgColor: 'bg-neutral-60', barColor: 'bg-neutral-80', icon: OthersIcon }, // 그외
};
};
2 changes: 1 addition & 1 deletion src/hooks/Asset/useGetAccountDetail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@ export const useGetAccountDetail = () => {
transactionHistory: mockHistory,
totalCount: 10,
};
};
};
15 changes: 4 additions & 11 deletions src/hooks/Asset/useGetAssetAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,17 @@ export const useGetAssetAnalysis = (selectedDate: Date = new Date()) => {

return ASSET_ANALYSIS_RAW_DATA.filter((item) => {
const itemDate = new Date(item.date);
return (
itemDate.getFullYear() === targetYear &&
itemDate.getMonth() === targetMonth
);
return itemDate.getFullYear() === targetYear && itemDate.getMonth() === targetMonth;
});
}, [selectedDate]);

// 💡 4. 상세 정보를 포함한 트랜잭션 데이터 가공
const mockTransactions = useMemo((): TransactionWithDetails[] => {
// 임시 시작 잔액
let tempBalance = 5230450;
let tempBalance = 5230450; // 초기 잔액 설정
return filteredData.map((item) => {
const simpleType = item.sub.includes('|') ? item.sub.split('|')[1].trim() : item.sub;
const currentBalance = tempBalance;
tempBalance -= item.amount; // 다음 아이템을 위해 역산 (리스트가 최신순일 경우)

return {
...item,
displayDetails: [
Expand All @@ -58,9 +53,7 @@ export const useGetAssetAnalysis = (selectedDate: Date = new Date()) => {
// 💡 5. 총 지출액 계산
const totalExpense = useMemo(
() =>
mockTransactions
.filter((item) => item.type === 'expense')
.reduce((sum, item) => sum + Math.abs(item.amount), 0),
mockTransactions.filter((item) => item.type === 'expense').reduce((sum, item) => sum + Math.abs(item.amount), 0),
[mockTransactions]
);

Expand All @@ -80,4 +73,4 @@ export const useGetAssetAnalysis = (selectedDate: Date = new Date()) => {
otherCount: Math.max(0, allSectors.length - 6),
otherTotalAmount: allSectors.slice(6).reduce((sum, s) => sum + s.amount, 0),
};
};
};
Loading