Skip to content

Commit 41cbd42

Browse files
authored
Merge pull request #157 from FC-DEV-FinalProject/feat/strategy-manage-150
[Feat] 나의 전략 페이지 퍼블리싱
2 parents c5b3725 + 3bdd8f3 commit 41cbd42

20 files changed

Lines changed: 287 additions & 69 deletions

File tree

app/(dashboard)/_ui/details-information/index.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ const cx = classNames.bind(styles)
1212

1313
interface Props {
1414
information: StrategyDetailsInformationModel
15+
type?: 'default' | 'my'
1516
}
1617

17-
const DetailsInformation = ({ information }: Props) => {
18+
const DetailsInformation = ({ information, type = 'default' }: Props) => {
1819
const percentageToArray = [
1920
{ percent: information.cumulativeProfitRate, label: '누적 수익률' },
2021
{ percent: information.maxDrawdownRate, label: '최대 자본 인하율' },
@@ -38,11 +39,13 @@ const DetailsInformation = ({ information }: Props) => {
3839
/>
3940
</div>
4041
<StrategyIntroduction content={information.strategyDescription} />
41-
<div className={cx('percentage-container')}>
42-
{percentageToArray.map((data) => (
43-
<Percentage key={data.label} percent={data.percent} label={data.label} />
44-
))}
45-
</div>
42+
{type === 'default' && (
43+
<div className={cx('percentage-container')}>
44+
{percentageToArray.map((data) => (
45+
<Percentage key={data.label} percent={data.percent} label={data.label} />
46+
))}
47+
</div>
48+
)}
4649
</>
4750
)
4851
}

app/(dashboard)/_ui/introduction/styles.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
background-color: $color-white;
44
border-radius: 5px;
55
padding: 20px;
6+
margin-bottom: 20px;
67
.title {
78
@include typo-b2;
89
margin-bottom: 15px;

app/(dashboard)/my/_api/get-my-strategy-list.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface StrategiesResponseModel {
1313

1414
export const getMyStrategyList = async ({ page = 1, size = 4 }: { page: number; size: number }) => {
1515
const response = await axiosInstance.get<StrategiesResponseModel>(
16-
`/api/my-strategies/page=${page}&size=${size}`
16+
`/api/my-strategies?page=${page}&size=${size}`
1717
)
1818
return response.data.result
1919
}
Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,65 @@
1-
const StrategyManagePage = () => {
2-
return <></>
3-
}
1+
'use client'
2+
3+
import DetailsInformation from '@/app/(dashboard)/_ui/details-information'
4+
import DetailsSideItem, {
5+
InformationModel,
6+
TitleType,
7+
} from '@/app/(dashboard)/_ui/details-side-item'
8+
import useGetDetailsInformationData from '@/app/(dashboard)/strategies/[strategyId]/_hooks/query/use-get-details-information-data'
9+
import AnalysisContainer from '@/app/(dashboard)/strategies/[strategyId]/_ui/analysis-container'
10+
import SubscriberItem from '@/app/(dashboard)/strategies/[strategyId]/_ui/subscriber-item'
11+
import SideContainer from '@/app/(dashboard)/strategies/_ui/side-container'
12+
import classNames from 'classnames/bind'
13+
14+
import { useMSWStore } from '@/shared/stores/msw'
15+
import { Button } from '@/shared/ui/button'
16+
import BackHeader from '@/shared/ui/header/back-header'
17+
import Title from '@/shared/ui/title'
18+
19+
import styles from './styles.module.scss'
20+
21+
const cx = classNames.bind(styles)
422

23+
export type InformationType = { title: TitleType; data: string | number } | InformationModel[]
24+
25+
const StrategyManagePage = ({ params }: { params: { strategyId: string } }) => {
26+
const isReady = useMSWStore((state) => state.isReady)
27+
const { data } = useGetDetailsInformationData({
28+
isReady,
29+
strategyId: params.strategyId,
30+
})
31+
32+
const { detailsSideData, detailsInformationData } = data || {}
33+
34+
const hasDetailsSideData = detailsSideData?.map((data) => {
35+
if (!Array.isArray(data)) return data.data !== undefined
36+
})
37+
38+
return (
39+
<div className={cx('container')}>
40+
<BackHeader label={'나의 전략으로 돌아가기'} />
41+
<div className={cx('header')}>
42+
<Title label={'나의 전략 관리'} />
43+
<Button size="small" variant="filled" className={cx('edit-button')}>
44+
정보 수정하기
45+
</Button>
46+
</div>
47+
<div className={cx('strategy-container')}>
48+
{detailsInformationData && (
49+
<DetailsInformation information={detailsInformationData} type="my" />
50+
)}
51+
<AnalysisContainer type="my" />
52+
<SideContainer hasButton={true}>
53+
<SubscriberItem subscribers={99} />
54+
{hasDetailsSideData?.[0] &&
55+
detailsSideData?.map((data, idx) => (
56+
<div key={`${data}_${idx}`}>
57+
<DetailsSideItem information={data} />
58+
</div>
59+
))}
60+
</SideContainer>
61+
</div>
62+
</div>
63+
)
64+
}
565
export default StrategyManagePage
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.container {
2+
position: relative;
3+
}
4+
5+
.header {
6+
display: flex;
7+
justify-content: space-between;
8+
9+
.edit-button {
10+
width: $strategy-sidebar-width;
11+
height: 40px;
12+
}
13+
}
14+
15+
.strategy-container {
16+
width: calc(100% - $strategy-sidebar-width);
17+
max-width: $max-width;
18+
padding-right: 10px;
19+
margin-top: -10px;
20+
}

app/(dashboard)/my/strategies/page.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
'use client'
2+
13
import { Suspense } from 'react'
24

5+
import { useRouter } from 'next/navigation'
6+
37
import classNames from 'classnames/bind'
48

9+
import { PATH } from '@/shared/constants/path'
10+
import { Button } from '@/shared/ui/button'
511
import Title from '@/shared/ui/title'
612

713
import ListHeader from '../../_ui/list-header'
@@ -11,9 +17,18 @@ import styles from './styles.module.scss'
1117
const cx = classNames.bind(styles)
1218

1319
const MyStrategiesPage = () => {
20+
const router = useRouter()
21+
const handleClick = () => {
22+
router.push(PATH.ADD_STRATEGY)
23+
}
1424
return (
1525
<div className={cx('container')}>
16-
<Title label={'나의 전략'} />
26+
<div className={cx('wrapper')}>
27+
<Title label={'나의 전략'} />
28+
<Button size="small" variant="filled" onClick={handleClick}>
29+
전략 등록하기
30+
</Button>
31+
</div>
1732
<ListHeader type="my" />
1833
<Suspense fallback={<div>Loading...</div>}>
1934
<MyStrategyList />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
.container {
22
margin-top: 80px;
33
}
4+
5+
.wrapper {
6+
display: flex;
7+
justify-content: space-between;
8+
align-items: center;
9+
padding-right: 20px;
10+
}

app/(dashboard)/strategies/[strategyId]/_ui/analysis-container/account-content.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Image from 'next/image'
44

55
import classNames from 'classnames/bind'
66

7+
import { Button } from '@/shared/ui/button'
78
import Pagination from '@/shared/ui/pagination'
89

910
import styles from './styles.module.scss'
@@ -21,9 +22,10 @@ interface Props {
2122
imagesData?: ImageDataModel[]
2223
currentPage: number
2324
onPageChange: (page: number) => void
25+
isEditable?: boolean
2426
}
2527

26-
const AccountContent = ({ imagesData, currentPage, onPageChange }: Props) => {
28+
const AccountContent = ({ imagesData, currentPage, onPageChange, isEditable = false }: Props) => {
2729
const croppedImagesData = imagesData?.slice(
2830
COUNT_PER_PAGE * (currentPage - 1),
2931
COUNT_PER_PAGE * (currentPage - 1) + COUNT_PER_PAGE
@@ -33,6 +35,16 @@ const AccountContent = ({ imagesData, currentPage, onPageChange }: Props) => {
3335

3436
return (
3537
<div className={cx('table-wrapper')}>
38+
{isEditable && (
39+
<div className={cx('edit-button-container')}>
40+
<Button size="small" className={cx('edit-button')} variant="filled">
41+
실계좌 이미지 업로드
42+
</Button>
43+
<Button size="small" className={cx('delete-button')} variant="outline">
44+
선택 삭제
45+
</Button>
46+
</div>
47+
)}
3648
{croppedImagesData && croppedImagesData.length !== 0 ? (
3749
<>
3850
<div className={cx('account-images-container', isTwoLines && 'line')}>

app/(dashboard)/strategies/[strategyId]/_ui/analysis-container/analysis-content.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,47 @@ interface AnalysisContentProps {
3636
analysisData: DailyAnalysisModel[] | MonthlyAnalysisModel[]
3737
currentPage: number
3838
onPageChange: (page: number) => void
39+
isEditable?: boolean
3940
}
4041

4142
const AnalysisContent = ({
4243
type,
4344
analysisData,
4445
currentPage,
4546
onPageChange,
47+
isEditable = false,
4648
}: AnalysisContentProps) => {
4749
const tableHeader = type === 'daily' ? DAILY_TABLE_HEADER : MONTHLY_TABLE_HEADER
4850

4951
return (
5052
<div className={cx('table-wrapper', 'analysis')}>
51-
<Button size="small" className={cx('excel-button')} variant="filled">
52-
엑셀 다운받기
53-
</Button>
53+
{!isEditable && (
54+
<Button size="small" className={cx('excel-button')} variant="filled">
55+
엑셀 다운받기
56+
</Button>
57+
)}
58+
{isEditable && (
59+
<div className={cx('button-container')}>
60+
<div className={cx('button-wrapper')}>
61+
<Button size="small" className={cx('upload-button')} variant="filled">
62+
엑셀 업로드
63+
</Button>
64+
<Button size="small" className={cx('upload-button')} variant="outline">
65+
직접 입력
66+
</Button>
67+
</div>
68+
<Button size="small" variant="filled">
69+
전체 삭제
70+
</Button>
71+
</div>
72+
)}
73+
5474
<VerticalTable
5575
tableHead={tableHeader}
5676
tableBody={analysisData}
5777
currentPage={currentPage}
5878
countPerPage={COUNT_PER_PAGE}
79+
isEditable={isEditable}
5980
/>
6081
<Pagination
6182
currentPage={currentPage}

app/(dashboard)/strategies/[strategyId]/_ui/analysis-container/index.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ const cx = classNames.bind(styles)
1616

1717
type OptionsType = (typeof YAXIS_OPTIONS)[keyof typeof YAXIS_OPTIONS]
1818

19-
const AnalysisContainer = () => {
19+
interface Props {
20+
type?: 'default' | 'my'
21+
}
22+
23+
const AnalysisContainer = ({ type = 'default' }: Props) => {
2024
const [firstValue, setFirstValue] = useState<OptionsType>('잔고')
2125
const [secondValue, setSecondValue] = useState<OptionsType>('잔고')
2226

@@ -30,27 +34,30 @@ const AnalysisContainer = () => {
3034
return (
3135
<div className={cx('container')}>
3236
<div className={cx('analysis-header')}>
33-
<p>분석</p>
34-
<div>
35-
<Select
36-
size="large"
37-
options={options}
38-
value={firstValue}
39-
onChange={(newValue) => setFirstValue(newValue as OptionsType)}
40-
/>
41-
<Select
42-
size="large"
43-
options={options}
44-
value={secondValue}
45-
onChange={(newValue) => setSecondValue(newValue as OptionsType)}
46-
/>
47-
</div>
37+
<p className={cx({ my: type === 'my' })}>분석</p>
38+
{type === 'default' && (
39+
<div>
40+
<Select
41+
size="large"
42+
options={options}
43+
value={firstValue}
44+
onChange={(newValue) => setFirstValue(newValue as OptionsType)}
45+
/>
46+
<Select
47+
size="large"
48+
options={options}
49+
value={secondValue}
50+
onChange={(newValue) => setSecondValue(newValue as OptionsType)}
51+
/>
52+
</div>
53+
)}
4854
</div>
49-
<div className={cx('chart-wrapper')}>
50-
<AnalysisChart analysisChartData={analysisChartData} />
51-
</div>
52-
53-
<TabsWithTable />
55+
{type === 'default' && (
56+
<div className={cx('chart-wrapper')}>
57+
<AnalysisChart analysisChartData={analysisChartData} />
58+
</div>
59+
)}
60+
<TabsWithTable isEditable={type === 'my' ? true : false} />
5461
</div>
5562
)
5663
}

0 commit comments

Comments
 (0)