diff --git a/.prettierrc b/.prettierrc.json
similarity index 100%
rename from .prettierrc
rename to .prettierrc.json
diff --git a/src/app/Router.tsx b/src/app/Router.tsx
index d7e38168..23d3a7cd 100644
--- a/src/app/Router.tsx
+++ b/src/app/Router.tsx
@@ -38,6 +38,11 @@ const LazyMyLinks = lazy(() =>
default: MyLinksPage,
}))
);
+const LazyPaymentManagement = lazy(() =>
+ import('@/pages/paymentManagement').then(({ PaymentManagementPage }) => ({
+ default: PaymentManagementPage,
+ }))
+);
const LazyMyPage = lazy(() =>
import('@/pages/my').then(({ MyPage }) => ({
default: MyPage,
@@ -97,6 +102,10 @@ function AppRouter() {
path: ROUTE.myEdit,
element: ,
},
+ {
+ path: ROUTE.paymentManagement,
+ element: ,
+ },
{
path: ROUTE.selectGroup,
element: ,
@@ -123,6 +132,7 @@ function AppRouter() {
element: ,
loader: groupTokenUrlLoader,
},
+
{
path: '*',
element: ,
diff --git a/src/pages/home/HomePage.style.ts b/src/pages/home/HomePage.style.ts
index 5eb5e768..2c5c6596 100644
--- a/src/pages/home/HomePage.style.ts
+++ b/src/pages/home/HomePage.style.ts
@@ -1,45 +1,5 @@
-import { Link } from 'react-router';
import styled from 'styled-components';
-/** @Todo Button 공통 컴포넌트 제작 */
-export const Button = styled.button<{ color?: string; bgColor?: string }>`
- display: flex;
- justify-content: center;
- align-items: center;
- background-color: ${({ bgColor }) => bgColor || 'black'};
- color: ${({ color }) => color || 'white'};
- font-weight: 400;
- border-radius: 9999px;
- padding: 0.5rem 0.75rem; // 8px 12px
- height: fit-content;
- width: fit-content;
- line-height: 1.5;
- font-size: 0.875rem; //14px
- cursor: pointer;
-
- &:hover {
- filter: brightness(0.9);
- transition: filter 0.1s;
- }
-`;
-
-export const SelectGroupButton = styled.button`
- display: flex;
- align-items: center;
- gap: ${({ theme }) => theme.unit[4]};
- background: transparent;
- color: ${({ theme }) => theme.color.semantic.orange.default};
-`;
-
-export const MainHeader = styled.header`
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 1rem 1.25rem; // 20px
- width: 100%;
- background-color: ${({ theme }) => theme.color.semantic.background.normal};
-`;
-
export const MainText = styled.h2`
font-size: 1.25rem; // 20px
font-weight: 700;
@@ -52,72 +12,3 @@ export const SubText = styled.p`
white-space: pre-wrap;
line-height: 1.5;
`;
-
-export const DescriptionImg = styled.img`
- width: 9.8rem;
- object-fit: contain;
- position: absolute;
- top: 9%;
- right: -0.2rem;
- rotate: -2deg;
-`;
-
-export const Hr = styled.hr`
- border: 0.5rem solid #edeeee;
- width: 100%;
-`;
-
-export const SettlementTitle = styled.h2`
- font-size: 1.25rem; // 20px
- font-weight: 700;
- padding: 0.5rem 1.25rem; // 8px 20px
- white-space: nowrap;
-`;
-
-export const SettlementButton = styled(Button)<{ selected?: boolean }>`
- background-color: ${({ selected, theme }) =>
- selected ? theme.color.semantic.primary : '#F1F3F5'};
- color: ${({ selected }) => (selected ? 'white' : 'black')};
-`;
-
-export const NoSettlementImg = styled.img`
- width: 33vw;
- max-width: 200px;
- object-fit: contain;
-`;
-
-export const BoxButton = styled(Link)`
- display: flex;
- padding: ${({ theme }) => `${theme.unit[16]} ${theme.unit[20]}`};
- position: relative;
- height: 5rem;
- background-color: ${({ theme }) => theme.color.semantic.orange.subtle};
- border-radius: ${({ theme }) => theme.radius.default};
-
- width: 100%;
-`;
-
-export const SmallImg = styled.img`
- width: 2.75rem;
- object-fit: contain;
- position: absolute;
- right: 1rem;
- bottom: 0.5rem;
-`;
-
-export const BoxButtonWrapper = styled.div`
- display: flex;
- max-width: 37.5rem;
- margin: ${({ theme }) =>
- `0 ${theme.unit[20]} ${theme.unit[32]} ${theme.unit[20]}`};
- gap: ${({ theme }) => theme.unit[8]};
-`;
-
-export const SettlementListWrapper = styled.div`
- display: flex;
- flex-direction: column;
- gap: ${({ theme }) => theme.unit[20]};
- margin: ${({ theme }) => `${theme.unit[20]} 0`};
- overflow-y: auto;
- flex: 1;
-`;
diff --git a/src/pages/home/HomePage.tsx b/src/pages/home/HomePage.tsx
index ee2aefcb..2ec4796d 100644
--- a/src/pages/home/HomePage.tsx
+++ b/src/pages/home/HomePage.tsx
@@ -1,181 +1,18 @@
-import { useTheme } from 'styled-components';
-import { LogoIcon } from '@/shared/assets/svgs';
-import MainHamImg2 from '@/shared/assets/pngs/MainHamImg2.png';
-import Text from '@/shared/ui/Text';
-import { ArrowRight, Bell, Menu, Next } from '@/shared/assets/svgs/icon';
-import { useNavigate } from 'react-router';
-import { ROUTE } from '@/shared/config/route';
-import { useState } from 'react';
-import CoinImg from '@/shared/assets/pngs/CoinImg.png';
-import LinkMain from '@/shared/assets/pngs/link_main.png';
-import CardMain from '@/shared/assets/pngs/card_main.png';
import Divider from '@/shared/ui/Divider';
import Flex from '@/shared/ui/Flex';
-import HomeExpenseItem from './ui/HomeExpenseItem';
-import * as S from './HomePage.style';
-
-interface HomeExpenseItemType {
- date: string;
- groupName: string;
- totalAmount: number;
- paidMember: number;
- totalMember: number;
- id: number;
-}
-/**
- * @Todo 진행중인 정산 내역 조회 API 함수 호출
- * 우선 mock data로 대체
- * */
-const settlementList: HomeExpenseItemType[] = [
- {
- id: 1,
- date: '2025년 2월 22일',
- groupName: 'DND 데모데이',
- totalAmount: 120000,
- paidMember: 3,
- totalMember: 6,
- },
- {
- id: 2,
- date: '2025년 1월 14일',
- groupName: 'DND 7조 첫모임',
- totalAmount: 150000,
- paidMember: 5,
- totalMember: 6,
- },
-];
+import {
+ MainHeader,
+ SettlementBanner,
+ SettlementList,
+} from './ui/HomePageSection';
function HomePage() {
- const [settlementType, setSettlementType] = useState<'RECEIVE' | 'SEND'>(
- 'RECEIVE'
- );
- const navigate = useNavigate();
- const theme = useTheme();
-
- const handleSettlementTypeButtonClick = (type: 'RECEIVE' | 'SEND') => {
- if (settlementType === type) {
- return;
- }
- setSettlementType(type);
- };
-
return (
-
- navigate(ROUTE.login)}
- />
-
-
-
-
-
-
- navigate(ROUTE.selectGroup)}>
- 정산하기
-
-
-
- 모임은 즐겁게, 정산은 깔끔하게!
-
- 모또만 믿고 맡겨줘!
-
-
-
-
-
-
- 링크 관리
-
-
-
-
-
- 캐릭터 도감
-
-
-
-
+
+
-
- 진행중인 정산
-
-
- handleSettlementTypeButtonClick('RECEIVE')}
- >
- 받을 정산
-
- handleSettlementTypeButtonClick('SEND')}
- >
- 보낼 정산
-
-
-
-
- 최신순
-
-
-
-
- {settlementList.length > 0 && settlementType === 'RECEIVE' && (
-
- {settlementList.map((data) => (
-
- ))}
-
- )}
- {settlementType === 'SEND' && (
-
-
-
- 아직 진행중인 정산이 없어요.
-
-
- )}
-
+
);
}
diff --git a/src/pages/home/ui/HomePageSection/index.style.ts b/src/pages/home/ui/HomePageSection/index.style.ts
new file mode 100644
index 00000000..146d4ab4
--- /dev/null
+++ b/src/pages/home/ui/HomePageSection/index.style.ts
@@ -0,0 +1,61 @@
+import styled from 'styled-components';
+import { Link } from 'react-router';
+
+export const SelectGroupButton = styled.button`
+ display: flex;
+ align-items: center;
+ gap: ${({ theme }) => theme.unit[4]};
+ background: transparent;
+ color: ${({ theme }) => theme.color.semantic.orange.default};
+`;
+
+export const DescriptionImg = styled.img`
+ width: 9.8rem;
+ object-fit: contain;
+ position: absolute;
+ top: 9%;
+ right: -0.2rem;
+ rotate: -2deg;
+`;
+
+export const NoSettlementImg = styled.img`
+ width: 33vw;
+ max-width: 200px;
+ object-fit: contain;
+`;
+
+export const BoxButton = styled(Link)`
+ display: flex;
+ padding: ${({ theme }) => `${theme.unit[16]} ${theme.unit[20]}`};
+ position: relative;
+ height: 5rem;
+ background-color: ${({ theme }) => theme.color.semantic.orange.subtle};
+ border-radius: ${({ theme }) => theme.radius.default};
+
+ width: 100%;
+`;
+
+export const SmallImg = styled.img`
+ width: 2.75rem;
+ object-fit: contain;
+ position: absolute;
+ right: 1rem;
+ bottom: 0.5rem;
+`;
+
+export const BoxButtonWrapper = styled.div`
+ display: flex;
+ max-width: 37.5rem;
+ margin: ${({ theme }) =>
+ `0 ${theme.unit[20]} ${theme.unit[32]} ${theme.unit[20]}`};
+ gap: ${({ theme }) => theme.unit[8]};
+`;
+
+export const SettlementListWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: ${({ theme }) => theme.unit[20]};
+ margin: ${({ theme }) => `${theme.unit[20]} 0`};
+ overflow-y: auto;
+ flex: 1;
+`;
diff --git a/src/pages/home/ui/HomePageSection/index.tsx b/src/pages/home/ui/HomePageSection/index.tsx
new file mode 100644
index 00000000..3f06eb87
--- /dev/null
+++ b/src/pages/home/ui/HomePageSection/index.tsx
@@ -0,0 +1,221 @@
+import { useTheme } from 'styled-components';
+import { LogoIcon } from '@/shared/assets/svgs';
+import MainHamImg2 from '@/shared/assets/pngs/MainHamImg2.png';
+import Text from '@/shared/ui/Text';
+import { ArrowRight, Bell, Menu, Next } from '@/shared/assets/svgs/icon';
+import { useNavigate } from 'react-router';
+import { ROUTE } from '@/shared/config/route';
+import { useState } from 'react';
+import CoinImg from '@/shared/assets/pngs/CoinImg.png';
+import LinkMain from '@/shared/assets/pngs/link_main.png';
+import CardMain from '@/shared/assets/pngs/card_main.png';
+
+import Flex from '@/shared/ui/Flex';
+import Button from '@/shared/ui/Button';
+import Header from '@/shared/ui/Header';
+import Chip from '@/shared/ui/Chip';
+import * as S from './index.style';
+import HomeExpenseItem from '../HomeExpenseItem';
+
+type SettlementType = 'IN_PROGRESS' | 'COMPLETED';
+
+interface HomeExpenseItemType {
+ date: string;
+ groupName: string;
+ totalAmount: number;
+ paidMember: number;
+ totalMember: number;
+ id: number;
+}
+/**
+ * @Todo 진행중인 정산 내역 조회 API 함수 호출
+ * 우선 mock data로 대체
+ * */
+const settlementListMock: HomeExpenseItemType[] = [
+ {
+ id: 1,
+ date: '2026년 2월 22일',
+ groupName: 'DND 데모데이',
+ totalAmount: 120000,
+ paidMember: 3,
+ totalMember: 6,
+ },
+ {
+ id: 2,
+ date: '2026년 1월 14일',
+ groupName: 'DND 7조 첫모임',
+ totalAmount: 150000,
+ paidMember: 5,
+ totalMember: 6,
+ },
+];
+
+export function MainHeader() {
+ const theme = useTheme();
+ return (
+
+ }
+ // leftButtonOnClick={() => navigate(ROUTE.login)}
+ rightButtonContent={
+
+ {/** @Todo 알림 기능 개발 후 변경 */}
+
+ {/** @Todo 마이페이지로 이동하는 핸들러 추가 */}
+
+
+ }
+ bgColor="semantic.background.normal.alternative"
+ />
+ );
+}
+
+export function SettlementBanner() {
+ const navigate = useNavigate();
+ const theme = useTheme();
+ return (
+ <>
+
+ navigate(ROUTE.selectGroup)}>
+ 정산하기
+
+
+
+ 모임은 즐겁게, 정산은 깔끔하게!
+
+ 모또만 믿고 맡겨줘!
+
+
+
+
+
+
+ 링크 관리
+
+
+
+
+
+ 입금 관리
+
+
+
+
+ >
+ );
+}
+
+export function SettlementList() {
+ const [settlementType, setSettlementType] =
+ useState('IN_PROGRESS');
+ const [sortToggle, setSortToggle] = useState(false);
+ const theme = useTheme();
+
+ const handleSettlementTypeButtonClick = (type: SettlementType) => {
+ if (settlementType === type) {
+ return;
+ }
+ setSettlementType(type);
+ };
+
+ const handleSortOptionClick = () => {
+ setSortToggle(!sortToggle);
+ };
+
+ const settlementList = sortToggle
+ ? [...settlementListMock].reverse()
+ : settlementListMock;
+
+ return (
+
+
+ 정산 내역
+
+
+
+ handleSettlementTypeButtonClick('IN_PROGRESS')}
+ label="진행 중인 정산"
+ />
+ handleSettlementTypeButtonClick('COMPLETED')}
+ label="완료된 정산"
+ />
+
+ {/** @Todo Select 컴포넌트 개발 후 변경 */}
+
+
+ {settlementList.length > 0 && settlementType === 'IN_PROGRESS' && (
+
+ {settlementList.map((data) => (
+
+ ))}
+
+ )}
+ {settlementType === 'COMPLETED' && (
+
+
+
+ 아직 진행중인 정산이 없어요.
+
+
+ )}
+
+ );
+}
diff --git a/src/pages/paymentManagement/PaymentManagementPage.tsx b/src/pages/paymentManagement/PaymentManagementPage.tsx
new file mode 100644
index 00000000..9caf0550
--- /dev/null
+++ b/src/pages/paymentManagement/PaymentManagementPage.tsx
@@ -0,0 +1,9 @@
+function PaymentManagementPage() {
+ return (
+
+
Payment Management
+
+ );
+}
+
+export default PaymentManagementPage;
diff --git a/src/pages/paymentManagement/index.ts b/src/pages/paymentManagement/index.ts
new file mode 100644
index 00000000..346e8664
--- /dev/null
+++ b/src/pages/paymentManagement/index.ts
@@ -0,0 +1 @@
+export { default as PaymentManagementPage } from './PaymentManagementPage';
diff --git a/src/shared/config/route.ts b/src/shared/config/route.ts
index 67f54574..0a8061f8 100644
--- a/src/shared/config/route.ts
+++ b/src/shared/config/route.ts
@@ -4,6 +4,7 @@ export const ROUTE = {
login: '/login',
home: '/',
myLinks: '/my-links',
+ paymentManagement: '/payment-management',
my: '/my',
myEdit: '/my/edit',
createExpense: '/create-expense/:groupToken',
diff --git a/src/shared/ui/Chip/index.styles.ts b/src/shared/ui/Chip/index.styles.ts
index 597088e1..3b4d6caa 100644
--- a/src/shared/ui/Chip/index.styles.ts
+++ b/src/shared/ui/Chip/index.styles.ts
@@ -42,4 +42,5 @@ export const Container = styled.div`
${({ $size }) => chipSizes[$size]};
${({ $variant }) => chipVariants[$variant]};
white-space: nowrap;
+ cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
`;
diff --git a/src/shared/ui/Chip/index.tsx b/src/shared/ui/Chip/index.tsx
index 8f34b947..796e2beb 100644
--- a/src/shared/ui/Chip/index.tsx
+++ b/src/shared/ui/Chip/index.tsx
@@ -5,11 +5,12 @@ interface ChipProps {
label: string;
variant?: ChipVariant;
size?: ChipSize;
+ onClick?: () => void;
}
-function Chip({ label, variant = 'primary', size = 'md' }: ChipProps) {
+function Chip({ label, variant = 'primary', size = 'md', onClick }: ChipProps) {
return (
-
+
{label}
);