Skip to content

Commit

Permalink
Feature/#181 - 주식 메인페이지 UI 구현 (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
baegyeong authored Nov 18, 2024
2 parents b3ff70d + ea31cb8 commit b5d2543
Show file tree
Hide file tree
Showing 10 changed files with 430 additions and 2 deletions.
3 changes: 3 additions & 0 deletions packages/frontend/src/assets/down-arrow.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 packages/frontend/src/components/layouts/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const Layout = () => {
return (
<div className="flex">
<Sidebar />
<main className="ml-20 flex-1 px-48 py-16">
<main className="ml-20 flex-1 px-60 py-16">
<Outlet />
</main>
</div>
Expand Down
25 changes: 25 additions & 0 deletions packages/frontend/src/mocks/market.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"data": [
{
"name": "코스피",
"price": 2591.03,
"change": -26.77,
"changePercent": -1.0,
"trend": "down"
},
{
"name": "코스닥",
"price": 738.49,
"change": 9.4,
"changePercent": 0.1,
"trend": "up"
},
{
"name": "달러환율",
"price": 1382.2,
"change": -26.77,
"changePercent": -1.0,
"trend": "down"
}
]
}
184 changes: 184 additions & 0 deletions packages/frontend/src/mocks/stock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
{
"data": [
{
"id": 1,
"name": "삼성전자",
"currentPrice": 82600,
"changeRate": 3200,
"changeRatePercent": 5.9,
"tradingVolume": 12850000,
"tradingValue": 1061410000000
},
{
"id": 2,
"name": "Alphabet Inc.",
"currentPrice": 2750.5,
"changeRate": -6500,
"changeRatePercent": 3.6,
"tradingVolume": 500000,
"tradingValue": 1377500000
},
{
"id": 3,
"name": "Amazon.com Inc.",
"currentPrice": 3400.1,
"changeRate": -1000,
"changeRatePercent": 2.5,
"tradingVolume": 300000,
"tradingValue": 1020300000
},
{
"id": 4,
"name": "애플",
"currentPrice": 145.3,
"changeRate": 2.5,
"changeRatePercent": 1.8,
"tradingVolume": 10000000,
"tradingValue": 1453000000
},
{
"id": 5,
"name": "테슬라",
"currentPrice": 680.4,
"changeRate": 15.2,
"changeRatePercent": 2.3,
"tradingVolume": 1200000,
"tradingValue": 816480000
},
{
"id": 6,
"name": "마이크로소프트",
"currentPrice": 300.1,
"changeRate": 4.0,
"changeRatePercent": 1.3,
"tradingVolume": 8000000,
"tradingValue": 2400800000
},
{
"id": 7,
"name": "페이스북",
"currentPrice": 345.8,
"changeRate": -10.5,
"changeRatePercent": -3.0,
"tradingVolume": 600000,
"tradingValue": 207480000
},
{
"id": 8,
"name": "넷플릭스",
"currentPrice": 525.4,
"changeRate": 20.6,
"changeRatePercent": 4.0,
"tradingVolume": 900000,
"tradingValue": 473860000
},
{
"id": 9,
"name": "IBM",
"currentPrice": 135.7,
"changeRate": -5.2,
"changeRatePercent": -3.7,
"tradingVolume": 200000,
"tradingValue": 27140000
},
{
"id": 10,
"name": "인텔",
"currentPrice": 55.5,
"changeRate": 1.0,
"changeRatePercent": 1.8,
"tradingVolume": 4000000,
"tradingValue": 222000000
},
{
"id": 11,
"name": "스타벅스",
"currentPrice": 95.0,
"changeRate": 1.5,
"changeRatePercent": 1.6,
"tradingVolume": 1500000,
"tradingValue": 142500000
},
{
"id": 12,
"name": "코카콜라",
"currentPrice": 60.2,
"changeRate": -0.3,
"changeRatePercent": -0.5,
"tradingVolume": 3000000,
"tradingValue": 180600000
},
{
"id": 13,
"name": "존슨앤드존슨",
"currentPrice": 165.0,
"changeRate": 3.0,
"changeRatePercent": 1.8,
"tradingVolume": 800000,
"tradingValue": 132000000
},
{
"id": 14,
"name": "월마트",
"currentPrice": 140.5,
"changeRate": 0.5,
"changeRatePercent": 0.4,
"tradingVolume": 2000000,
"tradingValue": 281000000
},
{
"id": 15,
"name": "디즈니",
"currentPrice": 175.0,
"changeRate": -2.0,
"changeRatePercent": -1.1,
"tradingVolume": 400000,
"tradingValue": 70000000
},
{
"id": 16,
"name": "NVIDIA",
"currentPrice": 220.3,
"changeRate": 6.0,
"changeRatePercent": 2.8,
"tradingVolume": 1500000,
"tradingValue": 330450000
},
{
"id": 17,
"name": "Qualcomm",
"currentPrice": 130.8,
"changeRate": 1.8,
"changeRatePercent": 1.4,
"tradingVolume": 900000,
"tradingValue": 117720000
},
{
"id": 18,
"name": "Adobe",
"currentPrice": 540.2,
"changeRate": 10.5,
"changeRatePercent": 2.0,
"tradingVolume": 300000,
"tradingValue": 162060000
},
{
"id": 19,
"name": "Salesforce",
"currentPrice": 270.0,
"changeRate": -3.0,
"changeRatePercent": -1.1,
"tradingVolume": 200000,
"tradingValue": 54000000
},
{
"id": 20,
"name": "PayPal",
"currentPrice": 90.5,
"changeRate": 2.0,
"changeRatePercent": 2.3,
"tradingVolume": 1000000,
"tradingValue": 90500000
}
]
}
60 changes: 60 additions & 0 deletions packages/frontend/src/pages/stocks/StockRankingTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Link } from 'react-router-dom';
import DownArrow from '@/assets/down-arrow.svg?react';
import stockData from '@/mocks/stock.json';
import { cn } from '@/utils/cn';

export const StockRankingTable = () => {
return (
<div className="rounded-md bg-white px-6 shadow">
<table className="w-full border-collapse">
<colgroup>
<col className="w-1/4" />
<col className="w-1/5" />
<col className="w-1/5" />
<col className="w-1/5" />
<col className="w-1/5" />
</colgroup>
<thead>
<tr className="display-medium12 text-dark-gray border-light-gray border-b text-left [&>*]:p-4 [&>*]:py-3">
<th>종목</th>
<th className="text-right">현재가</th>
<th className="flex items-center justify-end gap-1 text-right">
<p> 등락률</p>
<DownArrow className="cursor-pointer" />
</th>
<th className="text-right">거래대금</th>
<th className="text-right">거래량</th>
</tr>
</thead>
<tbody>
{stockData.data.map((stock, index) => (
<tr
key={stock.id}
className="display-medium14 text-dark-gray text-right [&>*]:p-4"
>
<td className="flex gap-6 text-left">
<span className="text-gray">{index + 1}</span>
<Link
to={`${stock.id}`}
className="display-bold14 hover:text-orange cursor-pointer text-ellipsis hover:underline"
>
{stock.name}
</Link>
</td>
<td>{stock.currentPrice.toLocaleString()}</td>
<td
className={cn(stock.changeRate >= 0 ? 'text-red' : 'text-blue')}
>
{stock.changeRate >= 0 && '+'}
{stock.changeRate.toLocaleString()}원 ({stock.changeRatePercent}
%)
</td>
<td>{stock.tradingVolume.toLocaleString()}</td>
<td>{stock.tradingValue.toLocaleString()}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
72 changes: 72 additions & 0 deletions packages/frontend/src/pages/stocks/Stocks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { StockIndexCard } from './components/StockIndexCard';
import { StockInfoCard } from './components/StockInfoCard';
import { StockRankingTable } from './StockRankingTable';
import marketData from '@/mocks/market.json';
import stockData from '@/mocks/stock.json';

const TOP_VIEW = 5;

export const Stocks = () => {
const kospi = marketData.data.filter((value) => value.name === '코스피')[0];
const kosdaq = marketData.data.filter((value) => value.name === '코스닥')[0];
const rateOfExchange = marketData.data.filter(
(value) => value.name === '달러환율',
)[0];

return (
<main className="flex flex-col gap-16">
<h1 className="display-bold24">오늘의 투자</h1>
<article>
<h2 className="display-bold16 text-dark-gray mb-5">
지금 시장, 이렇게 움직이고 있어요.
</h2>
<div className="grid w-fit grid-cols-3 gap-5">
<StockIndexCard
price={kospi.price}
change={kospi.change}
changePercent={kospi.changePercent}
>
코스피
</StockIndexCard>
<StockIndexCard
price={kosdaq.price}
change={kosdaq.change}
changePercent={kosdaq.changePercent}
>
코스닥
</StockIndexCard>
<StockIndexCard
price={rateOfExchange.price}
change={rateOfExchange.change}
changePercent={rateOfExchange.changePercent}
>
달러환율
</StockIndexCard>
</div>
</article>
<article>
<h2 className="display-bold16 text-dark-gray mb-5">
이 종목은 어떠신가요?
</h2>
<div className="grid w-fit grid-cols-5 gap-5">
{stockData.data.slice(0, TOP_VIEW).map((stock, index) => (
<StockInfoCard
key={stock.id}
index={index}
name={stock.name}
currentPrice={stock.currentPrice}
changeRate={stock.changeRate}
changeRatePercent={stock.changeRatePercent}
/>
))}
</div>
</article>
<article>
<h2 className="display-bold16 text-dark-gray mb-5">
지금 가장 활발한 종목이에요.
</h2>
<StockRankingTable />
</article>
</main>
);
};
32 changes: 32 additions & 0 deletions packages/frontend/src/pages/stocks/components/StockIndexCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ReactNode } from 'react';
import { cn } from '@/utils/cn';

interface StockIndexCardProps {
children: ReactNode;
price: number;
change: number;
changePercent: number;
}

export const StockIndexCard = ({
children,
price,
change,
changePercent,
}: StockIndexCardProps) => {
return (
<div className="flex w-full cursor-pointer flex-col gap-2 rounded-md bg-white py-4 pl-5 pr-28 shadow transition-all duration-300 hover:scale-110">
<p className="display-medium16">{children}</p>
<p className="display-bold24 text-dark-gray">{price}</p>
<p
className={cn(
'display-medium14',
changePercent >= 0 ? 'text-red' : 'text-blue',
)}
>
{changePercent >= 0 ? '▲' : '▼'}
{change}({changePercent})
</p>
</div>
);
};
Loading

0 comments on commit b5d2543

Please sign in to comment.