@@ -38,13 +38,16 @@ import {
3838 Search ,
3939 Plus ,
4040 Calendar ,
41+ CalendarOff ,
4142 Clock ,
4243 Filter ,
4344 MapPin
4445} from 'lucide-react' ;
46+ import { Pagination } from '@/components/shared' ;
4547import { TakeAttendanceModal } from './class-detail/TakeAttendanceModal' ;
48+ import { BulkCancelClassesModal } from '@/components/BulkCancelClassesModal' ;
4649
47- const STATUS_OPTIONS : Array < { label : string ; value : string } > = [
50+ const STATUS_OPTIONS : { label : string ; value : string } [ ] = [
4851 { label : 'All Status' , value : 'all' } ,
4952 { label : 'Active' , value : SelectedClassStatus . Active } ,
5053 { label : 'Scheduled' , value : SelectedClassStatus . Scheduled } ,
@@ -89,10 +92,14 @@ export default function ClassesPage() {
8992 const [ showCreateModal , setShowCreateModal ] = useState ( false ) ;
9093 const [ programSearch , setProgramSearch ] = useState ( '' ) ;
9194 const [ attendanceClass , setAttendanceClass ] = useState < Class | null > ( null ) ;
95+ const [ showBulkCancel , setShowBulkCancel ] = useState ( false ) ;
96+ const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
97+ const [ itemsPerPage , setItemsPerPage ] = useState ( 20 ) ;
9298
93- const { data : classesResp } = useSWR < ServerResponseMany < Class > > (
94- '/api/program-classes?per_page=100'
95- ) ;
99+ const { data : classesResp , mutate : mutateClasses } =
100+ useSWR < ServerResponseMany < Class > > (
101+ '/api/program-classes?per_page=100'
102+ ) ;
96103 const { data : programsResp } = useSWR < ServerResponseMany < Program > > (
97104 showCreateModal ? '/api/programs' : null
98105 ) ;
@@ -185,6 +192,15 @@ export default function ClassesPage() {
185192 statusFilter
186193 ] ) ;
187194
195+ useEffect ( ( ) => {
196+ setCurrentPage ( 1 ) ;
197+ } , [ searchQuery , todayOnly , attendanceConcerns , programFilter , statusFilter ] ) ;
198+
199+ const paginatedClasses = useMemo ( ( ) => {
200+ const start = ( currentPage - 1 ) * itemsPerPage ;
201+ return filteredClasses . slice ( start , start + itemsPerPage ) ;
202+ } , [ filteredClasses , currentPage , itemsPerPage ] ) ;
203+
188204 return (
189205 < div className = "-mx-6 -mt-4 -mb-4 min-h-[calc(100vh-4rem)] bg-[#E2E7EA]" >
190206 < div className = "max-w-7xl mx-auto px-6 py-8" >
@@ -198,13 +214,23 @@ export default function ClassesPage() {
198214 Manage and monitor all classes at your facility
199215 </ p >
200216 </ div >
201- < Button
202- className = "bg-[#F1B51C] text-[#203622] hover:bg-[#d9a419] gap-2"
203- onClick = { ( ) => setShowCreateModal ( true ) }
204- >
205- < Plus className = "size-5" />
206- Create New Class
207- </ Button >
217+ < div className = "flex gap-2" >
218+ < Button
219+ variant = "outline"
220+ className = "border-red-300 text-red-700 hover:bg-red-50 hover:border-red-400 gap-2"
221+ onClick = { ( ) => setShowBulkCancel ( true ) }
222+ >
223+ < CalendarOff className = "size-4" />
224+ Cancel Classes by Instructor
225+ </ Button >
226+ < Button
227+ className = "bg-[#F1B51C] text-[#203622] hover:bg-[#d9a419] gap-2"
228+ onClick = { ( ) => setShowCreateModal ( true ) }
229+ >
230+ < Plus className = "size-5" />
231+ Create New Class
232+ </ Button >
233+ </ div >
208234 </ div >
209235 </ div >
210236
@@ -292,11 +318,6 @@ export default function ClassesPage() {
292318 </ div >
293319 </ div >
294320
295- < div className = "mb-4 text-sm text-gray-600" >
296- Showing { filteredClasses . length } { ' ' }
297- { filteredClasses . length === 1 ? 'class' : 'classes' }
298- </ div >
299-
300321 < div className = "bg-white rounded-lg border border-gray-200 overflow-hidden" >
301322 < table className = "w-full" >
302323 < thead className = "bg-[#E2E7EA] border-b border-gray-200" >
@@ -322,7 +343,7 @@ export default function ClassesPage() {
322343 </ tr >
323344 </ thead >
324345 < tbody className = "divide-y divide-gray-200" >
325- { filteredClasses . length === 0 ? (
346+ { paginatedClasses . length === 0 ? (
326347 < tr >
327348 < td
328349 colSpan = { 6 }
@@ -332,7 +353,7 @@ export default function ClassesPage() {
332353 </ td >
333354 </ tr >
334355 ) : (
335- filteredClasses . map ( ( cls ) => (
356+ paginatedClasses . map ( ( cls ) => (
336357 < ClassRow
337358 key = { cls . id }
338359 cls = { cls }
@@ -349,6 +370,14 @@ export default function ClassesPage() {
349370 ) }
350371 </ tbody >
351372 </ table >
373+ < Pagination
374+ totalItems = { filteredClasses . length }
375+ itemsPerPage = { itemsPerPage }
376+ currentPage = { currentPage }
377+ onPageChange = { setCurrentPage }
378+ onItemsPerPageChange = { setItemsPerPage }
379+ itemLabel = "classes"
380+ />
352381 </ div >
353382 </ div >
354383
@@ -413,6 +442,12 @@ export default function ClassesPage() {
413442 className = { attendanceClass . name }
414443 />
415444 ) }
445+
446+ < BulkCancelClassesModal
447+ open = { showBulkCancel }
448+ onClose = { ( ) => setShowBulkCancel ( false ) }
449+ mutate = { mutateClasses }
450+ />
416451 </ div >
417452 ) ;
418453}
0 commit comments