This commit is contained in:
2023-10-29 18:07:00 +05:00
parent d72990ce2c
commit 9c97dbc620
9 changed files with 110 additions and 76 deletions
+2
View File
@@ -1 +1,3 @@
# VITE_SERVER_URL=http://localhost:3001
VITE_SERVER_URL=http://192.168.1.170:3001
# VITE_SERVER_URL=https://crm.stream.graff.tech/api
+10
View File
@@ -4,6 +4,8 @@ import { useEffect, useState } from "react";
import SelectUser from "./SelectUser";
import MoreIcon from "./icons/MoreIcon";
import api from "../utils/api";
import Button from "./Button";
import { Link } from "react-router-dom";
interface CardProps {
companyId: string;
@@ -99,6 +101,13 @@ function Card({
{manager ? manager.name : "Не назначен"}
</p>
</div>
<div className="flex gap-2">
{manager && (
<Link to={`http://192.168.1.170:5000/scheduled/${scheduledSessionId}`} target="_blank">
<Button>Начать</Button>
</Link>
)}
<button
onClick={() => setIsShow(!isShow)}
className="p-1 text-[#77828C] hover:bg-neutral-100 rounded-lg"
@@ -107,6 +116,7 @@ function Card({
</button>
</div>
</div>
</div>
<div className="absolute bottom-[2px] left-[272px] z-10">
{availableManagers?.length && (
+3 -1
View File
@@ -15,7 +15,8 @@
"dotenv": "^16.3.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"mongoose": "^7.5.1"
"mongoose": "^7.5.1",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/bcrypt": "^5.0.0",
@@ -23,6 +24,7 @@
"@types/express": "^4.17.17",
"@types/jsonwebtoken": "^9.0.2",
"@types/node": "^20.5.9",
"@types/uuid": "^9.0.6",
"nodemon": "^3.0.1",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
+1 -1
View File
@@ -24,12 +24,12 @@ app.use(cors());
app.use("/login", loginRouter);
app.use("/registration", registrationRouter);
app.use("/actions", actionsRouter);
app.use("/builds", buildsRouter);
app.use("/scheduled_sessions", scheduledSessionsRouter);
app.use("/schedules", schedulesRouter);
app.use("/app", authMiddleware, appRouter);
app.use("/companies", authMiddleware, companiesRouter);
app.use("/users", authMiddleware, usersRouter);
app.use("/builds", authMiddleware, buildsRouter);
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
+7 -1
View File
@@ -5,7 +5,7 @@ const scheduledSessionSchema = new Schema(
companyId: {
type: Schema.Types.ObjectId,
ref: "Company",
required: true,
// required: true,
},
buildId: {
type: Schema.Types.ObjectId,
@@ -36,6 +36,12 @@ const scheduledSessionSchema = new Schema(
type: String,
required: true,
},
adminInviteKey: {
type: String,
},
userInviteKey: {
type: String,
},
},
{
timestamps: true,
+3 -9
View File
@@ -3,16 +3,10 @@ import Build from "../models/Build.js";
const buildsRouter = Router();
buildsRouter.get("/", async (_req, res) => {
await Build.find();
buildsRouter.get("/:id", async (req, res) => {
const build = await Build.findById(req.params.id);
res.json({ ok: 1 });
res.json(build);
});
// buildsRouter.post("/", async (req, res) => {
// const build = await Build.create(req.body);
// res.json(build);
// });
export default buildsRouter;
+33 -39
View File
@@ -16,7 +16,7 @@ const companiesRouter = Router();
companiesRouter.get("/:id", async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
@@ -27,7 +27,7 @@ companiesRouter.get("/:id", async (req, res) => {
companiesRouter.get("/:id/builds", async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
@@ -39,7 +39,7 @@ companiesRouter.get("/:id/builds", async (req, res) => {
companiesRouter.get("/:id/users", async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
@@ -51,7 +51,7 @@ companiesRouter.get("/:id/users", async (req, res) => {
companiesRouter.get("/:id/builds/:buildId/users", async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
@@ -73,12 +73,12 @@ companiesRouter.get(
"/:id/builds/:buildId/scheduled_sessions",
async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
if (!req.query.date) {
res.json({ error: "req.query.date" });
res.json({ error: "Query parameter `date` is required" });
return;
}
@@ -106,34 +106,34 @@ companiesRouter.get(
}
);
companiesRouter.post(
"/:id/builds/:buildId/scheduled_sessions",
async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
return;
}
// companiesRouter.post(
// "/:id/builds/:buildId/scheduled_sessions",
// async (req, res) => {
// if (req.params.id != res.locals.user.companyId) {
// res.json({ error: "Access denied" });
// return;
// }
if (!req.params.buildId) {
res.json({ error: "req.params.buildId" });
return;
}
// if (!req.params.buildId) {
// res.json({ error: "req.params.buildId" });
// return;
// }
const scheduledSession = await ScheduledSession.create({
companyId: req.params.id,
buildId: req.params.buildId,
...req.body,
});
// const scheduledSession = await ScheduledSession.create({
// companyId: req.params.id,
// buildId: req.params.buildId,
// ...req.body,
// });
res.json(scheduledSession);
}
);
// res.json(scheduledSession);
// }
// );
companiesRouter.put(
"/:id/scheduled_sessions/:scheduledSessionId",
async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
@@ -142,21 +142,18 @@ companiesRouter.put(
req.params.scheduledSessionId
);
const scheduledSessionAtSameTime = await ScheduledSession.find({
const scheduledSessionAtSameTime = await ScheduledSession.findOne({
startAt: scheduledSession?.startAt,
userId: req.body.userId,
});
if (scheduledSessionAtSameTime.length) {
if (scheduledSessionAtSameTime) {
res.json({ error: "Scheduled session at same time" });
return;
}
const updatedScheduledSession = await ScheduledSession.findOneAndUpdate(
{
_id: req.params.scheduledSessionId,
companyId: req.params.id,
},
const updatedScheduledSession = await ScheduledSession.findByIdAndUpdate(
req.params.scheduledSessionId,
req.body,
{
new: true,
@@ -177,14 +174,11 @@ companiesRouter.get(
"/:id/builds/:buildId/scheduled_sessions/:scheduledSessionId/availableManagers",
async (req, res) => {
if (!req.query.startAt) {
res.json({ error: "No param `startAt`" });
res.json({ error: "Query parameter `startAt` is required" });
return;
}
try {
// const date = req.query.startAt;
// const sessions = ScheduledSession.find({ userId: res.locals.user.id });
const scheduledSession = await ScheduledSession.findById(
req.params.scheduledSessionId
);
@@ -229,7 +223,7 @@ companiesRouter.get(
companiesRouter.get("/:id/builds/:buildId/schedules", async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
@@ -243,7 +237,7 @@ companiesRouter.get("/:id/builds/:buildId/schedules", async (req, res) => {
companiesRouter.post("/:id/builds/:buildId/schedules", async (req, res) => {
if (req.params.id != res.locals.user.companyId) {
res.json({ error: "Access denied!" });
res.json({ error: "Access denied" });
return;
}
+34 -18
View File
@@ -3,17 +3,33 @@ import ScheduledSession from "../models/ScheduledSession.js";
import Build from "../models/Build.js";
import Schedule from "../models/Schedule.js";
import { addMinutes, endOfDay, parseISO, startOfDay } from "date-fns";
import { v4 as uuidv4 } from "uuid";
const scheduledSessionsRouter = Router();
scheduledSessionsRouter.get("/:id", async (req, res) => {
if (!req.query.inviteKeyType || !req.query.inviteKeyValue) {
res.json({
error:
"Query parameters `inviteKeyType` and `inviteKeyValue` is required",
});
return;
}
const scheduledSessionId = req.params.id;
const scheduledSession = await ScheduledSession.findById(scheduledSessionId);
res.json(scheduledSession);
});
scheduledSessionsRouter.get("/builds/:buildId", async (req, res) => {
if (!req.params.buildId) {
res.json({ error: "Parameter `buildId` is required!" });
res.json({ error: "Parameter `buildId` is required" });
return;
}
if (!req.query.date) {
res.json({ error: "Query parameter `date` is required!" });
res.json({ error: "Query parameter `date` is required" });
return;
}
@@ -32,12 +48,12 @@ scheduledSessionsRouter.get("/builds/:buildId", async (req, res) => {
scheduledSessionsRouter.get("/:buildId", async (req, res) => {
if (!req.params.buildId) {
res.json({ error: "Parameter `buildId` is required!" });
res.json({ error: "Parameter `buildId` is required" });
return;
}
if (!req.query.date) {
res.json({ error: "Query parameter `date` is required!" });
res.json({ error: "Query parameter `date` is required" });
return;
}
@@ -55,44 +71,43 @@ scheduledSessionsRouter.get("/:buildId", async (req, res) => {
});
scheduledSessionsRouter.post("/", async (req, res) => {
if (!req.body.companyId) {
res.json({ error: "Parameter `companyId` is required!" });
return;
}
// if (!req.body.companyId) {
// res.json({ error: "Parameter `companyId` is required" });
// return;
// }
if (!req.body.buildId) {
res.json({ error: "Parameter `buildId` is required!" });
res.json({ error: "Parameter `buildId` is required" });
return;
}
if (!req.body.startAt) {
res.json({ error: "Parameter `startAt` is required!" });
res.json({ error: "Parameter `startAt` is required" });
return;
}
if (!req.body.client) {
res.json({ error: "Parameter `client` is required!" });
res.json({ error: "Parameter `client` is required" });
return;
}
const { companyId, buildId, startAt, client } = req.body;
const { buildId, startAt, client } = req.body;
const build = await Build.findById(buildId);
const schedule = await Schedule.findOne({ companyId, buildId });
const schedule = await Schedule.findOne({ buildId });
const scheduledSessions = await ScheduledSession.find({
companyId,
buildId,
startAt,
});
if (!build) {
res.json({ error: "`Build` not found in the database!" });
res.json({ error: "`Build` not found in the database" });
return;
}
if (scheduledSessions.length === build.sessionLimit) {
res.json({
error: "No slots available!",
error: "No slots available",
scheduledSessionsLength: scheduledSessions.length,
buildSessionLimit: build.sessionLimit,
});
@@ -100,20 +115,21 @@ scheduledSessionsRouter.post("/", async (req, res) => {
}
if (!schedule) {
res.json({ error: "`Schedule` not found in the database!" });
res.json({ error: "`Schedule` not found in the database" });
return;
}
const endAt = addMinutes(parseISO(startAt), schedule.sessionDuration);
const scheduleSession = await ScheduledSession.create({
companyId,
buildId,
startAt,
endAt,
clientName: client.name,
clientEmail: client.email,
clientPhone: client.phone,
adminInviteKey: uuidv4(),
userInviteKey: uuidv4(),
});
res.json({ ok: 1, scheduleSession });
+10
View File
@@ -179,6 +179,11 @@
"@types/mime" "*"
"@types/node" "*"
"@types/uuid@^9.0.6":
version "9.0.6"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.6.tgz#c91ae743d8344a54b2b0c691195f5ff5265f6dfb"
integrity sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==
"@types/webidl-conversions@*":
version "7.0.0"
resolved "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz"
@@ -1366,6 +1371,11 @@ utils-merge@1.0.1:
resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz"
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
uuid@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
v8-compile-cache-lib@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz"