Skip to content

Commit

Permalink
Event RSVP Impl
Browse files Browse the repository at this point in the history
  • Loading branch information
Alder Whiteford authored and Alder Whiteford committed Jun 20, 2024
1 parent 2fbd9c8 commit 5e97526
Show file tree
Hide file tree
Showing 17 changed files with 240 additions and 50 deletions.
3 changes: 1 addition & 2 deletions backend/entities/events/rsvps/routes.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package rsvps

import (
"github.com/GenerateNU/sac/backend/permission"
"github.com/GenerateNU/sac/backend/types"
)

Expand All @@ -13,5 +12,5 @@ func EventsRSVPs(params types.RouteParams) {

eventRSVPS.Get("/", params.UtilityMiddleware.Paginator, controller.GetEventRSVPs)
eventRSVPS.Post("/:userID", params.AuthMiddleware.UserAuthorizeById, controller.CreateEventRSVP)
eventRSVPS.Delete("/:userID", params.AuthMiddleware.UserAuthorizeById, params.AuthMiddleware.Authorize(permission.DeleteAll), controller.DeleteEventRSVP)
eventRSVPS.Delete("/:userID", params.AuthMiddleware.UserAuthorizeById, controller.DeleteEventRSVP)
}
2 changes: 1 addition & 1 deletion frontend/lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@generatesac/lib",
"version": "0.0.187",
"version": "0.0.189",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
3 changes: 0 additions & 3 deletions frontend/lib/src/api/eventApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ export const eventApi = baseApi.injectEndpoints({
method: "POST",
responseHandler: 'text'
}),
transformResponse: (response) => {
return z.array(userSchema).parse(response);
}
}),
deleteEventRegistration: builder.mutation<void, EventUserParams>({
query: ({ user_id, event_id }) => ({
Expand Down
2 changes: 1 addition & 1 deletion frontend/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@fortawesome/react-native-fontawesome": "^0.3.2",
"@generatesac/lib": "0.0.186",
"@generatesac/lib": "0.0.189",
"@gorhom/bottom-sheet": "^4.6.3",
"@hookform/resolvers": "^3.4.2",
"@react-native-async-storage/async-storage": "^1.23.1",
Expand Down
14 changes: 13 additions & 1 deletion frontend/mobile/src/app/app/(tabs)/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { router } from 'expo-router';
import {
IconDefinition,
faSignOutAlt,
faUser
faUser,
faCalendar
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';

Expand All @@ -16,6 +17,9 @@ import { resetAccessToken } from '@/src/store/slices/globalSlice';
import { useAppDispatch, useAppSelector } from '@/src/store/store';

import { Box, Colors, SACColors, Spacing, Text } from '../../design-system';
import { resetEvent } from '@/src/store/slices/eventSlice';
import { resetUser } from '@/src/store/slices/userSlice';
import { resetClub } from '@/src/store/slices/clubSlice';

type ProfileItemProps = {
icon: IconDefinition;
Expand Down Expand Up @@ -76,6 +80,11 @@ const ProfilePage = () => {
onPress={() => router.push('/app/user/following/')}
text="Following"
/>
<ProfileItem
icon={faCalendar}
onPress={() => router.push('/app/user/events/')}
text="Upcoming Events"
/>
<Box
width="100%"
height={1}
Expand All @@ -88,6 +97,9 @@ const ProfilePage = () => {
textColor="darkRed"
onPress={() => {
dispatch(resetAccessToken());
dispatch(resetEvent());
dispatch(resetUser());
dispatch(resetClub());
}}
/>
</Box>
Expand Down
67 changes: 52 additions & 15 deletions frontend/mobile/src/app/app/event/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { Dimensions } from 'react-native';
import Animated, {
interpolate,
Expand All @@ -9,7 +9,7 @@ import Animated, {

import { Stack, useLocalSearchParams } from 'expo-router';

import { EventType } from '@generatesac/lib';
import { EventPreview, EventType, eventApi } from '@generatesac/lib';
import BottomSheet from '@gorhom/bottom-sheet';

import { Arrow, Box, KebabMenu } from '@/src/app/design-system';
Expand All @@ -29,6 +29,7 @@ import { Overview } from './components/overview';
import { RegisterBottomSheet } from './components/register';
import { ShareEventBottomSheet } from './components/share-event';
import EventPageSkeleton from './components/skeleton';
import { setUserRSVPs } from '@/src/store/slices/userSlice';

const MockEvent = {
eventImage:
Expand Down Expand Up @@ -60,18 +61,64 @@ const EventPage = () => {
const scrollOffset = useScrollViewOffset(scrollRef);

const dispatch = useAppDispatch();
const { id: userId, rsvps } = useAppSelector((state) => state.user);
const event = useAppSelector((state) => state.event);
const { name: clubName, logo: clubLogo } = useAppSelector(
(state) => state.club
);
const [userAttending, setUserAttending] = useState(event.rsvps.includes(userId))

const { setRetriggerFetch, apiLoading, apiError } = useEvent();
const [registerUser] = eventApi.useCreateEventRegistrationMutation();
const [unregisterUser] = eventApi.useDeleteEventRegistrationMutation();

useEffect(() => {
dispatch(setEventId(id));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (!userAttending) {
register.current?.close();
}
}, [userAttending]);

const handleRegistration = () => {
registerUser({ user_id: userId, event_id: id as string })
.then(({ error }) => {
if (error) {
throw new Error()
} else {
setUserAttending(true);
const eventPreview: EventPreview = {
id: event.id,
name: event.name,
host_name: clubName,
host_logo: clubLogo,
start_time: event.start_time,
end_time: event.end_time,
location: event.location,
event_type: event.event_type,
link: event.link,
}
dispatch(setUserRSVPs([...event.rsvps, eventPreview ]))
}
})
}

const handleUnregistration = () => {
unregisterUser({ user_id: userId, event_id: id as string })
.then(({ error }) => {
if (error) {
console.log(error);
throw new Error();
} else {
setUserAttending(false);
dispatch(setUserRSVPs([...rsvps.filter((event) => event.id !== id)]))
}
})
}

const headerAnimatedStyle = useAnimatedStyle(() => {
return {
transform: [
Expand Down Expand Up @@ -101,18 +148,6 @@ const EventPage = () => {
<Arrow color={apiError ? 'black' : 'white'} />
</Animated.View>
),
headerRight: !apiError
? () => (
<Animated.View style={headerAnimatedStyle}>
<KebabMenu
onPress={() =>
shareEvent.current?.snapToIndex(0)
}
color="white"
/>
</Animated.View>
)
: () => <></>
}}
/>
<Animated.ScrollView
Expand Down Expand Up @@ -153,7 +188,7 @@ const EventPage = () => {
register.current?.snapToIndex(0)
}
>
Register
{userAttending ? 'Registered': 'Register'}
</Button>
</Box>
<AboutEvent
Expand All @@ -180,6 +215,8 @@ const EventPage = () => {
eventName={event?.name as string}
location={event?.location as string}
eventType={event?.event_type as EventType}
userAttending={userAttending}
onSubmit={userAttending ? handleUnregistration : handleRegistration}
ref={register}
/>
<Description
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const Description = forwardRef<Ref, DescriptionProps>(
<BottomSheet
ref={ref}
index={-1}
snapPoints={['50%']}
snapPoints={['65%']}
enablePanDownToClose
backgroundStyle={{ backgroundColor: 'white' }}
backdropComponent={renderBackdrop}
Expand Down
8 changes: 7 additions & 1 deletion frontend/mobile/src/app/app/event/components/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ import { useAppDispatch } from '@/src/store/store';
import { firstLetterUppercase } from '@/src/utils/string';
import { createOptions, eventTime } from '@/src/utils/time';

const eventTypeMappings: Record<EventType, string> = {
'in_person': 'In Person',
'virtual': 'Virtual',
'hybrid': 'Hybrid'
}

interface OverviewProps {
logo: string;
eventName: string;
Expand Down Expand Up @@ -97,7 +103,7 @@ export const Overview: React.FC<OverviewProps> = ({
color={Colors[color]}
icon={faGlobe}
/>
<Text>{firstLetterUppercase(type)}</Text>
<Text>{eventTypeMappings[type]}</Text>
</Box>
</Box>
</Box>
Expand Down
69 changes: 58 additions & 11 deletions frontend/mobile/src/app/app/event/components/register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Divider } from './divider';

type Ref = BottomSheet;

const SaveEventText = `By saving this event, you are automatically signed up for notifications and this event will be added to your calendar.`;
const SaveEventText = `Add the event to your calendar to make sure you are always up to date with your upcoming events!`;

interface RegisterSheetProps {
eventType: EventType;
Expand All @@ -27,14 +27,16 @@ interface RegisterSheetProps {
location: string;
eventName: string;
eventDetail: string;
userAttending: boolean;
onSubmit: () => void;
}

const RegisterBottomSheet = forwardRef<Ref, RegisterSheetProps>(
(
{ eventType, eventName, location, eventDetail, startTime, endTime },
{ eventType, eventName, location, eventDetail, startTime, endTime, userAttending, onSubmit },
ref
) => {
const [sheet, setSheet] = useState('register');
const [sheet, setSheet] = useState(userAttending ? 'unregister' : 'register');

const renderBackdrop = useCallback(
(props: any) => (
Expand All @@ -47,6 +49,17 @@ const RegisterBottomSheet = forwardRef<Ref, RegisterSheetProps>(
[]
);

const handleRegistrationNavAndSubmit = (submit: boolean, nextSheet?: string) => {
try {
if (submit) {
onSubmit();
}
if (nextSheet) {
setSheet(nextSheet);
}
} catch {}
}

const CALENDAR_INFO: CalendarLink = {
eventDetail: eventDetail,
eventName: eventName,
Expand All @@ -63,12 +76,16 @@ const RegisterBottomSheet = forwardRef<Ref, RegisterSheetProps>(
enablePanDownToClose
backgroundStyle={{ backgroundColor: 'white' }}
backdropComponent={renderBackdrop}
onClose={() => setSheet(userAttending ? 'unregister' : 'register')}
>
{sheet === 'unregister' && (
<Unregister onClick={onSubmit} />
)}
{sheet === 'register' && (
<Register setSheet={setSheet} eventType={eventType} />
<Register onClick={handleRegistrationNavAndSubmit} eventType={eventType} />
)}
{sheet === 'attend' && (
<AttendanceType onPress={() => setSheet('save')} />
<AttendanceType onPress={() => handleRegistrationNavAndSubmit(true, 'save')} />
)}
{sheet === 'save' && (
<SaveEvent
Expand All @@ -80,8 +97,39 @@ const RegisterBottomSheet = forwardRef<Ref, RegisterSheetProps>(
}
);

interface UnregisterProps {
onClick: () => void;
}

const Unregister: React.FC<UnregisterProps> = ({ onClick }) => {
return (
<Box marginHorizontal="xl" flexDirection="column" gap="s">
<Text
paddingTop="s"
textAlign="center"
variant="subheader-2"
fontWeight="500"
>
Unregister
</Text>
<Divider />
<Text paddingTop="s">
Are you sure you want to unregister from this event?
</Text>
<Box marginTop="s" flexDirection="column" gap="s">
<Button
onPress={() => onClick()}
variant="standardButton"
>
<Text>Yes</Text>
</Button>
</Box>
</Box>
);
}

interface RegisterProps {
setSheet: React.Dispatch<React.SetStateAction<string>>;
onClick: (submit: boolean, nextSheet?: string) => void
eventType: EventType;
}

Expand All @@ -98,7 +146,7 @@ const userInfoSchema = z.object({
select: userDataSchema
});

const Register: React.FC<RegisterProps> = ({ setSheet, eventType }) => {
const Register: React.FC<RegisterProps> = ({ onClick, eventType }) => {
const {
control,
handleSubmit,
Expand All @@ -111,11 +159,11 @@ const Register: React.FC<RegisterProps> = ({ setSheet, eventType }) => {
const onSubmit = (data: UserData) => {
try {
if (data.select.key === 'maybe') {
setSheet('save');
onClick(false, 'save');
} else if (data.select.key === 'yes' && eventType === 'hybrid') {
setSheet('attend');
onClick(false, 'attend');
} else {
setSheet('save');
onClick(true, 'save');
}
} catch (error) {
if (error instanceof ZodError) {
Expand Down Expand Up @@ -189,7 +237,6 @@ const SaveEvent: React.FC<SaveEventProps> = ({ googleCalendar }) => (
>
<Text>Add to Google Calendar</Text>
</Button>
<Button variant="standardButton">Add to Apple Calendar</Button>
</Box>
</Box>
);
Expand Down
6 changes: 6 additions & 0 deletions frontend/mobile/src/app/app/user/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ const Layout = () => {
headerShown: false
}}
/>
<Stack.Screen
name="events"
options={{
headerShown: false
}}
/>
</Stack>
);
};
Expand Down
Loading

0 comments on commit 5e97526

Please sign in to comment.