11import {
2+ Button ,
23 Center ,
34 Heading ,
45 Table ,
@@ -11,18 +12,44 @@ import {
1112 Tr ,
1213 VStack ,
1314} from "@chakra-ui/react"
15+ import axios from "axios"
16+ import { useParams } from "react-router-dom"
1417import { usePoints , useStudentExampleSubmissions } from "../components/Hooks"
1518
1619export default function Participants ( ) {
20+ const { courseSlug } = useParams ( )
1721 const { data : participants } = usePoints ( )
1822 const { data : exampleSubmissions } = useStudentExampleSubmissions ( )
23+
24+ const downloadAssignmentPoints = async ( ) => {
25+ const response = await axios . get < Blob > ( `/courses/${ courseSlug } /assignmentPoints` , {
26+ responseType : 'blob' ,
27+ headers : { 'Accept' : 'text/csv' }
28+ } ) ;
29+ const link = document . createElement ( 'a' ) ;
30+ // why the weird casting?
31+ // response above is a Blob { size: ..., type: "text/csv" }
32+ // but createObjectURL sees it as AxiosResponse<Blob, any>
33+ // and also, response.data is undefiend. ¯\_(ツ)_/¯
34+ link . href = window . URL . createObjectURL ( response as unknown as Blob ) ;
35+ const currentDate = new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
36+ link . download = `${ courseSlug } _assignment_points_${ currentDate } .csv` ;
37+ document . body . appendChild ( link ) ;
38+ link . click ( ) ;
39+ document . body . removeChild ( link ) ;
40+ }
41+
42+
1943 if ( ! participants ) return < > </ >
2044 return (
2145 < VStack >
2246 < TableContainer p = { 8 } my = { 4 } layerStyle = "segment" >
2347 < Heading m = { 2 } mt = { 0 } fontSize = "3xl" >
2448 { participants . length } Participants
2549 </ Heading >
50+ < Button ml = { 2 } mb = { 2 } rounded = "md" onClick = { downloadAssignmentPoints } >
51+ Download Assignment points as CSV
52+ </ Button >
2653 < Table maxW = "container.sm" >
2754 < Thead >
2855 < Tr >
0 commit comments