Skip to content

Commit 586d76e

Browse files
authored
Merge pull request #24 from Team-DBE/feature/sideBar&chart
Feature/side bar&chart
2 parents b60acb6 + 4e429c3 commit 586d76e

File tree

14 files changed

+657
-51
lines changed

14 files changed

+657
-51
lines changed

bun.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
"@emotion/react": "^11.14.0",
1414
"@emotion/styled": "^11.14.1",
1515
"@tanstack/react-query": "^5.90.20",
16+
"chart.js": "^4.5.1",
1617
"pretendard": "^1.3.9",
1718
"react": "^19.2.0",
19+
"react-chartjs-2": "^5.3.1",
1820
"react-dom": "^19.2.0",
1921
"react-router-dom": "^7.12.0"
2022
},

src/App.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { Routes, Route } from "react-router-dom";
22
import GlobalStyles from "./styles/globalStyles";
33
import Home from "./pages/home/home";
4+
import Detail from "./pages/detail.tsx";
45

56
function App() {
67
return (
78
<>
89
<GlobalStyles />
910

1011
<Routes>
11-
<Route path="/" element={<Home />} />
12+
<Route path="/section-1" element={<Home />} />
13+
<Route path="/detail/:id" element={<Detail />} />
14+
<Route path="/*" element={<Home />} />
1215
</Routes>
1316
</>
1417
);

src/assets/logo.svg

Lines changed: 28 additions & 0 deletions
Loading

src/components/DeviceCardItem.tsx

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import React, { useState, useRef, useEffect } from "react";
12
import styled from "@emotion/styled";
2-
import { useState, useRef, useEffect } from "react";
33
import dot from "../assets/dot.svg";
44
import device from "../assets/device.svg";
55
import warningIcon from "../assets/warning.svg";
66
import DeviceDetail from "./DeviceDetail";
77
import useDeviceDetail from "../hooks/useDeviceDetail";
8+
import { useNavigate } from "react-router-dom";
89

910
interface DeviceCardProps {
1011
deviceName: string;
@@ -25,8 +26,9 @@ export default function DeviceCardItem({
2526
isSelected,
2627
onSelect,
2728
id,
28-
updateDeviceName
29+
updateDeviceName,
2930
}: DeviceCardProps) {
31+
const navigate = useNavigate();
3032
const { isDetailVisible, toggleDetailVisibility } = useDeviceDetail();
3133
const [isEditing, setIsEditing] = useState(false);
3234

@@ -42,7 +44,7 @@ export default function DeviceCardItem({
4244
if (e.key === "Enter") {
4345
const newName = (e.target as HTMLInputElement).value;
4446
if (newName.trim().length > 8) {
45-
alert("별명은 최대 8자까지 가능합니다.")
47+
alert("별명은 최대 8자까지 가능합니다.");
4648
return;
4749
}
4850
updateDeviceName(id, newName);
@@ -53,21 +55,56 @@ export default function DeviceCardItem({
5355

5456
return (
5557
<Container>
56-
<DeviceDetail isVisible={isDetailVisible} onClose={toggleDetailVisibility} setIsEditing={setIsEditing} />
57-
<CardContainer>
58+
<DeviceDetail
59+
isVisible={isDetailVisible}
60+
onClose={toggleDetailVisibility}
61+
setIsEditing={setIsEditing}
62+
/>
63+
<CardContainer
64+
onClick={() => {
65+
if (!isDeleteMode) {
66+
navigate(`/detail/${id}`);
67+
}
68+
}}
69+
>
5870
{isDeleteMode ? (
59-
<label onClick={onSelect}>
71+
<label
72+
onClick={(e: React.MouseEvent<HTMLLabelElement>) => {
73+
e.stopPropagation();
74+
onSelect();
75+
}}
76+
>
6077
<DeleteCheckbox isSelected={isSelected} />
6178
</label>
6279
) : (
6380
warning && <WarningIcon src={warningIcon} alt="warning" />
6481
)}
65-
<DotImage onClick={toggleDetailVisibility} className="menu-trigger">{isDeleteMode ? null : <img src={dot} alt="dot" />}</DotImage>
82+
<DotImage
83+
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
84+
e.stopPropagation();
85+
toggleDetailVisibility();
86+
}}
87+
className="menu-trigger"
88+
>
89+
{isDeleteMode ? null : <img src={dot} alt="dot" />}
90+
</DotImage>
6691
<DeviceContainer className="device">
6792
<DeviceImage>
6893
<img src={device} alt="device" />
6994
</DeviceImage>
70-
<p>{isEditing ? (<EditNameInput ref={inputRef} type="text" defaultValue={deviceName} onKeyDown={enterHandle} onBlur={() => setIsEditing(false)} />) : (deviceName)}</p>
95+
<p>
96+
{isEditing ? (
97+
<EditNameInput
98+
ref={inputRef}
99+
type="text"
100+
defaultValue={deviceName}
101+
onKeyDown={enterHandle}
102+
onBlur={() => setIsEditing(false)}
103+
/>
104+
) : (
105+
deviceName
106+
)}
107+
</p>
71108
</DeviceContainer>
72109
<TemperatureContainer className="temp">
73110
<p>{temperature}°C</p>
@@ -251,4 +288,4 @@ const EditNameInput = styled.input`
251288
252289
background: none;
253290
border: none;
254-
`;
291+
`;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import styled from "@emotion/styled";
2+
3+
export const SideBarHeader = styled.header`
4+
align-items: center;
5+
align-self: stretch;
6+
background-color: #393939;
7+
display: flex;
8+
justify-content: space-between;
9+
min-width: 280px;
10+
cursor: default;
11+
`;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { memo } from "react";
2+
import styled from "@emotion/styled";
3+
import LogoIcon from "../../../assets/logo.svg";
4+
5+
function SidebarHeaderComponent() {
6+
return (
7+
<SideBarHeader>
8+
<img src={LogoIcon} alt="logo" />
9+
</SideBarHeader>
10+
);
11+
}
12+
13+
const SideBarHeader = styled.header`
14+
display: flex;
15+
align-items: center;
16+
justify-content: center;
17+
align-self: stretch;
18+
width: 100%;
19+
background-color: #222222;
20+
padding-top: 95px;
21+
padding-bottom: 40px;
22+
box-sizing: border-box;
23+
cursor: default;
24+
`;
25+
26+
export const SidebarHeader = memo(SidebarHeaderComponent);

src/components/sidebar/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { Sidebar } from "./sidebar";
2+
export { SidebarHeader } from "./header/sidebar-header";
3+
export { SidebarItem } from "./item/sidebar-item";
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import styled from "@emotion/styled";
2+
3+
const ITEM_PADDING = "10px 0";
4+
const LABEL_FONT_SIZE = "20px";
5+
const TRANSITION_DURATION = "0.05s";
6+
7+
interface SideBarMenuItemProps {
8+
isActive: boolean;
9+
}
10+
11+
interface SideBarMenuItemLabelProps {
12+
isActive?: boolean;
13+
}
14+
15+
export const SideBarMenuItem = styled.div<SideBarMenuItemProps>`
16+
align-items: center;
17+
background-color: #121212;
18+
display: flex;
19+
padding: ${ITEM_PADDING};
20+
width: 100%;
21+
cursor: pointer;
22+
`;
23+
24+
export const SideBarMenuItemLabel = styled.button<SideBarMenuItemLabelProps>`
25+
appearance: none;
26+
background: transparent;
27+
border: 0;
28+
color: ${(props) => (props.isActive ? "#ffffff" : "#a0a0a0")};
29+
cursor: pointer;
30+
display: block;
31+
font-size: ${LABEL_FONT_SIZE};
32+
font-style: normal;
33+
line-height: normal;
34+
margin-bottom: 20px;
35+
padding-left: 65px;
36+
text-align: left;
37+
transition: color ${TRANSITION_DURATION} linear;
38+
width: 100%;
39+
font-family: "Pretendard";
40+
font-weight: 500;
41+
42+
&:hover,
43+
&:focus-visible {
44+
color: #ffffff;
45+
}
46+
47+
&:focus-visible {
48+
outline: 2px solid #ffffff;
49+
outline-offset: 2px;
50+
}
51+
`;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { memo } from "react";
2+
import { SideBarMenuItemLabel } from "./sidebar-item-style";
3+
4+
interface SidebarItemProps {
5+
label: string;
6+
isActive?: boolean;
7+
onClick?: () => void;
8+
}
9+
10+
function SidebarItemComponent({
11+
label,
12+
isActive = false,
13+
onClick,
14+
}: SidebarItemProps) {
15+
return (
16+
<SideBarMenuItemLabel
17+
type="button"
18+
isActive={isActive}
19+
onClick={onClick}
20+
aria-current={isActive ? "page" : undefined}
21+
>
22+
- {label}
23+
</SideBarMenuItemLabel>
24+
);
25+
}
26+
27+
export const SidebarItem = memo(SidebarItemComponent);

0 commit comments

Comments
 (0)