@@ -6,7 +6,12 @@ import type { DTO } from "@/dto/StudentDto";
66import generateColumns from "@/components/NewTableComponent/ColumnMapping" ;
77import { jsondto } from "@/dto/StudentDto" ;
88import { CSVImportModal } from "@/components/common/CSVImportModal" ;
9- import { addStudents , promoteToManagers , deleteStudents } from "@/helpers/admin/api" ;
9+ import {
10+ addStudents ,
11+ promoteToManagers ,
12+ deleteStudents ,
13+ updateStudents ,
14+ } from "@/helpers/admin/api" ;
1015import { fetchPrograms , fetchAllSeasons } from "@/helpers/api" ;
1116import { Program } from "@/dto/SalaryDto" ;
1217import { toast } from "react-hot-toast" ;
@@ -36,6 +41,7 @@ const StudentPage = () => {
3641 const [ selectedRows , setSelectedRows ] = useState < DTO [ ] > ( [ ] ) ;
3742 const [ seasons , setSeasons ] = useState < { id : string ; name : string } [ ] > ( [ ] ) ;
3843 const [ bulkLoading , setBulkLoading ] = useState ( false ) ;
44+ const [ cpiImportOpen , setCpiImportOpen ] = useState ( false ) ;
3945
4046 const visibleColumns = columns . filter (
4147 ( column : any ) => ! hiddenColumns . includes ( column ?. accessorKey ) ,
@@ -97,7 +103,38 @@ const StudentPage = () => {
97103 }
98104 setImportLoading ( false ) ;
99105 } ;
106+ const handleCpiImport = async ( data : any [ ] ) => {
107+ try {
108+ const payload = data
109+ . map ( ( row ) => {
110+ const student = students . find (
111+ ( s ) => String ( s . rollNo ) === String ( row . rollNo ) ,
112+ ) ;
113+
114+ if ( ! student ) return null ;
115+
116+ return {
117+ id : student . id ,
118+ cpi : Number ( row . cpi ) ,
119+ } ;
120+ } )
121+ . filter ( Boolean ) ;
122+ if ( payload . length === 0 ) {
123+ toast . error ( "No matching roll numbers found" ) ;
124+ return ;
125+ }
126+ await updateStudents ( payload ) ;
127+
128+ toast . success ( `Updated CPI for ${ payload . length } students` ) ;
100129
130+ const updatedData = await fetchStudentData ( ) ;
131+ setStudents ( updatedData ) ;
132+
133+ setCpiImportOpen ( false ) ;
134+ } catch ( e ) {
135+ toast . error ( "Failed to update CPI" ) ;
136+ }
137+ } ;
101138 const parseStudentRow = ( row : any ) => {
102139 if ( ! row . rollNo || ! row . name || ! row . email ) return null ;
103140
@@ -203,6 +240,9 @@ const StudentPage = () => {
203240 toast . error ( "Failed to delete students" ) ;
204241 }
205242 setBulkLoading ( false ) ;
243+ } else if ( action === "update-cpi" ) {
244+ setBulkModalOpen ( false ) ;
245+ setCpiImportOpen ( true ) ;
206246 }
207247 // Add more actions here later
208248 } ;
@@ -243,6 +283,16 @@ const StudentPage = () => {
243283 entityName = "students"
244284 cleanData = { true }
245285 />
286+ < CSVImportModal
287+ open = { cpiImportOpen }
288+ onClose = { ( ) => setCpiImportOpen ( false ) }
289+ onSubmit = { handleCpiImport }
290+ templateHeaders = { [ "rollNo" , "cpi" ] }
291+ templateFileName = "cpi_update_template.csv"
292+ entityName = "cpi updates"
293+ parseRow = { ( row ) => row }
294+ cleanData = { true }
295+ />
246296 < div >
247297 { students . length > 0 && (
248298 < Table
@@ -260,7 +310,11 @@ const StudentPage = () => {
260310 actions = { [
261311 { label : "Create registration for season" , value : "register-season" } ,
262312 { label : "Promote to CAMC Member" , value : "promote-tpc" } ,
263- { label : "🗑️ Delete Students (Admin Only)" , value : "delete-students" } ,
313+ {
314+ label : "🗑️ Delete Students (Admin Only)" ,
315+ value : "delete-students" ,
316+ } ,
317+ { label : "Bulk CPI Update (Admin Only)" , value : "update-cpi" } ,
264318 ] }
265319 onSubmit = { handleBulkModalSubmit }
266320 seasons = { seasons }
0 commit comments