Skip to content

Commit

Permalink
feat(friends): add incoming/outgoing request attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Likqez committed Dec 4, 2024
1 parent d1f89a0 commit 8db2fea
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 14 deletions.
23 changes: 21 additions & 2 deletions DB/friendships.sql
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,20 @@ BEGIN
END;
$$ LANGUAGE plpgsql;

-- 2nd version with id
CREATE OR REPLACE FUNCTION remove_friend_by_id(friendship_id_param INT) RETURNS void AS
$$
BEGIN
DELETE
FROM friendships
WHERE friendship_id = friendship_id_param
AND status = 'accepted';

IF NOT FOUND THEN
RAISE EXCEPTION 'No active friendship found with this ID';
END IF;
END;
$$ LANGUAGE plpgsql;

-- retrieve all friends, incoming and outgoing friend requests
CREATE OR REPLACE FUNCTION get_friends(user_id UUID)
Expand All @@ -147,7 +161,8 @@ CREATE OR REPLACE FUNCTION get_friends(user_id UUID)
status friendship_status,
action_user_id UUID,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE
updated_at TIMESTAMP WITH TIME ZONE,
request_type TEXT
)
AS
$$
Expand All @@ -161,7 +176,11 @@ BEGIN
f.status,
f.action_user_id,
f.created_at,
f.updated_at
f.updated_at,
CASE
WHEN f.action_user_id = user_id THEN 'outgoing'
ELSE 'incoming'
END AS request_type
FROM friendships f
WHERE (f.user1_id = user_id OR f.user2_id = user_id)
AND (f.status != 'declined');
Expand Down
30 changes: 27 additions & 3 deletions pages/testfriends.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import {
type FriendActionRequest,
FriendshipAction,
FriendshipStatus,
FriendshipType,
type GetFriendsResponse
} from "@/types/api/user.friends";
const requests: Ref<GetFriendsResponse[]> = useState("all_friendships", ()=> [])
const requests: Ref<GetFriendsResponse[]> = useState("incoming_friendships", ()=> [])
const friends: Ref<GetFriendsResponse[]> = useState("accepted_friendships", () => [])
const session = useSupabaseSession()
Expand All @@ -20,7 +21,7 @@ onMounted(async () => {
async function getFriendships() {
$fetch<GetFriendsResponse[]>('http://localhost:3000/api/v1/user/friends')
.then((data) => {
requests.value = data.filter((item) => item.status === FriendshipStatus.PENDING)
requests.value = data.filter((item) =>item.request_type == FriendshipType.INCOMING && item.status === FriendshipStatus.PENDING)
friends.value = data.filter((item) => item.status === FriendshipStatus.ACCEPTED)
});
}
Expand All @@ -36,6 +37,10 @@ function handleFriendRequestAction(action: FriendshipAction, friendship_id: numb
// optimistically update the UI instantly
requests.value = requests.value.filter((item) => item.friendship_id !== friendship_id)
getFriendships() // lazily refresh the list
} else if (action === FriendshipAction.REMOVE) {
// optimistically update the UI instantly
friends.value = friends.value.filter((item) => item.friendship_id !== friendship_id)
getFriendships() // lazily refresh the list
}
}
Expand Down Expand Up @@ -68,6 +73,20 @@ function decline(friendship_id: number) {
})
}
function remove(friendship_id: number) {
const actionRequest: FriendActionRequest = {
friendship_id: friendship_id,
action: FriendshipAction.REMOVE
}
$fetch<GetFriendsResponse[]>('http://localhost:3000/api/v1/user/friends/action', {
method: 'POST',
body: JSON.stringify(actionRequest)
}).then(() => {
handleFriendRequestAction(FriendshipAction.REMOVE, friendship_id)
})
}
</script>

<template>
Expand All @@ -85,7 +104,12 @@ function decline(friendship_id: number) {
<br>
<div class="flex flex-auto flex-row items-center">
<h1 class="py-4 mx-4 text-2xl">Friends:</h1>
<div v-for="item in friends" :key="item.friend_id" class="bg-white p-4 m-4 text-center rounded-lg">{{ item.friend_id }}</div>
<div v-for="item in friends" :key="item.friend_id" class="bg-white p-4 m-4 text-center rounded-lg">
{{ item.friend_id }}
<button class="pl-4 hover:text-red-500" @click="remove(item.friendship_id)">
Remove
</button>
</div>
</div>
<br><br>
</div>
Expand Down
14 changes: 11 additions & 3 deletions server/api/v1/user/friends/action.post.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {z} from "zod";
import {FriendshipAction, GetFriendsResponse} from "~/types/api/user.friends";
import {serverSupabaseServiceRole, serverSupabaseUser} from "#supabase/server";
import type {FriendActionParam} from "~/types/api/user.friends";
import {FriendshipAction} from "~/types/api/user.friends";
import {serverSupabaseServiceRole, serverSupabaseUser} from "#supabase/server";
import type {PostgrestError} from "@supabase/postgrest-js";

const friendActionSchema = z.object({
Expand Down Expand Up @@ -40,11 +40,19 @@ export default defineEventHandler(async (event) => {
error = declineErr;
break;
}
case FriendshipAction.REMOVE: {
const {error: declineErr} = await client.rpc('remove_friend_by_id', param as never);
error = declineErr;
break;
}
}

// Handle errors
if (error) {
setResponseStatus(event, 500);
if (error.code === 'P0001') {
setResponseStatus(event, 400)
} else setResponseStatus(event, 500);

return {error: error.message};
}

Expand Down
1 change: 0 additions & 1 deletion server/api/v1/user/friends/index.delete.ts

This file was deleted.

17 changes: 12 additions & 5 deletions types/api/user.friends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,25 @@ export interface GetFriendsResponse {
friend_id: string,
created_at: string
updated_at: string
status: "pending" | "accepted"
status: FriendshipStatus,
request_type: FriendshipType
}

export enum FriendshipAction {
ACCEPT = "accept",
DECLINE = "decline"
DECLINE = "decline",
REMOVE = "remove"
}

export enum FriendshipStatus {
PENDING= "pending",
ACCEPTED= "accepted",
DECLINED= "declined"
PENDING = "pending",
ACCEPTED = "accepted",
DECLINED = "declined"
}

export enum FriendshipType {
OUTGOING = "outgoing",
INCOMING = "incoming"
}

export interface FriendActionRequest {
Expand Down

0 comments on commit 8db2fea

Please sign in to comment.