From 0c7f181eb02e7bd71e2163beb6c49e62abdcf3d8 Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Tue, 10 Feb 2026 23:56:58 +0530 Subject: [PATCH 01/13] RDS new flow request changes button added and different field added for admin clarity --- applications/index.html | 6 + applications/script.js | 132 +++++++++++++++++---- applications/style.css | 196 +++++++++++++++++++++++++++++++- applications/utils.js | 50 ++++++++ mock-data/applications/index.js | 3 + 5 files changed, 362 insertions(+), 25 deletions(-) diff --git a/applications/index.html b/applications/index.html index af5e1c02..b9d45dfe 100644 --- a/applications/index.html +++ b/applications/index.html @@ -132,6 +132,12 @@

Status

> Accept + diff --git a/applications/script.js b/applications/script.js index 58a129c9..e5354d27 100644 --- a/applications/script.js +++ b/applications/script.js @@ -90,7 +90,14 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { const applicationTextarea = document.querySelector('.application-textarea'); if (isRequestChanges) { - if (!applicationTextarea || !applicationTextarea.value) { + if (!applicationTextarea || !applicationTextarea.value.trim()) { + showToastMessage({ + isDev, + oldToastFunction: showToast, + type: 'error', + message: 'Please provide feedback before requesting changes.', + }); + if (applicationTextarea) applicationTextarea.focus(); return; } updateApplication({ @@ -100,16 +107,20 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { }, }) .then(() => { - showToast({ - message: 'Changes requested successfully!', + showToastMessage({ + isDev, + oldToastFunction: showToast, type: 'success', + message: 'Changes requested successfully!', }); setTimeout(() => closeApplicationDetails(), 1000); }) .catch((error) => { - showToast({ - message: error.message || 'Failed to request changes', + showToastMessage({ + isDev, + oldToastFunction: showToast, type: 'error', + message: error.message || 'Failed to request changes', }); }); return; @@ -283,7 +294,7 @@ function openApplicationDetails(application) { let descriptionClass = 'description'; if (detail.isStatus) { - descriptionClass += ` status-${detail.description?.toLowerCase()}`; + descriptionClass += ` status-badge status-${detail.description?.toLowerCase()}`; } const applicationSectionDescription = createElement({ diff --git a/applications/style.css b/applications/style.css index a943e026..0d00ed5b 100644 --- a/applications/style.css +++ b/applications/style.css @@ -127,6 +127,7 @@ body { padding-left: 4rem; font-weight: normal; } + .filter-dropdown div:not(:first-child):hover { background-color: var(--light-gray-color); cursor: pointer; @@ -462,37 +463,33 @@ body { .application-details .application-details-main .application-section - .description.status-pending { + .description.status-badge { color: var(--white); - background-color: var(--color-pending); padding: 4px 12px; border-radius: 20px; display: inline-block; text-transform: capitalize; } +.application-details + .application-details-main + .application-section + .description.status-pending { + background-color: var(--color-pending); +} + .application-details .application-details-main .application-section .description.status-accepted { - color: var(--white); background-color: var(--color-accepted); - padding: 4px 12px; - border-radius: 20px; - display: inline-block; - text-transform: capitalize; } .application-details .application-details-main .application-section .description.status-rejected { - color: var(--white); background-color: var(--color-rejected); - padding: 4px 12px; - border-radius: 20px; - display: inline-block; - text-transform: capitalize; } .application-details .application-details-main .application-highlights { @@ -776,49 +773,56 @@ body { padding: 1rem; } } -.application-details .application-details-actions .application-details-reject { - width: 18%; -} -.application-details .application-details-actions .application-details-accept { - width: 18%; -} +@media screen and (min-width: 851px) { + .application-details + .application-details-actions + .application-details-reject { + width: 18%; + } -.application-details .application-details-actions .application-details-nudge { - background-color: white; - color: var(--color-primary); - margin: 0 auto; - width: 18%; - border: 2px solid var(--color-primary); - padding: 8px 16px; - border-radius: 4px; -} + .application-details + .application-details-actions + .application-details-accept { + width: 18%; + } -.application-details - .application-details-actions - .application-details-nudge:is(:hover, :active, :focus-visible) { - background: var(--color-primary); - color: var(--white); - transition: transform 0.2s ease; - will-change: transform; -} + .application-details .application-details-actions .application-details-nudge { + background-color: white; + color: var(--color-primary); + margin: 0 auto; + width: 18%; + border: 2px solid var(--color-primary); + padding: 8px 16px; + border-radius: 4px; + } -.application-details - .application-details-actions - .application-details-nudge:hover { - transform: scale(1.05); -} + .application-details + .application-details-actions + .application-details-nudge:is(:hover, :active, :focus-visible) { + background: var(--color-primary); + color: var(--white); + transition: transform 0.2s ease; + will-change: transform; + } -.application-details - .application-details-actions - .application-details-nudge:active { - animation: bounceBackAnimation 0.4s ease forwards; -} + .application-details + .application-details-actions + .application-details-nudge:hover { + transform: scale(1.05); + } -.application-details - .application-details-actions - .application-details-request-changes { - width: 24%; + .application-details + .application-details-actions + .application-details-nudge:active { + animation: bounceBackAnimation 0.4s ease forwards; + } + + .application-details + .application-details-actions + .application-details-request-changes { + width: 24%; + } } @media screen and (max-width: 500px) { @@ -839,6 +843,7 @@ body { .application-card .user-info .company-name { max-width: 100%; } + .application-details .application-details-actions { flex-wrap: wrap; gap: 8px; diff --git a/applications/utils.js b/applications/utils.js index 32f36971..0ce1ecff 100644 --- a/applications/utils.js +++ b/applications/utils.js @@ -117,28 +117,6 @@ async function updateApplication({ applicationPayload, applicationId }) { } } -async function nudgeApplication(applicationId) { - try { - const res = await fetch(`${BASE_URL}/applications/${applicationId}/nudge`, { - method: 'PATCH', - credentials: 'include', - headers: { - 'Content-type': 'application/json', - }, - }); - - if (!res.ok) { - const error = await res.json(); - throw error; - } - - const data = await res.json(); - return data; - } catch (error) { - throw error; - } -} - async function addApplicationFeedback(applicationId, feedbackData) { try { const res = await fetch( @@ -190,7 +168,6 @@ export { getApplications, getApplicationById, updateApplication, - nudgeApplication, addApplicationFeedback, getIsSuperUser, showToast, diff --git a/mock-data/applications/index.js b/mock-data/applications/index.js index b62818ef..23896fa1 100644 --- a/mock-data/applications/index.js +++ b/mock-data/applications/index.js @@ -37,6 +37,8 @@ const fetchedApplications = [ { id: 'YwTi6zFNI3GlDsZVjD8C', createdAt: '2023-12-19T00:22:03.845Z', + applicationScore: 0, + nudgeCount: 0, intro: { funFact: 'mattis aliquam faucibus purus in massa tempor nec feugiat nisl pretium fusce id velit ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius duis at consectetur lorem donec massa sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu augue ut lectus arcu bibendum at', @@ -68,6 +70,8 @@ const fetchedApplications = [ { id: 'q2ZzerFKxdsUYMxoexS9', createdAt: '2023-12-19T00:21:26.595Z', + applicationScore: 42, + nudgeCount: 5, intro: { funFact: 'mattis aliquam faucibus purus in massa tempor nec feugiat nisl pretium fusce id velit ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius duis at consectetur lorem donec massa sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu augue ut lectus arcu bibendum at', @@ -195,6 +199,8 @@ const acceptedApplications = [ { id: 'lavEduxsb2C5Bl4s289P', createdAt: '2023-12-19T00:23:07.865Z', + applicationScore: 90, + nudgeCount: 1, intro: { funFact: 'mattis aliquam faucibus purus in massa tempor nec feugiat nisl pretium fusce id velit ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius duis at consectetur lorem donec massa sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu augue ut lectus arcu bibendum at', @@ -227,6 +233,8 @@ const acceptedApplications = [ { id: 'YwTi6zFNI3GlDsZVjD8C', createdAt: '2023-12-19T00:22:03.845Z', + applicationScore: 0, + nudgeCount: 0, intro: { funFact: 'mattis aliquam faucibus purus in massa tempor nec feugiat nisl pretium fusce id velit ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius duis at consectetur lorem donec massa sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu augue ut lectus arcu bibendum at', @@ -258,6 +266,8 @@ const acceptedApplications = [ { id: 'q2ZzerFKxdsUYMxoexS9', createdAt: '2023-12-19T00:21:26.595Z', + applicationScore: 55, + nudgeCount: 3, intro: { funFact: 'mattis aliquam faucibus purus in massa tempor nec feugiat nisl pretium fusce id velit ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius duis at consectetur lorem donec massa sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu augue ut lectus arcu bibendum at', @@ -323,6 +333,8 @@ const pendingApplications = [ { id: 'lavEduxsb2C5Bl4s289P', createdAt: '2023-12-19T00:23:07.865Z', + applicationScore: 70, + nudgeCount: 4, intro: { funFact: 'mattis aliquam faucibus purus in massa tempor nec feugiat nisl pretium fusce id velit ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius duis at consectetur lorem donec massa sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu augue ut lectus arcu bibendum at', From 7640cb1fbc99738d82b07b70c38321589b59985b Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Wed, 11 Feb 2026 03:24:47 +0530 Subject: [PATCH 03/13] chore: Configure Yarn to use node_modules linker and define packageManager, improve API base URL loading, and refine application feedback and toast handling. --- applications/script.js | 12 ++++++++---- applications/style.css | 32 -------------------------------- components/toast/script.js | 2 +- 3 files changed, 9 insertions(+), 37 deletions(-) diff --git a/applications/script.js b/applications/script.js index e5354d27..1dd59af9 100644 --- a/applications/script.js +++ b/applications/script.js @@ -130,11 +130,15 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { const payload = { status: applicationStatus }; const promises = []; + const feedback = + applicationTextarea && applicationTextarea.value + ? applicationTextarea.value.trim() + : ''; - if (applicationTextarea && applicationTextarea.value) { + if (feedback) { promises.push( addApplicationFeedback(currentApplicationId, { - feedback: applicationTextarea.value, + feedback, status: applicationStatus, }), ); @@ -153,7 +157,7 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { isDev, oldToastFunction: showToast, type: 'success', - message: 'Application updated successfully!', + message: 'application updated successfully!', }); setTimeout(() => closeApplicationDetails(), 1000); }) @@ -737,5 +741,5 @@ applicationRejectButton.addEventListener('click', () => updateUserApplication({ isAccepted: false }), ); applicationRequestChangesButton.addEventListener('click', () => { - updateUserApplication({ isAccepted: false, isRequestChanges: true }); + updateUserApplication({ isRequestChanges: true }); }); diff --git a/applications/style.css b/applications/style.css index 0d00ed5b..05dbac75 100644 --- a/applications/style.css +++ b/applications/style.css @@ -787,37 +787,6 @@ body { width: 18%; } - .application-details .application-details-actions .application-details-nudge { - background-color: white; - color: var(--color-primary); - margin: 0 auto; - width: 18%; - border: 2px solid var(--color-primary); - padding: 8px 16px; - border-radius: 4px; - } - - .application-details - .application-details-actions - .application-details-nudge:is(:hover, :active, :focus-visible) { - background: var(--color-primary); - color: var(--white); - transition: transform 0.2s ease; - will-change: transform; - } - - .application-details - .application-details-actions - .application-details-nudge:hover { - transform: scale(1.05); - } - - .application-details - .application-details-actions - .application-details-nudge:active { - animation: bounceBackAnimation 0.4s ease forwards; - } - .application-details .application-details-actions .application-details-request-changes { @@ -851,7 +820,6 @@ body { padding: 15px; } - .application-details .application-details-actions .application-details-nudge, .application-details .application-details-actions .application-details-accept, .application-details .application-details-actions .application-details-reject, .application-details diff --git a/components/toast/script.js b/components/toast/script.js index ad340b48..a21bb9fc 100644 --- a/components/toast/script.js +++ b/components/toast/script.js @@ -51,7 +51,7 @@ function showToastMessage({ isDev, oldToastFunction, type, message }) { if (isDev) { createToast(type, message); } else if (oldToastFunction.length === 1) { - oldToastFunction(message); + oldToastFunction({ message, type }); } else { oldToastFunction(type, message); } From 848d556cb1d0833f25ae993bc1f1f27b6646991b Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Wed, 11 Feb 2026 09:59:48 +0530 Subject: [PATCH 04/13] Consolidate application feedback into the update payload, refine API base URL environment configuration, and upgrade to Yarn 4. --- applications/script.js | 24 ++++++------------------ applications/utils.js | 27 --------------------------- 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/applications/script.js b/applications/script.js index 1dd59af9..79597d25 100644 --- a/applications/script.js +++ b/applications/script.js @@ -5,7 +5,6 @@ import { showToast, updateApplication, getApplicationById, - addApplicationFeedback, } from './utils.js'; let nextLink; let isDataLoading = false; @@ -127,31 +126,20 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { } const applicationStatus = isAccepted ? 'accepted' : 'rejected'; - const payload = { status: applicationStatus }; - - const promises = []; const feedback = applicationTextarea && applicationTextarea.value ? applicationTextarea.value.trim() : ''; + const payload = { status: applicationStatus }; if (feedback) { - promises.push( - addApplicationFeedback(currentApplicationId, { - feedback, - status: applicationStatus, - }), - ); + payload.feedback = feedback; } - promises.push( - updateApplication({ - applicationId: currentApplicationId, - applicationPayload: payload, - }), - ); - - Promise.all(promises) + updateApplication({ + applicationId: currentApplicationId, + applicationPayload: payload, + }) .then(() => { showToastMessage({ isDev, diff --git a/applications/utils.js b/applications/utils.js index 0ce1ecff..aaa72ab0 100644 --- a/applications/utils.js +++ b/applications/utils.js @@ -117,32 +117,6 @@ async function updateApplication({ applicationPayload, applicationId }) { } } -async function addApplicationFeedback(applicationId, feedbackData) { - try { - const res = await fetch( - `${BASE_URL}/applications/${applicationId}/feedback`, - { - method: 'PATCH', - credentials: 'include', - body: JSON.stringify(feedbackData), - headers: { - 'Content-type': 'application/json', - }, - }, - ); - - if (!res.ok) { - const error = await res.json(); - throw error; - } - - const data = await res.json(); - return data; - } catch (error) { - throw error; - } -} - function showToast({ message, type }) { toast.innerText = message; @@ -168,7 +142,6 @@ export { getApplications, getApplicationById, updateApplication, - addApplicationFeedback, getIsSuperUser, showToast, }; From e712bda1d1e0ed41a080eeb8160c07adebab01f2 Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Wed, 11 Feb 2026 19:20:28 +0530 Subject: [PATCH 05/13] feat: Add 'changes requested' application status, migrate to Yarn 4, and refine API base URL loading logic. --- applications/script.js | 16 ++++++++++++++++ applications/style.css | 7 ++++++- applications/utils.js | 2 ++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/applications/script.js b/applications/script.js index 79597d25..571dd2de 100644 --- a/applications/script.js +++ b/applications/script.js @@ -102,6 +102,7 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { updateApplication({ applicationId: currentApplicationId, applicationPayload: { + status: 'changes_requested', feedback: applicationTextarea.value, }, }) @@ -360,6 +361,21 @@ function openApplicationDetails(application) { innerText: 'Application was already accepted', }); applicationDetailsActionsContainer.append(applicationDetailsAcceptedMsg); + } else if (application.status === 'changes_requested') { + applicationAcceptButton.classList.add('hidden'); + applicationRejectButton.classList.add('hidden'); + applicationRequestChangesButton.classList.add('hidden'); + + const applicationDetailsChangesRequestedMsg = createElement({ + type: 'p', + attributes: { + class: 'application-details-changes-requested-msg', + }, + innerText: 'Changes requested', + }); + applicationDetailsActionsContainer.append( + applicationDetailsChangesRequestedMsg, + ); } else { applicationRejectButton.disabled = false; applicationRejectButton.style.cursor = 'pointer'; diff --git a/applications/style.css b/applications/style.css index 05dbac75..8534b08f 100644 --- a/applications/style.css +++ b/applications/style.css @@ -665,7 +665,8 @@ body { } .application-details-accepted-msg, -.application-details-rejected-msg { +.application-details-rejected-msg, +.application-details-changes-requested-msg { font-weight: bold; font-size: 18px; width: 100%; @@ -680,6 +681,10 @@ body { color: var(--red-color); } +.application-details-changes-requested-msg { + color: var(--color-orange, #f5a623); +} + .unauthorized-text { text-align: center; } diff --git a/applications/utils.js b/applications/utils.js index aaa72ab0..4b15f1f4 100644 --- a/applications/utils.js +++ b/applications/utils.js @@ -118,6 +118,8 @@ async function updateApplication({ applicationPayload, applicationId }) { } function showToast({ message, type }) { + const toast = document.getElementById('toast'); + if (!toast) return; toast.innerText = message; if (type === 'success') { From aa71f402cc87dafca8ba6cd873be4a57b37dbb90 Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Thu, 12 Feb 2026 00:05:10 +0530 Subject: [PATCH 06/13] feat: Update application feedback handling, refine API interactions, and enhance styling for application statuses --- __tests__/applications/applications.test.js | 6 +- applications/script.js | 126 ++++++++++---------- applications/style.css | 35 +++--- applications/utils.js | 19 +-- mock-data/applications/index.js | 15 +-- 5 files changed, 99 insertions(+), 102 deletions(-) diff --git a/__tests__/applications/applications.test.js b/__tests__/applications/applications.test.js index b214a112..d3ded3a2 100644 --- a/__tests__/applications/applications.test.js +++ b/__tests__/applications/applications.test.js @@ -73,13 +73,13 @@ describe('Applications page', () => { body: JSON.stringify(superUserForAudiLogs), }); } else if ( - url === `${STAGING_API_URL}/applications/lavEduxsb2C5Bl4s289P` + url === `${STAGING_API_URL}/applications/lavEduxsb2C5Bl4s289P/feedback` ) { interceptedRequest.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ - message: 'application updated successfully!', + message: 'Application feedback submitted successfully', }), headers: { 'Access-Control-Allow-Origin': '*', @@ -355,7 +355,7 @@ describe('Applications page', () => { ).toBe(false); const toastMessage = await page.$('[data-testid="toast-message"]'); expect(await toastMessage.evaluate((el) => el.textContent)).toBe( - 'application updated successfully!', + 'Application feedback submitted successfully', ); }); diff --git a/applications/script.js b/applications/script.js index 571dd2de..794c2bf6 100644 --- a/applications/script.js +++ b/applications/script.js @@ -6,6 +6,7 @@ import { updateApplication, getApplicationById, } from './utils.js'; +import { showToastMessage } from '../components/toast/script.js'; let nextLink; let isDataLoading = false; let totalApplicationCount = 0; @@ -85,54 +86,28 @@ let currentApplicationId; let status = 'all'; -function updateUserApplication({ isAccepted, isRequestChanges = false }) { +function updateUserApplication({ status }) { const applicationTextarea = document.querySelector('.application-textarea'); - - if (isRequestChanges) { - if (!applicationTextarea || !applicationTextarea.value.trim()) { - showToastMessage({ - isDev, - oldToastFunction: showToast, - type: 'error', - message: 'Please provide feedback before requesting changes.', - }); - if (applicationTextarea) applicationTextarea.focus(); - return; - } - updateApplication({ - applicationId: currentApplicationId, - applicationPayload: { - status: 'changes_requested', - feedback: applicationTextarea.value, - }, - }) - .then(() => { - showToastMessage({ - isDev, - oldToastFunction: showToast, - type: 'success', - message: 'Changes requested successfully!', - }); - setTimeout(() => closeApplicationDetails(), 1000); - }) - .catch((error) => { - showToastMessage({ - isDev, - oldToastFunction: showToast, - type: 'error', - message: error.message || 'Failed to request changes', - }); - }); - return; - } - - const applicationStatus = isAccepted ? 'accepted' : 'rejected'; const feedback = applicationTextarea && applicationTextarea.value ? applicationTextarea.value.trim() : ''; - const payload = { status: applicationStatus }; + if (status === 'changes_requested' && !feedback) { + showToastMessage({ + isDev, + oldToastFunction: showToast, + type: 'error', + message: 'Please provide feedback before requesting changes.', + }); + if (applicationTextarea) applicationTextarea.focus(); + return; + } + + const payload = { + status, + }; + if (feedback) { payload.feedback = feedback; } @@ -141,12 +116,12 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { applicationId: currentApplicationId, applicationPayload: payload, }) - .then(() => { + .then((res) => { showToastMessage({ isDev, oldToastFunction: showToast, type: 'success', - message: 'application updated successfully!', + message: res.message || 'Application updated successfully!', }); setTimeout(() => closeApplicationDetails(), 1000); }) @@ -155,7 +130,7 @@ function updateUserApplication({ isAccepted, isRequestChanges = false }) { isDev, oldToastFunction: showToast, type: 'error', - message: error.message, + message: error.message || 'Failed to update application', }); }); } @@ -190,6 +165,12 @@ function closeApplicationDetails() { if (applicationRejectedMsg) { applicationRejectedMsg.remove(); } + const applicationChangesRequestedMsg = document.querySelector( + '.application-details-changes-requested-msg', + ); + if (applicationChangesRequestedMsg) { + applicationChangesRequestedMsg.remove(); + } removeQueryParamInUrl('id'); } @@ -209,11 +190,9 @@ function openApplicationDetails(application) { isStatus: true, }, { - title: 'Application Score', + title: 'Score', description: - application.applicationScore !== undefined - ? application.applicationScore - : 'N/A', + application.score !== undefined ? application.score : 'N/A', isHighlight: true, }, { @@ -274,9 +253,9 @@ function openApplicationDetails(application) { const applicationSection = createElement({ type: 'div', attributes: { - class: detail.isHighlight - ? 'application-section application-highlight-item' - : 'application-section', + class: `application-section ${ + detail.isHighlight ? 'application-highlight-item' : '' + }`.trim(), }, }); const applicationSectionTitle = createElement({ @@ -285,14 +264,15 @@ function openApplicationDetails(application) { innerText: detail.title, }); - let descriptionClass = 'description'; - if (detail.isStatus) { - descriptionClass += ` status-badge status-${detail.description?.toLowerCase()}`; - } - const applicationSectionDescription = createElement({ type: 'p', - attributes: { class: descriptionClass }, + attributes: { + class: `description ${ + detail.isStatus + ? `status-badge status-${detail.description?.toLowerCase()}` + : '' + }`.trim(), + }, innerText: detail.description, }); @@ -322,20 +302,34 @@ function openApplicationDetails(application) { innerText: 'Add Feedback', }); + let feedbackText = ''; + if (typeof application.feedback === 'string') { + feedbackText = application.feedback; + } else if (Array.isArray(application.feedback)) { + feedbackText = application.feedback + .map((f) => (typeof f === 'string' ? f : f.feedback || '')) + .filter((f) => f) + .join('\n'); + } else if (application.feedback && typeof application.feedback === 'object') { + feedbackText = application.feedback.feedback || ''; + } + const applicationTextArea = createElement({ type: 'textarea', attributes: { class: 'application-textarea', placeHolder: 'Add Feedback here', }, - innerText: application.feedback || '', + innerText: feedbackText, }); applicationSection.appendChild(applicationSectionTitle); applicationSection.appendChild(applicationTextArea); applicationDetailsMain.appendChild(applicationSection); - if (application.status === 'rejected') { + const currentStatus = application.status?.toLowerCase(); + + if (currentStatus === 'rejected') { applicationAcceptButton.classList.add('hidden'); applicationRejectButton.classList.add('hidden'); applicationRequestChangesButton.classList.add('hidden'); @@ -348,7 +342,7 @@ function openApplicationDetails(application) { innerText: 'Application is already rejected', }); applicationDetailsActionsContainer.append(applicationDetailsRejectedMsg); - } else if (application.status === 'accepted') { + } else if (currentStatus === 'accepted') { applicationAcceptButton.classList.add('hidden'); applicationRejectButton.classList.add('hidden'); applicationRequestChangesButton.classList.add('hidden'); @@ -361,7 +355,7 @@ function openApplicationDetails(application) { innerText: 'Application was already accepted', }); applicationDetailsActionsContainer.append(applicationDetailsAcceptedMsg); - } else if (application.status === 'changes_requested') { + } else if (currentStatus === 'changes_requested') { applicationAcceptButton.classList.add('hidden'); applicationRejectButton.classList.add('hidden'); applicationRequestChangesButton.classList.add('hidden'); @@ -371,7 +365,7 @@ function openApplicationDetails(application) { attributes: { class: 'application-details-changes-requested-msg', }, - innerText: 'Changes requested', + innerText: 'Changes were already requested', }); applicationDetailsActionsContainer.append( applicationDetailsChangesRequestedMsg, @@ -739,11 +733,11 @@ closeDropdownBtn.addEventListener('click', () => { }); applicationAcceptButton.addEventListener('click', () => - updateUserApplication({ isAccepted: true }), + updateUserApplication({ status: 'accepted' }), ); applicationRejectButton.addEventListener('click', () => - updateUserApplication({ isAccepted: false }), + updateUserApplication({ status: 'rejected' }), ); applicationRequestChangesButton.addEventListener('click', () => { - updateUserApplication({ isRequestChanges: true }); + updateUserApplication({ status: 'changes_requested' }); }); diff --git a/applications/style.css b/applications/style.css index 8534b08f..f57fad8b 100644 --- a/applications/style.css +++ b/applications/style.css @@ -13,12 +13,9 @@ 0 1px 2px 0 rgba(0, 0, 0, 0.1); --elevation-3: 0px 1px 3px 0px rgba(0, 0, 0, 0.3), 0px 4px 8px 3px rgba(0, 0, 0, 0.15); - --color-green: green; - --color-red-variant1: #f43030; - --color-orange: #f5a623; - --color-pending: #f5a623; - --color-accepted: #28a745; - --color-rejected: #dc3545; + --color-accepted: #16a34a; + --color-pending: #ca8a04; + --color-rejected: #dc2626; } .user-text-index { @@ -224,7 +221,7 @@ body { } .clear-btn:hover { - background-color: var(--red-color); + background-color: var(--color-rejected); color: var(--white); } @@ -577,16 +574,16 @@ body { } .application-details .application-details-actions .application-details-reject { - color: var(--red-color); + color: var(--color-rejected); background-color: white; margin: 0 auto; - border: 2px solid var(--red-color); + border: 2px solid var(--color-rejected); } .application-details .application-details-actions .application-details-reject:is(:hover, :active, :focus-visible) { - background: var(--red-color); + background: var(--color-rejected); color: var(--white); transition: transform 0.2s ease; will-change: transform; @@ -633,16 +630,16 @@ body { .application-details-actions .application-details-request-changes { background-color: white; - color: var(--color-orange, #f5a623); + color: var(--color-pending); margin: 0 auto; width: 32%; - border: 2px solid var(--color-orange, #f5a623); + border: 2px solid var(--color-pending); } .application-details .application-details-actions .application-details-request-changes:is(:hover, :active, :focus-visible) { - background: var(--color-orange, #f5a623); + background: var(--color-pending); color: var(--white); transition: transform 0.2s ease; will-change: transform; @@ -674,15 +671,15 @@ body { } .application-details-accepted-msg { - color: var(--color-green); + color: var(--color-accepted); } .application-details-rejected-msg { - color: var(--red-color); + color: var(--color-rejected); } .application-details-changes-requested-msg { - color: var(--color-orange, #f5a623); + color: var(--color-pending); } .unauthorized-text { @@ -720,11 +717,11 @@ body { } .success { - background: var(--color-green); + background: var(--color-accepted); } .failure { - background: var(--color-red-variant1); + background: var(--color-rejected); } .disable-button { @@ -779,7 +776,7 @@ body { } } -@media screen and (min-width: 851px) { +@media screen and (min-width: 48rem) { .application-details .application-details-actions .application-details-reject { diff --git a/applications/utils.js b/applications/utils.js index 4b15f1f4..33a3513e 100644 --- a/applications/utils.js +++ b/applications/utils.js @@ -1,3 +1,5 @@ +import { showToastMessage } from '../components/toast/script.js'; + const BASE_URL = window.API_BASE_URL; function createElement({ type, attributes = {}, innerText }) { @@ -96,14 +98,17 @@ async function getIsSuperUser(isDev) { async function updateApplication({ applicationPayload, applicationId }) { try { - const res = await fetch(`${BASE_URL}/applications/${applicationId}`, { - method: 'PATCH', - credentials: 'include', - body: JSON.stringify(applicationPayload), - headers: { - 'Content-type': 'application/json', + const res = await fetch( + `${BASE_URL}/applications/${applicationId}/feedback`, + { + method: 'PATCH', + credentials: 'include', + body: JSON.stringify(applicationPayload), + headers: { + 'Content-type': 'application/json', + }, }, - }); + ); if (!res.ok) { const error = await res.json(); diff --git a/mock-data/applications/index.js b/mock-data/applications/index.js index 23896fa1..68008ab5 100644 --- a/mock-data/applications/index.js +++ b/mock-data/applications/index.js @@ -3,7 +3,7 @@ const fetchedApplications = [ id: 'lavEduxsb2C5Bl4s289P', createdAt: '2023-12-19T00:23:07.865Z', updatedAt: '2023-12-20T10:15:30.000Z', - applicationScore: 85, + score: 85, nudgeCount: 2, intro: { funFact: @@ -37,7 +37,7 @@ const fetchedApplications = [ { id: 'YwTi6zFNI3GlDsZVjD8C', createdAt: '2023-12-19T00:22:03.845Z', - applicationScore: 0, + score: 0, nudgeCount: 0, intro: { funFact: @@ -70,7 +70,7 @@ const fetchedApplications = [ { id: 'q2ZzerFKxdsUYMxoexS9', createdAt: '2023-12-19T00:21:26.595Z', - applicationScore: 42, + score: 42, nudgeCount: 5, intro: { funFact: @@ -191,6 +191,7 @@ const fetchedApplications = [ skills: 'REACT, NODE JS', institution: 'Christ church college', }, + feedback: '', status: 'pending', }, ]; @@ -199,7 +200,7 @@ const acceptedApplications = [ { id: 'lavEduxsb2C5Bl4s289P', createdAt: '2023-12-19T00:23:07.865Z', - applicationScore: 90, + score: 90, nudgeCount: 1, intro: { funFact: @@ -233,7 +234,7 @@ const acceptedApplications = [ { id: 'YwTi6zFNI3GlDsZVjD8C', createdAt: '2023-12-19T00:22:03.845Z', - applicationScore: 0, + score: 0, nudgeCount: 0, intro: { funFact: @@ -266,7 +267,7 @@ const acceptedApplications = [ { id: 'q2ZzerFKxdsUYMxoexS9', createdAt: '2023-12-19T00:21:26.595Z', - applicationScore: 55, + score: 55, nudgeCount: 3, intro: { funFact: @@ -333,7 +334,7 @@ const pendingApplications = [ { id: 'lavEduxsb2C5Bl4s289P', createdAt: '2023-12-19T00:23:07.865Z', - applicationScore: 70, + score: 70, nudgeCount: 4, intro: { funFact: From 4209c6d3e01b043503c22df31f6f833b8c5a08ed Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Thu, 12 Feb 2026 21:00:12 +0530 Subject: [PATCH 07/13] chore: refactor CSS selectors --- applications/script.js | 1 - applications/style.css | 65 +++++++++--------------------------------- applications/utils.js | 4 --- 3 files changed, 14 insertions(+), 56 deletions(-) diff --git a/applications/script.js b/applications/script.js index 794c2bf6..bdd6dbd2 100644 --- a/applications/script.js +++ b/applications/script.js @@ -6,7 +6,6 @@ import { updateApplication, getApplicationById, } from './utils.js'; -import { showToastMessage } from '../components/toast/script.js'; let nextLink; let isDataLoading = false; let totalApplicationCount = 0; diff --git a/applications/style.css b/applications/style.css index f57fad8b..46712a35 100644 --- a/applications/style.css +++ b/applications/style.css @@ -433,10 +433,7 @@ body { gap: 15px; } -.application-details - .application-details-main - .application-section - .section-title { +.section-title { color: var(--black-color); font-size: 18px; font-weight: 700; @@ -445,10 +442,7 @@ body { margin: 0; } -.application-details - .application-details-main - .application-section - .description { +.description { color: var(--color-gray); font-size: 13px; font-style: normal; @@ -457,10 +451,7 @@ body { margin: 0; } -.application-details - .application-details-main - .application-section - .description.status-badge { +.description.status-badge { color: var(--white); padding: 4px 12px; border-radius: 20px; @@ -468,41 +459,29 @@ body { text-transform: capitalize; } -.application-details - .application-details-main - .application-section - .description.status-pending { +.description.status-pending { background-color: var(--color-pending); } -.application-details - .application-details-main - .application-section - .description.status-accepted { +.description.status-accepted { background-color: var(--color-accepted); } -.application-details - .application-details-main - .application-section - .description.status-rejected { +.description.status-rejected { background-color: var(--color-rejected); } -.application-details .application-details-main .application-highlights { +.application-highlights { display: flex; - gap: 20px; + gap: 1.25rem; flex-wrap: wrap; background-color: #f8f9fa; - padding: 15px; + padding: 1rem; border-radius: 10px; margin-bottom: 10px; } -.application-details - .application-details-main - .application-highlights - .application-highlight-item { +.application-highlight-item { flex: 1; min-width: 120px; text-align: center; @@ -512,31 +491,20 @@ body { box-shadow: var(--elevation-1); } -.application-details - .application-details-main - .application-highlights - .application-highlight-item - .section-title { +.application-highlight-item .section-title { font-size: 12px; text-decoration: none; color: var(--color-gray); margin-bottom: 5px; } -.application-details - .application-details-main - .application-highlights - .application-highlight-item - .description { +.application-highlight-item .description { font-size: 24px; font-weight: 800; color: var(--color-primary); } -.application-details - .application-details-main - .application-section - .application-textarea { +.application-textarea { width: 90%; height: 150px; resize: none; @@ -662,8 +630,7 @@ body { } .application-details-accepted-msg, -.application-details-rejected-msg, -.application-details-changes-requested-msg { +.application-details-rejected-msg { font-weight: bold; font-size: 18px; width: 100%; @@ -678,10 +645,6 @@ body { color: var(--color-rejected); } -.application-details-changes-requested-msg { - color: var(--color-pending); -} - .unauthorized-text { text-align: center; } diff --git a/applications/utils.js b/applications/utils.js index 33a3513e..eed3973b 100644 --- a/applications/utils.js +++ b/applications/utils.js @@ -1,5 +1,3 @@ -import { showToastMessage } from '../components/toast/script.js'; - const BASE_URL = window.API_BASE_URL; function createElement({ type, attributes = {}, innerText }) { @@ -123,8 +121,6 @@ async function updateApplication({ applicationPayload, applicationId }) { } function showToast({ message, type }) { - const toast = document.getElementById('toast'); - if (!toast) return; toast.innerText = message; if (type === 'success') { From 1b6ef9f70a5829e78d22166ed0e47f4f4ee01213 Mon Sep 17 00:00:00 2001 From: Dhirenderchoudhary Date: Sun, 15 Feb 2026 18:18:19 +0530 Subject: [PATCH 08/13] feat: Enhance application details with status messages, hide action buttons after updates, add success toast for requesting changes, and update Yarn configuration. --- __tests__/applications/applications.test.js | 37 +++++++++++++++++ applications/index.html | 11 ++++- applications/script.js | 46 +++++++++++++++++---- applications/style.css | 7 +++- 4 files changed, 90 insertions(+), 11 deletions(-) diff --git a/__tests__/applications/applications.test.js b/__tests__/applications/applications.test.js index d3ded3a2..7ada8ee0 100644 --- a/__tests__/applications/applications.test.js +++ b/__tests__/applications/applications.test.js @@ -371,4 +371,41 @@ describe('Applications page', () => { const applicationCardElements = await page.$$('.application-card'); expect(applicationCardElements.length).toBe(acceptedApplications.length); }); + + it('should show success toast after requesting changes for an application', async function () { + await page.goto( + `${LOCAL_TEST_PAGE_URL}/applications?dev=true&status=pending`, + ); + await page.waitForSelector('.application-card'); + await page.click('.application-card'); + + await page.type( + '.application-textarea', + 'Please update your introduction.', + ); + + await page.click('#application-details-request-changes'); + await page.waitForSelector('[data-testid="toast-component"].show'); + const toastComponent = await page.$('[data-testid="toast-component"]'); + expect( + await toastComponent.evaluate((el) => el.classList.contains('show')), + ).toBe(true); + expect( + await toastComponent.evaluate((el) => el.classList.contains('hide')), + ).toBe(false); + expect( + await toastComponent.evaluate((el) => + el.classList.contains('success__toast'), + ), + ).toBe(true); + expect( + await toastComponent.evaluate((el) => + el.classList.contains('error__toast'), + ), + ).toBe(false); + const toastMessage = await page.$('[data-testid="toast-message"]'); + expect(await toastMessage.evaluate((el) => el.textContent)).toBe( + 'Application feedback submitted successfully', + ); + }); }); diff --git a/applications/index.html b/applications/index.html index 8594aa2d..4d558f46 100644 --- a/applications/index.html +++ b/applications/index.html @@ -125,9 +125,14 @@

Status

/>
-
+