Skip to content

Commit 57bcf62

Browse files
authored
Merge pull request #25 from sw-security-web-app/24-scrum-47-chatAPI
24 scrum 47 chat api
2 parents fedfa94 + fb71da2 commit 57bcf62

33 files changed

+1253
-687
lines changed

sw-security/app/api/api.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import axios from "axios";
2-
import { useNavigate } from "react-router-dom";
32
import { useStore } from "../store/store";
43
const BASE_URL = import.meta.env.VITE_BASE_URL;
54

@@ -13,7 +12,7 @@ api.interceptors.request.use(
1312
(config) => {
1413
const accessToken = localStorage.getItem("accessToken");
1514
if (accessToken) {
16-
config.headers.Authorization = `Bearer ${accessToken}`;
15+
config.headers.Authorization = `${accessToken}`;
1716
}
1817
return config;
1918
},
@@ -25,21 +24,21 @@ api.interceptors.response.use(
2524
(response) => response,
2625
async (error) => {
2726
const originalRequest = error.config;
28-
const navigate = useNavigate();
29-
const logout = useStore((state) => state.logout);
27+
28+
// const logout = useStore((state) => state.logout);
3029
// 액세스 토큰 만료
3130
if (error.response?.status === 401 && !originalRequest._retry) {
3231
originalRequest._retry = true; // 무한 루프 방지
3332

3433
try {
3534
// 액세스 토큰 갱신 요청
3635
const res = await axios.post(
37-
"액세스 토큰 갱신 엔드포인트",
36+
"/api/auth/refresh",
3837
{},
3938
{ withCredentials: true }
4039
);
4140
if (res.status === 200) {
42-
const newAccessToken = res.data.accessToken;
41+
const newAccessToken = res.data;
4342
localStorage.setItem("accessToken", newAccessToken);
4443
// 새 액세스 토큰으로 원래 요청 다시 보내기
4544
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
@@ -48,11 +47,11 @@ api.interceptors.response.use(
4847
const error = res.data;
4948
console.error("토큰 갱신 실패");
5049
alert(error.message);
51-
logout();
50+
// logout();
5251
}
5352
} catch (refreshError) {
5453
console.error("토큰 갱신 실패", refreshError);
55-
logout();
54+
// logout();
5655
}
5756
}
5857

sw-security/app/components/chatBtn.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ import chatBtnStyle from "../css/chatBtn.module.css";
22

33
type Props = {
44
onClick: () => void;
5+
loading: boolean;
56
};
67

7-
export default function ChatBtn({ onClick }: Props) {
8+
export default function ChatBtn({ onClick, loading }: Props) {
89
return (
9-
<button className={chatBtnStyle.btnContainer} onClick={onClick}>
10-
<img src="../../img/chatSubmit.svg" alt="chatSubmit" />
10+
<button
11+
className={`${chatBtnStyle.btnContainer} ${
12+
loading ? chatBtnStyle.loading : ""
13+
}`}
14+
onClick={onClick}
15+
disabled={loading}
16+
>
17+
<img src="/img/chatSubmit.svg" alt="chatSubmit" />
1118
</button>
1219
);
1320
}

sw-security/app/components/loginHeader.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ export default function LoginHeader() {
77
return (
88
<div className={loginHeaderStyle.header}>
99
<div className={loginHeaderStyle.headerItems}>
10-
<Logo color="white" to="/" />
11-
10+
<Logo to="/" />
1211
<Link to="/login" className={loginHeaderStyle.login}>
1312
<DefaultButton
1413
text="로그인"

sw-security/app/components/logo.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ import { Link } from "@remix-run/react";
22
import logoStyle from "../css/logo.module.css";
33

44
type Props = {
5-
color: string;
6-
to: string; // 추가된 부분
5+
to: string;
76
};
87

9-
export default function Logo({ color = "white", to = "/" }: Props) {
8+
export default function Logo({ to = "/" }: Props) {
109
return (
1110
<Link to={to} style={{ textDecoration: "none" }}>
1211
<div className={logoStyle.container}>
13-
<div className={logoStyle.img} style={{ backgroundColor: color }}></div>
14-
<div className={logoStyle.text}>LOGO</div>
12+
<img
13+
src="../../img/logo.svg"
14+
alt="logo"
15+
className={logoStyle.img}
16+
></img>
17+
<div className={logoStyle.text}>VERO</div>
1518
</div>
1619
</Link>
1720
);

sw-security/app/components/modal.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import signupStyle from "../css/signup.module.css";
2+
3+
type Props = {
4+
setIsOpen: (isOpen: boolean) => void;
5+
text: string;
6+
title: string;
7+
};
8+
9+
export default function Modal({ setIsOpen, text, title }: Props) {
10+
return (
11+
<div className={signupStyle.modalContainer}>
12+
<div className={signupStyle.modalHeader}>
13+
<span className={signupStyle.headerText}>{title}</span>
14+
<button
15+
className={signupStyle.closeBtn}
16+
onClick={() => setIsOpen(false)}
17+
>
18+
<img
19+
src="../../img/modalClose.svg"
20+
alt="close"
21+
onClick={() => setIsOpen(false)}
22+
/>
23+
</button>
24+
</div>
25+
<div className={signupStyle.modalContent}>
26+
<span className={signupStyle.contentText}>{text}</span>
27+
</div>
28+
<div className={signupStyle.modalBtnDiv}>
29+
<button
30+
className={signupStyle.modalBtn}
31+
onClick={() => setIsOpen(false)}
32+
>
33+
확인
34+
</button>
35+
</div>
36+
</div>
37+
);
38+
}

sw-security/app/components/nickNameHeader.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Profile from "./profile";
55

66
type Props = { color: string };
77
export default function NickNameHeader({ color = "#0d0d0d" }: Props) {
8-
const logoColor: "white" | string = color === "#0d0d0d" ? "white" : "#484B50";
98
const nickNameColor: "#B7BDC7" | string =
109
color === "#0d0d0d" ? "#B7BDC7" : "#484B50";
1110
const profileColor: "#FFFFFF" | string =
@@ -14,7 +13,7 @@ export default function NickNameHeader({ color = "#0d0d0d" }: Props) {
1413
return (
1514
<div className={nickNameHeader.header} style={{ backgroundColor: color }}>
1615
<div className={nickNameHeader.headerItems}>
17-
<Logo color={logoColor} to="/main" />
16+
<Logo to="/main" />
1817
<Profile nickNameColor={nickNameColor} profileColor={profileColor} />
1918
</div>
2019
</div>

sw-security/app/components/profileForm.tsx

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,27 @@ export default function ProfileForm() {
1010
name: string;
1111
email: string;
1212
companyName: string;
13-
deptName: string;
14-
position: string;
13+
companyDept: string;
14+
companyPosition: string;
15+
memberStatus: "MANAGER" | "EMPLOYEE" | "INDIVIDUAL";
1516
}
16-
type Role = "MANAGER" | "EMPLOYEE" | "INDIVIDUAL";
17+
type Role = UserInfo["memberStatus"];
1718

1819
const { isLogin } = useStore();
1920
const logout = useStore((state) => state.logout);
2021
const navigate = useNavigate();
2122
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
22-
const [role, setRole] = useState<Role>("MANAGER");
23+
const [role, setRole] = useState<Role | null>(null);
2324

2425
// const isBrowser = typeof window !== "undefined"; // 브라우저에서만 실행되도록 체크
2526
// const role = isBrowser ? localStorage.getItem("role") : null; // 브라우저에서만 localStorage 접근
2627
// const role = "MANAGER";
2728

2829
const fetchUserInfo = async () => {
2930
try {
30-
const response = await api.get("엔드포인트");
31+
const response = await api.get("api/my-info");
3132
if (response.status === 200) {
33+
setRole(response.data.memberStatus);
3234
setUserInfo(response.data);
3335
} else {
3436
const error = await response.data;
@@ -42,14 +44,6 @@ export default function ProfileForm() {
4244
//유저 탈퇴 함수
4345
const handleDelete = () => {};
4446

45-
// role을 마운트될 때 localStorage에서 가져옴
46-
// useEffect(() => {
47-
// if (typeof window !== "undefined") {
48-
// const storedRole = localStorage.getItem("role");
49-
// setRole(storedRole as Role);
50-
// }
51-
// }, []);
52-
5347
useEffect(() => {
5448
if (!isLogin) {
5549
// 로그인되지 않았다면 로그인 페이지로 이동
@@ -65,17 +59,17 @@ export default function ProfileForm() {
6559
};
6660

6761
//로딩아이콘 띄우기
68-
// if (userInfo == null) {
69-
// return (
70-
// <div className={profileStyle.profileContainer}>
71-
// <div className={profileStyle.content}>
72-
// <div className={profileStyle.iconContainer}>
73-
// <AiOutlineLoading className={profileStyle.loadingIcon} />
74-
// </div>
75-
// </div>
76-
// </div>
77-
// );
78-
// }
62+
if (userInfo == null) {
63+
return (
64+
<div className={profileStyle.profileContainer}>
65+
<div className={profileStyle.content}>
66+
<div className={profileStyle.iconContainer}>
67+
<AiOutlineLoading className={profileStyle.loadingIcon} />
68+
</div>
69+
</div>
70+
</div>
71+
);
72+
}
7973

8074
return (
8175
<div className={profileStyle.profileContainer}>
@@ -86,38 +80,44 @@ export default function ProfileForm() {
8680
<div className={profileStyle.nameContainer}>
8781
<label>이름</label>
8882
<div className={profileStyle.nameDiv}>
89-
<span className={profileStyle.name}>아년석</span>
90-
{/* <span className={profileStyle.name}>{userInfo.name}</span> */}
83+
{/* <span className={profileStyle.name}>아년석</span> */}
84+
<span className={profileStyle.name}>{userInfo.name}</span>
9185
</div>
9286
</div>
9387
<div className={profileStyle.emailContainer}>
9488
<label>이메일</label>
9589
<div className={profileStyle.emailDiv}>
96-
<span className={profileStyle.email}>vero1234@naver.com</span>
97-
{/* <span className={profileStyle.email}>{userInfo.email}</span> */}
90+
{/* <span className={profileStyle.email}>vero1234@naver.com</span> */}
91+
<span className={profileStyle.email}>{userInfo.email}</span>
9892
</div>
9993
</div>
10094
{(role === "EMPLOYEE" || role === "MANAGER") && (
10195
<>
10296
<div className={profileStyle.companyContainer}>
10397
<label>회사명</label>
10498
<div className={profileStyle.companyDiv}>
105-
<span className={profileStyle.company}>삼성전자</span>
106-
{/* <span className={profileStyle.company}>{userInfo.companyName}</span> */}
99+
{/* <span className={profileStyle.company}>삼성전자</span> */}
100+
<span className={profileStyle.company}>
101+
{userInfo.companyName}
102+
</span>
107103
</div>
108104
</div>
109105
<div className={profileStyle.deptContainer}>
110106
<label>부서명</label>
111107
<div className={profileStyle.deptDiv}>
112-
<span className={profileStyle.dept}>SI</span>
113-
{/* <span className={profileStyle.dept}>{userInfo.deptName}</span> */}
108+
{/* <span className={profileStyle.dept}>SI</span> */}
109+
<span className={profileStyle.dept}>
110+
{userInfo.companyDept}
111+
</span>
114112
</div>
115113
</div>
116114
<div className={profileStyle.positionContainer}>
117115
<label>직책</label>
118116
<div className={profileStyle.positionDiv}>
119-
<span className={profileStyle.position}>BE-1년차</span>
120-
{/* <span className={profileSctyle.position}>{userInfo.position}</span> */}
117+
{/* <span className={profileStyle.position}>BE-1년차</span> */}
118+
<span className={profileStyle.position}>
119+
{userInfo.companyPosition}
120+
</span>
121121
</div>
122122
</div>
123123
</>

sw-security/app/components/signUpHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default function SignUpHeader() {
77
return (
88
<div className={loginHeaderStyle.header}>
99
<div className={loginHeaderStyle.headerItems}>
10-
<Logo color="white" to="/" />
10+
<Logo to="/" />
1111
{/* <div className={loginHeaderStyle.none}>none</div> */}
1212
</div>
1313
</div>

0 commit comments

Comments
 (0)