Skip to content

Commit 25e8519

Browse files
authored
Merge pull request #163 from FunD-StockProject/develop
반응형 추가
2 parents 39159da + 615c65a commit 25e8519

File tree

12 files changed

+308
-38
lines changed

12 files changed

+308
-38
lines changed

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<meta charset="UTF-8" />
1212
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
1313
<meta name="description" content="Human Zipyo" />
14+
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width" />
1415
<title>인간지표</title>
1516
</head>
1617
<body>

src/components/CardList/CardList.tsx

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ScrollMenu, VisibilityContext, publicApiType } from 'react-horizontal-s
33
import { CardInterface } from '@ts/Interfaces';
44
import { StockType } from '@ts/Types';
55
import { useQueryComponent } from '@hooks/useQueryComponent';
6+
import MobileStockCardItem from '@components/MobileStockCard/MobileStockCard';
67
import StockCardItem from '@components/StockCard/StockCard';
78
import ScoreSlotMachine from '@components/StockSlotMachine/StockSlotMachine';
89
import { StockFetchQuery } from '@controllers/query';
@@ -24,8 +25,17 @@ const CardList = ({
2425
const containerRef = useRef<HTMLDivElement>(null);
2526
const [didMount, setDidMount] = useState<boolean>(false);
2627
const [width, setWidth] = useState<number>(0);
27-
2828
const [curStocks, suspend] = useQueryComponent({ query: StockFetchQuery(name, index) });
29+
const isMobile = width < 768;
30+
31+
useEffect(() => {
32+
if (isMobile && curStocks?.length > 1) {
33+
setTimeout(() => {
34+
apiRef.current.scrollToItem(apiRef.current.getItemByIndex(1));
35+
window.scrollTo(0, 0);
36+
}, 1000);
37+
}
38+
}, [isMobile, curStocks]);
2939

3040
useEffect(() => {
3141
setDidMount(true);
@@ -35,7 +45,6 @@ const CardList = ({
3545
useEffect(() => {
3646
if (!didMount) return;
3747
if (!containerRef.current) return;
38-
3948
observer.observe(containerRef.current);
4049
}, [didMount]);
4150

@@ -61,6 +70,23 @@ const CardList = ({
6170
apiRef.current.scrollToItem(apiRef.current.getItemByIndex(idx));
6271
};
6372

73+
const renderMobileStocks = (curStocks: CardInterface[]) => {
74+
if (isHot) {
75+
return curStocks.map(renderStocks);
76+
}
77+
78+
const chunkCount = Math.ceil(curStocks.length / 3);
79+
const verticalStocks = Array.from({ length: chunkCount }, (_, idx) => curStocks.slice(idx * 3, idx * 3 + 3));
80+
81+
return verticalStocks.map((verticalStock) => (
82+
<CardListItemContainer key={`${name}_${verticalStock[0].stockId}`} width={width ?? 0}>
83+
{verticalStock.map((el) => (
84+
<MobileStockCardItem key={`${name}_${el.stockId}`} score={el.score} name={el.symbolName} delta={el.diff} />
85+
))}
86+
</CardListItemContainer>
87+
));
88+
};
89+
6490
return (
6591
<NoScrollbar ref={containerRef}>
6692
{suspend ||
@@ -70,17 +96,20 @@ const CardList = ({
7096
RightArrow={<ScrollArrow direction="right" />}
7197
apiRef={apiRef}
7298
>
73-
{curStocks.map(renderStocks)}
99+
{isMobile ? renderMobileStocks(curStocks) : curStocks.map(renderStocks)}
74100
</ScrollMenu>
75101
))}
76102
{!isHot && (
77103
<ItemButtonContainer>
78104
{curStocks &&
79-
curStocks.map((stock: CardInterface, idx: number) => (
80-
<ItemButton key={stock.stockId} onClick={() => handleButtonClick(idx)}>
81-
{stock.symbolName}
82-
</ItemButton>
83-
))}
105+
curStocks.map((stock: CardInterface, idx: number) => {
106+
if (isMobile && idx % 3) return;
107+
return (
108+
<ItemButton key={stock.stockId} onClick={() => handleButtonClick(idx)}>
109+
{stock.symbolName}
110+
</ItemButton>
111+
);
112+
})}
84113
</ItemButtonContainer>
85114
)}
86115
</NoScrollbar>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import styled from '@emotion/styled';
2+
import { ImgDiv } from '@components/Common/Common';
3+
import { theme } from '@styles/themes';
4+
5+
const MobileStockCardItemContainer = styled.div({
6+
boxSizing: 'border-box',
7+
overflow: 'hidden',
8+
display: 'flex',
9+
flexDirection: 'row', // 가로 정렬로 변경
10+
alignItems: 'center',
11+
// justifyContent: 'space-between', // 양쪽 정렬
12+
gap: '1em',
13+
borderRadius: '18px',
14+
padding: '1.6em',
15+
background: theme.colors.grayscale100,
16+
cursor: 'pointer',
17+
width: '100%',
18+
marginBottom: '12px',
19+
});
20+
21+
const MobileStockCardItemTitle = styled.div({
22+
display: 'flex',
23+
flexDirection: 'column',
24+
alignItems: 'flex-start',
25+
gap: '2em',
26+
fontSize: '1.0em',
27+
fontWeight: '700',
28+
color: 'white',
29+
lineHeight: '1.2',
30+
width: '100%',
31+
overflow: 'hidden',
32+
});
33+
34+
const MobileStockCardItemText = styled.div({
35+
whiteSpace: 'nowrap',
36+
textOverflow: 'ellipsis',
37+
overflow: 'hidden',
38+
width: '100%',
39+
fontSize: '1.2em',
40+
});
41+
42+
const MobileStockCardItemScore = styled.div(({ delta }: { delta: number }) => ({
43+
display: 'flex',
44+
alignItems: 'center',
45+
justifyContent: 'center',
46+
gap: '0.4em',
47+
color: delta > 0 ? theme.colors.red : theme.colors.blue,
48+
fontSize: '1.6em',
49+
}));
50+
51+
const MobileStockCardItemDeltaScore = styled.div(({ delta }: { delta: number }) => ({
52+
display: 'flex',
53+
alignItems: 'center',
54+
fontSize: '0.8em',
55+
gap: '4px',
56+
background: 'white',
57+
padding: '0 0.4em',
58+
borderRadius: '35px',
59+
60+
['svg']: {
61+
height: '0.5em',
62+
width: 'auto',
63+
fill: delta > 0 ? theme.colors.red : theme.colors.blue,
64+
},
65+
}));
66+
67+
const MobileScoreImage = styled(ImgDiv)({
68+
width: '40%', // 크기 조정
69+
borderRadius: '7px',
70+
});
71+
72+
export {
73+
MobileStockCardItemContainer,
74+
MobileStockCardItemTitle,
75+
MobileStockCardItemText,
76+
MobileStockCardItemScore,
77+
MobileStockCardItemDeltaScore,
78+
MobileScoreImage,
79+
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useNavigate } from 'react-router-dom';
2+
import { scoreToImage } from '@utils/ScoreConvert';
3+
import { webPath } from '@router/index';
4+
import DownSVG from '@assets/icons/down.svg?react';
5+
import UpSVG from '@assets/icons/up.svg?react';
6+
import {
7+
MobileScoreImage,
8+
MobileStockCardItemContainer,
9+
MobileStockCardItemDeltaScore,
10+
MobileStockCardItemScore,
11+
MobileStockCardItemText,
12+
MobileStockCardItemTitle,
13+
} from './MobileStockCard.Style';
14+
15+
const MobileStockCardItem = ({ name, score, delta }: { name: string; score: number; delta: number }) => {
16+
const navigate = useNavigate();
17+
const scoreImage = scoreToImage(score);
18+
const deltaSVG = delta > 0 ? <UpSVG /> : <DownSVG />;
19+
20+
const handleClick = () => {
21+
navigate(webPath.search(), { state: { stockName: name } });
22+
};
23+
24+
return (
25+
<MobileStockCardItemContainer onClick={handleClick}>
26+
<MobileScoreImage src={scoreImage} />
27+
<MobileStockCardItemTitle>
28+
<MobileStockCardItemText>{name}</MobileStockCardItemText>
29+
<MobileStockCardItemScore delta={delta}>
30+
{score}{' '}
31+
<MobileStockCardItemDeltaScore delta={delta}>
32+
{Math.abs(delta)}
33+
{deltaSVG}
34+
</MobileStockCardItemDeltaScore>
35+
</MobileStockCardItemScore>
36+
</MobileStockCardItemTitle>
37+
</MobileStockCardItemContainer>
38+
);
39+
};
40+
41+
export default MobileStockCardItem;

src/components/PopUp/AntVoicePopUp.style.ts

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import styled from '@emotion/styled';
2-
import { theme, themeColor } from '@styles/themes';
2+
import { media, theme, themeColor } from '@styles/themes';
33

44
const PopUpContainer = styled('div')({
55
display: 'flex',
@@ -16,6 +16,13 @@ const PopUpContainer = styled('div')({
1616
boxShadow: '0 4px 10px rgba(0, 0, 0, 0.2)',
1717
zIndex: 1000,
1818
fontFamily: 'Pretendard',
19+
20+
[media[0]]: {
21+
width: '90%',
22+
['svg']: {
23+
width: '30%',
24+
},
25+
},
1926
});
2027

2128
const PopUpTitle = styled('div')({
@@ -30,10 +37,15 @@ const PopUpTitle = styled('div')({
3037
height: '36px',
3138
width: 'auto',
3239
},
40+
41+
[media[0]]: {
42+
fontSize: '24px',
43+
padding: '32px 32px 0 32px',
44+
},
3345
});
3446

3547
const PopUpContent = styled('div')({
36-
padding: '0 48px 32px 32px',
48+
padding: '0 32px 32px 32px',
3749
display: 'flex',
3850
flexDirection: 'column',
3951
gap: '16px',
@@ -46,7 +58,6 @@ const PopUpImage = styled('ul')({
4658
display: 'flex',
4759
justifyContent: 'space-between',
4860
alignItems: 'center',
49-
// gap: '8px',
5061
padding: 0,
5162
listStyle: 'none',
5263

@@ -73,6 +84,50 @@ const PopUpImage = styled('ul')({
7384
width: '100%',
7485
},
7586
},
87+
[media[0]]: {
88+
['div']: {
89+
height: '120px',
90+
['img']: {
91+
height: '100%',
92+
width: '100%',
93+
borderRadius: '8px',
94+
},
95+
},
96+
},
97+
});
98+
99+
const PopUpDetailWord = styled('p')({
100+
display: 'flex',
101+
flexDirection: 'column',
102+
alignItems: 'center',
103+
margin: 0,
104+
105+
['span:first-of-type']: {
106+
fontSize: '1.5em',
107+
textAlign: 'center',
108+
lineHeight: '1.4',
109+
},
110+
111+
['span:last-of-type']: {
112+
color: theme.colors.grayscale60,
113+
fontSize: '0.8em',
114+
textAlign: 'center',
115+
lineHeight: '1.2',
116+
},
117+
[media[0]]: {
118+
['span:first-of-type']: {
119+
fontSize: '1em',
120+
textAlign: 'center',
121+
lineHeight: '1.4',
122+
},
123+
124+
['span:last-of-type']: {
125+
color: theme.colors.grayscale60,
126+
fontSize: '0.6em',
127+
textAlign: 'center',
128+
lineHeight: '1.2',
129+
},
130+
},
76131
});
77132

78133
const PopUpDetailContainer = styled('div')({
@@ -83,6 +138,11 @@ const PopUpDetailContainer = styled('div')({
83138
borderRadius: '8px',
84139
padding: '16px',
85140
marginTop: '12px',
141+
142+
[media[0]]: {
143+
padding: '12px',
144+
marginTop: '8px',
145+
},
86146
});
87147

88148
const PopUpDetail = styled('div')({
@@ -107,6 +167,11 @@ const PopUpDetailNumber = styled.div(({ color }: { color?: themeColor }) => ({
107167
borderRadius: '4px',
108168
background: color ? theme.colors[color] : theme.colors.primary40,
109169
color: theme.colors.primary0,
170+
[media[0]]: {
171+
width: '20px', // 모바일 크기 축소
172+
height: '20px',
173+
fontSize: '12px',
174+
},
110175
}));
111176

112177
const ConfirmButton = styled('div')({
@@ -118,6 +183,11 @@ const ConfirmButton = styled('div')({
118183
color: theme.colors.primary0,
119184
borderRadius: '0 0 12px 12px',
120185
padding: '27px 0',
186+
187+
[media[0]]: {
188+
fontSize: '14px',
189+
padding: '16px 0',
190+
},
121191
});
122192

123193
const Backdrop = styled('div')({
@@ -139,13 +209,19 @@ const CloseButton = styled('button')({
139209
fontSize: '18px',
140210
cursor: 'pointer',
141211
color: theme.colors.grayscale100,
212+
213+
[media[0]]: {
214+
top: '12px',
215+
right: '0px',
216+
},
142217
});
143218

144219
export {
145220
PopUpContainer,
146221
PopUpTitle,
147222
PopUpContent,
148223
PopUpImage,
224+
PopUpDetailWord,
149225
PopUpDetailContainer,
150226
PopUpDetail,
151227
PopUpDetailNumber,

0 commit comments

Comments
 (0)