initial commit

This commit is contained in:
Ivan 2024-05-15 16:27:22 +03:00
commit b34ea0b94c
Signed by untrusted user who does not match committer: ppechenkoo
GPG Key ID: 0C191B86D9582583
28 changed files with 19735 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
node_modules
.DS_Store
.env

11
captain-definition Normal file
View File

@ -0,0 +1,11 @@
{
"schemaVersion": 2,
"dockerfileLines": [
"FROM node",
"WORKDIR /app",
"COPY package*.json ./",
"RUN npm install --production",
"COPY . .",
"CMD [\"node\", \"index.js\"]"
]
}

602
index.js Normal file
View File

@ -0,0 +1,602 @@
const express = require("express");
const app = express();
const path = require("path");
const cookie = require("cookie");
const cookieParser = require("cookie-parser");
const fs = require("fs");
const handlebars = require("handlebars");
const axios = require("axios");
const FormData = require("form-data");
require("dotenv").config();
app.use(express.static("static"));
app.use(cookieParser());
handlebars.registerHelper("eq", function (val1, val2, options) {
return val1 === val2;
});
app.get("/logout", logout);
const twelveHoursInSeconds = 12 * 60 * 60; // 12 часов в секундах
const checkAuthorization = async (req, res, next) => {
const token = req.cookies.token;
console.log("checking token: " + token);
if (!token) {
res.redirect("/");
return;
}
const options = {
method: "GET",
url: process.env.API_SERVER + "/secure",
headers: {
Authorization: token,
},
};
try {
const response = await axios.request(options);
const authorizationHeader = response.headers["authorization"];
const responseBody = response.data;
req.apiResponse = responseBody;
// Обновляем токен в cookies
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
next();
} catch (error) {
if (
(error.response && error.response.status === 401) ||
error.response.status === 400
) {
res.redirect("/");
} else {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
}
};
app.get("/", async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/secure",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
console.log("redirecting to acc");
res.redirect("/account");
})
.catch(function (error) {
if (error.response && error.response.status === 401) {
var templateData = {
API_SERVER: process.env.API_SERVER,
};
const source = fs.readFileSync("static/templates/index.html", "utf8");
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
} else if (error.response && error.response.status === 400) {
var templateData = {
API_SERVER: process.env.API_SERVER,
};
const source = fs.readFileSync("static/templates/setup.html", "utf8");
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
} else {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/signup", async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/secure",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
res.redirect("/account");
})
.catch(function (error) {
if (error.response) {
var templateData = {
API_SERVER: process.env.API_SERVER,
};
const source = fs.readFileSync("static/templates/signup.html", "utf8");
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
} else {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/signin", async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/secure",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
res.redirect("/account");
})
.catch(function (error) {
if (error.response) {
var templateData = {
API_SERVER: process.env.API_SERVER,
};
const source = fs.readFileSync("static/templates/signin.html", "utf8");
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
} else {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/account", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/account",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
var templateData = {
API_SERVER: process.env.API_SERVER,
Role: response.data.role,
User: response.data.data,
};
const source = fs.readFileSync(
"static/templates/account/account.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/account/settings", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/account",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
var templateData = {
API_SERVER: process.env.API_SERVER,
Role: response.data.role,
User: response.data.data,
};
const source = fs.readFileSync(
"static/templates/account/settings.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/account/newform", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/account",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
var templateData = {
API_SERVER: process.env.API_SERVER,
Role: response.data.role,
User: response.data.data,
};
const source = fs.readFileSync(
"static/templates/account/form.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/account/newtso", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "GET",
url: process.env.API_SERVER + "/account",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
var templateData = {
API_SERVER: process.env.API_SERVER,
Role: response.data.role,
User: response.data.data,
};
const source = fs.readFileSync(
"static/templates/account/newtso.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/users", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "POST",
url: process.env.API_SERVER + "/users/getusers",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
if (response.data.role !== "Дирекция") {
if (response.data.role === "КПП") {
var templateData = {
API_SERVER: process.env.API_SERVER,
User: response.data.userData,
Role: response.data.role,
People: response.data.people,
Legals: response.data.legals,
PeopleCount: response.data.totalCountPeople,
LegalsCount: response.data.totalCountLegal,
};
const source = fs.readFileSync(
"static/templates/account/readusers.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
} else {
res.redirect("/account");
return;
}
}
var templateData = {
API_SERVER: process.env.API_SERVER,
User: response.data.userData,
Role: response.data.role,
People: response.data.people,
Legals: response.data.legals,
PeopleCount: response.data.totalCountPeople,
LegalsCount: response.data.totalCountLegal,
};
const source = fs.readFileSync(
"static/templates/account/users.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/applications", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "POST",
url: process.env.API_SERVER + "/forms/getapplications",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
if (
response.data.role !== "Дирекция" &&
response.data.role !== "Пропуска"
) {
res.redirect("/account");
return;
}
var templateData = {
API_SERVER: process.env.API_SERVER,
User: response.data.userData,
Role: response.data.role,
Applications: response.data.applications,
Total: response.data.totalCount,
};
const source = fs.readFileSync(
"static/templates/account/applications.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/passes", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "POST",
url: process.env.API_SERVER + "/passes/getpasses",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
if (
response.data.role !== "Дирекция" &&
response.data.role !== "Пропуска" &&
response.data.role !== "КПП"
) {
res.redirect("/account");
return;
}
var templateData = {
API_SERVER: process.env.API_SERVER,
User: response.data.userData,
Role: response.data.role,
Passes: response.data.passes,
Total: response.data.totalCount,
};
const source = fs.readFileSync(
"static/templates/account/passes.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
app.get("/tso", checkAuthorization, async (req, res) => {
const token = req.cookies.token;
var options = {
method: "POST",
url: process.env.API_SERVER + "/passes/gettso",
headers: {
Authorization: req.cookies.token,
},
};
axios
.request(options)
.then(function (response) {
const authorizationHeader = response.headers["authorization"];
res.cookie("token", authorizationHeader, {
maxAge: twelveHoursInSeconds * 1000,
});
if (
response.data.role !== "Дирекция" &&
response.data.role !== "Пропуска" &&
response.data.role !== "КПП"
) {
res.redirect("/account");
return;
}
var templateData = {
API_SERVER: process.env.API_SERVER,
User: response.data.userData,
Role: response.data.role,
Passes: response.data.passes,
Total: response.data.totalCount,
};
const source = fs.readFileSync(
"static/templates/account/tso.html",
"utf8"
);
const template = handlebars.compile(source);
const resultT = template(templateData);
res.send(resultT);
})
.catch(function (error) {
if (error.response) {
console.error("Ошибка при отправке GET-запроса:", error);
res.status(500).send("Произошла ошибка при выполнении запроса.");
}
});
});
async function logout(req, res) {
res.clearCookie("token");
res.redirect("/login");
}
const port = 8081;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
app.use((req, res, next) => {
res.redirect("/");
});

1542
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

22
package.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "passes",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "ppechenkoo",
"license": "ISC",
"dependencies": {
"axios": "^1.6.7",
"cookie": "^0.6.0",
"cookie-parser": "^1.4.6",
"dotenv": "^16.4.4",
"express": "^4.18.2",
"form-data": "^4.0.0",
"fs": "^0.0.1-security",
"handlebars": "^4.7.8",
"path": "^0.12.7"
}
}

BIN
static/docs/manual.pdf Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Pixelmator Pro 2.4.3 -->
<svg width="12" height="8" viewBox="0 0 12 8" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Group">
<path id="Path" fill="#000000" stroke="none" opacity="0" d="M -0 0.151983 L 12 0.151983 L 12 8 L -0 8 Z"/>
<path id="path1" fill="#000000" stroke="none" d="M 6.003452 8 C 6.176163 8 6.348875 7.926277 6.466314 7.786301 L 11.813452 1.942658 C 11.930884 1.817382 12 1.655266 12 1.471041 C 12 1.087846 11.730542 0.793088 11.37131 0.793088 C 11.198627 0.793088 11.03974 0.866779 10.922307 0.984686 L 5.630391 6.754628 L 6.369602 6.754628 L 1.077721 0.984686 C 0.967186 0.866779 0.808291 0.793088 0.62867 0.793088 C 0.26943 0.793088 -0 1.087846 -0 1.471041 C -0 1.655266 0.069085 1.817382 0.186528 1.950024 L 5.533679 7.786301 C 5.664934 7.926277 5.82383 8 6.003452 8 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 925 B

3
static/img/info.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 0C7.21997 0 5.47991 0.527841 3.99987 1.51677C2.51983 2.50571 1.36628 3.91131 0.685088 5.55585C0.00389951 7.20038 -0.17433 9.00998 0.172937 10.7558C0.520203 12.5016 1.37737 14.1053 2.63604 15.364C3.89472 16.6226 5.49836 17.4798 7.24419 17.8271C8.99002 18.1743 10.7996 17.9961 12.4442 17.3149C14.0887 16.6337 15.4943 15.4802 16.4832 14.0001C17.4722 12.5201 18 10.78 18 9C18 6.61305 17.0518 4.32387 15.364 2.63604C13.6761 0.948211 11.387 0 9 0ZM10.5 15H7.5V9H6V7.5H10.5V15ZM9 6C8.70333 6 8.41332 5.91203 8.16665 5.7472C7.91998 5.58238 7.72772 5.34811 7.61418 5.07403C7.50065 4.79994 7.47095 4.49834 7.52883 4.20736C7.5867 3.91639 7.72957 3.64912 7.93934 3.43934C8.14912 3.22956 8.4164 3.0867 8.70737 3.02882C8.99834 2.97094 9.29994 3.00065 9.57403 3.11418C9.84812 3.22771 10.0824 3.41997 10.2472 3.66664C10.412 3.91332 10.5 4.20333 10.5 4.5C10.5 4.89782 10.342 5.27936 10.0607 5.56066C9.77936 5.84196 9.39783 6 9 6Z" fill="#0050CF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

11
static/img/xmark.svg Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 232.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="387.147" height="387.391">
<g>
<rect height="387.391" opacity="0" width="387.147" x="0" y="0"/>
<path d="M6.31747 381.073C14.8624 389.374 29.0225 389.374 37.3233 381.073L193.573 224.823L349.823 381.073C358.124 389.374 372.528 389.618 380.829 381.073C389.13 372.528 389.13 358.612 380.829 350.312L224.579 193.817L380.829 37.5675C389.13 29.2667 389.374 15.1065 380.829 6.80575C372.284-1.73917 358.124-1.73917 349.823 6.80575L193.573 163.056L37.3233 6.80575C29.0225-1.73917 14.6183-1.98331 6.31747 6.80575C-1.98331 15.3507-1.98331 29.2667 6.31747 37.5675L162.567 193.817L6.31747 350.312C-1.98331 358.612-2.22745 372.773 6.31747 381.073Z" fill="#000000" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 984 B

View File

@ -0,0 +1,212 @@
const createTable = () => {
const table = document.getElementById("applicationsTable");
const tbody = table.querySelector("tbody");
// Очищаем таблицу
tbody.innerHTML = "";
applications.forEach((application) => {
const row = document.createElement("tr");
row.setAttribute("onclick", `openApplication(${application.id});`);
// Добавляем ячейки с данными
const id = document.createElement("td");
id.textContent = application.id;
row.appendChild(id);
const status = document.createElement("td");
status.textContent = application.status;
row.appendChild(status);
const type = document.createElement("td");
type.textContent = application.type;
row.appendChild(type);
const worker = document.createElement("td");
worker.textContent = application.worker;
row.appendChild(worker);
const legal = document.createElement("td");
legal.innerHTML = application.legal;
row.appendChild(legal);
const date = document.createElement("td");
const rawDate = new Date(application.date);
const formattedDate = `${rawDate.getDate().toString().padStart(2, "0")}/${(
rawDate.getMonth() + 1
)
.toString()
.padStart(2, "0")}/${rawDate.getFullYear()}`;
date.textContent = formattedDate;
row.appendChild(date);
const finaldate = document.createElement("td");
if (application.finaldate) {
const rawFinalDate = new Date(application.finaldate);
const formattedfinalDate = `${rawFinalDate
.getDate()
.toString()
.padStart(2, "0")}/${(rawFinalDate.getMonth() + 1)
.toString()
.padStart(2, "0")}/${rawFinalDate.getFullYear()}`;
finaldate.textContent = formattedfinalDate;
} else {
finaldate.textContent = "";
}
row.appendChild(finaldate);
const car = document.createElement("td");
if (application.car) {
let carText = application.car.replace(/&quot;/g, '"');
carText = JSON.parse(carText).join(", ");
car.textContent = carText;
}
row.appendChild(car);
tbody.appendChild(row);
});
};
document.addEventListener("DOMContentLoaded", function () {
createTable();
});
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function requestUpdate() {
document.getElementById("applicationsTable").style.filter =
"brightness(0.85)";
const formData = new FormData();
formData.append("searchText", document.getElementById("table-search").value);
formData.append(
"page",
parseInt(document.getElementById("page-number").textContent)
);
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
body: formData,
};
fetch(API_SERVER + "/forms/getapplications", requestOptions)
.then((response) => {
document.getElementById("applicationsTable").style.filter =
"brightness(1)";
if (response.ok) {
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
applications.splice(0, applications.length);
applications.push(
...data.applications.map((item) => ({
id: item.id,
status: item.Статус,
type: item.Видаявки,
worker: item.Работник,
date: item.Датааявки,
finaldate: item.Дата_решения,
legal: item.Организация,
car: item.Авто_госомер,
}))
);
createTable();
totalMax = Math.ceil(data.totalCount / 15);
if (totalMax === 0) {
totalMax = 1;
}
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > totalMax) {
pageNumberInput.textContent = totalMax;
requestUpdate();
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
// function closeForm() {
// var formContainer = $("#form-bg");
// var fform = $("#form");
// formContainer.removeClass("active");
// fform.removeClass("form-animation");
// $("body").css("overflow", "auto");
// }
// document.addEventListener("DOMContentLoaded", function () {
// const form = document.getElementById("add-form");
// form.addEventListener("submit", function (event) {
// event.preventDefault();
// const deleteConfirmation = document.getElementById("addInformation");
// const closeButton = document.getElementById("closeButton");
// const mark = document.getElementById("success-mark");
// closeForm();
// closeButton.style.display = "none";
// deleteConfirmation.style.display = "flex";
// mark.style.display = "none";
// const formData = new FormData(form);
// form.reset();
// fetch(API_SERVER + "/user", {
// method: "POST",
// headers: {
// Authorization: getCookie("token"),
// },
// body: formData,
// })
// .then((response) => response.json())
// .then((data) => {
// showMessage("Пользователь успешно добавлен", true);
// })
// .catch((error) => {
// showMessage("Не удалось добавить пользователя", false);
// console.error("Ошибка:", error);
// });
// });
// });
// function addUser() {
// var formContainer = $("#form-bg");
// var form = $("#form");
// formContainer.addClass("active");
// form.addClass("form-animation");
// $("body").css("overflow", "hidden");
// }
// $(document).ready(function () {
// // Закрывает popup форму
// $("#close-form-btn").click(function () {
// closeForm();
// });
// // Функция для закрытия формы
// function closeForm() {
// var formContainer = $("#form-bg");
// var form = $("#form");
// formContainer.removeClass("active");
// form.removeClass("form-animation");
// $("body").css("overflow", "auto");
// }
// });

View File

@ -0,0 +1,36 @@
function toggleDropdown(dropdownId) {
$(".dropdown-help")
.not("#" + dropdownId)
.removeClass("is-visible");
setTimeout(function () {
$(".dropdown-help")
.not("#" + dropdownId)
.css("display", "none");
}, 200);
const dropdownHelp = $("#" + dropdownId);
if (dropdownHelp.hasClass("is-visible")) {
event.preventDefault();
dropdownHelp.removeClass("is-visible");
setTimeout(function () {
dropdownHelp.css("display", "none");
}, 200);
} else {
event.preventDefault();
dropdownHelp.css("display", "inline-flex");
dropdownHelp.addClass("is-visible");
}
}
$(document).on("click", function (event) {
if ($(event.target).closest(".help-button").length) {
return;
} else {
if (!$(event.target).closest(".dropdown-help").length) {
$(".dropdown-help").removeClass("is-visible");
setTimeout(function () {
$(".dropdown-help").css("display", "none");
}, 200);
}
}
});

10965
static/scripts/jquery.min.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,144 @@
const createTable = () => {
const table = document.getElementById("passesTable");
const tbody = table.querySelector("tbody");
// Очищаем таблицу
tbody.innerHTML = "";
passes.forEach((pass) => {
const row = document.createElement("tr");
row.setAttribute("onclick", `openPass(${pass.id});`);
// Добавляем ячейки с данными
const id = document.createElement("td");
id.textContent = pass.id;
row.appendChild(id);
const status = document.createElement("td");
status.textContent = pass.status;
row.appendChild(status);
const date = document.createElement("td");
const rawDate = new Date(pass.date);
const formattedDate = `${rawDate.getDate().toString().padStart(2, "0")}/${(
rawDate.getMonth() + 1
)
.toString()
.padStart(2, "0")}/${rawDate.getFullYear()}`;
date.textContent = formattedDate;
row.appendChild(date);
const type = document.createElement("td");
type.textContent = pass.type;
row.appendChild(type);
const worker = document.createElement("td");
worker.textContent = pass.name;
row.appendChild(worker);
const legal = document.createElement("td");
legal.innerHTML = pass.legal;
row.appendChild(legal);
const finaldate = document.createElement("td");
if (pass.finaldate) {
const rawFinalDate = new Date(pass.finaldate);
const formattedfinalDate = `${rawFinalDate
.getDate()
.toString()
.padStart(2, "0")}/${(rawFinalDate.getMonth() + 1)
.toString()
.padStart(2, "0")}/${rawFinalDate.getFullYear()}`;
finaldate.textContent = formattedfinalDate;
} else {
finaldate.textContent = "";
}
row.appendChild(finaldate);
const address = document.createElement("td");
address.textContent = pass.address;
row.appendChild(address);
const car = document.createElement("td");
if (pass.car) {
let carText = pass.car.replace(/&quot;/g, '"');
carText = JSON.parse(carText).join(", ");
car.textContent = carText;
}
row.appendChild(car);
tbody.appendChild(row);
});
};
document.addEventListener("DOMContentLoaded", function () {
createTable();
});
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function requestUpdate() {
document.getElementById("passesTable").style.filter = "brightness(0.85)";
const formData = new FormData();
formData.append("searchText", document.getElementById("table-search").value);
formData.append(
"page",
parseInt(document.getElementById("page-number").textContent)
);
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
body: formData,
};
fetch(API_SERVER + "/passes/getpasses", requestOptions)
.then((response) => {
document.getElementById("passesTable").style.filter = "brightness(1)";
if (response.ok) {
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
passes.splice(0, passes.length);
passes.push(
...data.passes.map((item) => ({
id: item.id,
status: item.Состояние,
date: item.Дата_выдачи,
finaldate: item.Действиео,
type: item.Вид_пропуска,
name: item.Работник,
legal: item.Организация,
address: item.Зонаоступа,
car: item.Авто_госомер,
tmcname: item.Наименование,
}))
);
createTable();
totalMax = Math.ceil(data.totalCount / 15);
if (totalMax === 0) {
totalMax = 1;
}
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > totalMax) {
pageNumberInput.textContent = totalMax;
requestUpdate();
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}

134
static/scripts/tso-table.js Normal file
View File

@ -0,0 +1,134 @@
const createTable = () => {
const table = document.getElementById("passesTable");
const tbody = table.querySelector("tbody");
// Очищаем таблицу
tbody.innerHTML = "";
passes.forEach((pass) => {
const row = document.createElement("tr");
row.setAttribute("onclick", `openPass(${pass.id});`);
// Добавляем ячейки с данными
const id = document.createElement("td");
id.textContent = pass.id;
row.appendChild(id);
const status = document.createElement("td");
status.textContent = pass.status;
row.appendChild(status);
const date = document.createElement("td");
const rawDate = new Date(pass.date);
const formattedDate = `${rawDate.getDate().toString().padStart(2, "0")}/${(
rawDate.getMonth() + 1
)
.toString()
.padStart(2, "0")}/${rawDate.getFullYear()}`;
date.textContent = formattedDate;
row.appendChild(date);
const type = document.createElement("td");
type.textContent = pass.type;
row.appendChild(type);
const object = document.createElement("td");
object.textContent = pass.object;
row.appendChild(object);
const editdate = document.createElement("td");
if (pass.editdate) {
const rawFinalDate = new Date(pass.editdate);
const formattedfinalDate = `${rawFinalDate
.getDate()
.toString()
.padStart(2, "0")}/${(rawFinalDate.getMonth() + 1)
.toString()
.padStart(2, "0")}/${rawFinalDate.getFullYear()}`;
editdate.textContent = formattedfinalDate;
} else {
editdate.textContent = "";
}
row.appendChild(editdate);
const executor = document.createElement("td");
executor.textContent = pass.executor;
row.appendChild(executor);
tbody.appendChild(row);
});
};
document.addEventListener("DOMContentLoaded", function () {
createTable();
});
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function requestUpdate() {
document.getElementById("passesTable").style.filter = "brightness(0.85)";
const formData = new FormData();
// formData.append("searchText", document.getElementById("table-search").value);
formData.append(
"page",
parseInt(document.getElementById("page-number").textContent)
);
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
body: formData,
};
fetch(API_SERVER + "/passes/gettso", requestOptions)
.then((response) => {
document.getElementById("passesTable").style.filter = "brightness(1)";
if (response.ok) {
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
passes.splice(0, passes.length);
passes.push(
...data.passes.map((item) => ({
id: item.id,
status: item.Состояние,
object: item.Объект,
fabula: item.Фабула,
type: item.Видеисправности,
date: item.Дата_подачи,
editdate: item.Дата_изменения,
who: item.Кто_подал,
executor: item.Исполнитель,
events: item.Мероприятия,
}))
);
createTable();
totalMax = Math.ceil(data.totalCount / 15);
if (totalMax === 0) {
totalMax = 1;
}
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > totalMax) {
pageNumberInput.textContent = totalMax;
requestUpdate();
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}

View File

@ -0,0 +1,259 @@
const createTable = () => {
const table = document.getElementById("usersTable");
const legalsTable = document.getElementById("legalsTable");
const tbody = table.querySelector("tbody");
const legalsTbody = legalsTable.querySelector("tbody");
// Очищаем таблицу
tbody.innerHTML = "";
legalsTbody.innerHTML = "";
users.forEach((user) => {
const row = document.createElement("tr");
if (user.isblocked === "true" || user.isblocked === true) {
row.setAttribute("style", `background: rgba(255, 69, 58, 0.3)`);
}
row.setAttribute("onclick", `openUser(${user.id});`);
// Добавляем ячейки с данными
const id = document.createElement("td");
id.textContent = user.id;
row.appendChild(id);
const surname = document.createElement("td");
surname.textContent = user.surname;
row.appendChild(surname);
const name = document.createElement("td");
name.textContent = user.name;
row.appendChild(name);
const secondname = document.createElement("td");
secondname.textContent = user.secondname;
row.appendChild(secondname);
const role = document.createElement("td");
if (user.role) {
role.textContent = user.role;
} else {
role.textContent = "Гость";
}
row.appendChild(role);
const phone = document.createElement("td");
phone.textContent = user.phone;
row.appendChild(phone);
const email = document.createElement("td");
email.textContent = user.email;
row.appendChild(email);
const sub = document.createElement("td");
sub.textContent = user.sub;
row.appendChild(sub);
const department = document.createElement("td");
department.textContent = user.department;
row.appendChild(department);
tbody.appendChild(row);
});
legals.forEach((legal) => {
const legalsRow = document.createElement("tr");
legalsRow.setAttribute("onclick", `openLegal(${legal.id});`);
// Добавляем ячейки с данными
const id = document.createElement("td");
id.textContent = legal.id;
legalsRow.appendChild(id);
const name = document.createElement("td");
name.innerHTML = legal.name;
legalsRow.appendChild(name);
const inn = document.createElement("td");
inn.textContent = legal.inn;
legalsRow.appendChild(inn);
const ogrn = document.createElement("td");
ogrn.textContent = legal.ogrn;
legalsRow.appendChild(ogrn);
const address = document.createElement("td");
address.textContent = legal.address;
legalsRow.appendChild(address);
const realaddress = document.createElement("td");
realaddress.textContent = legal.realaddress;
legalsRow.appendChild(realaddress);
const email = document.createElement("td");
email.textContent = legal.email;
legalsRow.appendChild(email);
legalsTbody.appendChild(legalsRow);
});
};
document.addEventListener("DOMContentLoaded", function () {
createTable();
});
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function requestUpdate() {
document.getElementById("usersTable").style.filter = "brightness(0.85)";
document.getElementById("legalsTable").style.filter = "brightness(0.85)";
const formData = new FormData();
formData.append("searchText", document.getElementById("table-search").value);
formData.append(
"page",
parseInt(document.getElementById("page-number").textContent)
);
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
body: formData,
};
fetch(API_SERVER + "/users/getusers", requestOptions)
.then((response) => {
document.getElementById("usersTable").style.filter = "brightness(1)";
document.getElementById("legalsTable").style.filter = "brightness(1)";
if (response.ok) {
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
users.splice(0, users.length);
legals.splice(0, legals.length);
users.push(
...data.people.map((item) => ({
id: item.id,
name: item.Имя,
surname: item.Фамилия,
secondname: item.Отчество,
role: item.Должность,
sub: item.Субподряд,
department: item.Цех,
email: item.Email,
phone: item.Телефон,
isblocked: item.Черный_список,
}))
);
legals.push(
...data.legals.map((item) => ({
id: item.id,
name: item.Наименование,
inn: item.ИНН,
ogrn: item.ОГРН,
address: item.Юридический_адрес,
realaddress: item.Фактический_адрес,
email: item.Email,
}))
);
createTable();
peopleMax = Math.ceil(data.totalCountPeople / 15);
legalsMax = Math.ceil(data.totalCountLegal / 15);
if (peopleMax === 0) {
peopleMax = 1;
}
if (legalsMax === 0) {
legalsMax = 1;
}
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (tableType === "People") {
if (currentPage > peopleMax) {
pageNumberInput.textContent = peopleMax;
requestUpdate();
}
} else {
if (currentPage > legalsMax) {
pageNumberInput.textContent = legalsMax;
requestUpdate();
}
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
// function closeForm() {
// var formContainer = $("#form-bg");
// var fform = $("#form");
// formContainer.removeClass("active");
// fform.removeClass("form-animation");
// $("body").css("overflow", "auto");
// }
// document.addEventListener("DOMContentLoaded", function () {
// const form = document.getElementById("add-form");
// form.addEventListener("submit", function (event) {
// event.preventDefault();
// const deleteConfirmation = document.getElementById("addInformation");
// const closeButton = document.getElementById("closeButton");
// const mark = document.getElementById("success-mark");
// closeForm();
// closeButton.style.display = "none";
// deleteConfirmation.style.display = "flex";
// mark.style.display = "none";
// const formData = new FormData(form);
// form.reset();
// fetch(API_SERVER + "/user", {
// method: "POST",
// headers: {
// Authorization: getCookie("token"),
// },
// body: formData,
// })
// .then((response) => response.json())
// .then((data) => {
// showMessage("Пользователь успешно добавлен", true);
// })
// .catch((error) => {
// showMessage("Не удалось добавить пользователя", false);
// console.error("Ошибка:", error);
// });
// });
// });
// function addUser() {
// var formContainer = $("#form-bg");
// var form = $("#form");
// formContainer.addClass("active");
// form.addClass("form-animation");
// $("body").css("overflow", "hidden");
// }
// $(document).ready(function () {
// // Закрывает popup форму
// $("#close-form-btn").click(function () {
// closeForm();
// });
// // Функция для закрытия формы
// function closeForm() {
// var formContainer = $("#form-bg");
// var form = $("#form");
// formContainer.removeClass("active");
// form.removeClass("form-animation");
// $("body").css("overflow", "auto");
// }
// });

848
static/styles/main.css Normal file
View File

@ -0,0 +1,848 @@
body {
background-color: #fff;
font-family: "Montserrat", sans-serif;
margin: 0;
color: rgba(0, 0, 0, 0.87);
}
* {
box-sizing: border-box;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
input:read-only,
select:read-only,
textarea:read-only {
background-color: #0000000a;
}
header {
box-sizing: border-box;
width: 100%;
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
min-height: auto;
height: 56px;
background-color: #fff;
overflow: hidden;
transition: all 0.5s ease-out, background 1s ease-out;
transition-delay: 0.2s;
border-bottom: solid 1px #e5e7eb;
z-index: 6;
}
header a {
text-decoration: none;
}
header nav {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
header nav a {
color: rgb(102, 102, 102);
text-align: center;
font-size: 14px;
color: #6b7a99;
margin: 0;
font-weight: 500;
cursor: pointer;
transition: 0.2s;
display: flex;
justify-content: center;
align-items: center;
height: 40px;
padding: 0 16px;
border-radius: 4px;
}
header span {
color: rgb(102, 102, 102);
text-align: center;
font-size: 14px;
color: #6b7a99;
margin: 0;
font-weight: 500;
text-decoration: none;
padding: 10px 16px;
}
header nav a:hover {
background-color: #e5e7eb;
}
header h1 {
font-size: 14px;
color: #6b7a99;
margin: 0;
font-weight: 500;
}
h1 {
font-size: 24px;
font-weight: 500;
margin: 0;
}
.main-content {
box-sizing: border-box;
width: 100%;
padding: 50px;
display: flex;
flex-direction: column;
gap: 25px;
}
.main-content .bg {
box-sizing: border-box;
background-color: #fff;
border-radius: 4px;
width: 100%;
padding: 20px;
display: flex;
gap: 20px;
min-height: 300px;
}
.hub-bg {
box-sizing: border-box;
background-color: #fff;
border-radius: 4px;
width: 100%;
padding: 20px;
display: flex;
gap: 20px;
flex-wrap: wrap;
align-content: flex-start;
min-height: 300px;
}
.settings-area {
flex-direction: column;
}
.main-content .buttons {
width: 358px;
height: 260px;
padding-left: 20px;
border-left: solid 1px #e5e7eb;
display: flex;
flex-direction: column;
gap: 20px;
}
.main-content .buttons button {
background-color: #0050cf;
outline: none;
border: none;
box-sizing: border-box;
border-radius: 4px;
padding: 14px 16px;
font-size: 14px;
color: #fff;
font-weight: 500;
cursor: pointer;
transition: 0.2s;
}
.main-content .buttons button:hover {
background-color: #002d6e;
}
.main-form {
width: 775px;
margin: 100px auto;
border-radius: 4px;
background-color: #fff;
box-sizing: border-box;
padding: 50px 75px;
display: flex;
flex-direction: column;
gap: 25px;
}
.main-form .inputs {
display: flex;
flex-direction: column;
gap: 25px;
}
.main-form .radio-inputs {
margin: 0 auto;
}
.main-form h1 {
font-size: 32px;
font-size: 600;
margin-bottom: 20px;
text-align: center;
}
.input-area label,
.tmc-input-group label,
.car-input-group label {
font-size: 14px;
color: #6b7a99;
}
.input-area input,
.input-area textarea,
.input-area select,
.tmc-input-group input,
.car-input-group input {
box-sizing: border-box;
width: 100%;
padding: 14px 14px 12px 14px;
font-size: 16px;
line-height: 20px;
height: 48px;
border: 1px solid #d3d8e6;
border-radius: 4px;
outline: none;
margin-top: 5px;
}
.tmc-input-group input,
.car-input-group input {
margin-top: 0 !important;
}
.tmc-input-group,
.car-input-group {
display: flex;
flex-direction: column;
gap: 10px;
}
select {
cursor: pointer;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background: url(../img/down-input.svg) no-repeat right white !important;
background-position-x: calc(100% - 14px) !important;
}
.input-area textarea {
resize: vertical;
min-height: 110px;
}
.input-area input:focus,
.input-area textarea:focus,
.input-area select:focus,
.tmc-input-group input:focus {
border: 1px solid #000;
}
.form-info {
box-sizing: border-box;
padding: 16px 16px 16px 56px;
width: 100%;
background-color: rgb(240, 245, 255);
border-radius: 8px;
color: rgb(0, 45, 110);
font-size: 14px;
}
.form-info p {
color: rgb(0, 45, 110);
font-size: 14px;
position: relative;
margin: 0;
}
.form-info p:before {
content: "";
position: absolute;
top: calc(70% - 18px);
left: -29px;
display: block;
width: 18px;
height: 18px;
background: url(../img/info.svg) 100% 100% no-repeat;
}
button {
background-color: #0050cf;
outline: none;
border: none;
box-sizing: border-box;
border-radius: 4px;
padding: 14px;
font-size: 14px;
color: #fff;
font-weight: 600;
cursor: pointer;
transition: 0.3s;
}
button:hover {
background-color: #002d6e;
}
button.bright {
background-color: #f0f5ff;
color: #0050cf;
}
button.delete {
background-color: rgb(255, 69, 58);
}
button.delete:hover {
background-color: rgba(255, 69, 58, 0.8);
}
button.bright:hover {
background-color: #0050cf;
color: #fff;
}
button.inactive {
opacity: 0.5;
cursor: not-allowed;
}
button.inactive:hover {
background-color: #0050cf;
}
.login-form {
width: 775px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: auto;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.55);
border-radius: 10px;
background-color: #fff;
box-sizing: border-box;
padding: 36px;
display: flex;
flex-direction: column;
gap: 8px;
max-height: 80%;
max-width: 412px;
min-height: 185px;
min-width: 320px;
}
.login-form h1 {
font-size: 32px;
font-size: 600;
margin-bottom: 50px;
text-align: center;
}
.login-form input {
padding: 12px 18px;
border: 1px solid rgba(211, 215, 225, 0.6);
border-radius: 4px;
outline: none;
}
.login-form h1 {
margin-bottom: 15px;
}
.login-form button {
margin-top: 5px;
}
.login-form span {
font-size: 14.4px;
}
.login-form span a {
color: rgb(0, 103, 184);
text-decoration: none;
}
.exit-button {
height: 40px;
width: 40px;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
}
.hub-element {
padding: 10px 30px 10px 10px;
border-radius: 12px;
display: flex;
align-items: flex-start;
flex-direction: column;
justify-content: center;
flex-wrap: wrap;
width: 450px;
height: 80px;
cursor: pointer;
}
.hub-element:hover {
background-color: #eeeff3;
}
.hub-element .icon {
background-color: rgb(238, 239, 244);
border-radius: 12px;
padding: 8px;
width: 48px;
height: 48px;
margin-right: 16px;
}
.hub-element:hover .icon {
background-color: #fff;
}
.hub-element .icon svg {
width: 32px;
height: 32px;
}
.hub-element h1 {
font-size: 16px;
margin: 0;
font-weight: 600;
width: calc(100% - 60px);
}
.hub-element h2 {
font-size: 14px;
margin: 0;
font-weight: 400;
width: calc(100% - 60px);
}
.radio-inputs {
position: relative;
display: flex;
flex-wrap: wrap;
border-radius: 0.5rem;
background-color: #eee;
box-sizing: border-box;
box-shadow: 0 0 0px 1px rgba(0, 0, 0, 0.06);
padding: 0.25rem;
width: 300px;
font-size: 14px;
}
.radio-inputs .radio {
flex: 1 1 auto;
text-align: center;
}
.radio-inputs .radio input {
display: none;
}
.radio-inputs .radio .name {
display: flex;
cursor: pointer;
align-items: center;
justify-content: center;
border-radius: 0.5rem;
border: none;
padding: 0.5rem 0;
color: rgba(51, 65, 85, 1);
transition: all 0.15s ease-in-out;
}
.radio-inputs .radio input:checked + .name {
background-color: #fff;
font-weight: 600;
}
#pass-form .radio-inputs {
width: 600px;
}
.underheader-buttons {
width: 100%;
border-bottom: solid 1px #e5e7eb;
height: 56px;
display: flex;
align-items: center;
padding: 16px;
gap: 24px;
}
.underheader-buttons button {
border: solid 1px #d3d8e6;
border-radius: 4px;
background-color: #fff;
color: #6b7a99;
font-weight: 500;
height: 38px;
padding: 0 25px;
}
.underheader-buttons button:hover {
background-color: #e5e7eb;
}
.underheader-buttons input {
border: solid 1px #d3d8e6;
border-radius: 4px;
font-size: 14px;
background-color: #fff;
color: rgba(0, 0, 0, 0.75);
font-weight: 500;
height: 38px;
padding: 0 5px 0 10px;
outline: none;
width: 200px;
}
input::placeholder,
textarea::placeholder {
color: #6b7a99;
}
.underheader-buttons input:focus {
border: 1px solid #0050cf;
}
.underheader-buttons button.blue {
background-color: #0050cf;
color: #fff;
}
.table-wrapper {
overflow-x: auto;
position: relative;
box-sizing: border-box;
width: calc(100% - 32px);
margin: 24px 16px;
box-shadow: 0 0 0 1px #e5e7eb;
border-radius: 4px;
background-color: white;
}
table {
box-sizing: border-box;
width: 100%;
border-collapse: collapse;
overflow: hidden;
background-color: white;
}
table th {
color: rgba(0, 0, 0, 0.87);
font-size: 14px;
font-weight: 600;
height: 56px;
padding: 0 50px 0 10px;
border: 0;
text-align: left;
}
table td {
color: rgba(0, 0, 0, 0.87);
font-size: 14px;
padding: 0 50px 0 10px;
height: 56px;
font-weight: 500;
border-bottom: 0;
border-top: 1px solid #e5e7eb;
}
table tbody tr {
transition: 0.2s;
cursor: pointer;
background-color: white;
}
table tbody tr:hover {
background-color: #e5e7eb;
}
#pagination {
display: flex;
gap: 5px;
justify-content: center;
}
#pagination a {
color: rgba(0, 0, 0, 0.6);
border-radius: 10px;
padding: 8px 12px;
text-decoration: none;
margin-left: 6px;
}
#pagination a.active {
background-color: rgba(0, 0, 0, 0.05);
}
#pagination a:hover:not(.active) {
background-color: rgba(0, 0, 0, 0.025);
}
#pagination input:hover,
#pagination input:focus {
border: 1px solid rgba(0, 0, 0, 0.3);
}
#pagination #page-number {
width: 40px;
height: 40px;
display: flex;
border-radius: 8px;
background-color: #0050cf;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 14px;
}
#pagination #left-slider,
#pagination #right-slider {
width: 40px;
height: 40px;
display: flex;
border-radius: 4px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: 0.1s;
}
#pagination #left-slider:hover,
#pagination #right-slider:hover {
background-color: rgba(0, 0, 0, 0.1);
}
.form-popup-bg {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
background-color: rgba(255, 255, 255, 1);
opacity: 0;
visibility: hidden;
transition: opacity 0.3s, visibility 0s 0.3s;
overflow-y: auto;
z-index: 10000;
}
.form-popup-bg.is-visible {
opacity: 1;
visibility: visible;
-webkit-transition: opacity 0.3s 0s, visibility 0s 0s;
-moz-transition: opacity 0.3s 0s, visibility 0s 0s;
transition: opacity 0.3s 0s, visibility 0s 0s;
}
.form-popup-bg.not-main {
background-color: rgba(0, 0, 0, 0.1);
}
.form-container {
border-radius: 10px;
display: flex;
flex-direction: column;
gap: 15px;
width: 1000px;
margin-left: auto;
margin-right: auto;
position: relative;
padding: 50px 40px;
border-radius: 12px;
border: 1px solid #fff;
background: #fff;
box-shadow: 0px 12px 28px 0px #c5cbd0;
display: inline-flex;
flex-direction: column;
flex-shrink: 0;
max-height: calc(100vh - 100px);
overflow-y: auto;
}
.close-button {
width: 40px;
height: 40px;
position: absolute;
top: 8px;
right: 8px;
cursor: pointer;
user-select: none;
display: flex;
justify-content: center;
align-items: center;
}
.form-container h1 {
font-size: 32px;
margin: 0;
font-weight: 500;
}
.form-container h2 {
font-size: 18px;
margin: 0;
font-weight: 500;
}
.form-container .inputs,
.worker-inputs {
display: flex;
flex-direction: column;
gap: 15px;
}
.three-inputs,
.two-inputs {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 10px 0;
}
.three-inputs input,
.three-inputs select {
box-sizing: border-box;
width: 32.5%;
padding: 14px 14px 12px 14px;
font-size: 16px;
line-height: 20px;
height: 48px;
border: 1px solid #d3d8e6;
border-radius: 4px;
outline: none;
}
.two-inputs input,
.two-inputs select {
box-sizing: border-box;
width: 49.5%;
padding: 14px 14px 12px 14px;
font-size: 16px;
line-height: 20px;
height: 48px;
border: 1px solid #d3d8e6;
border-radius: 4px;
outline: none;
}
.three-inputs input:focus,
.three-inputs select:focus,
.two-inputs input:focus,
.two-inputs select:focus {
border: 1px solid #000;
}
.fullname-input-group {
display: flex;
gap: 5px;
}
.fullname-input-group button {
height: 48px;
margin-top: 5px;
}
#tmclist,
#carlist {
list-style-type: none;
padding: 0;
margin: 0;
}
.blocked-alarm {
display: flex;
position: absolute;
left: 25px;
top: 25px;
height: 75px;
width: 350px;
padding: 15px;
align-items: center;
justify-content: space-between;
gap: 10px;
background-color: white;
border-radius: 10px;
}
.blocked-alarm h1 {
margin: 0;
font-size: 20px;
}
.blocked-alarm svg {
height: 50px;
z-index: 100;
}
.dropdown-help {
display: none;
flex-direction: column;
align-items: flex-start;
position: absolute;
background-color: #fff;
width: 212px;
transform: translate(calc(-100% + 212px), 10px);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 12px;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.02),
0px 4px 8px -4px rgba(0, 0, 0, 0.04), 0px 16px 24px -8px rgba(0, 0, 0, 0.06);
padding: 8px;
z-index: 6;
opacity: 0;
transition: opacity 0.2s ease;
}
.dropdown-help.is-visible {
opacity: 1;
transition: none;
}
.dropdown-help a {
font-size: 14px;
height: 40px;
border-radius: 6px;
padding: 0 8px;
width: 100%;
display: flex;
align-items: center;
transition: 0.1s ease;
cursor: pointer;
text-decoration: none;
color: #0f0f10;
}
.dropdown-help a:hover {
background: rgba(0, 0, 0, 0.06);
}
.dropdown-manual {
width: 122px;
transform: translate(calc(-100% + 122px), 10px);
}

View File

@ -0,0 +1,272 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Личный кабинет</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<a href="/account"><h1>Бюро пропусков / Личный кабинет</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<section class="main-content">
<h1>Хаб услуг</h1>
<div class="hub-bg">
<div onclick="location.href='/account/newform'" class="hub-element">
<div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none" viewBox="0 0 32 32">
<g clip-path="url(#a)">
<path fill="#000" d="M18.667 10.667H6.222a.889.889 0 0 1-.889-.89V6.223a.889.889 0 0 1 .89-.889h12.444a.889.889 0 0 1 .889.89v3.555a.889.889 0 0 1-.89.889ZM7.11 8.889h10.667V7.058H7.11v1.83Zm11.557 3.626H6.222a.889.889 0 0 0-.889.89v3.484a.889.889 0 0 0 .89.889H16.32l3.236-3.29v-1.084a.889.889 0 0 0-.89-.889ZM17.777 16H7.112v-1.778h10.667V16Z"/>
<path fill="#000" d="M9.831 28.009v-.053l.285-1.236h-6.56V3.556h17.777v9.11l1.778-1.68v-8.32a.889.889 0 0 0-.889-.888H2.667a.889.889 0 0 0-.89.889v24.888a.889.889 0 0 0 .89.89h7.11c.008-.147.026-.292.054-.436Zm9.724-10.969-.693.702a.89.89 0 0 0 .694-.702Z"/>
<path fill="#000" d="M5.333 23.947a.889.889 0 0 0 .89.889h4.301l.267-1.156.116-.489v-.044H7.11v-1.814h5.636l1.777-1.777h-8.3a.889.889 0 0 0-.889.888v3.503Zm24.436-9.129-2.996-2.996a1.43 1.43 0 0 0-2.026 0L12.56 24.08l-1.005 4.276a1.43 1.43 0 0 0 1.12 1.688c.092.01.184.01.276 0 .109.018.22.018.329 0l4.311-.95L29.77 16.888a1.422 1.422 0 0 0 0-2.018v-.053ZM16.684 27.476l-3.253.72.791-3.227 9.138-9.236 2.507 2.507-9.183 9.236Zm10.187-10.24-2.507-2.507 1.414-1.396 2.524 2.525-1.43 1.378Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v32H0z"/>
</clipPath>
</defs>
</svg></div>
<h1>Заявка на пропуск</h1>
<h2>Оставить заявку на пропуск для сотрудника</h2>
</div>
<div onclick="location.href='/account/settings'" class="hub-element">
<div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="28" height="26" fill="none" viewBox="0 0 28 26">
<path fill="#292D32" d="M24.8 9.295c-2.413 0-3.4-1.706-2.2-3.8a2.529 2.529 0 0 0-.933-3.453L19.36.722c-1.053-.627-2.413-.253-3.04.8l-.147.253c-1.2 2.094-3.173 2.094-4.386 0l-.147-.253a2.188 2.188 0 0 0-3.013-.8L6.32 2.042c-1.213.693-1.627 2.253-.933 3.467C6.6 7.589 5.613 9.295 3.2 9.295A2.54 2.54 0 0 0 .667 11.83v2.346A2.54 2.54 0 0 0 3.2 16.71c2.413 0 3.4 1.706 2.187 3.8a2.529 2.529 0 0 0 .933 3.453l2.307 1.32c1.053.627 2.413.253 3.04-.8l.146-.253c1.2-2.094 3.174-2.094 4.387 0l.147.253c.626 1.053 1.986 1.427 3.04.8l2.306-1.32a2.532 2.532 0 0 0 .934-3.453c-1.214-2.094-.227-3.8 2.186-3.8a2.54 2.54 0 0 0 2.534-2.534v-2.347c-.014-1.386-1.147-2.533-2.547-2.533ZM14 17.335a4.342 4.342 0 0 1-4.333-4.333A4.342 4.342 0 0 1 14 8.669a4.342 4.342 0 0 1 4.333 4.333A4.342 4.342 0 0 1 14 17.335Z"/>
</svg>
</div>
<h1>Настройки</h1>
<h2>Изменить информацию профиля</h2>
</div>
{{#if (eq Role 'Дирекция')}}
<div onclick="location.href='/users'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="23" fill="none" viewBox="0 0 32 23">
<g clip-path="url(#a)">
<path fill="#000" fill-opacity=".85" d="M13.904 13.934c-1.773 1.54-2.771 3.511-2.771 5.279 0 .506.102.995.347 1.42H3.33c-1.345 0-1.878-.534-1.878-1.506 0-2.946 3.01-6.5 7.823-6.5 1.825 0 3.39.51 4.63 1.306Zm-.903-7.05c0 2.317-1.73 4.11-3.715 4.11-1.996 0-3.725-1.793-3.725-4.088 0-2.284 1.74-4.013 3.725-4.013 1.975 0 3.715 1.686 3.715 3.992Zm8.571 3.864c2.294 0 4.27-2.049 4.27-4.717 0-2.637-1.986-4.59-4.27-4.59s-4.27 1.996-4.27 4.611c0 2.647 1.975 4.697 4.27 4.697Zm-6.714 9.884h13.417c1.676 0 2.273-.48 2.273-1.42 0-2.753-3.447-6.553-8.987-6.553-5.529 0-8.977 3.8-8.977 6.554 0 .94.598 1.42 2.274 1.42Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v22.084H0z"/>
</clipPath>
</defs>
</svg>
</div>
<h1>Пользователи</h1>
<h2>Управление работниками и организациями</h2>
</div>
<div onclick="location.href='/applications'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="32" fill="none" viewBox="0 0 20 32">
<g clip-path="url(#a)">
<path fill="#000" fill-opacity=".85" d="M19.424 8.188v17.507c0 2.425-1.19 3.626-3.58 3.626H3.58C1.19 29.32 0 28.12 0 25.695V8.188c0-2.425 1.19-3.626 3.58-3.626h.153a2.71 2.71 0 0 0-.014.288v1.213c0 .123.007.243.023.358h-.07c-1.2 0-1.813.646-1.813 1.79v17.46c0 1.155.612 1.79 1.813 1.79h12.08c1.2 0 1.813-.635 1.813-1.79V8.212c0-1.144-.612-1.79-1.813-1.79h-.07a2.5 2.5 0 0 0 .024-.358V4.85c0-.098-.005-.195-.015-.288h.153c2.39 0 3.58 1.2 3.58 3.626Z"/>
<path fill="#000" fill-opacity=".85" d="M6.144 7.206h7.136c.67 0 1.074-.427 1.074-1.143V4.85c0-.716-.404-1.143-1.074-1.143h-1.062c-.08-1.305-1.166-2.367-2.506-2.367-1.34 0-2.425 1.062-2.506 2.367H6.144c-.67 0-1.074.427-1.074 1.143v1.213c0 .716.404 1.143 1.074 1.143Zm3.568-2.402a1.013 1.013 0 0 1-1.005-1.005c0-.566.45-1.016 1.005-1.016.554 0 1.005.45 1.005 1.016 0 .543-.45 1.005-1.005 1.005ZM4.62 22.069h5.127a.72.72 0 0 0 .716-.716.712.712 0 0 0-.716-.716H4.619a.722.722 0 0 0-.727.716.73.73 0 0 0 .727.716Zm0-4.319h10.185a.725.725 0 0 0 .727-.728.712.712 0 0 0-.727-.704H4.619a.712.712 0 0 0-.727.704c0 .404.323.728.727.728Zm0-4.1h10.185a.73.73 0 0 0 .727-.716.74.74 0 0 0-.727-.728H4.619a.74.74 0 0 0-.727.728.73.73 0 0 0 .727.716Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h19.424v32H0z"/>
</clipPath>
</defs>
</svg>
</div>
<h1>Заявки на пропуска</h1>
<h2>Управление заявками от физ лиц и от юр лиц</h2>
</div>
<div onclick="location.href='/passes'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="25" fill="none" viewBox="0 0 32 25">
<path fill="#000" fill-opacity=".85" d="M4.261 24.984H27.74c2.85 0 4.261-1.398 4.261-4.194V4.208C32 1.41 30.589 0 27.739 0H4.26C1.425 0 0 1.411 0 4.207V20.79c0 2.795 1.425 4.193 4.261 4.193Zm.027-2.185c-1.357 0-2.103-.72-2.103-2.13V4.328c0-1.411.746-2.144 2.103-2.144h23.424c1.343 0 2.103.733 2.103 2.144v16.34c0 1.41-.76 2.13-2.103 2.13H4.288Z"/>
<path fill="#000" fill-opacity=".85" d="M6.433 7.423a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.262-1.262-1.262-.679 0-1.263.57-1.263 1.262 0 .679.584 1.262 1.263 1.262Zm0 4.153a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.262-1.262-1.262-.679 0-1.263.57-1.263 1.262 0 .678.584 1.262 1.263 1.262Zm0 4.139c.705 0 1.262-.556 1.262-1.262a1.25 1.25 0 0 0-1.262-1.249c-.693 0-1.263.57-1.263 1.249 0 .706.57 1.262 1.263 1.262Zm0 4.356a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.276-1.262-1.276-.679 0-1.263.584-1.263 1.276 0 .679.584 1.262 1.263 1.262ZM10.53 6.99h15.525c.488 0 .855-.366.855-.828a.851.851 0 0 0-.855-.855H10.53a.851.851 0 0 0-.855.855c0 .462.366.828.855.828Zm0 4.166h8.604c.461 0 .841-.38.841-.841a.857.857 0 0 0-.841-.855H10.53a.86.86 0 0 0-.855.855c0 .461.38.841.855.841Zm0 4.153h15.525a.835.835 0 0 0 .855-.855c0-.461-.367-.828-.855-.828H10.53c-.489 0-.855.367-.855.828 0 .489.366.855.855.855Zm0 4.343h8.604c.461 0 .841-.38.841-.842a.829.829 0 0 0-.841-.841H10.53a.832.832 0 0 0-.855.841c0 .462.38.842.855.842Z"/>
</svg>
</div>
<h1>Пропуска</h1>
<h2>Управление пропусками всех видов</h2>
</div>
<div onclick="location.href='/tso'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="30" fill="none" viewBox="0 0 32 30">
<path fill="#000" d="M4.168 29.008h23.664c2.595 0 4.168-1.802 4.168-4.138 0-.717-.214-1.465-.596-2.137L19.557 2.092C18.763.702 17.405 0 16 0a4.028 4.028 0 0 0-3.557 2.092L.595 22.732A4.122 4.122 0 0 0 0 24.87c0 2.336 1.573 4.138 4.168 4.138Zm.015-2.397c-1.068 0-1.71-.825-1.71-1.756 0-.29.061-.657.23-.977l11.83-20.626c.321-.565.901-.81 1.466-.81s1.13.245 1.45.81l11.832 20.641c.168.32.245.672.245.962 0 .931-.672 1.756-1.726 1.756H4.184Z"/>
<path fill="#000" d="M16 18.718c.733 0 1.16-.428 1.176-1.222l.213-8.046c.016-.778-.595-1.358-1.404-1.358-.825 0-1.405.564-1.39 1.343l.199 8.061c.015.779.443 1.222 1.206 1.222Zm0 4.961c.886 0 1.649-.702 1.649-1.587 0-.901-.748-1.588-1.649-1.588-.9 0-1.649.702-1.649 1.588 0 .87.763 1.587 1.649 1.587Z"/>
</svg>
</div>
<h1>Заявки ТСО</h1>
<h2>Управление заявками ТСО</h2>
</div>
<div onclick="location.href='/account/newtso'" class="hub-element">
<div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none" viewBox="0 0 32 32">
<g clip-path="url(#a)">
<path fill="#000" d="M18.667 10.667H6.222a.889.889 0 0 1-.889-.89V6.223a.889.889 0 0 1 .89-.889h12.444a.889.889 0 0 1 .889.89v3.555a.889.889 0 0 1-.89.889ZM7.11 8.889h10.667V7.058H7.11v1.83Zm11.557 3.626H6.222a.889.889 0 0 0-.889.89v3.484a.889.889 0 0 0 .89.889H16.32l3.236-3.29v-1.084a.889.889 0 0 0-.89-.889ZM17.777 16H7.112v-1.778h10.667V16Z"/>
<path fill="#000" d="M9.831 28.009v-.053l.285-1.236h-6.56V3.556h17.777v9.11l1.778-1.68v-8.32a.889.889 0 0 0-.889-.888H2.667a.889.889 0 0 0-.89.889v24.888a.889.889 0 0 0 .89.89h7.11c.008-.147.026-.292.054-.436Zm9.724-10.969-.693.702a.89.89 0 0 0 .694-.702Z"/>
<path fill="#000" d="M5.333 23.947a.889.889 0 0 0 .89.889h4.301l.267-1.156.116-.489v-.044H7.11v-1.814h5.636l1.777-1.777h-8.3a.889.889 0 0 0-.889.888v3.503Zm24.436-9.129-2.996-2.996a1.43 1.43 0 0 0-2.026 0L12.56 24.08l-1.005 4.276a1.43 1.43 0 0 0 1.12 1.688c.092.01.184.01.276 0 .109.018.22.018.329 0l4.311-.95L29.77 16.888a1.422 1.422 0 0 0 0-2.018v-.053ZM16.684 27.476l-3.253.72.791-3.227 9.138-9.236 2.507 2.507-9.183 9.236Zm10.187-10.24-2.507-2.507 1.414-1.396 2.524 2.525-1.43 1.378Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v32H0z"/>
</clipPath>
</defs>
</svg></div>
<h1>Заявка ТСО</h1>
<h2>Оставить заявку ТСО</h2>
</div>
{{/if}}
{{#if (eq Role 'Пропуска')}}
<div onclick="location.href='/applications'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="32" fill="none" viewBox="0 0 20 32">
<g clip-path="url(#a)">
<path fill="#000" fill-opacity=".85" d="M19.424 8.188v17.507c0 2.425-1.19 3.626-3.58 3.626H3.58C1.19 29.32 0 28.12 0 25.695V8.188c0-2.425 1.19-3.626 3.58-3.626h.153a2.71 2.71 0 0 0-.014.288v1.213c0 .123.007.243.023.358h-.07c-1.2 0-1.813.646-1.813 1.79v17.46c0 1.155.612 1.79 1.813 1.79h12.08c1.2 0 1.813-.635 1.813-1.79V8.212c0-1.144-.612-1.79-1.813-1.79h-.07a2.5 2.5 0 0 0 .024-.358V4.85c0-.098-.005-.195-.015-.288h.153c2.39 0 3.58 1.2 3.58 3.626Z"/>
<path fill="#000" fill-opacity=".85" d="M6.144 7.206h7.136c.67 0 1.074-.427 1.074-1.143V4.85c0-.716-.404-1.143-1.074-1.143h-1.062c-.08-1.305-1.166-2.367-2.506-2.367-1.34 0-2.425 1.062-2.506 2.367H6.144c-.67 0-1.074.427-1.074 1.143v1.213c0 .716.404 1.143 1.074 1.143Zm3.568-2.402a1.013 1.013 0 0 1-1.005-1.005c0-.566.45-1.016 1.005-1.016.554 0 1.005.45 1.005 1.016 0 .543-.45 1.005-1.005 1.005ZM4.62 22.069h5.127a.72.72 0 0 0 .716-.716.712.712 0 0 0-.716-.716H4.619a.722.722 0 0 0-.727.716.73.73 0 0 0 .727.716Zm0-4.319h10.185a.725.725 0 0 0 .727-.728.712.712 0 0 0-.727-.704H4.619a.712.712 0 0 0-.727.704c0 .404.323.728.727.728Zm0-4.1h10.185a.73.73 0 0 0 .727-.716.74.74 0 0 0-.727-.728H4.619a.74.74 0 0 0-.727.728.73.73 0 0 0 .727.716Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h19.424v32H0z"/>
</clipPath>
</defs>
</svg>
</div>
<h1>Заявки на пропуска</h1>
<h2>Управление заявками от физ лиц и от юр лиц</h2>
</div>
<div onclick="location.href='/passes'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="25" fill="none" viewBox="0 0 32 25">
<path fill="#000" fill-opacity=".85" d="M4.261 24.984H27.74c2.85 0 4.261-1.398 4.261-4.194V4.208C32 1.41 30.589 0 27.739 0H4.26C1.425 0 0 1.411 0 4.207V20.79c0 2.795 1.425 4.193 4.261 4.193Zm.027-2.185c-1.357 0-2.103-.72-2.103-2.13V4.328c0-1.411.746-2.144 2.103-2.144h23.424c1.343 0 2.103.733 2.103 2.144v16.34c0 1.41-.76 2.13-2.103 2.13H4.288Z"/>
<path fill="#000" fill-opacity=".85" d="M6.433 7.423a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.262-1.262-1.262-.679 0-1.263.57-1.263 1.262 0 .679.584 1.262 1.263 1.262Zm0 4.153a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.262-1.262-1.262-.679 0-1.263.57-1.263 1.262 0 .678.584 1.262 1.263 1.262Zm0 4.139c.705 0 1.262-.556 1.262-1.262a1.25 1.25 0 0 0-1.262-1.249c-.693 0-1.263.57-1.263 1.249 0 .706.57 1.262 1.263 1.262Zm0 4.356a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.276-1.262-1.276-.679 0-1.263.584-1.263 1.276 0 .679.584 1.262 1.263 1.262ZM10.53 6.99h15.525c.488 0 .855-.366.855-.828a.851.851 0 0 0-.855-.855H10.53a.851.851 0 0 0-.855.855c0 .462.366.828.855.828Zm0 4.166h8.604c.461 0 .841-.38.841-.841a.857.857 0 0 0-.841-.855H10.53a.86.86 0 0 0-.855.855c0 .461.38.841.855.841Zm0 4.153h15.525a.835.835 0 0 0 .855-.855c0-.461-.367-.828-.855-.828H10.53c-.489 0-.855.367-.855.828 0 .489.366.855.855.855Zm0 4.343h8.604c.461 0 .841-.38.841-.842a.829.829 0 0 0-.841-.841H10.53a.832.832 0 0 0-.855.841c0 .462.38.842.855.842Z"/>
</svg>
</div>
<h1>Пропуска</h1>
<h2>Управление пропусками всех видов</h2>
</div>
<div onclick="location.href='/account/newtso'" class="hub-element">
<div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none" viewBox="0 0 32 32">
<g clip-path="url(#a)">
<path fill="#000" d="M18.667 10.667H6.222a.889.889 0 0 1-.889-.89V6.223a.889.889 0 0 1 .89-.889h12.444a.889.889 0 0 1 .889.89v3.555a.889.889 0 0 1-.89.889ZM7.11 8.889h10.667V7.058H7.11v1.83Zm11.557 3.626H6.222a.889.889 0 0 0-.889.89v3.484a.889.889 0 0 0 .89.889H16.32l3.236-3.29v-1.084a.889.889 0 0 0-.89-.889ZM17.777 16H7.112v-1.778h10.667V16Z"/>
<path fill="#000" d="M9.831 28.009v-.053l.285-1.236h-6.56V3.556h17.777v9.11l1.778-1.68v-8.32a.889.889 0 0 0-.889-.888H2.667a.889.889 0 0 0-.89.889v24.888a.889.889 0 0 0 .89.89h7.11c.008-.147.026-.292.054-.436Zm9.724-10.969-.693.702a.89.89 0 0 0 .694-.702Z"/>
<path fill="#000" d="M5.333 23.947a.889.889 0 0 0 .89.889h4.301l.267-1.156.116-.489v-.044H7.11v-1.814h5.636l1.777-1.777h-8.3a.889.889 0 0 0-.889.888v3.503Zm24.436-9.129-2.996-2.996a1.43 1.43 0 0 0-2.026 0L12.56 24.08l-1.005 4.276a1.43 1.43 0 0 0 1.12 1.688c.092.01.184.01.276 0 .109.018.22.018.329 0l4.311-.95L29.77 16.888a1.422 1.422 0 0 0 0-2.018v-.053ZM16.684 27.476l-3.253.72.791-3.227 9.138-9.236 2.507 2.507-9.183 9.236Zm10.187-10.24-2.507-2.507 1.414-1.396 2.524 2.525-1.43 1.378Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v32H0z"/>
</clipPath>
</defs>
</svg></div>
<h1>Заявка ТСО</h1>
<h2>Оставить заявку ТСО</h2>
</div>
{{/if}}
{{#if (eq Role 'КПП')}}
<div onclick="location.href='/users'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="23" fill="none" viewBox="0 0 32 23">
<g clip-path="url(#a)">
<path fill="#000" fill-opacity=".85" d="M13.904 13.934c-1.773 1.54-2.771 3.511-2.771 5.279 0 .506.102.995.347 1.42H3.33c-1.345 0-1.878-.534-1.878-1.506 0-2.946 3.01-6.5 7.823-6.5 1.825 0 3.39.51 4.63 1.306Zm-.903-7.05c0 2.317-1.73 4.11-3.715 4.11-1.996 0-3.725-1.793-3.725-4.088 0-2.284 1.74-4.013 3.725-4.013 1.975 0 3.715 1.686 3.715 3.992Zm8.571 3.864c2.294 0 4.27-2.049 4.27-4.717 0-2.637-1.986-4.59-4.27-4.59s-4.27 1.996-4.27 4.611c0 2.647 1.975 4.697 4.27 4.697Zm-6.714 9.884h13.417c1.676 0 2.273-.48 2.273-1.42 0-2.753-3.447-6.553-8.987-6.553-5.529 0-8.977 3.8-8.977 6.554 0 .94.598 1.42 2.274 1.42Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v22.084H0z"/>
</clipPath>
</defs>
</svg>
</div>
<h1>Пользователи</h1>
<h2>Просмотр данных сотрудников</h2>
</div>
<div onclick="location.href='/passes'" class="hub-element">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="25" fill="none" viewBox="0 0 32 25">
<path fill="#000" fill-opacity=".85" d="M4.261 24.984H27.74c2.85 0 4.261-1.398 4.261-4.194V4.208C32 1.41 30.589 0 27.739 0H4.26C1.425 0 0 1.411 0 4.207V20.79c0 2.795 1.425 4.193 4.261 4.193Zm.027-2.185c-1.357 0-2.103-.72-2.103-2.13V4.328c0-1.411.746-2.144 2.103-2.144h23.424c1.343 0 2.103.733 2.103 2.144v16.34c0 1.41-.76 2.13-2.103 2.13H4.288Z"/>
<path fill="#000" fill-opacity=".85" d="M6.433 7.423a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.262-1.262-1.262-.679 0-1.263.57-1.263 1.262 0 .679.584 1.262 1.263 1.262Zm0 4.153a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.262-1.262-1.262-.679 0-1.263.57-1.263 1.262 0 .678.584 1.262 1.263 1.262Zm0 4.139c.705 0 1.262-.556 1.262-1.262a1.25 1.25 0 0 0-1.262-1.249c-.693 0-1.263.57-1.263 1.249 0 .706.57 1.262 1.263 1.262Zm0 4.356a1.26 1.26 0 0 0 1.262-1.262c0-.706-.557-1.276-1.262-1.276-.679 0-1.263.584-1.263 1.276 0 .679.584 1.262 1.263 1.262ZM10.53 6.99h15.525c.488 0 .855-.366.855-.828a.851.851 0 0 0-.855-.855H10.53a.851.851 0 0 0-.855.855c0 .462.366.828.855.828Zm0 4.166h8.604c.461 0 .841-.38.841-.841a.857.857 0 0 0-.841-.855H10.53a.86.86 0 0 0-.855.855c0 .461.38.841.855.841Zm0 4.153h15.525a.835.835 0 0 0 .855-.855c0-.461-.367-.828-.855-.828H10.53c-.489 0-.855.367-.855.828 0 .489.366.855.855.855Zm0 4.343h8.604c.461 0 .841-.38.841-.842a.829.829 0 0 0-.841-.841H10.53a.832.832 0 0 0-.855.841c0 .462.38.842.855.842Z"/>
</svg>
</div>
<h1>Пропуска</h1>
<h2>Управление пропусками всех видов</h2>
</div>
{{/if}}
{{#if (eq Role 'Работник')}}
<div onclick="location.href='/account/newtso'" class="hub-element">
<div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none" viewBox="0 0 32 32">
<g clip-path="url(#a)">
<path fill="#000" d="M18.667 10.667H6.222a.889.889 0 0 1-.889-.89V6.223a.889.889 0 0 1 .89-.889h12.444a.889.889 0 0 1 .889.89v3.555a.889.889 0 0 1-.89.889ZM7.11 8.889h10.667V7.058H7.11v1.83Zm11.557 3.626H6.222a.889.889 0 0 0-.889.89v3.484a.889.889 0 0 0 .89.889H16.32l3.236-3.29v-1.084a.889.889 0 0 0-.89-.889ZM17.777 16H7.112v-1.778h10.667V16Z"/>
<path fill="#000" d="M9.831 28.009v-.053l.285-1.236h-6.56V3.556h17.777v9.11l1.778-1.68v-8.32a.889.889 0 0 0-.889-.888H2.667a.889.889 0 0 0-.89.889v24.888a.889.889 0 0 0 .89.89h7.11c.008-.147.026-.292.054-.436Zm9.724-10.969-.693.702a.89.89 0 0 0 .694-.702Z"/>
<path fill="#000" d="M5.333 23.947a.889.889 0 0 0 .89.889h4.301l.267-1.156.116-.489v-.044H7.11v-1.814h5.636l1.777-1.777h-8.3a.889.889 0 0 0-.889.888v3.503Zm24.436-9.129-2.996-2.996a1.43 1.43 0 0 0-2.026 0L12.56 24.08l-1.005 4.276a1.43 1.43 0 0 0 1.12 1.688c.092.01.184.01.276 0 .109.018.22.018.329 0l4.311-.95L29.77 16.888a1.422 1.422 0 0 0 0-2.018v-.053ZM16.684 27.476l-3.253.72.791-3.227 9.138-9.236 2.507 2.507-9.183 9.236Zm10.187-10.24-2.507-2.507 1.414-1.396 2.524 2.525-1.43 1.378Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v32H0z"/>
</clipPath>
</defs>
</svg></div>
<h1>Заявка ТСО</h1>
<h2>Оставить заявку ТСО</h2>
</div>
{{/if}}
</div>
</section>
</body>
</html>

View File

@ -0,0 +1,510 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Управление пользователями</title>
<script>
const API_SERVER = "{{API_SERVER}}";
let applications = [
{{#each Applications}}
{
id: {{this.id}},
status: "{{this.Статус}}",
type: "{{this.Вид_заявки}}",
worker: "{{this.Работник}}",
date: "{{this.Датааявки}}",
finaldate: "{{this.Дата_решения}}",
legal: "{{this.Организация}}",
car: "{{this.Авто_госомер}}",
},
{{/each}}
];
</script>
<script src="../scripts/applications-table.js"></script>
</head>
<body>
<header>
<a href="/account"><h1>Система управления заявками на пропуска</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/account">Профиль</a>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<nav class="underheader-buttons">
<button onclick="location.href='/account/newform'" class="blue">Создать заявку</button>
<input id="table-search" type="text" placeholder="Поиск...">
<button onclick="requestUpdate();">Найти</button>
<button onclick="requestUpdate();"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" fill="none" viewBox="0 0 16 20">
<path fill="#6B7A99" d="M8 4V0L3 5l5 5V6c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H0c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8Z"/>
</svg>
</button>
</nav>
<div id="applicationsWrapper" class="table-wrapper">
<table id="applicationsTable">
<thead>
<tr>
<th>ID</th>
<th>Статус</th>
<th>Вид</th>
<th>ФИО</th>
<th>Организация</th>
<th>Дата пропуска</th>
<th>Дата решения</th>
<th>Автомобиль</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div id="pagination">
<div id="left-slider" onclick="decrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M0 9.495c0 .273.101.514.315.722l8.92 8.477a.981.981 0 0 0 .73.295c.585 0 1.035-.427 1.035-.995 0-.285-.124-.525-.304-.711L2.508 9.495l8.188-7.789c.18-.186.304-.437.304-.71C11 .425 10.55 0 9.965 0c-.292 0-.54.098-.73.284L.314 8.773A.955.955 0 0 0 0 9.495Z"/>
</svg>
</div>
<div id="page-number">1</div>
<div id="right-slider" onclick="incrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M11 9.495a.967.967 0 0 0-.326-.722L1.766.284A1.062 1.062 0 0 0 1.024 0C.45 0 0 .427 0 .995c0 .274.112.525.292.711l8.189 7.789-8.189 7.788c-.18.186-.292.426-.292.71 0 .57.45.996 1.024.996.292 0 .54-.098.742-.295l8.908-8.477c.213-.208.326-.449.326-.722Z"/>
</svg>
</div>
</div>
<form id="editApplicationForm">
<input type="text" id="editapplicationid-input" hidden>
<input type="text" id="editapplicationtype-input" hidden>
<div id="editapplication-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Заявка на <span id="editApplication"></span> пропуск</h1>
<br>
<div class="input-area">
<label for="editauthor-input">Автор</label>
<input type="text" id="editauthor-input" readonly>
</div>
<div class="input-area">
<label for="editstatus-input">Статус</label>
<select id="editstatus-input">
<option value="Новая">Новая</option>
<option value="Утверждено">Утверждено</option>
<option value="Отказ">Отказ</option>
</select>
</div>
<div class="input-area">
<label for="editname-input">ФИО*</label>
<input type="text" id="editname-input" required>
</div>
<div class="input-area">
<label for="editlegal-input">Организация</label>
<input type="text" id="editlegal-input">
</div>
<div class="input-area">
<label for="editdate-input">Дата выдачи*</label>
<input type="date" id="editdate-input" required>
</div>
<div class="input-area">
<label for="editdate-input">Действие до*</label>
<input type="date" id="edittodate-input" required>
</div>
<div class="input-area">
<label for="editfinaldate-input">Дата решения</label>
<input type="date" id="editfinaldate-input">
</div>
<div class="input-area">
<label for="editdecision-input">Решение</label>
<input type="text" id="editdecision-input">
</div>
<div style="display: none;" class="inputs" id="car-inputs">
<ul id="carlist"></ul>
<input type="text" id="editcarnumber-input" hidden>
<input type="text" id="editcarbrand-input" hidden>
<input type="text" id="editcarmodel-input" hidden>
<input type="text" id="editcarcolor-input" hidden>
</div>
<div style="display: none;" class="inputs" id="tmc-inputs">
<ul id="tmclist"></ul>
<input type="text" id="edittmcname-input" hidden>
<input type="text" id="edittmcunit-input" hidden>
<input type="text" id="edittmcquantity-input" hidden>
</div>
<div class="input-area">
<label for="editadditional-input">Дополнительно</label>
<textarea id="editadditional-input"></textarea>
</div>
<button type="button" class="bright" id="makePass-button">Создать пропуск из заявки</button>
<div class="user-buttons" style="display: flex; justify-content: space-between;">
<button style="width: 49.5%;" type="submit" id="editApplication-button">Сохранить изменения</button>
<button style="width: 49.5%;" type="button" id="deleteApplication-button" class="delete">Удалить заявку</button>
</div>
</div>
</div>
</form>
<script>
var pageNumberInput = document.getElementById('page-number');
var totalMax = Math.ceil({{Total}} / 15);
function decrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > 1) {
pageNumberInput.textContent = currentPage - 1;
requestUpdate();
} else {
requestUpdate();
}
}
function incrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage === totalMax || currentPage > totalMax) {
pageNumberInput.textContent = totalMax;
requestUpdate();
}
if (currentPage < totalMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
}
</script>
<script>
function closeForm() {
$('.form-popup-bg').removeClass('is-visible');
}
$(document).ready(function($) {
$('#addUser').on('click', function(event) {
event.preventDefault();
$('#adduser-form-popup-bg').addClass('is-visible');
});
$('#editapplication-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#editapplication-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
});
document.addEventListener("DOMContentLoaded", function() {
const editApplicationForm = document.getElementById("editApplicationForm");
editApplicationForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#editApplication-button').addClass('inactive');
const id = $('#editapplicationid-input').val();
const status = $('#editstatus-input').val();
const name = $('#editname-input').val();
const legal = $('#editlegal-input').val();
const date = $('#editdate-input').val();
const finaldate = $('#editfinaldate-input').val();
const decision = $('#editdecision-input').val();
const carnumber = $('#editcarnumber-input').val();
const carbrand = $('#editcarbrand-input').val();
const carmodel = $('#editcarmodel-input').val();
const carcolor = $('#editcarcolor-input').val();
const tmcname = $('#edittmcname-input').val();
const tmcunit = $('#edittmcunit-input').val();
const tmcquantity = $('#edittmcquantity-input').val();
const additional = $('#editadditional-input').val();
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/forms/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ id, status, name, legal, date, finaldate, decision, carnumber, carbrand, carmodel, carcolor, tmcname, tmcunit, tmcquantity, additional })
});
if (response.status === 201) {
location.reload();
$('#editApplication-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#editApplication-button').removeClass('inactive');
}
});
});
function openApplication(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/forms/application?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editapplication-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#editapplicationid-input").val(id);
$("#editApplication").html(data.data.Вид_заявки);
$("#deleteApplication-button").attr("onclick", `deleteApplication(${id})`);
$("#makePass-button").attr("onclick", `makePass(${id})`);
if (data.data.Вид_заявки === "Временный") {
$("#car-inputs").css("display", "none");
$("#tmc-inputs").css("display", "none");
} else if (data.data.Вид_заявки === "Автомобильный") {
$("#car-inputs").css("display", "flex");
$("#tmc-inputs").css("display", "none");
} else if (data.data.Вид_заявки === "ТМЦ") {
$("#car-inputs").css("display", "none");
$("#tmc-inputs").css("display", "flex");
}
$("#editauthor-input").val(data.data.Автор);
$("#editname-input").val(data.data.Работник);
$("#editlegal-input").val(data.data.Организация);
$("#editstatus-input").val(data.data.Статус);
$("#editdecision-input").val(data.data.Решение);
$("#editcarnumber-input").val(data.data.Авто_госомер);
$("#editcarbrand-input").val(data.data.Автоарка);
$("#editcarmodel-input").val(data.data.Автоодель);
$("#editcarcolor-input").val(data.data.Авто_цвет);
$("#edittmcname-input").val(data.data.Наименование);
$("#edittmcunit-input").val(data.data.Единица_измерения);
$("#edittmcquantity-input").val(data.data.Количество);
if (data.data.Вид_заявки === "ТМЦ") {
var tmcnames = JSON.parse(data.data.Наименование);
var tmcunits = JSON.parse(data.data.Единица_измерения);
var tmcquantitys = JSON.parse(data.data.Количество);
var tmclist = "";
for (var i = 0; i < tmcnames.length; i++) {
tmclist += "<li><span style='font-weight: 600;'>Позиция " + (i + 1) + ":</span> <br>" +
"Наименование ТМЦ - " + tmcnames[i] + "<br>" +
"Единица измерения - " + tmcunits[i] + "<br>" +
"Количество - " + tmcquantitys[i] +
"</li>";
}
$("#tmclist").html(tmclist);
}
if (data.data.Вид_заявки === "Автомобильный") {
var carnumbers = JSON.parse(data.data.Авто_госомер);
var carbrands = JSON.parse(data.data.Автоарка);
var carmodels = JSON.parse(data.data.Автоодель);
var carcolors = JSON.parse(data.data.Авто_цвет);
var carlist = "";
for (var i = 0; i < carnumbers.length; i++) {
carlist += "<li><span style='font-weight: 600;'>Авто " + (i + 1) + ":</span> <br>" +
"Номер - " + carnumbers[i] + "<br>" +
"Марка - " + carbrands[i] + "<br>" +
"Модель - " + carmodels[i] + "<br>" +
"Цвет - " + carcolors[i] +
"</li>";
}
$("#carlist").html(carlist);
}
$("#editadditional-input").val(data.data.Дополнение);
$("#editapplicationtype-input").val(data.data.Вид_заявки);
function formatDateForDateInput(dateString, inputId) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
document.getElementById(inputId).value = formattedDate;
}
formatDateForDateInput(data.data.Датааявки, "editdate-input");
if (data.data.Дата_решения) {
formatDateForDateInput(data.data.Дата_решения, "editfinaldate-input");
} else {
$("#editfinaldate-input").val("");
}
$("#edittodate-input").val("");
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
async function makePass(id) {
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
};
$('#makePass-button').addClass('inactive');
const status = $('#editstatus-input').val();
const name = $('#editname-input').val();
const legal = $('#editlegal-input').val();
const date = $('#editdate-input').val();
const todate = $('#edittodate-input').val();
const finaldate = $('#editfinaldate-input').val();
const decision = $('#editdecision-input').val();
const carnumber = $('#editcarnumber-input').val();
const carbrand = $('#editcarbrand-input').val();
const carmodel = $('#editcarmodel-input').val();
const carcolor = $('#editcarcolor-input').val();
const tmcname = $('#edittmcname-input').val();
const tmcunit = $('#edittmcunit-input').val();
const tmcquantity = $('#edittmcquantity-input').val();
const additional = $('#editadditional-input').val();
const type = $('#editapplicationtype-input').val();
if (!todate || !date || !name ) {
alert("Пожалуйста, заполните все поля со звездочками.")
$('#makePass-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/forms/makepass", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ id, status, name, legal, date, todate, finaldate, decision, carnumber, carbrand, carmodel, carcolor, tmcname, tmcunit, tmcquantity, additional, type })
});
if (response.status === 201) {
alert("Заявка успешно преобразована в пропуск!")
location.reload();
$('#makePass-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#makePass-button').removeClass('inactive');
}
}
function deleteApplication(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/forms/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editapplication-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editcontactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
</body>
</html>

View File

@ -0,0 +1,350 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Заявка на пропуск</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<a href="/account"><h1>Бюро пропусков / Личный кабинет</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<form class="main-form" id="pass-form">
<h1>Новая заявка на пропуск</h1>
<div class="radio-inputs">
<label class="radio">
<input autocomplete="off" type="radio" id="temp-radio" name="form-type" value="temp" checked>
<span class="name">Временный пропуск</span>
</label>
<label class="radio">
<input autocomplete="off" type="radio" id="car-radio" name="form-type" value="car">
<span class="name">Автомобильный пропуск</span>
</label>
<label class="radio">
<input autocomplete="off" type="radio" id="tmc-radio" name="form-type" value="tmc">
<span class="name">Ввоз-Вывоз ТМЦ</span>
</label>
</div>
<div class="input-area" id="fullname-container">
<label>ФИО*</label>
<div class="fullname-input-group">
<input type="text" class="fullname-input" value="{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}" required>
<button type="button" class="add-fullname">+</button>
</div>
</div>
<div class="input-area">
<label for="legalname-input">Наименование организации</label>
<input type="text" id="legalname-input" value="{{User.Наименование}}">
</div>
<div class="input-area">
<label for="date-input">Дата посещения*</label>
<input type="date" id="date-input" required>
</div>
<div style="display: none;" class="inputs" id="car-inputs">
<div class="car-input-group" data-index="1">
<label>Номер автомобиля</label>
<input type="text" class="carnumber-input">
<label>Марка автомобиля</label>
<input type="text" class="carbrand-input">
<label>Модель автомобиля</label>
<input type="text" class="carmodel-input">
<label>Цвет автомобиля</label>
<input type="text" class="carcolor-input">
<button type="button" class="add-car">Добавить ещё автомобиль</button>
</div>
</div>
<div style="display: none;" class="inputs" id="tmc-inputs">
<div class="tmc-input-group" data-index="1">
<label>Наименование ТМЦ</label>
<input type="text" class="tmcname-input">
<label>Единица измерения</label>
<input type="text" class="tmcunit-input">
<label>Количество</label>
<input type="text" class="tmcquantity-input">
<button type="button" class="add-tmc">Добавить ещё ТМЦ</button>
</div>
</div>
<div class="input-area">
<label for="text-input">Текст заявки</label>
<textarea id="text-input" cols="30" rows="10"></textarea>
</div>
<div class="form-info">
<p>В тексте формы указывайе всю информацию, которая может быть полезна при оформлении пропусков. Например, ФИО или номер автомобиля.</p>
</div>
<button style="margin-top: 15px;" type="submit" id="send-button">Оставить заявку</button>
</form>
<script>
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
document.addEventListener("DOMContentLoaded", function() {
const passForm = document.getElementById("pass-form");
const carInputsContainer = document.getElementById("car-inputs");
let carIndex = 1;
function addCarInput() {
carIndex++;
const inputGroup = document.createElement("div");
inputGroup.classList.add("car-input-group");
inputGroup.setAttribute("data-index", carIndex);
inputGroup.innerHTML = `
<label>Номер автомобиля</label>
<input type="text" class="carnumber-input" required>
<label>Марка автомобиля</label>
<input type="text" class="carbrand-input" required>
<label>Модель автомобиля</label>
<input type="text" class="carmodel-input" required>
<label>Цвет автомобиля</label>
<input type="text" class="carcolor-input" required>
<button type="button" class="remove-car bright">Удалить этот автомобиль</button>
`;
carInputsContainer.appendChild(inputGroup);
inputGroup.querySelector(".remove-car").addEventListener("click", function() {
inputGroup.remove();
});
}
carInputsContainer.addEventListener("click", function(e) {
if (e.target.classList.contains("add-car")) {
addCarInput();
}
});
const tmcInputsContainer = document.getElementById("tmc-inputs");
let tmcIndex = 1;
function addTmcInput() {
tmcIndex++;
const inputGroup = document.createElement("div");
inputGroup.classList.add("tmc-input-group");
inputGroup.setAttribute("data-index", tmcIndex);
inputGroup.innerHTML = `
<label>Наименование ТМЦ</label>
<input type="text" class="tmcname-input" required>
<label>Единица измерения</label>
<input type="text" class="tmcunit-input" required>
<label>Количество</label>
<input type="text" class="tmcquantity-input" required>
<button type="button" class="remove-tmc bright">Удалить это ТМЦ</button>
`;
tmcInputsContainer.appendChild(inputGroup);
inputGroup.querySelector(".remove-tmc").addEventListener("click", function() {
inputGroup.remove();
});
}
tmcInputsContainer.addEventListener("click", function(e) {
if (e.target.classList.contains("add-tmc")) {
addTmcInput();
}
});
const fullnameContainer = document.getElementById("fullname-container");
function addFullnameInput() {
const inputGroup = document.createElement("div");
inputGroup.classList.add("fullname-input-group");
inputGroup.innerHTML = `
<input type="text" class="fullname-input" required>
<button type="button" class="remove-fullname bright">-</button>
`;
inputGroup.querySelector(".remove-fullname").addEventListener("click", function() {
inputGroup.remove();
});
fullnameContainer.appendChild(inputGroup);
}
fullnameContainer.addEventListener("click", function(e) {
if (e.target.classList.contains("add-fullname")) {
addFullnameInput();
}
});
passForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#send-button').addClass('inactive');
const formrole = '{{Role}}'
const passtext = $('#text-input').val();
const fullnames = Array.from(document.querySelectorAll(".fullname-input")).map(input => input.value);
const legalname = $('#legalname-input').val();
const date = $('#date-input').val();
var type;
if (document.getElementById('temp-radio').checked) {
type = "Временный";
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newform", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ formrole, passtext, type, fullnames, legalname, date })
});
if (response.status === 201) {
const data = await response.json();
alert("Ваша заявка принята к рассмотрению!")
window.location.href = "/";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
if (document.getElementById('car-radio').checked) {
type = "Автомобильный";
const carnumber = Array.from(document.querySelectorAll(".carnumber-input")).map(input => input.value);
const carbrand = Array.from(document.querySelectorAll(".carbrand-input")).map(input => input.value);
const carmodel = Array.from(document.querySelectorAll(".carmodel-input")).map(input => input.value);
const carcolor = Array.from(document.querySelectorAll(".carcolor-input")).map(input => input.value);
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newform", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ formrole, passtext, type, fullnames, legalname, date, carnumber, carbrand, carmodel, carcolor })
});
if (response.status === 201) {
const data = await response.json();
alert("Ваша заявка принята к рассмотрению!")
window.location.href = "/";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
if (document.getElementById('tmc-radio').checked) {
type = "ТМЦ";
const tmcname = Array.from(document.querySelectorAll(".tmcname-input")).map(input => input.value);
const tmcunit = Array.from(document.querySelectorAll(".tmcunit-input")).map(input => input.value);
const tmcquantity = Array.from(document.querySelectorAll(".tmcquantity-input")).map(input => input.value);
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newform", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ formrole, passtext, type, fullnames, legalname, date, tmcname, tmcunit, tmcquantity })
});
if (response.status === 201) {
const data = await response.json();
alert("Ваша заявка принята к рассмотрению!")
window.location.href = "/";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
});
});
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
<script>
const radioInputs = document.querySelectorAll('input[name="form-type"]');
const carInputs = document.getElementById('car-inputs');
const tmcInputs = document.getElementById('tmc-inputs');
radioInputs.forEach(input => {
input.addEventListener('change', function() {
if (this.checked) {
if (this.value === "car") {
carInputs.style.display = 'flex';
tmcInputs.style.display = 'none';
} else if (this.value === "tmc") {
carInputs.style.display = 'none';
tmcInputs.style.display = 'flex';
} else if (this.value === "temp") {
carInputs.style.display = 'none';
tmcInputs.style.display = 'none';
}
}
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Заявка на пропуск</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<a href="/account"><h1>Бюро пропусков / Личный кабинет</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<form class="main-form" id="pass-form">
<h1>Новая заявка ТСО</h1>
<div class="input-area">
<label for="fullname-input">ФИО*</label>
<input type="text" id="fullname-input" value="{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}" required>
</div>
<div class="input-area">
<label for="type-input">Вид неисправности*</label>
<textarea id="type-input" cols="30" rows="10"></textarea>
</div>
<div class="input-area">
<label for="object-input">Объект*</label>
<input type="text" id="object-input" required>
</div>
<div class="input-area">
<label for="fabula-input">Фабула</label>
<input type="text" id="fabula-input">
</div>
<div class="form-info">
<p>В тексте формы указывайе всю информацию, которая может быть полезна при решении проблемы.</p>
</div>
<button style="margin-top: 15px;" type="submit" id="send-button">Оставить заявку</button>
</form>
<script>
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
document.addEventListener("DOMContentLoaded", function() {
const passForm = document.getElementById("pass-form");
passForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#send-button').addClass('inactive');
const type = $('#type-input').val();
const object = $('#object-input').val();
const fabula = $('#fabula-input').val();
const fullname = $('#fullname-input').val();
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newtso", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ type, object, fabula, fullname })
});
if (response.status === 201) {
const data = await response.json();
alert("Ваша заявка принята к рассмотрению!")
window.location.href = "/";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,825 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Управление пользователями</title>
<script>
const API_SERVER = "{{API_SERVER}}";
let passes = [
{{#each Passes}}
{
id: {{this.id}},
status: "{{this.Состояние}}",
date: "{{this.Дата_выдачи}}",
finaldate: "{{this.Действиео}}",
type: "{{this.Вид_пропуска}}",
name: "{{this.Работник}}",
legal: "{{this.Организация}}",
address: "{{this.Зонаоступа}}",
car: "{{this.Авто_госомер}}",
tmcname: "{{this.Наименование}}",
},
{{/each}}
];
</script>
<script src="../scripts/passes-table.js"></script>
</head>
<body>
<header>
<a href="/account"><h1>Система управления заявками на пропуска</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/account">Профиль</a>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<nav class="underheader-buttons">
<button id="addPass" class="blue">Создать пропуск</button>
<input id="table-search" type="text" placeholder="Поиск...">
<button onclick="requestUpdate();">Найти</button>
<button onclick="requestUpdate();"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" fill="none" viewBox="0 0 16 20">
<path fill="#6B7A99" d="M8 4V0L3 5l5 5V6c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H0c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8Z"/>
</svg>
</button>
</nav>
<div id="passesWrapper" class="table-wrapper">
<table id="passesTable">
<thead>
<tr>
<th>ID</th>
<th>Состояние</th>
<th>Дата выдачи</th>
<th>Вид</th>
<th>ФИО</th>
<th>Организация</th>
<th>Действие до</th>
<th>Адрес</th>
<th>Автомобиль</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div id="pagination">
<div id="left-slider" onclick="decrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M0 9.495c0 .273.101.514.315.722l8.92 8.477a.981.981 0 0 0 .73.295c.585 0 1.035-.427 1.035-.995 0-.285-.124-.525-.304-.711L2.508 9.495l8.188-7.789c.18-.186.304-.437.304-.71C11 .425 10.55 0 9.965 0c-.292 0-.54.098-.73.284L.314 8.773A.955.955 0 0 0 0 9.495Z"/>
</svg>
</div>
<div id="page-number">1</div>
<div id="right-slider" onclick="incrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M11 9.495a.967.967 0 0 0-.326-.722L1.766.284A1.062 1.062 0 0 0 1.024 0C.45 0 0 .427 0 .995c0 .274.112.525.292.711l8.189 7.789-8.189 7.788c-.18.186-.292.426-.292.71 0 .57.45.996 1.024.996.292 0 .54-.098.742-.295l8.908-8.477c.213-.208.326-.449.326-.722Z"/>
</svg>
</div>
</div>
<form id="newPassForm">
<div id="addpass-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Новый пропуск (создание)</h1>
<br>
<div class="input-area">
<label for="newPassType">Вид пропуска*</label>
<select name="pass-type" id="newPassType">
<option value="Временный">Временный пропуск</option>
<option value="Автомобильный">Автомобильный пропуск</option>
<option value="ТМЦ">Ввоз-Вывоз ТМЦ</option>
<option value="Материальный">Материальный</option>
</select>
</div>
<div class="input-area">
<label for="newPassStatus">Состояние*</label>
<select name="user-type" id="newPassStatus">
<option value="Заказан">Заказан</option>
<option value="Отменен">Отменен</option>
<option value="Отмечен">Отмечен</option>
<option value="Отложен">Отложен</option>
<option value="Постоянный">Постоянный</option>
</select>
</div>
<h2>ФИО</h2>
<div class="three-inputs">
<input type="text" id="surname-input" placeholder="Фамилия">
<input type="text" id="firstname-input" placeholder="Иван">
<input type="text" id="secondname-input" placeholder="Отчество (при наличии)">
</div>
<h2>Срок действия</h2>
<div class="input-area">
<label for="date-input">Дата выдачи*</label>
<input type="date" id="date-input">
</div>
<div class="input-area">
<label for="todate-input">Действие до*</label>
<input type="date" id="todate-input">
</div>
<h2>Контактная информация посетителя</h2>
<div class="two-inputs">
<input type="text" id="phone-input" placeholder="Номер телефона посетителя">
<input type="text" id="email-input" placeholder="Email">
<input type="text" id="legal-input" placeholder="Организация">
</div>
<h2>Детали</h2>
<div class="input-area">
<input type="text" id="purpose-input" placeholder="Цель выдачи">
</div>
<div class="input-area">
<input type="text" id="address-input" placeholder="Территория посещения">
</div>
<div class="input-area">
<textarea id="additional-input" cols="30" rows="10" placeholder="Дополнительно"></textarea>
</div>
<div style="display: none;" class="inputs" id="car-inputs">
<h2>Информация о автомобилях</h2>
<div class="car-input-group" data-index="1">
<label>Номер автомобиля</label>
<input type="text" class="carnumber-input">
<label>Марка автомобиля</label>
<input type="text" class="carbrand-input">
<label>Модель автомобиля</label>
<input type="text" class="carmodel-input">
<label>Цвет автомобиля</label>
<input type="text" class="carcolor-input">
<button type="button" class="add-car bright">Добавить ещё автомобиль</button>
</div>
</div>
<div style="display: none;" class="inputs" id="tmc-inputs">
<h2>Информация о ТМЦ</h2>
<div class="tmc-input-group" data-index="1">
<label>Наименование ТМЦ</label>
<input type="text" class="tmcname-input">
<label>Единица измерения</label>
<input type="text" class="tmcunit-input">
<label>Количество</label>
<input type="text" class="tmcquantity-input">
<button type="button" class="add-tmc bright">Добавить ещё ТМЦ</button>
</div>
</div>
<button type="submit" id="addPass-button">Добавить пропуск</button>
</div>
</div>
</form>
<form id="editPassForm">
<input type="text" id="editpassid-input" hidden>
<input type="text" id="editpasstype-input" hidden>
<div id="editpass-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1><span id="editPass"></span> пропуск</h1>
<br>
<div class="input-area">
<label for="passStatus">Состояние*</label>
<select name="user-type" id="passStatus">
<option value="Заказан">Заказан</option>
<option value="Отменен">Отменен</option>
<option value="Отмечен">Отмечен</option>
<option value="Отложен">Отложен</option>
<option value="Постоянный">Постоянный</option>
</select>
</div>
<div class="input-area">
<label for="editname-input">ФИО*</label>
<input type="text" id="editname-input">
</div>
<h2>Срок действия</h2>
<div class="input-area">
<label for="date-input">Дата выдачи*</label>
<input type="date" id="editdate-input">
</div>
<div class="input-area">
<label for="todate-input">Действие до*</label>
<input type="date" id="edittodate-input">
</div>
<h2>Контактная информация посетителя</h2>
<div class="two-inputs">
<input type="text" id="editphone-input" placeholder="Номер телефона посетителя">
<input type="text" id="editemail-input" placeholder="Email">
<input type="text" id="editlegal-input" placeholder="Организация">
</div>
<h2>Детали</h2>
<div class="input-area">
<input type="text" id="editpurpose-input" placeholder="Цель выдачи">
</div>
<div class="input-area">
<input type="text" id="editaddress-input" placeholder="Территория посещения">
</div>
<div class="input-area">
<textarea id="editadditional-input" cols="30" rows="10" placeholder="Дополнительно"></textarea>
</div>
<div style="display: none;" class="inputs" id="editcar-inputs">
<h2>Информация о автомобилях</h2>
<ul id="carlist"></ul>
<input type="text" id="editcarnumber-input" hidden>
<input type="text" id="editcarbrand-input" hidden>
<input type="text" id="editcarmodel-input" hidden>
<input type="text" id="editcarcolor-input" hidden>
</div>
<div style="display: none;" class="inputs" id="edittmc-inputs">
<h2>Информация о ТМЦ</h2>
<ul id="tmclist"></ul>
<input type="text" id="edittmcname-input" hidden>
<input type="text" id="edittmcunit-input" hidden>
<input type="text" id="edittmcquantity-input" hidden>
</div>
<div class="user-buttons" style="display: flex; justify-content: space-between;">
<button style="width: 49.5%;" type="submit" id="editPass-button">Сохранить изменения</button>
<button style="width: 49.5%;" type="button" id="deletePass-button" class="delete">Удалить пропуск</button>
</div>
</div>
</div>
</form>
<script>
var pageNumberInput = document.getElementById('page-number');
var totalMax = Math.ceil({{Total}} / 15);
function decrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > 1) {
pageNumberInput.textContent = currentPage - 1;
requestUpdate();
} else {
requestUpdate();
}
}
function incrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage === totalMax || currentPage > totalMax) {
pageNumberInput.textContent = totalMax;
requestUpdate();
}
if (currentPage < totalMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
}
</script>
<script>
function closeForm() {
$('.form-popup-bg').removeClass('is-visible');
}
$(document).ready(function($) {
const carInputsContainer = document.getElementById("car-inputs");
let carIndex = 1;
function addCarInput() {
carIndex++;
const inputGroup = document.createElement("div");
inputGroup.classList.add("car-input-group");
inputGroup.setAttribute("data-index", carIndex);
inputGroup.innerHTML = `
<label>Номер автомобиля</label>
<input type="text" class="carnumber-input" required>
<label>Марка автомобиля</label>
<input type="text" class="carbrand-input" required>
<label>Модель автомобиля</label>
<input type="text" class="carmodel-input" required>
<label>Цвет автомобиля</label>
<input type="text" class="carcolor-input" required>
<button type="button" class="remove-car delete">Удалить этот автомобиль</button>
`;
carInputsContainer.appendChild(inputGroup);
inputGroup.querySelector(".remove-car").addEventListener("click", function() {
inputGroup.remove();
});
}
carInputsContainer.addEventListener("click", function(e) {
if (e.target.classList.contains("add-car")) {
addCarInput();
}
});
const tmcInputsContainer = document.getElementById("tmc-inputs");
let tmcIndex = 1; // Индекс для управления уникальностью блоков ТМЦ
function addTmcInput() {
tmcIndex++; // Увеличиваем индекс для следующего блока
const inputGroup = document.createElement("div");
inputGroup.classList.add("tmc-input-group");
inputGroup.setAttribute("data-index", tmcIndex);
inputGroup.innerHTML = `
<label>Наименование ТМЦ</label>
<input type="text" class="tmcname-input" required>
<label>Единица измерения</label>
<input type="text" class="tmcunit-input" required>
<label>Количество</label>
<input type="text" class="tmcquantity-input" required>
<button type="button" class="remove-tmc delete">Удалить это ТМЦ</button>
`;
tmcInputsContainer.appendChild(inputGroup);
// Добавляем обработчик для кнопки удаления
inputGroup.querySelector(".remove-tmc").addEventListener("click", function() {
inputGroup.remove();
});
}
// Обработчик для кнопки добавления ТМЦ
tmcInputsContainer.addEventListener("click", function(e) {
if (e.target.classList.contains("add-tmc")) {
addTmcInput();
}
});
$('#addPass').on('click', function(event) {
event.preventDefault();
$('#addpass-form-popup-bg').addClass('is-visible');
});
$('#addpass-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#addpass-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
$('#editpass-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#editpass-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
});
const typeSelect = document.getElementById('newPassType');
const carInputs = document.getElementById('car-inputs');
const tmcInputs = document.getElementById('tmc-inputs');
typeSelect.addEventListener('change', function() {
if (this.value === "Временный" || this.value === "Материальный") {
carInputs.style.display = 'none';
tmcInputs.style.display = 'none';
} else if (this.value === "Автомобильный") {
carInputs.style.display = 'flex';
tmcInputs.style.display = 'none';
} else if (this.value === "ТМЦ") {
carInputs.style.display = 'none';
tmcInputs.style.display = 'flex';
}
});
document.addEventListener("DOMContentLoaded", function() {
const passForm = document.getElementById("newPassForm");
passForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#send-button').addClass('inactive');
const type = $('#newPassType').val();
const status = $('#newPassStatus').val();
const name = `${$('#surname-input').val()} ${$('#firstname-input').val()} ${$('#secondname-input').val()}`;
const date = $('#date-input').val();
const todate = $('#todate-input').val();
const phone = $('#phone-input').val();
const email = $('#email-input').val();
const legal = $('#legal-input').val();
const purpose = $('#purpose-input').val();
const address = $('#address-input').val();
const additional = $('#additional-input').val();
if ($('#newPassType').val() === "Временный" || $('#newPassType').val() === "Материальный") {
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newpass", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ type, status, name, date, todate, phone, email, legal, purpose, address, additional })
});
if (response.status === 201) {
const data = await response.json();
alert("Пропуск успешно добавлен!")
window.location.href = "/passes";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
if ($('#newPassType').val() === "Автомобильный") {
const carnumber = Array.from(document.querySelectorAll(".carnumber-input")).map(input => input.value);
const carbrand = Array.from(document.querySelectorAll(".carbrand-input")).map(input => input.value);
const carmodel = Array.from(document.querySelectorAll(".carmodel-input")).map(input => input.value);
const carcolor = Array.from(document.querySelectorAll(".carcolor-input")).map(input => input.value);
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newpass", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ type, status, name, date, todate, phone, email, legal, purpose, address, additional, carnumber, carbrand, carmodel, carcolor })
});
if (response.status === 201) {
const data = await response.json();
alert("Пропуск успешно добавлен!")
window.location.href = "/passes";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
if ($('#newPassType').val() === "ТМЦ") {
const tmcname = Array.from(document.querySelectorAll(".tmcname-input")).map(input => input.value);
const tmcunit = Array.from(document.querySelectorAll(".tmcunit-input")).map(input => input.value);
const tmcquantity = Array.from(document.querySelectorAll(".tmcquantity-input")).map(input => input.value);
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/newpass", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ type, status, name, date, todate, phone, email, legal, purpose, address, additional, tmcname, tmcunit, tmcquantity })
});
if (response.status === 201) {
const data = await response.json();
alert("Пропуск успешно добавлен!")
window.location.href = "/passes";
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
});
const editPassForm = document.getElementById("editPassForm");
editPassForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#send-button').addClass('inactive');
const id = parseInt($('#editpassid-input').val());
const type = $('#editpasstype-input').val();
const status = $('#passStatus').val();
const name = $('#editname-input').val();
const date = $('#editdate-input').val();
const todate = $('#edittodate-input').val();
const phone = $('#editphone-input').val();
const email = $('#editemail-input').val();
const legal = $('#editlegal-input').val();
const purpose = $('#editpurpose-input').val();
const address = $('#editaddress-input').val();
const additional = $('#editadditional-input').val();
if ($('#editpasstype-input').val() === "Временный" || $('#editpasstype-input').val() === "Материальный") {
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ id, type, status, name, date, todate, phone, email, legal, purpose, address, additional })
});
if (response.status === 200) {
const data = await response.json();
location.reload();
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
if ($('#editpasstype-input').val() === "Автомобильный") {
const factsValues = $('.car-fact').map(function() {
return $(this).prop('checked');
}).toArray();
const carnumber = $('#editcarnumber-input').val();
const carbrand = $('#editcarbrand-input').val();
const carmodel = $('#editcarmodel-input').val();
const carcolor = $('#editcarcolor-input').val();
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ id, type, status, name, date, todate, phone, email, legal, purpose, address, additional, carnumber, carbrand, carmodel, carcolor, factsValues })
});
if (response.status === 200) {
const data = await response.json();
location.reload();
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
if ($('#editpasstype-input').val() === "ТМЦ") {
const factsValues = $('.tmc-fact').map(function() {
return $(this).val();
}).toArray();
const tmcname = $('#edittmcname-input').val();
const tmcunit = $('#edittmcunit-input').val();
const tmcquantity = $('#edittmcquantity-input').val();
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ id, type, status, name, date, todate, phone, email, legal, purpose, address, additional, tmcname, tmcunit, tmcquantity, factsValues })
});
if (response.status === 200) {
const data = await response.json();
location.reload();
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
}
});
});
function openPass(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/passes/pass?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editpass-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#editpassid-input").val(id);
$("#editpasstype-input").val(data.data.Вид_пропуска);
$("#editPass").html(data.data.Вид_пропуска);
$("#deletePass-button").attr("onclick", `deletePass(${id})`);
if (data.data.Вид_пропуска === "Временный" || data.data.Вид_пропуска === "Материальный") {
$("#editcar-inputs").css("display", "none");
$("#edittmc-inputs").css("display", "none");
} else if (data.data.Вид_пропуска === "Автомобильный") {
$("#editcar-inputs").css("display", "flex");
$("#edittmc-inputs").css("display", "none");
} else if (data.data.Вид_пропуска === "ТМЦ") {
$("#editcar-inputs").css("display", "none");
$("#edittmc-inputs").css("display", "flex");
}
$("#passStatus").val(data.data.Состояние);
$("#editname-input").val(data.data.Работник);
$("#editlegal-input").val(data.data.Организация);
$("#editphone-input").val(data.data.Телефон);
$("#editemail-input").val(data.data.Email);
$("#editcarnumber-input").val(data.data.Авто_госомер);
$("#editcarbrand-input").val(data.data.Автоарка);
$("#editcarmodel-input").val(data.data.Автоодель);
$("#editcarcolor-input").val(data.data.Авто_цвет);
$("#edittmcname-input").val(data.data.Наименование);
$("#edittmcunit-input").val(data.data.Единица_измерения);
$("#edittmcquantity-input").val(data.data.Количество);
if (data.data.Вид_пропуска === "ТМЦ") {
var tmcnames = JSON.parse(data.data.Наименование);
var tmcunits = JSON.parse(data.data.Единица_измерения);
var tmcquantitys = JSON.parse(data.data.Количество);
var fact = JSON.parse(data.data.Отметка);
if (fact === null) {
fact = new Array(tmcnames.length).fill("");
}
// Создаем пустую строку для хранения HTML наших элементов списка
var tmclist = "";
// Итерируем по одному из массивов (предполагая, что все они имеют одинаковую длину)
for (var i = 0; i < tmcnames.length; i++) {
// Добавляем элемент списка для каждой группы данных, индексируем начиная с 1
tmclist += "<li><span style='font-weight: 600;'>Позиция " + (i + 1) + ":</span> <br>" +
"Наименование ТМЦ - " + tmcnames[i] + "<br>" +
"Единица измерения - " + tmcunits[i] + "<br>" +
"Количество - " + tmcquantitys[i] + "<br>" +
"Фактически - " + '<input class="tmc-fact" value="' + fact[i] + '" type="text">' +
"</li>";
}
// Найти элемент, куда вы хотите добавить этот список, и установить его innerHTML
// Предположим, что у вас есть элемент <ul id="tmclist"></ul> для этой цели
$("#tmclist").html(tmclist);
}
if (data.data.Вид_пропуска === "Автомобильный") {
var carnumbers = JSON.parse(data.data.Авто_госомер);
var carbrands = JSON.parse(data.data.Автоарка);
var carmodels = JSON.parse(data.data.Автоодель);
var carcolors = JSON.parse(data.data.Авто_цвет);
var fact = JSON.parse(data.data.Отметка);
if (fact === null) {
fact = new Array(carnumbers.length).fill(false);
}
var carlist = "";
for (var i = 0; i < carnumbers.length; i++) {
carlist += "<li><span style='font-weight: 600;'>Авто " + (i + 1) + ":</span> <br>" +
"Номер - " + carnumbers[i] + "<br>" +
"Марка - " + carbrands[i] + "<br>" +
"Модель - " + carmodels[i] + "<br>" +
"Цвет - " + carcolors[i] + "<br>" +
"Отметка - " + '<input class="car-fact" type="checkbox"' + (fact[i] ? ' checked' : '') + '>' +
"</li>";
}
$("#carlist").html(carlist);
}
$("#editadditional-input").val(data.data.Дополнительно);
$("#editpurpose-input").val(data.data.Цель_выдачи);
$("#editaddress-input").val(data.data.Зонаоступа);
function formatDateForDateInput(dateString, inputId) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
document.getElementById(inputId).value = formattedDate;
}
formatDateForDateInput(data.data.Дата_выдачи, "editdate-input");
if (data.data.Действиео) {
formatDateForDateInput(data.data.Действиео, "edittodate-input");
} else {
$("#edittodate-input").val("");
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function deletePass(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/passes/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editpass-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editcontactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
</body>
</html>

View File

@ -0,0 +1,912 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Управление пользователями</title>
<script>
const API_SERVER = "{{API_SERVER}}";
let users = [
{{#each People}}
{
id: {{this.id}},
name: "{{this.Имя}}",
surname: "{{this.Фамилия}}",
secondname: "{{this.Отчество}}",
role: "{{this.Должность}}",
sub: "{{this.Субподряд}}",
department: "{{this.Цех}}",
email: "{{this.Email}}",
phone: "{{this.Телефон}}",
},
{{/each}}
];
let legals = [
{{#each Legals}}
{
id: {{this.id}},
name: "{{this.Наименование}}",
inn: "{{this.ИНН}}",
ogrn: "{{this.ОГРН}}",
address: "{{this.Юридический_адрес}}",
realaddress: "{{this.Фактический_адрес}}",
email: "{{this.Email}}",
},
{{/each}}
];
</script>
<script src="../scripts/users-table.js"></script>
</head>
<body>
<header>
<a href="/account"><h1>Система управления пользователями</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/account">Профиль</a>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<nav class="underheader-buttons">
<button id="switchButton" onclick="switchTables();">Юридические лица</button>
<input id="table-search" type="text" placeholder="Поиск...">
<button onclick="requestUpdate();">Найти</button>
<button onclick="requestUpdate();"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" fill="none" viewBox="0 0 16 20">
<path fill="#6B7A99" d="M8 4V0L3 5l5 5V6c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H0c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8Z"/>
</svg>
</button>
</nav>
<div id="usersWrapper" class="table-wrapper">
<table id="usersTable">
<thead>
<tr>
<th>ID</th>
<th>Фамилия</th>
<th>Имя</th>
<th>Отчество</th>
<th>Должность</th>
<th>Номер телефона</th>
<th>Email</th>
<th>Субподряд</th>
<th>Цех</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div style="display: none;" id="legalsWrapper" class="table-wrapper">
<table id="legalsTable">
<thead>
<tr>
<th>ID</th>
<th>Наименование</th>
<th>ИНН</th>
<th>ОГРН</th>
<th>Юридический адрес</th>
<th>Фактический адрес</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div id="pagination">
<div id="left-slider" onclick="decrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M0 9.495c0 .273.101.514.315.722l8.92 8.477a.981.981 0 0 0 .73.295c.585 0 1.035-.427 1.035-.995 0-.285-.124-.525-.304-.711L2.508 9.495l8.188-7.789c.18-.186.304-.437.304-.71C11 .425 10.55 0 9.965 0c-.292 0-.54.098-.73.284L.314 8.773A.955.955 0 0 0 0 9.495Z"/>
</svg>
</div>
<div id="page-number">1</div>
<div id="right-slider" onclick="incrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M11 9.495a.967.967 0 0 0-.326-.722L1.766.284A1.062 1.062 0 0 0 1.024 0C.45 0 0 .427 0 .995c0 .274.112.525.292.711l8.189 7.789-8.189 7.788c-.18.186-.292.426-.292.71 0 .57.45.996 1.024.996.292 0 .54-.098.742-.295l8.908-8.477c.213-.208.326-.449.326-.722Z"/>
</svg>
</div>
</div>
<form id="newUserForm">
<div id="adduser-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Новый пользователь</h1>
<br>
<div class="input-area">
<select name="user-type" id="newUserType" readonly>
<option value="guest">Физическое лицо</option>
<option value="legal">Юридическое лицо</option>
</select>
</div>
<div class="inputs" id="person-inputs">
<div class="input-area">
<label for="surname-input">Фамилия*</label>
<input type="text" id="surname-input" readonly>
</div>
<div class="input-area">
<label for="firstname-input">Имя*</label>
<input type="text" id="firstname-input" readonly>
</div>
<div class="input-area">
<label for="secondname-input">Отчество (при наличии)</label>
<input type="text" id="secondname-input" readonly>
</div>
<div class="input-area">
<label for="born-input">Дата рождения*</label>
<input type="date" id="born-input" readonly>
</div>
<div class="input-area">
<label for="phone-input">Номер телефона</label>
<input type="text" id="phone-input" readonly>
</div>
</div>
<div style="display: none;" class="inputs" id="legal-inputs">
<div class="input-area">
<label for="name-input">Наименование организации*</label>
<input type="text" id="name-input" readonly>
</div>
<div class="input-area">
<label for="inn-input">ИНН*</label>
<input maxlength="10" type="text" id="inn-input" readonly>
</div>
<div class="input-area">
<label for="ogrn-input">ОГРН*</label>
<input maxlength="13" type="text" id="ogrn-input" readonly>
</div>
<div class="input-area">
<label for="legaladdress-input">Юридический адрес*</label>
<input type="text" id="legaladdress-input" readonly>
</div>
<div class="input-area">
<label for="address-input">Фактический адрес*</label>
<input type="text" id="address-input" readonly>
</div>
<div class="input-area">
<label for="contact-input">Имя контактного лица</label>
<input type="text" id="contact-input" readonly>
</div>
<div class="input-area">
<label for="contactphone-input">Номер телефона контактного лица</label>
<input type="text" id="contactphone-input" readonly>
</div>
</div>
<div class="input-area">
<label for="email-input">Email*</label>
<input type="text" id="email-input" required readonly>
</div>
<div class="input-area">
<label for="password-input">Пароль*</label>
<input type="text" id="password-input" new-password required readonly>
</div>
<div class="form-info">
<p>Длина пароля должна быть не менее 8 символов.
Пароль должен состоять из букв латинского алфавита (A-z),
арабских цифр (0-9) и специальных символов ((пробел)!"#$%&amp;()*+,-./:;&lt;=&gt;?@[\]^`{|}~)</p>
</div>
<button type="submit" id="addUser-button">Добавить пользователя</button>
</div>
</div>
</form>
<form id="editUserForm">
<input type="text" id="edituserid-input" hidden>
<div id="edituser-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Пользователь <span id="editFIO"></span></h1>
<br>
<h2>ФИО</h2>
<div class="three-inputs">
<input type="text" id="editsurname-input" placeholder="Фамилия" readonly>
<input type="text" id="editfirstname-input" placeholder="Имя" readonly>
<input type="text" id="editsecondname-input" placeholder="Отчество" readonly>
</div>
<div class="input-area">
<label for="editoldsurname-input">Старая фамилия</label>
<input type="text" id="editoldsurname-input" readonly>
</div>
<div class="input-area">
<label for="editborn-input">Дата рождения*</label>
<input type="date" id="editborn-input" readonly>
</div>
<div class="input-area">
<label for="editphone-input">Номер телефона</label>
<input type="text" id="editphone-input" readonly>
</div>
<div class="input-area">
<label for="editbornplace-input">Место рождения</label>
<input type="text" id="editbornplace-input" readonly>
</div>
<div class="input-area">
<label for="editpassport-input">Серия и номер паспорта</label>
<input type="text" id="editpassport-input" readonly>
</div>
<div class="input-area">
<label for="editcitizenship-input">Гражданство</label>
<input type="text" id="editcitizenship-input" readonly>
</div>
<div class="input-area">
<label for="editregaddress-input">Место регистрации</label>
<input type="text" id="editregaddress-input" readonly>
</div>
<div class="input-area">
<label for="editrealaddress-input">Место жительства</label>
<input type="text" id="editrealaddress-input" readonly>
</div>
<div class="input-area">
<label for="editdms-input">Полис ДМС</label>
<input type="text" id="editdms-input" readonly>
</div>
<div class="input-area">
<label for="user-blocked">Чёрный список</label>
<select name="user-blocked" id="isUserBlocked" readonly>
<option value="false">Нет</option>
<option value="true">Да</option>
</select>
</div>
<div class="input-area">
<label for="editpassword-input">Новый пароль (Опционально)</label>
<input type="password" id="editpassword-input" new-password readonly>
</div>
<div class="worker-inputs" id="workersInputs">
<h2>Информация о работнике</h2>
<div class="two-inputs">
<input type="text" id="editsub-input" placeholder="Субподряд" readonly >
<input type="text" id="editdepartment-input" placeholder="Цех" readonly>
<select id="editrole-input" readonly>
<option value="Работник">Работник</option>
<option value="Дирекция">Дирекция по безопасности</option>
<option value="КПП">Работник КПП</option>
<option value="Пропуска">Управление пропусками</option>
</select>
<select id="editfire-input" readonly>
<option value="false">Не уволен</option>
<option value="true">Уволен</option>
</select>
</div>
<div class="input-area">
<label for="editmigration-input">Миграционная карта</label>
<input type="text" id="editmigration-input" readonly>
</div>
<div class="input-area">
<label for="editpermit-input">Разрешение на работу до</label>
<input type="date" id="editpermit-input" readonly>
</div>
<div class="input-area">
<label for="editcontract-input">Трудовой договор</label>
<input type="text" id="editcontract-input" readonly>
</div>
<div class="input-area">
<label for="editcontractdate-input">Дата договора</label>
<input type="date" id="editcontractdate-input" readonly>
</div>
<div class="input-area">
<label for="editlastjob-input">Последнее место работы</label>
<select id="editlastjob-input" readonly>
<option value="true">Да</option>
<option value="false">Нет</option>
</select>
</div>
<div class="input-area">
<label for="editfirereason-input">Причина увольнения</label>
<textarea id="editfirereason-input" readonly></textarea>
</div>
</div>
</div>
</div>
</form>
<form id="editLegalForm">
<input type="text" id="editlegalid-input" hidden>
<div id="editlegal-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Юр лицо <span id="editLegal"></span></h1>
<br>
<div class="input-area">
<label for="editname-input">Наименование*</label>
<input type="text" id="editname-input" required readonly>
</div>
<div class="input-area">
<label for="editinn-input">ИНН*</label>
<input type="text" id="editinn-input" required readonly>
</div>
<div class="input-area">
<label for="editogrn-input">ОГРН*</label>
<input type="text" id="editogrn-input" required readonly>
</div>
<div class="input-area">
<label for="editlegaladdress-input">Юридический адрес*</label>
<input type="text" id="editlegaladdress-input" required readonly>
</div>
<div class="input-area">
<label for="editaddress-input">Фактический адрес*</label>
<input type="text" id="editaddress-input" required readonly>
</div>
<div class="input-area">
<label for="editcontactphone-input">Номер телефона контактного лица</label>
<input type="text" id="editcontactphone-input" readonly>
</div>
<div class="input-area">
<label for="editcontact-input">Контактное лицо</label>
<input type="text" id="editcontact-input" readonly>
</div>
<div class="input-area">
<label for="editadditional-input">Дополнительно</label>
<textarea id="editadditional-input" readonly></textarea>
</div>
</div>
</div>
</form>
<script>
var tableType = "People";
function switchTables() {
var usersTable = document.getElementById('usersWrapper');
var legalsTable = document.getElementById('legalsWrapper');
var usersButton = document.getElementById('switchButton')
if (tableType === "People") {
usersTable.style.display = 'none';
legalsTable.style.display = 'block';
usersButton.textContent = 'Физические лица';
tableType = "Legals";
} else {
legalsTable.style.display = 'none';
usersTable.style.display = 'block';
usersButton.textContent = 'Юридические лица';
tableType = "People";
}
}
var pageNumberInput = document.getElementById('page-number');
var peopleMax = Math.ceil({{PeopleCount}} / 15);
var legalsMax = Math.ceil({{LegalsCount}} / 15);
function decrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > 1) {
pageNumberInput.textContent = currentPage - 1;
requestUpdate();
} else {
requestUpdate();
}
}
function incrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (tableType === "People") {
if (currentPage === peopleMax || currentPage > peopleMax) {
pageNumberInput.textContent = peopleMax;
requestUpdate();
}
if (currentPage < peopleMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
} else {
if (currentPage === legalsMax || currentPage > legalsMax) {
pageNumberInput.textContent = legalsMax;
requestUpdate();
}
if (currentPage < legalsMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
}
}
</script>
<script>
function closeForm() {
$('.form-popup-bg').removeClass('is-visible');
}
$(document).ready(function($) {
$('#addUser').on('click', function(event) {
event.preventDefault();
$('#adduser-form-popup-bg').addClass('is-visible');
});
$('#adduser-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#adduser-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
$('#edituser-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#edituser-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
$('#editlegal-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#editlegal-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
});
const typeSelect = document.getElementById('newUserType');
const personInputs = document.getElementById('person-inputs');
const legalInputs = document.getElementById('legal-inputs');
typeSelect.addEventListener('change', function() {
if (this.value === "guest") {
personInputs.style.display = 'flex';
legalInputs.style.display = 'none';
} else if (this.value === "legal") {
personInputs.style.display = 'none';
legalInputs.style.display = 'flex';
}
});
document.addEventListener("DOMContentLoaded", function() {
const newUserForm = document.getElementById("newUserForm");
newUserForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#addUser-button').addClass('inactive');
if (document.getElementById('newUserType').value === "guest") {
const formrole = "guest";
const firstname = $('#firstname-input').val();
const surname = $('#surname-input').val();
const secondname = $('#secondname-input').val();
const born = $('#born-input').val();
const phone = $('#phone-input').val();
if (!$('#firstname-input').val() || !$('#surname-input').val() || !$('#born-input').val()) {
alert("Пожалуйста, заполните все поля, помеченные звёздочкой.")
$('#addUser-button').removeClass('inactive');
return;
}
const email = $('#email-input').val();
const password = $('#password-input').val();
if (password.length < 8) {
alert('Длина пароля должна быть не менее 8 символов')
$('#addUser-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ firstname, surname, secondname, born, phone, email, password, formrole })
});
if (response.status === 201) {
location.reload();
$('#addUser-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#addUser-button').removeClass('inactive');
}
} else if (document.getElementById('newUserType').value === "legal") {
const formrole = "legal";
const name = $('#name-input').val();
const inn = $('#inn-input').val();
const ogrn = $('#ogrn-input').val();
const legaladdress = $('#legaladdress-input').val();
const address = $('#address-input').val();
const phone = $('#contactphone-input').val();
const contact = $('#contact-input').val();
if (!$('#name-input').val() || !$('#inn-input').val() || !$('#ogrn-input').val() || !$('#legaladdress-input').val()) {
alert("Пожалуйста, заполните все поля, помеченные звёздочкой.")
$('#addUser-button').removeClass('inactive');
return;
}
const email = $('#email-input').val();
const password = $('#password-input').val();
if (password.length < 8) {
alert('Длина пароля должна быть не менее 8 символов')
$('#addUser-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name, inn, ogrn, legaladdress, address, phone, email, contact, password, formrole })
});
if (response.status === 201) {
location.reload();
$('#addUser-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#addUser-button').removeClass('inactive');
}
}
});
const editUserForm = document.getElementById("editUserForm");
editUserForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#editUser-button').addClass('inactive');
const id = $('#edituserid-input').val();
const firstname = $('#editfirstname-input').val();
const surname = $('#editsurname-input').val();
const secondname = $('#editsecondname-input').val();
const oldsurname = $('#editoldsurname-input').val();
const born = $('#editborn-input').val();
const phone = $('#editphone-input').val();
const bornplace = $('#editbornplace-input').val();
const passport = $('#editpassport-input').val();
const citizenship = $('#editcitizenship-input').val();
const regaddress = $('#editregaddress-input').val();
const realaddress = $('#editrealaddress-input').val();
const dms = $('#editdms-input').val();
const block = $('#isUserBlocked').val();
const sub = $('#editsub-input').val();
const department = $('#editdepartment-input').val();
const role = $('#editrole-input').val();
const fire = $('#editfire-input').val();
const migration = $('#editmigration-input').val();
const permit = $('#editpermit-input').val();
const contract = $('#editcontract-input').val();
const contractdate = $('#editcontractdate-input').val();
const lastjob = $('#editlastjob-input').val();
const reason = $('#editfirereason-input').val();
const formrole = role;
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/users/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ firstname, surname, secondname, oldsurname, born, phone, bornplace, passport, citizenship, regaddress, realaddress, dms,
block, sub, department, role, fire, migration, permit, contract, contractdate, lastjob, reason, id, formrole })
});
if (response.status === 201) {
location.reload();
$('#editUser-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#editUser-button').removeClass('inactive');
}
});
const editLegalForm = document.getElementById("editLegalForm");
editLegalForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#editLegal-button').addClass('inactive');
const id = $('#editlegalid-input').val();
const name = $('#editname-input').val();
const inn = $('#editinn-input').val();
const ogrn = $('#editogrn-input').val();
const legaladdress = $('#editlegaladdress-input').val();
const address = $('#editaddress-input').val();
const contactphone = $('#editcontactphone-input').val();
const contact = $('#editcontact-input').val();
const additional = $('#editadditional-input').val();
const formrole = "legal";
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/users/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ name, inn, ogrn, legaladdress, address, contactphone, contact, additional, id, formrole })
});
if (response.status === 201) {
location.reload();
$('#editLegal-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#editLegal-button').removeClass('inactive');
}
});
});
function openUser(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/users/getuser?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#edituser-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#edituserid-input").val(id);
$("#editFIO").html(`${data.data.Фамилия} ${data.data.Имя} ${data.data.Отчество}`);
if (data.data.emp_id !== null) {
$("#workersInputs").css("display", "flex");
$("#makeWorker-button").css("display", "none");
} else {
$("#workersInputs").css("display", "none");
$("#makeWorker-button").attr("onclick", `makeWorker(${id})`);
$("#makeWorker-button").css("display", "block");
}
$("#deleteUser-button").attr("onclick", `deleteUser(${id})`);
$("#editsurname-input").val(data.data.Фамилия);
$("#editfirstname-input").val(data.data.Имя);
$("#editsecondname-input").val(data.data.Отчество);
$("#editoldsurname-input").val(data.data.Фамилия_старая);
$("#editphone-input").val(data.data.Телефон);
$("#editbornplace-input").val(data.data.Место_рождения);
$("#editpassport-input").val(data.data.Паспорт);
$("#editcitizenship-input").val(data.data.Гражданство);
$("#editregaddress-input").val(data.data.Место_регистрации);
$("#editrealaddress-input").val(data.data.Место_жительства);
$("#editdms-input").val(data.data.ПолисМС);
if (data.data.Черный_список) {
$("#isUserBlocked").val("true");
} else {
$("#isUserBlocked").val("false");
}
$("#editsub-input").val(data.data.Субподряд);
$("#editdepartment-input").val(data.data.Цех);
$("#editrole-input").val(data.data.Должность);
if (data.data.Увольнение) {
$("#editfire-input").val("true");
} else {
$("#editfire-input").val("false");
}
$("#editmigration-input").val(data.data.Миграционная_карта);
$("#editcontract-input").val(data.data.Трудовой_договор);
if (data.data.Последнееесто_работы) {
$("#editlastjob-input").val("true");
} else {
$("#editlastjob-input").val("false");
}
$("#editfirereason-input").val(data.data.Причина_увольнения);
function formatDateForDateInput(dateString, inputId) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
document.getElementById(inputId).value = formattedDate;
}
formatDateForDateInput(data.data.Дата_рождения, "editborn-input");
formatDateForDateInput(data.data.Разрешениеа_работуо, "editpermit-input");
formatDateForDateInput(data.data.Датаоговора, "editcontractdate-input");
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function makeWorker(id) {
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/users/makeworker?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#edituser-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function deleteUser(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/user/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#edituser-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function deleteLegal(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/legal/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editlegal-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function openLegal(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/legals/getlegal?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editlegal-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#editlegalid-input").val(id);
$("#editLegal").html(`${data.data.Наименование}`);
$("#deleteLegal-button").attr("onclick", `deleteLegal(${id})`);
$("#editname-input").val(data.data.Наименование);
$("#editinn-input").val(data.data.ИНН);
$("#editogrn-input").val(data.data.ОГРН);
$("#editlegaladdress-input").val(data.data.Юридический_адрес);
$("#editaddress-input").val(data.data.Фактический_адрес);
$("#editcontactphone-input").val(data.data.Телефон);
$("#editcontact-input").val(data.data.Контактное_лицо);
$("#editadditional-input").val(data.data.Дополнительно);
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editcontactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
</body>
</html>

View File

@ -0,0 +1,240 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Настройки профиля</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<a href="/account"><h1>Бюро пропусков / Личный кабинет</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<form id="update-form" autocomplete="off">
<section class="main-content">
<h1>Редактирование профиля</h1>
<div class="hub-bg settings-area">
{{#if (eq Role 'legal')}}
<div class="input-area">
<label for="name-input">Наименование организации*</label>
<input type="text" id="name-input" value="{{User.Наименование}}">
</div>
<div class="input-area">
<label for="inn-input">ИНН*</label>
<input maxlength="10" type="text" id="inn-input" value="{{User.ИНН}}" required>
</div>
<div class="input-area">
<label for="ogrn-input">ОГРН*</label>
<input maxlength="13" type="text" id="ogrn-input" value="{{User.ОГРН}}" required>
</div>
<div class="input-area">
<label for="legaladdress-input">Юридический адрес*</label>
<input type="text" id="legaladdress-input" value="{{User.Юридический_адрес}}" required>
</div>
<div class="input-area">
<label for="address-input">Фактический адрес*</label>
<input type="text" id="address-input" value="{{User.Фактический_адрес}}" required>
</div>
<div class="input-area">
<label for="contact-input">Имя контактного лица</label>
<input type="text" id="contact-input" value="{{User.Контактное_лицо}}">
</div>
<div class="input-area">
<label for="contactphone-input">Номер телефона контактного лица</label>
<input type="text" id="contactphone-input" value="{{User.Телефон}}">
</div>
{{else}}
<div class="input-area">
<label for="surname-input">Фамилия*</label>
<input type="text" id="surname-input" value="{{User.Фамилия}}" required>
</div>
<div class="input-area">
<label for="firstname-input">Имя*</label>
<input type="text" id="firstname-input" value="{{User.Имя}}" required>
</div>
<div class="input-area">
<label for="secondname-input">Отчество (при наличии)</label>
<input type="text" id="secondname-input" value="{{User.Отчество}}">
</div>
<div class="input-area">
<label for="born-input">Дата рождения*</label>
<input type="date" id="born-input">
</div>
<div class="input-area">
<label for="phone-input">Номер телефона</label>
<input type="text" id="phone-input" value="{{User.Телефон}}">
</div>
<div class="input-area">
<label for="bornplace-input">Место рождения</label>
<input type="text" id="bornplace-input" value="{{User.Место_рождения}}">
</div>
<div class="input-area">
<label for="passport-input">Серия и номер паспорта</label>
<input type="text" id="passport-input" value="{{User.Паспорт}}">
</div>
<div class="input-area">
<label for="citizenship-input">Гражданство</label>
<input type="text" id="citizenship-input" value="{{User.Гражданство}}">
</div>
<div class="input-area">
<label for="regaddress-input">Место регистрации</label>
<input type="text" id="regaddress-input" value="{{User.Место_регистрации}}">
</div>
<div class="input-area">
<label for="realaddress-input">Место жительства</label>
<input type="text" id="realaddress-input" name="address" autocomplete="off" value="{{User.Место_жительства}}">
</div>
<div class="input-area">
<label for="dms-input">Полис ДМС</label>
<input type="text" id="dms-input" value="{{User.ПолисМС}}">
</div>
{{/if}}
<div class="input-area">
<label for="password-input">Новый пароль (Опционально)</label>
<input type="password" id="password-input" name="new-password" autocomplete="new-password" new-password>
</div>
<button id="update-button">Сохранить</button>
</div>
</section>
</form>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
function formatDateForDateInput(dateString, inputId) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
document.getElementById(inputId).value = formattedDate;
}
formatDateForDateInput("{{User.Дата_рождения}}", "born-input");
});
</script>
<script>
function getCookie(name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return null;
}
document.addEventListener("DOMContentLoaded", function() {
const updateForm = document.getElementById("update-form");
updateForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#update-button').addClass('inactive');
{{#if (eq Role 'legal')}}
const name = $('#name-input').val();
const inn = $('#inn-input').val();
const ogrn = $('#ogrn-input').val();
const legaladdress = $('#legaladdress-input').val();
const address = $('#address-input').val();
const contact = $('#contact-input').val();
const contactphone = $('#contactphone-input').val();
const password = $('#password-input').val();
const response = await fetch("{{API_SERVER}}/account/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ name, inn, ogrn, legaladdress, address, contact, contactphone, password })
});
{{else}}
const surname = $('#surname-input').val();
const firstname = $('#firstname-input').val();
const secondname = $('#secondname-input').val();
const born = $('#born-input').val();
const phone = $('#phone-input').val();
const bornplace = $('#bornplace-input').val();
const passport = $('#passport-input').val();
const citizenship = $('#citizenship-input').val();
const regaddress = $('#regaddress-input').val();
const realaddress = $('#realaddress-input').val();
const dms = $('#dms-input').val();
const password = $('#password-input').val();
const response = await fetch("{{API_SERVER}}/account/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ surname, firstname, secondname, born, phone, bornplace, passport, citizenship, regaddress, realaddress, dms, password })
});
{{/if}}
if (response.status === 201) {
window.location.href = "/account";
$('#update-button').removeClass('inactive');
} else {
alert("Ошибка обновления данных");
$('#update-button').removeClass('inactive');
}
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,326 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Управление заявками ТСО</title>
<script>
const API_SERVER = "{{API_SERVER}}";
let passes = [
{{#each Passes}}
{
id: {{this.id}},
status: "{{this.Состояние}}",
object: "{{this.Объект}}",
fabula: "{{this.Фабула}}",
type: "{{this.Вид_неисправности}}",
date: "{{this.Дата_подачи}}",
editdate: "{{this.Дата_изменения}}",
who: "{{this.Кто_подал}}",
executor: "{{this.Исполнитель}}",
events: "{{this.Мероприятия}}",
},
{{/each}}
];
</script>
<script src="../scripts/tso-table.js"></script>
</head>
<body>
<header>
<a href="/account"><h1>Система управления заявками ТСО</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/account">Профиль</a>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<nav class="underheader-buttons">
<button onclick="location.href='/account/newtso'" class="blue">Создать заявку</button>
<button onclick="requestUpdate();"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" fill="none" viewBox="0 0 16 20">
<path fill="#6B7A99" d="M8 4V0L3 5l5 5V6c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H0c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8Z"/>
</svg>
</button>
</nav>
<div id="passesWrapper" class="table-wrapper">
<table id="passesTable">
<thead>
<tr>
<th>ID</th>
<th>Состояние</th>
<th>Дата подачи</th>
<th>Вид неисправности</th>
<th>Объект</th>
<th>Дата изменения</th>
<th>Исполнитель</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div id="pagination">
<div id="left-slider" onclick="decrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M0 9.495c0 .273.101.514.315.722l8.92 8.477a.981.981 0 0 0 .73.295c.585 0 1.035-.427 1.035-.995 0-.285-.124-.525-.304-.711L2.508 9.495l8.188-7.789c.18-.186.304-.437.304-.71C11 .425 10.55 0 9.965 0c-.292 0-.54.098-.73.284L.314 8.773A.955.955 0 0 0 0 9.495Z"/>
</svg>
</div>
<div id="page-number">1</div>
<div id="right-slider" onclick="incrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M11 9.495a.967.967 0 0 0-.326-.722L1.766.284A1.062 1.062 0 0 0 1.024 0C.45 0 0 .427 0 .995c0 .274.112.525.292.711l8.189 7.789-8.189 7.788c-.18.186-.292.426-.292.71 0 .57.45.996 1.024.996.292 0 .54-.098.742-.295l8.908-8.477c.213-.208.326-.449.326-.722Z"/>
</svg>
</div>
</div>
<form id="editPassForm">
<input type="text" id="editpassid-input" hidden>
<div id="editpass-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Заявка <span id="editPass"></span></h1>
<br>
<div class="input-area">
<label for="passStatus">Состояние*</label>
<select name="pass-type" id="passStatus">
<option value="Новая">Новая</option>
<option value="Принята в работу">Принята в работу</option>
<option value="Выполнена">Выполнена</option>
<option value="Отложена">Отложен</option>
</select>
</div>
<div class="input-area">
<label for="edittype-input">Вид неисправности*</label>
<textarea id="edittype-input" cols="30" rows="10"></textarea>
</div>
<div class="input-area">
<label for="editobject-input">Объект*</label>
<input type="text" id="editobject-input">
</div>
<div class="input-area">
<label for="editfabula-input">Фабула</label>
<input type="text" id="editfabula-input">
</div>
<div class="input-area">
<label for="editexecutor-input">Исполнитель</label>
<input type="text" id="editexecutor-input">
</div>
<div class="input-area">
<label for="editevents-input">Мероприятия</label>
<input type="text" id="editevents-input">
</div>
<div class="user-buttons" style="display: flex; justify-content: space-between;">
<button style="width: 49.5%;" type="submit" id="editPass-button">Сохранить изменения</button>
<button style="width: 49.5%;" type="button" id="deletePass-button" class="delete">Удалить заявку</button>
</div>
</div>
</div>
</form>
<script>
var pageNumberInput = document.getElementById('page-number');
var totalMax = Math.ceil({{Total}} / 15);
function decrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > 1) {
pageNumberInput.textContent = currentPage - 1;
requestUpdate();
} else {
requestUpdate();
}
}
function incrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage === totalMax || currentPage > totalMax) {
pageNumberInput.textContent = totalMax;
requestUpdate();
}
if (currentPage < totalMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
}
</script>
<script>
function closeForm() {
$('.form-popup-bg').removeClass('is-visible');
}
$(document).ready(function($) {
$('#editpass-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#editpass-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
const editPassForm = document.getElementById("editPassForm");
editPassForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#send-button').addClass('inactive');
const id = parseInt($('#editpassid-input').val());
const type = $('#edittype-input').val();
const status = $('#passStatus').val();
const object = $('#editobject-input').val();
const fabula = $('#editfabula-input').val();
const executor = $('#editexecutor-input').val();
const events = $('#editevents-input').val();
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/passes/tso/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ id, type, status, object, fabula, executor, events })
});
if (response.status === 200) {
const data = await response.json();
location.reload();
$('#send-button').removeClass('inactive');
} else {
alert("Произошла ошибка при попытке отправить заявку");
$('#send-button').removeClass('inactive');
}
});
});
function openPass(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/passes/tso?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editpass-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#editpassid-input").val(id);
$("#edittype-input").val(data.data.Вид_неисправности);
$("#editPass").html(id);
$("#deletePass-button").attr("onclick", `deletePass(${id})`);
$("#passStatus").val(data.data.Состояние);
$("#editobject-input").val(data.data.Объект);
$("#editfabula-input").val(data.data.Фабула);
$("#editexecutor-input").val(data.data.Исполнитель);
$("#editevents-input").val(data.data.Мероприятия);
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function deletePass(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/passes/tso/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editpass-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editcontactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
</body>
</html>

View File

@ -0,0 +1,937 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Управление пользователями</title>
<script>
const API_SERVER = "{{API_SERVER}}";
let users = [
{{#each People}}
{
id: {{this.id}},
name: "{{this.Имя}}",
surname: "{{this.Фамилия}}",
secondname: "{{this.Отчество}}",
role: "{{this.Должность}}",
sub: "{{this.Субподряд}}",
department: "{{this.Цех}}",
email: "{{this.Email}}",
phone: "{{this.Телефон}}",
isblocked: "{{this.Черный_список}}",
},
{{/each}}
];
let legals = [
{{#each Legals}}
{
id: {{this.id}},
name: "{{this.Наименование}}",
inn: "{{this.ИНН}}",
ogrn: "{{this.ОГРН}}",
address: "{{this.Юридический_адрес}}",
realaddress: "{{this.Фактический_адрес}}",
email: "{{this.Email}}",
},
{{/each}}
];
</script>
<script src="../scripts/users-table.js"></script>
</head>
<body>
<header>
<a href="/account"><h1>Система управления пользователями</h1></a>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/account">Профиль</a>
{{#if (eq Role 'legal')}}
<span>{{User.Наименование}}</span>
{{else}}
<span>{{User.Фамилия}} {{User.Имя}} {{User.Отчество}}</span>
{{/if}}
<a class="exit-button" href="/logout"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" fill="none" viewBox="0 0 20 16">
<path fill="#6B7A99" d="m4.016 7.13 2.608-2.606-1.226-1.226L.696 8l4.702 4.702 1.226-1.226L4.016 8.87h4.858V7.131H4.016ZM8.874.179v6.953h5.215V8.87H8.874v6.953h10.43V.178H8.873Z"/>
</svg>
</a>
</nav>
</header>
<nav class="underheader-buttons">
<button id="addUser" class="blue">Создать пользователя</button>
<button id="switchButton" onclick="switchTables();">Юридические лица</button>
<input id="table-search" type="text" placeholder="Поиск...">
<button onclick="requestUpdate();">Найти</button>
<button onclick="requestUpdate();"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" fill="none" viewBox="0 0 16 20">
<path fill="#6B7A99" d="M8 4V0L3 5l5 5V6c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H0c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8Z"/>
</svg>
</button>
</nav>
<div id="usersWrapper" class="table-wrapper">
<table id="usersTable">
<thead>
<tr>
<th>ID</th>
<th>Фамилия</th>
<th>Имя</th>
<th>Отчество</th>
<th>Должность</th>
<th>Номер телефона</th>
<th>Email</th>
<th>Субподряд</th>
<th>Цех</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div style="display: none;" id="legalsWrapper" class="table-wrapper">
<table id="legalsTable">
<thead>
<tr>
<th>ID</th>
<th>Наименование</th>
<th>ИНН</th>
<th>ОГРН</th>
<th>Юридический адрес</th>
<th>Фактический адрес</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<!-- Сюда будут добавляться строки таблицы -->
</tbody>
</table>
</div>
<div id="pagination">
<div id="left-slider" onclick="decrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M0 9.495c0 .273.101.514.315.722l8.92 8.477a.981.981 0 0 0 .73.295c.585 0 1.035-.427 1.035-.995 0-.285-.124-.525-.304-.711L2.508 9.495l8.188-7.789c.18-.186.304-.437.304-.71C11 .425 10.55 0 9.965 0c-.292 0-.54.098-.73.284L.314 8.773A.955.955 0 0 0 0 9.495Z"/>
</svg>
</div>
<div id="page-number">1</div>
<div id="right-slider" onclick="incrementPage()">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="19" fill="none" viewBox="0 0 11 19">
<path fill="#000" fill-opacity=".75" d="M11 9.495a.967.967 0 0 0-.326-.722L1.766.284A1.062 1.062 0 0 0 1.024 0C.45 0 0 .427 0 .995c0 .274.112.525.292.711l8.189 7.789-8.189 7.788c-.18.186-.292.426-.292.71 0 .57.45.996 1.024.996.292 0 .54-.098.742-.295l8.908-8.477c.213-.208.326-.449.326-.722Z"/>
</svg>
</div>
</div>
<form id="newUserForm">
<div id="adduser-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Новый пользователь</h1>
<br>
<div class="input-area">
<select name="user-type" id="newUserType">
<option value="guest">Физическое лицо</option>
<option value="legal">Юридическое лицо</option>
</select>
</div>
<div class="inputs" id="person-inputs">
<div class="input-area">
<label for="surname-input">Фамилия*</label>
<input type="text" id="surname-input">
</div>
<div class="input-area">
<label for="firstname-input">Имя*</label>
<input type="text" id="firstname-input">
</div>
<div class="input-area">
<label for="secondname-input">Отчество (при наличии)</label>
<input type="text" id="secondname-input">
</div>
<div class="input-area">
<label for="born-input">Дата рождения*</label>
<input type="date" id="born-input">
</div>
<div class="input-area">
<label for="phone-input">Номер телефона</label>
<input type="text" id="phone-input">
</div>
</div>
<div style="display: none;" class="inputs" id="legal-inputs">
<div class="input-area">
<label for="name-input">Наименование организации*</label>
<input type="text" id="name-input">
</div>
<div class="input-area">
<label for="inn-input">ИНН*</label>
<input maxlength="10" type="text" id="inn-input">
</div>
<div class="input-area">
<label for="ogrn-input">ОГРН*</label>
<input maxlength="13" type="text" id="ogrn-input">
</div>
<div class="input-area">
<label for="legaladdress-input">Юридический адрес*</label>
<input type="text" id="legaladdress-input">
</div>
<div class="input-area">
<label for="address-input">Фактический адрес*</label>
<input type="text" id="address-input">
</div>
<div class="input-area">
<label for="contact-input">Имя контактного лица</label>
<input type="text" id="contact-input">
</div>
<div class="input-area">
<label for="contactphone-input">Номер телефона контактного лица</label>
<input type="text" id="contactphone-input">
</div>
</div>
<div class="input-area">
<label for="email-input">Email*</label>
<input type="text" id="email-input" required>
</div>
<div class="input-area">
<label for="password-input">Пароль*</label>
<input type="text" id="password-input" new-password required>
</div>
<div class="form-info">
<p>Длина пароля должна быть не менее 8 символов.
Пароль должен состоять из букв латинского алфавита (A-z),
арабских цифр (0-9) и специальных символов ((пробел)!"#$%&amp;()*+,-./:;&lt;=&gt;?@[\]^`{|}~)</p>
</div>
<button type="submit" id="addUser-button">Добавить пользователя</button>
</div>
</div>
</form>
<form id="editUserForm">
<input type="text" id="edituserid-input" hidden>
<div id="edituser-form-popup-bg" class="form-popup-bg not-main" >
<div class="blocked-alarm" style="display: none;" id="alarmBlocked">
<svg xmlns="http://www.w3.org/2000/svg" width="55" height="50" fill="none" viewBox="0 0 55 50">
<path fill="red" fill-opacity=".85" d="M7.143 49.712h40.554c4.448 0 7.143-3.087 7.143-7.09 0-1.23-.366-2.512-1.02-3.663L33.516 3.585C32.156 1.204 29.827 0 27.42 0s-4.762 1.204-6.096 3.585L1.02 38.959A7.065 7.065 0 0 0 0 42.622c0 4.003 2.695 7.09 7.143 7.09Zm.026-4.108c-1.831 0-2.93-1.413-2.93-3.008 0-.498.104-1.126.392-1.675L24.908 5.573c.55-.968 1.544-1.387 2.512-1.387s1.936.419 2.486 1.387l20.277 35.374c.288.55.419 1.151.419 1.648 0 1.596-1.151 3.01-2.957 3.01H7.17Z"/>
<path fill="red" fill-opacity=".85" d="M27.42 32.077c1.256 0 1.989-.732 2.015-2.093l.366-13.788c.026-1.335-1.02-2.329-2.407-2.329-1.413 0-2.407.968-2.381 2.302l.34 13.815c.026 1.335.759 2.093 2.067 2.093Zm0 8.504c1.518 0 2.826-1.204 2.826-2.721 0-1.544-1.282-2.721-2.826-2.721s-2.826 1.203-2.826 2.72c0 1.492 1.309 2.722 2.826 2.722Z"/>
</svg>
<h1>Внимание! Пользователь в черном списке.</h1>
</div>
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Пользователь <span id="editFIO"></span></h1>
<br>
<h2>ФИО</h2>
<div class="three-inputs">
<input type="text" id="editsurname-input" placeholder="Фамилия">
<input type="text" id="editfirstname-input" placeholder="Имя">
<input type="text" id="editsecondname-input" placeholder="Отчество">
</div>
<div class="input-area">
<label for="editoldsurname-input">Старая фамилия</label>
<input type="text" id="editoldsurname-input">
</div>
<div class="input-area">
<label for="editborn-input">Дата рождения*</label>
<input type="date" id="editborn-input">
</div>
<div class="input-area">
<label for="editphone-input">Номер телефона</label>
<input type="text" id="editphone-input" >
</div>
<div class="input-area">
<label for="editbornplace-input">Место рождения</label>
<input type="text" id="editbornplace-input" >
</div>
<div class="input-area">
<label for="editpassport-input">Серия и номер паспорта</label>
<input type="text" id="editpassport-input" >
</div>
<div class="input-area">
<label for="editcitizenship-input">Гражданство</label>
<input type="text" id="editcitizenship-input" >
</div>
<div class="input-area">
<label for="editregaddress-input">Место регистрации</label>
<input type="text" id="editregaddress-input" >
</div>
<div class="input-area">
<label for="editrealaddress-input">Место жительства</label>
<input type="text" id="editrealaddress-input" >
</div>
<div class="input-area">
<label for="editdms-input">Полис ДМС</label>
<input type="text" id="editdms-input" >
</div>
<div class="input-area">
<label for="edittabel-input">Табельный номер</label>
<input type="text" id="edittabel-input" >
</div>
<div class="input-area">
<label for="user-blocked">Чёрный список</label>
<select name="user-blocked" id="isUserBlocked">
<option value="false">Нет</option>
<option value="true">Да</option>
</select>
</div>
<div class="input-area">
<label for="editpassword-input">Новый пароль (Опционально)</label>
<input type="password" id="editpassword-input" new-password>
</div>
<div class="worker-inputs" id="workersInputs">
<h2>Информация о работнике</h2>
<div class="two-inputs">
<input type="text" id="editsub-input" placeholder="Субподряд">
<input type="text" id="editdepartment-input" placeholder="Цех">
<select id="editrole-input">
<option value="Работник">Работник</option>
<option value="Дирекция">Дирекция по безопасности</option>
<option value="КПП">Работник КПП</option>
<option value="Пропуска">Управление пропусками</option>
</select>
<select id="editfire-input">
<option value="false">Не уволен</option>
<option value="true">Уволен</option>
</select>
</div>
<div class="input-area">
<label for="editmigration-input">Миграционная карта</label>
<input type="text" id="editmigration-input">
</div>
<div class="input-area">
<label for="editpermit-input">Разрешение на работу до</label>
<input type="date" id="editpermit-input">
</div>
<div class="input-area">
<label for="editcontract-input">Трудовой договор</label>
<input type="text" id="editcontract-input">
</div>
<div class="input-area">
<label for="editcontractdate-input">Дата договора</label>
<input type="date" id="editcontractdate-input">
</div>
<div class="input-area">
<label for="editlastjob-input">Последнее место работы</label>
<select id="editlastjob-input">
<option value="true">Да</option>
<option value="false">Нет</option>
</select>
</div>
<div class="input-area">
<label for="editfirereason-input">Причина увольнения</label>
<textarea id="editfirereason-input"></textarea>
</div>
</div>
<button type="button" style="display: none;" class="bright" id="makeWorker-button">Сделать работником</button>
<div class="user-buttons" style="display: flex; justify-content: space-between;">
<button style="width: 49.5%;" type="submit" id="editUser-button">Сохранить изменения</button>
<button style="width: 49.5%;" type="button" id="deleteUser-button" class="delete">Удалить пользователя</button>
</div>
</div>
</div>
</form>
<form id="editLegalForm">
<input type="text" id="editlegalid-input" hidden>
<div id="editlegal-form-popup-bg" class="form-popup-bg not-main" >
<div class="form-container">
<div id="btnCloseForm" class="close-button"><svg onclick="closeForm();" id="btnCloseFormSvg" xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path fill="#0050CF" fill-rule="evenodd" d="M14 1.41 12.59 0 7 5.59 1.41 0 0 1.41 5.59 7 0 12.59 1.41 14 7 8.41 12.59 14 14 12.59 8.41 7 14 1.41Z" clip-rule="evenodd"/>
</svg>
</div>
<h1>Юр лицо <span id="editLegal"></span></h1>
<br>
<div class="input-area">
<label for="editname-input">Наименование*</label>
<input type="text" id="editname-input" required>
</div>
<div class="input-area">
<label for="editinn-input">ИНН*</label>
<input type="text" id="editinn-input" required>
</div>
<div class="input-area">
<label for="editogrn-input">ОГРН*</label>
<input type="text" id="editogrn-input" required>
</div>
<div class="input-area">
<label for="editlegaladdress-input">Юридический адрес*</label>
<input type="text" id="editlegaladdress-input" required>
</div>
<div class="input-area">
<label for="editaddress-input">Фактический адрес*</label>
<input type="text" id="editaddress-input" required>
</div>
<div class="input-area">
<label for="editcontactphone-input">Номер телефона контактного лица</label>
<input type="text" id="editcontactphone-input">
</div>
<div class="input-area">
<label for="editcontact-input">Контактное лицо</label>
<input type="text" id="editcontact-input">
</div>
<div class="input-area">
<label for="editadditional-input">Дополнительно</label>
<textarea id="editadditional-input"></textarea>
</div>
<div class="user-buttons" style="display: flex; justify-content: space-between;">
<button style="width: 49.5%;" type="submit" id="editLegal-button">Сохранить изменения</button>
<button style="width: 49.5%;" type="button" id="deleteLegal-button" class="delete">Удалить пользователя</button>
</div>
</div>
</div>
</form>
<script>
var tableType = "People";
function switchTables() {
var usersTable = document.getElementById('usersWrapper');
var legalsTable = document.getElementById('legalsWrapper');
var usersButton = document.getElementById('switchButton')
if (tableType === "People") {
usersTable.style.display = 'none';
legalsTable.style.display = 'block';
usersButton.textContent = 'Физические лица';
tableType = "Legals";
} else {
legalsTable.style.display = 'none';
usersTable.style.display = 'block';
usersButton.textContent = 'Юридические лица';
tableType = "People";
}
}
var pageNumberInput = document.getElementById('page-number');
var peopleMax = Math.ceil({{PeopleCount}} / 15);
var legalsMax = Math.ceil({{LegalsCount}} / 15);
function decrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (currentPage > 1) {
pageNumberInput.textContent = currentPage - 1;
requestUpdate();
} else {
requestUpdate();
}
}
function incrementPage() {
var currentPage = parseInt(pageNumberInput.textContent, 10);
if (tableType === "People") {
if (currentPage === peopleMax || currentPage > peopleMax) {
pageNumberInput.textContent = peopleMax;
requestUpdate();
}
if (currentPage < peopleMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
} else {
if (currentPage === legalsMax || currentPage > legalsMax) {
pageNumberInput.textContent = legalsMax;
requestUpdate();
}
if (currentPage < legalsMax) {
pageNumberInput.textContent = currentPage + 1;
requestUpdate();
}
}
}
</script>
<script>
function closeForm() {
$('.form-popup-bg').removeClass('is-visible');
}
$(document).ready(function($) {
$('#addUser').on('click', function(event) {
event.preventDefault();
$('#adduser-form-popup-bg').addClass('is-visible');
});
$('#adduser-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#adduser-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
$('#edituser-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#edituser-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
$('#editlegal-form-popup-bg').on('click', function(event) {
if ($(event.target).is('#editlegal-form-popup-bg') || $(event.target).is('#btnCloseForm')) {
event.preventDefault();
$(this).removeClass('is-visible');
}
});
});
const typeSelect = document.getElementById('newUserType');
const personInputs = document.getElementById('person-inputs');
const legalInputs = document.getElementById('legal-inputs');
typeSelect.addEventListener('change', function() {
if (this.value === "guest") {
personInputs.style.display = 'flex';
legalInputs.style.display = 'none';
} else if (this.value === "legal") {
personInputs.style.display = 'none';
legalInputs.style.display = 'flex';
}
});
document.addEventListener("DOMContentLoaded", function() {
const newUserForm = document.getElementById("newUserForm");
newUserForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#addUser-button').addClass('inactive');
if (document.getElementById('newUserType').value === "guest") {
const formrole = "guest";
const firstname = $('#firstname-input').val();
const surname = $('#surname-input').val();
const secondname = $('#secondname-input').val();
const born = $('#born-input').val();
const phone = $('#phone-input').val();
if (!$('#firstname-input').val() || !$('#surname-input').val() || !$('#born-input').val()) {
alert("Пожалуйста, заполните все поля, помеченные звёздочкой.")
$('#addUser-button').removeClass('inactive');
return;
}
const email = $('#email-input').val();
const password = $('#password-input').val();
if (password.length < 8) {
alert('Длина пароля должна быть не менее 8 символов')
$('#addUser-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ firstname, surname, secondname, born, phone, email, password, formrole })
});
if (response.status === 201) {
location.reload();
$('#addUser-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#addUser-button').removeClass('inactive');
}
} else if (document.getElementById('newUserType').value === "legal") {
const formrole = "legal";
const name = $('#name-input').val();
const inn = $('#inn-input').val();
const ogrn = $('#ogrn-input').val();
const legaladdress = $('#legaladdress-input').val();
const address = $('#address-input').val();
const phone = $('#contactphone-input').val();
const contact = $('#contact-input').val();
if (!$('#name-input').val() || !$('#inn-input').val() || !$('#ogrn-input').val() || !$('#legaladdress-input').val()) {
alert("Пожалуйста, заполните все поля, помеченные звёздочкой.")
$('#addUser-button').removeClass('inactive');
return;
}
const email = $('#email-input').val();
const password = $('#password-input').val();
if (password.length < 8) {
alert('Длина пароля должна быть не менее 8 символов')
$('#addUser-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name, inn, ogrn, legaladdress, address, phone, email, contact, password, formrole })
});
if (response.status === 201) {
location.reload();
$('#addUser-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#addUser-button').removeClass('inactive');
}
}
});
const editUserForm = document.getElementById("editUserForm");
editUserForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#editUser-button').addClass('inactive');
const id = $('#edituserid-input').val();
const firstname = $('#editfirstname-input').val();
const surname = $('#editsurname-input').val();
const secondname = $('#editsecondname-input').val();
const oldsurname = $('#editoldsurname-input').val();
const born = $('#editborn-input').val();
const phone = $('#editphone-input').val();
const bornplace = $('#editbornplace-input').val();
const passport = $('#editpassport-input').val();
const citizenship = $('#editcitizenship-input').val();
const regaddress = $('#editregaddress-input').val();
const realaddress = $('#editrealaddress-input').val();
const dms = $('#editdms-input').val();
const tabel = $('#edittabel-input').val();
const block = $('#isUserBlocked').val();
const sub = $('#editsub-input').val();
const department = $('#editdepartment-input').val();
const role = $('#editrole-input').val();
const fire = $('#editfire-input').val();
const migration = $('#editmigration-input').val();
const permit = $('#editpermit-input').val();
const contract = $('#editcontract-input').val();
const contractdate = $('#editcontractdate-input').val();
const lastjob = $('#editlastjob-input').val();
const reason = $('#editfirereason-input').val();
const formrole = role;
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/users/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ firstname, surname, secondname, oldsurname, born, phone, bornplace, passport, citizenship, regaddress, realaddress, dms, tabel,
block, sub, department, role, fire, migration, permit, contract, contractdate, lastjob, reason, id, formrole })
});
if (response.status === 201) {
location.reload();
$('#editUser-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#editUser-button').removeClass('inactive');
}
});
const editLegalForm = document.getElementById("editLegalForm");
editLegalForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#editLegal-button').addClass('inactive');
const id = $('#editlegalid-input').val();
const name = $('#editname-input').val();
const inn = $('#editinn-input').val();
const ogrn = $('#editogrn-input').val();
const legaladdress = $('#editlegaladdress-input').val();
const address = $('#editaddress-input').val();
const contactphone = $('#editcontactphone-input').val();
const contact = $('#editcontact-input').val();
const additional = $('#editadditional-input').val();
const formrole = "legal";
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/users/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getCookie("token"),
},
body: JSON.stringify({ name, inn, ogrn, legaladdress, address, contactphone, contact, additional, id, formrole })
});
if (response.status === 201) {
location.reload();
$('#editLegal-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#editLegal-button').removeClass('inactive');
}
});
});
function openUser(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/users/getuser?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#edituser-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#edituserid-input").val(id);
$("#editFIO").html(`${data.data.Фамилия} ${data.data.Имя} ${data.data.Отчество}`);
if (data.data.emp_id !== null) {
$("#workersInputs").css("display", "flex");
$("#makeWorker-button").css("display", "none");
} else {
$("#workersInputs").css("display", "none");
$("#makeWorker-button").attr("onclick", `makeWorker(${id})`);
$("#makeWorker-button").css("display", "block");
}
$("#deleteUser-button").attr("onclick", `deleteUser(${id})`);
$("#editsurname-input").val(data.data.Фамилия);
$("#editfirstname-input").val(data.data.Имя);
$("#editsecondname-input").val(data.data.Отчество);
$("#editoldsurname-input").val(data.data.Фамилия_старая);
$("#editphone-input").val(data.data.Телефон);
$("#editbornplace-input").val(data.data.Место_рождения);
$("#editpassport-input").val(data.data.Паспорт);
$("#editcitizenship-input").val(data.data.Гражданство);
$("#editregaddress-input").val(data.data.Место_регистрации);
$("#editrealaddress-input").val(data.data.Место_жительства);
$("#edittabel-input").val(data.data.Табельный_номер);
$("#editdms-input").val(data.data.ПолисМС);
if (data.data.Черный_список) {
$("#alarmBlocked").show();
$("#isUserBlocked").val("true");
} else {
$("#alarmBlocked").hide();
$("#isUserBlocked").val("false");
}
$("#editsub-input").val(data.data.Субподряд);
$("#editdepartment-input").val(data.data.Цех);
$("#editrole-input").val(data.data.Должность);
if (data.data.Увольнение) {
$("#editfire-input").val("true");
} else {
$("#editfire-input").val("false");
}
$("#editmigration-input").val(data.data.Миграционная_карта);
$("#editcontract-input").val(data.data.Трудовой_договор);
if (data.data.Последнееесто_работы) {
$("#editlastjob-input").val("true");
} else {
$("#editlastjob-input").val("false");
}
$("#editfirereason-input").val(data.data.Причина_увольнения);
function formatDateForDateInput(dateString, inputId) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
document.getElementById(inputId).value = formattedDate;
}
formatDateForDateInput(data.data.Дата_рождения, "editborn-input");
formatDateForDateInput(data.data.Разрешениеа_работуо, "editpermit-input");
formatDateForDateInput(data.data.Датаоговора, "editcontractdate-input");
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function makeWorker(id) {
const requestOptions = {
method: "POST",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/users/makeworker?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#edituser-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function deleteUser(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/user/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#edituser-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function deleteLegal(id) {
const requestOptions = {
method: "DELETE",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/legal/delete?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editlegal-form-popup-bg").removeClass("is-visible");
location.reload();
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
function openLegal(id) {
const requestOptions = {
method: "GET",
headers: {
Authorization: getCookie("token"),
},
};
fetch(API_SERVER + "/legals/getlegal?id=" + id, requestOptions)
.then((response) => {
if (response.ok) {
$("#editlegal-form-popup-bg").addClass("is-visible");
return response.json();
} else {
console.error("Ошибка при отправке POST запроса.");
return "Ошибка при отправке запроса.";
}
})
.then((data) => {
$("#editlegalid-input").val(id);
$("#editLegal").html(`${data.data.Наименование}`);
$("#deleteLegal-button").attr("onclick", `deleteLegal(${id})`);
$("#editname-input").val(data.data.Наименование);
$("#editinn-input").val(data.data.ИНН);
$("#editogrn-input").val(data.data.ОГРН);
$("#editlegaladdress-input").val(data.data.Юридический_адрес);
$("#editaddress-input").val(data.data.Фактический_адрес);
$("#editcontactphone-input").val(data.data.Телефон);
$("#editcontact-input").val(data.data.Контактное_лицо);
$("#editadditional-input").val(data.data.Дополнительно);
})
.catch((error) => {
console.error("Ошибка при отправке запроса:", error);
});
}
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editphone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#editcontactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
</body>
</html>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Бюро пропусков</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<h1>Бюро пропусков</h1>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/signin">Войти</a>
<a href="/signup">Зарегистрироваться</a>
</nav>
</header>
<section class="main-content">
<h1>Авторизация пользователя</h1>
<div class="bg">
<span>
Для оформления пропусков работников организаций и их автомобилей, необходимо зарегистрировать аккаунт подрядной организации и оставить заявку в личном кабинете.
<br><br>
После рассмотрения вашей зявки, информация поступит вам в письме на почту.
<br><br>
Для входа используйте e-mail и пароль, указанные при регистрации.
</span>
<div class="vertical-line"></div>
<div class="buttons">
<button onclick="location.href='/signup'">Зарегистрироваться</button>
<button onclick="location.href='/signin'">Войти</button>
</div>
</div>
</section>
</body>
</html>

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Регистрация</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<h1>Бюро пропусков</h1>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/signin">Войти</a>
<a href="/signup">Зарегистрироваться</a>
</nav>
</header>
<form class="login-form" id="signin-form">
<h1>Авторизация</h1>
<input type="text" id="email-input" placeholder="Введите email" required>
<input type="password" id="password-input" placeholder="Введите пароль" required>
<button style="margin-top: 15px;" type="submit" id="signin-button">Войти</button>
<span>Нет аккаунта? <a href="/signup">Зарегистрироваться</a></span>
</form>
<script>
document.addEventListener("DOMContentLoaded", function() {
const signupForm = document.getElementById("signin-form");
signupForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#signin-button').addClass('inactive');
const email = $('#email-input').val();
const password = $('#password-input').val();
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ email, password })
});
if (response.status === 200) {
const data = await response.json();
const token = data.token;
console.log("GET TOKEN", token);
document.cookie = "token=" + token;
window.location.href = "/";
$('#signin-button').removeClass('inactive');
} else {
$('#signin-button').removeClass('inactive');
alert("Ошибка авторизации");
}
});
});
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
</body>
</html>

View File

@ -0,0 +1,281 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/jquery.min.js"></script>
<script src="../scripts/helpPopup.js"></script>
<title>Регистрация</title>
<style>
body {
background-color: #EEEFF5;
}
</style>
</head>
<body>
<header>
<h1>Бюро пропусков</h1>
<nav>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-1')">Техническая поддержка</a>
<div id="dropdownHelp-1" class="dropdown-help">
<a href="tel:83477527706">8 (34775) 2-77-06</a>
<a href="tel:89174023516">8 (917) 402-35-16</a>
</div>
</div>
<div class="dropdown">
<a class="help-button" onclick="toggleDropdown('dropdownHelp-2')">Инструкции</a>
<div id="dropdownHelp-2" class="dropdown-help dropdown-manual">
<a href="/docs/manual.pdf" target="_blank">Текст</a>
<a href="https://drive.google.com/file/d/1CxrAgr2brQclZqtbbreSUU9tN-jsNTwf/view?usp=sharing" target="_blank">Видео</a>
</div>
</div>
<a href="/signin">Войти</a>
<a href="/signup">Зарегистрироваться</a>
</nav>
</header>
<form class="main-form" id="signup-form">
<h1>Регистрация</h1>
<div class="radio-inputs">
<label class="radio">
<input autocomplete="off" type="radio" id="person-radio" name="account-type" value="guest" checked>
<span class="name">Физ лицо</span>
</label>
<label class="radio">
<input autocomplete="off" type="radio" id="legal-radio" name="account-type" value="legal">
<span class="name">Юр лицо</span>
</label>
</div>
<div class="inputs" id="person-inputs">
<div class="input-area">
<label for="surname-input">Фамилия*</label>
<input type="text" id="surname-input">
</div>
<div class="input-area">
<label for="firstname-input">Имя*</label>
<input type="text" id="firstname-input">
</div>
<div class="input-area">
<label for="secondname-input">Отчество (при наличии)</label>
<input type="text" id="secondname-input">
</div>
<div class="input-area">
<label for="born-input">Дата рождения*</label>
<input type="date" id="born-input">
</div>
<div class="input-area">
<label for="phone-input">Номер телефона</label>
<input type="text" id="phone-input">
</div>
</div>
<div style="display: none;" class="inputs" id="legal-inputs">
<div class="input-area">
<label for="name-input">Наименование организации*</label>
<input type="text" id="name-input">
</div>
<div class="input-area">
<label for="inn-input">ИНН*</label>
<input maxlength="10" type="text" id="inn-input">
</div>
<div class="input-area">
<label for="ogrn-input">ОГРН*</label>
<input maxlength="13" type="text" id="ogrn-input">
</div>
<div class="input-area">
<label for="legaladdress-input">Юридический адрес*</label>
<input type="text" id="legaladdress-input">
</div>
<div class="input-area">
<label for="address-input">Фактический адрес*</label>
<input type="text" id="address-input">
</div>
<div class="input-area">
<label for="contact-input">Имя контактного лица</label>
<input type="text" id="contact-input">
</div>
<div class="input-area">
<label for="contactphone-input">Номер телефона контактного лица</label>
<input type="text" id="contactphone-input">
</div>
</div>
<div class="input-area">
<label for="email-input">Email*</label>
<input type="text" id="email-input" required>
</div>
<div class="input-area">
<label for="password-input">Пароль*</label>
<input type="password" id="password-input" new-password required>
</div>
<div class="input-area">
<label for="repeatpassword-input">Повторите пароль*</label>
<input type="password" id="repeatpassword-input" required>
</div>
<div class="form-info">
<p>Длина пароля должна быть не менее 8 символов.
Пароль должен состоять из букв латинского алфавита (A-z),
арабских цифр (0-9) и специальных символов ((пробел)!"#$%&amp;()*+,-./:;&lt;=&gt;?@[\]^`{|}~)</p>
</div>
<button style="margin-top: 15px;" type="submit" id="signup-button">Регистрация</button>
<button onclick="location.href='/signin'" type="button" class="bright">Авторизация</button>
</form>
<script>
document.addEventListener("DOMContentLoaded", function() {
const signupForm = document.getElementById("signup-form");
signupForm.addEventListener("submit", async function(event) {
event.preventDefault();
$('#signup-button').addClass('inactive');
if (document.getElementById('person-radio').checked) {
const formrole = "guest";
const firstname = $('#firstname-input').val();
const surname = $('#surname-input').val();
const secondname = $('#secondname-input').val();
const born = $('#born-input').val();
const phone = $('#phone-input').val();
if (!$('#firstname-input').val() || !$('#surname-input').val() || !$('#born-input').val()) {
alert("Пожалуйста, заполните все поля, помеченные звёздочкой.")
$('#signup-button').removeClass('inactive');
return;
}
const email = $('#email-input').val();
const password = $('#password-input').val();
const repeatPassword = $('#repeatpassword-input').val();
if (password.length < 8) {
alert('Длина пароля должна быть не менее 8 символов')
$('#signup-button').removeClass('inactive');
return;
}
// Проверяем, совпадают ли пароли
if (password !== repeatPassword) {
alert("Пароли не совпадают");
$('#signup-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ firstname, surname, secondname, born, phone, email, password, formrole })
});
if (response.status === 201) {
const data = await response.json();
const token = data.token;
document.cookie = "token=" + token;
window.location.href = "/";
$('#signup-button').removeClass('inactive');
} else if (response.status === 400) {
alert("Такой Email уже зарегистрирован");
$('#signup-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#signup-button').removeClass('inactive');
}
} else if (document.getElementById('legal-radio').checked) {
const formrole = "legal";
const name = $('#name-input').val();
const inn = $('#inn-input').val();
const ogrn = $('#ogrn-input').val();
const legaladdress = $('#legaladdress-input').val();
const address = $('#address-input').val();
const phone = $('#contactphone-input').val();
const contact = $('#contact-input').val();
if (!$('#name-input').val() || !$('#inn-input').val() || !$('#ogrn-input').val() || !$('#legaladdress-input').val()) {
alert("Пожалуйста, заполните все поля, помеченные звёздочкой.")
$('#signup-button').removeClass('inactive');
return;
}
const email = $('#email-input').val();
const password = $('#password-input').val();
const repeatPassword = $('#repeatpassword-input').val();
if (password.length < 8) {
alert('Длина пароля должна быть не менее 8 символов')
$('#signup-button').removeClass('inactive');
return;
}
// Проверяем, совпадают ли пароли
if (password !== repeatPassword) {
alert("Пароли не совпадают");
$('#signup-button').removeClass('inactive');
return;
}
// Отправляем запрос на сервер для авторизации
const response = await fetch("{{API_SERVER}}/signup", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name, inn, ogrn, legaladdress, address, phone, email, contact, password, formrole })
});
if (response.status === 201) {
const data = await response.json();
const token = data.token;
document.cookie = "token=" + token;
window.location.href = "/";
$('#signup-button').removeClass('inactive');
} else if (response.status === 400) {
alert("Такой Email уже зарегистрирован");
$('#signup-button').removeClass('inactive');
} else {
alert("Ошибка авторизации");
$('#signup-button').removeClass('inactive');
}
}
});
});
</script>
<script src="https://rawgit.com/RobinHerbots/Inputmask/5.x/dist/jquery.inputmask.js"></script>
<script>
$(document).ready(function(){
$('#phone-input').inputmask({"mask": "+7 (999) 999-9999"});
$('#contactphone-input').inputmask({"mask": "+7 (999) 999-9999"});
});
</script>
<script>
const radioInputs = document.querySelectorAll('input[name="account-type"]');
const personInputs = document.getElementById('person-inputs');
const legalInputs = document.getElementById('legal-inputs');
radioInputs.forEach(input => {
input.addEventListener('change', function() {
if (this.checked) {
if (this.value === "guest") {
personInputs.style.display = 'flex';
legalInputs.style.display = 'none';
} else if (this.value === "legal") {
personInputs.style.display = 'none';
legalInputs.style.display = 'flex';
}
}
});
});
</script>
</body>
</html>