From 0307f123016e41f6b8dc30809cde1d13775a68d1 Mon Sep 17 00:00:00 2001 From: soulsam480 Date: Thu, 26 May 2022 23:07:20 +0530 Subject: [PATCH] feat: added score update and finalized student profile view --- .eslintrc-auto-import.json | 3 - api/src/lib/auth.ts | 10 +- api/src/lib/student.ts | 2 - api/src/routes/tickets.ts | 12 -- api/src/rpc/routers/student/score.ts | 40 ++---- app/auto-imports.d.ts | 3 - app/src/components/globals/NavBar.tsx | 6 +- app/src/components/lib/MDialog.tsx | 5 +- app/src/components/student/ProfileSection.tsx | 6 +- .../student/profile/Basics/BasicsCard.tsx | 60 ++++---- .../student/profile/Basics/index.tsx | 20 +-- .../student/profile/Course/CourseCard.tsx | 133 ++++++++++++------ .../student/profile/Course/index.tsx | 18 ++- app/src/contexts/student/basics.tsx | 1 + app/src/contexts/student/score.tsx | 10 +- app/src/pages/student/onboarding.tsx | 11 +- app/src/pages/student/profile.tsx | 1 + app/src/schemas/index.ts | 12 +- app/src/stores/student.ts | 13 +- app/src/stores/user.ts | 13 +- app/src/utils/constnts.ts | 9 ++ .../migration.sql | 12 ++ prisma/schema.prisma | 15 +- 23 files changed, 233 insertions(+), 182 deletions(-) delete mode 100644 api/src/routes/tickets.ts create mode 100644 prisma/migrations/20220526153448_score_updates/migration.sql diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json index 0294dfc..2ccc565 100644 --- a/.eslintrc-auto-import.json +++ b/.eslintrc-auto-import.json @@ -8,7 +8,6 @@ "IconLaCheckCircleSolid": true, "IconLaChevronDown": true, "IconLaExclamationCircle": true, - "IconLaExclamationTriangle": true, "IconLaFileAltSolid": true, "IconLaFlask": true, "IconLaGraduationCap": true, @@ -27,8 +26,6 @@ "IconLaSchool": true, "IconLaShieldAlt": true, "IconLaSitemap": true, - "IconLaSortAmountDown": true, - "IconLaSortAmountUp": true, "IconLaSun": true, "IconLaTicketAlt": true, "IconLaTimes": true, diff --git a/api/src/lib/auth.ts b/api/src/lib/auth.ts index 6d56433..9e835b1 100644 --- a/api/src/lib/auth.ts +++ b/api/src/lib/auth.ts @@ -31,7 +31,15 @@ export function prismaQueryHelper(client: WithExcludeClient) { account = await client.account.findFirst({ where: { email, id }, select: { - tenant: true, + tenant: { + include: { + basics: { + select: { + name: true, + }, + }, + }, + }, ...client.$exclude('account', ['password', 'otp', 'otpExpiry', 'emailToken']), }, }) diff --git a/api/src/lib/student.ts b/api/src/lib/student.ts index c72f286..c6e23ad 100644 --- a/api/src/lib/student.ts +++ b/api/src/lib/student.ts @@ -77,10 +77,8 @@ export async function createStudent({ await miraiClient.studentScore.create({ data: { studentId, - aggregatePercentage: '0', courseStartedAt: batch.startsAt, currentTerm: 0, - hasBacklog: false, lateralEntry: false, scores: '{}', }, diff --git a/api/src/routes/tickets.ts b/api/src/routes/tickets.ts deleted file mode 100644 index 4c05f98..0000000 --- a/api/src/routes/tickets.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { FastifyPluginAsync } from 'fastify' -import { ticketQueue } from '../queues' - -export const router: FastifyPluginAsync = async (fastify, _opts): Promise => { - fastify.post<{ Body: { data: string } }>('/', async ({ body }) => { - await ticketQueue.add(body) - - return 'success' - }) -} - -export const prefix = '/tickets' diff --git a/api/src/rpc/routers/student/score.ts b/api/src/rpc/routers/student/score.ts index bd06dc3..24a1a3d 100644 --- a/api/src/rpc/routers/student/score.ts +++ b/api/src/rpc/routers/student/score.ts @@ -1,33 +1,9 @@ import { createRouter } from '../../createRouter' import { z } from 'zod' -import { createStudentScoreSchema } from '@mirai/app' import { TRPCError } from '@trpc/server' +import { semUpdateSchema } from '@mirai/app' export const scoreRouter = createRouter() - .mutation('manage', { - input: createStudentScoreSchema, - async resolve({ ctx, input }) { - const { studentId, ...data } = input - - const result = await ctx.prisma.studentScore.upsert({ - where: { studentId }, - create: input, - update: data, - }) - - return result - }, - }) - .mutation('remove', { - input: z.number(), - async resolve({ ctx, input }) { - try { - await ctx.prisma.studentScore.delete({ where: { id: input } }) - } catch (error) { - throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Unable to delete score' }) - } - }, - }) .query('get', { input: z.number(), async resolve({ ctx, input }) { @@ -41,6 +17,20 @@ export const scoreRouter = createRouter() message: 'Student score details not found !', }) } + return scoreDetails }, }) + .mutation('update_score_card', { + input: z.object({ studentId: z.number(), data: z.record(semUpdateSchema) }), + async resolve({ ctx, input: { data, studentId } }) { + const scoreData = await ctx.prisma.studentScore.update({ + where: { studentId }, + data: { + scores: data, + }, + }) + + return scoreData + }, + }) diff --git a/app/auto-imports.d.ts b/app/auto-imports.d.ts index 0b0bbf0..b0bc7dd 100644 --- a/app/auto-imports.d.ts +++ b/app/auto-imports.d.ts @@ -9,7 +9,6 @@ declare global { const IconLaCheckCircleSolid: typeof import('~icons/la/check-circle-solid.jsx')['default'] const IconLaChevronDown: typeof import('~icons/la/chevron-down.jsx')['default'] const IconLaExclamationCircle: typeof import('~icons/la/exclamation-circle.jsx')['default'] - const IconLaExclamationTriangle: typeof import('~icons/la/exclamation-triangle.jsx')['default'] const IconLaFileAltSolid: typeof import('~icons/la/file-alt-solid.jsx')['default'] const IconLaFlask: typeof import('~icons/la/flask.jsx')['default'] const IconLaGraduationCap: typeof import('~icons/la/graduation-cap.jsx')['default'] @@ -28,8 +27,6 @@ declare global { const IconLaSchool: typeof import('~icons/la/school.jsx')['default'] const IconLaShieldAlt: typeof import('~icons/la/shield-alt.jsx')['default'] const IconLaSitemap: typeof import('~icons/la/sitemap.jsx')['default'] - const IconLaSortAmountDown: typeof import('~icons/la/sort-amount-down.jsx')['default'] - const IconLaSortAmountUp: typeof import('~icons/la/sort-amount-up.jsx')['default'] const IconLaSun: typeof import('~icons/la/sun.jsx')['default'] const IconLaTicketAlt: typeof import('~icons/la/ticket-alt.jsx')['default'] const IconLaTimes: typeof import('~icons/la/times.jsx')['default'] diff --git a/app/src/components/globals/NavBar.tsx b/app/src/components/globals/NavBar.tsx index 5937940..6e08b5d 100644 --- a/app/src/components/globals/NavBar.tsx +++ b/app/src/components/globals/NavBar.tsx @@ -41,8 +41,8 @@ export const NavBar: React.FC = () => { <>
setSidebar(false)}>
    = () => {
  • - {userData.name} ({userData.role}) + {userData.name ?? userData?.tenant?.basics?.name} ({userData.role})
  • diff --git a/app/src/components/lib/MDialog.tsx b/app/src/components/lib/MDialog.tsx index 460c29d..4a92b8f 100644 --- a/app/src/components/lib/MDialog.tsx +++ b/app/src/components/lib/MDialog.tsx @@ -8,6 +8,7 @@ export interface Props { children: React.ReactChild noEscape?: boolean className?: string + afterLeave?: () => void } interface ContentProps { @@ -28,9 +29,9 @@ const DialogContent = React.forwardRef(({ children ) }) -export const MDialog: React.FC = ({ show, children, onClose, noEscape, className }) => { +export const MDialog: React.FC = ({ show, children, onClose, noEscape, className, afterLeave }) => { return ( - + {} export const ProfileSection = React.forwardRef( ({ children, className: _className = '', ...rest }, ref) => { return ( -
    +
    {children}
    ) diff --git a/app/src/components/student/profile/Basics/BasicsCard.tsx b/app/src/components/student/profile/Basics/BasicsCard.tsx index 87c0591..e9c3abd 100644 --- a/app/src/components/student/profile/Basics/BasicsCard.tsx +++ b/app/src/components/student/profile/Basics/BasicsCard.tsx @@ -34,19 +34,19 @@ export const BasicsCard: React.FC = ({ studentBasics, onTrigger }) => {
    -
    -
    -
    Name:
    -
    Gender:
    -
    Category:
    -
    Date of birth:
    -
    +
    +
    Name
    +
    {studentBasics?.name ?? '-'}
    + +
    Gender
    +
    {studentBasics?.gender ?? '-'}
    -
    -
    {studentBasics?.name ?? '-'}
    -
    {studentBasics?.gender ?? '-'}
    -
    {studentBasics?.category ?? '-'}
    -
    {(studentBasics?.dob !== undefined && formatDate(studentBasics.dob, 'DD MMM YYYY')) || '-'}
    +
    Category
    +
    {studentBasics?.category ?? '-'}
    + +
    Date of birth
    +
    + {(studentBasics?.dob !== undefined && formatDate(studentBasics.dob, 'DD MMM YYYY')) || '-'}
    @@ -75,26 +75,26 @@ export const BasicsCard: React.FC = ({ studentBasics, onTrigger }) => {
    -
    -
    -
    Mobile Number:
    -
    Primary Email:
    -
    Secondary Email:
    -
    Permanent address:
    -
    Current address:
    +
    +
    Mobile Number
    +
    {studentBasics?.mobileNumber ?? '-'}
    + +
    Primary Email
    +
    {studentBasics?.primaryEmail ?? '-'}
    + +
    Secondary Email
    +
    {studentBasics?.secondaryEmail ?? '-'}
    + +
    Permanent address
    + {/* // TODO: break when length is more */} +
    + {studentBasics?.permanentAddress === undefined ? '-' : normalizeAddress(studentBasics.permanentAddress)}
    -
    -
    {studentBasics?.mobileNumber ?? '-'}
    -
    {studentBasics?.primaryEmail ?? '-'}
    -
    {studentBasics?.secondaryEmail ?? '-'}
    - {/* // TODO: break when length is more */} -
    - {studentBasics?.permanentAddress === undefined ? '-' : normalizeAddress(studentBasics.permanentAddress)} -
    -
    - {studentBasics?.currentAddress === undefined ? '-' : normalizeAddress(studentBasics.currentAddress)} -
    +
    Current address
    + +
    + {studentBasics?.currentAddress === undefined ? '-' : normalizeAddress(studentBasics.currentAddress)}
    diff --git a/app/src/components/student/profile/Basics/index.tsx b/app/src/components/student/profile/Basics/index.tsx index a6b1efb..729547f 100644 --- a/app/src/components/student/profile/Basics/index.tsx +++ b/app/src/components/student/profile/Basics/index.tsx @@ -15,18 +15,10 @@ import { useUser } from 'stores/user' import { z } from 'zod' import { BasicsCard } from './BasicsCard' import { formatDate } from 'utils/helpers' +import { CATEGORY_TYPES, GENDER_TYPES } from 'utils/constnts' interface Props {} -const GENDER_TYPES = ['MALE', 'FEMALE', 'OTHER'].map((o) => ({ label: o, value: o })) -const CATEGORY_TYPES = [ - 'General', - 'Scheduled Caste', - 'Scheduled Tribe', - 'Other Backward Classes', - 'Economically Weaker Section', -].map((v) => ({ label: v, value: v })) - const ADDRES_FIELDS: Array = ['address', 'city', 'district', 'state', 'pin', 'country'] const initialAddress = { @@ -62,10 +54,8 @@ export const Basics: React.FC = () => { name: '', category: '', gender: '', - // TODO: it's here for now as student onboarding setup is not done - // once we have that ready, basics data will be here by default from API - mobileNumber: '8917300318', - primaryEmail: 'soulsam480@gmail.com', + mobileNumber: '', + primaryEmail: '', secondaryEmail: '', currentAddress: initialAddress, permanentAddress: initialAddress, @@ -159,11 +149,11 @@ export const Basics: React.FC = () => { return (
    -
    Basic info
    +
    Basic info
    - null}> + null} noEscape> { diff --git a/app/src/components/student/profile/Course/CourseCard.tsx b/app/src/components/student/profile/Course/CourseCard.tsx index 1003811..f001f4a 100644 --- a/app/src/components/student/profile/Course/CourseCard.tsx +++ b/app/src/components/student/profile/Course/CourseCard.tsx @@ -37,10 +37,10 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => { resolver: zodResolver(semUpdateSchema), defaultValues: { backlogDetails: '', - cummScore: '0', - semScore: '0', - ongoingBacklogs: '0', - totalBacklogs: '0', + cummScore: 0, + semScore: 0, + ongoingBacklogs: 0, + totalBacklogs: 0, }, }) @@ -53,6 +53,24 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => { if (courseData === null) return null + function renderSafeVal(val: any) { + return val !== undefined && String(val).length > 0 ? val : '-' + } + + const totalBacklogs = Object.values(studentScore?.scores ?? {}).reduce((acc, val) => { + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands + acc = acc + ((val?.totalBacklogs as number) ?? 0) + + return acc + }, 0) + + const ongoingBacklogs = Object.values(studentScore?.scores ?? {}).reduce((acc, val) => { + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands + acc = acc + ((val?.ongoingBacklogs as number) ?? 0) + + return acc + }, 0) + return ( null} noEscape> @@ -61,8 +79,9 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => { onSubmit={handleSubmit((data) => { if (selectedSem === null) return onSemUpdate(selectedSem, data) + setSelectedSem(null) - reset() + reset({}) setDialog(false) })} className="flex flex-col gap-2 sm:w-[400px] sm:max-w-[400px]" @@ -78,12 +97,13 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => { return ( ) })} @@ -103,6 +123,7 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => { onClick={() => { setDialog(false) setSelectedSem(null) + reset({}) }} type="button" > @@ -129,7 +150,7 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => {
    Score card
    -
    +
    Semester
    @@ -140,46 +161,66 @@ export const CourseCard: React.FC = ({ onSemUpdate }) => { ))}
    -
    - {/* semesters */} - {Array.from(Array(courseData.course.programDuration)).map((_, idx) => { - const semId = idx + 1 +
    +
    + {/* semesters */} + {Array.from(Array(courseData.course.programDuration)).map((_, idx) => { + const semId = idx + 1 + + return ( +
    +
    {semId}
    + + {/* score columns */} + {Object.keys(SCORE_RENDER_COLS).map((key) => ( +
    + {key === '_update' ? ( + + ) : ( + renderSafeVal(studentScore?.scores?.[String(semId)]?.[key as keyof StudentSemScore]) + )} +
    + ))} +
    + ) + })} +
    +
    +
    + +
    Backlog details
    - return ( -
    -
    {semId}
    - - {/* score columns */} - {Object.keys(SCORE_RENDER_COLS).map((key) => ( -
    - {key === '_update' ? ( - - ) : ( - studentScore?.scores?.[String(semId)]?.[key as keyof StudentSemScore] ?? '-' - )} -
    - ))} -
    - ) - })} +
    +
    + + Total Backlogs + +
    +
    {totalBacklogs}
    + +
    + + Ongoing backlogs +
    +
    {ongoingBacklogs}
    diff --git a/app/src/components/student/profile/Course/index.tsx b/app/src/components/student/profile/Course/index.tsx index bf13edd..a4ec4f2 100644 --- a/app/src/components/student/profile/Course/index.tsx +++ b/app/src/components/student/profile/Course/index.tsx @@ -1,13 +1,29 @@ +import { useScore } from 'contexts/student/score' +import { useAtomValue } from 'jotai' import React from 'react' import { semUpdateSchema } from 'schemas' +import { studentScoreAtom } from 'stores/student' +import { useUser } from 'stores/user' import { z } from 'zod' import { CourseCard } from './CourseCard' interface Props {} export const Course: React.FC = () => { + const { updateScoreCard } = useScore() + const userData = useUser() + const studentScore = useAtomValue(studentScoreAtom) + function handleSemUpdate(semId: number, data: z.infer) { - console.log(semId, data) + if (userData.studentId === null) return + + updateScoreCard({ + studentId: userData.studentId, + data: { + ...((studentScore?.scores as any) ?? {}), + [String(semId)]: data, + }, + }) } return (
    diff --git a/app/src/contexts/student/basics.tsx b/app/src/contexts/student/basics.tsx index 600f47c..1d01513 100644 --- a/app/src/contexts/student/basics.tsx +++ b/app/src/contexts/student/basics.tsx @@ -33,6 +33,7 @@ export function useBasics() { void setBasics(data as any) } + return { manage, invalidate, diff --git a/app/src/contexts/student/score.tsx b/app/src/contexts/student/score.tsx index 5665a45..9729e9e 100644 --- a/app/src/contexts/student/score.tsx +++ b/app/src/contexts/student/score.tsx @@ -9,19 +9,21 @@ export function useScore() { const userData = useUser() const setScore = useSetAtom(studentScoreAtom) - const { mutateAsync: manage, isLoading } = trpc.useMutation(['student.score.manage'], { + const { mutate: updateScoreCard, isLoading } = trpc.useMutation(['student.score.update_score_card'], { onError() { setAlert({ type: 'danger', message: 'Unable to process request', }) }, - onSuccess() { + onSuccess(data) { setAlert({ type: 'success', message: 'Score updated successfully !', }) + void setScore(data as unknown as any) + void invalidate() }, }) @@ -31,11 +33,11 @@ export function useScore() { const data = await trpcClient.query('student.score.get', userData.studentId) - void setScore(data) + void setScore(data as any) } return { - manage, + updateScoreCard, isLoading, invalidate, } diff --git a/app/src/pages/student/onboarding.tsx b/app/src/pages/student/onboarding.tsx index 57273cb..829260c 100644 --- a/app/src/pages/student/onboarding.tsx +++ b/app/src/pages/student/onboarding.tsx @@ -12,19 +12,10 @@ import { GetServerSideProps, InferGetServerSidePropsType } from 'next' import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { studentOnboardingSchema } from 'schemas' +import { CATEGORY_TYPES, GENDER_TYPES } from 'utils/constnts' import { z } from 'zod' import { NextPageWithLayout } from '../_app' -const GENDER_TYPES = ['MALE', 'FEMALE', 'OTHER'].map((o) => ({ label: o, value: o })) - -const CATEGORY_TYPES = [ - 'General', - 'Scheduled Caste', - 'Scheduled Tribe', - 'Other Backward Classes', - 'Economically Weaker Section', -].map((v) => ({ label: v, value: v })) - export const getServerSideProps: GetServerSideProps< { error: string | null diff --git a/app/src/pages/student/profile.tsx b/app/src/pages/student/profile.tsx index 0544d72..5de5d91 100644 --- a/app/src/pages/student/profile.tsx +++ b/app/src/pages/student/profile.tsx @@ -35,6 +35,7 @@ const StudentProfile: NextPageWithLayout = () => { debounce(() => { const elements = [ getElement('basics'), + getElement('course'), getElement('education'), getElement('experience'), getElement('skills'), diff --git a/app/src/schemas/index.ts b/app/src/schemas/index.ts index e14a613..4ce2792 100644 --- a/app/src/schemas/index.ts +++ b/app/src/schemas/index.ts @@ -61,8 +61,8 @@ export const createStudentBasicsSchema = z.object({ gender: z.string().min(1, 'Gender is required'), category: z.string().min(1, 'Category is required'), mobileNumber: z.string().min(1, 'Mobile number is required'), - primaryEmail: z.string().min(1, 'Primary email is required'), - secondaryEmail: z.string().nullable(), + primaryEmail: z.string().email().min(1, 'Primary email is required'), + secondaryEmail: z.string().email().nullable(), permanentAddress: z .object({ address: z.string(), @@ -292,10 +292,10 @@ export const bulkTicketResolveSchema = z.object({ export const semUpdateSchema = z .object({ - semScore: z.string().min(1, 'Required'), - cummScore: z.string().min(1, 'Required'), - ongoingBacklogs: z.string(), - totalBacklogs: z.string(), + semScore: z.number({ invalid_type_error: 'Should be numeric' }), + cummScore: z.number({ invalid_type_error: 'Should be numeric' }), + ongoingBacklogs: z.number({ invalid_type_error: 'Should be numeric' }), + totalBacklogs: z.number({ invalid_type_error: 'Should be numeric' }), fileUrl: z.string(), backlogDetails: z.string(), }) diff --git a/app/src/stores/student.ts b/app/src/stores/student.ts index c5e4553..bf93c7c 100644 --- a/app/src/stores/student.ts +++ b/app/src/stores/student.ts @@ -18,10 +18,10 @@ import type { OverWrite } from 'types' import { z } from 'zod' export interface StudentSemScore { - ongoingBacklogs?: string - cummScore?: string - semScore?: string - totalBacklogs?: string + ongoingBacklogs?: number + cummScore?: number + semScore?: number + totalBacklogs?: number verified?: boolean verifiedBy?: string verifiedOn?: Date @@ -32,10 +32,7 @@ export type StudentScoreType = Record export interface StudentValueType { basics: StudentBasicsOverwrite | null - score: OverWrite< - StudentScore, - { scores: StudentScoreType; backlogDetails: Record } - > | null + score: OverWrite | null education: StudentEducation[] experience: StudentWorkExperience[] skills: StudentSkill[] diff --git a/app/src/stores/user.ts b/app/src/stores/user.ts index 6ae14fc..314086f 100644 --- a/app/src/stores/user.ts +++ b/app/src/stores/user.ts @@ -3,7 +3,18 @@ import { atom, useAtomValue } from 'jotai' export type User = Omit< Prisma.AccountGetPayload<{ - include: { owner: true; tenant: true } + include: { + owner: true + tenant: { + include: { + basics: { + select: { + name: true + } + } + } + } + } }>, 'password' | 'otp' | 'otpExpiry' | 'emailToken' > diff --git a/app/src/utils/constnts.ts b/app/src/utils/constnts.ts index 47557fa..9ec5ef3 100644 --- a/app/src/utils/constnts.ts +++ b/app/src/utils/constnts.ts @@ -150,3 +150,12 @@ export const INDUSTRY_TYPES = [ ] export const STUDENT_PROFILE_IGNORE_KEYS = ['verified', 'verifiedOn', 'verifiedBy', 'createdAt', 'updatedAt'] + +export const GENDER_TYPES = ['MALE', 'FEMALE', 'OTHER'].map((o) => ({ label: o, value: o })) +export const CATEGORY_TYPES = [ + 'General', + 'Scheduled Caste', + 'Scheduled Tribe', + 'Other Backward Classes', + 'Economically Weaker Section', +].map((v) => ({ label: v, value: v })) diff --git a/prisma/migrations/20220526153448_score_updates/migration.sql b/prisma/migrations/20220526153448_score_updates/migration.sql new file mode 100644 index 0000000..c07875f --- /dev/null +++ b/prisma/migrations/20220526153448_score_updates/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `aggregatePercentage` on the `StudentScore` table. All the data in the column will be lost. + - You are about to drop the column `hasBacklog` on the `StudentScore` table. All the data in the column will be lost. + - You are about to drop the column `totalBacklogs` on the `StudentScore` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "StudentScore" DROP COLUMN "aggregatePercentage", +DROP COLUMN "hasBacklog", +DROP COLUMN "totalBacklogs"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a4c0004..7459214 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -172,20 +172,17 @@ model StudentScore { student Student @relation(fields: [studentId], references: [id], onDelete: Cascade) studentId Int @unique - aggregatePercentage String - currentTerm Int - hasGraduated Boolean @default(false) - lateralEntry Boolean - - // backlogs - hasBacklog Boolean - totalBacklogs Int @default(0) + currentTerm Int + hasGraduated Boolean @default(false) + lateralEntry Boolean + // Why JSON ? // As this is going to be edited less frequently // adding a new table doesn't make sense // We can statically type this field using TS to ensure // the JSON schema remains same - backlogDetails Json @default("{}") + // TODO: remove this from table + backlogDetails Json @default("{}") // Why JSON ? // As this is going to be edited less frequently