Добавил работу с расписанием

This commit is contained in:
Artem VV 2023-05-19 21:15:27 +07:00
parent e9b8b44d1b
commit 35a20acce6
13 changed files with 939 additions and 25 deletions

View file

@ -23,33 +23,22 @@ model study_item {
model study_slot { model study_slot {
id Int @id(map: "pk_study_slot") @default(autoincrement()) id Int @id(map: "pk_study_slot") @default(autoincrement())
study_item_id Int? study_item_id Int
study_item study_item? @relation(fields: [study_item_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_study_slot_study_item") where String
timetable_timetable_slot_1Tostudy_slot timetable[] @relation("timetable_slot_1Tostudy_slot") studentsGroup String
timetable_timetable_slot_2Tostudy_slot timetable[] @relation("timetable_slot_2Tostudy_slot") position Int
timetable_timetable_slot_3Tostudy_slot timetable[] @relation("timetable_slot_3Tostudy_slot") study_item study_item @relation(fields: [study_item_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "fk_study_slot_study_item")
timetable_timetable_slot_4Tostudy_slot timetable[] @relation("timetable_slot_4Tostudy_slot") timetable timetable? @relation(fields: [timetableId], references: [id])
timetable_timetable_slot_5Tostudy_slot timetable[] @relation("timetable_slot_5Tostudy_slot") timetableId Int?
timetable_timetable_slot_6Tostudy_slot timetable[] @relation("timetable_slot_6Tostudy_slot")
} }
model timetable { model timetable {
id Int @id(map: "pk_timetable") @default(autoincrement()) id Int @id(map: "pk_timetable") @default(autoincrement())
slot_1 Int?
slot_2 Int?
slot_3 Int?
slot_4 Int?
slot_5 Int?
slot_6 Int?
day Int @db.SmallInt day Int @db.SmallInt
teacher Int odd Boolean
study_slot_timetable_slot_1Tostudy_slot study_slot? @relation("timetable_slot_1Tostudy_slot", fields: [slot_1], references: [id], map: "fk_timetable_study_slot_1") slots study_slot[]
study_slot_timetable_slot_2Tostudy_slot study_slot? @relation("timetable_slot_2Tostudy_slot", fields: [slot_2], references: [id], map: "fk_timetable_study_slot_2") teacher users @relation(fields: [teacherId], references: [id])
study_slot_timetable_slot_3Tostudy_slot study_slot? @relation("timetable_slot_3Tostudy_slot", fields: [slot_3], references: [id], map: "fk_timetable_study_slot_3") teacherId Int
study_slot_timetable_slot_4Tostudy_slot study_slot? @relation("timetable_slot_4Tostudy_slot", fields: [slot_4], references: [id], map: "fk_timetable_study_slot_4")
study_slot_timetable_slot_5Tostudy_slot study_slot? @relation("timetable_slot_5Tostudy_slot", fields: [slot_5], references: [id], map: "fk_timetable_study_slot_5")
study_slot_timetable_slot_6Tostudy_slot study_slot? @relation("timetable_slot_6Tostudy_slot", fields: [slot_6], references: [id], map: "fk_timetable_study_slot_6")
users users @relation(fields: [teacher], references: [id], onDelete: Cascade, map: "fk_timetable_users_teacher")
} }
model users { model users {

View file

@ -0,0 +1,82 @@
---
import { getStudyItems } from "../db";
const studyItems = await getStudyItems();
---
<div class="container">
<datalist id="siOptions">
{studyItems.map((si) => <option value={`${si.id} | ${si.title}`}>{si.title}</option>)}
</datalist>
<div class="row">
<div class="col-12">
<h1>Предметы</h1>
<form class="row g-3" onsubmit="createNewStudyItem(this); return false;">
<div class="col-auto">
<label for="studyItemName" class="visually-hidden">Название предмета</label>
<input type="text" class="form-control" id="studyItemName" name="studyItemName" placeholder="Название предмета" />
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-3">Создать</button>
</div>
</form>
<div class="d-flex text-center gap-3 flex-wrap">
{
studyItems.map((item) => (
<div class="g-col-4 card p-2">
<p>{item.title}</p>
<button class="btn btn-sm btn-danger" onclick={`deleteStudyItem(${item.id})`}>
Удалить
</button>
</div>
))
}
{studyItems.length === 0 && <div class="g-col">Предметов нет</div>}
</div>
</div>
</div>
</div>
<hr />
<script is:inline>
async function createNewStudyItem(form) {
try {
const fd = new FormData(form);
const resp = await fetch("/ttapi/createStudyItem", {
method: "POST",
body: fd,
});
const json = await resp.json();
if (json.ok) {
location.reload();
} else {
throw new Error(json.reason);
}
} catch (e) {
console.error(e);
alert(e.message);
}
}
async function deleteStudyItem(itemId) {
try {
const fd = new FormData();
fd.append("itemId", itemId);
const resp = await fetch("/ttapi/deleteStudyItem", {
method: "POST",
body: fd,
});
const json = await resp.json();
if (json.ok) {
location.reload();
} else {
throw new Error(json.reason);
}
} catch (e) {
console.error(e);
alert(e.message);
}
}
</script>

View file

@ -0,0 +1,258 @@
---
import TimetableElement from "./TimetableElement.astro";
import type { users, timetable } from "@prisma/client";
import { getUserFromLogin, searchUsers, getTimetable, createTimetable } from "../db";
const allUsers = await searchUsers({
isAdmin: false,
});
let editedUser: users | null = null;
const sLogin = Astro.url.searchParams.get("login");
if (sLogin !== null) {
editedUser = await getUserFromLogin(sLogin);
}
let oddTT: timetable[] = [];
let evenTT: timetable[] = [];
if (editedUser !== null) {
oddTT = await getTimetable(editedUser.id, true);
if (oddTT.length === 0) {
await createTimetable(editedUser.id, true);
oddTT = await getTimetable(editedUser.id, true);
}
evenTT = await getTimetable(editedUser.id, false);
if (evenTT.length === 0) {
await createTimetable(editedUser.id, false);
evenTT = await getTimetable(editedUser.id, false);
}
}
---
<div class="container" data-user={editedUser?.login}>
{
editedUser === null && (
<form>
<label for="selectedUser" class="form-label">
Выбор пользователя
</label>
<input class="form-control mb-3" list="usersOptions" id="selectedUser" name="login" placeholder="Начните ввод, чтобы выбрать пользователя" />
<datalist id="usersOptions">
{allUsers.map((user) => (
<option value={user.login}>{user.login}</option>
))}
</datalist>
<button type="submit" class="btn btn-primary btn-sm w-100">
Выбрать
</button>
</form>
)
}
{
editedUser !== null && (
<>
<div class="row">
<div class="col-6">
<h5>Нечётная неделя</h5>
<div class="d-flex flex-wrap gap-2">
<TimetableElement tt={oddTT[0]} position={0} />
<TimetableElement tt={oddTT[1]} position={1} />
<TimetableElement tt={oddTT[2]} position={2} />
<TimetableElement tt={oddTT[3]} position={3} />
<TimetableElement tt={oddTT[4]} position={4} />
<TimetableElement tt={oddTT[5]} position={5} />
</div>
</div>
<div class="col-6">
<h5>Чётная неделя</h5>
<div class="d-flex flex-wrap gap-2">
<TimetableElement tt={evenTT[0]} position={0} />
<TimetableElement tt={evenTT[1]} position={1} />
<TimetableElement tt={evenTT[2]} position={2} />
<TimetableElement tt={evenTT[3]} position={3} />
<TimetableElement tt={evenTT[4]} position={4} />
<TimetableElement tt={evenTT[5]} position={5} />
</div>
</div>
</div>
<div id="fluindSaveButton">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
<>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z" />
</>
</svg>
</div>
<a id="fluindExitButton" href="/timetable">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
<>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</>
</svg>
</a>
</>
)
}
</div>
<script>
function serializeTimetable() {
const result = [...document.querySelectorAll("[data-day]")].map((pe) => {
const data = [...pe!.querySelectorAll(".list-group > div")].map((e, idx) => {
const isWindow = (e.querySelector("[name=iw]")! as HTMLInputElement).checked;
const position = idx;
const day = parseInt((pe as HTMLInputElement).dataset.position!);
const studyItem = parseInt((e.querySelector("[name=si]")! as HTMLInputElement).value.split(" | ")[0]);
const slotPlace = (e.querySelector("[name=sp]")! as HTMLInputElement).value;
const slotGroup = (e.querySelector("[name=sg]")! as HTMLInputElement).value;
if (!isWindow && Number.isNaN(position) && Number.isNaN(studyItem) && slotPlace === "" && slotGroup === "") {
(e.querySelector("form")! as HTMLFormElement).reportValidity();
throw new Error("Некорректные данные");
}
return {
odd: (pe as HTMLElement).dataset.odd === "odd",
isWindow,
position,
day,
studyItem,
slotPlace,
slotGroup,
};
});
console.log(data);
return data;
});
return result.reduce(
(acc, cur) => {
let newValue: {
isWindow: boolean;
position?: number;
day?: number;
studyItem?: number;
slotPlace?: string;
slotGroup?: string;
}[] = cur.map((e) => {
if (e.isWindow) {
return {
isWindow: true,
};
}
return {
isWindow: false,
position: e.position,
day: e.day,
studyItem: e.studyItem,
slotPlace: e.slotPlace,
slotGroup: e.slotGroup,
};
});
if (cur[0].odd) {
acc.odd.push(newValue);
} else {
acc.even.push(newValue);
}
return acc;
},
{
odd: [],
even: [],
} as {
odd: object[];
even: object[];
}
);
}
async function saveTimetable() {
try {
const serializedTimetable = serializeTimetable();
console.log(serializedTimetable);
const resp = await fetch("/ttapi/updateTimetable", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
login: document.querySelector("[data-user]")!.getAttribute("data-user"),
odd: serializedTimetable.odd,
even: serializedTimetable.even,
}),
});
const json = await resp.json();
if (json.ok) {
alert("Расписание сохранено");
location.reload();
} else {
throw new Error(json.reason);
}
} catch (e) {
if (e instanceof Error) {
alert(e.message);
}
return;
}
}
document.addEventListener("DOMContentLoaded", () => {
const forms = document.querySelectorAll(".needs-validation");
Array.from(forms).forEach((form) => {
form.addEventListener(
"submit",
(event) => {
if (!(form as HTMLFormElement).checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add("was-validated");
},
false
);
});
document.getElementById("fluindSaveButton")?.addEventListener("click", () => {
saveTimetable();
});
});
</script>
<style>
#fluindSaveButton,
#fluindExitButton {
position: fixed;
bottom: 1rem;
right: 1rem;
width: 3rem;
height: 3rem;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: 0.2s;
}
#fluindSaveButton:hover,
#fluindExitButton:hover {
transform: scale(1.1);
}
#fluindSaveButton {
background-color: #007bff;
fill: white;
bottom: 5rem;
}
#fluindExitButton {
background-color: #dc3545;
fill: white;
}
</style>

View file

@ -0,0 +1,30 @@
---
import TimetableSlotElement from "./TimetableSlotElement.astro";
import type { timetable } from "@prisma/client";
import { getTimetableSlots } from "../db";
export interface Props {
tt: timetable;
position: number;
}
const { tt, position } = Astro.props;
const dayNames = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
const slots = await getTimetableSlots(tt.id);
---
<div class="card w-100" data-day={tt.day} data-odd={tt.odd ? "odd" : "even"} data-position={position}>
<div class="card-body">
<h5 class="card-title">{dayNames[tt.day]}</h5>
</div>
<div class="list-group list-group-flush">
{
[0, 1, 2, 3, 4, 5].map((i) => (
<TimetableSlotElement ss={slots.find((slot, idx) => slot.position == i) ?? null} position={i} day={tt.day} isOdd={tt.odd} />
))
}
</div>
</div>

View file

@ -0,0 +1,33 @@
---
import TimetableSlotElementViewer from "./TimetableSlotElementViewer.astro";
import type { timetable } from "@prisma/client";
import { getTimetableSlots } from "../db";
export interface Props {
tt: timetable;
position: number;
}
const { tt, position } = Astro.props;
const dayNames = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
const slots = await getTimetableSlots(tt.id);
const none = slots.length == 0;
---
{
!none && (
<div class="card w-100" data-day={tt.day} data-odd={tt.odd ? "odd" : "even"} data-position={position}>
<div class="card-body">
<h5 class="card-title">{dayNames[tt.day]}</h5>
</div>
<div class="list-group list-group-flush">
{[0, 1, 2, 3, 4, 5].map((i) => (
<TimetableSlotElementViewer ss={slots.find((slot, idx) => slot.position == i) ?? null} position={i} day={tt.day} isOdd={tt.odd} />
))}
</div>
</div>
)
}

View file

@ -0,0 +1,120 @@
---
import type { study_slot, study_item } from "@prisma/client";
import { getStudyItem } from "../db";
export interface Props {
ss: study_slot | null;
position: number;
day: number;
isOdd: boolean;
}
const { ss, position, day, isOdd } = Astro.props;
const positionToTime = ["08:30-10:05", "10:15-11:50", "12:00-13:35", "14:10-15:45", "15:55-17:30", "17:40-19:15"];
let studyItem: study_item | null = null;
if (ss !== null) {
studyItem = await getStudyItem(ss.id);
}
---
<div class="list-group-item">
<div>
{
ss === null && (
<input
class="form-check-input"
type="checkbox"
id={`isWindow-${day}-${position}`}
data-target={`dh-${day}-${position}-${isOdd ? "o" : "e"}`}
name="iw"
checked
/>
)
}
{
ss !== null && (
<input
class="form-check-input"
type="checkbox"
id={`isWindow-${day}-${position}`}
data-target={`dh-${day}-${position}-${isOdd ? "o" : "e"}`}
name="iw"
/>
)
}
<label class="form-check-label" for={`isWindow-${day}-${position}`}> Окно</label>
<div>{positionToTime[position]}</div>
<form
id={`dh-${day}-${position}-${isOdd ? "o" : "e"}`}
class:list={[
{
"d-none": ss === null,
},
]}
>
<label for={`slotSI-${day}-${position}`} class="form-label"> Предмет</label>
<input
class="form-control mb-3"
list="siOptions"
id={`slotSI-${day}-${position}`}
placeholder="Начните ввод"
name="si"
value={studyItem !== null ? `${(studyItem as study_item).id} | ${(studyItem as study_item).title}` : ""}
required
/>
<label for={`slotPlace-${day}-${position}`} class="form-label"> Место проведения</label>
<input class="form-control mb-3" id={`slotPlace-${day}-${position}`} name="sp" value={ss !== null ? (ss as study_slot).where : ""} required />
<label for={`slotGroup-${day}-${position}`} class="form-label"> Группа</label>
<input
class="form-control mb-3"
id={`slotGroup-${day}-${position}`}
name="sg"
value={ss !== null ? (ss as study_slot).studentsGroup : ""}
required
/>
</form>
</div>
{
ss !== null && (
<>
<hr />
<div>
<div>{studyItem!.title}</div>
<div>{positionToTime[position]}</div>
<div>Где: {ss.where}</div>
<div>Группа(ы): {ss.studentsGroup}</div>
</div>
</>
)
}
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll("[data-target]").forEach((e) => {
e.addEventListener("change", () => {
const targetId = e.getAttribute("data-target");
if (targetId === null) {
console.error("targetId is null");
return;
}
const target = document.getElementById(targetId) as HTMLInputElement;
if ((e as HTMLInputElement).checked) {
target.classList.add("d-none");
target.querySelectorAll("input").forEach((e) => {
e.required = false;
});
} else {
target.classList.remove("d-none");
target.querySelectorAll("input").forEach((e) => {
e.required = true;
});
}
});
});
});
</script>

View file

@ -0,0 +1,44 @@
---
import type { study_slot, study_item } from "@prisma/client";
import { getStudyItem } from "../db";
export interface Props {
ss: study_slot | null;
position: number;
day: number;
isOdd: boolean;
}
const { ss, position, day, isOdd } = Astro.props;
const positionToTime = ["08:30-10:05", "10:15-11:50", "12:00-13:35", "14:10-15:45", "15:55-17:30", "17:40-19:15"];
let studyItem: study_item | null = null;
if (ss !== null) {
studyItem = await getStudyItem(ss.id);
}
---
{
ss !== null && (
<div class="list-group-item">
<div>
<div>{studyItem!.title}</div>
<div>{positionToTime[position]}</div>
<div>Где: {ss.where}</div>
<div>Группа(ы): {ss.studentsGroup}</div>
</div>
</div>
)
}
{
/*
ss === null && (
<div class="list-group-item">
<div>
<div>Свободно</div>
<div>{positionToTime[position]}</div>
</div>
</div>
)*/
}

View file

@ -0,0 +1,51 @@
---
import TimetableElementViewer from "./TimetableElementViewer.astro";
import type { users, timetable } from "@prisma/client";
import { getTimetable, createTimetable } from "../db";
export interface Props {
user: users;
}
const { user } = Astro.props;
let oddTT: timetable[] = await getTimetable(user.id, true);
let evenTT: timetable[] = await getTimetable(user.id, false);
if (oddTT.length === 0) {
await createTimetable(user.id, true);
oddTT = await getTimetable(user.id, true);
}
if (evenTT.length === 0) {
await createTimetable(user.id, false);
evenTT = await getTimetable(user.id, false);
}
---
<div class="container">
<div class="row mt-5 mb-5">
<div class="col-6">
<h5>Нечётная неделя</h5>
<div class="d-flex flex-wrap gap-2">
<TimetableElementViewer tt={oddTT[0]} position={0} />
<TimetableElementViewer tt={oddTT[1]} position={1} />
<TimetableElementViewer tt={oddTT[2]} position={2} />
<TimetableElementViewer tt={oddTT[3]} position={3} />
<TimetableElementViewer tt={oddTT[4]} position={4} />
<TimetableElementViewer tt={oddTT[5]} position={5} />
</div>
</div>
<div class="col-6">
<h5>Чётная неделя</h5>
<div class="d-flex flex-wrap gap-2">
<TimetableElementViewer tt={evenTT[0]} position={0} />
<TimetableElementViewer tt={evenTT[1]} position={1} />
<TimetableElementViewer tt={evenTT[2]} position={2} />
<TimetableElementViewer tt={evenTT[3]} position={3} />
<TimetableElementViewer tt={evenTT[4]} position={4} />
<TimetableElementViewer tt={evenTT[5]} position={5} />
</div>
</div>
</div>
</div>

153
src/db.ts
View file

@ -218,3 +218,156 @@ export async function searchUsers(params: { login?: string; isAdmin?: boolean; f
}); });
return users; return users;
} }
export async function getStudyItems() {
const items = await client.study_item.findMany({
orderBy: {
id: "asc",
},
});
return items;
}
export async function createStudyItem(title: string) {
const item = await client.study_item.create({
data: {
title: title,
},
});
return item !== null;
}
export async function deleteStudyItem(id: number) {
const result = await client.study_item.delete({
where: {
id: id,
},
});
return result !== null;
}
export async function getTimetable(userId: number, isOdd: boolean) {
const tt = await client.timetable.findMany({
where: {
teacherId: userId,
odd: isOdd,
},
orderBy: {
day: "asc",
},
});
return tt;
}
export async function createTimetable(userId: number, isOdd: boolean) {
const tt = await client.timetable.createMany({
data: [
{ day: 0, odd: isOdd, teacherId: userId },
{ day: 1, odd: isOdd, teacherId: userId },
{ day: 2, odd: isOdd, teacherId: userId },
{ day: 3, odd: isOdd, teacherId: userId },
{ day: 4, odd: isOdd, teacherId: userId },
{ day: 5, odd: isOdd, teacherId: userId },
],
});
return tt.count === 6;
}
export async function getTimetableSlots(ttId: number) {
const slots = await client.study_slot.findMany({
where: {
timetableId: ttId,
},
orderBy: {
position: "asc",
},
});
return slots;
}
export async function getStudyItem(ttSlotId: number) {
const slot = await client.study_slot.findFirst({
where: {
id: ttSlotId,
},
});
const item = await client.study_item.findFirst({
where: {
id: slot!.study_item_id,
},
});
return item;
}
export type UpdateTTElementModel = {
isWindow: boolean;
position: number;
day: number;
studyItem: number;
slotPlace: string;
slotGroup: string;
};
export async function updateUserTimetable(userLogin: string, oddUpdate: UpdateTTElementModel[][], evenUpdate: UpdateTTElementModel[][]) {
const user = await getUserFromLogin(userLogin);
const oddTT = await client.timetable.findMany({
where: {
teacherId: user!.id,
odd: true,
},
});
const evenTT = await client.timetable.findMany({
where: {
teacherId: user!.id,
odd: false,
},
});
for (let odt of oddTT) {
await client.study_slot.deleteMany({
where: {
timetableId: odt.id,
},
});
}
for (let edt of evenTT) {
await client.study_slot.deleteMany({
where: {
timetableId: edt.id,
},
});
}
await client.study_slot.createMany({
data: oddUpdate
.map((e) => {
return e
.filter((e) => !e.isWindow)
.map((el) => {
return {
timetableId: oddTT.find((e) => e.day === el.day)!.id,
position: el.position,
study_item_id: el.studyItem,
where: el.slotPlace,
studentsGroup: el.slotGroup,
};
});
})
.reduce((acc, val) => acc.concat(val), []),
});
await client.study_slot.createMany({
data: evenUpdate
.map((e) => {
return e
.filter((e) => !e.isWindow)
.map((el) => {
return {
timetableId: evenTT.find((e) => e.day === el.day)!.id,
position: el.position,
study_item_id: el.studyItem,
where: el.slotPlace,
studentsGroup: el.slotGroup,
};
});
})
.reduce((acc, val) => acc.concat(val), []),
});
}

32
src/pages/timetable.astro Normal file
View file

@ -0,0 +1,32 @@
---
import Layout from "../layouts/Layout.astro";
import Navbar from "../components/Navbar.astro";
import TimetableViewer from "../components/TimetableViewer.astro";
import StudyItemsList from "../components/StudyItemsList.astro";
import TimetableEditor from "../components/TimetableEditor.astro";
import { getUserSession, getSessionUser } from "../db";
if (Astro.cookies.has("session")) {
const sessId = Astro.cookies.get("session").value!;
const dbSess = await getUserSession(sessId);
if (dbSess === null) {
Astro.cookies.delete("session");
return Astro.redirect("/login");
}
} else {
return Astro.redirect("/login");
}
const sessId = Astro.cookies.get("session").value!;
const user = (await getSessionUser(sessId))!;
---
<Layout title="Пользователи">
<main>
<Navbar is_user_admin={user.is_admin} />
{user.is_admin && <StudyItemsList />}
{user.is_admin && <TimetableEditor />}
{!user.is_admin && <TimetableViewer user={user} />}
</main>
</Layout>

View file

@ -0,0 +1,39 @@
import type { APIContext } from "astro";
import { createStudyItem, getSessionUser } from "../../db";
import { Prisma } from "@prisma/client";
export async function post({ request, cookies }: APIContext) {
const response: { ok: boolean; reason?: string } = {
ok: true,
};
try {
const sessId = cookies.get("session").value!;
const user = (await getSessionUser(sessId))!;
if (!user.is_admin) {
throw new Error("Доступно только администраторам");
}
const formData = await request.formData();
const studyItemName = formData.get("studyItemName");
if (studyItemName === null) {
throw new Error("Не предоставлены данные создания предмета");
}
await createStudyItem(studyItemName.toString());
response.ok = true;
} catch (e: any) {
response.ok = false;
if (e instanceof Prisma.PrismaClientKnownRequestError) {
response.reason = `Неизвестная ошибка базы данных. Код ${e.code}`;
} else if (e instanceof Error) {
response.reason = e.message.trim();
} else {
response.reason = e.toString().trim();
}
}
return {
body: JSON.stringify(response),
};
}

View file

@ -0,0 +1,39 @@
import type { APIContext } from "astro";
import { deleteStudyItem, getSessionUser } from "../../db";
import { Prisma } from "@prisma/client";
export async function post({ request, cookies }: APIContext) {
const response: { ok: boolean; reason?: string } = {
ok: true,
};
try {
const sessId = cookies.get("session").value!;
const user = (await getSessionUser(sessId))!;
if (!user.is_admin) {
throw new Error("Доступно только администраторам");
}
const formData = await request.formData();
const itemId = formData.get("itemId");
if (itemId === null) {
throw new Error("Не предоставлены данные создания предмета");
}
await deleteStudyItem(parseInt(itemId.toString()));
response.ok = true;
} catch (e: any) {
response.ok = false;
if (e instanceof Prisma.PrismaClientKnownRequestError) {
response.reason = `Неизвестная ошибка базы данных. Код ${e.code}`;
} else if (e instanceof Error) {
response.reason = e.message.trim();
} else {
response.reason = e.toString().trim();
}
}
return {
body: JSON.stringify(response),
};
}

View file

@ -0,0 +1,44 @@
import type { APIContext } from "astro";
import { getSessionUser, updateUserTimetable, UpdateTTElementModel } from "../../db";
import { Prisma } from "@prisma/client";
type UpdateTTModel = {
login: string;
odd: UpdateTTElementModel[][];
even: UpdateTTElementModel[][];
};
export async function post({ request, cookies }: APIContext) {
const response: { ok: boolean; reason?: string } = {
ok: true,
};
try {
const sessId = cookies.get("session").value!;
const user = (await getSessionUser(sessId))!;
if (!user.is_admin) {
throw new Error("Доступно только администраторам");
}
const data: UpdateTTModel = await request.json();
if (data === null || data.login === null || data.odd === null || data.even === null) {
throw new Error("Не предоставлены данные обновления расписания");
}
await updateUserTimetable(data.login, data.odd, data.even);
response.ok = true;
} catch (e: any) {
response.ok = false;
if (e instanceof Prisma.PrismaClientKnownRequestError) {
response.reason = `Неизвестная ошибка базы данных. Код ${e.code}`;
} else if (e instanceof Error) {
response.reason = e.message.trim();
} else {
response.reason = e.toString().trim();
}
}
return {
body: JSON.stringify(response),
};
}