diff --git a/components/Event/Contact.tsx b/components/Event/Contact.tsx index 49d7f077..97afdd33 100644 --- a/components/Event/Contact.tsx +++ b/components/Event/Contact.tsx @@ -12,6 +12,7 @@ import { EVENT_CONTACT_ICON_HEIGHT, } from '@/utils/constants'; import { Media } from '@/lib/media'; +import Link from 'next/link'; /** * Contain Contact info @@ -42,7 +43,9 @@ const Contact = ({ phone, email }: { phone: string; email: string }) => ( width={EVENT_CONTACT_ICON_WIDTH} height={EVENT_CONTACT_ICON_HEIGHT} /> - {email} + + {email} + diff --git a/components/Event/Event.tsx b/components/Event/Event.tsx index a8dc75ba..0c5ce49a 100644 --- a/components/Event/Event.tsx +++ b/components/Event/Event.tsx @@ -1,4 +1,4 @@ -import { QueriedVolunteerEventData } from 'bookem-shared/src/types/database'; +import { QueriedVolunteerEventDTO } from 'bookem-shared/src/types/database'; import React, { useState } from 'react'; import Header from '@/components/Event/Header'; import BookIcon from '@/components/Event/BookIcon'; @@ -21,7 +21,7 @@ import { BOOKEM_THEME } from '@/utils/constants'; * Event Detail * @param event Data about the event */ -const Event = ({ event }: { event: QueriedVolunteerEventData }) => { +const Event = ({ event }: { event: QueriedVolunteerEventDTO }) => { /** * True: display About * False: display Contact diff --git a/components/Event/EventName.tsx b/components/Event/EventName.tsx index 2c66df15..f10c0d57 100644 --- a/components/Event/EventName.tsx +++ b/components/Event/EventName.tsx @@ -1,4 +1,4 @@ -import { QueriedVolunteerEventData } from 'bookem-shared/src/types/database'; +import { QueriedVolunteerEventDTO } from 'bookem-shared/src/types/database'; import React, { useEffect } from 'react'; import { EventNameBox, @@ -15,7 +15,7 @@ import Image from 'next/image'; * Calculate the length of the event volunteers * If event.volunteers is undefined, return 0 */ -export const getEventLength = (event: QueriedVolunteerEventData) => { +export const getEventLength = (event: QueriedVolunteerEventDTO) => { if (event.volunteers && event.volunteers.length) return event.volunteers.length; else return 0; @@ -33,7 +33,7 @@ const EventName = ({ }: { signedUp: boolean; setSignedUp: (signedUp: boolean) => void; - event: QueriedVolunteerEventData; + event: QueriedVolunteerEventDTO; signUpEvent: () => void; }) => { const { data: session } = useSession(); @@ -54,7 +54,7 @@ const EventName = ({ {event.name} - {event.tags.length > 0 && ({event.program.tagName})} + {event.tags.length > 0 && ({event.program?.name})} {getEventLength(event)}/{event.maxSpot} spots filled @@ -66,7 +66,7 @@ const EventName = ({ {/* Mobile */} - {event.name} ({event.program?.tagName}) + {event.name} ({event.program?.name}) diff --git a/components/Event/Footer.tsx b/components/Event/Footer.tsx index d8fb7ff1..68d06d9f 100644 --- a/components/Event/Footer.tsx +++ b/components/Event/Footer.tsx @@ -1,5 +1,5 @@ import { SignupButton } from '@/styles/components/Event/event.styles'; -import { QueriedVolunteerEventData } from 'bookem-shared/src/types/database'; +import { QueriedVolunteerEventDTO } from 'bookem-shared/src/types/database'; import { useSession } from 'next-auth/react'; import React, { useEffect } from 'react'; import { getEventLength } from '@/components/Event/EventName'; @@ -20,7 +20,7 @@ const Footer = ({ }: { signedUp: boolean; setSignedUp: (signedUp: boolean) => void; - event: QueriedVolunteerEventData; + event: QueriedVolunteerEventDTO; signUpEvent: () => void; }) => { // Get user id in session diff --git a/components/Home/PastActivity.tsx b/components/Home/PastActivity.tsx index 95d552c4..4ba9cc9d 100644 --- a/components/Home/PastActivity.tsx +++ b/components/Home/PastActivity.tsx @@ -30,10 +30,7 @@ const dummyEventData: QueriedVolunteerEventData = { }, phone: '123-456-7890', email: 'test_user@bookem.com', - program: { - _id: new mongoose.Types.ObjectId(), - tagName: 'BNFK', - }, + program: new mongoose.Types.ObjectId(), requireApplication: true, volunteers: [], tags: [], diff --git a/components/Volunteer/FilterEventsPopup.tsx b/components/Volunteer/FilterEventsPopup.tsx index 2935ff4a..cd6bec8c 100644 --- a/components/Volunteer/FilterEventsPopup.tsx +++ b/components/Volunteer/FilterEventsPopup.tsx @@ -43,8 +43,8 @@ const FilterEventsPopup = ({ <> - Most Recent - Least Recent + Most Recent + Least Recent Most Spots Least Spots diff --git a/components/Volunteer/FutureVolunteerEvents.tsx b/components/Volunteer/FutureVolunteerEvents.tsx index e501824b..12c4a262 100644 --- a/components/Volunteer/FutureVolunteerEvents.tsx +++ b/components/Volunteer/FutureVolunteerEvents.tsx @@ -22,6 +22,7 @@ import { fetchData } from '@/utils/utils'; import { Media } from '@/lib/media'; import LongEventCard from '../shared/LongEventCard'; import Link from 'next/link'; +import { start } from 'repl'; const FutureVolunteerEvents = () => { // Holds text in input box @@ -68,18 +69,24 @@ const FutureVolunteerEvents = () => { }; // Sorts events in order of most to least recent - const sortMostRecent = () => { + const sortLeastRecent = () => { if (!events) return; const copy = [...events]; - copy.sort((a, b) => a.startDate.valueOf() - b.startDate.valueOf()); + copy.sort( + (a, b) => + new Date(b.startDate).valueOf() - new Date(a.startDate).valueOf() + ); setEvents(copy); }; // Sorts events in order of least to most recent - const sortLeastRecent = () => { + const sortMostRecent = () => { if (!events) return; const copy = [...events]; - copy.sort((b, a) => a.startDate.valueOf() - b.startDate.valueOf()); + copy.sort( + (a, b) => + new Date(a.startDate).valueOf() - new Date(b.startDate).valueOf() + ); setEvents(copy); }; @@ -138,7 +145,9 @@ const FutureVolunteerEvents = () => { {/* Container for events that show up based on query input */} {events - .filter(event => event.name.includes(query)) + .filter(event => + event.name.toLowerCase().includes(query.toLowerCase()) + ) .map(event => ( { + const generatedProgram = generateProgram(program); + await VolunteerPrograms.insertMany(generatedProgram); + }); + + // Generate tags + INSERTED_TAGS.forEach(async tag => { + const genratedTag = generateTag(tag); + await Tags.insertMany(genratedTag); + }); + + res.status(200).json({ + success: true, + message: 'Inserted fake tags and program data', + }); + } catch (error: any) { + res.status(500).json({ success: false, error: error.message }); + } + + break; + + default: + res.status(400).json({ success: false }); + break; + } +} diff --git a/pages/api/scripts/02-insert-events.ts b/pages/api/scripts/03-insert-events.ts similarity index 52% rename from pages/api/scripts/02-insert-events.ts rename to pages/api/scripts/03-insert-events.ts index bce1d5bc..eac85cf6 100644 --- a/pages/api/scripts/02-insert-events.ts +++ b/pages/api/scripts/03-insert-events.ts @@ -1,8 +1,23 @@ import dbConnect from '@/lib/dbConnect'; import VolunteerEvents from 'bookem-shared/src/models/VolunteerEvents'; import { NextApiRequest, NextApiResponse } from 'next'; -import { generateEvent } from '@/pages/api/scripts/helper-functions'; -import { EventStatus } from '@/pages/api/scripts/constants'; +import { + fillProgramEvents, + generateEvent, + generateProgram, + generateTag, +} from '@/pages/api/scripts/helper-functions'; +import { + INSERTED_PROGRAMS, + INSERTED_TAGS, +} from '@/pages/api/scripts/constants'; +import Tags from 'bookem-shared/src/models/Tags'; +import VolunteerPrograms from 'bookem-shared/src/models/VolunteerPrograms'; +import { + QueriedTagData, + QueriedVolunteerEventData, + QueriedVolunteerProgramData, +} from 'bookem-shared/src/types/database'; export default async function handler( req: NextApiRequest, @@ -17,19 +32,36 @@ export default async function handler( // delete all events await VolunteerEvents.deleteMany({}); + // get all tags + const tags = await Tags.find({}); + + // get all programs + const programs = await VolunteerPrograms.find({}); + // create a bulk operation to minimize the number of db calls const bulkEvents = VolunteerEvents.collection.initializeUnorderedBulkOp(); // insert a bunch of equally distributed events for (let i = 0; i < 100; i++) { - const event = generateEvent(i); + const event = generateEvent( + i, + tags as QueriedTagData[], + programs as QueriedVolunteerProgramData[] + ); bulkEvents.insert(event); } // execute the bulk operation await bulkEvents.execute(); + // Query them back to update program + const events = await VolunteerEvents.find({ program: { $ne: null } }); + // Update programs so that programs contain their corresponding events + await fillProgramEvents(events); + + // TODO: Fill the tags with events as well + res.status(200).json({ success: true, message: diff --git a/pages/api/scripts/constants.ts b/pages/api/scripts/constants.ts index a9e44083..2b6ab235 100644 --- a/pages/api/scripts/constants.ts +++ b/pages/api/scripts/constants.ts @@ -8,55 +8,58 @@ export const GENDERS = ['male', 'female']; // ------------------ CONFIGURATIONS ------------------ export const EVENTS: { name: string; - tag: string; + program: string; isMultipleDays: boolean; requireApplication: boolean; + tags?: string[]; }[] = [ { name: 'Distribute books', - tag: 'BFNK', + program: 'BFNK', isMultipleDays: false, requireApplication: false, }, { name: 'Reading role model', - tag: 'RFR', + program: 'RFR', isMultipleDays: true, requireApplication: true, }, { name: 'Book drive', - tag: '', + program: '', isMultipleDays: false, requireApplication: false, }, { name: 'Special event', - tag: '', + program: '', isMultipleDays: false, requireApplication: false, }, { name: 'Interactive reading', - tag: 'RIF', + program: 'RIF', isMultipleDays: true, requireApplication: true, }, { name: 'Book sort, clean, process', - tag: '', + program: '', isMultipleDays: false, requireApplication: false, }, { name: 'Office work', - tag: '', + program: '', + tags: ['saved'], isMultipleDays: false, requireApplication: false, }, { name: 'Book bus', - tag: '', + program: '', + tags: ['hidden'], isMultipleDays: false, requireApplication: false, }, @@ -64,24 +67,27 @@ export const EVENTS: { export const INSERTED_TAGS = [ { - _id: new mongoose.Types.ObjectId('642a4dec74c697623278344d'), - tagName: 'RIF', + _id: new mongoose.Types.ObjectId('642a4e0a74c6976232783450'), + tagName: 'saved', }, { - _id: new mongoose.Types.ObjectId('642a4dfc74c697623278344e'), - tagName: 'RFR', + _id: new mongoose.Types.ObjectId('642a4e1274c6976232783451'), + tagName: 'hidden', }, +]; + +export const INSERTED_PROGRAMS = [ { - _id: new mongoose.Types.ObjectId('642a4e0474c697623278344f'), - tagName: 'BFNK', + _id: new mongoose.Types.ObjectId('642a4dec74c697623278344d'), + name: 'RIF', }, { - _id: new mongoose.Types.ObjectId('642a4e0a74c6976232783450'), - tagName: 'saved', + _id: new mongoose.Types.ObjectId('642a4dfc74c697623278344e'), + name: 'RFR', }, { - _id: new mongoose.Types.ObjectId('642a4e1274c6976232783451'), - tagName: 'hidden', + _id: new mongoose.Types.ObjectId('642a4e0474c697623278344f'), + name: 'BFNK', }, ]; diff --git a/pages/api/scripts/helper-functions.ts b/pages/api/scripts/helper-functions.ts index ba8b4738..1d60a73d 100644 --- a/pages/api/scripts/helper-functions.ts +++ b/pages/api/scripts/helper-functions.ts @@ -3,7 +3,11 @@ import { hash } from 'bcrypt'; import { AdminStatus, QueriedTagData, + QueriedVolunteerEventData, + QueriedVolunteerProgramData, + TagData, VolunteerEventData, + VolunteerProgramData, } from 'bookem-shared/src/types/database'; import { AdminData, UserData } from 'bookem-shared/src/types/database'; import { @@ -13,6 +17,8 @@ import { INSERTED_TAGS, SOURCES, } from '@/pages/api/scripts/constants'; +import Tags from 'bookem-shared/src/models/Tags'; +import VolunteerPrograms from 'bookem-shared/src/models/VolunteerPrograms'; const generatePhone = (): string => { const phone = `(${faker.random.numeric(3)}) ${faker.random.numeric( @@ -52,7 +58,8 @@ export const generateUser = async ({ expirationDate: new Date(), }, events: [], - tags: [], + programs: [], + // tags: [], }); export const generateAdmin = async (): Promise => ({ @@ -65,7 +72,11 @@ export const generateAdmin = async (): Promise => ({ }); // ------------------ insert-events.ts ------------------ -export const generateEvent = (i: number): VolunteerEventData => { +export const generateEvent = ( + i: number, + tags: QueriedTagData[], + programs: QueriedVolunteerProgramData[] +): VolunteerEventData => { // get index of event const indexOfEvent = i % EVENTS.length; @@ -74,15 +85,25 @@ export const generateEvent = (i: number): VolunteerEventData => { // get an array containing just the tag id of this event const tagIds = ( - INSERTED_TAGS.filter(tag => - chosenEvent.tag.includes(tag.tagName) + tags.filter( + tag => chosenEvent.tags && chosenEvent.tags.includes(tag.tagName) ) as QueriedTagData[] ).map(tag => tag._id); + // get an array containing just the program id of this event + const programIds = ( + programs.filter( + program => chosenEvent.program && chosenEvent.program === program.name + ) as QueriedVolunteerProgramData[] + ).map(program => program._id); + // get the start and end dates let startDate, endDate; if (chosenEvent.isMultipleDays) { - startDate = faker.date.future(1); + startDate = faker.date.between( + '2022-01-01T00:00:00.000Z', + '2025-01-01T00:00:00.000Z' + ); endDate = faker.date.future(1, startDate); } else { startDate = new Date(); @@ -103,9 +124,34 @@ export const generateEvent = (i: number): VolunteerEventData => { }, phone: generatePhone(), email: faker.internet.email(), - program: tagIds[0] || null, - requireApplication: chosenEvent.requireApplication, + program: programIds[0] || null, + requireApplication: false, tags: tagIds, volunteers: [], }; }; + +export const generateProgram = (program: any): VolunteerProgramData => { + return { + name: program.name, + events: [], + volunteers: [], + }; +}; + +export const fillProgramEvents = async (events: any) => { + for (const event of events) { + const program = await VolunteerPrograms.findById(event.program); + if (program) { + program.events.unshift(event._id); + await program.save(); + } + } +}; + +export const generateTag = (tag: any): TagData => { + return { + events: [], + tagName: tag.tagName, + }; +}; diff --git a/pages/api/users/create.ts b/pages/api/users/create.ts index 920041a9..cac93406 100644 --- a/pages/api/users/create.ts +++ b/pages/api/users/create.ts @@ -60,7 +60,7 @@ export default async function handler( sourceHeardFrom: user.sourceHeardFrom, ethnicity: user.ethnicity, gender: user.gender, - tags: user.tags, + programs: [], events: user.events, }; diff --git a/pages/event/[pid].tsx b/pages/event/[pid].tsx index 283ad57d..f2e936bc 100644 --- a/pages/event/[pid].tsx +++ b/pages/event/[pid].tsx @@ -1,6 +1,6 @@ import Event from '@/components/Event/Event'; import { fetchData } from '@/utils/utils'; -import { QueriedVolunteerEventData } from 'bookem-shared/src/types/database'; +import { QueriedVolunteerEventDTO } from 'bookem-shared/src/types/database'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; @@ -12,7 +12,7 @@ const EventDetail = () => { const router = useRouter(); const { pid } = router.query; - const [event, setEvent] = useState(); + const [event, setEvent] = useState(); const [error, setError] = useState(); // use simple fetch to fetch when component is mounted diff --git a/pages/register.tsx b/pages/register.tsx index dcae5ed1..c0d9747b 100644 --- a/pages/register.tsx +++ b/pages/register.tsx @@ -133,7 +133,7 @@ const RegisterPage = () => { sourceHeardFrom: data.sourceHeardFrom, ethnicity: userEthnicity, gender: userGender, - tags: [], + programs: [], events: [], }; diff --git a/pages/volunteerHistory.tsx b/pages/volunteerHistory.tsx index 2cb5f842..9e7fbfd0 100644 --- a/pages/volunteerHistory.tsx +++ b/pages/volunteerHistory.tsx @@ -17,7 +17,7 @@ const VolunteerHistoryPage = () => { const [error, setError] = useState(); // Fetch volunteer history events when rendered useEffect(() => { - fetchData('/api/events/user') + fetchData('/api/events/history') .then(data => setEvents(data)) .catch(err => setError(err)); }, []);
({event.program.tagName})
({event.program?.name})