Skip to content

Commit

Permalink
merge summer-demo
Browse files Browse the repository at this point in the history
  • Loading branch information
Alder Whiteford authored and Alder Whiteford committed Jun 20, 2024
2 parents c108db6 + e321819 commit b13fe76
Show file tree
Hide file tree
Showing 17 changed files with 305 additions and 43 deletions.
2 changes: 1 addition & 1 deletion backend/entities/events/rsvps/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func EventsRSVPs(params types.RouteParams) {
controller := NewController(NewHandler(params.ServiceParams))

// api/v1/events/:eventID/rsvps/*
params.Router.Route("/rsvps", func(r fiber.Router) {
params.Router.Route("/:eventID/rsvps", func(r fiber.Router) {
r.Get("/", params.UtilityMiddleware.Paginator, controller.GetEventRSVPs)
r.Post("/:userID", controller.CreateEventRSVP)
r.Delete("/:userID", params.AuthMiddleware.UserAuthorizeById, params.AuthMiddleware.Authorize(permission.DeleteAll), controller.DeleteEventRSVP)
Expand Down
2 changes: 1 addition & 1 deletion backend/integrations/oauth/soth/msft_web/msft_web.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var defaultScopes = []string{"openid", "offline_access", "user.read", "calendars
func New(clientKey *m.Secret[string], secret *m.Secret[string], callbackURL string, tenant string, scopes ...string) *Provider {
p := &Provider{
ClientKey: clientKey,
Secret: secret,
Secret: secret,
CallbackURL: callbackURL,
ProviderName: "microsoftonlineweb",
tenant: tenant,
Expand Down
30 changes: 29 additions & 1 deletion frontend/lib/src/api/eventApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import {
CreateEventRequestBody,
Event,
EventPreview,
EventUserParams,
UpdateEventRequestBody,
eventPreviewSchema,
eventSchema,
} from "../types/event";
import { PaginationQueryParams } from "../types/root";
import { Tag } from "../types/tag";
import { Tag, tagSchema } from "../types/tag";
import { baseApi, handleQueryParams } from "./base";
import { User, userSchema } from "../types";

const EVENT_API_BASE_URL = "/events";

Expand Down Expand Up @@ -102,6 +104,32 @@ export const eventApi = baseApi.injectEndpoints({
}),
providesTags: (result) =>
result ? result.map((tag) => ({ type: "Tag", id: tag.id })) : ["Tag"],
transformResponse: (response) => {
return z.array(tagSchema).parse(response);
}
}),
createEventRegistration: builder.mutation<User[], EventUserParams>({
query: ({ user_id, event_id }) => ({
url: `${EVENT_API_BASE_URL}/${event_id}/rsvps/${user_id}`,
method: "POST",
responseHandler: 'text'
}),
}),
deleteEventRegistration: builder.mutation<void, EventUserParams>({
query: ({ user_id, event_id }) => ({
url: `${EVENT_API_BASE_URL}/${event_id}/rsvps/${user_id}`,
method: "DELETE",
responseHandler: 'text',
}),
}),
eventRegistrations: builder.query<User[], string>({
query: (id) => ({
url: `${EVENT_API_BASE_URL}/${id}/rsvps`,
method: "GET",
}),
transformResponse: (response) => {
return z.array(userSchema).parse(response);
},
}),
}),
});
6 changes: 6 additions & 0 deletions frontend/lib/src/types/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ const eventPreviewSchemaIntermediate = z.object({
host_logo: z.string().max(255).optional(),
});

const eventUserParams = z.object({
event_id: z.string().uuid(),
user_id: z.string().uuid(),
})

export const eventSchema = eventSchemaIntermediate.merge(rootModelSchema);
export const eventPreviewSchema = eventPreviewSchemaIntermediate

Expand All @@ -79,3 +84,4 @@ export type UpdateEventRequestBody = z.infer<
export type Event = z.infer<typeof eventSchema>;
export type EventPreview = z.infer<typeof eventPreviewSchema>;
export type EventType = z.infer<typeof eventTypeEnum>;
export type EventUserParams = z.infer<typeof eventUserParams>;
12 changes: 12 additions & 0 deletions frontend/mobile/src/app/app/(tabs)/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import { router } from 'expo-router';

import {
IconDefinition,
faCalendar,
faSignOutAlt,
faUser
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';

import { GlobalLayout } from '@/src/app/design-system/components/GlobalLayout/GlobalLayout';
import { resetClub } from '@/src/store/slices/clubSlice';
import { resetEvent } from '@/src/store/slices/eventSlice';
import { resetAccessToken } from '@/src/store/slices/globalSlice';
import { resetUser } from '@/src/store/slices/userSlice';
import { useAppDispatch, useAppSelector } from '@/src/store/store';

import { Box, Colors, SACColors, Spacing, Text } from '../../design-system';
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
83 changes: 66 additions & 17 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,15 +9,16 @@ 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';
import { Arrow, Box } from '@/src/app/design-system';
import { SACColors } from '@/src/app/design-system';
import { Button } from '@/src/app/design-system/components/Button/Button';
import { description, events, tags } from '@/src/consts/event-page';
import useEvent from '@/src/hooks/useEvent';
import { setEventId } from '@/src/store/slices/eventSlice';
import { setUserRSVPs } from '@/src/store/slices/userSlice';
import { useAppDispatch, useAppSelector } from '@/src/store/store';

import AnimatedImageHeader from '../../design-system/components/AnimatedImageHeader/AnimatedImageHeader';
Expand Down Expand Up @@ -60,18 +61,72 @@ 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)

Check warning on line 122 in frontend/mobile/src/app/app/event/[id].tsx

View workflow job for this annotation

GitHub Actions / Lint

'event' is already declared in the upper scope on line 65 column 11
])
);
}
}
);
};

const headerAnimatedStyle = useAnimatedStyle(() => {
return {
transform: [
Expand Down Expand Up @@ -100,19 +155,7 @@ const EventPage = () => {
<Animated.View style={headerAnimatedStyle}>
<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 +196,9 @@ const EventPage = () => {
register.current?.snapToIndex(0)
}
>
Register
{userAttending
? 'Registered'
: 'Register'}
</Button>
</Box>
<AboutEvent
Expand All @@ -180,6 +225,10 @@ 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
9 changes: 7 additions & 2 deletions frontend/mobile/src/app/app/event/components/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import { Avatar } from '@rneui/base';
import { Box, Colors, SACColors, Text } from '@/src/app/design-system';
import { setClubId, setClubShouldPreview } from '@/src/store/slices/clubSlice';
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 +102,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
Loading

0 comments on commit b13fe76

Please sign in to comment.