Skip to content

Commit 62f63ff

Browse files
committed
feat: photo verification dashboard done
1 parent cc66e07 commit 62f63ff

File tree

7 files changed

+475
-0
lines changed

7 files changed

+475
-0
lines changed

constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const DISABLED = 'disabled';
2727
const STATUS_BASE_URL_PROD = 'https://status.realdevsquad.com';
2828
const STATUS_BASE_URL_STAGING = 'https://staging-status.realdevsquad.com';
2929
const STATUS_BASE_URL = STATUS_BASE_URL_PROD;
30+
const PHOTO_VERIFICATION_REQUESTS_BUTTON = 'photo-verification-requests-button';
3031

3132
const dummyPicture = 'https://dashboard.realdevsquad.com/images/avatar.png';
3233
const USER_MANAGEMENT_URL =

index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@
138138
>
139139
Extension Requests
140140
</a>
141+
<a
142+
id="photo-verification-requests-button"
143+
class="action-button element-display-remove"
144+
href="photo-verification-requests"
145+
>
146+
Photo Verification Requests
147+
</a>
141148
<a
142149
id="task-requests-link"
143150
class="action-button element-display-remove"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<link rel="stylesheet" href="/photo-verification-requests/style.css" />
7+
<title>Photo Verification Requests</title>
8+
</head>
9+
10+
<body>
11+
<header class="header">
12+
<h1>Photo Verification Requests</h1>
13+
</header>
14+
15+
<div class="search-filter">
16+
<div id="search">
17+
<input id="user-search" type="text" placeholder="Enter username" />
18+
</div>
19+
</div>
20+
21+
<div class="container">
22+
<div class="photo-verification-requests"></div>
23+
<div class="virtual"></div>
24+
</div>
25+
26+
<script src="/helpers/loadENV.js"></script>
27+
<script src="/utils.js"></script>
28+
<script src="/photo-verification-requests/local-utils.js"></script>
29+
<script src="/photo-verification-requests/script.js"></script>
30+
</body>
31+
</html>
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
async function approvePhotoVerificationRequest(id, userId, imageType) {
2+
const res = await modifyPhotoVerificationRequest(
3+
userId,
4+
imageType,
5+
'APPROVED',
6+
);
7+
const card = document.querySelector(`.photo-verification-card--${id}`);
8+
const message = document.createElement('p');
9+
message.innerText = res.data.message;
10+
11+
card.appendChild(message);
12+
13+
setTimeout(() => {
14+
window.location.reload();
15+
}, 2000);
16+
}
17+
18+
async function rejectPhotoVerificationRequest(id, userId) {
19+
const res = await modifyPhotoVerificationRequest(userId, 'both', 'REJECTED');
20+
const card = document.querySelector(`.photo-verification-card--${id}`);
21+
const message = document.createElement('p');
22+
message.innerText = res.data.message;
23+
24+
card.appendChild(message);
25+
26+
if (res.statusCode === 200) {
27+
setTimeout(() => {
28+
card.remove();
29+
}, 2000);
30+
}
31+
32+
setTimeout(() => {
33+
window.location.reload();
34+
}, 4000);
35+
}
36+
37+
function notifyPhotoVerificationRequest(id) {
38+
console.log(id, 'method to be implemented on the backend');
39+
}
40+
41+
function createPhotoVerificationRequestImageBox(
42+
prevImage,
43+
newImage,
44+
discordImage,
45+
) {
46+
const imageBox = document.createElement('div');
47+
imageBox.className = 'photo-verification-image-box';
48+
49+
const prevImageBox = document.createElement('div');
50+
prevImageBox.className = 'photo-verification-image-box__block';
51+
prevImageBox.innerHTML = `<h4>Previous Image</h4><img src="${prevImage}" alt="Previous Image" />`;
52+
imageBox.appendChild(prevImageBox);
53+
54+
const newImageBox = document.createElement('div');
55+
newImageBox.className = 'photo-verification-image-box__block';
56+
newImageBox.innerHTML = `<h4>New Image</h4><img src="${newImage}" alt="New Image" />`;
57+
imageBox.appendChild(newImageBox);
58+
59+
const discordImageBox = document.createElement('div');
60+
discordImageBox.className = 'photo-verification-image-box__block';
61+
discordImageBox.innerHTML = `<h4>Discord Image</h4><img src="${discordImage}" alt="Discord Image" />`;
62+
imageBox.appendChild(discordImageBox);
63+
64+
return imageBox;
65+
}
66+
67+
function createPhotoVerificationRequestButtonBox(
68+
approvePhoto,
69+
rejectPhoto,
70+
notifyPhoto,
71+
discordImageStatus,
72+
profileImageStatus,
73+
) {
74+
const buttonBox = document.createElement('div');
75+
buttonBox.className = 'photo-verification-button-box';
76+
77+
if (!discordImageStatus) {
78+
const approveDiscordButton = document.createElement('button');
79+
approveDiscordButton.innerText = 'Approve Discord';
80+
approveDiscordButton.onclick = () => approvePhoto('discord');
81+
buttonBox.appendChild(approveDiscordButton);
82+
}
83+
84+
if (!profileImageStatus) {
85+
const approveProfileButton = document.createElement('button');
86+
approveProfileButton.innerText = 'Approve Profile';
87+
approveProfileButton.onclick = () => approvePhoto('profile');
88+
buttonBox.appendChild(approveProfileButton);
89+
}
90+
91+
const approveBothButton = document.createElement('button');
92+
approveBothButton.innerText = 'Approve Both';
93+
approveBothButton.onclick = () => approvePhoto('both');
94+
buttonBox.appendChild(approveBothButton);
95+
96+
const rejectButton = document.createElement('button');
97+
rejectButton.innerText = 'Reject';
98+
rejectButton.className = 'reject-button';
99+
rejectButton.onclick = rejectPhoto;
100+
buttonBox.appendChild(rejectButton);
101+
102+
const notifyButton = document.createElement('button');
103+
notifyButton.innerText = 'Notify User';
104+
notifyButton.onclick = notifyPhoto;
105+
notifyButton.className = 'notify-button';
106+
notifyButton.disabled = true;
107+
108+
buttonBox.appendChild(notifyButton);
109+
return buttonBox;
110+
}
111+
112+
function createPhotoVerificationRequestStatusBox(
113+
discordImageStatus,
114+
profileImageStatus,
115+
) {
116+
const statusBox = document.createElement('div');
117+
statusBox.className = 'photo-verification-status-box';
118+
119+
const statusHeading = document.createElement('h3');
120+
statusHeading.innerText = 'Status';
121+
statusBox.appendChild(statusHeading);
122+
123+
const statusBoxContent = document.createElement('div');
124+
statusBoxContent.className = `photo-verification-status-box__block`;
125+
statusBoxContent.innerHTML = `<h4>Discord Image - ${
126+
discordImageStatus ? 'Approved' : 'Pending'
127+
}</h4><h4>Profile Image - ${
128+
profileImageStatus ? 'Approved' : 'Pending'
129+
}</h4>`;
130+
statusBox.appendChild(statusBoxContent);
131+
132+
return statusBox;
133+
}
134+
135+
function createPhotoVerificationRequestCard(photoVerificationRequest) {
136+
const card = document.createElement('div');
137+
card.className = `photo-verification-card photo-verification-card--${photoVerificationRequest.id}`;
138+
139+
const heading = document.createElement('h3');
140+
heading.innerText = `Photo Verifcation for ${photoVerificationRequest.user?.username}`;
141+
card.appendChild(heading);
142+
143+
card.appendChild(
144+
createPhotoVerificationRequestImageBox(
145+
photoVerificationRequest.user.picture,
146+
photoVerificationRequest.profile.url,
147+
photoVerificationRequest.discord.url,
148+
),
149+
);
150+
151+
card.appendChild(
152+
createPhotoVerificationRequestStatusBox(
153+
photoVerificationRequest.discord.approved,
154+
photoVerificationRequest.profile.approved,
155+
),
156+
);
157+
158+
card.appendChild(
159+
createPhotoVerificationRequestButtonBox(
160+
(imageType) =>
161+
approvePhotoVerificationRequest(
162+
photoVerificationRequest.id,
163+
photoVerificationRequest.userId,
164+
imageType,
165+
),
166+
() =>
167+
rejectPhotoVerificationRequest(
168+
photoVerificationRequest.id,
169+
photoVerificationRequest.userId,
170+
),
171+
() => notifyPhotoVerificationRequest(photoVerificationRequest.id),
172+
photoVerificationRequest.discord.approved,
173+
photoVerificationRequest.profile.approved,
174+
),
175+
);
176+
177+
return card;
178+
}
179+
180+
async function getPhotoVerificationRequests(username) {
181+
let url = `${API_BASE_URL}/users/picture/all/`;
182+
if (username) {
183+
url += `?username=${username}`;
184+
}
185+
186+
const response = await fetch(url, {
187+
credentials: 'include',
188+
method: 'GET',
189+
headers: {
190+
'Content-type': 'application/json',
191+
},
192+
});
193+
return await response.json();
194+
}
195+
196+
async function modifyPhotoVerificationRequest(userId, imageType, status) {
197+
const response = await fetch(
198+
`${API_BASE_URL}/users/picture/verify/${userId}/?status=${status}&type=${imageType}`,
199+
{
200+
credentials: 'include',
201+
method: 'PATCH',
202+
headers: {
203+
'Content-type': 'application/json',
204+
},
205+
},
206+
);
207+
return { data: await response.json(), statusCode: response.status };
208+
}
209+
210+
function debounce(func, wait) {
211+
let timeout;
212+
return function executedFunction(...args) {
213+
const later = () => {
214+
clearTimeout(timeout);
215+
func(...args);
216+
};
217+
clearTimeout(timeout);
218+
timeout = setTimeout(later, wait);
219+
};
220+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const photoVerificationRequestContainer = document.querySelector(
2+
'.photo-verification-requests',
3+
);
4+
const userSearchInput = document.querySelector('#user-search');
5+
6+
async function render() {
7+
const photoVerificationRequests = await getPhotoVerificationRequests();
8+
const photoVerificationRequestObjects = photoVerificationRequests.data;
9+
photoVerificationRequestObjects.forEach((obj) => {
10+
photoVerificationRequestContainer.append(
11+
createPhotoVerificationRequestCard(obj),
12+
);
13+
});
14+
}
15+
16+
render();
17+
18+
async function onUserSearchInput(e) {
19+
photoVerificationRequestContainer.innerHTML = '';
20+
if (e.target.value === '') {
21+
render();
22+
}
23+
const photoVerificationRequests = await getPhotoVerificationRequests(
24+
e.target.value,
25+
);
26+
const photoVerificationRequestObjects = photoVerificationRequests.data;
27+
photoVerificationRequestContainer.innerHTML = '';
28+
photoVerificationRequestObjects.forEach((obj) => {
29+
photoVerificationRequestContainer.append(
30+
createPhotoVerificationRequestCard(obj),
31+
);
32+
});
33+
}
34+
35+
userSearchInput.addEventListener('input', debounce(onUserSearchInput, 500));

0 commit comments

Comments
 (0)