Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c93685d
initial commit
koteuka201 Feb 16, 2024
d59d6ea
заверстал страницу пользователей
koteuka201 Feb 17, 2024
7e8fbb0
Merge branch 'feature/UsersPage' into develop
koteuka201 Feb 17, 2024
08751b3
Изменил дизайн страницы пользователей, а также добавил функционал выб…
koteuka201 Feb 18, 2024
0278e17
исправил ошибку загрузки компонентов, а также добавил фичу с подсветк…
koteuka201 Feb 19, 2024
42e557e
исправил отображение в хедере, изменил свойства модального окна
koteuka201 Feb 19, 2024
e099105
Переделал фид пользователей, сделал карточки адаптивными
koteuka201 Feb 21, 2024
9525107
файлы к коммиту
koteuka201 Feb 23, 2024
632a437
Merge branch 'feature/UsersPage' into develop
koteuka201 Feb 23, 2024
0136fbf
коммит для сохранения
koteuka201 Feb 23, 2024
1f9e0e9
подвязал логин к апи сделал анимацию загрузки
koteuka201 Feb 23, 2024
48b42cf
поправил хедер (изменение вход/выход в зависимости от аутентификации)
koteuka201 Feb 23, 2024
096079e
добавил выход
koteuka201 Feb 23, 2024
315fda0
сделал изменение хедера в зависимости от логина
koteuka201 Feb 24, 2024
f8d88bb
быстрый фикс после исправления ошибки на апи
koteuka201 Feb 24, 2024
dda5bb3
сделал ограничение на вход в зависимости от роли пользователя
koteuka201 Feb 25, 2024
de2b1ba
Merge branch 'feature/Login' into develop
koteuka201 Feb 25, 2024
e3ccf2f
верстка заявки
rr33dd11 Feb 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 182 additions & 40 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"bootstrap": "^5.3.2",
"http-proxy-middleware": "^2.0.6",
"react": "^18.2.0",
"react-bootstrap": "^2.10.1",
"react-bootstrap-icons": "^1.10.3",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.0",
"react-icons": "^5.0.1",
"react-loader-spinner": "^6.1.6",
"react-router-dom": "^6.22.1",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
60 changes: 60 additions & 0 deletions src/components/Requests/requestCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import {Card, Container} from 'react-bootstrap';

const RequestCard = (props) => {
const {id, dateOfBooking, startTime, endTime, status, ownerRole, classroomNumber } = props;

let roleType = "";
switch (ownerRole) {
case 'User':
roleType = 'Пользователь';
break;
case 'Teacher':
roleType = 'Учитель';
break;
case 'DeanTeacher':
roleType = 'Учитель-работник деканата';
break;
case 'Student':
roleType = 'Студент';
break;
}

const fullname = "Русик, добавь в апишку имя"

let backgroundType = '';
switch (status) {
case 'Pending':
backgroundType = 'secondary-subtle';
break;
case 'Approved':
backgroundType = 'success-subtle';
break;
case 'Rejected':
backgroundType = 'danger-subtle';
break;
}


return (
<div>
<Container className="mt-2">
<Card bg={backgroundType}>
<Card.Body>
<Card.Title>Заявка на бронирование кабинета №{classroomNumber}</Card.Title>
<Card.Text>
<p className="mb-1">Дата бронирования: {dateOfBooking}</p>
<p className="mb-1">Время бронирования: {startTime} - {endTime}</p>
<p className="mb-1">Автор: {roleType} {fullname}</p>
<p className="mb-1">Статус: {status}</p>

</Card.Text>

</Card.Body>
</Card>
</Container>
</div>
);
};

export default RequestCard;
101 changes: 83 additions & 18 deletions src/components/header.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,99 @@
import React from "react";
import { Container, Row, Col, Button, Navbar, Image,Dropdown,DropdownButton } from 'react-bootstrap';
import { Link } from "react-router-dom";
import React, { useState, useEffect } from "react";
import { Container, Row, Col, Button, Navbar, Image, Dropdown, DropdownButton } from 'react-bootstrap';
import { Link, useLocation, useNavigate } from "react-router-dom";
import { LogoutFetch } from "../requests/requestsMetods";

function Header() {
const location = useLocation();
const [headerText, setHeaderText] = useState("");

useEffect(() => {

switch (location.pathname) {
case "/users":
setHeaderText("Пользователи");
break;
case "/login":
setHeaderText("Вход");
break;
case "/keys":
setHeaderText("Ключи");
break;
case "/requests":
setHeaderText("Заявки");
break;

default:
setHeaderText("");
break;
}
}, [location]);

const token=localStorage.getItem('token')
const navigate = useNavigate();

const handleLogout = async (e) => {
e.preventDefault()
const response=await LogoutFetch(token)
if (response){
localStorage.clear()
navigate('/login')
}
};

function Header(){
return (
<Navbar className="bg-dark shadow">
<div className="py-1 d-flex align-items-center ms-5 flex-grow-1">
<Link to="/" className="text-decoration-none">
<Image
src="https://facultetus.ru/images/universities/fe528b970af8e7a11ee44374ecd12e24.png"
width="35"
height="35"
style={{ filter: 'brightness(0) invert(1)' }}
className="mb-2"
/>
src="https://facultetus.ru/images/universities/fe528b970af8e7a11ee44374ecd12e24.png"
width="35"
height="35"
style={{ filter: 'brightness(0) invert(1)' }}
className="mb-2"
/>
<span className="text-white fs-5 ms-1">TSU.Ключи</span>
</Link>

<span className="text-white ms-5" style={{opacity: 0.7}}>Заявки</span>
<span className="text-white ms-5" style={{opacity: 0.7}}>Пользователи</span>
<span className="text-white ms-5" style={{opacity: 0.7}}>Ключи</span>
<Link to="/login" className="text-white ms-auto me-5 text-decoration-none">
<span style={{opacity: 0.7}}>Вход</span>

{/* <Link to='' className="text-white ms-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Заявки" ? <span className='text-primary'>Заявки</span> : "Заявки"}

</Link>
<Link to='/users' className="text-white ms-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Пользователи" ? <span className='text-primary'>Пользователи</span> : "Пользователи"}
</Link>

<Link to='' className="text-white ms-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Ключи" ? <span className='text-primary'>Ключи</span> : "Ключи"}

</Link> */}
{
token ? (
<div className="py-1 d-flex align-items-center ms-5 flex-grow-1">
<Link to='' className="text-white ms-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Заявки" ? <span className='text-primary'>Заявки</span> : "Заявки"}

</Link>
<Link to='/users' className="text-white ms-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Пользователи" ? <span className='text-primary'>Пользователи</span> : "Пользователи"}
</Link>
<Link to='' className="text-white ms-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Ключи" ? <span className='text-primary'>Ключи</span> : "Ключи"}

</Link>
<span className="text-white ms-auto me-5 text-decoration-none" style={{ opacity: 0.7, cursor: 'pointer' }} onClick={handleLogout}>Выход</span>

</div>
// <Link to="/login" className="text-white ms-auto me-5 text-decoration-none" style={{ opacity: 0.7 }} onClick={handleLogout}>
// Выход
// </Link>
) : <Link to="/login" className="text-white ms-auto me-5 text-decoration-none" style={{ opacity: 0.7 }}>
{headerText === "Вход" ? <span className='text-primary'>Вход</span> : "Вход"}
</Link>
}

</div>
</Navbar>
);
}

export default Header
export default Header;
78 changes: 70 additions & 8 deletions src/components/login.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,85 @@
import React from "react";
import { Container, Row, Col, Button, Navbar, Image,Dropdown,DropdownButton, Card, CardBody, CardTitle,Form, FormGroup, FormControl, FormLabel } from 'react-bootstrap';

import React, { useState } from "react";
import { Container, Row, Col, Button, Alert,Navbar, Image,Dropdown,DropdownButton, Card, CardBody, CardTitle,Form, FormGroup, FormControl, FormLabel } from 'react-bootstrap';
import { LoginFetch, ProfileFetch } from "../requests/requestsMetods";
import { useNavigate } from "react-router-dom";
import { LineWave as Loader} from "react-loader-spinner";

export default function Login(){

const navigate = useNavigate();
const [data, setData]=useState({
email: '',
password: ''
})
const [loading, setLoading] = useState(false);

const [errorMessage, setErrorMessage] = useState('')

const handleEmailChange=(e)=>{
setData({
...data,
email: e.target.value
})
}
const handlePasswordChange=(e)=>{
setData({
...data,
password: e.target.value
})
}
const handleSubmit=async (e)=>{
e.preventDefault()
setLoading(true);

const response=await LoginFetch(data)

setTimeout(async () => {
setLoading(false);
if (response.token) {
const responseProfile=await ProfileFetch(response.token)
console.log('role',responseProfile.role)
if (responseProfile.role==='DeanTeacher' || responseProfile.role==='Dean' || responseProfile.role==='Administrator'){
localStorage.setItem('token', response.token)
navigate('/users');
}
else{
setErrorMessage('У вас недостаточно прав доступа! Обратитесь к администратору');
}

// console.log(responseData);
}
else {
setErrorMessage('Неправильный пароль или email');
}
}, 1000);

}

return (
<Container className="d-flex justify-content-center align-items-center mt-5">
<Card className="col-md-6 shadow">
<CardBody>
<CardTitle className="text-center fs-3">Вход</CardTitle>
<Form>
<Form onSubmit={handleSubmit}>
<FormGroup>
<FormLabel>Email</FormLabel>
<FormControl type="email" placeholder="Введите ваш email" />
<FormControl type="email" value={data.email} onChange={handleEmailChange} placeholder="Введите ваш email" />
</FormGroup>
<FormGroup className="mt-4">
<FormGroup className="mt-4 ">
<FormLabel>Пароль</FormLabel>
<FormControl type="password" placeholder="Введите ваш пароль" />
<FormControl type="password" value={data.password} onChange={handlePasswordChange} placeholder="Введите ваш пароль" />
</FormGroup>
<Button id="enterBtn" className="mt-4 text-center w-100">Войти</Button>
{loading ? (
<div className="d-flex ms-4 justify-content-center align-items-center">
<Loader
color="#43c4ca"
height={80}
width={80}
/>
</div>
) :<Button type="submit" className="mt-4 mb-3 text-center w-100">Войти</Button>}

{errorMessage && <Alert variant="danger">{errorMessage}</Alert>}
</Form>
</CardBody>
</Card>
Expand Down
80 changes: 80 additions & 0 deletions src/components/userCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, {useState} from "react";
import { Form, ModalHeader,ModalTitle,ModalBody, ModalFooter, Container, Row, Col, Button, Navbar, Image,Modal,CardBody, Card, CardTitle, CardHeader, FormGroup, FormLabel, FormControl, FormSelect } from 'react-bootstrap';
import { BsFillPersonFill } from "react-icons/bs";

export default function UserCard(props){
const { name, role, email } = props;

let roleClass;
if(role==='Студент'){
roleClass='bg-success'
}
if(role==='Преподаватель'){
roleClass='bg-info'
}
if(role==='Пользователь'){
roleClass='bg-secondary'
}
const [showModal, setShowModal] = useState(false);
const [selectedRole, setSelectedRole] = useState(role);


const handleClose = () => setShowModal(false);
const handleShow = () => setShowModal(true);

const handleRoleChange = (e) => {
setSelectedRole(e.target.value);
};

return (
<Container className="mt-1">
<Card className="">
<CardBody className="row">

{/* <Image
src="https://www.svgrepo.com/show/500470/avatar.svg"
className="img-fluid"
alt="Avatar"
style={{ maxWidth: '10%', maxHeight: '10%' }}
/> */}
{/* <BsFillPersonFill className="fs-4 col"/> */}

<CardTitle className="col-md-2">{name}</CardTitle>
<div className="fw-bold col-md-4">
{email}
</div>



<Button className={`ms-auto me-2 col-md-2 fw-bold text-black ${roleClass} rounded-4 border border-dark`} onClick={handleShow}>{role}</Button>
<Modal centered show={showModal} onHide={handleClose}>
<ModalHeader closeButton>
<ModalTitle>Назначить роль</ModalTitle>
</ModalHeader>
<ModalBody>
<Form>
<FormGroup controlId="roleSelect">
<FormLabel>Выберите роль:</FormLabel>
<FormControl as="select" value={selectedRole} onChange={handleRoleChange}>
<option value="Студент">Студент</option>
<option value="Преподаватель">Преподаватель</option>
</FormControl>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button variant="secondary" onClick={handleClose}>
Закрыть
</Button>
<Button variant="primary" onClick={handleClose}>
Сохранить
</Button>
</ModalFooter>
</Modal>

</CardBody>
</Card>
</Container>

);
}
Loading