@studious-lms/server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE.txt +8 -0
  2. package/README.md +143 -0
  3. package/dist/exportType.d.ts +9 -0
  4. package/dist/exportType.d.ts.map +1 -0
  5. package/dist/exportType.js +7 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +82 -0
  9. package/dist/lib/fileUpload.d.ts +38 -0
  10. package/dist/lib/fileUpload.d.ts.map +1 -0
  11. package/dist/lib/fileUpload.js +136 -0
  12. package/dist/lib/googleCloudStorage.d.ts +20 -0
  13. package/dist/lib/googleCloudStorage.d.ts.map +1 -0
  14. package/dist/lib/googleCloudStorage.js +88 -0
  15. package/dist/lib/prisma.d.ts +8 -0
  16. package/dist/lib/prisma.d.ts.map +1 -0
  17. package/dist/lib/prisma.js +11 -0
  18. package/dist/lib/thumbnailGenerator.d.ts +23 -0
  19. package/dist/lib/thumbnailGenerator.d.ts.map +1 -0
  20. package/dist/lib/thumbnailGenerator.js +180 -0
  21. package/dist/logger.d.ts +26 -0
  22. package/dist/logger.d.ts.map +1 -0
  23. package/dist/logger.js +135 -0
  24. package/dist/middleware/auth.d.ts +7 -0
  25. package/dist/middleware/auth.d.ts.map +1 -0
  26. package/dist/middleware/auth.js +170 -0
  27. package/dist/middleware/logging.d.ts +2 -0
  28. package/dist/middleware/logging.d.ts.map +1 -0
  29. package/dist/middleware/logging.js +51 -0
  30. package/dist/routers/_app.d.ts +4369 -0
  31. package/dist/routers/_app.d.ts.map +1 -0
  32. package/dist/routers/_app.js +29 -0
  33. package/dist/routers/agenda.d.ts +66 -0
  34. package/dist/routers/agenda.d.ts.map +1 -0
  35. package/dist/routers/agenda.js +78 -0
  36. package/dist/routers/announcement.d.ts +79 -0
  37. package/dist/routers/announcement.d.ts.map +1 -0
  38. package/dist/routers/announcement.js +122 -0
  39. package/dist/routers/assignment.d.ts +1051 -0
  40. package/dist/routers/assignment.d.ts.map +1 -0
  41. package/dist/routers/assignment.js +1497 -0
  42. package/dist/routers/attendance.d.ts +99 -0
  43. package/dist/routers/attendance.d.ts.map +1 -0
  44. package/dist/routers/attendance.js +269 -0
  45. package/dist/routers/auth.d.ts +87 -0
  46. package/dist/routers/auth.d.ts.map +1 -0
  47. package/dist/routers/auth.js +255 -0
  48. package/dist/routers/class.d.ts +427 -0
  49. package/dist/routers/class.d.ts.map +1 -0
  50. package/dist/routers/class.js +693 -0
  51. package/dist/routers/event.d.ts +249 -0
  52. package/dist/routers/event.d.ts.map +1 -0
  53. package/dist/routers/event.js +467 -0
  54. package/dist/routers/file.d.ts +27 -0
  55. package/dist/routers/file.d.ts.map +1 -0
  56. package/dist/routers/file.js +88 -0
  57. package/dist/routers/section.d.ts +51 -0
  58. package/dist/routers/section.d.ts.map +1 -0
  59. package/dist/routers/section.js +123 -0
  60. package/dist/routers/user.d.ts +49 -0
  61. package/dist/routers/user.d.ts.map +1 -0
  62. package/dist/routers/user.js +74 -0
  63. package/dist/socket/handlers.d.ts +3 -0
  64. package/dist/socket/handlers.d.ts.map +1 -0
  65. package/dist/socket/handlers.js +130 -0
  66. package/dist/trpc.d.ts +147 -0
  67. package/dist/trpc.d.ts.map +1 -0
  68. package/dist/trpc.js +67 -0
  69. package/dist/types/trpc.d.ts +16 -0
  70. package/dist/types/trpc.d.ts.map +1 -0
  71. package/dist/types/trpc.js +2 -0
  72. package/dist/utils/email.d.ts +3 -0
  73. package/dist/utils/email.d.ts.map +1 -0
  74. package/dist/utils/email.js +16 -0
  75. package/dist/utils/generateInviteCode.d.ts +6 -0
  76. package/dist/utils/generateInviteCode.d.ts.map +1 -0
  77. package/dist/utils/generateInviteCode.js +11 -0
  78. package/dist/utils/logger.d.ts +27 -0
  79. package/dist/utils/logger.d.ts.map +1 -0
  80. package/dist/utils/logger.js +124 -0
  81. package/generated/prisma/client.d.ts +1 -0
  82. package/generated/prisma/client.js +4 -0
  83. package/generated/prisma/default.d.ts +1 -0
  84. package/generated/prisma/default.js +4 -0
  85. package/generated/prisma/edge.d.ts +1 -0
  86. package/generated/prisma/edge.js +389 -0
  87. package/generated/prisma/index-browser.js +375 -0
  88. package/generated/prisma/index.d.ts +34865 -0
  89. package/generated/prisma/index.js +410 -0
  90. package/generated/prisma/libquery_engine-darwin-arm64.dylib.node +0 -0
  91. package/generated/prisma/package.json +140 -0
  92. package/generated/prisma/runtime/edge-esm.js +34 -0
  93. package/generated/prisma/runtime/edge.js +34 -0
  94. package/generated/prisma/runtime/index-browser.d.ts +370 -0
  95. package/generated/prisma/runtime/index-browser.js +16 -0
  96. package/generated/prisma/runtime/library.d.ts +3647 -0
  97. package/generated/prisma/runtime/library.js +146 -0
  98. package/generated/prisma/runtime/react-native.js +83 -0
  99. package/generated/prisma/runtime/wasm.js +35 -0
  100. package/generated/prisma/schema.prisma +304 -0
  101. package/generated/prisma/wasm.d.ts +1 -0
  102. package/generated/prisma/wasm.js +375 -0
  103. package/package.json +46 -0
@@ -0,0 +1,693 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classRouter = void 0;
4
+ const zod_1 = require("zod");
5
+ const trpc_1 = require("../trpc");
6
+ const prisma_1 = require("@lib/prisma");
7
+ const server_1 = require("@trpc/server");
8
+ const generateInviteCode_1 = require("@/utils/generateInviteCode");
9
+ exports.classRouter = (0, trpc_1.createTRPCRouter)({
10
+ getAll: trpc_1.protectedProcedure
11
+ .query(async ({ ctx }) => {
12
+ const [teacherClasses, studentClasses] = await Promise.all([
13
+ prisma_1.prisma.class.findMany({
14
+ where: {
15
+ teachers: {
16
+ some: {
17
+ id: ctx.user?.id,
18
+ },
19
+ },
20
+ },
21
+ include: {
22
+ assignments: {
23
+ where: {
24
+ dueDate: {
25
+ equals: new Date(new Date().setHours(0, 0, 0, 0)),
26
+ },
27
+ },
28
+ select: {
29
+ id: true,
30
+ title: true,
31
+ },
32
+ },
33
+ },
34
+ }),
35
+ prisma_1.prisma.class.findMany({
36
+ where: {
37
+ students: {
38
+ some: {
39
+ id: ctx.user?.id,
40
+ },
41
+ },
42
+ },
43
+ include: {
44
+ assignments: {
45
+ where: {
46
+ dueDate: {
47
+ equals: new Date(new Date().setHours(0, 0, 0, 0)),
48
+ },
49
+ },
50
+ select: {
51
+ id: true,
52
+ title: true,
53
+ },
54
+ },
55
+ },
56
+ }),
57
+ ]);
58
+ const adminClasses = await prisma_1.prisma.class.findMany({
59
+ where: {
60
+ teachers: {
61
+ some: {
62
+ id: ctx.user?.id,
63
+ },
64
+ },
65
+ },
66
+ include: {
67
+ assignments: {
68
+ where: {
69
+ dueDate: {
70
+ equals: new Date(new Date().setHours(0, 0, 0, 0)),
71
+ },
72
+ },
73
+ select: {
74
+ id: true,
75
+ title: true,
76
+ },
77
+ },
78
+ },
79
+ });
80
+ return {
81
+ teacherInClass: teacherClasses.map(cls => ({
82
+ id: cls.id,
83
+ name: cls.name,
84
+ section: cls.section,
85
+ subject: cls.subject,
86
+ dueToday: cls.assignments,
87
+ color: cls.color,
88
+ })),
89
+ studentInClass: studentClasses.map(cls => ({
90
+ id: cls.id,
91
+ name: cls.name,
92
+ section: cls.section,
93
+ subject: cls.subject,
94
+ dueToday: cls.assignments,
95
+ color: cls.color,
96
+ })),
97
+ adminInClass: adminClasses.map(cls => ({
98
+ id: cls.id,
99
+ name: cls.name,
100
+ section: cls.section,
101
+ subject: cls.subject,
102
+ dueToday: cls.assignments,
103
+ color: cls.color,
104
+ })),
105
+ };
106
+ }),
107
+ get: trpc_1.protectedProcedure
108
+ .input(zod_1.z.object({
109
+ classId: zod_1.z.string(),
110
+ }))
111
+ .query(async ({ ctx, input }) => {
112
+ const { classId } = input;
113
+ const classData = await prisma_1.prisma.class.findUnique({
114
+ where: {
115
+ id: classId,
116
+ },
117
+ include: {
118
+ teachers: {
119
+ select: {
120
+ id: true,
121
+ username: true,
122
+ },
123
+ },
124
+ students: {
125
+ select: {
126
+ id: true,
127
+ username: true,
128
+ },
129
+ },
130
+ announcements: {
131
+ orderBy: {
132
+ createdAt: 'desc',
133
+ },
134
+ select: {
135
+ id: true,
136
+ remarks: true,
137
+ createdAt: true,
138
+ teacher: {
139
+ select: {
140
+ id: true,
141
+ username: true,
142
+ },
143
+ },
144
+ },
145
+ },
146
+ assignments: {
147
+ select: {
148
+ type: true,
149
+ id: true,
150
+ title: true,
151
+ dueDate: true,
152
+ createdAt: true,
153
+ weight: true,
154
+ graded: true,
155
+ maxGrade: true,
156
+ instructions: true,
157
+ section: {
158
+ select: {
159
+ id: true,
160
+ name: true,
161
+ },
162
+ },
163
+ markScheme: {
164
+ select: {
165
+ id: true,
166
+ structured: true,
167
+ },
168
+ },
169
+ gradingBoundary: {
170
+ select: {
171
+ id: true,
172
+ structured: true,
173
+ },
174
+ },
175
+ submissions: {
176
+ where: {
177
+ studentId: ctx.user?.id,
178
+ },
179
+ select: {
180
+ studentId: true,
181
+ id: true,
182
+ submitted: true,
183
+ returned: true,
184
+ submittedAt: true,
185
+ },
186
+ },
187
+ },
188
+ },
189
+ },
190
+ });
191
+ const sections = await prisma_1.prisma.section.findMany({
192
+ where: {
193
+ classId: classId,
194
+ },
195
+ });
196
+ if (!classData) {
197
+ throw new Error('Class not found');
198
+ }
199
+ return {
200
+ class: {
201
+ ...classData,
202
+ assignments: classData.assignments.map(assignment => ({
203
+ ...assignment,
204
+ late: assignment.dueDate < new Date(),
205
+ submitted: assignment.submissions.some(submission => submission.studentId === ctx.user?.id),
206
+ returned: assignment.submissions.some(submission => submission.studentId === ctx.user?.id && submission.returned),
207
+ })),
208
+ sections,
209
+ },
210
+ };
211
+ }),
212
+ update: trpc_1.protectedTeacherProcedure
213
+ .input(zod_1.z.object({
214
+ classId: zod_1.z.string(),
215
+ name: zod_1.z.string().optional(),
216
+ section: zod_1.z.string().optional(),
217
+ subject: zod_1.z.string().optional(),
218
+ }))
219
+ .mutation(async ({ ctx, input }) => {
220
+ const { classId, ...updateData } = input;
221
+ const updatedClass = await prisma_1.prisma.class.update({
222
+ where: {
223
+ id: classId,
224
+ },
225
+ data: updateData,
226
+ select: {
227
+ id: true,
228
+ name: true,
229
+ section: true,
230
+ subject: true,
231
+ }
232
+ });
233
+ return {
234
+ updatedClass,
235
+ };
236
+ }),
237
+ create: trpc_1.protectedProcedure
238
+ .input(zod_1.z.object({
239
+ students: zod_1.z.array(zod_1.z.string()).optional(),
240
+ teachers: zod_1.z.array(zod_1.z.string()).optional(),
241
+ name: zod_1.z.string(),
242
+ section: zod_1.z.string(),
243
+ subject: zod_1.z.string(),
244
+ }))
245
+ .mutation(async ({ ctx, input }) => {
246
+ const { students, teachers, name, section, subject } = input;
247
+ if (teachers && teachers.length > 0 && students && students.length > 0) {
248
+ const newClass = await prisma_1.prisma.class.create({
249
+ data: {
250
+ name,
251
+ section,
252
+ subject,
253
+ teachers: {
254
+ connect: teachers.map(teacher => ({ id: teacher })),
255
+ },
256
+ students: {
257
+ connect: students.map(student => ({ id: student })),
258
+ },
259
+ },
260
+ include: {
261
+ teachers: true,
262
+ students: true,
263
+ },
264
+ });
265
+ return newClass;
266
+ }
267
+ const newClass = await prisma_1.prisma.class.create({
268
+ data: {
269
+ name,
270
+ section,
271
+ subject,
272
+ teachers: {
273
+ connect: {
274
+ id: ctx.user?.id,
275
+ },
276
+ },
277
+ },
278
+ });
279
+ return newClass;
280
+ }),
281
+ delete: trpc_1.protectedTeacherProcedure
282
+ .input(zod_1.z.object({
283
+ classId: zod_1.z.string(),
284
+ id: zod_1.z.string(),
285
+ }))
286
+ .mutation(async ({ ctx, input }) => {
287
+ // Verify user is the teacher of this class
288
+ const classToDelete = await prisma_1.prisma.class.findFirst({
289
+ where: {
290
+ id: input.id,
291
+ },
292
+ });
293
+ if (!classToDelete) {
294
+ throw new Error("Class not found or you don't have permission to delete it");
295
+ }
296
+ await prisma_1.prisma.class.delete({
297
+ where: {
298
+ id: input.id,
299
+ },
300
+ });
301
+ return {
302
+ deletedClass: {
303
+ id: input.id,
304
+ }
305
+ };
306
+ }),
307
+ addStudent: trpc_1.protectedTeacherProcedure
308
+ .input(zod_1.z.object({
309
+ classId: zod_1.z.string(),
310
+ studentId: zod_1.z.string(),
311
+ }))
312
+ .mutation(async ({ ctx, input }) => {
313
+ const { classId, studentId } = input;
314
+ const student = await prisma_1.prisma.user.findUnique({
315
+ where: {
316
+ id: studentId,
317
+ },
318
+ });
319
+ if (!student) {
320
+ throw new Error("Student not found");
321
+ }
322
+ const updatedClass = await prisma_1.prisma.class.update({
323
+ where: {
324
+ id: classId,
325
+ },
326
+ data: {
327
+ students: {
328
+ connect: {
329
+ id: studentId,
330
+ },
331
+ },
332
+ },
333
+ select: {
334
+ id: true,
335
+ name: true,
336
+ section: true,
337
+ subject: true,
338
+ }
339
+ });
340
+ return {
341
+ updatedClass,
342
+ newStudent: student,
343
+ };
344
+ }),
345
+ changeRole: trpc_1.protectedTeacherProcedure
346
+ .input(zod_1.z.object({
347
+ classId: zod_1.z.string(),
348
+ userId: zod_1.z.string(),
349
+ type: zod_1.z.enum(['teacher', 'student']),
350
+ }))
351
+ .mutation(async ({ ctx, input }) => {
352
+ const { classId, userId, type } = input;
353
+ const user = await prisma_1.prisma.user.findUnique({
354
+ where: { id: userId },
355
+ select: {
356
+ id: true,
357
+ username: true,
358
+ },
359
+ });
360
+ if (!user) {
361
+ throw new Error("User not found");
362
+ }
363
+ const updatedClass = await prisma_1.prisma.class.update({
364
+ where: { id: classId },
365
+ data: {
366
+ [type === 'teacher' ? 'teachers' : 'students']: {
367
+ connect: { id: userId },
368
+ },
369
+ [type === 'teacher' ? 'students' : 'teachers']: {
370
+ disconnect: { id: userId },
371
+ },
372
+ },
373
+ });
374
+ return {
375
+ updatedClass,
376
+ user: {
377
+ ...user,
378
+ type,
379
+ },
380
+ };
381
+ }),
382
+ removeMember: trpc_1.protectedTeacherProcedure
383
+ .input(zod_1.z.object({
384
+ classId: zod_1.z.string(),
385
+ userId: zod_1.z.string(),
386
+ }))
387
+ .mutation(async ({ ctx, input }) => {
388
+ const { classId, userId } = input;
389
+ const updatedClass = await prisma_1.prisma.class.update({
390
+ where: { id: classId },
391
+ data: {
392
+ teachers: {
393
+ disconnect: { id: userId },
394
+ },
395
+ students: {
396
+ disconnect: { id: userId },
397
+ },
398
+ },
399
+ });
400
+ return {
401
+ updatedClass,
402
+ removedUserId: userId,
403
+ };
404
+ }),
405
+ join: trpc_1.protectedProcedure
406
+ .input(zod_1.z.object({
407
+ classCode: zod_1.z.string(),
408
+ }))
409
+ .mutation(async ({ ctx, input }) => {
410
+ const { classCode } = input;
411
+ const session = await prisma_1.prisma.session.findFirst({
412
+ where: {
413
+ id: classCode,
414
+ },
415
+ });
416
+ if (!session || !session.classId) {
417
+ throw new Error("Class not found");
418
+ }
419
+ if (session.expiresAt && session.expiresAt < new Date()) {
420
+ throw new Error("Session expired");
421
+ }
422
+ const updatedClass = await prisma_1.prisma.class.update({
423
+ where: { id: session.classId },
424
+ data: {
425
+ students: {
426
+ connect: { id: ctx.user?.id },
427
+ },
428
+ },
429
+ select: {
430
+ id: true,
431
+ name: true,
432
+ section: true,
433
+ subject: true,
434
+ },
435
+ });
436
+ return {
437
+ joinedClass: updatedClass,
438
+ };
439
+ }),
440
+ getInviteCode: trpc_1.protectedTeacherProcedure
441
+ .input(zod_1.z.object({
442
+ classId: zod_1.z.string(),
443
+ }))
444
+ .query(async ({ ctx, input }) => {
445
+ const { classId } = input;
446
+ const session = await prisma_1.prisma.session.findFirst({
447
+ where: {
448
+ classId,
449
+ },
450
+ });
451
+ if ((session?.expiresAt && session.expiresAt < new Date()) || !session) {
452
+ const newSession = await prisma_1.prisma.session.create({
453
+ data: {
454
+ id: (0, generateInviteCode_1.generateInviteCode)(),
455
+ classId,
456
+ expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours from now
457
+ }
458
+ });
459
+ return {
460
+ code: newSession.id,
461
+ };
462
+ }
463
+ return {
464
+ code: session?.id,
465
+ };
466
+ }),
467
+ createInviteCode: trpc_1.protectedTeacherProcedure
468
+ .input(zod_1.z.object({
469
+ classId: zod_1.z.string(),
470
+ }))
471
+ .mutation(async ({ ctx, input }) => {
472
+ const { classId } = input;
473
+ // Create a new session for the invite code
474
+ const session = await prisma_1.prisma.session.create({
475
+ data: {
476
+ id: (0, generateInviteCode_1.generateInviteCode)(),
477
+ classId,
478
+ expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours from now
479
+ }
480
+ });
481
+ return {
482
+ code: session.id,
483
+ };
484
+ }),
485
+ getGrades: trpc_1.protectedClassMemberProcedure
486
+ .input(zod_1.z.object({
487
+ classId: zod_1.z.string(),
488
+ userId: zod_1.z.string(),
489
+ }))
490
+ .query(async ({ ctx, input }) => {
491
+ const { classId, userId } = input;
492
+ const isTeacher = await prisma_1.prisma.class.findFirst({
493
+ where: {
494
+ id: classId,
495
+ teachers: {
496
+ some: { id: ctx.user?.id }
497
+ }
498
+ }
499
+ });
500
+ // If student, only allow viewing their own grades
501
+ if (ctx.user?.id !== userId && !isTeacher) {
502
+ throw new server_1.TRPCError({
503
+ code: 'UNAUTHORIZED',
504
+ message: 'You can only view your own grades',
505
+ });
506
+ }
507
+ const grades = await prisma_1.prisma.submission.findMany({
508
+ where: {
509
+ studentId: userId,
510
+ assignment: {
511
+ classId: classId,
512
+ graded: true
513
+ }
514
+ },
515
+ include: {
516
+ assignment: {
517
+ select: {
518
+ id: true,
519
+ title: true,
520
+ maxGrade: true,
521
+ weight: true,
522
+ }
523
+ },
524
+ }
525
+ });
526
+ return {
527
+ grades,
528
+ };
529
+ }),
530
+ updateGrade: trpc_1.protectedTeacherProcedure
531
+ .input(zod_1.z.object({
532
+ classId: zod_1.z.string(),
533
+ assignmentId: zod_1.z.string(),
534
+ submissionId: zod_1.z.string(),
535
+ gradeReceived: zod_1.z.number().nullable(),
536
+ }))
537
+ .mutation(async ({ ctx, input }) => {
538
+ const { classId, assignmentId, submissionId, gradeReceived } = input;
539
+ // Update the grade
540
+ const updatedSubmission = await prisma_1.prisma.submission.update({
541
+ where: {
542
+ id: submissionId,
543
+ assignmentId: assignmentId,
544
+ },
545
+ data: {
546
+ gradeReceived,
547
+ },
548
+ include: {
549
+ assignment: {
550
+ select: {
551
+ id: true,
552
+ title: true,
553
+ maxGrade: true,
554
+ weight: true,
555
+ }
556
+ }
557
+ }
558
+ });
559
+ return updatedSubmission;
560
+ }),
561
+ getEvents: trpc_1.protectedTeacherProcedure
562
+ .input(zod_1.z.object({
563
+ classId: zod_1.z.string(),
564
+ }))
565
+ .query(async ({ ctx, input }) => {
566
+ const { classId } = input;
567
+ const events = await prisma_1.prisma.event.findMany({
568
+ where: {
569
+ class: {
570
+ id: classId,
571
+ }
572
+ },
573
+ select: {
574
+ name: true,
575
+ startTime: true,
576
+ endTime: true,
577
+ }
578
+ });
579
+ return events;
580
+ }),
581
+ listMarkSchemes: trpc_1.protectedTeacherProcedure
582
+ .input(zod_1.z.object({
583
+ classId: zod_1.z.string(),
584
+ }))
585
+ .query(async ({ ctx, input }) => {
586
+ const { classId } = input;
587
+ const markSchemes = await prisma_1.prisma.markScheme.findMany({
588
+ where: {
589
+ classId: classId,
590
+ },
591
+ });
592
+ return markSchemes;
593
+ }),
594
+ createMarkScheme: trpc_1.protectedTeacherProcedure
595
+ .input(zod_1.z.object({
596
+ classId: zod_1.z.string(),
597
+ structure: zod_1.z.string(),
598
+ }))
599
+ .mutation(async ({ ctx, input }) => {
600
+ const { classId, structure } = input;
601
+ const validatedStructure = structure.replace(/\\n/g, '\n');
602
+ const markScheme = await prisma_1.prisma.markScheme.create({
603
+ data: {
604
+ classId: classId,
605
+ structured: validatedStructure,
606
+ },
607
+ });
608
+ return markScheme;
609
+ }),
610
+ updateMarkScheme: trpc_1.protectedTeacherProcedure
611
+ .input(zod_1.z.object({
612
+ classId: zod_1.z.string(),
613
+ markSchemeId: zod_1.z.string(),
614
+ structure: zod_1.z.string(),
615
+ }))
616
+ .mutation(async ({ ctx, input }) => {
617
+ const { classId, markSchemeId, structure } = input;
618
+ const validatedStructure = structure.replace(/\\n/g, '\n');
619
+ const markScheme = await prisma_1.prisma.markScheme.update({
620
+ where: { id: markSchemeId },
621
+ data: { structured: validatedStructure },
622
+ });
623
+ return markScheme;
624
+ }),
625
+ deleteMarkScheme: trpc_1.protectedTeacherProcedure
626
+ .input(zod_1.z.object({
627
+ classId: zod_1.z.string(),
628
+ markSchemeId: zod_1.z.string(),
629
+ }))
630
+ .mutation(async ({ ctx, input }) => {
631
+ const { classId, markSchemeId } = input;
632
+ const markScheme = await prisma_1.prisma.markScheme.delete({
633
+ where: { id: markSchemeId },
634
+ });
635
+ return markScheme;
636
+ }),
637
+ listGradingBoundaries: trpc_1.protectedTeacherProcedure
638
+ .input(zod_1.z.object({
639
+ classId: zod_1.z.string(),
640
+ }))
641
+ .query(async ({ ctx, input }) => {
642
+ const { classId } = input;
643
+ const gradingBoundaries = await prisma_1.prisma.gradingBoundary.findMany({
644
+ where: {
645
+ classId: classId,
646
+ },
647
+ });
648
+ return gradingBoundaries;
649
+ }),
650
+ createGradingBoundary: trpc_1.protectedTeacherProcedure
651
+ .input(zod_1.z.object({
652
+ classId: zod_1.z.string(),
653
+ structure: zod_1.z.string(),
654
+ }))
655
+ .mutation(async ({ ctx, input }) => {
656
+ const { classId, structure } = input;
657
+ const validatedStructure = structure.replace(/\\n/g, '\n');
658
+ const gradingBoundary = await prisma_1.prisma.gradingBoundary.create({
659
+ data: {
660
+ classId: classId,
661
+ structured: validatedStructure,
662
+ },
663
+ });
664
+ return gradingBoundary;
665
+ }),
666
+ updateGradingBoundary: trpc_1.protectedTeacherProcedure
667
+ .input(zod_1.z.object({
668
+ classId: zod_1.z.string(),
669
+ gradingBoundaryId: zod_1.z.string(),
670
+ structure: zod_1.z.string(),
671
+ }))
672
+ .mutation(async ({ ctx, input }) => {
673
+ const { classId, gradingBoundaryId, structure } = input;
674
+ const validatedStructure = structure.replace(/\\n/g, '\n');
675
+ const gradingBoundary = await prisma_1.prisma.gradingBoundary.update({
676
+ where: { id: gradingBoundaryId },
677
+ data: { structured: validatedStructure },
678
+ });
679
+ return gradingBoundary;
680
+ }),
681
+ deleteGradingBoundary: trpc_1.protectedTeacherProcedure
682
+ .input(zod_1.z.object({
683
+ classId: zod_1.z.string(),
684
+ gradingBoundaryId: zod_1.z.string(),
685
+ }))
686
+ .mutation(async ({ ctx, input }) => {
687
+ const { classId, gradingBoundaryId } = input;
688
+ const gradingBoundary = await prisma_1.prisma.gradingBoundary.delete({
689
+ where: { id: gradingBoundaryId },
690
+ });
691
+ return gradingBoundary;
692
+ }),
693
+ });