Skip to content

Commit

Permalink
Added program edit popup and "no programs" message (#97)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
andrewzpu authored May 8, 2024
1 parent d1d1ff5 commit 26d7248
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 92 deletions.
Binary file added frontend/public/programs/EditIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/programs/Empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
162 changes: 123 additions & 39 deletions frontend/src/components/ProgramCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,69 @@ export type CardProps = {
setPrograms: React.Dispatch<React.SetStateAction<ProgramMap>>;
};

function processDate(startString: Date): string {
const startDate = new Date(startString);
// function checkOffscreen(id: string) {
// const elem = document.getElementById("edit" + id);
// if (elem === null) {
// return;
// }

const options = {
year: "numeric",
month: "short",
day: "numeric",
} as const;
// const bounding = elem.getBoundingClientRect();

return "Started " + startDate.toLocaleDateString("en-US", options);
// console.log(bounding.right);
// console.log(window.innerWidth);
// console.log(document.documentElement.clientWidth);

// return bounding.right + 26 - (window.innerWidth || document.documentElement.clientWidth);
// }

function toggleEdit(id: string) {
const editId = "edit" + id;
console.log(editId);
const editButton = document.getElementById(editId);
if (editButton === null) {
console.log("error");
return;
}

if (editButton.style.display !== "block") {
editButton.style.display = "block";
} else {
editButton.style.display = "none";
}

// if (checkOffscreen(id) > 0) {
// editButton.style.right = "0px";
// }
}

export function ProgramCard({ program, isAdmin, className, setPrograms }: CardProps) {
const { isTablet } = useWindowSize();

const editId = "edit" + program._id;
const optionsId = "option" + program._id;

const optionsButton = document.getElementById(optionsId);
if (optionsButton !== null) {
optionsButton.onclick = function () {
toggleEdit(program._id);
};
}

let editClass = "absolute right-2 hidden";
let outerDivClass = "text-white grow overflow-hidden tracking-wide leading-6";
let topDivClass = "flex flex-row";
let botDivClass = "text-black bg-white";
let typeClass;
let titleClass;
let optionsDiv = "grow";
const optionsClass = "relative float-right hover:cursor-pointer";
let dateClass;
let numClass;
let numTextClass;
let iconClass = "relative";

let optionsHeight = 18;
let optionsWidth = 16;

const programFields: Program = {
_id: program._id,
name: program.name,
Expand All @@ -61,25 +97,27 @@ export function ProgramCard({ program, isAdmin, className, setPrograms }: CardPr
};

if (isTablet) {
editClass += " top-7 w-12 h-5 text-[10px]";
outerDivClass += " rounded-lg h-36";
topDivClass += " h-20";
botDivClass += " h-16";
typeClass = cn("uppercase relative text-[10px] top-2 left-3", poppins.className);
titleClass = cn("capitalize relative text-sm top-2 left-3 font-bold", poppins.className);
optionsDiv += " pr-[8px] pt-[12px]";
dateClass = cn("relative text-[10px] top-2 left-3", poppins.className);
optionsHeight /= 2;
optionsWidth /= 2;
numClass = "h-5 gap-x-1.5 flex flex-row relative top-2 left-3";
numTextClass = cn("text-[10px]", poppins.className);
iconClass = "h-2 w-3 mt-[7px]";
} else {
editClass += " top-12 w-24 h-8";
outerDivClass += " rounded-2xl h-68";
topDivClass += " h-36";
botDivClass += " h-32";
typeClass = cn("uppercase relative text-sm top-5 left-7", poppins.className);
titleClass = cn("capitalize relative text-3xl top-8 left-7 font-bold", poppins.className);
optionsDiv += " pr-[16px] pt-[24px]";
dateClass = cn("relative text-base top-5 left-7", poppins.className);
numClass = "h-8 gap-x-1.5 flex flex-row relative top-14 left-7";
numClass = "h-8 gap-x-1.5 flex flex-row relative top-5 left-7";
numTextClass = cn("text-base", poppins.className);
iconClass = "h-3 w-[18px] mt-[5px]";
}
Expand All @@ -88,37 +126,83 @@ export function ProgramCard({ program, isAdmin, className, setPrograms }: CardPr
outerDivClass = cn(outerDivClass, className);
}

let buttonClass = "relative flex h-full w-full flex-row rounded bg-white";
let iconHeight = 16;
let iconWidth = 16;
let imageClass = "absolute";
let editTextClass = "absolute text-pia_dark_green";

if (isTablet) {
iconHeight = 10;
iconWidth = 10;
buttonClass += " py-[3px]";
imageClass += " left-[7px] top-[5px]";
editTextClass += " right-[7px]";
} else {
buttonClass += " py-1";
imageClass += " left-2.5 top-2";
editTextClass += " left-0 w-full";
}

const editButton: React.JSX.Element = (
<button className={buttonClass} value="Edit">
<Image
className={imageClass}
id="editIcon"
alt="edit"
src="/programs/EditIcon.png"
height={iconHeight}
width={iconWidth}
/>
<p className={editTextClass}>Edit</p>
</button>
);

return (
<div className={outerDivClass}>
<div className={topDivClass} style={{ backgroundColor: program.color }}>
<div>
<p className={typeClass}>{program.type} Program</p>
<p className={titleClass}>{program.name}</p>
</div>
{isAdmin && (
<div className={optionsDiv}>
<div className={optionsClass}>
<ProgramFormButton type="edit" data={programFields} setPrograms={setPrograms} />
</div>
</div>
)}
<div className="relative">
<div id={editId} className={editClass}>
<ProgramFormButton
type="edit"
component={editButton}
data={programFields}
setPrograms={setPrograms}
/>
</div>
<div className={botDivClass}>
<p className={dateClass}>{processDate(program.startDate)}</p>
<div className={numClass}>
<Image
alt="students"
src="/programs/Students.png"
height={12}
width={18}
className={iconClass}
/>
{program.students.length === 0 && <p className={numTextClass}>No Students</p>}
{program.students.length === 1 && <p className={numTextClass}>1 Student</p>}
{program.students.length > 1 && (
<p className={numTextClass}>{program.students.length} Students</p>
<div className={outerDivClass}>
<div className={topDivClass} style={{ backgroundColor: program.color }}>
<div>
<p className={typeClass}>{program.type} Program</p>
<p className={titleClass}>{program.name}</p>
</div>
{isAdmin && (
<div className={optionsDiv}>
<Image
id={optionsId}
alt="options"
src="/programs/Options.png"
height={optionsHeight}
width={optionsWidth}
className={optionsClass}
/>
</div>
)}
</div>
<div className={botDivClass}>
<div className={numClass}>
<Image
alt="students"
src="/programs/Students.png"
height={12}
width={18}
className={iconClass}
/>
{program.students.length === 0 && <p className={numTextClass}>No Students</p>}
{program.students.length === 1 && <p className={numTextClass}>1 Student</p>}
{program.students.length > 1 && (
<p className={numTextClass}>{program.students.length} Students</p>
)}
</div>
</div>
</div>
</div>
);
Expand Down
47 changes: 4 additions & 43 deletions frontend/src/components/ProgramFormButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Image from "next/image";
import { useMemo, useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";

Expand All @@ -17,6 +16,7 @@ import { Dialog, DialogClose, DialogContent, DialogContentSlide, DialogTrigger }

type BaseProperties = {
classname?: string;
component: React.JSX.Element;
setPrograms: React.Dispatch<React.SetStateAction<ProgramMap>>;
};

Expand All @@ -34,6 +34,7 @@ type ProgramFormProperties = EditProperties | AddProperties;

export default function ProgramFormButton({
type = "edit",
component = <p>Please add a component</p>,
data = null,
setPrograms,
classname,
Expand Down Expand Up @@ -117,27 +118,7 @@ export default function ProgramFormButton({
return !isMobile ? (
<>
<Dialog open={openForm} onOpenChange={setOpenForm}>
{type === "add" && (
<DialogTrigger asChild>
<Button
label="Add Program"
onClick={() => {
setOpenForm(true);
}}
/>
</DialogTrigger>
)}
{type === "edit" && (
<DialogTrigger asChild>
<Image
alt="options"
src="/programs/Options.png"
height={18}
width={16}
className={"relative float-right hover:cursor-pointer"}
/>
</DialogTrigger>
)}
<DialogTrigger asChild>{component}</DialogTrigger>
<DialogContentSlide className="w-full bg-white object-right p-6 sm:w-[50%]">
<form onSubmit={handleSubmit(onSubmit)} className={cn(classname)}>
{type === "edit" && (
Expand Down Expand Up @@ -231,27 +212,7 @@ export default function ProgramFormButton({
) : (
<>
<Dialog open={openForm} onOpenChange={setOpenForm}>
{type === "add" && (
<DialogTrigger asChild>
<Button
label="Add Program"
onClick={() => {
setOpenForm(true);
}}
/>
</DialogTrigger>
)}
{type === "edit" && (
<DialogTrigger asChild>
<Image
alt="options"
src="/programs/Options.png"
height={9}
width={8}
className={"relative float-right hover:cursor-pointer"}
/>
</DialogTrigger>
)}
<DialogTrigger asChild>{component}</DialogTrigger>
<DialogContent className="bg-white p-3">
<ProgramCancel
isMobile={isMobile}
Expand Down
Loading

0 comments on commit 26d7248

Please sign in to comment.