From ce5e242a1305f537f936da2e874ff4d0778b25a8 Mon Sep 17 00:00:00 2001 From: Sameer Choudhary <142528209+samnotfound404@users.noreply.github.com> Date: Fri, 12 Jul 2024 09:53:30 +0530 Subject: [PATCH] Updated registration (#104) --- package.json | 2 +- src/app/(routes)/admin/students/page.tsx | 48 +++-- .../NewTableComponent/StudentModal.tsx | 180 +++++++++++++++--- src/helpers/api.ts | 22 +++ src/helpers/types.ts | 7 +- yarn.lock | 22 ++- 6 files changed, 229 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index 9ea4b60c..c5365d8a 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@reduxjs/toolkit": "^2.0.1", "@tanstack/react-table": "^8.11.2", "@types/qs": "^6.9.14", - "antd": "^5.13.1", + "antd": "^5.19.1", "axios": "^1.6.3", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", diff --git a/src/app/(routes)/admin/students/page.tsx b/src/app/(routes)/admin/students/page.tsx index 4c9a763d..416435c9 100644 --- a/src/app/(routes)/admin/students/page.tsx +++ b/src/app/(routes)/admin/students/page.tsx @@ -1,37 +1,49 @@ "use client"; -import { fetchStudentData } from "@/helpers/api"; +import { useState, useEffect } from 'react'; +import { fetchStudentData, } from "@/helpers/api"; import Cookies from "js-cookie"; import Table from "@/components/NewTableComponent/Table"; -import type {DTO} from '@/dto/StudentDto' -import { - MaterialReactTable, - useMaterialReactTable, - type MRT_Row, - createMRTColumnHelper, -} from 'material-react-table'; +import type { DTO } from '@/dto/StudentDto'; +import { createMRTColumnHelper } from 'material-react-table'; import generateColumns from "@/components/NewTableComponent/ColumnMapping"; import { jsondto } from "@/dto/StudentDto"; +import { Form } from 'antd'; +import { cookies } from 'next/headers'; +const hiddenColumns = ['userId', 'programId','id']; +const StudentPage = () => { + const [students, setStudents] = useState([]); + const columnHelper = createMRTColumnHelper(); + const columns = generateColumns(jsondto); -const hiddenColumns = ['userId', 'programId', 'id']; -const StudentPage = async () => { - const columnHelper = createMRTColumnHelper(); - const columns = generateColumns(jsondto) - console.log(columns) - const AllStudents = await fetchStudentData(Cookies.get("accessToken"),null); + + + const visibleColumns = columns.filter( - (column:any) => !hiddenColumns.includes(column?.accessorKey) + (column: any) => !hiddenColumns.includes(column?.accessorKey) ); - + + useEffect(() => { + const fetchData = async () => { + const data = await fetchStudentData(Cookies.get("accessToken"), null); + setStudents(data); + console.log(data); + }; + + + fetchData(); + }, []); + + return (

Students

- {AllStudents && ( + {students.length > 0 && ( diff --git a/src/components/NewTableComponent/StudentModal.tsx b/src/components/NewTableComponent/StudentModal.tsx index 363b0c7b..4c572108 100644 --- a/src/components/NewTableComponent/StudentModal.tsx +++ b/src/components/NewTableComponent/StudentModal.tsx @@ -15,7 +15,10 @@ import CircularProgress from '@mui/material/CircularProgress'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import { grey } from '@mui/material/colors'; import { Button } from '@mui/material'; + +import Cookies from 'js-cookie'; import Loader from '@/components/Loader/loader'; +const redirect = () => {}; const theme = createTheme({ palette: { primary: { @@ -49,32 +52,122 @@ const style = { const baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL; +const handleRegistration = async (accessToken, studentId, seasonId, currentStatus) => { + if (!accessToken) { + console.error('No access token provided'); + return; + } + + try { + const res = await fetch(`${baseUrl}/api/v1/registrations`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify([{ + studentId, + seasonId, + registered: !currentStatus + }]), + }); + + if (!res.ok) { + const errorDetails = await res.json(); + console.error(`Failed to update registration status: ${errorDetails.message}`); + throw new Error(`Failed to update registration status: ${errorDetails.message}`); + //Will change it in a separate console removal PR + } + + console.log('Registration status updated successfully'); + return true; + } catch (error) { + console.error('Error updating registration status:', error.message); + alert(`Error updating registration status: ${error.message}`); + return false; + } +}; + export default function StudentModal({ open, setOpen, id }) { const [studentData, setStudentData] = useState(null); - const [loading, setLoading] = useState(false); + const [registrationData, setRegistrationData] = useState(null); + const [loading, setLoading] = useState(true); - useEffect(() => { - const fetchStudentData = async () => { - setLoading(true); - try { - const response = await fetch(`${baseUrl}/api/v1/students/${id}`); - const data = await response.json(); - setStudentData(data); - } catch (error) { - console.error('Error fetching student data:', error); + const fetchStudentData = async (accessToken, id) => { + if (!accessToken) { + console.error('No access token provided'); + return; + } + + setLoading(true); + try { + const response = await fetch(`${baseUrl}/api/v1/students/${id}`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }); + if (!response.ok) { + throw new Error(`Error fetching student data: ${response.statusText}`); } + const data = await response.json(); + setStudentData(data); + } catch (error) { + console.error('Error fetching student data:', error); + } finally { setLoading(false); - }; + } + }; + + const fetchRegistrationData = async (accessToken, studentId) => { + if (!accessToken) { + console.error('No access token provided'); + return; + } + + setLoading(true); + try { + const response = await fetch(`${baseUrl}/api/v1/registrations`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }); + + if (!response.ok) { + throw new Error(`Error fetching registration data: ${response.statusText}`); + } + const allData = await response.json(); + const filteredData = allData.filter((registration) => registration.student.id === studentId); + setRegistrationData(filteredData); + } catch (error) { + + } finally { + setLoading(false); + } + }; + useEffect(() => { if (open && id) { - fetchStudentData(); + const accessToken = Cookies.get("accessToken"); + fetchStudentData(accessToken, id); + fetchRegistrationData(accessToken, id); } }, [open, id]); const handleClose = () => setOpen(false); + const handleStatusChange = async (studentId, seasonId, currentStatus) => { + const success = await handleRegistration(Cookies.get("accessToken"), studentId, seasonId, currentStatus); + if (success) { + setRegistrationData((prevData) => + prevData.map((registration) => + registration.season.id === seasonId ? { ...registration, registered: !currentStatus } : registration + ) + ); + } + }; + return ( - + Name - {studentData.user.name} + {studentData.user ? studentData.user.name : 'N/A'} Email - {studentData.user.email} + {studentData.user ? studentData.user.email : 'N/A'} Contact - {studentData.user.contact} + {studentData.user ? studentData.user.contact : 'N/A'}
@@ -187,24 +280,24 @@ export default function StudentModal({ open, setOpen, id }) { Branch - {studentData.program.branch} + {studentData.program ? studentData.program.branch : 'N/A'} Course - {studentData.program.course} + {studentData.program ? studentData.program.course : 'N/A'} Year - {studentData.program.year} + {studentData.program ? studentData.program.year : 'N/A'} Department - {studentData.program.department} + {studentData.program ? studentData.program.department : 'N/A'} @@ -222,7 +315,7 @@ export default function StudentModal({ open, setOpen, id }) { - {studentData.resumes.map((resume) => ( + {studentData.resumes ? studentData.resumes.map((resume) => ( {resume.id} @@ -238,7 +331,7 @@ export default function StudentModal({ open, setOpen, id }) { {resume.verified.toString()} - ))} + )) : 'N/A'} @@ -249,19 +342,52 @@ export default function StudentModal({ open, setOpen, id }) { - ID Penalty Reason - {studentData.penalties.map((penalty) => ( + {studentData.penalties ? studentData.penalties.map((penalty) => ( - {penalty.id} {penalty.penalty} {penalty.reason} - ))} + )) : 'N/A'} + +
+ + + Registration + + + + + + + Year + Type + Status + Actions + + + + {registrationData ? registrationData.map((registration) => ( + + + {registration.season.year} + {registration.season.type} + {registration.registered ? "Registered" : "Not Registered"} + + + + + )) : 'N/A'}
@@ -273,4 +399,4 @@ export default function StudentModal({ open, setOpen, id }) { ); -} \ No newline at end of file +} diff --git a/src/helpers/api.ts b/src/helpers/api.ts index 53b37953..82193cb8 100644 --- a/src/helpers/api.ts +++ b/src/helpers/api.ts @@ -203,6 +203,27 @@ export const fetchStudentData = async ( return json; }; +export const fetchSeasonData = async ( + accessToken: string | undefined, + filter: string | undefined +) => { + if (!accessToken || accessToken === undefined) { + redirect(); + return; + } + const res = await fetch( + filter ? url(`/registrations?${filter}`) : url("/registrations"), + { + next: { tags: ["AllStudents"] }, + headers: { + Authorization: `Bearer ${accessToken}`, + }, + } + ); + const json = await res.json(); + return json; +}; + export const fetchCompanyRecruiters = async ( accessToken: string | undefined, companyId: string | undefined @@ -300,6 +321,7 @@ export const fetchRecruiterData = async ( redirect(); return; } + const res = await fetch( filter ? url(`/recruiters?${filter}`) : url("/recruiters"), { diff --git a/src/helpers/types.ts b/src/helpers/types.ts index 33f5068f..92fdeba5 100644 --- a/src/helpers/types.ts +++ b/src/helpers/types.ts @@ -1,4 +1,5 @@ export interface ResumePatchData { - id: string; - verified: boolean; -} + id: string; + verified: boolean; + } + diff --git a/yarn.lock b/yarn.lock index 77e7ba04..e0c2b9ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1665,7 +1665,7 @@ ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -antd@^5.13.1: +antd@^5.19.1: version "5.19.1" resolved "https://registry.yarnpkg.com/antd/-/antd-5.19.1.tgz#5bd5ddef96f7b529ce37310ba9997032160d3443" integrity sha512-ogGEUPaamSZ2HFGvlyLBNfxZ0c4uX5aqEIwMtmqRTPNjcLY/k+qdMmdWrMMiY1CDJ3j1in5wjzQTvREG+do65g== @@ -4916,7 +4916,16 @@ string-convert@^0.2.0: resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4988,7 +4997,14 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==