Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions frontend/src/components/FieldLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { ReactNode } from "react";

type FieldLabelProps = {
isRequired?: boolean;
className?: string;
children: ReactNode;
};

export default function FieldLabel({
isRequired,
className,
children,
}: FieldLabelProps) {
return (
<label className={className}>
{children}
{isRequired && <span className="text-red ml-1">*</span>}
</label>
);
}
11 changes: 7 additions & 4 deletions frontend/src/main-page/grants/edit-grant/EditGrant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,27 +81,30 @@ const EditGrant: React.FC<{
if (!form.organization.trim()) return "Organization Name is required";
if (!form.status) return "Status is required";
if (form.amount == null || form.amount <= 0) return "Amount must be greater than 0";
Comment thread
maxn990 marked this conversation as resolved.
if (!form.applicationDeadline) return "Due Date is required";
if (!grantToEdit && !form.applicationDeadline) return "Due Date is required";
if (!grantToEdit && !form.grantStartDate) return "Grant Start Date is required";
if (!grantToEdit && !Number.isFinite(form.estimatedCompletionTime)) return "Estimated completion time is required";
if (
form.applicationDate &&
form.applicationDeadline &&
new Date(form.applicationDate).getTime() >
new Date(form.applicationDeadline).getTime()
) {
return "Application Date cannot be after Due Date";
}
if (!form.grantStartDate) return "Grant Start Date is required";
if (
form.grantStartDate &&
form.applicationDeadline &&
new Date(form.grantStartDate).getTime() <
new Date(form.applicationDeadline).getTime()
) {
return "Grant Start Date cannot be before Due Date";
}
if (!form.estimatedCompletionTime || form.estimatedCompletionTime <= 0) return "Estimated completion time must be greater than 0";
if (form.estimatedCompletionTime < 0) return "Estimated completion time cannot be negative";
if (!form.doesBcanQualify) return "BCAN eligibility is required";
if(form.reportDates.length > 0 && !form.reportDates.every((date) => date !== "")) return "Report deadlines must have a value";
if (!form.timeline || form.timeline <= 0) return "Timeline must be greater than 0";
if (!form.bcanPocEmail) return "BCAN contact required";
if (!form.grantProviderPocEmail) return "Grant provider contact required";
if(form.attachments.length > 0 && !form.attachments.every((attachment) => attachment.url !== "")) return "Attachments must have a value";
return null;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Action } from "../processGrantDataEditSave";
import { useState } from "react";
import AddContactPopup from "./AddContactPopup";
import { observer } from "mobx-react-lite";
import FieldLabel from "../../../../components/FieldLabel";

type EditGrantProps = {
form: GrantFormState;
Expand Down Expand Up @@ -34,9 +35,9 @@ const EditGrantContacts = ({ dispatch, form }: EditGrantProps) => {

return (
<div className="w-full h-full">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel isRequired className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Contacts
</label>
</FieldLabel>

<div className="grid grid-cols-2 gap-4 min-h-24 w-full lg:w-[80%] ml-2">
{form.bcanPocEmail !== "" && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
faSquareXmark,
} from "@fortawesome/free-solid-svg-icons";
import EditGrantDeleteItem from "./EditGrantDeleteItem";
import FieldLabel from "../../../../components/FieldLabel";

type EditGrantProps = {
form: GrantFormState;
Expand All @@ -18,9 +19,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
return (
<div className="w-full">
<div className="mb-6">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Description
</label>
</FieldLabel>
<textarea
className="h-32 block w-full text-gray-700 border bg-white border-grey-300 rounded placeholder:text-gray-700 p-2"
placeholder="Enter grant description..."
Expand All @@ -39,9 +40,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
<div className="flex flex-col w-full gap-6 items-start text-left col-span-1">
{/* Amount */}
<div className="w-3/4">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel isRequired className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Amount ($)
</label>
</FieldLabel>
<input
type="number"
min={0}
Expand All @@ -59,9 +60,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {

{/* BCAN Eligible */}
<div className="w-fit">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1 whitespace-nowrap">
<FieldLabel isRequired className="flex text-gray-700 sm:text-sm lg:text-base mb-1 whitespace-nowrap">
BCAN Eligible?
</label>
</FieldLabel>
<div className="flex flex-col gap-1">
<Button
logo={faCheckSquare}
Expand Down Expand Up @@ -97,9 +98,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
<div className="flex flex-col w-full gap-6 items-start text-left col-span-1">
{/* Due Date */}
<div className="">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Due Date
</label>
</FieldLabel>
<input
type="date"
className="appearance-none block w-full h-[2.25rem] text-gray-700 placeholder:text-gray-700 border border-grey-300 rounded-md py-2 px-4"
Expand All @@ -115,9 +116,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
</div>
{/* Application Date */}
<div className="">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Application Date
</label>
</FieldLabel>
<input
type="date"
className="appearance-none block w-full h-[2.25rem] text-gray-700 placeholder:text-gray-700 border border-grey-300 rounded-md py-2 px-4"
Expand All @@ -136,9 +137,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
<div className="flex flex-col w-full gap-6 items-start text-left col-span-1">
{/* Grant Start Date */}
<div>
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Grant Start Date
</label>
</FieldLabel>
<input
type="date"
className="appearance-none block w-full h-[2.25rem] text-gray-700 placeholder:text-gray-700 border border-grey-300 rounded-md py-2 px-4"
Expand All @@ -155,9 +156,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {

{/* Report Deadlines */}
<div className="">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
<FieldLabel className="flex text-gray-700 sm:text-sm lg:text-base mb-1">
Report Deadlines
</label>
</FieldLabel>
<div className="flex flex-col gap-2">
<div className="ml-2 flex flex-col gap-2">
{form.reportDates.map((date, index) => (
Expand Down Expand Up @@ -200,9 +201,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
<div className="flex flex-col w-full gap-6 items-start text-left col-span-1">
{/* Timeline */}
<div className="">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1 ">
<FieldLabel isRequired className="flex text-gray-700 sm:text-sm lg:text-base mb-1 ">
Timeline (years)
</label>
</FieldLabel>
<input
type="number"
min="0"
Expand All @@ -219,9 +220,9 @@ export default function EditGrantInfo({ form, dispatch }: EditGrantProps) {
</div>
{/* Estimated Completion Time */}
<div className="">
<label className="flex text-gray-700 sm:text-sm lg:text-base mb-1 whitespace-nowrap">
<FieldLabel className="flex text-gray-700 sm:text-sm lg:text-base mb-1 whitespace-nowrap">
Estimated Completion Time (hours)
</label>
</FieldLabel>
<input
type="number"
min="0"
Expand Down
18 changes: 12 additions & 6 deletions frontend/src/main-page/grants/grant-view/GrantView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ const GrantItem: React.FC<GrantItemProps> = observer(({ grant }) => {
},
{
label: "Estimated Completion Time (hours)",
value: grant.estimated_completion_time,
value: grant.estimated_completion_time
? grant.estimated_completion_time
: "N/A",
Comment thread
maxn990 marked this conversation as resolved.
},
]}
/>
Expand All @@ -205,12 +207,16 @@ const GrantItem: React.FC<GrantItemProps> = observer(({ grant }) => {
{
label: "Contacts",
item: (
<div className="grid grid-cols-1 2xl:grid-cols-2 w-full h-full lg:w-[90%] gap-6">
<div
className={`grid ${grant.grantmaker_poc?.POC_email ? "grid-cols-1 2xl:grid-cols-2" : "grid-cols-1"} w-full h-full lg:w-[90%] gap-6`}
>
<ContactCard contact={grant.bcan_poc} type="BCAN" />
<ContactCard
contact={grant.grantmaker_poc}
type="Granter"
/>
{grant.grantmaker_poc?.POC_email && (
<ContactCard
contact={grant.grantmaker_poc}
type="Granter"
/>
)}
</div>
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ interface GrantCardProps {

const GrantCard: React.FC<GrantCardProps> = ({ grant, isSelected, onClick }) => {

const formattedDate = new Date(grant.application_deadline).toLocaleDateString('en-US', {
month: 'numeric',
day: 'numeric',
year: '2-digit',
});
const formattedDate = grant.application_deadline
? new Date(grant.application_deadline).toLocaleDateString('en-US', {
month: 'numeric',
day: 'numeric',
year: '2-digit',
})
: "N/A";

return (
<div
Expand Down
Loading