Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
131 changes: 76 additions & 55 deletions app/(dashboard)/_ui/strategies-item/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import Link from 'next/link'
import { useRouter } from 'next/navigation'

import classNames from 'classnames/bind'

import { PATH } from '@/shared/constants/path'
import useModal from '@/shared/hooks/custom/use-modal'
import { useAuthStore } from '@/shared/stores/use-auth-store'
import { StrategiesModel } from '@/shared/types/strategy-data'
import { Button } from '@/shared/ui/button'
import { LinkButton } from '@/shared/ui/link-button'
import SigninCheckModal from '@/shared/ui/modal/signin-check-modal'
import { formatNumber } from '@/shared/utils/format'

import AreaChart from './area-chart'
Expand All @@ -20,63 +24,80 @@ interface Props {
}

const StrategiesItem = ({ strategiesData: data, type = 'default' }: Props) => {
const router = useRouter()
const user = useAuthStore((state) => state.user)
const { isModalOpen, openModal, closeModal } = useModal()

const handleRouter = () => {
if (!user) {
openModal()
} else {
router.push(`${PATH.STRATEGIES}/${data.strategyId}`)
}
}

return (
<Link className={cx('container', type)} href={`/strategies/${data.strategyId}`}>
<StrategiesSummary
iconUrls={[data.tradeTypeIconUrl, ...(data.stockTypeInfo?.stockTypeIconUrls ?? [])]}
iconNames={[data.tradeTypeName, ...(data.stockTypeInfo?.stockTypeNames ?? [])]}
title={data.strategyName}
profile={{
traderImage: data.traderImgUrl,
nickname: data.nickname,
}}
subscriptionCount={data.subscriptionCount}
averageRating={data.averageRating}
totalReview={data.totalReviews}
/>
<AreaChart profitRateChartData={data.profitRateChartData} />
<div className={cx('mdd')}>
<p>{formatNumber(data.mdd)}</p>
</div>
<div className={cx('sm-score')}>
<p>{data.smScore}</p>
</div>
<div className={cx('profit')}>
<span>누적 수익률</span>
<p>{data.cumulativeProfitRate}%</p>
<span>최근 1년 수익률</span>
<p>{data.recentYearProfitLossRate ? data.recentYearProfitLossRate + '%' : '-'}</p>
</div>
{type === 'default' && (
<div className={cx('subscribe')}>
<Subscribe
subscriptionStatus={data.isSubscribed}
strategyId={data.strategyId}
traderName={data.nickname}
/>
<>
<button className={cx('container', type)} onClick={handleRouter}>
<StrategiesSummary
iconUrls={[data.tradeTypeIconUrl, ...(data.stockTypeInfo?.stockTypeIconUrls ?? [])]}
iconNames={[data.tradeTypeName, ...(data.stockTypeInfo?.stockTypeNames ?? [])]}
title={data.strategyName}
profile={{
traderImage: data.traderImgUrl,
nickname: data.nickname,
}}
subscriptionCount={data.subscriptionCount}
averageRating={data.averageRating}
totalReview={data.totalReviews}
/>
<AreaChart profitRateChartData={data.profitRateChartData} />
<div className={cx('mdd')}>
<p>{formatNumber(data.mdd)}</p>
</div>
)}
{type === 'my' && (
<>
<div className={cx('public')}>
<p>{data.isPublic === 'PUBLIC' ? '공개' : '비공개'}</p>
</div>
<div className={cx('manage-buttons')}>
<LinkButton
size="small"
variant="filled"
href={`/my/strategies/manage/${data.strategyId}`}
className={cx('manage-button')}
>
관리
</LinkButton>
<Button size="small" variant="outline" className={cx('manage-button')}>
삭제
</Button>
<div className={cx('sm-score')}>
<p>{data.smScore}</p>
</div>
<div className={cx('profit')}>
<span>누적 수익률</span>
<p>{data.cumulativeProfitRate.toFixed(2)}%</p>
<span>최근 1년 수익률</span>
<p>
{data.recentYearProfitLossRate ? data.recentYearProfitLossRate.toFixed(2) + '%' : '-'}
</p>
</div>
{type === 'default' && (
<div className={cx('subscribe')}>
<Subscribe
subscriptionStatus={data.isSubscribed}
strategyId={data.strategyId}
traderName={data.nickname}
/>
</div>
</>
)}
</Link>
)}
{type === 'my' && (
<>
<div className={cx('public')}>
<p>{data.isPublic === 'PUBLIC' ? '공개' : '비공개'}</p>
</div>
<div className={cx('manage-buttons')}>
<LinkButton
size="small"
variant="filled"
href={`/my/strategies/manage/${data.strategyId}`}
className={cx('manage-button')}
>
관리
</LinkButton>
<Button size="small" variant="outline" className={cx('manage-button')}>
삭제
</Button>
</div>
</>
)}
</button>
<SigninCheckModal isModalOpen={isModalOpen} onCloseModal={closeModal} />
</>
)
}

Expand Down
2 changes: 2 additions & 0 deletions app/(dashboard)/_ui/strategies-item/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
.title {
@include typo-h4;
@include ellipsis(1);
display: flex;
justify-content: flex-start;
}
.trader-profile {
display: flex;
Expand Down
50 changes: 13 additions & 37 deletions app/(dashboard)/_ui/strategies-item/subscribe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@

import { useEffect, useState } from 'react'

import { useRouter } from 'next/navigation'

import { BookmarkIcon, BookmarkOutlineIcon } from '@/public/icons'
import classNames from 'classnames/bind'

import { PATH } from '@/shared/constants/path'
import useModal from '@/shared/hooks/custom/use-modal'
import { useAuthStore } from '@/shared/stores/use-auth-store'
import SigninCheckModal from '@/shared/ui/modal/signin-check-modal'
import SubscribeWarningModal from '@/shared/ui/modal/subscribe-warning-modal'

import useGetSubscribe from '../../strategies/_hooks/query/use-get-subscribe'
Expand All @@ -26,18 +22,8 @@ interface Props {

const Subscribe = ({ strategyId, subscriptionStatus, traderName }: Props) => {
const [isSubscribed, setIsSubscribed] = useState(false)
const router = useRouter()
const user = useAuthStore((state) => state.user)
const {
isModalOpen: isSigninCheckModalOpen,
openModal: openSigninCheckModal,
closeModal: closeSigninCheckModal,
} = useModal()
const {
isModalOpen: isSubscribeWarningModal,
openModal: openSubscribeWarningModal,
closeModal: closeSubscribeWarningModal,
} = useModal()
const { isModalOpen, openModal, closeModal } = useModal()
const { mutate } = useGetSubscribe()

useEffect(() => {
Expand All @@ -47,37 +33,27 @@ const Subscribe = ({ strategyId, subscriptionStatus, traderName }: Props) => {
}, [subscriptionStatus])

const handleSubscribe = (e: React.MouseEvent) => {
e.preventDefault()
if (!user) {
openSigninCheckModal()
} else if (user?.nickname === traderName) {
openSubscribeWarningModal()
} else {
mutate(strategyId, {
onSuccess: () => setIsSubscribed(!isSubscribed),
})
if (user) {
e.stopPropagation()
if (user?.nickname === traderName) {
openModal()
} else {
e.preventDefault()
mutate(strategyId, {
onSuccess: () => setIsSubscribed(!isSubscribed),
})
}
}
}

const handleRoute = () => router.push(PATH.SIGN_IN)

return (
<>
<div className={cx('subscribe-icon')}>
<button onClick={handleSubscribe}>
<button onClick={(e) => handleSubscribe(e)}>
{isSubscribed ? <BookmarkIcon /> : <BookmarkOutlineIcon />}
</button>
</div>

<SigninCheckModal
isModalOpen={isSigninCheckModalOpen}
onCloseModal={closeSigninCheckModal}
onChange={handleRoute}
/>
<SubscribeWarningModal
isModalOpen={isSubscribeWarningModal}
onCloseModal={closeSubscribeWarningModal}
/>
<SubscribeWarningModal isModalOpen={isModalOpen} onCloseModal={closeModal} />
</>
)
}
Expand Down
3 changes: 2 additions & 1 deletion shared/hooks/custom/use-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ const useModal = () => {
const [isModalOpen, setIsModalOpen] = useState(false)

const openModal = () => setIsModalOpen(true)

const closeModal = (e?: React.MouseEvent) => {
if (e) {
e.preventDefault()
e.stopPropagation()
}
setIsModalOpen(false)
}
Expand Down
2 changes: 1 addition & 1 deletion shared/ui/modal/account-image-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface Props {

const AccountImageModal = ({ isOpen, title, url, onClose }: Props) => {
return (
<Modal isOpen={isOpen} message={title} className={cx('account')}>
<Modal isOpen={isOpen} message={title} className={cx('medium')}>
<div className={cx('image')}>
<Image src={url} alt={'imageData.title'} fill sizes="100%" />
</div>
Expand Down
15 changes: 12 additions & 3 deletions shared/ui/modal/signin-check-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import React from 'react'

import { useRouter } from 'next/navigation'

import { ModalAlertIcon } from '@/public/icons'
import classNames from 'classnames/bind'

import { PATH } from '@/shared/constants/path'

import Modal from '.'
import { Button } from '../button'
import styles from './styles.module.scss'
Expand All @@ -14,18 +18,23 @@ const cx = classNames.bind(styles)
interface Props {
isModalOpen: boolean
onCloseModal: () => void
onChange?: () => void
}

const SigninCheckModal = ({ isModalOpen, onCloseModal, onChange }: Props) => {
const SigninCheckModal = ({ isModalOpen, onCloseModal }: Props) => {
const router = useRouter()

const handleRouter = () => {
router.push(PATH.SIGN_IN)
}

return (
<Modal isOpen={isModalOpen} icon={ModalAlertIcon}>
<span className={cx('message')}>
로그인이 필요합니다. <br /> 로그인 하시겠습니까?
</span>
<div className={cx('two-button')}>
<Button onClick={onCloseModal}>아니오</Button>
<Button onClick={onChange} variant="filled" className={cx('button')}>
<Button onClick={handleRouter} variant="filled" className={cx('button')}>
</Button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion shared/ui/modal/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
}
}
}
&.account {
&.medium {
width: 600px;
}
&.big {
Expand Down