From 24fea2979d4b34997d1a31a0d66c2a05db27d62e Mon Sep 17 00:00:00 2001 From: pujitakalinadhabhotla <161961520+pujitakalinadhabhotla@users.noreply.github.com> Date: Wed, 15 Apr 2026 23:16:06 -0400 Subject: [PATCH 1/5] added ExportModal component and tester page --- apps/frontend/src/app.tsx | 5 ++++ .../DonationInformationModal.tsx | 0 .../components/DonationModals/ExportModal.tsx | 29 +++++++++++++++++++ .../DonationModals/ExportModalTester.tsx | 20 +++++++++++++ .../DonationModals/NewDonationModal.tsx | 0 .../DonationModals/SortingModal.tsx | 0 6 files changed, 54 insertions(+) create mode 100644 apps/frontend/src/components/DonationModals/DonationInformationModal.tsx create mode 100644 apps/frontend/src/components/DonationModals/ExportModal.tsx create mode 100644 apps/frontend/src/components/DonationModals/ExportModalTester.tsx create mode 100644 apps/frontend/src/components/DonationModals/NewDonationModal.tsx create mode 100644 apps/frontend/src/components/DonationModals/SortingModal.tsx diff --git a/apps/frontend/src/app.tsx b/apps/frontend/src/app.tsx index 1d1f2d4..80fb09b 100644 --- a/apps/frontend/src/app.tsx +++ b/apps/frontend/src/app.tsx @@ -18,6 +18,7 @@ import { DonorStatsChart } from '@components/DonorStatsChart'; import SidebarTester from '@containers/dashboard/sidebar/SidebarTester'; import EditDonationGoalTester from '@components/DonationGoal/EditDonationGoalTester'; import { AdminGrowingGoalTester } from '@containers/dashboard/AdminGrowingGoalTester'; +import ExportModalTester from '@components/DonationModals/ExportModalTester'; const router = createBrowserRouter([ { @@ -51,6 +52,10 @@ const router = createBrowserRouter([ path: '/sidebar-test', element: , }, + { + path: '/export-modal-test', + element: , + }, { path: '/edit-donation-goal-test', element: , diff --git a/apps/frontend/src/components/DonationModals/DonationInformationModal.tsx b/apps/frontend/src/components/DonationModals/DonationInformationModal.tsx new file mode 100644 index 0000000..e69de29 diff --git a/apps/frontend/src/components/DonationModals/ExportModal.tsx b/apps/frontend/src/components/DonationModals/ExportModal.tsx new file mode 100644 index 0000000..67936e5 --- /dev/null +++ b/apps/frontend/src/components/DonationModals/ExportModal.tsx @@ -0,0 +1,29 @@ +type ExportModalProps = { + onExportCsv?: () => void; + onExportPdf?: () => void; +}; + +export default function ExportModal({ + onExportCsv, + onExportPdf, +}: ExportModalProps) { + return ( +
+ + + +
+ ); +} diff --git a/apps/frontend/src/components/DonationModals/ExportModalTester.tsx b/apps/frontend/src/components/DonationModals/ExportModalTester.tsx new file mode 100644 index 0000000..a7ca94d --- /dev/null +++ b/apps/frontend/src/components/DonationModals/ExportModalTester.tsx @@ -0,0 +1,20 @@ +import ExportModal from './ExportModal'; + +export default function ExportModalTester() { + return ( +
+
+

ExportModal tester

+ + { + console.log('Export as CSV clicked'); + }} + onExportPdf={() => { + console.log('Export as PDF clicked'); + }} + /> +
+
+ ); +} diff --git a/apps/frontend/src/components/DonationModals/NewDonationModal.tsx b/apps/frontend/src/components/DonationModals/NewDonationModal.tsx new file mode 100644 index 0000000..e69de29 diff --git a/apps/frontend/src/components/DonationModals/SortingModal.tsx b/apps/frontend/src/components/DonationModals/SortingModal.tsx new file mode 100644 index 0000000..e69de29 From 9055d3d1689ee40ebe2d074b949c6f2b3f783376 Mon Sep 17 00:00:00 2001 From: pujitakalinadhabhotla <161961520+pujitakalinadhabhotla@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:57:52 -0400 Subject: [PATCH 2/5] Added DonationInformationModal component with date, recurrence, and amount filters --- apps/frontend/src/api/apiClient.ts | 2 +- apps/frontend/src/app.tsx | 5 + .../DonationInformationModal.tsx | 341 ++++++++++++++++++ .../DonationInformationModalTester.tsx | 9 + 4 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 apps/frontend/src/components/DonationModals/DonationInformationModalTester.tsx diff --git a/apps/frontend/src/api/apiClient.ts b/apps/frontend/src/api/apiClient.ts index 1502437..64f4f33 100644 --- a/apps/frontend/src/api/apiClient.ts +++ b/apps/frontend/src/api/apiClient.ts @@ -127,7 +127,7 @@ export class ApiClient { this.handleAxiosError(err, 'Failed to reset password'); } } - + public async getActiveGoalSummary(): Promise { try { const res = await this.axiosInstance.get('/api/donations/goal/active'); diff --git a/apps/frontend/src/app.tsx b/apps/frontend/src/app.tsx index 80fb09b..4bac1ca 100644 --- a/apps/frontend/src/app.tsx +++ b/apps/frontend/src/app.tsx @@ -19,6 +19,7 @@ import SidebarTester from '@containers/dashboard/sidebar/SidebarTester'; import EditDonationGoalTester from '@components/DonationGoal/EditDonationGoalTester'; import { AdminGrowingGoalTester } from '@containers/dashboard/AdminGrowingGoalTester'; import ExportModalTester from '@components/DonationModals/ExportModalTester'; +import { DonationInformationModalTester } from '@components/DonationModals/DonationInformationModalTester'; const router = createBrowserRouter([ { @@ -56,6 +57,10 @@ const router = createBrowserRouter([ path: '/export-modal-test', element: , }, + { + path: '/donation-information-modal-test', + element: , + }, { path: '/edit-donation-goal-test', element: , diff --git a/apps/frontend/src/components/DonationModals/DonationInformationModal.tsx b/apps/frontend/src/components/DonationModals/DonationInformationModal.tsx index e69de29..1eb9136 100644 --- a/apps/frontend/src/components/DonationModals/DonationInformationModal.tsx +++ b/apps/frontend/src/components/DonationModals/DonationInformationModal.tsx @@ -0,0 +1,341 @@ +import { useState } from 'react'; +import { Calendar } from 'lucide-react'; + +interface RecurrenceOption { + id: string; + label: string; + left: string; + top: string; + checkLeft: string; + checkTop: string; +} + +const RECURRENCE_OPTIONS: RecurrenceOption[] = [ + { + id: 'one-time', + label: 'One-Time', + left: 'left-[20px]', + top: 'top-[128px]', + checkLeft: 'left-[29.03px]', + checkTop: 'top-[136px]', + }, + { + id: 'weekly', + label: 'Weekly', + left: 'left-[126px]', + top: 'top-[128px]', + checkLeft: 'left-[136.03px]', + checkTop: 'top-[136px]', + }, + { + id: 'monthly', + label: 'Monthly', + left: 'left-[20px]', + top: 'top-[165px]', + checkLeft: 'left-[29.03px]', + checkTop: 'top-[173px]', + }, + { + id: 'yearly', + label: 'Yearly', + left: 'left-[126px]', + top: 'top-[165px]', + checkLeft: 'left-[136.03px]', + checkTop: 'top-[173px]', + }, +]; + +const LABEL_POSITIONS: Record = { + 'one-time': { left: 'left-[49.23px]', top: 'top-[136px]' }, + weekly: { left: 'left-[157px]', top: 'top-[136px]' }, + monthly: { left: 'left-[49px]', top: 'top-[173px]' }, + yearly: { left: 'left-[157px]', top: 'top-[173px]' }, +}; + +const INITIAL_SELECTED = { + 'one-time': true, + weekly: true, + monthly: true, + yearly: true, +}; + +const INITIAL_RANGE: [number, number] = [0, 1000]; + +export const DonationInformationModal = () => { + const [selected, setSelected] = + useState>(INITIAL_SELECTED); + const [amountRange, setAmountRange] = + useState<[number, number]>(INITIAL_RANGE); + const [amountFrom, setAmountFrom] = useState(''); + const [amountTo, setAmountTo] = useState(''); + const [dateFrom, setDateFrom] = useState(''); + const [dateTo, setDateTo] = useState(''); + + const toggleOption = (id: string) => { + setSelected((prev) => ({ ...prev, [id]: !prev[id] })); + }; + + const handleReset = () => { + setSelected(INITIAL_SELECTED); + setAmountRange(INITIAL_RANGE); + setAmountFrom(''); + setAmountTo(''); + setDateFrom(''); + setDateTo(''); + }; + + const handleApply = () => { + // TODO: wire up apply logic + }; + + const handleMinChange = (e: React.ChangeEvent) => { + const value = Number(e.target.value); + if (value < amountRange[1]) { + setAmountRange([value, amountRange[1]]); + } + }; + + const handleMaxChange = (e: React.ChangeEvent) => { + const value = Number(e.target.value); + if (value > amountRange[0]) { + setAmountRange([amountRange[0], value]); + } + }; + + const formatDate = (value: string) => { + if (!value) return ''; + const [year, month, day] = value.split('-'); + return `${month}/${day}/${year}`; + }; + + const placeholderLabelClass = + "text-neutral-500 text-[10px] font-normal font-['Source_Sans_Pro'] leading-4"; + const blackLabelClass = + "text-black text-[10px] font-normal font-['Source_Sans_Pro'] leading-4"; + + const DateBox = ({ + label, + value, + onChange, + left, + }: { + label: string; + value: string; + onChange: (v: string) => void; + left: string; + }) => ( +
+
+ {label} +
+
+ +
+ + {value ? formatDate(value) : 'MM/DD/YYYY'} + + onChange(e.target.value)} + className="absolute inset-0 w-full h-full opacity-0 cursor-pointer" + /> +
+
+
+ ); + + return ( +
+ {/* Date Label */} +
+ Date +
+ + + + + {/* Recurrence Label */} +
+ Recurrence +
+ + {/* Recurrence Checkboxes */} + {RECURRENCE_OPTIONS.map((option) => ( +
toggleOption(option.id)} + className="cursor-pointer" + > +
+
+ {selected[option.id] && ( + + + + )} +
+
+ {option.label} +
+
+ ))} + + {/* Amount Label */} +
+ Amount +
+ + {/* Slider Track */} +
+ + {/* Slider Min */} + + + {/* Slider Max */} + + {/* Min Label */} +
+ Min +
+ + {/* Max Label */} +
+ Max +
+ + {/* Amount From Box */} +
+
From
+ setAmountFrom(e.target.value)} + className={`w-full bg-transparent border-none outline-none ${blackLabelClass}`} + /> +
+ + {/* Amount To Box */} +
+
To
+ setAmountTo(e.target.value)} + className={`w-full bg-transparent border-none outline-none ${blackLabelClass}`} + /> +
+ + {/* Reset Button */} + + + {/* Apply Button */} + +
+ ); +}; diff --git a/apps/frontend/src/components/DonationModals/DonationInformationModalTester.tsx b/apps/frontend/src/components/DonationModals/DonationInformationModalTester.tsx new file mode 100644 index 0000000..c87b599 --- /dev/null +++ b/apps/frontend/src/components/DonationModals/DonationInformationModalTester.tsx @@ -0,0 +1,9 @@ +import { DonationInformationModal } from './DonationInformationModal'; + +export const DonationInformationModalTester = () => { + return ( +
+ +
+ ); +}; From 7a5e3439df7e235626c518cee8041c663c0f5c80 Mon Sep 17 00:00:00 2001 From: pujitakalinadhabhotla <161961520+pujitakalinadhabhotla@users.noreply.github.com> Date: Thu, 16 Apr 2026 14:25:44 -0400 Subject: [PATCH 3/5] Added NewDonationModal component with form fields and tester route --- apps/frontend/src/app.tsx | 5 + .../DonationModals/NewDonationModal.tsx | 172 ++++++++++++++++++ .../DonationModals/NewDonationModalTester.tsx | 9 + 3 files changed, 186 insertions(+) create mode 100644 apps/frontend/src/components/DonationModals/NewDonationModalTester.tsx diff --git a/apps/frontend/src/app.tsx b/apps/frontend/src/app.tsx index 4bac1ca..a4b7be5 100644 --- a/apps/frontend/src/app.tsx +++ b/apps/frontend/src/app.tsx @@ -20,6 +20,7 @@ import EditDonationGoalTester from '@components/DonationGoal/EditDonationGoalTes import { AdminGrowingGoalTester } from '@containers/dashboard/AdminGrowingGoalTester'; import ExportModalTester from '@components/DonationModals/ExportModalTester'; import { DonationInformationModalTester } from '@components/DonationModals/DonationInformationModalTester'; +import { NewDonationModalTester } from '@components/DonationModals/NewDonationModalTester'; const router = createBrowserRouter([ { @@ -77,6 +78,10 @@ const router = createBrowserRouter([ path: '/admin-growing-goal-test', element: , }, + { + path: '/new-donation-modal-test', + element: , + }, { path: '/chart', element: , diff --git a/apps/frontend/src/components/DonationModals/NewDonationModal.tsx b/apps/frontend/src/components/DonationModals/NewDonationModal.tsx index e69de29..d2d92c9 100644 --- a/apps/frontend/src/components/DonationModals/NewDonationModal.tsx +++ b/apps/frontend/src/components/DonationModals/NewDonationModal.tsx @@ -0,0 +1,172 @@ +import { useState } from 'react'; +import { Calendar } from 'lucide-react'; + +export const NewDonationModal = () => { + const [firstName, setFirstName] = useState(''); + const [lastName, setLastName] = useState(''); + const [email, setEmail] = useState(''); + const [amount, setAmount] = useState(''); + const [date, setDate] = useState(''); + const [reason, setReason] = useState(''); + + const handleCancel = () => { + setFirstName(''); + setLastName(''); + setEmail(''); + setAmount(''); + setDate(''); + setReason(''); + //might hsve to change this logic + }; + + const handleAdd = () => { + // TODO: wire up add logic + }; + + const labelClass = + "justify-start text-neutral-700 text-xl font-semibold font-['Source_Sans_Pro']"; + const inputClass = + "w-full bg-transparent border-none outline-none text-neutral-500 text-xl font-normal font-['Source_Sans_Pro'] placeholder:text-neutral-500"; + const boxClass = + 'absolute px-5 pt-2 pb-3 bg-white rounded-[10px] outline outline-1 outline-offset-[-1px] outline-neutral-500 inline-flex justify-start items-center'; + + return ( +
+ {/* Title */} +
+ New Donation +
+ + {/* First Name Label */} +
+ First Name +
+ + {/* First Name Input */} +
+ setFirstName(e.target.value)} + placeholder="Enter First Name" + className={inputClass} + /> +
+ + {/* Last Name Label */} +
+ Last Name +
+ + {/* Last Name Input */} +
+ setLastName(e.target.value)} + placeholder="Enter Last Name" + className={inputClass} + /> +
+ + {/* Email Label */} +
+ Email +
+ + {/* Email Input */} +
+ setEmail(e.target.value)} + placeholder="Enter Email Address" + className={inputClass} + /> +
+ + {/* Amount Label */} +
+ Amount +
+ + {/* Amount Input */} +
+ setAmount(e.target.value)} + placeholder="Enter Amount" + className={inputClass} + /> +
+ + {/* Date Label */} +
+ Date +
+ + {/* Date Input */} +
+
+ + {date ? date : 'MM/DD/YYYY'} + + setDate(e.target.value)} + placeholder="MM/DD/YYYY" + maxLength={10} + className="absolute inset-0 w-full bg-transparent border-none outline-none text-neutral-500 text-xl font-normal font-['Source_Sans_Pro'] placeholder:text-neutral-500" + /> +
+ +
+ + {/* Reason Label */} +
+ Reason +
+ + {/* Reason Textarea */} +
+