diff --git a/backend/entities/clubs/followers/routes.go b/backend/entities/clubs/followers/routes.go index a89ee1f6..4b4e8fa1 100644 --- a/backend/entities/clubs/followers/routes.go +++ b/backend/entities/clubs/followers/routes.go @@ -1,8 +1,6 @@ package followers import ( - authMiddleware "github.com/GenerateNU/sac/backend/middleware/auth" - "github.com/GenerateNU/sac/backend/types" ) @@ -15,12 +13,12 @@ func ClubFollower(clubParams types.RouteParams) { clubFollowers.Get("/", clubParams.UtilityMiddleware.Paginator, clubFollowerController.GetClubFollowers) clubFollowers.Post( "/:userID", - authMiddleware.AttachExtractor(clubParams.AuthMiddleware.ClubAuthorizeById, authMiddleware.ExtractFromParams("clubID")), + clubParams.AuthMiddleware.UserAuthorizeById, clubFollowerController.CreateClubFollowing, ) clubFollowers.Delete( "/:userID", - authMiddleware.AttachExtractor(clubParams.AuthMiddleware.ClubAuthorizeById, authMiddleware.ExtractFromParams("clubID")), + clubParams.AuthMiddleware.UserAuthorizeById, clubFollowerController.DeleteClubFollowing, ) } diff --git a/frontend/lib/package.json b/frontend/lib/package.json index 185bd649..350abf78 100644 --- a/frontend/lib/package.json +++ b/frontend/lib/package.json @@ -1,6 +1,6 @@ { "name": "@generatesac/lib", - "version": "0.0.184", + "version": "0.0.186", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/frontend/lib/src/api/clubApi.ts b/frontend/lib/src/api/clubApi.ts index 70d9f8d3..4d6c5447 100644 --- a/frontend/lib/src/api/clubApi.ts +++ b/frontend/lib/src/api/clubApi.ts @@ -2,6 +2,7 @@ import { z } from "zod"; import { Club, + CreateClubFollower, CreateClubRequestBody, CreateClubTagsRequestBody, UpdateClubRequestBody, @@ -132,6 +133,22 @@ export const clubApi = baseApi.injectEndpoints({ return z.array(eventSchema).parse(response); }, }), + createClubFollower: builder.mutation({ + query: ({ club_id, user_id }) => ({ + url: `${CLUB_API_BASE_URL}/${club_id}/followers/${user_id}`, + method: "POST", + responseHandler: "text" + }), + invalidatesTags: ["Follower"], + }), + deleteClubFollower: builder.mutation({ + query: ({ club_id, user_id }) => ({ + url: `${CLUB_API_BASE_URL}/${club_id}/followers/${user_id}`, + method: "DELETE", + responseHandler: "text" + }), + invalidatesTags: ["Follower"], + }), clubFollowers: builder.query< User[], { id: string; queryParams?: PaginationQueryParams } @@ -154,47 +171,6 @@ export const clubApi = baseApi.injectEndpoints({ return z.array(userSchema).parse(response); }, }), - clubMembers: builder.query< - User[], - { id: string; queryParams?: PaginationQueryParams } - >({ - query: ({ id, queryParams }) => ({ - url: handleQueryParams( - `${CLUB_API_BASE_URL}/${id}/members/`, - queryParams, - ), - method: "GET", - }), - providesTags: (result) => - result - ? result.map((member) => ({ type: "User", id: member.id })) - : ["User"], - transformResponse: (response) => { - return z.array(userSchema).parse(response); - }, - }), - createClubMember: builder.mutation< - User, - { clubID: string; userID: string } - >({ - query: ({ clubID, userID }) => ({ - url: `${CLUB_API_BASE_URL}/${clubID}/members/${userID}`, - method: "POST", - }), - invalidatesTags: (result, _, { userID }) => - result ? [{ type: "User", id: userID }] : [], - }), - deleteClubMember: builder.mutation< - void, - { clubID: string; userID: string } - >({ - query: ({ clubID, userID }) => ({ - url: `${CLUB_API_BASE_URL}/${clubID}/members/${userID}`, - method: "DELETE", - }), - invalidatesTags: (result, _, { userID }) => - result ? [{ type: "User", id: userID }] : [], - }), clubPointOfContacts: builder.query({ query: (id) => ({ url: `${CLUB_API_BASE_URL}/${id}/pocs/`, diff --git a/frontend/lib/src/api/userApi.ts b/frontend/lib/src/api/userApi.ts index e91c205c..76c5cfb0 100644 --- a/frontend/lib/src/api/userApi.ts +++ b/frontend/lib/src/api/userApi.ts @@ -1,6 +1,5 @@ import { z } from "zod"; -import { Club, clubSchema } from "../types/club"; import { PaginationQueryParams } from "../types/root"; import { Tag, tagSchema } from "../types/tag"; import { @@ -11,6 +10,7 @@ import { userSchema, } from "../types/user"; import { baseApi, handleQueryParams } from "./base"; +import { Club, clubSchema } from "../types"; const USER_API_BASE_URL = "/users"; @@ -81,54 +81,6 @@ export const userApi = baseApi.injectEndpoints({ }), invalidatesTags: (_result, _, id) => [{ type: "User", id }], }), - userFollowing: builder.query({ - query: (id) => ({ - url: `${USER_API_BASE_URL}/${id}/follower/`, - method: "GET", - }), - providesTags: (result, _, id) => - result - ? [{ type: "Follower", id }, "Club"] - : [{ type: "Follower", id }], - transformResponse: (response) => { - return z.array(clubSchema).parse(response); - }, - }), - createUserFollowing: builder.mutation< - void, - { userID: string; clubID: string } - >({ - query: ({ userID, clubID }) => ({ - url: `${USER_API_BASE_URL}/${userID}/follower/${clubID}`, - method: "POST", - }), - invalidatesTags: (_result, _, { userID }) => [ - { type: "Follower", id: userID }, - ], - }), - deleteUserFollowing: builder.mutation< - void, - { userID: string; clubID: string } - >({ - query: ({ userID, clubID }) => ({ - url: `${USER_API_BASE_URL}/${userID}/follower/${clubID}`, - method: "DELETE", - }), - invalidatesTags: (_result, _, { userID }) => [ - { type: "Follower", id: userID }, - ], - }), - userMembership: builder.query({ - query: (id) => ({ - url: `${USER_API_BASE_URL}/${id}/member/`, - method: "GET", - }), - providesTags: (result, _, id) => - result ? [{ type: "Member", id }, "Club"] : [{ type: "Member", id }], - transformResponse: (response) => { - return z.array(clubSchema).parse(response); - }, - }), userTags: builder.query({ query: () => ({ url: `${USER_API_BASE_URL}/tags/`, @@ -159,5 +111,14 @@ export const userApi = baseApi.injectEndpoints({ }), invalidatesTags: (_result, _, id) => [{ type: "Tag", id }], }), + getUserFollowing: builder.query({ + query: (id) => ({ + url: `${USER_API_BASE_URL}/${id}/follower`, + method: "GET", + }), + transformResponse: (response) => { + return z.array(clubSchema).parse(response); + }, + }) }), }); diff --git a/frontend/lib/src/types/club.ts b/frontend/lib/src/types/club.ts index 20e871cf..cc67c8a7 100644 --- a/frontend/lib/src/types/club.ts +++ b/frontend/lib/src/types/club.ts @@ -42,6 +42,11 @@ const clubSchemaIntermediate = z.object({ recruitment: recruitmentSchema.optional(), }); +const createClubFollowerSchema = z.object({ + club_id: z.string().uuid(), + user_id: z.string().uuid(), +}); + export const clubSchema = clubSchemaIntermediate.merge(rootModelSchema); // Types: @@ -50,4 +55,5 @@ export type UpdateClubRequestBody = z.infer; export type CreateClubTagsRequestBody = z.infer< typeof createClubTagsRequestBodySchema >; +export type CreateClubFollower = z.infer; export type Club = z.infer; diff --git a/frontend/mobile/package.json b/frontend/mobile/package.json index 74efa44e..97789045 100644 --- a/frontend/mobile/package.json +++ b/frontend/mobile/package.json @@ -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.184", + "@generatesac/lib": "0.0.186", "@gorhom/bottom-sheet": "^4.6.3", "@hookform/resolvers": "^3.4.2", "@react-native-async-storage/async-storage": "^1.23.1", diff --git a/frontend/mobile/src/app/app/(tabs)/_layout.tsx b/frontend/mobile/src/app/app/(tabs)/_layout.tsx index 174ec3a6..6ee8a027 100644 --- a/frontend/mobile/src/app/app/(tabs)/_layout.tsx +++ b/frontend/mobile/src/app/app/(tabs)/_layout.tsx @@ -4,7 +4,6 @@ import { Tabs } from 'expo-router'; import { IconDefinition } from '@fortawesome/fontawesome-svg-core'; import { faCalendarDays } from '@fortawesome/free-solid-svg-icons/faCalendarDays'; -import { faHouse } from '@fortawesome/free-solid-svg-icons/faHouse'; import { faUser } from '@fortawesome/free-solid-svg-icons/faUser'; import { Text } from '@/src/app/design-system'; @@ -49,17 +48,6 @@ const Layout = () => { backgroundColor: 'white' }} > - - TabBarLabel({ focused, title: 'Home' }), - tabBarIcon: ({ focused }) => - TabBarIcon({ focused, icon: faHouse }) - }} - /> { - return <>; -}; - -export default HomePage; diff --git a/frontend/mobile/src/app/app/(tabs)/profile.tsx b/frontend/mobile/src/app/app/(tabs)/profile.tsx index 06275c0f..37e32132 100644 --- a/frontend/mobile/src/app/app/(tabs)/profile.tsx +++ b/frontend/mobile/src/app/app/(tabs)/profile.tsx @@ -6,7 +6,6 @@ import { router } from 'expo-router'; import { IconDefinition, - faHeart, faSignOutAlt, faUser } from '@fortawesome/free-solid-svg-icons'; @@ -62,7 +61,7 @@ const ProfilePage = () => { - router.push('/app/user/detail/')} icon={faUser} text="Edit Profile" @@ -71,6 +70,11 @@ const ProfilePage = () => { icon={faHeart} onPress={() => router.push('/app/user/interest/')} text="Edit Interests" + /> */} + router.push('/app/user/following/')} + text="Following" /> { const styles = StyleSheet.create({ container: { - flex: 1, flexDirection: 'column', alignItems: 'flex-start', justifyContent: 'flex-start', diff --git a/frontend/mobile/src/app/app/club/[id].tsx b/frontend/mobile/src/app/app/club/[id].tsx index 3a6b5f38..dd285840 100644 --- a/frontend/mobile/src/app/app/club/[id].tsx +++ b/frontend/mobile/src/app/app/club/[id].tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef } from 'react'; +import { useRef } from 'react'; import { Dimensions, Linking } from 'react-native'; import Animated, { interpolate, @@ -10,6 +10,7 @@ import Animated, { import { Stack, useLocalSearchParams } from 'expo-router'; import { faExternalLink } from '@fortawesome/free-solid-svg-icons'; +import { clubApi } from '@generatesac/lib'; import BottomSheet from '@gorhom/bottom-sheet'; import { @@ -22,7 +23,7 @@ import { import { SACColors } from '@/src/app/design-system'; import { Button } from '@/src/app/design-system/components/Button/Button'; import useClub from '@/src/hooks/useClub'; -import { setClubId } from '@/src/store/slices/clubSlice'; +import { setUserFollowing } from '@/src/store/slices/userSlice'; import { useAppDispatch, useAppSelector } from '@/src/store/store'; import { AboutSection } from '../../design-system/components/AboutSection/AboutSection'; @@ -47,13 +48,35 @@ const ClubPage = () => { const bottomSheet = useRef(null); const club = useAppSelector((state) => state.club); + const { id: user_id, following } = useAppSelector((state) => state.user); const dispatch = useAppDispatch(); - const { setRetriggerFetch, apiLoading, apiError } = useClub(); + const { setRetriggerFetch, apiLoading, apiError } = useClub(id); + const [followClub] = clubApi.useCreateClubFollowerMutation(); + const [unFollowClub] = clubApi.useDeleteClubFollowerMutation(); - useEffect(() => { - dispatch(setClubId(id)); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const clubFollowed = following.includes(id as string); + + const handleUserFollow = (follow: boolean) => { + if (id) { + if (follow) { + followClub({ club_id: id, user_id }).then(({ error }) => { + if (!error) { + dispatch(setUserFollowing([...following, id])); + } + }); + } else { + unFollowClub({ club_id: id, user_id }).then(({ error }) => { + if (!error) { + dispatch( + setUserFollowing( + following.filter((clubId) => clubId !== id) + ) + ); + } + }); + } + } + }; const headerAnimatedStyle = useAnimatedStyle(() => { return { @@ -92,7 +115,7 @@ const ClubPage = () => { scrollEventThrottle={16} ref={scrollRef} > - {apiLoading ? ( + {apiLoading || club.id !== id ? ( ) : apiError ? ( @@ -119,8 +142,11 @@ const ClubPage = () => { color={color} size="sm" variant="standardButton" + onPress={() => + handleUserFollow(!clubFollowed) + } > - Follow + {clubFollowed ? 'Unfollow' : 'Follow'} diff --git a/frontend/mobile/src/app/app/user/_layout.tsx b/frontend/mobile/src/app/app/user/_layout.tsx index be0d2d5e..55936478 100644 --- a/frontend/mobile/src/app/app/user/_layout.tsx +++ b/frontend/mobile/src/app/app/user/_layout.tsx @@ -5,13 +5,24 @@ import { Stack } from 'expo-router'; const Layout = () => { return ( - + + ); }; diff --git a/frontend/mobile/src/app/app/user/following.tsx b/frontend/mobile/src/app/app/user/following.tsx new file mode 100644 index 00000000..33e44fa7 --- /dev/null +++ b/frontend/mobile/src/app/app/user/following.tsx @@ -0,0 +1,89 @@ +import { useEffect } from 'react'; +import { SafeAreaView } from 'react-native'; + +import { Stack, router } from 'expo-router'; + +import { userApi } from '@generatesac/lib'; + +import { useAppSelector } from '@/src/store/store'; + +import { Arrow, Box, Button, Text } from '../../design-system'; +import { Clubcard } from '../../design-system/components/ClubCard/ClubCard'; +import ClubCardStandardSkeleton from '../../design-system/components/ClubCard/Skeletons/ClubCardStandardSkeleton'; +import { GlobalLayout } from '../../design-system/components/GlobalLayout/GlobalLayout'; +import PageError from '../../design-system/components/PageError/PageError'; + +const Following = () => { + const { id, following } = useAppSelector((state) => state.user); + const [getFollowers, { data, isLoading, error }] = + userApi.useLazyGetUserFollowingQuery(); + + useEffect(() => { + getFollowers(id); + }, [following, id, getFollowers]); + + if (error) { + return {}} />; + } + + return ( + <> + ( + Clubs you Follow + ), + headerTransparent: true, + headerShown: true, + headerLeft: () => + }} + /> + + + + {isLoading || !data ? ( + + + + + + ) : ( + + {data.map((club) => { + if (club.name !== 'SAC') { + return ( + + ); + } + })} + + + + + )} + + + + + ); +}; + +export default Following; diff --git a/frontend/mobile/src/app/auth/callback.tsx b/frontend/mobile/src/app/auth/callback.tsx index 908c8114..d8651acd 100644 --- a/frontend/mobile/src/app/auth/callback.tsx +++ b/frontend/mobile/src/app/auth/callback.tsx @@ -3,11 +3,16 @@ import { Image } from 'react-native'; import { router, useLocalSearchParams } from 'expo-router'; -import { OAuthCallbackRequestQueryParams, authApi } from '@generatesac/lib'; +import { + Club, + OAuthCallbackRequestQueryParams, + authApi, + userApi +} from '@generatesac/lib'; import Loading from '@/src/assets/gif/loading.gif'; import { setLoggedIn } from '@/src/store/slices/globalSlice'; -import { setUser } from '@/src/store/slices/userSlice'; +import { setUser, setUserFollowing } from '@/src/store/slices/userSlice'; import { useAppDispatch, useAppSelector } from '@/src/store/store'; import { Box, Text } from '../design-system'; @@ -15,17 +20,38 @@ import { Box, Text } from '../design-system'; const OAuthCallback = () => { const params = useLocalSearchParams(); const [oAuthCallback] = authApi.useLazyCallbackQuery(); + const [getUserFollowing] = userApi.useLazyGetUserFollowingQuery(); const dispatch = useAppDispatch(); const { accessToken } = useAppSelector((state) => state.global); + const parseUserFollowing = (clubs: Club[]) => { + return clubs + .filter((club) => club.name !== 'SAC') + .map((club) => club.id); + }; + useEffect(() => { const { code, session_state, state } = params as OAuthCallbackRequestQueryParams; if (code || session_state || state) { oAuthCallback({ code, session_state, state }).then( - ({ data, error }) => { + async ({ data, error }) => { if (data) { + // Set the user: dispatch(setUser(data)); + + // Retrieve their following: + await getUserFollowing(data.id).then( + ({ data: followingData }) => { + if (followingData) { + const following = + parseUserFollowing(followingData); + dispatch(setUserFollowing(following)); + } + } + ); + + // Set the user as logged in and redirect to the app: dispatch(setLoggedIn(true)); router.push('/app/'); } diff --git a/frontend/mobile/src/app/design-system/components/ClubCard/ClubCard.tsx b/frontend/mobile/src/app/design-system/components/ClubCard/ClubCard.tsx new file mode 100644 index 00000000..5fa309f1 --- /dev/null +++ b/frontend/mobile/src/app/design-system/components/ClubCard/ClubCard.tsx @@ -0,0 +1,25 @@ +import { Tag } from '@generatesac/lib'; + +import ClubCardStandard from './Variants/ClubCardStandard'; + +export interface ClubCardProps { + id: string; + logo: string; + name: string; + tags?: Tag[]; + variant?: 'standard'; +} + +export const Clubcard = ({ + id, + logo, + name, + variant = 'standard' +}: ClubCardProps) => { + switch (variant) { + case 'standard': + return ; + default: + return ; + } +}; diff --git a/frontend/mobile/src/app/design-system/components/ClubCard/Skeletons/ClubCardStandardSkeleton.tsx b/frontend/mobile/src/app/design-system/components/ClubCard/Skeletons/ClubCardStandardSkeleton.tsx new file mode 100644 index 00000000..003e4447 --- /dev/null +++ b/frontend/mobile/src/app/design-system/components/ClubCard/Skeletons/ClubCardStandardSkeleton.tsx @@ -0,0 +1,48 @@ +import { Skeleton } from '@rneui/base'; + +import { Colors } from '../../../shared/colors'; +import { createStyles } from '../../../theme'; +import { Box } from '../../Box/Box'; + +const ClubCardStandardSkeleton = () => { + return ( + + + + + + + ); +}; + +const styles = createStyles({ + cardContainer: { + shadowColor: 'black', + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.1, + shadowRadius: 2, + backgroundColor: 'white', + borderRadius: 'md' + }, + cardSubContainer: { + width: '100%', + borderRadius: 'md', + padding: 'm', + backgroundColor: 'white', + flexDirection: 'row', + alignItems: 'center', + gap: 's', + overflow: 'hidden' + } +}); + +export default ClubCardStandardSkeleton; diff --git a/frontend/mobile/src/app/design-system/components/ClubCard/Variants/ClubCardStandard.tsx b/frontend/mobile/src/app/design-system/components/ClubCard/Variants/ClubCardStandard.tsx new file mode 100644 index 00000000..6e500096 --- /dev/null +++ b/frontend/mobile/src/app/design-system/components/ClubCard/Variants/ClubCardStandard.tsx @@ -0,0 +1,59 @@ +import { TouchableOpacity } from 'react-native-gesture-handler'; + +import { router } from 'expo-router'; + +import { resetEvent } from '@/src/store/slices/eventSlice'; +import { useAppDispatch } from '@/src/store/store'; + +import { createStyles } from '../../../theme'; +import { Box } from '../../Box/Box'; +import { ClubIcon } from '../../ClubIcon/ClubIcon'; +import { Text } from '../../Text/Text'; +import { ClubCardProps } from '../ClubCard'; + +const ClubCardStandard = ({ logo, name, id }: ClubCardProps) => { + const dispatch = useAppDispatch(); + + return ( + + { + dispatch(resetEvent()); + router.navigate(`/app/club/${id}`); + }} + > + + + + {name.length > 28 + ? name.slice(0, 28).trim() + '...' + : name} + + + + + ); +}; + +const styles = createStyles({ + cardContainer: { + shadowColor: 'black', + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.1, + shadowRadius: 2, + backgroundColor: 'white', + borderRadius: 'md', + width: '100%' + }, + cardSubContainer: { + width: '100%', + borderRadius: 'md', + padding: 'm', + backgroundColor: 'white', + flexDirection: 'row', + alignItems: 'center', + gap: 's' + } +}); + +export default ClubCardStandard; diff --git a/frontend/mobile/src/app/design-system/components/ClubIcon/ClubIcon.tsx b/frontend/mobile/src/app/design-system/components/ClubIcon/ClubIcon.tsx index 5a9280cb..fa90f870 100644 --- a/frontend/mobile/src/app/design-system/components/ClubIcon/ClubIcon.tsx +++ b/frontend/mobile/src/app/design-system/components/ClubIcon/ClubIcon.tsx @@ -4,12 +4,13 @@ import { Avatar } from '@rneui/themed'; interface ClubIconProps { imageUrl: string; + size?: number; } -export const ClubIcon: React.FC = ({ imageUrl }) => { +export const ClubIcon: React.FC = ({ imageUrl, size = 77 }) => { return ( { - return ( - - {children} - - ); + return {children}; }; diff --git a/frontend/mobile/src/hooks/useClub.ts b/frontend/mobile/src/hooks/useClub.ts index d1ec9707..57893162 100644 --- a/frontend/mobile/src/hooks/useClub.ts +++ b/frontend/mobile/src/hooks/useClub.ts @@ -5,7 +5,7 @@ import { clubApi } from '@generatesac/lib'; import { setClub, setClubEvents, setClubTags } from '../store/slices/clubSlice'; import { useAppDispatch, useAppSelector } from '../store/store'; -const useClub = () => { +const useClub = (id?: string) => { const [retriggerFetch, setRetriggerFetch] = useState(false); const [getClub, { isLoading: clubLoading, error: clubError }] = @@ -21,9 +21,11 @@ const useClub = () => { const apiLoading = clubLoading || tagsLoading || eventsLoading; const apiError = clubError || tagsError || eventsError; + const idToFetch = id ?? clubId; + useEffect(() => { - if (clubId !== '') { - getClub(clubId).then(({ data: clubData }) => { + if (idToFetch !== '') { + getClub(idToFetch).then(({ data: clubData }) => { if (clubData) { dispatch(setClub(clubData)); } @@ -35,7 +37,7 @@ const useClub = () => { } }); - getEvents({ id: clubId }).then(({ data: eventData }) => { + getEvents({ id: idToFetch }).then(({ data: eventData }) => { if (eventData) { const sortedEvents = [...eventData]; sortedEvents.sort((a, b) => { @@ -54,7 +56,7 @@ const useClub = () => { }); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [retriggerFetch, clubId]); + }, [retriggerFetch, idToFetch]); return { setRetriggerFetch, diff --git a/frontend/mobile/src/store/slices/userSlice.ts b/frontend/mobile/src/store/slices/userSlice.ts index 0f5528bd..ae50a937 100644 --- a/frontend/mobile/src/store/slices/userSlice.ts +++ b/frontend/mobile/src/store/slices/userSlice.ts @@ -1,13 +1,20 @@ import { User } from '@generatesac/lib'; import { createSlice } from '@reduxjs/toolkit'; -const initialState: User = { +type UserState = { + following: string[]; + rsvps: string[]; +}; + +const initialState: User & UserState = { id: '', email: '', created_at: '', updated_at: '', name: '', - role: 'student' + role: 'student', + following: [], + rsvps: [] }; export const userSlice = createSlice({ @@ -26,9 +33,16 @@ export const userSlice = createSlice({ state.name = action.payload.name; state.role = action.payload.role; }, - resetUser: () => initialState + resetUser: () => initialState, + setUserFollowing: (state, action) => { + state.following = action.payload; + }, + setUserRSVPs: (state, action) => { + state.rsvps = action.payload; + } } }); -export const { setUser, resetUser } = userSlice.actions; +export const { setUser, resetUser, setUserFollowing, setUserRSVPs } = + userSlice.actions; export default userSlice.reducer; diff --git a/frontend/mobile/yarn.lock b/frontend/mobile/yarn.lock index 065c593e..a164934e 100644 --- a/frontend/mobile/yarn.lock +++ b/frontend/mobile/yarn.lock @@ -1402,10 +1402,10 @@ humps "^2.0.1" prop-types "^15.7.2" -"@generatesac/lib@0.0.184": - version "0.0.184" - resolved "https://registry.yarnpkg.com/@generatesac/lib/-/lib-0.0.184.tgz#1a024934e05e69685a46bfcfe388fdf8b4809226" - integrity sha512-btRNxaCH7ovI9WCRt/0fsaUTW2mWzhgDZwBC6fDmIH929bo6etX477jPAdtBJXAWxMz/RIYvIAuLRda8qma/oA== +"@generatesac/lib@0.0.186": + version "0.0.186" + resolved "https://registry.yarnpkg.com/@generatesac/lib/-/lib-0.0.186.tgz#2e77a197b8fc621ec3ec07ee990d9acc3d867fa9" + integrity sha512-CPZsejA4K/3/uk0E1Al1vahtYh7bRLKt2Fn8qoOA+Rq1jZKUbkp6NVO+2iDz+yyZfA2UwpSUhbzjKnE/YbTuGg== dependencies: "@reduxjs/toolkit" "^2.2.3" react "^18.2.0"