Add form for adding students
This commit is contained in:
parent
b03e369b73
commit
3d36569844
175
frontend/package-lock.json
generated
175
frontend/package-lock.json
generated
@ -16,8 +16,10 @@
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.4",
|
||||
"axios": "^0.27.2",
|
||||
"daisyui": "^2.15.2",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-hook-form": "^7.31.3",
|
||||
"react-query": "^3.39.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1",
|
||||
@ -5314,6 +5316,18 @@
|
||||
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
|
||||
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg=="
|
||||
},
|
||||
"node_modules/color": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1",
|
||||
"color-string": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
@ -5327,6 +5341,31 @@
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"node_modules/color-string": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"dependencies": {
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/color/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/colord": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz",
|
||||
@ -5782,6 +5821,15 @@
|
||||
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
|
||||
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
|
||||
},
|
||||
"node_modules/css-selector-tokenizer": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
|
||||
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"fastparse": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "1.0.0-alpha.37",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
|
||||
@ -5981,6 +6029,21 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
||||
},
|
||||
"node_modules/daisyui": {
|
||||
"version": "2.15.2",
|
||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-2.15.2.tgz",
|
||||
"integrity": "sha512-12hjzlOUkGVzMPKhaBc8soqNY2mJWGTYJF8sTuCibDcdGbHDmYgBUY0OX1HHIVq/qh2vELh5yHb4QCgCDWUAwg==",
|
||||
"dependencies": {
|
||||
"color": "^4.2",
|
||||
"css-selector-tokenizer": "^0.8.0",
|
||||
"postcss-js": "^4.0.0",
|
||||
"tailwindcss": "^3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"autoprefixer": "^10.0.2",
|
||||
"postcss": "^8.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
@ -7400,6 +7463,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||
},
|
||||
"node_modules/fastparse": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
|
||||
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
@ -13561,6 +13629,21 @@
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
||||
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.31.3",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.31.3.tgz",
|
||||
"integrity": "sha512-NVZdCWViIWXXXlQ3jxVQH0NuNfwPf8A/0KvuCxrM9qxtP1qYosfR2ZudarziFrVOC7eTUbWbm1T4OyYCwv9oSQ==",
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-hook-form"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
@ -14423,6 +14506,19 @@
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"node_modules/simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-swizzle/node_modules/is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||
},
|
||||
"node_modules/sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
@ -20186,6 +20282,30 @@
|
||||
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
|
||||
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg=="
|
||||
},
|
||||
"color": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1",
|
||||
"color-string": "^1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
@ -20199,6 +20319,15 @@
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"color-string": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"requires": {
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"colord": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz",
|
||||
@ -20517,6 +20646,15 @@
|
||||
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
|
||||
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
|
||||
},
|
||||
"css-selector-tokenizer": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
|
||||
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
|
||||
"requires": {
|
||||
"cssesc": "^3.0.0",
|
||||
"fastparse": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"css-tree": {
|
||||
"version": "1.0.0-alpha.37",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
|
||||
@ -20659,6 +20797,17 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
||||
},
|
||||
"daisyui": {
|
||||
"version": "2.15.2",
|
||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-2.15.2.tgz",
|
||||
"integrity": "sha512-12hjzlOUkGVzMPKhaBc8soqNY2mJWGTYJF8sTuCibDcdGbHDmYgBUY0OX1HHIVq/qh2vELh5yHb4QCgCDWUAwg==",
|
||||
"requires": {
|
||||
"color": "^4.2",
|
||||
"css-selector-tokenizer": "^0.8.0",
|
||||
"postcss-js": "^4.0.0",
|
||||
"tailwindcss": "^3.0"
|
||||
}
|
||||
},
|
||||
"damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
@ -21705,6 +21854,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||
},
|
||||
"fastparse": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
|
||||
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
|
||||
},
|
||||
"fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
@ -26009,6 +26163,12 @@
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
||||
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
||||
},
|
||||
"react-hook-form": {
|
||||
"version": "7.31.3",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.31.3.tgz",
|
||||
"integrity": "sha512-NVZdCWViIWXXXlQ3jxVQH0NuNfwPf8A/0KvuCxrM9qxtP1qYosfR2ZudarziFrVOC7eTUbWbm1T4OyYCwv9oSQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
@ -26636,6 +26796,21 @@
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
|
||||
"requires": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
|
@ -11,8 +11,10 @@
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.4",
|
||||
"axios": "^0.27.2",
|
||||
"daisyui": "^2.15.2",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-hook-form": "^7.31.3",
|
||||
"react-query": "^3.39.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1",
|
||||
|
@ -2,6 +2,7 @@ import React from 'react'
|
||||
import { QueryClient, QueryClientProvider } from 'react-query'
|
||||
import { Route, Routes } from 'react-router-dom'
|
||||
import './App.css'
|
||||
import AddStudent from './views/coordinator/AddStudent'
|
||||
import Coordinator from './views/coordinator/Coordinator'
|
||||
import Groups from './views/coordinator/Groups'
|
||||
import Leaders from './views/coordinator/Leaders'
|
||||
@ -25,6 +26,7 @@ function App() {
|
||||
<Route path="groups" element={<Groups />} />
|
||||
<Route path="students" element={<Students />} />
|
||||
<Route path="leaders" element={<Leaders />} />
|
||||
<Route path="add-student" element={<AddStudent />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</QueryClientProvider>
|
||||
|
@ -2,13 +2,15 @@ import axiosInstance from './axiosInstance'
|
||||
|
||||
interface StudentResponse {
|
||||
max_pages: number
|
||||
students: {
|
||||
first_name: string
|
||||
last_name: string
|
||||
index: number
|
||||
mode: boolean
|
||||
group: any
|
||||
}[]
|
||||
students: Student[]
|
||||
}
|
||||
|
||||
export interface Student {
|
||||
first_name: string
|
||||
last_name: string
|
||||
index: number
|
||||
mode: boolean
|
||||
group?: any
|
||||
}
|
||||
|
||||
export const getStudents = () =>
|
||||
@ -16,6 +18,9 @@ export const getStudents = () =>
|
||||
'http://127.0.0.1:5000/api/coordinator/students',
|
||||
)
|
||||
|
||||
export const createStudent = (payload: Student) =>
|
||||
axiosInstance.post('http://127.0.0.1:5000/api/coordinator/students/', payload)
|
||||
|
||||
export const uploadStudents = (payload: FormData) =>
|
||||
axiosInstance.post(
|
||||
'http://127.0.0.1:5000/api/coordinator/students/upload/',
|
||||
|
4
frontend/src/components/InputError.tsx
Normal file
4
frontend/src/components/InputError.tsx
Normal file
@ -0,0 +1,4 @@
|
||||
const InputError = (props: { children: React.ReactNode }) => (
|
||||
<p className="text-rose-600 ">{props.children}</p>
|
||||
)
|
||||
export default InputError
|
125
frontend/src/views/coordinator/AddStudent.tsx
Normal file
125
frontend/src/views/coordinator/AddStudent.tsx
Normal file
@ -0,0 +1,125 @@
|
||||
import { useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useMutation } from 'react-query'
|
||||
import { createStudent, Student } from '../../api/students'
|
||||
import InputError from '../../components/InputError'
|
||||
|
||||
const AddStudent = () => {
|
||||
const [isAlertVisible, setIsAlertVisible] = useState(false)
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm<Student>({ mode: 'onBlur' })
|
||||
|
||||
const { mutate: mutateCreateStudent } = useMutation(
|
||||
'createStudent',
|
||||
(payload: Student) => createStudent(payload),
|
||||
{
|
||||
onSuccess: () => {
|
||||
reset()
|
||||
setIsAlertVisible(true)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const onSubmit = (data: Student) => {
|
||||
mutateCreateStudent(data)
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
className="w-full lg:w-1/4 flex flex-col mx-auto"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
{isAlertVisible && (
|
||||
<div className="alert alert-success shadow-lg">
|
||||
<span>Udało się dodać studenta!</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="form-control">
|
||||
<label className="label" htmlFor="first_name">
|
||||
Imię
|
||||
</label>
|
||||
<input
|
||||
className="input input-bordered"
|
||||
id="first_name"
|
||||
type="text"
|
||||
{...register('first_name', { required: true })}
|
||||
/>
|
||||
{errors.first_name?.type === 'required' && (
|
||||
<InputError>Imię jest wymagane</InputError>
|
||||
)}
|
||||
</div>
|
||||
<div className="form-control">
|
||||
<label className="label" htmlFor="last_name">
|
||||
Nazwisko
|
||||
</label>
|
||||
<input
|
||||
className="input input-bordered"
|
||||
id="last_name"
|
||||
type="text"
|
||||
{...register('last_name', { required: true })}
|
||||
/>
|
||||
{errors.last_name?.type === 'required' && (
|
||||
<InputError>Nazwisko jest wymagane</InputError>
|
||||
)}
|
||||
</div>
|
||||
<div className="form-control">
|
||||
<label className="label" htmlFor="index">
|
||||
Indeks
|
||||
</label>
|
||||
<input
|
||||
className="input input-bordered"
|
||||
id="index"
|
||||
type="text"
|
||||
{...register('index', {
|
||||
required: true,
|
||||
pattern: /^[0-9]{6}$/,
|
||||
})}
|
||||
/>
|
||||
{errors.index?.type === 'required' && (
|
||||
<InputError>Indeks jest wymagany</InputError>
|
||||
)}
|
||||
{errors.index?.type === 'pattern' && (
|
||||
<InputError>Indeks musi mieć 6 cyfr</InputError>
|
||||
)}
|
||||
</div>
|
||||
<div className="form-control gap-2">
|
||||
<label className="label">Tryb studiów</label>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
className="radio"
|
||||
id="mode-0"
|
||||
type="radio"
|
||||
{...register('mode', {
|
||||
required: true,
|
||||
})}
|
||||
value="0"
|
||||
/>
|
||||
<label htmlFor="mode-0">Stacjonarny</label>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
className="radio"
|
||||
id="mode-1"
|
||||
type="radio"
|
||||
{...register('mode', {
|
||||
required: true,
|
||||
})}
|
||||
value="1"
|
||||
/>
|
||||
<label htmlFor="mode-1">Niestacjonarny</label>
|
||||
</div>
|
||||
{errors.mode?.type === 'required' && (
|
||||
<InputError>Wybierz tryb studiów</InputError>
|
||||
)}
|
||||
</div>
|
||||
<button className="btn btn-success mt-4">Dodaj studenta</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddStudent
|
@ -1,14 +1,12 @@
|
||||
import React, { useState } from 'react'
|
||||
import { useMutation, useQuery } from 'react-query'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { getStudents, uploadStudents } from '../../api/students'
|
||||
|
||||
const TableHeader = (props: { children: React.ReactNode }) => (
|
||||
<th className="px-4 py-2 font-medium text-left text-gray-900 whitespace-nowrap">
|
||||
{props.children}
|
||||
</th>
|
||||
)
|
||||
|
||||
const Students = () => {
|
||||
let navigate = useNavigate()
|
||||
const [showGroupless, setShowGroupless] = useState(false)
|
||||
|
||||
const {
|
||||
isLoading: isStudentsLoading,
|
||||
data: students,
|
||||
@ -30,23 +28,19 @@ const Students = () => {
|
||||
mutateUpload(payload)
|
||||
}
|
||||
|
||||
const [state, setState] = useState({
|
||||
showGroupless: false
|
||||
});
|
||||
|
||||
if (isStudentsLoading) {
|
||||
return <div>Ładowanie</div>
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center">
|
||||
<button className="bg-green-400 p-3 rounded-lg text-white font-extrabold hover:bg-green-300">
|
||||
<button
|
||||
className="btn btn-success"
|
||||
onClick={() => navigate('/coordinator/add-student')}
|
||||
>
|
||||
Dodaj nowego studenta
|
||||
</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"
|
||||
>
|
||||
<label className="ml-4 btn btn-success btn-outline" htmlFor="file">
|
||||
Importuj
|
||||
</label>
|
||||
<input
|
||||
@ -57,53 +51,39 @@ const Students = () => {
|
||||
className="hidden"
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
<label className="ml-auto">
|
||||
<span className="slider round">Tylko niezapisani</span>
|
||||
<input type="checkbox"
|
||||
className="m-2 checked: bg-black-400"
|
||||
onChange={() => setState({
|
||||
...state,
|
||||
showGroupless: !state.showGroupless
|
||||
})}
|
||||
<label className="label ml-auto">
|
||||
<span className="mr-2">Tylko niezapisani</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="checkbox"
|
||||
onChange={() => setShowGroupless(!showGroupless)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<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 table table-compact">
|
||||
<thead>
|
||||
<tr className="bg-gray-50">
|
||||
<TableHeader>Imie</TableHeader>
|
||||
<TableHeader>Nazwisko</TableHeader>
|
||||
<TableHeader>Indeks</TableHeader>
|
||||
<TableHeader>Zapisany</TableHeader>
|
||||
<TableHeader>Tryb</TableHeader>
|
||||
<th>Imię</th>
|
||||
<th>Nazwisko</th>
|
||||
<th>Indeks</th>
|
||||
<th>Zapisany</th>
|
||||
<th>Tryb</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-100">
|
||||
{students?.data?.students?.filter(
|
||||
(st) => (st.group === null || !state.showGroupless)
|
||||
).map(
|
||||
({ first_name, last_name, index, group, mode }) => (
|
||||
{students?.data?.students
|
||||
?.filter((st) => st.group === null || !showGroupless)
|
||||
.map(({ first_name, last_name, index, group, mode }) => (
|
||||
<tr key={index}>
|
||||
<td className="px-4 py-2 font-medium text-gray-900 whitespace-nowrap">
|
||||
{first_name}
|
||||
</td>
|
||||
<td className="px-4 py-2 text-gray-700 whitespace-nowrap">
|
||||
{last_name}
|
||||
</td>
|
||||
<td className="px-4 py-2 text-gray-700 whitespace-nowrap">
|
||||
{index}
|
||||
</td>
|
||||
<td className="px-4 py-2 text-gray-700 whitespace-nowrap">
|
||||
{group === null ? 'Nie' : 'Tak'}
|
||||
</td>
|
||||
<td className="px-4 py-2 text-gray-700 whitespace-nowrap">
|
||||
{mode ? 'stacjonarny' : 'niestacjonarny'}
|
||||
</td>
|
||||
<td>{first_name}</td>
|
||||
<td>{last_name}</td>
|
||||
<td>{index}</td>
|
||||
<td>{group === null ? 'Nie' : 'Tak'}</td>
|
||||
<td>{mode ? 'stacjonarny' : 'niestacjonarny'}</td>
|
||||
</tr>
|
||||
),
|
||||
)}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -1,9 +1,7 @@
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
plugins: [require('daisyui')],
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user