Skip to content

Commit

Permalink
V2 Student Form (#108)
Browse files Browse the repository at this point in the history
* feat: starting form changes

* feat: set up useFieldArray, refactor

* feat: working student form

* rerun build

* Squashed commit of the following:

commit 058c01b
Author: Victor Siu <[email protected]>
Date:   Mon Jun 17 19:25:24 2024 -0700

    Feature/vs2961/attendance dashboard (#106)

    * Add backend query code

    * Add frontend components

    * Add mobile

    * Add attendance dashboard code

    * Add code for attendanceTable

    * Fix linting

    * Make varying sessions work

    * Fix linting

    * Fix types

    * fix linting

    * Prevent buttons from being clicked multiple times

commit 525fbe2
Author: adhi0331 <[email protected]>
Date:   Sun Jun 16 15:29:45 2024 -0500

    fixed minor bug

commit a16cf00
Author: Aaron Chan <[email protected]>
Date:   Sun Jun 16 13:15:56 2024 -0700

    Account Archival Frontend & Backend (#107)

    * feat: add create program notes backend

    * fix: THead unique key prop warning

    * feat: add edited by field to notes

    * fix: fix styling issues

    * feat: add edit and delete functionality to progress notes and change userId to uid for backend

    * fix: fix calendar styling

    * feat: add download progress notes functionality using react-pdf

    * feat: add mobile responsiveness

    * feat: create program context provider shared across Home, Programs, and Notes page

    * fix: fix styling to be consistent across pages

    * feat: add progress note filtering and add loading spinner to pages

    * feat: add account type authorization checks on frontend and backend

    * refactor: refactor notes logic and fix styling

    * feat: add logic to check for no students and refactor filter

    * feat: add shadows using overflow clip

    * fix: fix styling for search filter

    * fix: fix small style inconsistencies

    * fix: update poppins font url to use https

    * fix: fix modal close button styling to be more consistent

    * fix: fix escape key overriding dialog close

    * Squashed commit of the following:

    commit 0b133b8
    Author: Michael Sullivan <[email protected]>
    Date:   Tue May 14 09:09:16 2024 -0700

        Feature/mraysu/program form v2 (#100)

        * Update Backend Program Schema

        * V2 UI

        * Disabled Editing Program Type

        * Frontend-backend integration

        * Lint fixes

        ---------

        Co-authored-by: mraysu <[email protected]>
        Co-authored-by: Adhithya Ananthan <[email protected]>

    commit e17b509
    Author: parth4apple <[email protected]>
    Date:   Tue May 14 09:01:15 2024 -0700

        Student and Enrollment Schema modifications (#101)

        * feat: initial schema

        * feat: edit routes

        * feat: test and fix routes

    * feat: add frontend and backend for account archival

    * feat: ensure ui updates and refactor code

    * Squashed merge with main

    * fix: update type of VerifyUser to be same as User

    * fix: fix user type error

commit fe61637
Author: Andrew Pu <[email protected]>
Date:   Sun Jun 16 13:00:01 2024 -0700

    Feature/andrewzpu/program profile pages (#105)

    * added backend route for getting single program

    * added separate pages for each program

    * Added program edit popup and "no programs" message

    * Fixed add button display

    * Reorganized ProgramFormButton to take take any component

    * Removed start and end date from card

    * Connected Program Card to Program Profile Pages

    * Set up basic framework of Program Profile Page

    * Added feature where clicking anywhere else will close the edit popup button

    * Updated popup and redirect functionality of program profiles

    * Finished full screen view of program profile

    * Fixed hourly pay references

    * Added backend route to get program enrollments

    * Connected enrollments route to program profile page

    * Updated student count messages on cards and program profile

    * Added Student Names to Enrollment Table

    * Fixed mobile view

    * Fixed minor details

    * Minor Table Change

    * finish merge

    * fixed try catch error

    ---------

    Co-authored-by: Adhithya Ananthan <[email protected]>
    Co-authored-by: adhi0331 <[email protected]>

commit 6e67ad3
Author: Michael Sullivan <[email protected]>
Date:   Sat Jun 15 08:16:22 2024 -0700

    Feature/mraysu/program archive (#96)

    * Archive Program Route

    * Change program status to archived for students

    * Added Archived field to program schema

    * Implemented Archive Button

    * Prevent students from 'joining' archived programs

    * Lint fix

    * Integrated new enrollment schema

    * Archived Programs Page

    * Fix merge issues

    * Updated Archive Page View

    * Mobile UI Adjustments

    ---------

    Co-authored-by: mraysu <[email protected]>

commit b0b800a
Author: Aammya Sapra <[email protected]>
Date:   Fri Jun 14 21:40:43 2024 -0700

    Feature/aammya8/new account approval (#104)

    * Add user approval and denial functionality, as well as email user about account approval updates

    * backup

    * backup

    * fixed delete route

    * change approve/deny/delete to use email

    * approve/deny controllers do not get entered? but delete does

    * Fix Notifications UI (immediately remove corresponding card when approve/deny button clicked)

    * Modify routes for testing purposes

    * Debug statements --> user does not get found in denyUser

    * Email successfully sent for deny (accidentally deleted user before trying to send email earlier lol)

    * Fix frontend (populate account type)

    * Remove extra comments

    * added auth protection and cleaned up code

    * added env for emails

    * fix user role bug

    * fixed some bugs and deleted some log statements

    * ran lint fix

    ---------

    Co-authored-by: adhi0331 <[email protected]>

* fix: fix enrollment frontend and backend inconsistency

* Squashed merge branch 'feature/lisasiliu/view-student-profile-v2' into feature/parth4apple/student-form-updates

* feat: add image upload to student profile

* feat: add document upload to student profile and fix image upload

* feat: fix document upload so that it only triggers when user saves

* fix: fix merge conflict bug

* feat: ensure team accounts cannot see documents that are markedAdmin

* add firebase token

* make docs visible on student profile

* make delete student admin only

---------

Co-authored-by: adhi0331 <[email protected]>
Co-authored-by: Aaron Chan <[email protected]>
  • Loading branch information
3 people authored Dec 18, 2024
1 parent 4791e05 commit 5710fff
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 122 deletions.
23 changes: 22 additions & 1 deletion backend/src/controllers/student.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,22 @@ export const editStudent: RequestHandler = async (req, res, next) => {
}
};

export const getAllStudents: RequestHandler = async (_, res, next) => {
export const getAllStudents: RequestHandler = async (req, res, next) => {
try {
const students = await StudentModel.find().populate("enrollments");

// Even though this is a get request, we have verifyAuthToken middleware that sets the accountType in the request body
const { accountType } = req.body;

// Ensure that documents that are marked admin are not returned to non-admin users
if (accountType !== "admin") {
students.forEach((student) => {
student.documents = student.documents.filter(
(doc) => !doc.markedAdmin,
) as typeof student.documents;
});
}

res.status(200).json(students);
} catch (error) {
next(error);
Expand All @@ -126,6 +138,8 @@ export const getStudent: RequestHandler = async (req, res, next) => {
try {
const errors = validationResult(req);

const { accountType } = req.body;

validationErrorParser(errors);

const studentId = req.params.id;
Expand All @@ -135,6 +149,13 @@ export const getStudent: RequestHandler = async (req, res, next) => {
return res.status(404).json({ message: "Student not found" });
}

// Ensure that documents that are marked admin are not returned to non-admin users
if (accountType !== "admin") {
studentData.documents = studentData.documents.filter(
(doc) => !doc.markedAdmin,
) as typeof studentData.documents;
}

const enrollments = await EnrollmentModel.find({ studentId });

res.status(200).json({ ...studentData.toObject(), enrollments });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ export const useProgressNotes = () => {
}
};

const fetchStudentData = async (progressNotes: Record<string, ProgressNote>) => {
const fetchStudentData = async (progressNotes: Record<string, ProgressNote>, token: string) => {
try {
const result = await getAllStudents(firebaseToken);
const result = await getAllStudents(token);
if (result.success) {
const studentDataWithNotes: StudentWithNotes[] = result.data.map((student) => ({
...student,
Expand Down Expand Up @@ -92,7 +92,7 @@ export const useProgressNotes = () => {

const progressNotes = await fetchProgressNotes(token);
if (progressNotes) {
await fetchStudentData(progressNotes);
await fetchStudentData(progressNotes, token);
}
})
.catch((error) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/StudentForm/StudentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export default function StudentForm({
Student Information
</legend>

<StudentInfo data={data ?? null} documentData={documentData} />
<StudentInfo data={data ?? null} documentData={documentData} isAdmin={isAdmin} />
</fieldset>
</div>
<div className="grid w-full gap-10 lg:grid-cols-2">
Expand Down
79 changes: 44 additions & 35 deletions frontend/src/components/StudentForm/StudentInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type StudentInfoProps = {
setStudentDocuments: Dispatch<SetStateAction<Document[]>>;
setDidDeleteOrMark: Dispatch<SetStateAction<boolean>>;
};
isAdmin: boolean;
};

const SUPPORTED_FILETYPES = [
Expand All @@ -52,7 +53,7 @@ const SUPPORTED_FILETYPES = [
"image/webp",
];

export default function StudentInfo({ classname, data, documentData }: StudentInfoProps) {
export default function StudentInfo({ classname, data, documentData, isAdmin }: StudentInfoProps) {
const { register, setValue: setCalendarValue } = useFormContext<StudentFormData>();
const [modalOpen, setModalOpen] = useState(false);
const [documentError, setDocumentError] = useState("");
Expand Down Expand Up @@ -200,6 +201,8 @@ export default function StudentInfo({ classname, data, documentData }: StudentIn
);
};

console.log({ isAdmin });

return (
<div className={cn("grid flex-1 gap-x-8 gap-y-10 md:grid-cols-2", classname)}>
<div>
Expand Down Expand Up @@ -283,45 +286,51 @@ export default function StudentInfo({ classname, data, documentData }: StudentIn
onClick={() => {
window.open(document.link, "_blank");
}}
className="rounded-tl-md rounded-tr-md border-[1px] border-solid border-black bg-white px-10 py-4"
className={`${!isAdmin ? "rounded-bl-md rounded-br-md" : ""} rounded-tl-md rounded-tr-md border-[1px] border-solid border-black bg-white px-10 py-4`}
>
View File
</button>
)}

<ModalConfirmation
icon={<GreenQuestionIcon />}
triggerElement={
<button
className={`${!document.link && "rounded-tl-md rounded-tr-md border-t-[1px]"} border-[1px] border-b-0 border-t-0 border-solid border-black bg-white px-10 py-4 text-pia_dark_green`}
>
{document.markedAdmin ? "Unmark" : "Mark"} Admin
</button>
}
title={document.markedAdmin ? "Unmark admin?" : "Mark admin only?"}
description={`${document.markedAdmin ? "Everyone will be able to" : "Only admin will"} see these files`}
confirmText={document.markedAdmin ? "Unmark" : "Mark"}
kind="primary"
onConfirmClick={() => {
handleMarkAdmin(document);
setDidDeleteOrMark(true);
}}
/>
<ModalConfirmation
icon={<RedDeleteIcon />}
triggerElement={
<button className="rounded-bl-md rounded-br-md border-[1px] border-solid border-black bg-white px-10 py-4 text-destructive">
Delete File
</button>
}
title="Are you sure you want to delete?"
confirmText="Delete"
kind="destructive"
onConfirmClick={() => {
handleDeleteDocument(document);
setDidDeleteOrMark(true);
}}
/>
{isAdmin ? (
<>
<ModalConfirmation
icon={<GreenQuestionIcon />}
triggerElement={
<button
className={`${!document.link && "rounded-tl-md rounded-tr-md border-t-[1px]"} border-[1px] border-b-0 border-t-0 border-solid border-black bg-white px-10 py-4 text-pia_dark_green`}
>
{document.markedAdmin ? "Unmark" : "Mark"} Admin
</button>
}
title={document.markedAdmin ? "Unmark admin?" : "Mark admin only?"}
description={`${document.markedAdmin ? "Everyone will be able to" : "Only admin will"} see these files`}
confirmText={document.markedAdmin ? "Unmark" : "Mark"}
kind="primary"
onConfirmClick={() => {
handleMarkAdmin(document);
setDidDeleteOrMark(true);
}}
/>
<ModalConfirmation
icon={<RedDeleteIcon />}
triggerElement={
<button className="rounded-bl-md rounded-br-md border-[1px] border-solid border-black bg-white px-10 py-4 text-destructive">
Delete File
</button>
}
title="Are you sure you want to delete?"
confirmText="Delete"
kind="destructive"
onConfirmClick={() => {
handleDeleteDocument(document);
setDidDeleteOrMark(true);
}}
/>
</>
) : (
""
)}
</PopoverContent>
</Popover>
</Fragment>
Expand Down
123 changes: 81 additions & 42 deletions frontend/src/components/StudentProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function ProgramLayout({ enrollmentInfo }: ProgramLayoutProps) {

export default function StudentProfile({ id }: StudentProfileProps) {
const [currentView, setCurrentView] = useState<"View" | "Edit">("View");
const { firebaseUser } = useContext(UserContext);
const { firebaseUser, isAdmin } = useContext(UserContext);
const [firebaseToken, setFirebaseToken] = useState<string>();
const [notFound, setNotFound] = useState<boolean>(false);
const [studentData, setStudentData] = useState<Student>();
Expand All @@ -176,6 +176,30 @@ export default function StudentProfile({ id }: StudentProfileProps) {
setCurrentView(currentView === "View" ? "Edit" : "View");
};

const TruncateDocument = ({
documentName,
documentLength,
}: {
documentName: string;
documentLength: number;
}) => {
const minLength = 9; // Shortest truncation
const maxLength = 20; // Longest truncation
const baseName = documentName.slice(0, documentName.lastIndexOf("."));

// Use an inverse relationship: fewer documents = longer names
const dynamicLength = Math.max(
minLength,
Math.min(maxLength, 20 - Math.floor((documentLength - 1) * 2)),
);

// Only truncate and add ellipsis if the basename is longer than dynamicLength
const displayName =
baseName.length > dynamicLength ? baseName.substring(0, dynamicLength) + "..." : baseName;

return displayName;
};

const deleteStudentHandler: MouseEventHandler = () => {
const lastName = getDeleteValue("lastname");
if (studentData && firebaseToken && studentData.student.lastName === lastName) {
Expand Down Expand Up @@ -423,12 +447,24 @@ export default function StudentProfile({ id }: StudentProfileProps) {
<div id="documents" className="basis-1/2 space-y-[20px]">
<div className="font-[Poppins-Bold] text-[28px]">Documents</div>
<div className="flex space-x-[20px]">
<button className="h-[48px] w-[116px] rounded-lg border border-pia_border bg-pia_secondary_green text-pia_primary_white">
Student Info
</button>
<button className="h-[48px] w-[116px] rounded-lg border border-pia_border bg-pia_light_gray">
Waivers
</button>
{studentData.documents?.map((doc, index) => (
<button
onClick={() => {
window.open(doc.link, "_blank");
}}
key={index}
className={
index % 2 === 0
? "h-[48px] w-[116px] rounded-lg border border-pia_border bg-pia_light_gray"
: "h-[48px] w-[116px] rounded-lg border border-pia_border bg-pia_secondary_green text-pia_primary_white"
}
>
{TruncateDocument({
documentName: doc.name,
documentLength: doc.name.length,
}) || `Document ${index + 1}`}
</button>
))}
</div>
</div>
<div id="medications" className="basis-1/2 space-y-[20px]">
Expand Down Expand Up @@ -472,43 +508,46 @@ export default function StudentProfile({ id }: StudentProfileProps) {
</div>
<NotificationTable />
</div> */}

<div id="Bottom Buttons" className="flex justify-between">
<ModalConfirmation
className="h-[60%] w-[40%] rounded-[8px]"
title="Are you sure you want to delete this student?"
innerContent={
<>
<div className="flex w-[60%] justify-center">
<div className="font-base text-sm sm:text-base">
<li className="font-bold text-destructive">This cannot be undone!</li>
<li>
This will remove this student from all enrolled programs and delete all
notes and documents.
</li>
{isAdmin && (
<ModalConfirmation
className="h-[60%] w-[40%] rounded-[8px]"
title="Are you sure you want to delete this student?"
innerContent={
<>
<div className="flex w-[60%] justify-center">
<div className="font-base text-sm sm:text-base">
<li className="font-bold text-destructive">This cannot be undone!</li>
<li>
This will remove this student from all enrolled programs and delete all
notes and documents.
</li>
</div>
</div>
</div>
<div className="mx-8 mb-8 mt-6">
Enter the student&apos;s last name to proceed
<Textfield
name="lastname"
placeholder="Last Name"
register={deleteRegister}
/>
</div>
</>
}
kind="destructive"
triggerElement={
<button className="h-[48px] w-[96px] rounded-sm border border-pia_border text-pia_border">
Delete
</button>
}
confirmText="Delete"
icon={<div />}
isParentOpen={deleteDialogOpen}
setIsParentOpen={setDeleteDialogOpen}
onConfirmClick={deleteStudentHandler}
/>
<div className="mx-8 mb-8 mt-6">
Enter the student&apos;s last name to proceed
<Textfield
name="lastname"
placeholder="Last Name"
register={deleteRegister}
/>
</div>
</>
}
kind="destructive"
triggerElement={
<button className="h-[48px] w-[96px] rounded-sm border border-pia_border text-pia_border">
Delete
</button>
}
confirmText="Delete"
icon={<div />}
isParentOpen={deleteDialogOpen}
setIsParentOpen={setDeleteDialogOpen}
onConfirmClick={deleteStudentHandler}
/>
)}
<button
className="h-[48px] w-[96px] rounded-sm border border-pia_dark_green bg-pia_dark_green text-pia_primary_white"
onClick={() => {
Expand Down
Loading

0 comments on commit 5710fff

Please sign in to comment.