diff --git a/package-lock.json b/package-lock.json index 8a61619..55fde1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "mongoose": "^7.4.5", "next": "13.4.19", "next-auth": "^4.24.7", + "nodemailer": "^6.9.15", "react": "18.2.0", "react-dom": "18.2.0", "react-google-button": "^0.7.2", @@ -31,6 +32,7 @@ "@testing-library/react": "^14.0.0", "@types/jest": "^29.5.4", "@types/node": "20.5.6", + "@types/nodemailer": "^6.4.16", "@types/react": "18.2.21", "@types/react-dom": "18.2.7", "@typescript-eslint/eslint-plugin": "^6.4.1", @@ -55,9 +57,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", "dev": true }, "node_modules/@ampproject/remapping": { @@ -2324,6 +2326,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz", "integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==" }, + "node_modules/@types/nodemailer": { + "version": "6.4.16", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.16.tgz", + "integrity": "sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/parse-json": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", @@ -3128,12 +3139,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -4897,9 +4908,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5530,9 +5541,9 @@ } }, "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" }, "node_modules/is-arguments": { "version": "1.1.1", @@ -8020,6 +8031,14 @@ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, + "node_modules/nodemailer": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -10282,9 +10301,9 @@ } }, "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index c814e0b..5267e86 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "mongoose": "^7.4.5", "next": "13.4.19", "next-auth": "^4.24.7", + "nodemailer": "^6.9.15", "react": "18.2.0", "react-dom": "18.2.0", "react-google-button": "^0.7.2", @@ -34,6 +35,7 @@ "@testing-library/react": "^14.0.0", "@types/jest": "^29.5.4", "@types/node": "20.5.6", + "@types/nodemailer": "^6.4.16", "@types/react": "18.2.21", "@types/react-dom": "18.2.7", "@typescript-eslint/eslint-plugin": "^6.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35b02e9..d5c3e30 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ dependencies: specifier: ^4.24.7 version: 4.24.7(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) version: 13.4.19(@babel/core@7.25.7)(react-dom@18.2.0)(react@18.2.0) + nodemailer: + specifier: ^6.9.15 + version: 6.9.15 react: specifier: 18.2.0 version: 18.2.0 @@ -73,6 +76,9 @@ devDependencies: '@types/node': specifier: 20.5.6 version: 20.5.6 + '@types/nodemailer': + specifier: ^6.4.16 + version: 6.4.16 '@types/react': specifier: 18.2.21 version: 18.2.21 @@ -4539,6 +4545,12 @@ snapshots: /@types/node@20.5.6: resolution: {integrity: sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==} + /@types/nodemailer@6.4.16: + resolution: {integrity: sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==} + dependencies: + '@types/node': 20.5.6 + dev: true + /@types/parse-json@4.0.2: resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} dev: false @@ -7854,6 +7866,11 @@ snapshots: /node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + /nodemailer@6.9.15: + resolution: {integrity: sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==} + engines: {node: '>=6.0.0'} + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} diff --git a/src/app/api/donors/[donorId]/route.ts b/src/app/api/donors/[donorId]/route.ts index 830873e..6999921 100644 --- a/src/app/api/donors/[donorId]/route.ts +++ b/src/app/api/donors/[donorId]/route.ts @@ -1,4 +1,4 @@ -import { DonorResponse } from '@/types/persons'; +import { DonorResponse } from '@/types/donors'; import { NextResponse, NextRequest } from 'next/server'; import { getDonorById, updateDonor } from '../../../../server/actions/donors'; @@ -19,7 +19,7 @@ export async function GET( return NextResponse.json(result, { status: 200 }); } catch (error) { // if the donor is not found, return a 500 error - return NextResponse.json({ error: 'Donor not found' }, { status: 500 }); + return NextResponse.json({ error: 'Donor not found' }, { status: 404 }); } } @@ -52,7 +52,7 @@ export async function PUT( return NextResponse.json(updatedDonor, { status: 200 }); } catch (error) { // Handle any errors during parsing or updating - const message = error instanceof Error ? error.message : 'Unknowm errpr'; + const message = error instanceof Error ? error.message : 'Unknown error'; return NextResponse.json( { error: 'Failed to update donor information', details: message }, { status: 500 } diff --git a/src/app/api/donors/route.ts b/src/app/api/donors/route.ts index ff22892..3204bd1 100644 --- a/src/app/api/donors/route.ts +++ b/src/app/api/donors/route.ts @@ -1,20 +1,17 @@ import { NextRequest, NextResponse } from 'next/server'; import { getAllDonors, createDonors } from '@/server/actions/donors'; -import { DonorResponse, zCreateDonorRequest } from '@/types/persons'; +import { DonorResponse, zCreateDonorRequest } from '@/types/donors'; -export async function GET(request: NextRequest) { - if (request.method == 'GET') { - try { - const response: DonorResponse[] = await getAllDonors(); // Call getDonors function - return NextResponse.json(response, { status: 200 }); // Return result with status 200 on success - } catch (error) { - console.error(error); // Log the error for debugging - return NextResponse.json('Unknown error', { status: 500 }); // Return status 500 for unknown errors - } +export async function GET() { + try { + const response: DonorResponse[] = await getAllDonors(); // Call getDonors function + return NextResponse.json(response, { status: 200 }); // Return result with status 200 on success + } catch (error) { + console.error(error); // Log the error for debugging + return NextResponse.json('Unknown error', { status: 500 }); // Return status 500 for unknown errors } } - export async function POST(request: NextRequest) { try { const requestBody = await request.json(); @@ -36,6 +33,5 @@ export async function POST(request: NextRequest) { // create a response for any unknown errors console.log(error); return NextResponse.json({ message: 'Unknown Error' }, { status: 500 }); - } } diff --git a/src/app/api/items/route.ts b/src/app/api/items/route.ts index 84a84d3..debf20c 100644 --- a/src/app/api/items/route.ts +++ b/src/app/api/items/route.ts @@ -1,7 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; import { createItem, getAllItems } from '@/server/actions/items'; import { zCreateItemRequest } from '@/types/items'; -// import { CreateItem } from '@/server/actions/items'; export async function POST(request: NextRequest) { try { diff --git a/src/app/donors/[donorId]/page.tsx b/src/app/donors/[donorId]/page.tsx index 0d58acd..9aa0571 100644 --- a/src/app/donors/[donorId]/page.tsx +++ b/src/app/donors/[donorId]/page.tsx @@ -1,5 +1,5 @@ import { getDonorById } from '@/server/actions/donors'; -import { DonorResponse } from '@/types/persons'; +import { DonorResponse } from '@/types/donors'; import DonorIdView from '@/views/donorIdView'; export default async function DonorEditPage({ diff --git a/src/app/donors/page.tsx b/src/app/donors/page.tsx index 2fbf8c5..6fe82c6 100644 --- a/src/app/donors/page.tsx +++ b/src/app/donors/page.tsx @@ -1,7 +1,7 @@ import { getAllDonations } from '@/server/actions/donations'; import { getAllDonors } from '@/server/actions/donors'; import { DonationResponse } from '@/types/donation'; -import { DonorResponse } from '@/types/persons'; +import { DonorResponse } from '@/types/donors'; import DonorView from '@/views/donorView'; export default async function DonorPage() { diff --git a/src/components/donation-form/AutofillDonorEmail.tsx b/src/components/donation-form/AutofillDonorEmail.tsx index f953b9a..3a174bd 100644 --- a/src/components/donation-form/AutofillDonorEmail.tsx +++ b/src/components/donation-form/AutofillDonorEmail.tsx @@ -1,5 +1,5 @@ import { DonorFormData } from '@/types/forms/donor'; -import { DonorResponse } from '@/types/persons'; +import { DonorResponse } from '@/types/donors'; import { Autocomplete, TextField } from '@mui/material'; import { useState } from 'react'; diff --git a/src/components/donationItemForm/index.tsx b/src/components/donationItemForm/index.tsx index a00f53b..c858c7e 100644 --- a/src/components/donationItemForm/index.tsx +++ b/src/components/donationItemForm/index.tsx @@ -79,7 +79,7 @@ export default function DonationItemForm({ return ( <> - + - - - - + - + + + + - New or Used + New or Used? @@ -185,7 +185,7 @@ export default function DonationItemForm({ setHighOrLow(e.target.value); }}*/} - + $, }} disabled={donationItemData.newOrUsed !== 'New' || disabled} // Disable if used + fullWidth // error={!!validationErrors?.price} // helperText={validationErrors?.price} /> diff --git a/src/components/donorForm/index.tsx b/src/components/donorForm/index.tsx index 9ca174c..f6bbd5c 100644 --- a/src/components/donorForm/index.tsx +++ b/src/components/donorForm/index.tsx @@ -51,7 +51,7 @@ export default function DonorForm(props: donorProps) { }} /> - + - + ) => { props.onChange({ ...props.donorData, - zip: Number(e.target.value), + zip: e.target.value, }); }} /> diff --git a/src/server/actions/donationItem.ts b/src/server/actions/donationItem.ts index f755d6e..ce9185f 100644 --- a/src/server/actions/donationItem.ts +++ b/src/server/actions/donationItem.ts @@ -8,6 +8,7 @@ import { import dbConnect from '@/utils/db-connect'; import ItemSchema from '@/server/models/items'; ItemSchema; + export async function getDonationItemById( id: string ): Promise { @@ -41,10 +42,12 @@ export async function createDonationItem( ): Promise { await dbConnect(); - const response = await DonationItemSchema.create(donationItem); + const response: DonationItemEntity = + await DonationItemSchema.create(donationItem); return response; } +// currently not used in the app export async function updateDonationItem( id: string, updatedData: UpdateDonationItemRequest diff --git a/src/server/actions/donations.ts b/src/server/actions/donations.ts index 9c17ede..4011bdd 100644 --- a/src/server/actions/donations.ts +++ b/src/server/actions/donations.ts @@ -1,26 +1,31 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import dbConnect from '@/utils/db-connect'; +import Donor from '../models/donors'; import DonationSchema from '../models/donations'; +import DonationItem from '../models/donationItem'; +import User from '../models/users'; import { CreateDonationRequest, DonationEntity, DonationResponse, UpdateDonationRequest, } from '@/types/donation'; -import UserSchema from '@/server/models/users'; -import DonorSchema from '@/server/models/donors'; -import DonationItemSchema from '@/server/models/donationItem'; -UserSchema; -DonorSchema; -DonationItemSchema; +User; +DonationItem; +Donor; export async function createDonation( donation: CreateDonationRequest ): Promise { - await dbConnect(); + try { + await dbConnect(); - const response: DonationEntity = await DonationSchema.create(donation); - return response; + const response: DonationEntity = await DonationSchema.create(donation); + return response; + } catch (error) { + throw error; + } } export async function getAllDonations(): Promise { diff --git a/src/server/actions/donors.ts b/src/server/actions/donors.ts index 24ee63b..a3e7822 100644 --- a/src/server/actions/donors.ts +++ b/src/server/actions/donors.ts @@ -2,7 +2,7 @@ import { CreateDonorRequest, DonorResponse, UpdateDonorRequest, //deleted a duplicate DonorResponse -} from '@/types/persons'; +} from '@/types/donors'; import dbConnect from '@/utils/db-connect'; import DonorSchema from '../models/donors'; diff --git a/src/server/actions/email.ts b/src/server/actions/email.ts new file mode 100644 index 0000000..7779455 --- /dev/null +++ b/src/server/actions/email.ts @@ -0,0 +1,34 @@ +import nodemailer from 'nodemailer'; + +export async function sendEmail( + recipients: string[], + subject: string, + body: string +) { + try { + // Note: Verification w/ app password requires a 2FA'd Google Account + // The MoH mailer acct currently has 2FA tied to Ethan Maness's + // phone number -- 423-276-1498 + // Text me or email me at ethanhmaness@gmail.com if there are issues. + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.MAILER_ADDR, + pass: process.env.MAILER_APP_PASS, + }, + }); + + const emailOptions = { + from: process.env.EVENTS_EMAIL_ADDR, + to: recipients.join(','), + subject: subject, + html: body, + }; + + await transporter.sendMail(emailOptions); + + return recipients; + } catch (error) { + throw error; + } +} diff --git a/src/server/actions/users.ts b/src/server/actions/users.ts index 30a1732..75083e4 100644 --- a/src/server/actions/users.ts +++ b/src/server/actions/users.ts @@ -1,5 +1,5 @@ import UserSchema from '@/server/models/users'; -import { UserResponse } from '@/types/persons'; +import { UserResponse } from '@/types/users'; import dbConnect from '@/utils/db-connect'; export async function getAllUsers(): Promise { diff --git a/src/server/models/donationItem.ts b/src/server/models/donationItem.ts index cd86a22..d5fe320 100644 --- a/src/server/models/donationItem.ts +++ b/src/server/models/donationItem.ts @@ -25,7 +25,7 @@ const DonationItemSchema = new Schema( evaluation: { type: String, enum: evaluationEnum, - required: false, + required: true, }, }, required: true, diff --git a/src/server/models/donors.ts b/src/server/models/donors.ts index 5c64fc5..cd44722 100644 --- a/src/server/models/donors.ts +++ b/src/server/models/donors.ts @@ -1,5 +1,5 @@ import { model, Schema, Document, models, Model } from 'mongoose'; -import { DonorEntity } from '../../types/persons'; +import { DonorEntity } from '../../types/donors'; const DonorSchema = new Schema( { @@ -28,7 +28,7 @@ const DonorSchema = new Schema( required: true, }, zip: { - type: Number, + type: String, required: true, }, }, diff --git a/src/server/models/users.ts b/src/server/models/users.ts index a67f51f..ad2f0e1 100644 --- a/src/server/models/users.ts +++ b/src/server/models/users.ts @@ -1,5 +1,5 @@ import { model, Schema, Document, models, Model } from 'mongoose'; -import { UserEntity } from '../../types/persons'; +import { UserEntity } from '../../types/users'; const UserSchema = new Schema( { diff --git a/src/types/donation.ts b/src/types/donation.ts index 77c51ca..9385a28 100644 --- a/src/types/donation.ts +++ b/src/types/donation.ts @@ -2,7 +2,8 @@ import zBase from './base'; import { z } from 'zod'; import zObjectId from './objectId'; import { zItemResponse } from './items'; -import { zDonorResponse, zUserResponse } from './persons'; +import { zUserResponse } from './users'; +import { zDonorResponse } from './donors'; export const evaluationEnum = ['High', 'Low', 'New'] as const; diff --git a/src/types/persons.ts b/src/types/donors.ts similarity index 63% rename from src/types/persons.ts rename to src/types/donors.ts index cb83498..ded12de 100644 --- a/src/types/persons.ts +++ b/src/types/donors.ts @@ -1,30 +1,14 @@ import zBase from './base'; import { z } from 'zod'; -const zPersonBase = z.object({ +const zDonorBase = z.object({ lastName: z.string(), firstName: z.string().optional(), email: z.string(), -}); - -export const zUserEntity = zBase.extend({ - name: z.string(), - email: z.string().email(), - image: z.string(), - isAdmin: z.boolean(), -}); - -export const zUserResponse = zUserEntity; - -export interface UserEntity extends z.infer {} - -export interface UserResponse extends z.infer {} - -export const zDonorBase = zPersonBase.extend({ address: z.string(), city: z.string(), state: z.string(), - zip: z.number(), + zip: z.string(), }); export const zDonorEntity = zDonorBase.extend({ ...zBase.shape }); diff --git a/src/types/forms/donor.ts b/src/types/forms/donor.ts index 35bdb53..4d43923 100644 --- a/src/types/forms/donor.ts +++ b/src/types/forms/donor.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; // Zip number and zip string are seperated to help with error checking and -// form valideation +// form validation export const zDonorFormData = z.object({ _id: z.string(), firstName: z.string().min(1, { message: 'Required' }), @@ -10,7 +10,7 @@ export const zDonorFormData = z.object({ address: z.string().min(1, { message: 'Required' }), city: z.string().min(1, { message: 'Required' }), state: z.string().min(1, { message: 'Required' }), - zip: z.number().positive().min(1, { message: 'Required' }), + zip: z.string().min(1, { message: 'Required' }), }); export interface DonorFormData extends z.infer {} diff --git a/src/types/users.ts b/src/types/users.ts new file mode 100644 index 0000000..eca8dd6 --- /dev/null +++ b/src/types/users.ts @@ -0,0 +1,15 @@ +import zBase from './base'; +import { z } from 'zod'; + +export const zUserEntity = zBase.extend({ + name: z.string(), + email: z.string().email(), + image: z.string(), + isAdmin: z.boolean(), +}); + +export const zUserResponse = zUserEntity; + +export interface UserEntity extends z.infer {} + +export interface UserResponse extends z.infer {} diff --git a/src/views/AddDonationView/index.tsx b/src/views/AddDonationView/index.tsx index f13d969..36c5d72 100644 --- a/src/views/AddDonationView/index.tsx +++ b/src/views/AddDonationView/index.tsx @@ -4,19 +4,15 @@ import DonorForm from '@/components/donorForm'; import useValidation from '@/hooks/useValidation'; import { DonationFormData, zDonationFormData } from '@/types/forms/donation'; import { DonorFormData, zDonorFormData } from '@/types/forms/donor'; -import { CreateDonorRequest, DonorResponse } from '@/types/persons'; +import { CreateDonorRequest, DonorResponse } from '@/types/donors'; import AddIcon from '@mui/icons-material/Add'; import DeleteIcon from '@mui/icons-material/Delete'; import { Box, Button, Divider, - FormControl, Grid, IconButton, - InputLabel, - MenuItem, - Select, TextField, ThemeProvider, Tooltip, @@ -283,9 +279,13 @@ export default function AddDonationView({ Add Donation - + - + - + - {donationItemFormDatas.map((_, index) => ( - <> - - - { - donationItemFormDatas.splice(index, 1); - setDonationItemFormDatas([...donationItemFormDatas]); - }} - key={index} - > - - - - - - handleDonationItemFormChange(value, index) - } - key={index} - disabled={false} - // validationErrors={} - /> - - ))} - - - - + + + - + {donationItemFormDatas.map((_, index) => ( + <> + + + + + handleDonationItemFormChange(value, index) + } + key={index} + disabled={false} + // validationErrors={} + /> + + + { + donationItemFormDatas.splice(index, 1); + setDonationItemFormDatas([...donationItemFormDatas]); + }} + key={index} + > + + + + + + ))} + + + + + - - - Has this donor previously donated? - - - - - diff --git a/src/views/donationItemView/index.tsx b/src/views/donationItemView/index.tsx index 40d38e4..3841c99 100644 --- a/src/views/donationItemView/index.tsx +++ b/src/views/donationItemView/index.tsx @@ -1,4 +1,5 @@ 'use client'; +import React, { useEffect } from 'react'; import { Box, Chip, @@ -75,9 +76,12 @@ export default function DonationItemView({ donations }: DonationItemProps) { //map the donation items to the rows const { searchString, searchQuery, setSearchQuery } = useSearch(); const { selectedMonth, monthQuery, setMonthQuery } = useMonth(); - if (monthQuery === '') { - setMonthQuery((new Date().getMonth() + 1).toString()); // Default to current month - } + // use useEffect hook that only runs once to prevent infinite rerender for monthQuery. + useEffect(() => { + if (monthQuery === '') { + setMonthQuery((new Date().getMonth() + 1).toString()); + } + }, [monthQuery, setMonthQuery]); // const [selectedMonth, setSelectedMonth] = useState( // (new Date().getMonth() + 1).toString() // Default to current month // ); diff --git a/src/views/donorIdView/index.tsx b/src/views/donorIdView/index.tsx index 747b252..0cf2124 100644 --- a/src/views/donorIdView/index.tsx +++ b/src/views/donorIdView/index.tsx @@ -2,7 +2,7 @@ import DonorForm from '@/components/donorForm'; import useSnackbar from '@/hooks/useSnackbar'; import { DonorFormData } from '@/types/forms/donor'; -import { DonorResponse } from '@/types/persons'; +import { DonorResponse } from '@/types/donors'; import mohColors from '@/utils/moh-theme'; import { ArrowBack } from '@mui/icons-material'; import { diff --git a/src/views/donorView/index.tsx b/src/views/donorView/index.tsx index 9e163ab..2f0b91d 100644 --- a/src/views/donorView/index.tsx +++ b/src/views/donorView/index.tsx @@ -2,7 +2,7 @@ import useMonth from '@/hooks/useMonth'; import useSearch from '@/hooks/useSearch'; import { DonationResponse } from '@/types/donation'; -import { DonorResponse } from '@/types/persons'; +import { DonorResponse } from '@/types/donors'; import EditIcon from '@mui/icons-material/Edit'; import { Box, diff --git a/src/views/settingsView/index.tsx b/src/views/settingsView/index.tsx index fc611d3..690ec93 100644 --- a/src/views/settingsView/index.tsx +++ b/src/views/settingsView/index.tsx @@ -26,6 +26,7 @@ export default function SettingsView() { setUserInfo({ ...userInfo, email: event.target.value }); }; + // TODO: Create settings API endpoint const handleSubmit = async () => { try { // Make an API call to update the user's information