._.
This commit is contained in:
parent
83b9e57ea6
commit
492807f8a2
43
API/main.py
43
API/main.py
@ -5,10 +5,13 @@ import jwt
|
||||
|
||||
from data.connect import init_db, connect, User, Document, DocumentCategory, Comment
|
||||
from flask import Flask, Response, request, jsonify
|
||||
from flask_cors import CORS
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['SECRET_KEY'] = 'jyeraghueykgaeyugheaughkawefy'
|
||||
|
||||
CORS(app)
|
||||
|
||||
|
||||
@app.route('/api/v1/SignIn', methods=['POST'])
|
||||
def login():
|
||||
@ -249,6 +252,46 @@ def protected():
|
||||
return jsonify({'message': 'Invalid token!'}), 401
|
||||
|
||||
|
||||
@app.route('/employees')
|
||||
def get_employee_list():
|
||||
resp = []
|
||||
|
||||
months = {
|
||||
1: 'января',
|
||||
2: 'февраля',
|
||||
3: 'марта',
|
||||
4: 'апреля',
|
||||
5: 'мая',
|
||||
6: 'июня',
|
||||
7: 'июля',
|
||||
8: 'августа',
|
||||
9: 'сентября',
|
||||
10: 'октября',
|
||||
11: 'ноября',
|
||||
12: 'декабря'
|
||||
}
|
||||
|
||||
with connect() as session:
|
||||
employees = session.query(User).all()
|
||||
|
||||
for employee in employees:
|
||||
resp.append(
|
||||
{
|
||||
'id': employee.id,
|
||||
'first_name': employee.first_name,
|
||||
'last_name': employee.last_name,
|
||||
'patronymic': employee.patronymic,
|
||||
'email': employee.email,
|
||||
'phone': employee.work_phone,
|
||||
'post': employee.post.title,
|
||||
'birthday': f'{str(employee.birthday.day)} {months[employee.birthday.month]}'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
return resp
|
||||
|
||||
|
||||
def main():
|
||||
init_db()
|
||||
app.run()
|
||||
|
||||
58
WEB/app/package-lock.json
generated
58
WEB/app/package-lock.json
generated
@ -10,7 +10,8 @@
|
||||
"dependencies": {
|
||||
"next": "15.1.5",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
"react-dom": "^19.0.0",
|
||||
"react-qr-code": "^2.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8",
|
||||
@ -1227,6 +1228,12 @@
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||
@ -1247,6 +1254,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
@ -1430,7 +1449,6 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@ -1676,6 +1694,23 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/qr.js": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz",
|
||||
"integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
@ -1718,6 +1753,25 @@
|
||||
"react": "^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-qr-code": {
|
||||
"version": "2.0.15",
|
||||
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.15.tgz",
|
||||
"integrity": "sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.8.1",
|
||||
"qr.js": "0.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "15.1.5",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"next": "15.1.5"
|
||||
"react-qr-code": "^2.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8",
|
||||
|
||||
@ -24,5 +24,47 @@
|
||||
|
||||
.user-list {
|
||||
margin: 2vw;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.employee-card {
|
||||
min-width: 250px;
|
||||
height: 200px;
|
||||
background-color: #2f9836;
|
||||
|
||||
padding: 1vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.fio {
|
||||
margin-right: 5px;
|
||||
font-size: x-large;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.employee-text {
|
||||
font-size: large;
|
||||
margin-top: 3px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.user-row-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.row-qr {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
74
WEB/app/src/app/components/employee-card.js
Normal file
74
WEB/app/src/app/components/employee-card.js
Normal file
@ -0,0 +1,74 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from "react";
|
||||
import QRCode from "react-qr-code";
|
||||
|
||||
|
||||
const EmployeeCard = (employee) => {
|
||||
const [showQR, setShowQR] = useState(false);
|
||||
|
||||
const qrText = `BEGIN:VCARD
|
||||
VERSION:3.0
|
||||
N:${employee.employee.first_name}
|
||||
FN:${employee.employee.last_name}
|
||||
ORG:Дороги России
|
||||
TITLE:${employee.employee.post}
|
||||
TEL;WORK;VOICE:${employee.employee.phone}
|
||||
TEL;CELL:${employee.employee.phone}
|
||||
EMAIL;WORK;INTERNET:${employee.employee.email}
|
||||
END:VCARD
|
||||
`;
|
||||
if (showQR) {
|
||||
return (
|
||||
<>
|
||||
<div className="employee-card">
|
||||
<QRCode
|
||||
size={256}
|
||||
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
|
||||
value={qrText}
|
||||
viewBox={`0 0 256 256`}
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowQR(false)
|
||||
}}
|
||||
>
|
||||
Закрыть
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="employee-card">
|
||||
|
||||
<div className="row">
|
||||
<label className="fio">{employee.employee.last_name}</label>
|
||||
<label className="fio">{employee.employee.first_name}</label>
|
||||
<label className="fio">{employee.employee.patronymic}</label>
|
||||
</div>
|
||||
|
||||
<label className="employee-text">{employee.employee.post}</label>
|
||||
<a className="employee-text" href={`mailto:${employee.employee.email}`}>{employee.employee.email}</a>
|
||||
<label className="employee-text">{employee.employee.phone}</label>
|
||||
<label className="employee-text">{employee.employee.phone}</label>
|
||||
|
||||
<div className="row-qr">
|
||||
<label className="employee-text">{employee.employee.birthday}</label>
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowQR(true)
|
||||
}}
|
||||
>
|
||||
QR-код
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default EmployeeCard;
|
||||
@ -1,7 +1,40 @@
|
||||
'use client';
|
||||
|
||||
import './app.css';
|
||||
import Header from './components/header.js';
|
||||
import EmployeeCard from './components/employee-card.js';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function Home() {
|
||||
|
||||
const [employees, setEmployees] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchEmployees();
|
||||
}, []);
|
||||
|
||||
const fetchEmployees = async () => {
|
||||
try {
|
||||
const data = await fetch('http://localhost:5000/employees');
|
||||
|
||||
if (data.ok) {
|
||||
const json_data = await data.json();
|
||||
setEmployees(json_data)
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const b = (digit) => {
|
||||
}
|
||||
|
||||
const a = [1, 2, 3, 4];
|
||||
a.map(
|
||||
b
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
@ -14,6 +47,12 @@ export default function Home() {
|
||||
|
||||
<div className='user-row-list'>
|
||||
|
||||
{employees.map(
|
||||
(employee) => (
|
||||
<EmployeeCard key={employee.id} employee={employee} />
|
||||
)
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user