This commit is contained in:
2024-06-06 18:15:51 +05:00
parent e4331fb31f
commit 7e692fee4c
11 changed files with 116 additions and 173 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
# VITE_API_URL=http://localhost:3001
VITE_API_URL=http://192.168.1.171:3001
# VITE_API_URL=https://crm.stream.graff.tech/api
# VITE_API_URL=http://192.168.1.171:3001
VITE_API_URL=https://crm.stream.graff.tech/api
VITE_STREAM_URL=https://stream.graff.tech
+17 -6
View File
@@ -60,13 +60,17 @@ function Card({
return (
<div className="relative flex flex-col gap-2">
<div className="w-[264px] h-[128px] px-3 py-2 bg-white border-r border-b border-[#DAE0E5] flex flex-col gap-2">
<div className="w-[264px] h-[164px] px-3 py-2 bg-white border-r border-b border-[#DAE0E5] flex flex-col justify-between gap-2">
<div className="space-y-2">
<div className="flex justify-between">
<p className="text-sm font-semibold">{client.name}</p>
<div className="">
<p className="text-[10px] font-semibold text-[#77828C]">Клиент</p>
<p className="text-sm">{client.name}</p>
</div>
{manager ? (
<div className="bg-[#E6F2FE] rounded-full px-2 h-[20px] flex items-center gap-1">
<div className="w-1 h-1 rounded-full bg-[#49A1F5]"></div>
<p className="text-[10px] font-semibold text-[#49A1F5] pt-0.5">
<p className="text-[10px] font-semibold text-[#49A1F5]">
Готов
</p>
</div>
@@ -80,8 +84,13 @@ function Card({
)}
</div>
<div className="border-b border-[#DAE0E5] pb-2">
<p className="text-xs text-[#77828C] leading-tight">{client.phone}</p>
<p className="text-xs text-[#77828C] leading-tight">{client.email}</p>
<p className="text-xs text-[#77828C] leading-tight">
{client.phone}
</p>
<p className="text-xs text-[#77828C] leading-tight">
{client.email}
</p>
</div>
</div>
<div className="flex justify-between items-center py-1">
<div className=" flex items-center gap-2">
@@ -105,7 +114,9 @@ function Card({
<div className="flex gap-2">
{manager && (
<Link
to={`${import.meta.env.VITE_STREAM_URL}/scheduled/${scheduledSessionId}`}
to={`${
import.meta.env.VITE_STREAM_URL
}/scheduled/${scheduledSessionId}?admin=true`}
target="_blank"
>
<Button>Начать</Button>
+1 -1
View File
@@ -51,7 +51,7 @@ function DatePicker({ defaultValue, startDate, onChange }: Props) {
function handleClick(date: Date) {
setValue(date);
onChange && onChange(value);
onChange && onChange(date);
}
return (
+1 -1
View File
@@ -3,7 +3,7 @@ import PlusIcon from "./icons/PlusIcon";
function EmptyCard() {
return (
<div className="w-[264px] h-[128px] text-sm font-semibold bg-[#F0F1F2] border-r border-b border-[#DAE0E5] flex items-center justify-center group">
<div className="w-[264px] h-[164px] text-sm font-semibold bg-[#F0F1F2] border-r border-b border-[#DAE0E5] flex items-center justify-center group">
<Button
color="tertiary"
icon={<PlusIcon />}
@@ -8,36 +8,29 @@ import { useEffect, useState } from "react";
import Select from "../Select";
import useModalStore from "../../stores/useModalStore";
import Input from "../Input";
import {
eachMinuteOfInterval,
isAfter,
isBefore,
parse,
parseISO,
startOfDay,
} from "date-fns";
import { eachMinuteOfInterval, parse, parseISO, startOfDay } from "date-fns";
import api from "../../utils/api";
import ChoiceChips from "../ChoiceChips";
import ISchedule from "../../types/ISchedule";
// import ISchedule from "../../types/ISchedule";
import DatePicker from "../DatePicker";
import IScheduledSession from "../../types/IScheduledSession";
interface Props {
companyId: string;
buildId: string;
schedules: ISchedule[];
// schedules: ISchedule[];
handleCreate: () => void;
}
function CreateScheduleModal({
companyId,
buildId,
schedules,
// schedules,
handleCreate,
}: Props) {
const setModal = useModalStore((state) => state.setModal);
const [date, setDate] = useState<Date>(new Date());
const [startDate, setStartDate] = useState<Date>();
const [date, setDate] = useState<Date>(startOfDay(new Date()));
const [startDate, setStartDate] = useState<Date>(startOfDay(new Date()));
const [sessionDuration, setSessionDuration] = useState<number>(30);
const [sessionBreak, setSessionBreak] = useState<number>(5);
const [startTime, setStartTime] = useState<string>("10:00");
@@ -47,17 +40,15 @@ function CreateScheduleModal({
async function getLastScheduledSessionDate() {
try {
const { startAt }: IScheduledSession = await api
const result: IScheduledSession | null = await api
.get(`companies/${companyId}/builds/${buildId}/last_scheduled_session`)
.json();
if (!startAt) return;
if (!result || !result.startAt) return;
setStartDate(startOfDay(parseISO(startAt)));
setStartDate(startOfDay(parseISO(result.startAt)));
} catch (error) {
if (error instanceof Error) {
alert(error.message);
}
alert((error as Error).message);
}
}
@@ -66,7 +57,7 @@ function CreateScheduleModal({
}, []);
function calculateSessionsPerDay() {
if (!startDate) return;
// if (!startDate) return;
const sessionsPerDay = eachMinuteOfInterval(
{
@@ -88,7 +79,7 @@ function CreateScheduleModal({
async function createSchedule() {
await api.post(`companies/${companyId}/builds/${buildId}/schedules`, {
json: {
startDate,
startDate: date,
startTime,
endTime,
weekends,
@@ -100,7 +91,7 @@ function CreateScheduleModal({
}
async function handleClickCreateSchedule() {
if (!startDate) return;
// if (!startDate) return;
await createSchedule();
handleCreate();
@@ -141,8 +132,8 @@ function CreateScheduleModal({
<div className="flex flex-col">
<Label value="Начало" />
<DatePicker
startDate={startDate || new Date()}
onChange={(date) => setDate(date)}
startDate={startDate}
onChange={(date) => (setDate(date), console.log(date))}
/>
</div>
</div>
+2 -6
View File
@@ -422,11 +422,7 @@ function DashboardPage() {
scheduleSessionStartAt={
scheduledSession.startAt
}
client={{
name: scheduledSession.clientName,
phone: scheduledSession.clientPhone,
email: scheduledSession.clientEmail,
}}
client={scheduledSession.client}
manager={selectedManager}
managers={selectedBuildManagers || []}
handleSelect={(scheduledSessionId, managerId) =>
@@ -523,7 +519,7 @@ function DashboardPage() {
<CreateScheduleModal
companyId={company?.id}
buildId={selectedBuild?.id}
schedules={schedules}
// schedules={schedules}
handleCreate={getSchedules}
/>
)
+3 -3
View File
@@ -21,15 +21,15 @@ connectDB();
app.use(json());
app.use(cors({ origin: "*" }));
app.use("/app", authMiddleware, appRouter);
app.use("/companies", authMiddleware, companiesRouter);
app.use("/users", authMiddleware, usersRouter);
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.listen(port, () => {
console.log(`Server listening on port ${port}`);
-3
View File
@@ -258,9 +258,6 @@ router.get(
async (req, res) => {
const { companyId, buildId } = req.params;
console.log("companyId", companyId);
console.log("buildId", buildId);
try {
const lastScheduledSession = await ScheduledSession.findOne({
companyId,
+26 -81
View File
@@ -5,13 +5,11 @@ import Schedule from "../models/Schedule";
import {
addMinutes,
areIntervalsOverlapping,
differenceInMinutes,
endOfDay,
isValid,
parseISO,
startOfDay,
} from "date-fns";
import { isValidObjectId } from "mongoose";
const scheduledSessionsRouter = Router();
@@ -26,50 +24,33 @@ scheduledSessionsRouter.get("/", async (_req, res) => {
scheduledSessionsRouter.get("/:id", async (req, res) => {
const scheduledSessionId = req.params.id;
if (!isValidObjectId(scheduledSessionId)) {
return res.json({
status: "error",
message: "Invalid session ID value",
});
}
const scheduledSession = await ScheduledSession.findById(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" });
return;
}
if (!req.query.date) {
res.json({ error: "Query parameter `date` is required" });
return;
}
const buildId = req.params.buildId;
const date = req.query.date as string;
if (!isValidObjectId(buildId)) {
return res.json({
status: "error",
message: "Invalid build ID value",
});
}
scheduledSessionsRouter.get(
"/companies/:companyId/builds/:buildId",
async (req, res) => {
const { companyId, buildId } = req.params;
const { date } = req.query;
try {
const scheduledSessions = await ScheduledSession.find({
companyId,
buildId,
startAt: {
$gte: startOfDay(parseISO(date)),
$lt: endOfDay(parseISO(date)),
$gte: startOfDay(parseISO(date as string)),
$lt: endOfDay(parseISO(date as string)),
},
});
res.json(scheduledSessions);
});
} catch (error) {
res.json({ error: (error as Error).message });
}
}
);
scheduledSessionsRouter.get("/:buildId", async (req, res) => {
if (!req.params.buildId) {
@@ -98,13 +79,6 @@ scheduledSessionsRouter.get("/:buildId", async (req, res) => {
scheduledSessionsRouter.post("/", async (req, res) => {
const { buildId, startAt, client, duration } = req.body;
if (!isValidObjectId(buildId)) {
return res.json({
status: "error",
message: "Invalid build ID value",
});
}
if (!buildId || !startAt) {
return res.json({
status: "error",
@@ -183,7 +157,7 @@ scheduledSessionsRouter.post("/", async (req, res) => {
const schedule = await Schedule.findOne({
buildId,
startDate: { $lte: startAtISO },
endDate: { $gte: startAtISO },
// endDate: { $gte: startAtISO },
});
if (!schedule) {
@@ -246,16 +220,13 @@ scheduledSessionsRouter.post("/", async (req, res) => {
scheduledSessionsRouter.put("/:id", async (req, res) => {
const scheduledSessionId = req.params.id;
if (!isValidObjectId(scheduledSessionId)) {
return res.json({
status: "error",
message: "Invalid session ID value",
});
}
let {
startAt,
endAt,
activeSessionId,
}: { startAt: string; endAt: string; activeSessionId: string } = req.body;
let { startAt, duration }: { startAt: string; duration: number } = req.body;
if (!startAt && !duration) {
if (!startAt && !endAt) {
return res.json({
status: "error",
message: "Parameter `startAt` or `duration` is required, or both",
@@ -269,16 +240,9 @@ scheduledSessionsRouter.put("/:id", async (req, res) => {
});
}
function isInteger(num: number) {
return (num ^ 0) === num;
}
if (duration && !isInteger(duration)) {
return res.json({
status: "error",
message: "Parameter `duration` is not an integer",
});
}
// function isInteger(num: number) {
// return (num ^ 0) === num;
// }
const scheduledSession = await ScheduledSession.findById(scheduledSessionId);
@@ -289,22 +253,10 @@ scheduledSessionsRouter.put("/:id", async (req, res) => {
});
}
if (!duration) {
duration = differenceInMinutes(
scheduledSession.endAt,
scheduledSession.startAt
);
}
const endAt = addMinutes(
(startAt && parseISO(startAt.toString())) || scheduledSession.startAt,
duration
);
try {
const scheduledSession = await ScheduledSession.findByIdAndUpdate(
scheduledSessionId,
{ startAt, endAt },
{ startAt, endAt, activeSessionId },
{ new: true }
);
@@ -319,13 +271,6 @@ scheduledSessionsRouter.put("/:id", async (req, res) => {
scheduledSessionsRouter.delete("/:id", async (req, res) => {
const scheduledSessionId = req.params.id;
if (!isValidObjectId(scheduledSessionId)) {
return res.json({
status: "error",
message: "Invalid session ID value",
});
}
try {
await ScheduledSession.findByIdAndDelete(scheduledSessionId);
+8 -5
View File
@@ -3,14 +3,16 @@ import Schedule from "../models/Schedule";
const schedulesRouter = Router();
schedulesRouter.get("/builds/:buildId", async (req, res) => {
const buildId = req.params.buildId;
schedulesRouter.get(
"/companies/:companyId/builds/:buildId",
async (req, res) => {
const { companyId, buildId } = req.params;
const date = new Date();
const schedules = await Schedule.find({
companyId,
buildId,
startDate: { $lte: date },
endDate: { $gte: date },
});
if (!schedules.length) {
@@ -20,9 +22,9 @@ schedulesRouter.get("/builds/:buildId", async (req, res) => {
if (req.query.date) {
const schedule = await Schedule.findOne({
companyId,
buildId,
startDate: { $lte: date },
endDate: { $gte: date },
});
res.json(schedule);
@@ -30,6 +32,7 @@ schedulesRouter.get("/builds/:buildId", async (req, res) => {
}
res.json(schedules);
});
}
);
export default schedulesRouter;
+1 -1
View File
@@ -10,7 +10,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true
"skipLibCheck": true,
},
"ts-node": {
"transpileOnly": true