Skip to content

Commit 9fa7f7b

Browse files
authored
Merge branch 'main' into #23/socket-connection
2 parents 948bfa9 + 586d76e commit 9fa7f7b

14 files changed

Lines changed: 652 additions & 37 deletions

File tree

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
@@ -14,8 +14,10 @@
1414
"@emotion/styled": "^11.14.1",
1515
"@stomp/stompjs": "^7.3.0",
1616
"@tanstack/react-query": "^5.90.20",
17+
"chart.js": "^4.5.1",
1718
"pretendard": "^1.3.9",
1819
"react": "^19.2.0",
20+
"react-chartjs-2": "^5.3.1",
1921
"react-dom": "^19.2.0",
2022
"react-router-dom": "^7.12.0",
2123
"sockjs-client": "^1.6.1"

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: 47 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,57 @@ export default function DeviceCardItem({
5355

5456
return (
5557
<Container>
56-
<DeviceDetail isVisible={isDetailVisible} onClose={toggleDetailVisibility} setIsEditing={setIsEditing} id={id} />
57-
<CardContainer className="Cardcontainer">
58+
<DeviceDetail
59+
isVisible={isDetailVisible}
60+
onClose={toggleDetailVisibility}
61+
setIsEditing={setIsEditing}
62+
id={id}
63+
/>
64+
<CardContainer className="Cardcontainer"
65+
onClick={() => {
66+
if (!isDeleteMode) {
67+
navigate(`/detail/${id}`);
68+
}
69+
}}
70+
>
5871
{isDeleteMode ? (
59-
<label onClick={onSelect}>
72+
<label
73+
onClick={(e: React.MouseEvent<HTMLLabelElement>) => {
74+
e.stopPropagation();
75+
onSelect();
76+
}}
77+
>
6078
<DeleteCheckbox isSelected={isSelected} />
6179
</label>
6280
) : (
6381
warning && <WarningIcon src={warningIcon} alt="warning" />
6482
)}
65-
<DotImage onClick={toggleDetailVisibility} className="menu-trigger">{isDeleteMode ? null : <img src={dot} alt="dot" />}</DotImage>
83+
<DotImage
84+
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
85+
e.stopPropagation();
86+
toggleDetailVisibility();
87+
}}
88+
className="menu-trigger"
89+
>
90+
{isDeleteMode ? null : <img src={dot} alt="dot" />}
91+
</DotImage>
6692
<DeviceContainer className="device">
6793
<DeviceImage>
6894
<img src={device} alt="device" />
6995
</DeviceImage>
70-
<p>{isEditing ? (<EditNameInput ref={inputRef} type="text" defaultValue={deviceName} onKeyDown={enterHandle} onBlur={() => setIsEditing(false)} />) : (deviceName)}</p>
96+
<p>
97+
{isEditing ? (
98+
<EditNameInput
99+
ref={inputRef}
100+
type="text"
101+
defaultValue={deviceName}
102+
onKeyDown={enterHandle}
103+
onBlur={() => setIsEditing(false)}
104+
/>
105+
) : (
106+
deviceName
107+
)}
108+
</p>
71109
</DeviceContainer>
72110
<TemperatureContainer className="temp">
73111
<p>{temperature}°C</p>
@@ -251,4 +289,4 @@ const EditNameInput = styled.input`
251289
252290
background: none;
253291
border: none;
254-
`;
292+
`;
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)