Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add timestamp for last edit in UG tutor form #51

Merged
merged 10 commits into from
Jan 22, 2025
5 changes: 3 additions & 2 deletions components/dialog/AdminScoringDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import TmuaGradeBox from '@/components/dialog/TmuaGradeBox'
import Dropdown from '@/components/general/Dropdown'
import LabelText from '@/components/general/LabelText'
import { adminAccess } from '@/lib/access'
import { dateFormatting } from '@/lib/constants'
import { upsertAdminScoring } from '@/lib/query/forms'
import { FormPassbackState } from '@/lib/types'
import { decimalToNumber } from '@/lib/utils'
Expand Down Expand Up @@ -41,8 +42,8 @@ const AdminScoringForm: FC<AdminScoringFormProps> = ({ data, readOnly }) => {
<Flex direction="column" gap="3">
{internalReview?.lastAdminEditOn && internalReview?.lastAdminEditBy && (
<Text size="2" className="italic text-gray-500">
Last edited by {internalReview.lastAdminEditBy} on{' '}
{format(internalReview.lastAdminEditOn, "dd/MM/yy 'at' HH:mm")}
Last admin scoring by {internalReview.lastAdminEditBy} on{' '}
{format(internalReview.lastAdminEditOn, dateFormatting)}
</Text>
)}

Expand Down
5 changes: 3 additions & 2 deletions components/dialog/ReviewerScoringDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import FormWrapper from '@/components/dialog/FormWrapper'
import GenericDialog from '@/components/dialog/GenericDialog'
import LabelText from '@/components/general/LabelText'
import { reviewerAccess } from '@/lib/access'
import { dateFormatting } from '@/lib/constants'
import { upsertReviewerScoring } from '@/lib/query/forms'
import { FormPassbackState } from '@/lib/types'
import { ord } from '@/lib/utils'
Expand Down Expand Up @@ -45,7 +46,7 @@ const ReviewerScoringForm: FC<ReviewerScoringFormProps> = ({ data, readOnly }) =
<Flex direction="column" gap="3">
{internalReview?.lastReviewerEditOn && (
<Text size="2" className="italic text-gray-500">
Last edited on {format(internalReview.lastReviewerEditOn, "dd/MM/yy 'at' HH:mm")}
Last reviewed on {format(internalReview.lastReviewerEditOn, dateFormatting)}
</Text>
)}

Expand Down Expand Up @@ -142,7 +143,7 @@ const ReviewerScoringDialog: FC<ReviewerScoringDialogProps> = ({ data, userEmail
const handleFormSuccess = () => setIsOpen(false)

const upsertReviewerScoringWithId = (prevState: FormPassbackState, formData: FormData) =>
upsertReviewerScoring(data.id, prevState, formData)
upsertReviewerScoring(data.id, userEmail, prevState, formData)

const readOnly = !reviewerAccess(data.reviewer?.login, userEmail)

Expand Down
10 changes: 10 additions & 0 deletions components/dialog/UgTutorDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Dropdown from '@/components/general/Dropdown'
import LabelText from '@/components/general/LabelText'
import { ApplicationRow } from '@/components/table/ApplicationTable'
import { adminAccess } from '@/lib/access'
import { dateFormatting } from '@/lib/constants'
import { insertComment, updateOutcomes } from '@/lib/query/forms'
import { FormPassbackState } from '@/lib/types'
import { decimalToNumber } from '@/lib/utils'
Expand All @@ -32,6 +33,7 @@ import {
TextArea,
TextField
} from '@radix-ui/themes'
import { format } from 'date-fns'
import React, { FC, useEffect, useMemo, useState } from 'react'

type Tab = 'outcomes' | 'comments'
Expand Down Expand Up @@ -86,6 +88,13 @@ const UgTutorForm: FC<UgTutorFormProps> = ({

return (
<Flex direction="column" gap="3">
{internalReview?.lastUserEditOn && internalReview?.lastUserEditBy && (
<Text size="2" className="italic text-gray-500">
Last overall edit by {internalReview.lastUserEditBy} on{' '}
{format(internalReview.lastUserEditOn, dateFormatting)}
</Text>
)}

<CandidateCallout
firstName={applicant.firstName}
surname={applicant.surname}
Expand Down Expand Up @@ -224,6 +233,7 @@ const UgTutorDialog: FC<UgTutorDialogProps> = ({ data, reviewerLogin, user }) =>
const upsertOutcomeWithId = async (prevState: FormPassbackState, formData: FormData) => {
return await updateOutcomes(
id,
email,
data.outcomes.map((o) => ({
id: o.id,
degreeCode: o.degreeCode
Expand Down
12 changes: 9 additions & 3 deletions components/table/ApplicationTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,11 @@ const ApplicationTable: FC<ApplicationTableProps> = ({
}),
columnHelper.accessor('nextAction', {
cell: (info) => (
<NextActionCell nextAction={info.getValue()} applicationId={info.row.original.id} />
<NextActionCell
userEmail={email}
nextAction={info.getValue()}
applicationId={info.row.original.id}
/>
),
header: 'Next Action',
id: SEARCH_PARAM_NEXT_ACTION
Expand Down Expand Up @@ -258,9 +262,10 @@ const WPColourMap: Record<WP, 'green' | 'red' | 'yellow'> = {
[WP.NOT_CALCULATED]: 'yellow'
}

const NextActionCell: FC<{ nextAction: NextAction; applicationId: number }> = ({
const NextActionCell: FC<{ nextAction: NextAction; applicationId: number; userEmail: string }> = ({
nextAction,
applicationId
applicationId,
userEmail
}) => {
return (
<Flex align="center" justify="between" gap="2">
Expand All @@ -271,6 +276,7 @@ const NextActionCell: FC<{ nextAction: NextAction; applicationId: number }> = ({
color="grass"
onClick={async () => {
await updateNextAction(
userEmail,
nextAction === NextAction.INFORM_CANDIDATE
? NextAction.FINAL_CHECK
: NextAction.CANDIDATE_INFORMED,
Expand Down
1 change: 1 addition & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const dateFormatting = "dd/MM/yy 'at' HH:mm"
5 changes: 4 additions & 1 deletion lib/csv/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ function updateAdminScoring(
if (currentNextAction === NextAction.ADMIN_SCORING_WITH_TMUA)
nextNextAction = NextAction.REVIEWER_SCORING

const currentTimestamp = new Date()
return prisma.application.update({
where: {
admissionsCycle_cid: {
Expand All @@ -211,7 +212,9 @@ function updateAdminScoring(
extracurricularAdminScore: a.extracurricularAdminScore,
examComments: a.examComments,
lastAdminEditBy: userEmail,
lastAdminEditOn: new Date()
lastAdminEditOn: currentTimestamp,
lastUserEditBy: userEmail,
lastUserEditOn: currentTimestamp
}
}
}
Expand Down
31 changes: 25 additions & 6 deletions lib/query/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export async function upsertAdminScoring(
}
})

const currentTimestamp = new Date()
await prisma.internalReview.upsert({
where: {
applicationId
Expand All @@ -60,14 +61,18 @@ export async function upsertAdminScoring(
extracurricularAdminScore,
examComments,
lastAdminEditBy: adminLogin,
lastAdminEditOn: new Date()
lastAdminEditOn: currentTimestamp,
lastUserEditBy: adminLogin,
lastUserEditOn: currentTimestamp
},
update: {
motivationAdminScore,
extracurricularAdminScore,
examComments,
lastAdminEditBy: adminLogin,
lastAdminEditOn: new Date()
lastAdminEditOn: currentTimestamp,
lastUserEditBy: adminLogin,
lastUserEditOn: currentTimestamp
}
})

Expand All @@ -77,6 +82,7 @@ export async function upsertAdminScoring(

export async function upsertReviewerScoring(
applicationId: number,
userEmail: string,
_: FormPassbackState,
formData: FormData
): Promise<FormPassbackState> {
Expand All @@ -97,14 +103,17 @@ export async function upsertReviewerScoring(
}
})

const currentTimestamp = new Date()
await prisma.internalReview.update({
where: { applicationId },
data: {
motivationReviewerScore,
extracurricularReviewerScore,
referenceReviewerScore,
academicComments,
lastReviewerEditOn: new Date()
procaconsul marked this conversation as resolved.
Show resolved Hide resolved
lastReviewerEditOn: currentTimestamp,
lastUserEditBy: userEmail,
lastUserEditOn: currentTimestamp
}
})

Expand All @@ -114,6 +123,7 @@ export async function upsertReviewerScoring(

export async function updateOutcomes(
applicationId: number,
userEmail: string,
partialOutcomes: { id: number; degreeCode: string }[],
_: FormPassbackState,
formData: FormData
Expand All @@ -126,7 +136,7 @@ export async function updateOutcomes(
return { id, ...parsedOutcome }
})

await updateNextAction(formData.get('nextAction'), applicationId)
await updateNextAction(userEmail, formData.get('nextAction'), applicationId)

for (const { id, offerCode, offerText, decision } of fullOutcomes) {
await prisma.outcome.update({
Expand Down Expand Up @@ -156,7 +166,7 @@ export async function insertComment(
const result = formCommentSchema.safeParse(Object.fromEntries(formData))
if (!result.success) return { status: 'error', message: result.error.issues[0].message }

await updateNextAction(formData.get('nextAction'), applicationId)
await updateNextAction(authorEmail, formData.get('nextAction'), applicationId)

await prisma.comment.create({
data: {
Expand All @@ -171,12 +181,21 @@ export async function insertComment(
}

export async function updateNextAction(
userEmail: string,
nextActionInput: FormDataEntryValue | string | null,
applicationId: number
) {
if (!nextActionInput || nextActionInput === 'Unchanged') return
await prisma.internalReview.update({
where: { applicationId },
data: {
lastUserEditBy: userEmail,
lastUserEditOn: new Date()
}
})

if (!nextActionInput || nextActionInput === 'Unchanged') return
const nextAction = nextActionField.parse(nextActionInput)

await prisma.application.update({
where: { id: applicationId },
data: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "InternalReview" ADD COLUMN "lastUserEditBy" TEXT,
ADD COLUMN "lastUserEditOn" TIMESTAMP(3);
2 changes: 2 additions & 0 deletions prisma/schema/application.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ model InternalReview {
examComments String?
lastAdminEditBy String?
lastAdminEditOn DateTime?
lastUserEditBy String?
lastUserEditOn DateTime?
motivationReviewerScore Decimal? @db.Decimal(3, 1)
extracurricularReviewerScore Decimal? @db.Decimal(3, 1)
referenceReviewerScore Decimal? @db.Decimal(3, 1)
Expand Down
Loading