Round 20: Student Portal, District Management, userId field, styling enhancements, bug fixes
- Added userId field to Student model with User relation - Created Student Portal view with 6 tabs (competencies, goals, achievements, schedule, homework, feedback) - Created StudentGoal model + CRUD API with role-based access - Created District Management view with CRUD, analytics, school assignment - Enhanced auth page: animated gradient, floating particles, glassmorphism, staggered entrance - Enhanced dashboard: time-based greeting, animated stat cards, class overview, school branding - Enhanced student portal: hero section, circular progress, streak counter, celebration particles - Fixed student-goals API 403 for STUDENT role (name-matching fallback for legacy data) - Added userId filter to students API with OR fallback - Added nav.student-portal i18n key - 100+ new i18n keys in DE and EN - All lint checks pass
This commit is contained in:
1 parent
9680cc9244
commit
04ae7aa80c
23 files changed
+4624
-2868
No files matched your search
@@ -25,11 +25,31 @@ export async function GET(request: Request) {
|
||||
const schoolId = searchParams.get('schoolId');
|
||||
const classGroupId = searchParams.get('classGroupId');
|
||||
const search = searchParams.get('search');
|
||||
const userId = searchParams.get('userId');
|
||||
|
||||
const where: Record<string, unknown> = { deletedAt: null };
|
||||
|
||||
if (schoolId) where.schoolId = schoolId;
|
||||
|
||||
// Filter by userId (direct link to User account)
|
||||
let userIdFilter: Record<string, unknown>[] | null = null;
|
||||
if (userId) {
|
||||
// For STUDENT role, also match by name + school as fallback for legacy data
|
||||
if (session.user?.role === 'STUDENT' && session.user.id === userId) {
|
||||
userIdFilter = [
|
||||
{ userId },
|
||||
{
|
||||
userId: null,
|
||||
firstName: session.user.firstName,
|
||||
lastName: session.user.lastName,
|
||||
schoolId: session.user.schoolId,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
where.userId = userId;
|
||||
}
|
||||
}
|
||||
|
||||
if (classGroupId) {
|
||||
where.enrollments = {
|
||||
some: { classGroupId, endDate: null },
|
||||
@@ -37,11 +57,22 @@ export async function GET(request: Request) {
|
||||
}
|
||||
|
||||
if (search) {
|
||||
where.OR = [
|
||||
const searchOr = [
|
||||
{ firstName: { contains: search } },
|
||||
{ lastName: { contains: search } },
|
||||
{ externalId: { contains: search } },
|
||||
];
|
||||
// If userId filter also uses OR, combine with AND
|
||||
if (userIdFilter) {
|
||||
where.AND = [
|
||||
{ OR: userIdFilter },
|
||||
{ OR: searchOr },
|
||||
];
|
||||
} else {
|
||||
where.OR = searchOr;
|
||||
}
|
||||
} else if (userIdFilter) {
|
||||
where.OR = userIdFilter;
|
||||
}
|
||||
|
||||
const students = await db.student.findMany({
|
||||
|
||||
Reference in new issue
Block a user