Skip to content

Commit e77feab

Browse files
authored
Merge pull request #148 from boostcampwm-2022/feat/#147-B
Feat/#140-B: VoteBlock UI ๊ตฌํ˜„
2 parents d556a8c + 14837eb commit e77feab

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { BiX } from '@react-icons/all-files/bi/BiX';
2+
import classNames from 'classnames/bind';
3+
import React, { useState, useRef } from 'react';
4+
5+
import Button from '../common/Button';
6+
import style from './style.module.scss';
7+
8+
const cx = classNames.bind(style);
9+
10+
interface Option {
11+
id: number;
12+
option: string;
13+
}
14+
15+
const initialOption: Option[] = [
16+
{ id: 1, option: '์งœ์žฅ๋ฉด' },
17+
{
18+
id: 2,
19+
option: '์งฌ๋ฝ•',
20+
},
21+
];
22+
23+
function VoteBlock() {
24+
const [options, setOptions] = useState<Option[]>(initialOption);
25+
const [isUnRegisterd, setIsUnRegisterd] = useState<boolean>(true);
26+
const inputRef = useRef<HTMLInputElement>(null);
27+
28+
const onRegister = () => {
29+
if (!options.length) throw new Error('ํˆฌํ‘œ ํ•ญ๋ชฉ์€ ์ตœ์†Œ 1๊ฐœ์—์š” ^^');
30+
31+
if (!isUnRegisterd) return;
32+
33+
setIsUnRegisterd(false);
34+
};
35+
36+
const onAdd = () => {
37+
if (!inputRef.current || !inputRef.current.value) return;
38+
39+
const { value: option } = inputRef.current;
40+
41+
const lastId = options.at(-1)?.id;
42+
const nextId = lastId !== undefined ? lastId + 1 : 0;
43+
const newOption: Option = { id: nextId, option };
44+
45+
setOptions([...options, newOption]);
46+
47+
inputRef.current.value = '';
48+
};
49+
50+
const onDelete = (targetId: number) => {
51+
const filteredOptions = options.filter(
52+
(option) => option.id !== Number(targetId),
53+
);
54+
55+
setOptions(filteredOptions);
56+
};
57+
58+
const onClose = () => {
59+
alert('ํˆฌํ‘œ ์ข…๋ฃŒ..!');
60+
/**ํˆฌํ‘œ ๊ฒฐ๊ณผ ๋ณด์—ฌ์ค˜์•ผํ•จ */
61+
setIsUnRegisterd(true);
62+
};
63+
64+
return (
65+
<div className={style['vote-container']}>
66+
<h3 className={style.title}>ํˆฌํ‘œ</h3>
67+
<ul>
68+
{options.map(({ id, option }, index) => (
69+
<li className={style['option-item']} key={id} id={id.toString()}>
70+
<div className={style['box-fill']}>{index + 1}</div>
71+
<p className={style.option}>{option}</p>
72+
{isUnRegisterd && (
73+
<div
74+
className={cx('box-fill', { 'position-right': true })}
75+
onClick={() => onDelete(id)}
76+
>
77+
<BiX size="20" />
78+
</div>
79+
)}
80+
</li>
81+
))}
82+
</ul>
83+
{isUnRegisterd && (
84+
<div className={style['option-item']}>
85+
<div className={style['box-fill']}></div>
86+
<input
87+
ref={inputRef}
88+
className={style['option-input']}
89+
placeholder="ํ•ญ๋ชฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"
90+
></input>
91+
</div>
92+
)}
93+
<div className={style['vote-buttons']}>
94+
{isUnRegisterd ? (
95+
<>
96+
<Button onClick={onAdd} text="ํ•ญ๋ชฉ ์ถ”๊ฐ€" />
97+
<Button onClick={onRegister} text="ํˆฌํ‘œ ๋“ฑ๋ก" />
98+
</>
99+
) : (
100+
<Button onClick={onClose} text="ํˆฌํ‘œ ์ข…๋ฃŒ" />
101+
)}
102+
</div>
103+
</div>
104+
);
105+
}
106+
107+
export default VoteBlock;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
@import 'styles/color.module';
2+
3+
.vote-container {
4+
width: 100%;
5+
6+
padding: 20px;
7+
8+
border-radius: 12px;
9+
10+
background-color: $white;
11+
box-shadow: 1px 4px 12px rgba(0, 0, 0, 0.2);
12+
13+
.title {
14+
font-size: 16px;
15+
font-weight: 700;
16+
17+
text-align: center;
18+
}
19+
20+
.option-item {
21+
display: flex;
22+
position: relative;
23+
flex-direction: row;
24+
align-items: center;
25+
26+
width: 100%;
27+
28+
margin: 14px 0px;
29+
padding: 12px;
30+
31+
border-radius: 12px;
32+
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.2);
33+
34+
cursor: pointer;
35+
36+
.box-fill {
37+
display: flex;
38+
align-items: center;
39+
justify-content: center;
40+
41+
width: 30px;
42+
height: 30px;
43+
44+
margin-right: 12px;
45+
46+
border-radius: 4px;
47+
48+
background-color: $primary-100;
49+
color: $white;
50+
51+
font-size: 16px;
52+
}
53+
54+
.option {
55+
font-size: 16px;
56+
font-weight: 400;
57+
}
58+
59+
.option-input {
60+
width: 100%;
61+
}
62+
63+
.position-right {
64+
position: absolute;
65+
right: 0;
66+
}
67+
}
68+
69+
.vote-buttons {
70+
display: flex;
71+
flex-direction: row;
72+
justify-content: end;
73+
74+
margin-top: 20px;
75+
76+
button {
77+
display: flex;
78+
align-items: center;
79+
justify-content: center;
80+
81+
width: 100px;
82+
height: 30px;
83+
margin-left: 12px;
84+
padding: 0px;
85+
86+
border-radius: 8px;
87+
88+
background-color: $primary-100;
89+
color: $white;
90+
91+
span {
92+
padding: 0px;
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
ย (0)