Skip to content

Commit cd154b3

Browse files
Merge pull request #857 from Real-Dev-Squad/develop
dev to main sync
2 parents 54d230b + 2147127 commit cd154b3

22 files changed

+1890
-20
lines changed

__tests__/applications/applications.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,25 @@ describe('Applications page', () => {
135135
).toBe(true, 'status query param is not removed from url');
136136
});
137137

138+
it('should load and render accepted application and check the applied filter label,render all applications when the applied filter is removed', async function () {
139+
await page.goto(`${SITE_URL}/applications/?dev=true`);
140+
await page.waitForNetworkIdle();
141+
await page.click('#filter-button-new');
142+
await page.click('.filter-dropdown div[data-filter="accepted"]');
143+
applicationCards = await page.$$('.application-card');
144+
expect(applicationCards.length).toBe(4);
145+
const filterLabelElement = page.$('.filter-label .filter-text');
146+
expect(filterLabelElement).toBeTruthy();
147+
await page.click('.filter-remove');
148+
await page.waitForNetworkIdle();
149+
applicationCards = await page.$$('.application-card');
150+
const urlAfterClearingStatusFilter = new URL(page.url());
151+
expect(
152+
urlAfterClearingStatusFilter.searchParams.get('status') === null,
153+
).toBe(true, 'status query param is not removed from url');
154+
expect(applicationCards.length).toBe(6);
155+
});
156+
138157
it('should load more applications on going to the bottom of the page', async function () {
139158
let applicationCards = await page.$$('.application-card');
140159
expect(applicationCards.length).toBe(6);
@@ -166,6 +185,25 @@ describe('Applications page', () => {
166185
expect(urlAfterOpeningModal.searchParams.get('id') !== null).toBe(true);
167186
});
168187

188+
it('under feature flag should open application details modal for application, when user click on view details on any card', async function () {
189+
await page.goto(`${SITE_URL}/applications/?dev=true`);
190+
await page.waitForNetworkIdle();
191+
const applicationDetailsModal = await page.$('.application-details');
192+
expect(
193+
await applicationDetailsModal.evaluate((el) =>
194+
el.classList.contains('hidden'),
195+
),
196+
).toBe(true);
197+
await page.click('.view-details-button');
198+
expect(
199+
await applicationDetailsModal.evaluate((el) =>
200+
el.classList.contains('hidden'),
201+
),
202+
).toBe(false);
203+
const urlAfterOpeningModal = new URL(page.url());
204+
expect(urlAfterOpeningModal.searchParams.get('id') !== null).toBe(true);
205+
});
206+
169207
it('should close application details modal, when user clicks the close button', async function () {
170208
const applicationDetailsModal = await page.$('.application-details');
171209
await page.click('.view-details-button');

applications/index.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<script src="/helpers/loadENV.js"></script>
99
<title>Applications</title>
1010
</head>
11+
1112
<body>
1213
<header class="header">
1314
<h1>RDS Join Applications</h1>
@@ -24,6 +25,30 @@ <h1>RDS Join Applications</h1>
2425
alt="funnel icon"
2526
/>
2627
</button>
28+
<div class="filter-container hidden">
29+
<div class="filter-menu">
30+
<button id="filter-button-new" class="filter-button hidden">
31+
<img
32+
class="funnel-icon"
33+
src="/task-requests/assets/funnel.svg"
34+
alt="funnel icon"
35+
/>
36+
Filters
37+
</button>
38+
<div class="filter-dropdown">
39+
<div data-filter="" class="filter-dropdown-header">
40+
Status <button class="close-dropdown-btn">&#x2715;</button>
41+
</div>
42+
<div data-filter="rejected">Rejected</div>
43+
<div data-filter="accepted">Accepted</div>
44+
<div data-filter="pending">Pending</div>
45+
</div>
46+
</div>
47+
<div class="filter-label hidden">
48+
<span class="filter-text"></span>
49+
<span class="filter-remove">&#x2715;</span>
50+
</div>
51+
</div>
2752
<p class="no_applications_found hidden">No applications Found!</p>
2853
<div
2954
class="filter-modal hidden"

applications/script.js

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
let nextLink;
1010
let isDataLoading = false;
1111
const loader = document.querySelector('.loader');
12-
const filterButton = document.getElementById('filter-button');
1312
const filterModal = document.querySelector('.filter-modal');
1413
const backDrop = document.querySelector('.backdrop');
1514
const backDropBlur = document.querySelector('.backdrop-blur');
@@ -36,8 +35,25 @@ const lastElementContainer = document.getElementById('page_bottom_element');
3635
const applicationDetailsActionsContainer = document.querySelector(
3736
'.application-details-actions',
3837
);
39-
4038
const urlParams = new URLSearchParams(window.location.search);
39+
const isDev = urlParams.get('dev') === 'true';
40+
const filterButton = isDev
41+
? document.getElementById('filter-button-new')
42+
: document.getElementById('filter-button');
43+
if (isDev)
44+
document
45+
.getElementsByClassName('filter-container')[0]
46+
.classList.remove('hidden');
47+
48+
const filterDropdown = document.querySelector('.filter-dropdown');
49+
const filterOptions = document.querySelectorAll(
50+
'.filter-dropdown div:not(.close-dropdown-btn)',
51+
);
52+
const filterLabel = document.querySelector('.filter-label');
53+
const filterText = document.querySelector('.filter-label .filter-text');
54+
const filterRemove = document.querySelector('.filter-remove');
55+
const closeDropdownBtn = document.querySelector('.close-dropdown-btn');
56+
4157
let applicationId = urlParams.get('id');
4258

4359
let currentApplicationId;
@@ -76,8 +92,12 @@ function updateUserApplication({ isAccepted }) {
7692

7793
function changeFilter() {
7894
nextLink = '';
79-
filterModal.classList.add('hidden');
80-
backDrop.style.display = 'none';
95+
if (!isDev) {
96+
filterModal.classList.add('hidden');
97+
backDrop.style.display = 'none';
98+
} else {
99+
status = 'all';
100+
}
81101
applicationContainer.innerHTML = '';
82102
}
83103

@@ -343,6 +363,9 @@ async function renderApplicationCards(next, status, isInitialRender) {
343363
changeLoaderVisibility({ hide: true });
344364
const applications = data.applications;
345365
nextLink = data.next;
366+
if (isDev && status != 'all') {
367+
showAppliedFilter(status);
368+
}
346369
if (isInitialRender) filterButton.classList.remove('hidden');
347370
if (!applications.length)
348371
return noApplicationFoundText.classList.remove('hidden');
@@ -392,7 +415,7 @@ async function renderApplicationById(id) {
392415
const urlParams = new URLSearchParams(window.location.search);
393416
status = urlParams.get('status') || 'all';
394417

395-
if (status !== 'all') {
418+
if (!isDev && status !== 'all') {
396419
document.querySelector(`input[name="status"]#${status}`).checked = true;
397420
}
398421

@@ -418,9 +441,71 @@ const addIntersectionObserver = () => {
418441
intersectionObserver.observe(lastElementContainer);
419442
};
420443

421-
filterButton.addEventListener('click', () => {
422-
filterModal.classList.toggle('hidden');
423-
backDrop.style.display = 'flex';
444+
if (isDev) {
445+
filterButton.addEventListener('click', () => {
446+
filterDropdown.style.display =
447+
filterDropdown.style.display === 'block' ? 'none' : 'block';
448+
});
449+
450+
filterOptions.forEach((option) => {
451+
option.addEventListener('click', () => {
452+
const filter = option.getAttribute('data-filter');
453+
applyFilter(filter);
454+
});
455+
});
456+
} else {
457+
filterButton.addEventListener('click', () => {
458+
filterModal.classList.toggle('hidden');
459+
backDrop.style.display = 'flex';
460+
});
461+
462+
backDrop.addEventListener('click', () => {
463+
filterModal.classList.add('hidden');
464+
backDrop.style.display = 'none';
465+
});
466+
467+
applyFilterButton.addEventListener('click', () => {
468+
const selectedFilterOption = document.querySelector(
469+
'input[name="status"]:checked',
470+
);
471+
472+
const selectedStatus = selectedFilterOption.value;
473+
addQueryParamInUrl('status', selectedStatus);
474+
changeFilter();
475+
status = selectedStatus;
476+
renderApplicationCards(nextLink, status);
477+
});
478+
479+
clearButton.addEventListener('click', clearFilter);
480+
}
481+
482+
function showAppliedFilter(filterApplied) {
483+
if (filterApplied) {
484+
filterLabel.classList.remove('hidden');
485+
filterText.textContent =
486+
'Status :' + filterApplied[0].toUpperCase() + filterApplied.substring(1);
487+
}
488+
}
489+
490+
function applyFilter(filter) {
491+
if (filter.length > 0) {
492+
if (!filterLabel.classList.contains('hidden')) {
493+
filterLabel.classList.add('hidden');
494+
}
495+
addQueryParamInUrl('status', filter);
496+
changeFilter();
497+
status = filter;
498+
renderApplicationCards(nextLink, status);
499+
filterDropdown.style.display = 'none';
500+
}
501+
}
502+
503+
filterRemove.addEventListener('click', () => {
504+
filterLabel.classList.add('hidden');
505+
filterText.textContent = '';
506+
removeQueryParamInUrl('status');
507+
changeFilter();
508+
renderApplicationCards(nextLink, status);
424509
});
425510

426511
backDrop.addEventListener('click', () => {
@@ -431,19 +516,15 @@ backDrop.addEventListener('click', () => {
431516
backDropBlur.addEventListener('click', closeApplicationDetails);
432517
applicationCloseButton.addEventListener('click', closeApplicationDetails);
433518

434-
applyFilterButton.addEventListener('click', () => {
435-
const selectedFilterOption = document.querySelector(
436-
'input[name="status"]:checked',
437-
);
438-
439-
const selectedStatus = selectedFilterOption.value;
440-
addQueryParamInUrl('status', selectedStatus);
441-
changeFilter();
442-
status = selectedStatus;
443-
renderApplicationCards(nextLink, status);
519+
document.addEventListener('click', (e) => {
520+
if (!filterButton.contains(e.target) && !filterDropdown.contains(e.target)) {
521+
filterDropdown.style.display = 'none';
522+
}
444523
});
445524

446-
clearButton.addEventListener('click', clearFilter);
525+
closeDropdownBtn.addEventListener('click', () => {
526+
filterDropdown.style.display = 'none';
527+
});
447528

448529
applicationAcceptButton.addEventListener('click', () =>
449530
updateUserApplication({ isAccepted: true }),

applications/style.css

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,96 @@ body {
5353
overflow-y: auto;
5454
}
5555

56+
.filter-container {
57+
display: flex;
58+
align-items: end;
59+
gap: 10px;
60+
margin: 20px;
61+
}
62+
5663
.funnel-icon {
5764
width: 1.2rem;
5865
height: 1.5rem;
5966
margin-left: 0.5rem;
6067
}
6168

69+
.filter-menu .filter-button:hover {
70+
background-color: var(--color-primary-hover);
71+
}
72+
73+
.filter-menu .filter-button {
74+
margin-left: auto;
75+
background-color: var(--color-primary);
76+
color: var(--white);
77+
border: none;
78+
border-radius: 0.4rem;
79+
cursor: pointer;
80+
display: flex;
81+
align-items: center;
82+
justify-content: center;
83+
width: 9rem;
84+
height: 2.5rem;
85+
padding: 0.7rem;
86+
}
87+
88+
.filter-dropdown {
89+
width: 300px;
90+
padding: 0;
91+
margin: 0;
92+
display: none;
93+
position: absolute;
94+
border: 1px solid var(--light-gray-color);
95+
border-radius: 0.2rem;
96+
background-color: var(--white);
97+
}
98+
99+
.filter-dropdown div {
100+
padding: 0.5rem 1rem 0.5rem 2rem;
101+
color: var(--color-gray);
102+
border: 1px solid var(--light-gray-color);
103+
}
104+
105+
.filter-dropdown div:first-child {
106+
font-weight: bold;
107+
}
108+
109+
.filter-dropdown div:not(:first-child) {
110+
padding-left: 4rem;
111+
font-weight: normal;
112+
}
113+
.filter-dropdown div:not(:first-child):hover {
114+
background-color: var(--light-gray-color);
115+
cursor: pointer;
116+
}
117+
118+
.filter-dropdown-header {
119+
display: flex;
120+
justify-content: space-between;
121+
align-items: center;
122+
}
123+
124+
/* Filter label */
125+
.filter-label {
126+
display: flex;
127+
font-size: 14px;
128+
font-weight: 600;
129+
align-items: center;
130+
color: var(--color-primary);
131+
background-color: var(--white);
132+
border: 1px solid var(--color-primary);
133+
padding: 5px 10px;
134+
border-radius: 50px;
135+
}
136+
137+
.filter-text {
138+
margin-right: 5px;
139+
}
140+
141+
.filter-remove {
142+
cursor: pointer;
143+
font-size: 14px;
144+
}
145+
62146
.filter-button:hover {
63147
background-color: var(--color-primary-hover);
64148
}
@@ -134,6 +218,18 @@ body {
134218
justify-content: center;
135219
}
136220

221+
.close-dropdown-btn {
222+
font-weight: bold;
223+
color: var(--color-gray);
224+
text-align: center;
225+
font-size: 12px;
226+
background-color: var(--white);
227+
border: none;
228+
outline: none;
229+
box-shadow: none;
230+
cursor: pointer;
231+
}
232+
137233
.modal-form {
138234
text-align: initial;
139235
padding: 0.5rem;

0 commit comments

Comments
 (0)