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
2 changes: 1 addition & 1 deletion frontend/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function Button({ text, onClick, className, logo, logoPosition, d
<button onClick={onClick} disabled={disabled || false} type={type || "button"}
className={`
px-4 py-2 rounded-3xl font-medium text-black border-2 active:bg-primary-900 active:border-primary-900 active:text-white
flex items-center justify-center transition-opacity
h-fit flex items-center justify-center transition-opacity
${className} ${disabled
? "cursor-not-allowed opacity-50"
: "hover:opacity-90"}
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/InputField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type InputFieldProps = {
label: string;
required?: boolean;
error?: boolean;
className?: string;
} & Omit<InputHTMLAttributes<HTMLInputElement>, "id" | "className">;

/**
Expand All @@ -20,7 +21,7 @@ export default function InputField({
}: InputFieldProps) {
return (
<div className="w-full">
<label htmlFor={id} className="block text-left font-bold text-black">
<label htmlFor={id} className="block text-left font-semibold">
{label}
{required && <span className="text-red">*</span>}
</label>
Expand All @@ -29,7 +30,7 @@ export default function InputField({
id={id}
{...inputProps}
className={`block w-full rounded-md py-2.5 pl-4 pr-3 text-base border-2 placeholder:text-grey-500 ${
error ? "border-red bg-red-lightest" : "border-grey-500 bg-white "
error ? "border-red bg-red-lightest" : "border-grey-500 bg-grey-100 "
}`}

/>
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/external/bcanSatchel/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { User } from '../../../../middle-layer/types/User'
import { Grant } from '../../../../middle-layer/types/Grant'
import { Status } from '../../../../middle-layer/types/Status'
import { Notification } from '../../../../middle-layer/types/Notification'
import { CashflowRevenue } from '../../../../middle-layer/types/CashflowRevenue'
import { CashflowCost } from '../../../../middle-layer/types/CashflowCost'

export interface AppState {
isAuthenticated: boolean;
Expand All @@ -25,6 +27,8 @@ export interface AppState {
userSort: {header: keyof User, sort: "asc" | "desc" | "none"} | null;
notifications: Notification[];
userQuery: string;
revenueSource: CashflowRevenue[];
costSource: CashflowCost[];
}

// Define initial state
Expand All @@ -48,6 +52,8 @@ const initialState: AppState = {
sort: null,
userSort: null,
userQuery: '',
revenueSource: [],
costSource: [],
};

/**
Expand Down
90 changes: 47 additions & 43 deletions frontend/src/main-page/cash-flow/CashFlowPage.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,62 @@
import "../dashboard/styles/Dashboard.css";
import { observer } from "mobx-react-lite";
import CashFlowCard from "./components/CashFlowCard";
import {
faDollarSign,
faArrowTrendUp,
faUserGroup,
} from "@fortawesome/free-solid-svg-icons";
import "../dashboard/styles/Dashboard.css";
import CashPosition from "./components/CashPosition";
import CashAnnualSettings from "./components/CashAnnualSettings";
import CashProjection from "./components/CashProjection";
import CashAdd from "./components/CashCreateLineItem";
import CashSourceList from "./components/CashSourceList";

const CashFlowPage = observer(() => {
return (
<div className="dashboard-page">
<div className="grid grid-cols-4 grid-rows-[1fr_3fr_3fr] gap-4 min-h-screen">
<div className="">
<div className="grid grid-cols-4 grid-rows-[auto_auto_1fr] gap-4">
{/* Row 1 */}
<div className="chart-container h-full">
{/* Card 1 placeholder */}
</div>

<div className="chart-container h-full">
{/* Card 2 placeholder */}
</div>

<div className="chart-container h-full">
{/* Card 3 placeholder */}
</div>

<div className="chart-container h-full">
{/* Card 4 placeholder */}
</div>
<CashFlowCard
text="Current Cash"
value="$50,000"
logo={faDollarSign}
className="text-blue"
/>
<CashFlowCard
text="Total Revenue"
value="$50,000"
logo={faArrowTrendUp}
className="text-green"
/>
<CashFlowCard
text="Monthly Costs"
value="$50,000"
logo={faUserGroup}
className="text-primary"
/>
<CashFlowCard
text="Annual Increases"
value="Salary: 4.5% | Benefits: 4%"
logo={faArrowTrendUp}
className="text-green"
size="small"
/>

{/* Row 2 */}
<div className="chart-container col-span-2 h-full">
{/* Card 1 placeholder */}
<div className="bg-grey-200 px-2 py-2 h-14 rounded-full">
<div className="bg-white h-full w-1/2 rounded-full">
</div>
</div>
</div>

<div className="chart-container col-span-2 h-full flex flex-col">
{/* Card 2 placeholder */}
<div className="mt-auto flex gap-2">
{/* 4 buttons at bottom */}
<div className="bg-grey-200 rounded-md flex-1 h-14"></div>
<div className="bg-grey-200 rounded-md flex-1 h-14"></div>
<div className="bg-grey-200 rounded-md flex-1 h-14"></div>
<div className="bg-grey-200 rounded-md flex-1 h-14"></div>
</div>
</div>
<CashPosition />
<CashAnnualSettings />

{/* Row 3 */}
<div className="chart-container col-span-2 h-full">
{/* Card 1 placeholder */}
</div>
<CashAdd />
<CashProjection />

<div className="chart-container col-span-2 h-full">
{/* Card 2 placeholder */}
</div>
{/* Row 4 */}
<CashSourceList type="Revenue" />
<CashSourceList type="Cost" />
</div>
</div>
);
});

export default CashFlowPage;
export default CashFlowPage;
39 changes: 39 additions & 0 deletions frontend/src/main-page/cash-flow/components/CashAddCosts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { CostType } from "../../../../../middle-layer/types/CostType";
import Button from "../../../components/Button";
import InputField from "../../../components/InputField";
import CashCategoryDropdown from "./CashCategoryDropdown";

export default function CashAddCosts() {
return (
<div className="flex flex-col pt-2 px-2 col-span-2 h-full gap-2">
<div className="text-lg lg:text-xl w-full text-left font-bold">
{"Add Cost Source"}
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 w-full justify-between gap-4">
<div className="flex flex-col col-span-1 w-full gap-3">
<CashCategoryDropdown type={CostType} onChange={() => {}} />
</div>
<div className="flex flex-col col-span-1 gap-3">
<InputField
type="text"
id="cost_name"
label="Cost Item Name"
value={"Program Directory"}
/>
</div>
</div>
<InputField
type="number"
id="amount"
label="Annual Amount ($)"
value={"325000"}
className="w-full"
/>
<Button
text="Add Cost Item"
onClick={() => alert("add cost source")}
className="bg-primary text-white mt-2"
/>
</div>
);
}
52 changes: 52 additions & 0 deletions frontend/src/main-page/cash-flow/components/CashAddRevenue.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { RevenueType } from "../../../../../middle-layer/types/RevenueType";
import Button from "../../../components/Button";
import InputField from "../../../components/InputField";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import CashCategoryDropdown from "./CashCategoryDropdown";

export default function CashAddRevenue() {
return (
<div className="flex flex-col pt-2 px-2 col-span-2 h-full gap-2">
<div className="text-lg lg:text-xl w-full text-left font-bold">
{"Add Revenue Source"}
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 w-full justify-between gap-4">
<div className="flex flex-col col-span-1 w-full gap-2">
<CashCategoryDropdown type={RevenueType} onChange={() => {}} />
<InputField
type="number"
id="amount"
label="Amount ($)"
value={"325000"}
/>
</div>
<div className="flex flex-col col-span-1 gap-2">
<InputField
type="text"
id="source_name"
label="Revenue Source Name"
value={"Foundation Grant"}
/>
<InputField
type="date"
id="date"
label="Date"
value={new Date().toDateString()}
/>
</div>
</div>
<Button
text="Add Installment"
onClick={() => alert("add installment")}
logo={faPlus}
logoPosition="left"
className="bg-primary-900 text-white w-fit ml-auto text-sm"
/>
<Button
text="Add Revenue Source"
onClick={() => alert("add revenue source")}
className="bg-green text-white mt-2"
/>
</div>
);
}
27 changes: 27 additions & 0 deletions frontend/src/main-page/cash-flow/components/CashAnnualSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import InputField from "../../../components/InputField";

export default function CashAnnualSettings() {

return (
<div className="chart-container col-span-2 h-full">
<div className="text-lg lg:text-xl mb-2 w-full text-left font-bold">
{"Annual Increase Settings"}
</div>
<div className="flex flex-row justify-between gap-4">
<InputField
type="number"
id="salary_increase"
label="Personnel Salary Increase (%)"
value={"3.5"}
className=""
/>
<InputField
type="number"
id="benefits_increase"
label="Personnel Benefits Increase (%)"
value={"4.0"}
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CostType } from "../../../../../middle-layer/types/CostType";
import { RevenueType } from "../../../../../middle-layer/types/RevenueType";

type CashCategoryDropdown = {
type: typeof RevenueType | typeof CostType;
onChange: () => void;
};

export default function CashCategoryDropdown({
type,
onChange,
}: CashCategoryDropdown) {
return (
<div className="w-full">
<label htmlFor={"Category"} className="block text-left font-semibold">
{"Category"}
</label>
<div className="mt-2 flex items-center rounded-md">
<select
id="Category"
value={"Grants"}
onChange={onChange}
className="block w-full rounded-md py-2.5 pl-4 pr-3 text-base border-2 placeholder:text-grey-500 ${
border-grey-500 bg-grey-100 h-[3rem]"
>
{Object.values(type).map((r) => (
<option key={r} value={r}>
{r}
</option>
))}
</select>
</div>
</div>
);
}
30 changes: 30 additions & 0 deletions frontend/src/main-page/cash-flow/components/CashCreateLineItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useState } from "react";
import Button from "../../../components/Button";
import CashAddRevenue from "./CashAddRevenue";
import CashAddCosts from "./CashAddCosts";

export default function CashCreateLineItem() {
const [showCosts, setShowCosts] = useState<boolean>(false);

return (
<div className="chart-container col-span-2 h-full">
<div className="flex flex-row rounded-4xl p-1 border border-grey-500 mb-2">
<Button
text="Revenue"
onClick={() => setShowCosts(!showCosts)}
className={`w-1/2 font-semibold ${!showCosts ? "bg-primary-900 text-white" : "bg-white"}`}
/>
<Button
text="Costs"
onClick={() => setShowCosts(!showCosts)}
className={`w-1/2 font-semibold ${showCosts ? "bg-primary-900 text-white" : "bg-white"}`}
/>
</div>

<div className="">
{!showCosts && <CashAddRevenue />}
{showCosts && <CashAddCosts />}
</div>
</div>
);
}
Loading
Loading