diff --git a/app/(dashboard)/_ui/strategies-item/area-chart.tsx b/app/(dashboard)/_ui/strategies-item/area-chart.tsx
index 6c61330f..ff6f106c 100644
--- a/app/(dashboard)/_ui/strategies-item/area-chart.tsx
+++ b/app/(dashboard)/_ui/strategies-item/area-chart.tsx
@@ -33,8 +33,8 @@ const AreaChart = ({ profitRateChartData: data }: Props) => {
},
yAxis: {
visible: false,
- min: Math.min(...data.yAxis),
- max: Math.max(...data.yAxis),
+ min: Math.min(...data.profitRates),
+ max: Math.max(...data.profitRates),
},
legend: { enabled: false },
plotOptions: {
@@ -56,9 +56,9 @@ const AreaChart = ({ profitRateChartData: data }: Props) => {
series: [
{
type: 'areaspline',
- data: data.xAxis.map((x, idx) => ({
+ data: data.dates.map((x, idx) => ({
x: new Date(x).getTime(),
- y: data.yAxis[idx],
+ y: data.profitRates[idx],
})),
color: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
diff --git a/app/(dashboard)/_ui/strategies-item/index.tsx b/app/(dashboard)/_ui/strategies-item/index.tsx
index dc8f508d..8053e335 100644
--- a/app/(dashboard)/_ui/strategies-item/index.tsx
+++ b/app/(dashboard)/_ui/strategies-item/index.tsx
@@ -19,16 +19,16 @@ const StrategiesItem = ({ strategiesData: data }: Props) => {
return (
@@ -39,7 +39,7 @@ const StrategiesItem = ({ strategiesData: data }: Props) => {
누적 수익률
-
{data.cumulativeProfitLossRate}%
+
{data.cumulativeProfitRate}%
최근 1년 수익률
{data.recentYearProfitLossRate ? data.recentYearProfitLossRate + '%' : '-'}
diff --git a/app/(dashboard)/_ui/strategies-item/strategies-item.stories.tsx b/app/(dashboard)/_ui/strategies-item/strategies-item.stories.tsx
index bf64c563..639c7884 100644
--- a/app/(dashboard)/_ui/strategies-item/strategies-item.stories.tsx
+++ b/app/(dashboard)/_ui/strategies-item/strategies-item.stories.tsx
@@ -22,13 +22,16 @@ export const Primary = strategy.bind({})
Primary.args = {
strategiesData: [
{
- strategyId: '123',
- strategyName: '리치테크 FuturesDay',
- nickname: 'MACS',
- stockTypeIconUrls: [],
- stockTypeNames: [],
+ strategyId: 1,
+ strategyName: 'Dynamic ETF 전략',
+ traderImgUrl: '/images/trader1.png',
+ nickname: 'AlphaTrader',
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -39,27 +42,30 @@ Primary.args = {
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
- tradeTypeIconUrl: '',
- tradeTypeName: '',
- mdd: '-20,580,856',
- smScore: 60.6,
- cumulativeProfitLossRate: 120.1,
- recentYearProfitLossRate: 30.1,
- subscriptionCnt: 23,
+ tradeTypeIconUrl: '/images/trade.png',
+ tradeTypeName: '자동',
+ mdd: -15432567,
+ smScore: 72.1,
+ cumulativeProfitRate: 140.5,
+ recentYearProfitLossRate: 35.2,
+ subscriptionCount: 45,
+ averageRating: 4.9,
+ totalReviews: 34,
isSubscribed: true,
- averageRating: 4.8,
- totalReview: 12,
},
{
- strategyId: '12345',
- strategyName: 'ETF 레버리지/인버',
- nickname: '수밍',
- stockTypeIconUrls: [],
- stockTypeNames: [],
+ strategyId: 2,
+ strategyName: '고수익 ETF',
+ traderImgUrl: '/images/trader2.png',
+ nickname: 'BetaTrader',
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -70,18 +76,18 @@ Primary.args = {
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
- tradeTypeIconUrl: '',
- tradeTypeName: '',
- mdd: '-20,580,856',
- smScore: 60.6,
- cumulativeProfitLossRate: 120.1,
- recentYearProfitLossRate: 30.1,
- subscriptionCnt: 23,
+ tradeTypeIconUrl: '/images/trade.png',
+ tradeTypeName: '자동',
+ mdd: -12786543,
+ smScore: 65.4,
+ cumulativeProfitRate: 125.3,
+ recentYearProfitLossRate: 28.4,
+ subscriptionCount: 67,
+ averageRating: 4.6,
+ totalReviews: 19,
isSubscribed: false,
- averageRating: 4.8,
- totalReview: 12,
},
],
}
diff --git a/app/(dashboard)/my/_api/get-favorite-strategy-list.ts b/app/(dashboard)/my/_api/get-favorite-strategy-list.ts
new file mode 100644
index 00000000..b30fb6d9
--- /dev/null
+++ b/app/(dashboard)/my/_api/get-favorite-strategy-list.ts
@@ -0,0 +1,34 @@
+import { strategiesMockData } from '@/mocks/handlers/strategies'
+
+import axiosInstance from '@/shared/api/axios'
+import { StrategiesModel } from '@/shared/types/strategy-details-data'
+
+interface Props {
+ page: number
+ size: number
+}
+
+const getFavoriteStrategyList = async ({
+ page = 1,
+ size = 6,
+}: Props): Promise<{ strategiesData: StrategiesModel[]; totalPages: number } | undefined> => {
+ try {
+ const response = await axiosInstance.get(
+ `/api/my-strategies/subscribed?page=${page}&size=${size}`
+ )
+
+ const {
+ content: strategiesData,
+ totalPages,
+ }: { content: StrategiesModel[]; totalPages: number } = await response.data.result
+
+ return { strategiesData, totalPages }
+ } catch (err) {
+ console.error(err)
+ // throw new Error('구독한 전략 조회에 실패했습니다.')
+ // 임시 목데이터
+ return { strategiesData: strategiesMockData.filter((data) => data.isSubscribed), totalPages: 1 }
+ }
+}
+
+export default getFavoriteStrategyList
diff --git a/app/(dashboard)/my/_hooks/query/use-get-favorite-strategy-list.ts b/app/(dashboard)/my/_hooks/query/use-get-favorite-strategy-list.ts
new file mode 100644
index 00000000..7138a936
--- /dev/null
+++ b/app/(dashboard)/my/_hooks/query/use-get-favorite-strategy-list.ts
@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query'
+
+import getFavoriteStrategyList from '../../_api/get-favorite-strategy-list'
+
+interface Props {
+ page: number
+ size: number
+}
+
+const useGetFavoriteStrategyList = ({ page, size }: Props) => {
+ return useQuery({
+ queryKey: ['favoriteStrategies', page, size],
+ queryFn: () => getFavoriteStrategyList({ page, size }),
+ })
+}
+
+export default useGetFavoriteStrategyList
diff --git a/app/(dashboard)/my/favorites/_ui/favorite-strategy-list/index.tsx b/app/(dashboard)/my/favorites/_ui/favorite-strategy-list/index.tsx
new file mode 100644
index 00000000..54f251e9
--- /dev/null
+++ b/app/(dashboard)/my/favorites/_ui/favorite-strategy-list/index.tsx
@@ -0,0 +1,44 @@
+'use client'
+
+import ListHeader from '@/app/(dashboard)/_ui/list-header'
+import StrategiesItem from '@/app/(dashboard)/_ui/strategies-item'
+import classNames from 'classnames/bind'
+
+import { PATH } from '@/shared/constants/path'
+import { usePagination } from '@/shared/hooks/custom/use-pagination'
+import Pagination from '@/shared/ui/pagination'
+
+import useGetFavoriteStrategyList from '../../../_hooks/query/use-get-favorite-strategy-list'
+import styles from './styles.module.scss'
+
+const cx = classNames.bind(styles)
+
+const COUNT_PER_PAGE = 6
+
+const FavoriteStrategyList = () => {
+ const { page, handlePageChange } = usePagination({
+ basePath: PATH.FAVORITES,
+ pageSize: COUNT_PER_PAGE,
+ })
+
+ const { data } = useGetFavoriteStrategyList({ page, size: COUNT_PER_PAGE })
+
+ const strategiesData = data?.strategiesData || []
+ const totalPages = data?.totalPages || null
+
+ return (
+ <>
+
+
+ {strategiesData?.map((strategy) => (
+
+ ))}
+ {totalPages && (
+
+ )}
+
+ >
+ )
+}
+
+export default FavoriteStrategyList
diff --git a/app/(dashboard)/my/favorites/_ui/favorite-strategy-list/styles.module.scss b/app/(dashboard)/my/favorites/_ui/favorite-strategy-list/styles.module.scss
new file mode 100644
index 00000000..f5081c9f
--- /dev/null
+++ b/app/(dashboard)/my/favorites/_ui/favorite-strategy-list/styles.module.scss
@@ -0,0 +1,3 @@
+.pagination {
+ margin-bottom: 24px;
+}
diff --git a/app/(dashboard)/my/favorites/page.module.scss b/app/(dashboard)/my/favorites/page.module.scss
new file mode 100644
index 00000000..62016214
--- /dev/null
+++ b/app/(dashboard)/my/favorites/page.module.scss
@@ -0,0 +1,5 @@
+.container {
+ h1 {
+ margin: 80px 0 24px;
+ }
+}
diff --git a/app/(dashboard)/my/favorites/page.tsx b/app/(dashboard)/my/favorites/page.tsx
index 6d98eaf1..e64c2537 100644
--- a/app/(dashboard)/my/favorites/page.tsx
+++ b/app/(dashboard)/my/favorites/page.tsx
@@ -1,5 +1,23 @@
+import { Suspense } from 'react'
+
+import classNames from 'classnames/bind'
+
+import Title from '@/shared/ui/title'
+
+import FavoriteStrategyList from './_ui/favorite-strategy-list'
+import styles from './page.module.scss'
+
+const cx = classNames.bind(styles)
+
const MyFavoritesPage = () => {
- return <>>
+ return (
+
+
+ Loading...}>
+
+
+
+ )
}
export default MyFavoritesPage
diff --git a/app/(dashboard)/strategies/_api/get-strategies.ts b/app/(dashboard)/strategies/_api/get-strategies.ts
index 66dde4b0..b7b882c5 100644
--- a/app/(dashboard)/strategies/_api/get-strategies.ts
+++ b/app/(dashboard)/strategies/_api/get-strategies.ts
@@ -1,3 +1,4 @@
+import { strategiesMockData } from '@/mocks/handlers/strategies'
import axios from 'axios'
import { StrategiesModel } from '@/shared/types/strategy-details-data'
@@ -6,23 +7,24 @@ const getStrategiesData = async (
isReady: boolean,
page: number,
size: number
-): Promise<{ strategiesData: StrategiesModel[]; totalCount: number } | undefined> => {
- if (!isReady) return { strategiesData: [], totalCount: 0 }
+): Promise<{ strategiesData: StrategiesModel[]; totalPages: number } | undefined> => {
+ if (!isReady) return { strategiesData: [], totalPages: 0 }
try {
const response = await axios.get(`/api/strategies?page=${page}&size=${size}`)
if (!response.data) {
console.error('전략 목록 데이터 가져오기 실패')
- return { strategiesData: [], totalCount: 0 }
}
const {
- strategiesData,
- totalCount,
- }: { strategiesData: StrategiesModel[]; totalCount: number } = await response.data
+ content: strategiesData,
+ totalPages,
+ }: { content: StrategiesModel[]; totalPages: number } = await response.data.result
- return { strategiesData, totalCount }
+ return { strategiesData, totalPages }
} catch (err) {
console.error(err)
+ // 임시 목데이터
+ return { strategiesData: strategiesMockData, totalPages: 2 }
}
}
diff --git a/app/(dashboard)/strategies/_ui/strategy-list/index.tsx b/app/(dashboard)/strategies/_ui/strategy-list/index.tsx
index 7ae141ce..f7a65019 100644
--- a/app/(dashboard)/strategies/_ui/strategy-list/index.tsx
+++ b/app/(dashboard)/strategies/_ui/strategy-list/index.tsx
@@ -1,45 +1,32 @@
'use client'
-import { useEffect } from 'react'
-
-import { useRouter, useSearchParams } from 'next/navigation'
-
import ListHeader from '@/app/(dashboard)/_ui/list-header'
import StrategiesItem from '@/app/(dashboard)/_ui/strategies-item'
import classNames from 'classnames/bind'
+import { PATH } from '@/shared/constants/path'
+import { usePagination } from '@/shared/hooks/custom/use-pagination'
import { useMSWStore } from '@/shared/stores/msw'
import Pagination from '@/shared/ui/pagination'
import useGetStrategiesData from '../../_hooks/query/use-get-strategies-data'
import styles from './styles.module.scss'
-/* eslint-disable react-hooks/exhaustive-deps */
-
const cx = classNames.bind(styles)
const COUNT_PER_PAGE = 8
const StrategyList = () => {
- const searchParams = useSearchParams()
- const router = useRouter()
const isReady = useMSWStore((state) => state.isReady)
- const page = parseInt(searchParams?.get('page') || '1')
-
+ const { page, handlePageChange } = usePagination({
+ basePath: PATH.STRATEGIES,
+ pageSize: COUNT_PER_PAGE,
+ })
const { data } = useGetStrategiesData({ isReady, page, size: COUNT_PER_PAGE })
- useEffect(() => {
- if (!searchParams.size) {
- router.push(`/strategies?page=1&size=${COUNT_PER_PAGE}`)
- }
- }, [searchParams])
-
const strategiesData = data?.strategiesData || []
- const totalCount = data?.totalCount || null
+ const totalPages = data?.totalPages || null
- const handlePageChange = (page: number) => {
- router.push(`/strategies?page=${page}&size=${COUNT_PER_PAGE}`)
- }
return (
<>
@@ -47,12 +34,8 @@ const StrategyList = () => {
))}
- {totalCount && (
-
+ {totalPages && (
+
)}
>
diff --git a/mocks/handlers/strategies.ts b/mocks/handlers/strategies.ts
index 66854190..73c75794 100644
--- a/mocks/handlers/strategies.ts
+++ b/mocks/handlers/strategies.ts
@@ -1,14 +1,19 @@
import { HttpResponse, http } from 'msw'
-const strategiesData = [
+import { StrategiesModel } from '@/shared/types/strategy-details-data'
+
+export const strategiesMockData: StrategiesModel[] = [
{
- strategyId: '1',
+ strategyId: 1,
strategyName: 'Dynamic ETF 전략',
+ traderImgUrl: '/images/trader1.png',
nickname: 'AlphaTrader',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -19,27 +24,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-15,432,567',
+ mdd: -15432567,
smScore: 72.1,
- cumulativeProfitLossRate: 140.5,
+ cumulativeProfitRate: 140.5,
recentYearProfitLossRate: 35.2,
- subscriptionCnt: 45,
- isSubscribed: true,
+ subscriptionCount: 45,
averageRating: 4.9,
- totalReview: 34,
+ totalReviews: 34,
+ isSubscribed: true,
},
{
- strategyId: '2',
+ strategyId: 2,
strategyName: '고수익 ETF',
+ traderImgUrl: '/images/trader2.png',
nickname: 'BetaTrader',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -50,27 +58,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-12,786,543',
+ mdd: -12786543,
smScore: 65.4,
- cumulativeProfitLossRate: 125.3,
+ cumulativeProfitRate: 125.3,
recentYearProfitLossRate: 28.4,
- subscriptionCnt: 67,
- isSubscribed: false,
+ subscriptionCount: 67,
averageRating: 4.6,
- totalReview: 19,
+ totalReviews: 19,
+ isSubscribed: false,
},
{
- strategyId: '3',
+ strategyId: 3,
strategyName: 'Futures Pro',
+ traderImgUrl: '/images/trader3.png',
nickname: 'Gamma',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -81,27 +92,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-18,234,678',
+ mdd: -18234678,
smScore: 79.6,
- cumulativeProfitLossRate: 160.4,
+ cumulativeProfitRate: 160.4,
recentYearProfitLossRate: 40.1,
- subscriptionCnt: 89,
- isSubscribed: true,
+ subscriptionCount: 89,
averageRating: 4.7,
- totalReview: 45,
+ totalReviews: 45,
+ isSubscribed: true,
},
{
- strategyId: '4',
+ strategyId: 4,
strategyName: '월별 수익 전략',
+ traderImgUrl: '/images/trader4.png',
nickname: 'TraderX',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -112,27 +126,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-11,456,789',
+ mdd: -11456789,
smScore: 68.4,
- cumulativeProfitLossRate: 134.5,
+ cumulativeProfitRate: 134.5,
recentYearProfitLossRate: 32.7,
- subscriptionCnt: 34,
- isSubscribed: false,
+ subscriptionCount: 34,
averageRating: 4.5,
- totalReview: 29,
+ totalReviews: 29,
+ isSubscribed: false,
},
{
- strategyId: '5',
+ strategyId: 5,
strategyName: '리스크 관리 전략',
+ traderImgUrl: '/images/trader5.png',
nickname: 'DeltaOne',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -143,27 +160,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-14,345,678',
+ mdd: -14345678,
smScore: 62.3,
- cumulativeProfitLossRate: 120.3,
+ cumulativeProfitRate: 120.3,
recentYearProfitLossRate: 25.7,
- subscriptionCnt: 21,
- isSubscribed: true,
+ subscriptionCount: 21,
averageRating: 4.8,
- totalReview: 22,
+ totalReviews: 22,
+ isSubscribed: true,
},
{
- strategyId: '6',
+ strategyId: 6,
strategyName: 'Active LongShort',
+ traderImgUrl: '/images/trader6.png',
nickname: 'Hedger',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -174,27 +194,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-17,890,234',
+ mdd: -17890234,
smScore: 80.2,
- cumulativeProfitLossRate: 175.4,
+ cumulativeProfitRate: 175.4,
recentYearProfitLossRate: 45.8,
- subscriptionCnt: 120,
- isSubscribed: true,
+ subscriptionCount: 120,
averageRating: 4.9,
- totalReview: 52,
+ totalReviews: 52,
+ isSubscribed: true,
},
{
- strategyId: '7',
+ strategyId: 7,
strategyName: '안정적 성장 전략',
+ traderImgUrl: '/images/trader7.png',
nickname: 'SafeGrow',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -205,27 +228,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-13,567,890',
+ mdd: -13567890,
smScore: 70.1,
- cumulativeProfitLossRate: 138.2,
+ cumulativeProfitRate: 138.2,
recentYearProfitLossRate: 30.9,
- subscriptionCnt: 54,
- isSubscribed: false,
+ subscriptionCount: 54,
averageRating: 4.4,
- totalReview: 18,
+ totalReviews: 18,
+ isSubscribed: false,
},
{
- strategyId: '8',
+ strategyId: 8,
strategyName: 'High Risk High Return',
+ traderImgUrl: '/images/trader8.png',
nickname: 'RiskyTrader',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -236,27 +262,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-25,678,345',
+ mdd: -25678345,
smScore: 85.7,
- cumulativeProfitLossRate: 200.5,
+ cumulativeProfitRate: 200.5,
recentYearProfitLossRate: 50.4,
- subscriptionCnt: 76,
- isSubscribed: true,
+ subscriptionCount: 76,
averageRating: 4.7,
- totalReview: 37,
+ totalReviews: 37,
+ isSubscribed: true,
},
{
- strategyId: '9',
+ strategyId: 9,
strategyName: 'ETF 분산 투자',
+ traderImgUrl: '/images/trader9.png',
nickname: 'Diversifier',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -267,27 +296,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-9,876,543',
+ mdd: -9876543,
smScore: 58.3,
- cumulativeProfitLossRate: 112.4,
+ cumulativeProfitRate: 112.4,
recentYearProfitLossRate: 20.7,
- subscriptionCnt: 23,
- isSubscribed: false,
+ subscriptionCount: 23,
averageRating: 4.3,
- totalReview: 11,
+ totalReviews: 11,
+ isSubscribed: false,
},
{
- strategyId: '10',
+ strategyId: 10,
strategyName: 'Momentum 전략',
+ traderImgUrl: '/images/trader10.png',
nickname: 'MomentumKing',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -298,27 +330,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-18,456,789',
+ mdd: -18456789,
smScore: 75.6,
- cumulativeProfitLossRate: 165.3,
+ cumulativeProfitRate: 165.3,
recentYearProfitLossRate: 38.5,
- subscriptionCnt: 89,
- isSubscribed: true,
+ subscriptionCount: 89,
averageRating: 4.9,
- totalReview: 48,
+ totalReviews: 48,
+ isSubscribed: true,
},
{
- strategyId: '11',
+ strategyId: 11,
strategyName: '소형주 집중 전략',
+ traderImgUrl: '/images/trader11.png',
nickname: 'SmallCapPro',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -329,27 +364,30 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-14,345,678',
+ mdd: -14345678,
smScore: 69.4,
- cumulativeProfitLossRate: 130.7,
+ cumulativeProfitRate: 130.7,
recentYearProfitLossRate: 28.2,
- subscriptionCnt: 67,
- isSubscribed: false,
+ subscriptionCount: 67,
averageRating: 4.6,
- totalReview: 26,
+ totalReviews: 26,
+ isSubscribed: false,
},
{
- strategyId: '12',
+ strategyId: 12,
strategyName: 'Active Bond 전략',
+ traderImgUrl: '/images/trader12.png',
nickname: 'BondExpert',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
+ stockTypeInfo: {
+ stockTypeIconUrls: ['/images/stock.png'],
+ stockTypeNames: ['해외지수선물'],
+ },
profitRateChartData: {
- xAxis: [
+ dates: [
'2023-01-01',
'2023-01-02',
'2023-01-03',
@@ -360,268 +398,21 @@ const strategiesData = [
'2023-01-08',
'2023-01-09',
],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
+ profitRates: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
},
tradeTypeIconUrl: '/images/trade.png',
tradeTypeName: '자동',
- mdd: '-10,567,890',
+ mdd: -10567890,
smScore: 64.3,
- cumulativeProfitLossRate: 125.8,
+ cumulativeProfitRate: 125.8,
recentYearProfitLossRate: 27.4,
- subscriptionCnt: 42,
- isSubscribed: true,
- averageRating: 4.5,
- totalReview: 21,
- },
- {
- strategyId: '13',
- strategyName: 'Smart Index 전략',
- nickname: 'IndexGuru',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-16,543,678',
- smScore: 71.8,
- cumulativeProfitLossRate: 145.6,
- recentYearProfitLossRate: 32.7,
- subscriptionCnt: 54,
- isSubscribed: true,
- averageRating: 4.6,
- totalReview: 33,
- },
- {
- strategyId: '14',
- strategyName: 'MACD Pro',
- nickname: 'TrendRider',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-19,567,890',
- smScore: 77.5,
- cumulativeProfitLossRate: 175.8,
- recentYearProfitLossRate: 42.3,
- subscriptionCnt: 78,
- isSubscribed: true,
- averageRating: 4.8,
- totalReview: 49,
- },
- {
- strategyId: '15',
- strategyName: '균형 성장 전략',
- nickname: 'BalancedGrow',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-12,567,890',
- smScore: 62.8,
- cumulativeProfitLossRate: 118.5,
- recentYearProfitLossRate: 24.3,
- subscriptionCnt: 31,
- isSubscribed: false,
- averageRating: 4.2,
- totalReview: 16,
- },
- {
- strategyId: '16',
- strategyName: '단기 스윙 전략',
- nickname: 'SwingPro',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-22,345,678',
- smScore: 80.3,
- cumulativeProfitLossRate: 190.7,
- recentYearProfitLossRate: 45.8,
- subscriptionCnt: 85,
- isSubscribed: true,
- averageRating: 4.9,
- totalReview: 42,
- },
- {
- strategyId: '17',
- strategyName: '로우볼 전략',
- nickname: 'LowVolKing',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-8,345,678',
- smScore: 55.9,
- cumulativeProfitLossRate: 102.4,
- recentYearProfitLossRate: 18.5,
- subscriptionCnt: 18,
- isSubscribed: false,
- averageRating: 4.1,
- totalReview: 9,
- },
- {
- strategyId: '18',
- strategyName: '인컴 중심 전략',
- nickname: 'IncomeMaster',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-10,678,345',
- smScore: 60.2,
- cumulativeProfitLossRate: 115.9,
- recentYearProfitLossRate: 23.6,
- subscriptionCnt: 40,
- isSubscribed: true,
+ subscriptionCount: 42,
averageRating: 4.5,
- totalReview: 20,
- },
- {
- strategyId: '19',
- strategyName: '글로벌 주식 전략',
- nickname: 'GlobalTrader',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-17,890,567',
- smScore: 74.2,
- cumulativeProfitLossRate: 153.6,
- recentYearProfitLossRate: 36.4,
- subscriptionCnt: 72,
- isSubscribed: true,
- averageRating: 4.7,
- totalReview: 38,
- },
- {
- strategyId: '20',
- strategyName: '테크 성장 전략',
- nickname: 'TechGrow',
- stockTypeIconUrls: ['/images/stock.png'],
- stockTypeNames: ['해외지수선물'],
- profitRateChartData: {
- xAxis: [
- '2023-01-01',
- '2023-01-02',
- '2023-01-03',
- '2023-01-04',
- '2023-01-05',
- '2023-01-06',
- '2023-01-07',
- '2023-01-08',
- '2023-01-09',
- ],
- yAxis: [7.2, 5.2, 25, 12.8, 17.2, 11.4, 20, 16, 18],
- },
- tradeTypeIconUrl: '/images/trade.png',
- tradeTypeName: '자동',
- mdd: '-23,567,890',
- smScore: 88.3,
- cumulativeProfitLossRate: 210.9,
- recentYearProfitLossRate: 52.8,
- subscriptionCnt: 95,
+ totalReviews: 21,
isSubscribed: true,
- averageRating: 5.0,
- totalReview: 50,
},
]
+
export const strategiesHandlers = [
http.get('/api/strategies', ({ request }) => {
const url = new URL(request.url)
@@ -629,16 +420,19 @@ export const strategiesHandlers = [
const size = parseInt(url.searchParams.get('size') || '8')
if (!isNaN(page) && !isNaN(size)) {
- const croppedStrategiesData = strategiesData.slice(
+ const croppedStrategiesData = strategiesMockData.slice(
size * (page - 1),
size * (page - 1) + size
)
return HttpResponse.json({
- strategiesData: croppedStrategiesData,
- totalCount: strategiesData.length,
+ result: {
+ content: croppedStrategiesData,
+ totalPages: Math.ceil(strategiesMockData.length / size),
+ },
})
}
+
return HttpResponse.json(
{
isSuccess: false,
diff --git a/shared/hooks/custom/use-pagination.ts b/shared/hooks/custom/use-pagination.ts
new file mode 100644
index 00000000..8f37ce49
--- /dev/null
+++ b/shared/hooks/custom/use-pagination.ts
@@ -0,0 +1,36 @@
+'use client'
+
+import { useEffect } from 'react'
+
+import { useRouter, useSearchParams } from 'next/navigation'
+
+interface Props {
+ basePath: string
+ pageSize: number
+}
+
+interface UsePaginationReturnModel {
+ page: number
+ handlePageChange: (page: number) => void
+}
+
+export const usePagination = ({ basePath, pageSize }: Props): UsePaginationReturnModel => {
+ const searchParams = useSearchParams()
+ const router = useRouter()
+ const page = parseInt(searchParams?.get('page') || '1')
+
+ useEffect(() => {
+ if (!searchParams.size) {
+ router.push(`${basePath}?page=1&size=${pageSize}`)
+ }
+ }, [searchParams, router, basePath, pageSize])
+
+ const handlePageChange = (page: number) => {
+ router.push(`${basePath}?page=${page}&size=${pageSize}`)
+ }
+
+ return {
+ page,
+ handlePageChange,
+ }
+}
diff --git a/shared/types/strategy-details-data.ts b/shared/types/strategy-details-data.ts
index 4e78b564..10a42157 100644
--- a/shared/types/strategy-details-data.ts
+++ b/shared/types/strategy-details-data.ts
@@ -20,28 +20,30 @@ export interface MonthlyAnalysisModel {
}
export interface ProfitRateChartDataModel {
- xAxis: string[]
- yAxis: number[]
+ dates: string[]
+ profitRates: number[]
}
export interface StrategiesModel {
- strategyId: string
+ strategyId: number
strategyName: string
+ traderImgUrl?: string
nickname: string
- traderImage?: string
- stockTypeIconUrls: string[]
- stockTypeNames: string[]
- profitRateChartData: ProfitRateChartDataModel
+ stockTypeInfo: {
+ stockTypeIconUrls: string[]
+ stockTypeNames: string[]
+ }
tradeTypeIconUrl: string
tradeTypeName: string
- mdd: string
+ profitRateChartData: ProfitRateChartDataModel
+ mdd: number
smScore: number
- cumulativeProfitLossRate: number
+ cumulativeProfitRate: number
recentYearProfitLossRate?: number
- subscriptionCnt: number
- isSubscribed: boolean
+ subscriptionCount: number
averageRating: number
- totalReview: number
+ totalReviews: number
+ isSubscribed: boolean
}
export interface StrategyDetailsInformationModel {
diff --git a/shared/ui/header/_ui/header-links/index.tsx b/shared/ui/header/_ui/header-links/index.tsx
index 52658346..1757cebf 100644
--- a/shared/ui/header/_ui/header-links/index.tsx
+++ b/shared/ui/header/_ui/header-links/index.tsx
@@ -5,7 +5,7 @@ import { LinkButton } from '@/shared/ui/link-button'
const HeaderLinks = () => {
return (
-
+
대시보드