Skip to content

Commit

Permalink
Add Club Following
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 6cd9ec0 commit 3d58e75
Show file tree
Hide file tree
Showing 23 changed files with 355 additions and 143 deletions.
6 changes: 2 additions & 4 deletions backend/entities/clubs/followers/routes.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package followers

import (
authMiddleware "github.com/GenerateNU/sac/backend/middleware/auth"

"github.com/GenerateNU/sac/backend/types"
)

Expand All @@ -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,
)
}
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.184",
"version": "0.0.186",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
58 changes: 17 additions & 41 deletions frontend/lib/src/api/clubApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { z } from "zod";

import {
Club,
CreateClubFollower,
CreateClubRequestBody,
CreateClubTagsRequestBody,
UpdateClubRequestBody,
Expand Down Expand Up @@ -132,6 +133,22 @@ export const clubApi = baseApi.injectEndpoints({
return z.array(eventSchema).parse(response);
},
}),
createClubFollower: builder.mutation<void, CreateClubFollower>({
query: ({ club_id, user_id }) => ({
url: `${CLUB_API_BASE_URL}/${club_id}/followers/${user_id}`,
method: "POST",
responseHandler: "text"
}),
invalidatesTags: ["Follower"],
}),
deleteClubFollower: builder.mutation<void, CreateClubFollower>({
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 }
Expand All @@ -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<PointOfContact[], string>({
query: (id) => ({
url: `${CLUB_API_BASE_URL}/${id}/pocs/`,
Expand Down
59 changes: 10 additions & 49 deletions frontend/lib/src/api/userApi.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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";

Expand Down Expand Up @@ -81,54 +81,6 @@ export const userApi = baseApi.injectEndpoints({
}),
invalidatesTags: (_result, _, id) => [{ type: "User", id }],
}),
userFollowing: builder.query<Club[], string>({
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<Club[], string>({
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<Tag[], void>({
query: () => ({
url: `${USER_API_BASE_URL}/tags/`,
Expand Down Expand Up @@ -159,5 +111,14 @@ export const userApi = baseApi.injectEndpoints({
}),
invalidatesTags: (_result, _, id) => [{ type: "Tag", id }],
}),
getUserFollowing: builder.query<Club[], string>({
query: (id) => ({
url: `${USER_API_BASE_URL}/${id}/follower`,
method: "GET",
}),
transformResponse: (response) => {
return z.array(clubSchema).parse(response);
},
})
}),
});
6 changes: 6 additions & 0 deletions frontend/lib/src/types/club.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -50,4 +55,5 @@ export type UpdateClubRequestBody = z.infer<typeof updateClubRequestBodySchema>;
export type CreateClubTagsRequestBody = z.infer<
typeof createClubTagsRequestBodySchema
>;
export type CreateClubFollower = z.infer<typeof createClubFollowerSchema>;
export type Club = z.infer<typeof clubSchema>;
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.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",
Expand Down
11 changes: 0 additions & 11 deletions frontend/mobile/src/app/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,6 @@ const Layout = () => {
backgroundColor: 'white'
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
headerShown: false,
tabBarLabel: ({ focused }) =>
TabBarLabel({ focused, title: 'Home' }),
tabBarIcon: ({ focused }) =>
TabBarIcon({ focused, icon: faHouse })
}}
/>
<Tabs.Screen
name="calendar"
options={{
Expand Down
7 changes: 0 additions & 7 deletions frontend/mobile/src/app/app/(tabs)/index.tsx

This file was deleted.

8 changes: 6 additions & 2 deletions frontend/mobile/src/app/app/(tabs)/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const ProfilePage = () => {
</Box>
</Box>
<Box width="100%">
<ProfileItem
{/* <ProfileItem
onPress={() => router.push('/app/user/detail/')}
icon={faUser}
text="Edit Profile"
Expand All @@ -71,6 +71,11 @@ const ProfilePage = () => {
icon={faHeart}
onPress={() => router.push('/app/user/interest/')}
text="Edit Interests"
/> */}
<ProfileItem
icon={faUser}
onPress={() => router.push('/app/user/following/')}
text="Following"
/>
<Box
width="100%"
Expand All @@ -94,7 +99,6 @@ const ProfilePage = () => {

const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'flex-start',
justifyContent: 'flex-start',
Expand Down
37 changes: 30 additions & 7 deletions frontend/mobile/src/app/app/club/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import { EventCardList } from '../../design-system/components/EventCard/EventCar
import PageError from '../../design-system/components/PageError/PageError';
import { Description } from '../event/components/description';
import ClubPageSkeleton from './components/skeleton';
import { clubApi } from '@generatesac/lib';

Check failure on line 36 in frontend/mobile/src/app/app/club/[id].tsx

View workflow job for this annotation

GitHub Actions / Lint

Delete `import·{·clubApi·}·from·'@generatesac/lib';⏎import·{·setUserFollowing·}·from·'@/src/store/slices/userSlice';⏎`
import { setUserFollowing } from '@/src/store/slices/userSlice';

const color: SACColors = 'darkRed';

Expand All @@ -47,13 +49,33 @@ const ClubPage = () => {
const bottomSheet = useRef<BottomSheet>(null);

const club = useAppSelector((state) => state.club);
const { id: user_id, following } = useAppSelector((state) => state.user)

Check failure on line 52 in frontend/mobile/src/app/app/club/[id].tsx

View workflow job for this annotation

GitHub Actions / Lint

Insert `;`
const dispatch = useAppDispatch();
const { setRetriggerFetch, apiLoading, apiError } = useClub();
const { setRetriggerFetch, apiLoading, apiError } = useClub(id);
const [followClub] = clubApi.useCreateClubFollowerMutation();
const [unFollowClub] = clubApi.useDeleteClubFollowerMutation();

Check failure on line 57 in frontend/mobile/src/app/app/club/[id].tsx

View workflow job for this annotation

GitHub Actions / Lint

Delete `····`
const clubFollowed = following.includes(id as string);

useEffect(() => {
dispatch(setClubId(id));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleUserFollow = (follow: boolean) => {
if (id) {
if (follow) {
followClub({ club_id: id, user_id })

Check failure on line 63 in frontend/mobile/src/app/app/club/[id].tsx

View workflow job for this annotation

GitHub Actions / Lint

Delete `⏎····················`
.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 {
Expand Down Expand Up @@ -92,7 +114,7 @@ const ClubPage = () => {
scrollEventThrottle={16}
ref={scrollRef}
>
{apiLoading ? (
{apiLoading || club.id !== id ? (
<ClubPageSkeleton />
) : apiError ? (
<PageError refetch={setRetriggerFetch} />
Expand All @@ -119,8 +141,9 @@ const ClubPage = () => {
color={color}
size="sm"
variant="standardButton"
onPress={() => handleUserFollow(!clubFollowed)}
>
Follow
{clubFollowed ? 'Unfollow' : 'Follow'}
</Button>
</Box>
</Box>
Expand Down
13 changes: 12 additions & 1 deletion frontend/mobile/src/app/app/user/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,24 @@ import { Stack } from 'expo-router';
const Layout = () => {
return (
<Stack>
<Stack.Screen name="interest" options={{ headerShown: false }} />
<Stack.Screen
name="interest"
options={{
headerShown: false
}}
/>
<Stack.Screen
name="detail"
options={{
headerShown: false
}}
/>
<Stack.Screen
name="following"
options={{
headerShown: false
}}
/>
</Stack>
);
};
Expand Down
Loading

0 comments on commit 3d58e75

Please sign in to comment.