Если у обоих техников есть работа в 05:00, а один заканчивается в 05:30, а другие - в 05:45, что они должны показать, что в этом коде - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - Li - LI - LI - LI. это постоянная служба скольжения, которая используется для расчета временных слотов.const SERVICE_DURATIONS: Record = {
"A/C Service": 30,
"A/C Installation": 105,
"A/C Problem": 40,
};
interface TimeSlot {
start: string;
end: string;
}
// Helper to calculate duration based on type and count
function calculateDuration(type: string, count: number): number {
switch (type) {
case "A/C Service":
return 30 + (count - 1) * 5;
case "A/C Installation":
return 105 + (count - 1) * 45;
case "A/C Problem":
return 40;
default:
return SERVICE_DURATIONS[type] ?? 0;
}
}
app.get("/api/slots", async (req: any, res: any) => {
try {
const { type, count, date } = req.query;
const { authorization } = req.headers;
const accessToken = authorization.split(" ")[1];
const decoded = jwt.verify(accessToken, "accesssecret");
const OrgID = decoded.OrgID;
const UserID = decoded.UserID;
const ROLE = decoded.OrgRole;
const appointmentType = String(type);
let unitCount = parseInt(String(count ?? "1"), 10);
if (!appointmentType || !(appointmentType in SERVICE_DURATIONS)) {
return res.status(400).json({ error: "Invalid or missing appointment type." });
}
if (isNaN(unitCount) || unitCount < 1) {
return res.status(400).json({ error: "Invalid count parameter." });
}
if (appointmentType === "A/C Service" && unitCount {
const minutes = time.minute();
const remainder = minutes % 15;
const addMinutes = remainder > 0 ? 15 - remainder : 0;
return time.add(addMinutes, "minute").startOf("minute");
};
const next15Min = roundUpToNext15Min(now);
cursor = next15Min.isBefore(todayWorkStart) ? todayWorkStart : next15Min;
latestStart = todayWorkEnd.subtract(duration, "minute");
queryStart = todayWorkStart;
queryEnd = todayWorkEnd;
}
let reservedRows = [];
const blockedTimes = new Set();
if (ROLE === "tech") {
const result = await db.query(
`
SELECT "Date" as date, "Type" as type, COALESCE("Count", 1) as count
FROM appointments
WHERE "Date" >= $1 AND "Date" = $1 AND "Date" {
const normalized = dayjs(row.date).toISOString();
console.log(normalized)
if (parseInt(row.count, 10) >= totalTechs) {
console.log('adding to blocked')
blockedTimes.add(normalized);
}
});
// 3. Reserved appointments (for end-time conflict detection)
const reservedResult = await db.query(
`
SELECT "Date" as date, "Type" as type, COALESCE("Count", 1) as count
FROM appointments
WHERE "Date" >= $1 AND "Date" {
const reservedCount = row.count ?? 1;
const reservedDuration = calculateDuration(row.type, reservedCount);
const start = dayjs(row.date);
const end = start.add(reservedDuration, "minute");
return { start, end };
});
console.log(reservedSlots)
const slots: TimeSlot[] = [];
while (slots.length < 6 && cursor.isSameOrBefore(latestStart)) {
const slotStart = cursor;
const slotEnd = slotStart.add(duration, "minute");
const isOverlapping = reservedSlots.some(
(reserved: any) =>
slotStart.isBefore(reserved.end) && slotEnd.isAfter(reserved.start)
);
const normalizedSlot = slotStart.toISOString();
const isBlockedTime = blockedTimes.has(normalizedSlot);
if (!isOverlapping && !isBlockedTime) {
slots.push({
start: slotStart.toISOString(),
end: slotEnd.toISOString(),
});
}
cursor = cursor.add(duration, "minute");
}
return res.json({ slots });
} catch (error) {
console.error("
return res.status(500).json({ error: "Internal server error" });
}
});
< /code>
Все, что я мог придумать, было опробовано. Слишком много вещей, чтобы набрать
Подробнее здесь: https://stackoverflow.com/questions/797 ... -and-times
Мобильная версия