Keep chat pinned to the latest message while AI thinks or streams, and align buttons/inputs with the logo teal/blue focus treatment. Co-authored-by: Cursor <cursoragent@cursor.com>
146 lines
4.5 KiB
TypeScript
146 lines
4.5 KiB
TypeScript
/**
|
||
* Dev helper: jump a password user to Session 11 chat (sessions 1–10 done,
|
||
* pre-test done, training/post-test NOT done) so you can test the post-test handoff.
|
||
*
|
||
* Usage:
|
||
* npx tsx scripts/jump-to-session-11.ts alireza@gmail.com
|
||
*/
|
||
import { AttemptPhase, AttemptStatus, SessionProgressStatus } from '@prisma/client';
|
||
import { prisma } from '../src/lib/prisma.ts';
|
||
import { PROGRAM_SESSION_COUNT } from '../src/modules/sessions/catalog.ts';
|
||
|
||
const emailArg = process.argv[2]?.trim().toLowerCase();
|
||
if (!emailArg) {
|
||
console.error('Usage: npx tsx scripts/jump-to-session-11.ts <email>');
|
||
process.exit(1);
|
||
}
|
||
|
||
async function main() {
|
||
const identity = await prisma.authIdentity.findFirst({
|
||
where: {
|
||
provider: 'password',
|
||
OR: [{ email: emailArg }, { providerSubject: emailArg }],
|
||
},
|
||
include: {
|
||
user: { include: { journey: true, profile: true } },
|
||
},
|
||
});
|
||
|
||
if (!identity) {
|
||
throw new Error(`No password account found for ${emailArg}`);
|
||
}
|
||
|
||
const userId = identity.userId;
|
||
const now = new Date();
|
||
const hourAgo = (n: number) => new Date(now.getTime() - n * 60 * 60 * 1000);
|
||
|
||
await prisma.$transaction(async (tx) => {
|
||
await tx.learningJourney.upsert({
|
||
where: { userId },
|
||
create: {
|
||
userId,
|
||
currentStep: 'training_in_progress',
|
||
preTestCompletedAt: hourAgo(20),
|
||
trainingStartedAt: hourAgo(19),
|
||
trainingCompletedAt: null,
|
||
postTestCompletedAt: null,
|
||
lastActivityAt: now,
|
||
},
|
||
update: {
|
||
currentStep: 'training_in_progress',
|
||
preTestCompletedAt: identity.user.journey?.preTestCompletedAt ?? hourAgo(20),
|
||
trainingStartedAt: identity.user.journey?.trainingStartedAt ?? hourAgo(19),
|
||
trainingCompletedAt: null,
|
||
postTestCompletedAt: null,
|
||
lastActivityAt: now,
|
||
},
|
||
});
|
||
|
||
const existingPre = await tx.assessmentAttempt.findFirst({
|
||
where: { userId, phase: AttemptPhase.pre, status: AttemptStatus.scored },
|
||
});
|
||
if (!existingPre) {
|
||
const preAt = hourAgo(20);
|
||
await tx.assessmentAttempt.create({
|
||
data: {
|
||
userId,
|
||
phase: AttemptPhase.pre,
|
||
status: AttemptStatus.scored,
|
||
submittedAt: preAt,
|
||
scoredAt: preAt,
|
||
},
|
||
});
|
||
}
|
||
|
||
// Clear final-session / post-test leftovers so the handoff can be retested.
|
||
await tx.sessionProgress.deleteMany({
|
||
where: { userId, sessionOrder: PROGRAM_SESSION_COUNT },
|
||
});
|
||
await tx.chatSession.deleteMany({
|
||
where: { userId, sessionOrder: PROGRAM_SESSION_COUNT },
|
||
});
|
||
await tx.assessmentAttempt.deleteMany({
|
||
where: { userId, phase: AttemptPhase.post },
|
||
});
|
||
|
||
for (let order = 1; order < PROGRAM_SESSION_COUNT; order += 1) {
|
||
const completedAt = hourAgo(PROGRAM_SESSION_COUNT - order);
|
||
await tx.sessionProgress.upsert({
|
||
where: { userId_sessionOrder: { userId, sessionOrder: order } },
|
||
create: {
|
||
userId,
|
||
sessionOrder: order,
|
||
status: SessionProgressStatus.completed,
|
||
startedAt: completedAt,
|
||
completedAt,
|
||
completionMetadata: {
|
||
reason: 'Dev jump-to-session-11 helper',
|
||
sessionComplete: true,
|
||
},
|
||
},
|
||
update: {
|
||
status: SessionProgressStatus.completed,
|
||
startedAt: completedAt,
|
||
completedAt,
|
||
completionMetadata: {
|
||
reason: 'Dev jump-to-session-11 helper',
|
||
sessionComplete: true,
|
||
},
|
||
},
|
||
});
|
||
}
|
||
});
|
||
|
||
const progress = await prisma.sessionProgress.findMany({
|
||
where: { userId, status: SessionProgressStatus.completed },
|
||
select: { sessionOrder: true },
|
||
orderBy: { sessionOrder: 'asc' },
|
||
});
|
||
const journey = await prisma.learningJourney.findUnique({ where: { userId } });
|
||
|
||
console.log(
|
||
JSON.stringify(
|
||
{
|
||
email: identity.email ?? identity.providerSubject,
|
||
profileName: identity.user.profile?.name ?? null,
|
||
completedSessions: progress.map((p) => p.sessionOrder),
|
||
nextSession: PROGRAM_SESSION_COUNT,
|
||
trainingCompletedAt: journey?.trainingCompletedAt ?? null,
|
||
postTestCompletedAt: journey?.postTestCompletedAt ?? null,
|
||
hint: 'Login → open Chat. You should land on Session 11 review. Finish the wrap-up to reach post-test.',
|
||
},
|
||
null,
|
||
2,
|
||
),
|
||
);
|
||
}
|
||
|
||
main()
|
||
.catch((err) => {
|
||
console.error(err instanceof Error ? err.message : err);
|
||
process.exit(1);
|
||
})
|
||
.finally(async () => {
|
||
await prisma.$disconnect();
|
||
});
|