@studious-lms/server 1.2.46 → 1.2.48
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.
- package/dist/index.js +22 -18
- package/dist/index.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +3 -2
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/security.d.ts.map +1 -1
- package/dist/middleware/security.js +4 -4
- package/dist/middleware/security.js.map +1 -1
- package/dist/routers/_app.d.ts +126 -26
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/assignment.d.ts +10 -0
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +18 -3
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/class.d.ts +18 -0
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +56 -2
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/conversation.d.ts +1 -0
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/labChat.d.ts +1 -0
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +5 -321
- package/dist/routers/labChat.js.map +1 -1
- package/dist/routers/message.d.ts +1 -0
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/message.js +3 -2
- package/dist/routers/message.js.map +1 -1
- package/dist/routers/newtonChat.d.ts.map +1 -1
- package/dist/routers/newtonChat.js +6 -183
- package/dist/routers/newtonChat.js.map +1 -1
- package/dist/routers/section.d.ts +10 -0
- package/dist/routers/section.d.ts.map +1 -1
- package/dist/routers/section.js +21 -3
- package/dist/routers/section.js.map +1 -1
- package/dist/routers/worksheet.d.ts +22 -13
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +16 -3
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/seedDatabase.d.ts.map +1 -1
- package/dist/seedDatabase.js +34 -8
- package/dist/seedDatabase.js.map +1 -1
- package/dist/server/pipelines/aiLabChat.d.ts +12 -1
- package/dist/server/pipelines/aiLabChat.d.ts.map +1 -1
- package/dist/server/pipelines/aiLabChat.js +388 -15
- package/dist/server/pipelines/aiLabChat.js.map +1 -1
- package/dist/server/pipelines/aiNewtonChat.d.ts +30 -0
- package/dist/server/pipelines/aiNewtonChat.d.ts.map +1 -0
- package/dist/server/pipelines/aiNewtonChat.js +280 -0
- package/dist/server/pipelines/aiNewtonChat.js.map +1 -0
- package/dist/server/pipelines/gradeWorksheet.d.ts +14 -1
- package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -1
- package/dist/server/pipelines/gradeWorksheet.js +6 -5
- package/dist/server/pipelines/gradeWorksheet.js.map +1 -1
- package/dist/utils/inference.d.ts +3 -1
- package/dist/utils/inference.d.ts.map +1 -1
- package/dist/utils/inference.js +34 -4
- package/dist/utils/inference.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +2 -0
- package/src/index.ts +24 -22
- package/src/middleware/auth.ts +1 -0
- package/src/middleware/security.ts +2 -2
- package/src/routers/assignment.ts +17 -2
- package/src/routers/class.ts +55 -0
- package/src/routers/labChat.ts +3 -366
- package/src/routers/message.ts +1 -1
- package/src/routers/newtonChat.ts +8 -231
- package/src/routers/section.ts +21 -1
- package/src/routers/worksheet.ts +17 -1
- package/src/seedDatabase.ts +38 -6
- package/src/server/pipelines/aiLabChat.ts +434 -19
- package/src/server/pipelines/aiNewtonChat.ts +338 -0
- package/src/server/pipelines/gradeWorksheet.ts +3 -4
- package/src/utils/inference.ts +40 -5
|
@@ -3,13 +3,9 @@ import { createTRPCRouter, protectedProcedure } from '../trpc.js';
|
|
|
3
3
|
import { prisma } from '../lib/prisma.js';
|
|
4
4
|
import { pusher } from '../lib/pusher.js';
|
|
5
5
|
import { TRPCError } from '@trpc/server';
|
|
6
|
-
import {
|
|
7
|
-
inferenceClient,
|
|
8
|
-
openAIClient,
|
|
9
|
-
sendAIMessage,
|
|
10
|
-
} from '../utils/inference.js';
|
|
11
6
|
import { logger } from '../utils/logger.js';
|
|
12
7
|
import { isAIUser } from '../utils/aiUser.js';
|
|
8
|
+
import { generateAndSendNewtonIntroduction, generateAndSendNewtonResponse } from '../server/pipelines/aiNewtonChat.js';
|
|
13
9
|
|
|
14
10
|
export const newtonChatRouter = createTRPCRouter({
|
|
15
11
|
getTutorConversation: protectedProcedure
|
|
@@ -124,19 +120,17 @@ export const newtonChatRouter = createTRPCRouter({
|
|
|
124
120
|
title: 'Session with Newton Tutor',
|
|
125
121
|
},
|
|
126
122
|
});
|
|
123
|
+
generateAndSendNewtonIntroduction(
|
|
124
|
+
newtonChat.id,
|
|
125
|
+
newtonChat.conversationId,
|
|
126
|
+
submission.id
|
|
127
|
+
).catch(error => {
|
|
128
|
+
logger.error('Failed to generate AI introduction:', { error, newtonChatId: result.id });
|
|
129
|
+
});
|
|
127
130
|
|
|
128
131
|
return newtonChat;
|
|
129
132
|
});
|
|
130
133
|
|
|
131
|
-
// Generate AI introduction message in parallel (don't await - fire and forget)
|
|
132
|
-
generateAndSendNewtonIntroduction(
|
|
133
|
-
result.id,
|
|
134
|
-
result.conversationId,
|
|
135
|
-
submission.id
|
|
136
|
-
).catch(error => {
|
|
137
|
-
logger.error('Failed to generate AI introduction:', { error, newtonChatId: result.id });
|
|
138
|
-
});
|
|
139
|
-
|
|
140
134
|
return {
|
|
141
135
|
conversationId: result.conversationId,
|
|
142
136
|
newtonChatId: result.id,
|
|
@@ -300,221 +294,4 @@ export const newtonChatRouter = createTRPCRouter({
|
|
|
300
294
|
}),
|
|
301
295
|
});
|
|
302
296
|
|
|
303
|
-
/**
|
|
304
|
-
* Generate and send AI introduction for Newton chat
|
|
305
|
-
*/
|
|
306
|
-
async function generateAndSendNewtonIntroduction(
|
|
307
|
-
newtonChatId: string,
|
|
308
|
-
conversationId: string,
|
|
309
|
-
submissionId: string
|
|
310
|
-
): Promise<void> {
|
|
311
|
-
try {
|
|
312
|
-
// Get submission details for context
|
|
313
|
-
const submission = await prisma.submission.findUnique({
|
|
314
|
-
where: { id: submissionId },
|
|
315
|
-
include: {
|
|
316
|
-
assignment: {
|
|
317
|
-
select: {
|
|
318
|
-
title: true,
|
|
319
|
-
instructions: true,
|
|
320
|
-
class: {
|
|
321
|
-
select: {
|
|
322
|
-
subject: true,
|
|
323
|
-
name: true,
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
attachments: {
|
|
329
|
-
select: {
|
|
330
|
-
id: true,
|
|
331
|
-
name: true,
|
|
332
|
-
type: true,
|
|
333
|
-
},
|
|
334
|
-
},
|
|
335
|
-
},
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
if (!submission) {
|
|
339
|
-
throw new Error('Submission not found');
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const systemPrompt = `You are Newton, an AI tutor helping a student with their assignment submission.
|
|
343
|
-
|
|
344
|
-
Assignment: ${submission.assignment.title}
|
|
345
|
-
Subject: ${submission.assignment.class.subject}
|
|
346
|
-
Instructions: ${submission.assignment.instructions || 'No specific instructions provided'}
|
|
347
|
-
|
|
348
|
-
Your role:
|
|
349
|
-
- Help the student understand concepts related to their assignment
|
|
350
|
-
- Provide guidance and explanations without giving away direct answers
|
|
351
|
-
- Encourage learning and critical thinking
|
|
352
|
-
- Be supportive and encouraging
|
|
353
|
-
- Use clear, educational language appropriate for the subject
|
|
354
|
-
|
|
355
|
-
Do not use markdown formatting in your responses - use plain text only.`;
|
|
356
|
-
|
|
357
|
-
const completion = await inferenceClient.chat.completions.create({
|
|
358
|
-
model: 'command-a-03-2025',
|
|
359
|
-
messages: [
|
|
360
|
-
{ role: 'system', content: systemPrompt },
|
|
361
|
-
{
|
|
362
|
-
role: 'user',
|
|
363
|
-
content: 'Please introduce yourself to the student. Explain that you are Newton, their AI tutor, and you are here to help them with their assignment. Ask them what they would like help with.'
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
max_tokens: 300,
|
|
367
|
-
temperature: 0.8,
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
const response = completion.choices[0]?.message?.content;
|
|
371
|
-
|
|
372
|
-
if (!response) {
|
|
373
|
-
throw new Error('No response generated from inference API');
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Send AI introduction using centralized sender
|
|
377
|
-
await sendAIMessage(response, conversationId, {
|
|
378
|
-
subject: submission.assignment.class.subject || 'Assignment',
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
logger.info('AI Introduction sent', { newtonChatId, conversationId });
|
|
382
|
-
|
|
383
|
-
} catch (error) {
|
|
384
|
-
logger.error('Failed to generate AI introduction:', { error, newtonChatId });
|
|
385
|
-
|
|
386
|
-
// Send fallback introduction
|
|
387
|
-
try {
|
|
388
|
-
const fallbackIntro = `Hello! I'm Newton, your AI tutor. I'm here to help you with your assignment. I can answer questions, explain concepts, and guide you through your work. What would you like help with today?`;
|
|
389
|
-
|
|
390
|
-
await sendAIMessage(fallbackIntro, conversationId, {
|
|
391
|
-
subject: 'Assignment',
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
logger.info('Fallback AI introduction sent', { newtonChatId });
|
|
395
|
-
|
|
396
|
-
} catch (fallbackError) {
|
|
397
|
-
logger.error('Failed to send fallback AI introduction:', { error: fallbackError, newtonChatId });
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Generate and send AI response to student message
|
|
404
|
-
*/
|
|
405
|
-
async function generateAndSendNewtonResponse(
|
|
406
|
-
newtonChatId: string,
|
|
407
|
-
studentMessage: string,
|
|
408
|
-
conversationId: string,
|
|
409
|
-
submission: {
|
|
410
|
-
id: string;
|
|
411
|
-
assignment: {
|
|
412
|
-
id: string;
|
|
413
|
-
title: string;
|
|
414
|
-
instructions: string | null;
|
|
415
|
-
class: {
|
|
416
|
-
subject: string | null;
|
|
417
|
-
};
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
): Promise<void> {
|
|
421
|
-
try {
|
|
422
|
-
// Get recent conversation history
|
|
423
|
-
const recentMessages = await prisma.message.findMany({
|
|
424
|
-
where: {
|
|
425
|
-
conversationId,
|
|
426
|
-
},
|
|
427
|
-
include: {
|
|
428
|
-
sender: {
|
|
429
|
-
select: {
|
|
430
|
-
id: true,
|
|
431
|
-
username: true,
|
|
432
|
-
profile: {
|
|
433
|
-
select: {
|
|
434
|
-
displayName: true,
|
|
435
|
-
},
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
},
|
|
439
|
-
},
|
|
440
|
-
orderBy: {
|
|
441
|
-
createdAt: 'desc',
|
|
442
|
-
},
|
|
443
|
-
take: 10, // Last 10 messages for context
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
const systemPrompt = `You are Newton, an AI tutor helping a student with their assignment submission.
|
|
447
|
-
|
|
448
|
-
Assignment: ${submission.assignment.title}
|
|
449
|
-
Subject: ${submission.assignment.class.subject || 'General'}
|
|
450
|
-
Instructions: ${submission.assignment.instructions || 'No specific instructions provided'}
|
|
451
|
-
|
|
452
|
-
Your role:
|
|
453
|
-
- Help the student understand concepts related to their assignment
|
|
454
|
-
- Provide guidance and explanations without giving away direct answers
|
|
455
|
-
- Encourage learning and critical thinking
|
|
456
|
-
- Be supportive and encouraging
|
|
457
|
-
- Use clear, educational language appropriate for the subject
|
|
458
|
-
- If the student asks for direct answers, guide them to think through the problem instead
|
|
459
|
-
- Break down complex concepts into simpler parts
|
|
460
|
-
- Use examples and analogies when helpful
|
|
461
|
-
|
|
462
|
-
IMPORTANT:
|
|
463
|
-
- Do not use markdown formatting in your responses - use plain text only
|
|
464
|
-
- Keep responses conversational and educational
|
|
465
|
-
- Focus on helping the student learn, not just completing the assignment`;
|
|
466
|
-
|
|
467
|
-
const messages: Array<{ role: 'user' | 'assistant' | 'system'; content: string }> = [
|
|
468
|
-
{ role: 'system', content: systemPrompt },
|
|
469
|
-
];
|
|
470
|
-
|
|
471
|
-
// Add recent conversation history
|
|
472
|
-
recentMessages.reverse().forEach(msg => {
|
|
473
|
-
const role = isAIUser(msg.senderId) ? 'assistant' : 'user';
|
|
474
|
-
const senderName = msg.sender?.profile?.displayName || msg.sender?.username || 'Student';
|
|
475
|
-
const content = isAIUser(msg.senderId) ? msg.content : `${senderName}: ${msg.content}`;
|
|
476
|
-
|
|
477
|
-
messages.push({
|
|
478
|
-
role: role as 'user' | 'assistant',
|
|
479
|
-
content,
|
|
480
|
-
});
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
// Add the new student message
|
|
484
|
-
messages.push({
|
|
485
|
-
role: 'user',
|
|
486
|
-
content: `Student: ${studentMessage}`,
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
const completion = await openAIClient.chat.completions.create({
|
|
490
|
-
model: 'gpt-5-nano',
|
|
491
|
-
messages,
|
|
492
|
-
temperature: 0.7,
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
const response = completion.choices[0]?.message?.content;
|
|
496
|
-
|
|
497
|
-
if (!response) {
|
|
498
|
-
throw new Error('No response generated from inference API');
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// Send the text response to the conversation
|
|
502
|
-
await sendAIMessage(response, conversationId, {
|
|
503
|
-
subject: submission.assignment.class.subject || 'Assignment',
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
logger.info('AI response sent', { newtonChatId, conversationId });
|
|
507
|
-
|
|
508
|
-
} catch (error) {
|
|
509
|
-
logger.error('Failed to generate AI response:', {
|
|
510
|
-
error: error instanceof Error ? {
|
|
511
|
-
message: error.message,
|
|
512
|
-
stack: error.stack,
|
|
513
|
-
name: error.name
|
|
514
|
-
} : error,
|
|
515
|
-
newtonChatId
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
297
|
|
package/src/routers/section.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { createTRPCRouter, protectedProcedure, protectedTeacherProcedure } from "../trpc.js";
|
|
2
|
+
import { createTRPCRouter, protectedClassMemberProcedure, protectedProcedure, protectedTeacherProcedure } from "../trpc.js";
|
|
3
3
|
import { TRPCError } from "@trpc/server";
|
|
4
4
|
import { prisma } from "../lib/prisma.js";
|
|
5
5
|
|
|
6
6
|
const createSectionSchema = z.object({
|
|
7
7
|
classId: z.string(),
|
|
8
|
+
id: z.string().optional(),
|
|
8
9
|
name: z.string(),
|
|
9
10
|
color: z.string().optional(),
|
|
10
11
|
});
|
|
@@ -22,6 +23,24 @@ const deleteSectionSchema = z.object({
|
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
export const sectionRouter = createTRPCRouter({
|
|
26
|
+
exists: protectedClassMemberProcedure
|
|
27
|
+
.input(z.object({
|
|
28
|
+
id: z.string(),
|
|
29
|
+
}))
|
|
30
|
+
.query(async ({ ctx, input }) => {
|
|
31
|
+
if (!ctx.user) {
|
|
32
|
+
throw new TRPCError({
|
|
33
|
+
code: "UNAUTHORIZED",
|
|
34
|
+
message: "User must be authenticated",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const section = await prisma.section.findUnique({
|
|
39
|
+
where: { id: input.id },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return section ? true : false;
|
|
43
|
+
}),
|
|
25
44
|
create: protectedTeacherProcedure
|
|
26
45
|
.input(createSectionSchema)
|
|
27
46
|
.mutation(async ({ ctx, input }) => {
|
|
@@ -53,6 +72,7 @@ export const sectionRouter = createTRPCRouter({
|
|
|
53
72
|
|
|
54
73
|
const section = await prisma.section.create({
|
|
55
74
|
data: {
|
|
75
|
+
...(input.id && { id: input.id }),
|
|
56
76
|
name: input.name,
|
|
57
77
|
order: 0,
|
|
58
78
|
class: {
|
package/src/routers/worksheet.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TRPCError } from "@trpc/server";
|
|
2
|
-
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
|
|
2
|
+
import { createTRPCRouter, protectedClassMemberProcedure, protectedProcedure } from "../trpc.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { prisma } from "../lib/prisma.js";
|
|
5
5
|
import { GenerationStatus, WorksheetQuestionType } from "@prisma/client";
|
|
@@ -38,6 +38,22 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
38
38
|
return worksheet;
|
|
39
39
|
}),
|
|
40
40
|
|
|
41
|
+
exists: protectedClassMemberProcedure
|
|
42
|
+
.input(z.object({
|
|
43
|
+
id: z.string(),
|
|
44
|
+
}))
|
|
45
|
+
.query(async ({ ctx, input }) => {
|
|
46
|
+
if (!ctx.user) {
|
|
47
|
+
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'User must be authenticated' });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const worksheet = await prisma.worksheet.findUnique({
|
|
51
|
+
where: { id: input.id },
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return worksheet ? true : false;
|
|
55
|
+
}),
|
|
56
|
+
|
|
41
57
|
// List all worksheets for a class
|
|
42
58
|
listWorksheets: protectedProcedure
|
|
43
59
|
.input(z.object({
|
package/src/seedDatabase.ts
CHANGED
|
@@ -8,6 +8,21 @@ export async function clearDatabase() {
|
|
|
8
8
|
logger.info('Clearing database');
|
|
9
9
|
await prisma.notification.deleteMany();
|
|
10
10
|
|
|
11
|
+
// Delete worksheet-related records
|
|
12
|
+
await prisma.studentQuestionProgress.deleteMany();
|
|
13
|
+
await prisma.studentWorksheetResponse.deleteMany();
|
|
14
|
+
await prisma.worksheetQuestion.deleteMany();
|
|
15
|
+
await prisma.worksheet.deleteMany();
|
|
16
|
+
|
|
17
|
+
// Delete reactions (they reference announcements and comments)
|
|
18
|
+
await prisma.reaction.deleteMany();
|
|
19
|
+
|
|
20
|
+
// Delete comments (they reference announcements and users)
|
|
21
|
+
await prisma.comment.deleteMany();
|
|
22
|
+
|
|
23
|
+
// Delete NewtonChat (they reference submissions and conversations)
|
|
24
|
+
await prisma.newtonChat.deleteMany();
|
|
25
|
+
|
|
11
26
|
// Delete chat-related records
|
|
12
27
|
await prisma.mention.deleteMany();
|
|
13
28
|
await prisma.message.deleteMany();
|
|
@@ -39,10 +54,19 @@ export async function clearDatabase() {
|
|
|
39
54
|
// Delete schools (which reference files for logos) - this will cascade delete the file references
|
|
40
55
|
await prisma.school.deleteMany();
|
|
41
56
|
|
|
57
|
+
// Delete marketing-related records
|
|
58
|
+
await prisma.schoolDevelopementProgram.deleteMany();
|
|
59
|
+
await prisma.earlyAccessRequest.deleteMany();
|
|
60
|
+
|
|
42
61
|
// Finally delete all files
|
|
43
62
|
await prisma.file.deleteMany();
|
|
44
63
|
}
|
|
45
64
|
|
|
65
|
+
// Helper function to generate DiceBear avatar URL
|
|
66
|
+
function getDiceBearAvatar(seed: string): string {
|
|
67
|
+
return `https://api.dicebear.com/7.x/avataaars/svg?seed=${encodeURIComponent(seed)}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
export async function createUser(email: string, password: string, username: string) {
|
|
47
71
|
logger.debug("Creating user", { email, username, password });
|
|
48
72
|
|
|
@@ -109,7 +133,7 @@ export const seedDatabase = async () => {
|
|
|
109
133
|
createUser('charlotte.walker@student.riverside.edu', 'student123', 'charlotte.walker'),
|
|
110
134
|
]);
|
|
111
135
|
|
|
112
|
-
// 4. Create User Profiles
|
|
136
|
+
// 4. Create User Profiles with DiceBear avatars
|
|
113
137
|
await Promise.all([
|
|
114
138
|
prisma.userProfile.create({
|
|
115
139
|
data: {
|
|
@@ -118,6 +142,7 @@ export const seedDatabase = async () => {
|
|
|
118
142
|
bio: 'Biology teacher with 15 years of experience. Passionate about making science accessible to all students.',
|
|
119
143
|
location: 'Riverside, CA',
|
|
120
144
|
website: 'https://sarahjohnson-bio.com',
|
|
145
|
+
profilePicture: getDiceBearAvatar(teachers[0].username),
|
|
121
146
|
}
|
|
122
147
|
}),
|
|
123
148
|
prisma.userProfile.create({
|
|
@@ -126,6 +151,7 @@ export const seedDatabase = async () => {
|
|
|
126
151
|
displayName: 'Mr. Michael Chen',
|
|
127
152
|
bio: 'Mathematics teacher and department head. Specializes in AP Calculus and Statistics.',
|
|
128
153
|
location: 'Riverside, CA',
|
|
154
|
+
profilePicture: getDiceBearAvatar(teachers[1].username),
|
|
129
155
|
}
|
|
130
156
|
}),
|
|
131
157
|
prisma.userProfile.create({
|
|
@@ -134,18 +160,24 @@ export const seedDatabase = async () => {
|
|
|
134
160
|
displayName: 'Ms. Emma Davis',
|
|
135
161
|
bio: 'English Literature teacher. Loves fostering creative writing and critical thinking.',
|
|
136
162
|
location: 'Riverside, CA',
|
|
163
|
+
profilePicture: getDiceBearAvatar(teachers[2].username),
|
|
137
164
|
}
|
|
138
165
|
}),
|
|
139
166
|
]);
|
|
140
167
|
|
|
141
|
-
// Add profiles for
|
|
142
|
-
await Promise.all(students.
|
|
143
|
-
const names = [
|
|
168
|
+
// Add profiles for all students with DiceBear avatars
|
|
169
|
+
await Promise.all(students.map((student, index) => {
|
|
170
|
+
const names = [
|
|
171
|
+
'Alex Martinez', 'Sophia Williams', 'James Brown', 'Olivia Taylor',
|
|
172
|
+
'Ethan Anderson', 'Ava Thomas', 'Noah Jackson', 'Isabella White',
|
|
173
|
+
'Liam Harris', 'Mia Clark', 'Lucas Lewis', 'Charlotte Walker'
|
|
174
|
+
];
|
|
144
175
|
return prisma.userProfile.create({
|
|
145
176
|
data: {
|
|
146
177
|
userId: student.id,
|
|
147
|
-
displayName: names[index],
|
|
148
|
-
bio: `Grade 11 student at Riverside High School
|
|
178
|
+
displayName: names[index] || student.username,
|
|
179
|
+
bio: index < 6 ? `Grade 11 student at Riverside High School.` : undefined,
|
|
180
|
+
profilePicture: getDiceBearAvatar(student.username),
|
|
149
181
|
}
|
|
150
182
|
});
|
|
151
183
|
}));
|