Add import button

This commit is contained in:
adam-skowronek 2022-05-30 21:38:45 +02:00
parent a607964114
commit 859885a520
4 changed files with 81 additions and 29 deletions

View File

@ -1,13 +1,19 @@
import React from "react"; import React from 'react'
import { QueryClient, QueryClientProvider } from "react-query"; import { QueryClient, QueryClientProvider } from 'react-query'
import { Route, Routes } from "react-router-dom"; import { Route, Routes } from 'react-router-dom'
import "./App.css"; import './App.css'
import Coordinator from "./views/coordinator/Coordinator"; import Coordinator from './views/coordinator/Coordinator'
import Groups from "./views/coordinator/Groups"; import Groups from './views/coordinator/Groups'
import Leaders from "./views/coordinator/Leaders"; import Leaders from './views/coordinator/Leaders'
import Students from "./views/coordinator/Students"; import Students from './views/coordinator/Students'
const queryClient = new QueryClient(); const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
},
},
})
function App() { function App() {
return ( return (
@ -23,7 +29,7 @@ function App() {
</Routes> </Routes>
</QueryClientProvider> </QueryClientProvider>
</div> </div>
); )
} }
export default App; export default App

View File

@ -1,10 +1,23 @@
import axiosInstance from "./axiosInstance"; import axiosInstance from './axiosInstance'
interface StudentResponse { interface StudentResponse {
max_pages: number, max_pages: number
students: {first_name: string, last_name: string, index: number, mode: boolean; group: any}[] students: {
first_name: string
last_name: string
index: number
mode: boolean
group: any
}[]
} }
export const getStudents = () => axiosInstance.get<StudentResponse>( export const getStudents = () =>
"http://127.0.0.1:5000/api/coordinator/students" axiosInstance.get<StudentResponse>(
'http://127.0.0.1:5000/api/coordinator/students',
)
export const uploadStudents = (payload: FormData) =>
axiosInstance.post(
'http://127.0.0.1:5000/api/coordinator/students/upload/',
payload,
) )

View File

@ -1,8 +1,8 @@
import { NavLink } from "react-router-dom"; import { NavLink } from 'react-router-dom'
const TopBar = () => { const TopBar = () => {
const linkClass = ({ isActive }: { isActive: boolean }) => const linkClass = ({ isActive }: { isActive: boolean }) =>
isActive ? "underline font-bold" : ""; isActive ? 'underline font-bold' : ''
return ( return (
<div className="flex items-center bg-gray-300 p-6"> <div className="flex items-center bg-gray-300 p-6">
<h1 className="text-xl font-bold">System PRI</h1> <h1 className="text-xl font-bold">System PRI</h1>
@ -18,7 +18,7 @@ const TopBar = () => {
</NavLink> </NavLink>
</div> </div>
</div> </div>
); )
}; }
export default TopBar; export default TopBar

View File

@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import { useQuery } from 'react-query' import { useMutation, useQuery } from 'react-query'
import { getStudents } from '../../api/students' import { getStudents, uploadStudents } from '../../api/students'
const TableHeader = (props: { children: React.ReactNode }) => ( const TableHeader = (props: { children: React.ReactNode }) => (
<th className="px-4 py-2 font-medium text-left text-gray-900 whitespace-nowrap"> <th className="px-4 py-2 font-medium text-left text-gray-900 whitespace-nowrap">
@ -9,17 +9,50 @@ const TableHeader = (props: { children: React.ReactNode }) => (
) )
const Students = () => { const Students = () => {
const { isLoading, data: students } = useQuery('students', () => const {
getStudents(), isLoading: isStudentsLoading,
data: students,
refetch: refetchStudents,
} = useQuery('students', () => getStudents())
const { mutate: mutateUpload } = useMutation(
'uploadStudents',
(payload: FormData) => uploadStudents(payload),
{
onSuccess: () => refetchStudents(),
},
) )
if (isLoading) {
const handleOnChange = (event: any) => {
const file = event.target.files[0]
const payload = new FormData()
payload.append('file', file, file.name)
mutateUpload(payload)
}
if (isStudentsLoading) {
return <div>Ładowanie</div> return <div>Ładowanie</div>
} }
return ( return (
<div> <div>
<button className="bg-green-400 p-3 rounded-lg text-white font-bold hover:bg-green-300"> <button className="bg-green-400 p-3 rounded-lg text-white font-extrabold hover:bg-green-300">
Dodaj nowego studenta Dodaj nowego studenta
</button> </button>
<label
className="ml-4 text-green-400 font-extrabold rounded-lg border-2 p-3 border-green-400 hover:border-green-300 cursor-pointer"
htmlFor="file"
>
Importuj
</label>
<input
type="file"
id="file"
name="avatar"
accept=".csv"
className="hidden"
onChange={handleOnChange}
/>
<div className="flex mx-auto mt-5 overflow-hidden overflow-x-auto border border-gray-100 rounded"> <div className="flex mx-auto mt-5 overflow-hidden overflow-x-auto border border-gray-100 rounded">
<table className="min-w-full text-sm divide-y divide-gray-200"> <table className="min-w-full text-sm divide-y divide-gray-200">
<thead> <thead>
@ -34,7 +67,7 @@ const Students = () => {
<tbody className="divide-y divide-gray-100"> <tbody className="divide-y divide-gray-100">
{students?.data?.students?.map( {students?.data?.students?.map(
({ first_name, last_name, index, group, mode }) => ( ({ first_name, last_name, index, group, mode }) => (
<tr> <tr key={index}>
<td className="px-4 py-2 font-medium text-gray-900 whitespace-nowrap"> <td className="px-4 py-2 font-medium text-gray-900 whitespace-nowrap">
{first_name} {first_name}
</td> </td>