Skip to content

Commit c8d6bad

Browse files
authored
Merge pull request #111 from GPGT-Algorithm-Study/dev
[Feat] 관리자 페이지 크롤링, 경고 ON/OFF 기능 추가
2 parents 09d45e5 + 00136ad commit c8d6bad

File tree

5 files changed

+273
-0
lines changed

5 files changed

+273
-0
lines changed

src/api/userSetting.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import axios from 'axios';
2+
import { getHeaderRefreshTokenConfig } from 'utils/auth';
3+
4+
const PREFIX_URL = '/api/v1/user/setting';
5+
6+
/**
7+
* 전체 사용자의 설정 정보를 가져온다.
8+
*/
9+
export function getAllUserSettingInfo() {
10+
return axios.get(`${PREFIX_URL}/all`, getHeaderRefreshTokenConfig());
11+
}
12+
13+
/**
14+
* 특정 사용자의 설정 정보를 가져온다.
15+
*/
16+
export function getUserSettingInfo(bojHandle) {
17+
return axios.get(
18+
`${PREFIX_URL}?bojHandle=${bojHandle}`,
19+
getHeaderRefreshTokenConfig(),
20+
);
21+
}
22+
23+
/**
24+
* 특정 사용자의 경고 설정을 토글한다.
25+
*/
26+
export function toggleUserWarningSetting(bojHandle) {
27+
return axios.put(
28+
`${PREFIX_URL}/toggle/warning?bojHandle=${bojHandle}`,
29+
getHeaderRefreshTokenConfig(),
30+
);
31+
}
32+
33+
/**
34+
* 특정 사용자의 크롤링 설정을 토글한다.
35+
*/
36+
export function toggleUserScrapingSetting(bojHandle) {
37+
return axios.put(
38+
`${PREFIX_URL}/toggle/scraping?bojHandle=${bojHandle}`,
39+
getHeaderRefreshTokenConfig(),
40+
);
41+
}

src/pages/Admin/UserSetting/index.jsx

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import React, { useCallback, useEffect, useState } from 'react';
2+
import { Card, Content, ScrollButton, Title, User, UserWrapper } from './style';
3+
import useScroll from 'hooks/useScroll';
4+
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
5+
import useSWR from 'swr';
6+
import fetcher from 'utils/fetcher';
7+
import { USER_SETTING_PREFIX_URL } from 'utils/constants';
8+
import { ToggleButton } from './style';
9+
import {
10+
toggleUserScrapingSetting,
11+
toggleUserWarningSetting,
12+
} from 'api/userSetting';
13+
import { toast } from 'react-toastify';
14+
15+
function UserSetting() {
16+
const { data: userSetting, mutate: mutateSettings } = useSWR(
17+
`${USER_SETTING_PREFIX_URL}/all`,
18+
fetcher,
19+
);
20+
21+
const [
22+
leftArrowHovering,
23+
rightArrowHovering,
24+
setArrowHovering,
25+
horizontalScrollRef,
26+
handleNextButtonClick,
27+
] = useScroll();
28+
29+
const onClickToggleScraping = (setting) => {
30+
const isAgree = confirm(
31+
'<' +
32+
setting.bojHandle +
33+
'>의 크롤링 설정을 ' +
34+
(setting.scrapingOn ? 'ON' : 'OFF') +
35+
' -> ' +
36+
(setting.scrapingOn ? 'OFF' : 'ON') +
37+
'(으)로 변경하시겠습니까?\n',
38+
);
39+
if (!isAgree) return;
40+
toggleUserScrapingSetting(setting.bojHandle)
41+
.then((res) => {
42+
if (res.status !== 200)
43+
//에러 처리
44+
console.log(res);
45+
toast.success('크롤링 설정이 변경되었습니다.');
46+
mutateSettings();
47+
return;
48+
})
49+
.catch((e) => {
50+
const { data } = e.response;
51+
if (data && data.code == 400) {
52+
toast.error(data.message);
53+
return;
54+
}
55+
});
56+
};
57+
58+
const onClickToggleWarning = (setting) => {
59+
const isAgree = confirm(
60+
'<' +
61+
setting.bojHandle +
62+
'>의 경고 설정을 ' +
63+
(setting.scrapingOn ? 'ON' : 'OFF') +
64+
' -> ' +
65+
(setting.scrapingOn ? 'OFF' : 'ON') +
66+
'(으)로 변경하시겠습니까?\n',
67+
);
68+
if (!isAgree) return;
69+
toggleUserWarningSetting(setting.bojHandle)
70+
.then((res) => {
71+
if (res.status !== 200)
72+
//에러 처리
73+
console.log(res);
74+
toast.success('경고 설정이 변경되었습니다.');
75+
mutateSettings();
76+
return;
77+
})
78+
.catch((e) => {
79+
const { data } = e.response;
80+
if (data && data.code == 400) {
81+
toast.error(data.message);
82+
return;
83+
}
84+
});
85+
};
86+
87+
if (!userSetting) return null;
88+
89+
console.log(userSetting);
90+
91+
return (
92+
<Card>
93+
<Title>유저 설정</Title>
94+
<Content>
95+
<UserWrapper ref={horizontalScrollRef}>
96+
{userSetting.map((setting) => (
97+
<User key={setting.bojHandle}>
98+
<div>{setting.bojHandle}</div>
99+
<ToggleButton
100+
isActive={setting.scrapingOn}
101+
onClick={() => onClickToggleScraping(setting)}
102+
>
103+
{setting.scrapingOn ? '크롤링 ON' : '크롤링 OFF'}
104+
</ToggleButton>
105+
<ToggleButton
106+
isActive={setting.warningOn}
107+
onClick={() => onClickToggleWarning(setting)}
108+
>
109+
{setting.warningOn ? '경고 ON' : '경고 OFF'}
110+
</ToggleButton>
111+
</User>
112+
))}
113+
</UserWrapper>
114+
<ScrollButton
115+
onClick={() => {
116+
handleNextButtonClick('prev');
117+
}}
118+
onMouseOver={() => setArrowHovering('prev', true)}
119+
onMouseOut={() => setArrowHovering('prev', false)}
120+
type="prev"
121+
>
122+
{leftArrowHovering && (
123+
<div>
124+
<FaChevronLeft />
125+
</div>
126+
)}
127+
</ScrollButton>
128+
<ScrollButton
129+
onClick={() => {
130+
handleNextButtonClick('next');
131+
}}
132+
onMouseOver={() => setArrowHovering('next', true)}
133+
onMouseOut={() => setArrowHovering('next', false)}
134+
type="next"
135+
>
136+
{rightArrowHovering && (
137+
<div>
138+
<FaChevronRight />
139+
</div>
140+
)}
141+
</ScrollButton>
142+
</Content>
143+
</Card>
144+
);
145+
}
146+
147+
export default UserSetting;

src/pages/Admin/UserSetting/style.jsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import styled from '@emotion/styled';
2+
import { CommonCard } from 'style/commonStyle';
3+
export const Card = styled(CommonCard)`
4+
position: relative;
5+
flex-wrap: nowrap;
6+
padding: 20px 0 20px 0;
7+
`;
8+
9+
export const UserWrapper = styled.div`
10+
margin-left: 10px;
11+
margin-right: 10px;
12+
display: flex;
13+
overflow-x: auto;
14+
-ms-overflow-style: none;
15+
scrollbar-width: none;
16+
::-webkit-scrollbar {
17+
display: none;
18+
}
19+
`;
20+
21+
export const Content = styled.div`
22+
position: relative;
23+
display: flex;
24+
`;
25+
26+
export const User = styled.div`
27+
width: 130px;
28+
display: flex;
29+
flex: 0 0 auto;
30+
padding: 10px 0 10px 0;
31+
flex-direction: column;
32+
align-items: center;
33+
font-weight: bold;
34+
font: 0.9rem;
35+
& div {
36+
margin-bottom: 20px;
37+
}
38+
`;
39+
40+
export const Title = styled.div`
41+
position: relative;
42+
top: 0;
43+
left: 0;
44+
font-weight: bold;
45+
margin-bottom: 25px;
46+
padding-left: 25px;
47+
`;
48+
49+
export const ScrollButton = styled.button`
50+
border: none;
51+
position: absolute;
52+
background: transparent;
53+
text-align: center;
54+
cursor: pointer;
55+
z-index: 999;
56+
right: ${(props) => (props.type == 'next' ? '0' : '')};
57+
left: ${(props) => (props.type == 'prev' ? '0' : '')};
58+
height: 120px;
59+
& div {
60+
color: #b6b6b6;
61+
}
62+
`;
63+
64+
export const LastLoginDate = styled.div`
65+
font-size: 12px;
66+
white-space: pre-line;
67+
text-align: center;
68+
`;
69+
70+
export const ToggleButton = styled.button`
71+
border: none;
72+
background: transparent;
73+
background-color: ${(props) => (props.isActive ? '#04aa6d' : 'crimson')};
74+
padding: 4px 7px;
75+
display: inline-block;
76+
border-radius: 4px;
77+
color: white;
78+
text-align: center;
79+
text-decoration: none;
80+
cursor: pointer;
81+
font-size: 12px;
82+
`;

src/pages/Admin/index.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { CardWrapper, ComponentWrapper } from './style';
99
import { getAllComplaint } from 'api/complaint';
1010
import ComplaintManagement from './ComplaintManagement';
1111
import { SkeletonTheme } from 'react-loading-skeleton';
12+
import UserSetting from './UserSetting';
1213

1314
function Admin() {
1415
const complaint = getAllComplaint()
@@ -30,6 +31,7 @@ function Admin() {
3031
<ShowAllUserLogs />
3132
<UserManageList />
3233
</CardWrapper>
34+
<UserSetting />
3335
</div>
3436
);
3537
}

src/utils/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const BOARD_PAGE_SIZE = 10;
66
export const MY_BOARD_PAGE_SIZE = 5;
77
export const PREFIX_URL = '/api/v1';
88
export const USER_PREFIX_URL = '/api/v1/user';
9+
export const USER_SETTING_PREFIX_URL = '/api/v1/user/setting';
910
export const STAT_PREFIX_URL = '/api/v2/stat';
1011
export const REC_PREFIX_URL = '/api/v1/recommend';
1112
export const PRB_PREFIX_URL = '/api/v1/problem';

0 commit comments

Comments
 (0)