Skip to content

Commit

Permalink
Merge branch 'front/main' into feature/tradeAndMypage
Browse files Browse the repository at this point in the history
  • Loading branch information
dannysir authored Nov 27, 2024
2 parents e47dcee + 6df8d8a commit 177c64d
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 71 deletions.
35 changes: 35 additions & 0 deletions FE/src/components/News/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { NewsMockDataType } from './newsMockData.ts';

type CardWithImageProps = {
data: NewsMockDataType;
};
export default function Card({ data }: CardWithImageProps) {
return (
<a
className='flex cursor-pointer flex-col rounded-lg border p-4 transition-all hover:bg-juga-grayscale-50'
href={data.link}
target='_blank'
rel='noopener noreferrer'
>
<div className={'mb-2 flex w-full flex-row items-center justify-between'}>
<div className={'flex flex-row items-center gap-3'}>
<span className='rounded-full bg-juga-blue-10 px-2 py-0.5 text-xs text-juga-blue-50'>
증권
</span>
<h3 className='w-[320px] truncate text-left text-base font-medium'>
{data.title}
</h3>
</div>
<span className={'w-fit text-sm text-gray-500'}>{data.date}</span>
</div>
<div className='flex w-full items-center justify-between gap-4'>
<p className='w-96 truncate text-left text-sm text-juga-grayscale-500'>
{data.img}
</p>
<span className='whitespace-nowrap text-sm text-juga-grayscale-500'>
{data.publisher}
</span>
</div>
</a>
);
}
32 changes: 0 additions & 32 deletions FE/src/components/News/CardWithImage.tsx

This file was deleted.

12 changes: 0 additions & 12 deletions FE/src/components/News/CardWithoutImage.tsx

This file was deleted.

29 changes: 10 additions & 19 deletions FE/src/components/News/News.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
import CardWithImage from './CardWithImage.tsx';
import CardWithoutImage from './CardWithoutImage.tsx';
import { newsMockData, NewsMockDataType } from './newsMockData.ts';
import Card from './Card.tsx';
import { newsMockData } from './newsMockData.ts';

export default function News() {
return (
<div
className={'items-center, mt-7 flex w-full flex-col justify-center gap-3'}
>
<div className={'flex flex-row'}>
<div className={'text-left text-xl font-bold'}>주요 뉴스</div>
<div className='w-full'>
<div className='mb-4 flex items-center justify-between'>
<h2 className='text-xl font-bold'>주요 뉴스</h2>
</div>
<ul className='grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'>
{newsMockData.slice(0, 4).map((data: NewsMockDataType) => (
<CardWithImage data={data} key={data.title} />
))}
</ul>

<ul className='mt-5 grid grid-cols-2 gap-3'>
<CardWithoutImage />
<CardWithoutImage />
<CardWithoutImage />
<CardWithoutImage />
</ul>
<div className='grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-2'>
{newsMockData.slice(0, 4).map((news, index) => (
<Card key={index} data={news} />
))}
</div>
</div>
);
}
3 changes: 2 additions & 1 deletion FE/src/components/News/newsMockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const newsMockData: NewsMockDataType[] = [
{
publisher: '동아일보',
img: 'https://s.pstatic.net/dthumb.phinf/?src=%22https%3A%2F%2Fs.pstatic.net%2Fstatic%2Fnewsstand%2F2024%2F1125%2Farticle_img%2Fnew_main%2F9131%2F172557_001.jpg%22&type=nf312_208&service=navermain',
title: '청년 주거대책 발표...월세 지원 확대',
title:
'청년 주거대책 발표...월세 지원 확대https://s.pstatic.net/dthumb.phinf/?src=%22https%3A%2F%2Fs.pstatic.net%2Fstatic%2Fnewsstand%2F2024%2F1125%2Farticle_img%2Fnew_main%2F9131%2F172557_001.jpg%22&type=nf312_208&service=navermain',
date: '11월 03일 18:39 직접 편집',
link: 'https://www.donga.com/news/article/all/20241103/123456',
},
Expand Down
36 changes: 30 additions & 6 deletions FE/src/components/StocksDetail/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const padding: Padding = {
top: 20,
right: 80,
bottom: 10,
left: 20,
left: 40,
};

type StocksDeatailChartProps = {
Expand All @@ -46,7 +46,8 @@ export default function Chart({ code }: StocksDeatailChartProps) {
const upperChartY = useRef<HTMLCanvasElement>(null);
const lowerChartY = useRef<HTMLCanvasElement>(null);
const chartX = useRef<HTMLCanvasElement>(null);

// RAF 관리를 위한 ref
const rafRef = useRef<number>();
const [timeCategory, setTimeCategory] = useState<TiemCategory>('D');
const [charSizeConfig, setChartSizeConfig] = useState<ChartSizeConfigType>({
upperHeight: 0.5,
Expand All @@ -63,12 +64,14 @@ export default function Chart({ code }: StocksDeatailChartProps) {
y: 0,
});


const { data, isLoading } = useQuery(
['stocksChartData', code, timeCategory],
() => getStocksChartDataByCode(code, timeCategory),
{ staleTime: 1000 },
);


const handleMouseDown = useCallback((e: MouseEvent) => {
e.preventDefault();
setIsDragging(true);
Expand Down Expand Up @@ -118,10 +121,19 @@ export default function Chart({ code }: StocksDeatailChartProps) {

const getCanvasMousePosition = (e: MouseEvent) => {
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
setMousePosition({
x: (e.clientX - rect.left) * 2,
y: (e.clientY - rect.top) * 2,

if (rafRef.current) {
cancelAnimationFrame(rafRef.current);
}

rafRef.current = requestAnimationFrame(() => {
const rect = containerRef.current?.getBoundingClientRect();
if (!rect) return;

setMousePosition({
x: (e.clientX - rect.left) * 2,
y: (e.clientY - rect.top) * 2,
});
});
};

Expand All @@ -134,6 +146,9 @@ export default function Chart({ code }: StocksDeatailChartProps) {
return () => {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);
if (rafRef.current) {
cancelAnimationFrame(rafRef.current);
}
};
}, [isDragging, handleMouseDown, handleMouseUp, handleMouseMove]);
const setCanvasSize = useCallback(
Expand Down Expand Up @@ -224,6 +239,9 @@ export default function Chart({ code }: StocksDeatailChartProps) {
upperLabelNum,
padding,
0.1,
mousePosition,
upperChartCanvas.width,
upperChartCanvas.height,
);

drawLowerYAxis(
Expand All @@ -233,6 +251,10 @@ export default function Chart({ code }: StocksDeatailChartProps) {
lowerChartYCanvas.height - padding.top - padding.bottom,
lowerLabelNum,
padding,
mousePosition,
lowerChartCanvas.width,
lowerChartCanvas.height,
upperChartCanvas.height,
);

drawXAxis(
Expand All @@ -241,6 +263,8 @@ export default function Chart({ code }: StocksDeatailChartProps) {
chartXCanvas.width - padding.left - padding.right,
chartXCanvas.height,
padding,
mousePosition,
upperChartCanvas.height + lowerChartCanvas.height,
);

if (
Expand Down
40 changes: 40 additions & 0 deletions FE/src/utils/chart/drawLowerYAxis.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Padding, StockChartUnit } from '../../types.ts';
import { makeYLabels } from './makeLabels.ts';
import { MousePositionType } from '../../components/StocksDetail/Chart.tsx';

export const drawLowerYAxis = (
ctx: CanvasRenderingContext2D,
Expand All @@ -8,6 +9,10 @@ export const drawLowerYAxis = (
height: number,
labelsNum: number,
padding: Padding,
mousePosition: MousePositionType,
lowerChartWidth: number,
lowerChartHeight: number,
upperChartHeight: number,
) => {
ctx.clearRect(
0,
Expand All @@ -32,6 +37,41 @@ export const drawLowerYAxis = (
const formattedValue = formatNumber(label);
ctx.fillText(formattedValue, width / 2 + padding.left, yPos + padding.top);
});

if (
mousePosition.x > padding.left &&
mousePosition.x < lowerChartWidth &&
mousePosition.y > upperChartHeight &&
mousePosition.y < upperChartHeight + lowerChartHeight
) {
const relativeY =
mousePosition.y - padding.top - padding.bottom - upperChartHeight;

const valueRatio = 1 - relativeY / height;
const mouseValue = yMin + valueRatio * (yMax - yMin);

const boxPadding = 10;
const boxHeight = 30;
const valueText = formatNumber(Math.round(mouseValue));

ctx.font = '24px Arial';
const textWidth = ctx.measureText(valueText).width;

ctx.fillStyle = '#2175F3';
const boxX = width / 2 + padding.left - 12;
const boxY =
mousePosition.y - upperChartHeight - padding.bottom - boxHeight / 2;

ctx.fillRect(boxX, boxY, textWidth + boxPadding * 2, boxHeight);

ctx.fillStyle = '#FFF';
ctx.textAlign = 'center';
ctx.fillText(
valueText,
boxX + (textWidth + boxPadding * 2) / 2,
boxY + boxHeight / 2 + 2,
);
}
};

const formatNumber = (value: number) => {
Expand Down
37 changes: 37 additions & 0 deletions FE/src/utils/chart/drawUpperYAxis.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Padding, StockChartUnit } from '../../types.ts';
import { makeYLabels } from './makeLabels.ts';
import { MousePositionType } from '../../components/StocksDetail/Chart.tsx';

export const drawUpperYAxis = (
ctx: CanvasRenderingContext2D,
Expand All @@ -9,6 +10,9 @@ export const drawUpperYAxis = (
labelsNum: number,
padding: Padding,
weight: number = 0,
mousePosition: MousePositionType,
upperChartWidth: number,
upperChartHeight: number,
) => {
const values = data
.map((d) => [+d.stck_hgpr, +d.stck_lwpr, +d.stck_clpr, +d.stck_oprc])
Expand All @@ -35,4 +39,37 @@ export const drawUpperYAxis = (
const formattedValue = label.toLocaleString();
ctx.fillText(formattedValue, width / 2 + padding.left, yPos + padding.top);
});

if (
mousePosition.x > padding.left &&
mousePosition.x < upperChartWidth &&
mousePosition.y > padding.top &&
mousePosition.y < upperChartHeight
) {
const relativeY = mousePosition.y - padding.top;

const valueRatio = 1 - relativeY / height;
const mouseValue = yMin + valueRatio * (yMax - yMin);

const boxPadding = 10;
const boxHeight = 30;
const valueText = Math.round(mouseValue).toLocaleString();

ctx.font = '24px Arial';
const textWidth = ctx.measureText(valueText).width;

ctx.fillStyle = '#2175F3';
const boxX = width / 2 + padding.left - 12;
const boxY = mousePosition.y - boxHeight / 2;

ctx.fillRect(boxX, boxY, textWidth + boxPadding * 2, boxHeight);

ctx.fillStyle = '#FFF';
ctx.textAlign = 'center';
ctx.fillText(
valueText,
boxX + (textWidth + boxPadding * 2) / 2,
boxY + boxHeight / 2 + 2,
);
}
};
Loading

0 comments on commit 177c64d

Please sign in to comment.