diff --git a/apps/dashboard/components/events/events-calendar.tsx b/apps/dashboard/components/events/events-calendar.tsx index 468f917d..8d83589e 100644 --- a/apps/dashboard/components/events/events-calendar.tsx +++ b/apps/dashboard/components/events/events-calendar.tsx @@ -239,7 +239,7 @@ const CalendarGrid = styled.div` display: grid; grid-template-rows: auto 1fr; grid-template-columns: 50px repeat(${(props) => props.columns}, 1fr); - width: 70vw; + max-width: 70vw; border-radius: 5px; diff --git a/apps/dashboard/components/nav/side-nav2.tsx b/apps/dashboard/components/nav/side-nav2.tsx index 8b44112c..2639e9d8 100644 --- a/apps/dashboard/components/nav/side-nav2.tsx +++ b/apps/dashboard/components/nav/side-nav2.tsx @@ -5,6 +5,7 @@ import ArrowRight from '../../public/arrow-right.svg'; import { useState } from 'react'; import { IconType } from 'react-icons'; import styled from 'styled-components'; +import { logout } from '@hibiscus/sso-client'; interface Props { options: { name: string; url: string; image: IconType }[]; @@ -16,6 +17,7 @@ const SideNav = ({ options }: Props) => { return (
{ ))}
- -
Log out
- {'-'} width={20} height={20}> -
+
+
+
Contact HackSC Support
+
(213)-513-1234
+
team@hacksc.com
+
+ +
Log out
+ {'-'} width={20} height={20}> +
+
); }; diff --git a/apps/dashboard/layouts/themeless-layout.tsx b/apps/dashboard/layouts/themeless-layout.tsx index 6ed75b7d..4c57aed9 100644 --- a/apps/dashboard/layouts/themeless-layout.tsx +++ b/apps/dashboard/layouts/themeless-layout.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import useHibiscusUser from '../hooks/use-hibiscus-user/use-hibiscus-user'; import StyledSideNav from '../components/nav/side-nav'; @@ -19,6 +19,7 @@ import { } from 'react-icons/md'; import { FaRegUserCircle } from 'react-icons/fa'; import { useRouter } from 'next/router'; +import { SponsorServiceAPI } from '../common/api'; export type ThemelessLayoutProps = React.PropsWithChildren; @@ -60,7 +61,33 @@ function ThemelessLayout({ children }: ThemelessLayoutProps) { image: MdOutlinePlaylistAddCheck, }, ]; - return []; + if (user.role === HibiscusRole.SPONSOR) + return [ + { + name: 'Events', + url: '/sponsor-booth', + image: MdOutlineCalendarViewMonth, + }, + { + name: 'Hacker Attendees', + url: '/participant-database', + image: MdOutlinePeopleAlt, + }, + ]; + }, [user]); + + const [companyName, setCompanyName] = useState(null); + useEffect(() => { + const fetchData = async () => { + const data = await SponsorServiceAPI.getCompanyIdAndEventId(user.id); + if (data.data != null) { + setCompanyName(data.data.data.company_name); + } + }; + + if (user != null && user.role === HibiscusRole.SPONSOR) { + fetchData(); + } }, [user]); const router = useRouter(); @@ -72,9 +99,10 @@ function ThemelessLayout({ children }: ThemelessLayoutProps) { '/identity-portal/attendee-event-scan': 'Event Check-in', '/identity-portal/event-checkin': 'Event Check-in', '/hacker-profile': 'Profile', + '/sponsor-booth': companyName ? `Welcome ${companyName}` : 'Welcome', }; return map[router.pathname] ?? ''; - }, [router]); + }, [router, companyName]); if (user == null || router == null) { return <>; diff --git a/apps/dashboard/pages/api/companies/[userId].ts b/apps/dashboard/pages/api/companies/[userId].ts index d08de50e..9df16094 100644 --- a/apps/dashboard/pages/api/companies/[userId].ts +++ b/apps/dashboard/pages/api/companies/[userId].ts @@ -30,17 +30,25 @@ export default async function handler( console.log(companyData); //we know companies can't be null. This indexes down the object tree to get event_id. ASSUMED THAT NOTHING IS NULL OR ANYTHING - const event = companyData.data['companies']['events'] as any[]; + const event = companyData.data['companies']['events']; let eventId: number | null; + let companyName: string | null; console.log(event); if (event.length) { eventId = event.at(0)['id']; + companyName = event.at(0)['name']; } const companyId = companyData.data['company_id']; return res .status(200) - .json({ data: { company_id: companyId, event_id: eventId } }); + .json({ + data: { + company_id: companyId, + event_id: eventId, + company_name: companyName, + }, + }); } else { return res.status(401).json({ message: 'Unauthorized access.' }); } diff --git a/apps/dashboard/pages/sponsor-booth/index.tsx b/apps/dashboard/pages/sponsor-booth/index.tsx index 07dce059..85ee7721 100644 --- a/apps/dashboard/pages/sponsor-booth/index.tsx +++ b/apps/dashboard/pages/sponsor-booth/index.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import useHibiscusUser from '../../hooks/use-hibiscus-user/use-hibiscus-user'; import Image from 'next/image'; import { Colors2023 } from '@hibiscus/styles'; -import { BoldText, H1 } from '@hibiscus/ui'; +import { BoldText, H1, Modal } from '@hibiscus/ui'; import { Text } from '@hibiscus/ui'; import { HackerTab } from '../../components/sponsor-portal/hacker-tab'; import HackerProfile from '../../components/sponsor-portal/hacker-profile'; @@ -15,6 +15,7 @@ import { ParagraphText } from '@hibiscus/ui-kit-2023'; import { getWordCount } from '../../common/utils'; import { SponsorServiceAPI } from '../../common/api'; import { MutatingDots } from 'react-loader-spinner'; +import searchEvent from '../../common/search-event'; import { Button, BodyText, @@ -23,6 +24,18 @@ import { GlobalStyle, Heading, } from '@hacksc/sctw-ui-kit'; +import { IoBookmark } from 'react-icons/io5'; +import { FaArrowRight } from 'react-icons/fa'; +import EventsCalendar from 'apps/dashboard/components/events/events-calendar'; +import { + Event, + getAllEvents, + getPinnedEvents, + isSameDate, +} from 'apps/dashboard/common/events.utils'; +import { getEnv } from '@hibiscus/env'; +import { getCookie } from 'cookies-next'; +import EventDetails from 'apps/dashboard/components/events/event-details'; const Index = () => { const { user } = useHibiscusUser(); @@ -37,8 +50,23 @@ const Index = () => { const [savedSpinner, setSavedSpinner] = useState(false); const [checkInSpinner, setCheckInSpinner] = useState(false); + const [events, setEvents] = useState(null); + const [eventsGrouped, setEventsGrouped] = useState(null); + const [pinnedEvents, setPinnedEvents] = useState(null); + const [pinnedEventsGrouped, setPinnedEventsGrouped] = useState< + Event[][] | null + >(null); + + // Modal state + const [activeEvent, setActiveEvent] = useState(null); + const router = useRouter(); const supabase = useHibiscusSupabase().supabase.getClient(); + const hibiscusSupabaseClient = useHibiscusSupabase().supabase; + + useEffect(() => { + searchEvent(hibiscusSupabaseClient).then(setEvents); + }, [hibiscusSupabaseClient]); useEffect(() => { if (modalActive) { @@ -84,6 +112,75 @@ const Index = () => { }; }, [COMPANY_ID, EVENT_ID]); + // Get events + useEffect(() => { + async function fetchEvents() { + try { + const events = await getAllEvents( + getCookie(getEnv().Hibiscus.Cookies.accessTokenName)?.toString() + ); + setEvents(events); + + // Group events by date + const eventsByDate: Event[][] = []; + for (const e of events) { + if ( + eventsByDate.length === 0 || + !isSameDate(eventsByDate.at(-1)[0].startTime, e.startTime) + ) { + eventsByDate.push([e]); + } else { + eventsByDate.at(-1).push(e); + } + } + setEventsGrouped(eventsByDate); + } catch (e) { + console.log(e); + } + } + + fetchEvents(); + }, []); + + // Get pinned events + useEffect(() => { + async function fetchPinnedEvents() { + try { + const pinnedEvents = await getPinnedEvents( + user.id, + getCookie(getEnv().Hibiscus.Cookies.accessTokenName)?.toString() + ); + setPinnedEvents(pinnedEvents); + } catch (e) { + console.log(e); + } + } + fetchPinnedEvents(); + }, [user.id]); + + useEffect(() => { + if (pinnedEvents && eventsGrouped) { + // Group events by date + const eventsByDate: Event[][] = []; + const column = 0; + for (const e of pinnedEvents) { + // while (!isSameDate(e.startTime, eventsGrouped[column][0].startTime)) { + // if (eventsByDate.length <= column) { + // eventsByDate.push([]); + // } + // column++; + // } + + if (eventsByDate.length <= column) { + eventsByDate.push([e]); + } else { + eventsByDate.at(-1).push(e); + } + } + setPinnedEventsGrouped(eventsByDate); + } + }, [pinnedEvents, eventsGrouped]); + if (user == null) { return <>Loading; } @@ -105,7 +202,15 @@ const Index = () => { if (error) { console.log(error); } - setAttendees(data.data as Attendee[]); + // sort attendees so that saved attendees are first + if (data.data) { + const sortedAttendees = data.data.slice().sort((a, b) => { + if (a.saved && !b.saved) return -1; + if (!a.saved && b.saved) return 1; + return 0; + }); + setAttendees(sortedAttendees); + } }) .catch((error) => { console.log(error); @@ -297,173 +402,289 @@ const Index = () => { } return ( - - - - -
- - - Welcome {user.firstName} {user.lastName} - - - This is your booth! Search through your booth attendees and - review their qualifications! - - -
- - HACKSC SUPPORT - (213) - 513 - HACK - dayof@hacksc.com - - - <> - RECENTLY SAVED - {showSavedAttendees()} - - -
- - router.push({ - pathname: '/participant-database', - query: { - viewSaved: true, - companyId: COMPANY_ID, - eventId: EVENT_ID, - }, - }) - } - > - VIEW ALL SAVED - -
- - - +
+
- All Check-Ins - - {getAttendees()} - - router.push({ - pathname: '/participant-database', - query: { - companyId: COMPANY_ID, - eventId: EVENT_ID, - }, - }) - } +
Events
+ setActiveEvent(eventId)} + /> +
+
- VIEW ALL ATTENDEES - - {modalActive && ( - - - { - setModalActive(false); - setInput(''); +
Hacker Attendees
+
+ {attendees.slice(0, 8).map((attendee, index) => ( +
- x-button - - QUICK NOTES - - {attendeeName} - - - { - setInput(e.target.value); +
- - Word count: {getWordCount(textInput)} - - -
- -
- +
{attendee.full_name}
+ {attendee.saved && ( +
+ +
+ )}
- - - )} - + ))} +
+ +
+
- setActiveEvent(null)} > - { - setCurrentAttendee(null); - }} - > - - HACKER - - x-button - - {currentAttendee !== null ? ( -
- openQuickNote(currentAttendee)} - /> -
- ) : ( - <> + {activeEvent !== null && activeEvent !== undefined && ( + e.eventId === activeEvent)} + userId={user.id} + pinnedEvents={pinnedEvents} + setError={() => {}} + setPinnedEvents={setPinnedEvents} + refresh={() => {}} + admin={user.role === HibiscusRole.ADMIN} + /> )} -
- + + ); + // return ( + // + // + // + // + //
+ // + // + // Welcome {user.firstName} {user.lastName} + // + // + // This is your booth! Search through your booth attendees and + // review their qualifications! + // + // + //
+ // + // HACKSC SUPPORT + // (213) - 513 - HACK + // dayof@hacksc.com + // + // + // <> + // RECENTLY SAVED + // {showSavedAttendees()} + // + // + //
+ // + // router.push({ + // pathname: '/participant-database', + // query: { + // viewSaved: true, + // companyId: COMPANY_ID, + // eventId: EVENT_ID, + // }, + // }) + // } + // > + // VIEW ALL SAVED + // + //
+ + // + // + // All Check-Ins + // + // {getAttendees()} + // + // router.push({ + // pathname: '/participant-database', + // query: { + // companyId: COMPANY_ID, + // eventId: EVENT_ID, + // }, + // }) + // } + // > + // VIEW ALL ATTENDEES + // + // {modalActive && ( + // + // + // { + // setModalActive(false); + // setInput(''); + // }} + // > + // x-button + // + // QUICK NOTES + // + // {attendeeName} + // + // + // { + // setInput(e.target.value); + // }} + // /> + // + // Word count: {getWordCount(textInput)} + // + // + //
+ // + //
+ // + //
+ //
+ //
+ //
+ // )} + //
+ + // + // { + // setCurrentAttendee(null); + // }} + // > + // + // HACKER + // + // x-button + // + // {currentAttendee !== null ? ( + //
+ // openQuickNote(currentAttendee)} + // /> + //
+ // ) : ( + // <> + // )} + //
+ //
+ // ); }; export default Index; diff --git a/apps/dashboard/repository/company.repository.ts b/apps/dashboard/repository/company.repository.ts index ee5827f9..78014856 100644 --- a/apps/dashboard/repository/company.repository.ts +++ b/apps/dashboard/repository/company.repository.ts @@ -133,7 +133,8 @@ export class CompanyRepository { company_id, companies( events( - id + id, + name ) ) `