Fix export/import of students, add grade card view
This commit is contained in:
parent
5d94bba15f
commit
292ef17be6
@ -23,6 +23,8 @@ import SupervisorSchedule from './views/supervisor/SupervisorSchedule'
|
||||
import Home from './views/coordinator/Home'
|
||||
import SupervisorAvailabilities from './views/coordinator/SupervisorAvailabilities'
|
||||
import AvailabilitySchedule from './views/coordinator/AvailabilitySchedule'
|
||||
import GradeCard from './views/GradeCard'
|
||||
import Group from './views/coordinator/Group'
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
@ -41,6 +43,7 @@ function App() {
|
||||
<Route path="coordinator" element={<Coordinator />}>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="groups" element={<Groups />} />
|
||||
<Route path="groups/:id" element={<Group />} />
|
||||
<Route path="students" element={<Students />} />
|
||||
<Route path="leaders" element={<Leaders />} />
|
||||
<Route path="add-student" element={<AddStudent />} />
|
||||
@ -52,6 +55,7 @@ function App() {
|
||||
path="supervisors_availability"
|
||||
element={<SupervisorAvailabilities />}
|
||||
/>
|
||||
<Route path="groups/:id/grade-card" element={<GradeCard />} />
|
||||
<Route
|
||||
path="supervisors_availability/:id"
|
||||
element={<AvailabilitySchedule />}
|
||||
|
33
frontend/src/api/grades.ts
Normal file
33
frontend/src/api/grades.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import axiosInstance from './axiosInstance'
|
||||
|
||||
export const updateGradesFirstTerm = (
|
||||
groupId: number,
|
||||
supervisorId: number,
|
||||
payload: any,
|
||||
) => {
|
||||
return axiosInstance.patch(
|
||||
`project_supervisor/project-grade-sheet/group/${groupId}/first-term/?id=${supervisorId}`,
|
||||
payload,
|
||||
)
|
||||
}
|
||||
|
||||
export const updateGradesSecondTerm = (
|
||||
groupId: number,
|
||||
supervisorId: number,
|
||||
payload: any,
|
||||
) => {
|
||||
return axiosInstance.patch(
|
||||
`project_supervisor/project-grade-sheet/group/${groupId}/second-term/?id=${supervisorId}`,
|
||||
payload,
|
||||
)
|
||||
}
|
||||
|
||||
export const getGradesForSupervisor = (
|
||||
groupId: number,
|
||||
term: number,
|
||||
supervisorId: number,
|
||||
) => {
|
||||
return axiosInstance.get<{ [key: string]: any }>(
|
||||
`project_supervisor/project-grade-sheet/group/${groupId}/?term=${term}&id=${supervisorId}`,
|
||||
)
|
||||
}
|
@ -38,3 +38,6 @@ export const createGroup = (year_group_id: number, payload: CreateGroup) =>
|
||||
|
||||
export const deleteGroup = (id: number) =>
|
||||
axiosInstance.delete(`coordinator/groups/${id}/`)
|
||||
|
||||
export const getGroup = (id: number) =>
|
||||
axiosInstance.get<Group>(`coordinator/groups/${id}/detail/`)
|
||||
|
@ -35,13 +35,21 @@ export const getStudents = (
|
||||
export const createStudent = (payload: Student & { year_group_id: number }) =>
|
||||
axiosInstance.post('coordinator/students/', payload)
|
||||
|
||||
export const uploadStudents = (payload: FormData) =>
|
||||
axiosInstance.post('coordinator/students/upload/', payload)
|
||||
export const uploadStudents = (payload: FormData, year_group_id: number) =>
|
||||
axiosInstance.post(
|
||||
`coordinator/students/upload/?id=${year_group_id}`,
|
||||
payload,
|
||||
)
|
||||
|
||||
export const deleteStudent = (index: number) =>
|
||||
axiosInstance.delete(`coordinator/students/${index}/`)
|
||||
|
||||
export const downloadStudents = (mode: boolean) =>
|
||||
axiosInstance.post(`coordinator/students/download/?mode=${Number(mode)}`, {
|
||||
export const downloadStudents = (mode: boolean, year_group_id: number) =>
|
||||
axiosInstance.post(
|
||||
`coordinator/students/download/?mode=${Number(
|
||||
mode,
|
||||
)}&year_group_id=${year_group_id}`,
|
||||
{
|
||||
responseType: 'blob',
|
||||
})
|
||||
},
|
||||
)
|
||||
|
13
frontend/src/views/GradeCard.module.css
Normal file
13
frontend/src/views/GradeCard.module.css
Normal file
@ -0,0 +1,13 @@
|
||||
.grade-table td,
|
||||
.grade-table th {
|
||||
border: 1px solid lightgray;
|
||||
}
|
||||
.grade-table th {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
.grade-table input {
|
||||
background: #f2f2f2;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
}
|
721
frontend/src/views/GradeCard.tsx
Normal file
721
frontend/src/views/GradeCard.tsx
Normal file
@ -0,0 +1,721 @@
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useMutation, useQuery } from 'react-query'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import useLocalStorageState from 'use-local-storage-state'
|
||||
import {
|
||||
getGradesForSupervisor,
|
||||
updateGradesFirstTerm,
|
||||
updateGradesSecondTerm,
|
||||
} from '../api/grades'
|
||||
import styles from './GradeCard.module.css' // Import css modules stylesheet as styles
|
||||
|
||||
const GradeCard = () => {
|
||||
const { register, handleSubmit, setValue } = useForm()
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const [supervisorId] = useLocalStorageState('supervisorId')
|
||||
|
||||
useQuery(
|
||||
['getGradesFirst'],
|
||||
() => getGradesForSupervisor(Number(id), 1, Number(supervisorId)),
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
for (const [key, value] of Object.entries(data.data)) {
|
||||
if (key !== 'id') setValue(key, value)
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
useQuery(
|
||||
['getGradesSecond'],
|
||||
() => getGradesForSupervisor(Number(id), 2, Number(supervisorId)),
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
for (const [key, value] of Object.entries(data.data)) {
|
||||
if (key !== 'id') setValue(key, value)
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const { mutate: mutateGradesFirstTerm } = useMutation(
|
||||
'update_grades_first',
|
||||
(payload: any) => updateGradesFirstTerm(1, 1, payload),
|
||||
)
|
||||
|
||||
const { mutate: mutateGradesSecondTerm } = useMutation(
|
||||
'update_grades_second',
|
||||
(payload: any) => updateGradesSecondTerm(1, 1, payload),
|
||||
)
|
||||
|
||||
const onSubmit = (data: any) => {
|
||||
let firstTermGrades: { [key: string]: any } = {}
|
||||
let secondTermGrades: { [key: string]: any } = {}
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
if (key.endsWith('_1')) {
|
||||
firstTermGrades[key] = Number(value)
|
||||
} else {
|
||||
secondTermGrades[key] = Number(value)
|
||||
}
|
||||
}
|
||||
mutateGradesFirstTerm(firstTermGrades)
|
||||
mutateGradesSecondTerm(secondTermGrades)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles['grade-table']}>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="flex justify-end">
|
||||
<button className="btn btn-success mb-2">ZAPISZ</button>
|
||||
</div>
|
||||
<table className=" table-normal border-collapse">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Kryterium</th>
|
||||
<th>Waga I semestr</th>
|
||||
<th>Waga II semestr</th>
|
||||
<th>Punkty I semestr [0,1,3,4]</th>
|
||||
<th>Punkty II semestr [0,1,3,4]</th>
|
||||
<th>Udział I</th>
|
||||
<th>Udział II</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<h3 className="text-xl font-bold">Prezentacja</h3>
|
||||
</td>
|
||||
<td>1,5</td>
|
||||
<td>1,5</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Czy prezentacja zawierała wszystkie wymagane treści (cel i
|
||||
założenia projektowe, podział prac na semestry, przegląd
|
||||
zrealizowanych funkcjonalności, architektura i użyte
|
||||
technologie, role osób w zespole, demo systemu)? * (oceniane
|
||||
podczas obrony semestralnej)
|
||||
</td>
|
||||
<td>3</td>
|
||||
<td>1</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('presentation_required_content_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('presentation_required_content_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>3,5%</td>
|
||||
<td>1,2%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Czy prezentacja (omówienie projektu i jego demonstracja) była
|
||||
przeprowadzona zgodnie ze sztuką? (oceniane podczas obrony
|
||||
semestralnej)
|
||||
</td>
|
||||
<td>4</td>
|
||||
<td>4</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('presentation_was_compatible_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('presentation_was_compatible_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>4,6%</td>
|
||||
<td>4,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Demonstracja systemu * (oceniane podczas obrony semestralnej)
|
||||
</td>
|
||||
<td>4</td>
|
||||
<td>6</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('presentation_showing_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('presentation_showing_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>4,6%</td>
|
||||
<td>6,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Odpowiedzi na pytania komisji (oceniane podczas obrony
|
||||
semestralnej)
|
||||
</td>
|
||||
<td>2</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register(
|
||||
'presentation_answers_to_questions_from_committee_1',
|
||||
{},
|
||||
)}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register(
|
||||
'presentation_answers_to_questions_from_committee_2',
|
||||
{},
|
||||
)}
|
||||
/>
|
||||
</td>
|
||||
<td>2,3%</td>
|
||||
<td>2,3%</td>
|
||||
</tr>
|
||||
{/* */}
|
||||
<tr>
|
||||
<td>
|
||||
{' '}
|
||||
<h3 className="text-xl font-bold">Dokumentacja</h3>
|
||||
</td>
|
||||
<td>2</td>
|
||||
<td>1</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dokument wizji projektu *</td>
|
||||
<td>3</td>
|
||||
<td>0</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_project_vision_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_project_vision_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>7,5%</td>
|
||||
<td>0,0%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dokument wymagań projektowych *</td>
|
||||
<td>3</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_requirements_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_requirements_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>7,5%</td>
|
||||
<td>2,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dokumentacja dla klienta/grupy docelowej/użytkownika</td>
|
||||
<td>0</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_for_clients_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_for_clients_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>0,0%</td>
|
||||
<td>2,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dokumentacja deweloperska</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_for_developers_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_for_developers_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>2,5%</td>
|
||||
<td>2,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Licencja i podział praw własności</td>
|
||||
<td>1</td>
|
||||
<td>1</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_license_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('documentation_license_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>2,5%</td>
|
||||
<td>1,4%</td>
|
||||
</tr>
|
||||
{/* */}
|
||||
<tr>
|
||||
<td>Praca grupy w semestrze</td>
|
||||
<td>3</td>
|
||||
<td>3</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Systematyczność pracy w semestrze *</td>
|
||||
<td>5</td>
|
||||
<td>5</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_regularity_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_regularity_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>7,9%</td>
|
||||
<td>6,5%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Podział prac w semestrze * (obowiązkowe w II sem)</td>
|
||||
<td>3</td>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_division_of_work_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_division_of_work_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>4,7%</td>
|
||||
<td>3,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Kontakt z klientem/grupą docelową, testy w grupie docelowej
|
||||
</td>
|
||||
<td>4</td>
|
||||
<td>4</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_contact_with_client_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_contact_with_client_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>6,3%</td>
|
||||
<td>5,2%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Zarządzanie ryzykiem i zakresem projektu</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_management_of_risk_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_management_of_risk_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>3,2%</td>
|
||||
<td>3,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Metodyka pracy i narzędzia ją wspierające *</td>
|
||||
<td>3</td>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_work_methodology_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_work_methodology_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>4,7%</td>
|
||||
<td>3,9%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Zarządzanie kodem źródłowym *</td>
|
||||
<td>2</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_management_of_source_code_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('group_work_management_of_source_code_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>3,2%</td>
|
||||
<td>2,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DevOps</td>
|
||||
<td>0</td>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<input type="text" {...register('group_work_devops_1', {})} />
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" {...register('group_work_devops_2', {})} />
|
||||
</td>
|
||||
<td>0,0%</td>
|
||||
<td>3,9%</td>
|
||||
</tr>
|
||||
{/* */}
|
||||
<tr>
|
||||
<td>Produkty projektu</td>
|
||||
<td>3,5</td>
|
||||
<td>4,5</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Czy złożoność produktu projektu odpowiada wielkości zespołu? Czy
|
||||
jakość produktu odpowiada wielkości projektu *
|
||||
</td>
|
||||
<td>3</td>
|
||||
<td>5</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_complexity_of_product_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_complexity_of_product_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>4,8%</td>
|
||||
<td>6,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Dostęp do produktu projektu dla komisji do testów podczas
|
||||
prezentacji * (obowiązkowe w II sem) (oceniane podczas obrony
|
||||
semestralnej)
|
||||
</td>
|
||||
<td>1</td>
|
||||
<td>1</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_access_to_application_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_access_to_application_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>1,6%</td>
|
||||
<td>1,3%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Brak krytycznych błędów w tym: bezpieczeństwa oraz
|
||||
uniemożliwiających korzystanie z systemu * (oceniane podczas
|
||||
obrony semestralnej)
|
||||
</td>
|
||||
<td>0</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_security_issues_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_security_issues_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>0,0%</td>
|
||||
<td>2,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Dostęp do produktu projektu dla komisji do testów tydzień przed
|
||||
prezentacją (oceniane podczas obrony semestralnej)
|
||||
</td>
|
||||
<td>0</td>
|
||||
<td>5</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register(
|
||||
'products_project_access_to_test_application_1',
|
||||
{},
|
||||
)}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register(
|
||||
'products_project_access_to_test_application_2',
|
||||
{},
|
||||
)}
|
||||
/>
|
||||
</td>
|
||||
<td>0,0%</td>
|
||||
<td>6,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spełnienie kryteriów akceptacji *</td>
|
||||
<td>5</td>
|
||||
<td>5</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_acceptance_criteria_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_acceptance_criteria_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>8,0%</td>
|
||||
<td>6,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Czy wdrożone zostały wszystkie zakładane na dany semestr
|
||||
funkcjonalności (ocenia prowadzący)?
|
||||
</td>
|
||||
<td>2</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_expected_functionality_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_expected_functionality_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>3,2%</td>
|
||||
<td>2,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Czy projekt dobrze rokuje?</td>
|
||||
<td>5</td>
|
||||
<td>0</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_promises_well_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_promises_well_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>8,0%</td>
|
||||
<td>0,0%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Czy projekt został wdrożony?</td>
|
||||
<td>0</td>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_has_been_implemented_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_has_been_implemented_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>0,0%</td>
|
||||
<td>4,0%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Czy projekt jest użyteczny dla grupy docelowej; Czy spełnia
|
||||
kryteria użyteczności i został przetestowany pod tym kątem?
|
||||
</td>
|
||||
<td>3</td>
|
||||
<td>5</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_is_useful_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_is_useful_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>4,8%</td>
|
||||
<td>6,6%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Czy przygotowano prototyp projektu zgodnie ze sztuką? *</td>
|
||||
<td>2</td>
|
||||
<td>0</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_prototype_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_prototype_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>3,2%</td>
|
||||
<td>0,0%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Czy przeprowadzono i udokumentowano testy, w tym testy:
|
||||
jednostkowe, integracyjne, akceptacyjne, obciążeniowe,
|
||||
funkcjonalne (kryterium nie obejmuje testów użyteczności) oraz
|
||||
statyczna analiza jakości kodu
|
||||
</td>
|
||||
<td>0</td>
|
||||
<td>4</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_tests_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_tests_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>0,0%</td>
|
||||
<td>5,3%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Dobór techologii i architektury systemu do rozwiązywanego
|
||||
problemu
|
||||
</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_technology_1', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
{...register('products_project_technology_2', {})}
|
||||
/>
|
||||
</td>
|
||||
<td>1,6%</td>
|
||||
<td>2,6%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="flex justify-end">
|
||||
<button className="btn btn-success mt-2">ZAPISZ</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default GradeCard
|
24
frontend/src/views/coordinator/Group.tsx
Normal file
24
frontend/src/views/coordinator/Group.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { useQuery } from 'react-query'
|
||||
import { Link, useParams } from 'react-router-dom'
|
||||
import { getGroup } from '../../api/groups'
|
||||
|
||||
const Group = () => {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
|
||||
const { data: groups } = useQuery(['getGroup'], () => getGroup(Number(id)))
|
||||
const { name, project_supervisor } = groups?.data || {}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="font-bold text-xl">{name}</h1>
|
||||
<h2 className="">
|
||||
Opiekun: {project_supervisor?.first_name}{' '}
|
||||
{project_supervisor?.last_name}
|
||||
</h2>
|
||||
<Link to={`/coordinator/groups/${id}/grade-card`}>
|
||||
<button className="btn btn-success mt-2">KARTA OCENY</button>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Group
|
@ -5,6 +5,7 @@ import { useNavigate } from 'react-router-dom'
|
||||
import useLocalStorageState from 'use-local-storage-state'
|
||||
import { deleteGroup, getGroups } from '../../api/groups'
|
||||
import { ReactComponent as IconRemove } from '../../assets/svg/icon-remove.svg'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const Groups = () => {
|
||||
let navigate = useNavigate()
|
||||
@ -94,7 +95,14 @@ const Groups = () => {
|
||||
points_for_second_term,
|
||||
}) => (
|
||||
<tr key={id}>
|
||||
<td>{name}</td>
|
||||
<td>
|
||||
<Link
|
||||
to={`/coordinator/groups/${id}`}
|
||||
className="underline font-bold"
|
||||
>
|
||||
{name}
|
||||
</Link>
|
||||
</td>
|
||||
<td>
|
||||
{`${project_supervisor.first_name} ${project_supervisor.last_name}`}
|
||||
</td>
|
||||
|
@ -53,7 +53,7 @@ const Students = () => {
|
||||
|
||||
const { mutate: mutateDownload } = useMutation(
|
||||
'downloadStudents',
|
||||
(mode: boolean) => downloadStudents(mode),
|
||||
(mode: boolean) => downloadStudents(mode, Number(yearGroupId)),
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
const url = window.URL.createObjectURL(new Blob([res.data]))
|
||||
@ -68,7 +68,7 @@ const Students = () => {
|
||||
|
||||
const { mutate: mutateUpload } = useMutation(
|
||||
'uploadStudents',
|
||||
(payload: FormData) => uploadStudents(payload),
|
||||
(payload: FormData) => uploadStudents(payload, Number(yearGroupId)),
|
||||
{
|
||||
onSuccess: () => refetchStudents(),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user