Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/friend requests #25

Merged
merged 27 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9b07ba6
added working playlist view
synan798 Dec 8, 2024
e176918
added scroll effect for long names
synan798 Dec 8, 2024
dd07a89
fixed sizing for long text
synan798 Dec 9, 2024
4f9a03b
resized PlaylistsBoxes and added 'Add Playlists' button
synan798 Dec 10, 2024
f2f713c
added value for friend requests
synan798 Dec 10, 2024
d03570d
added box for incoming friend requests
synan798 Dec 10, 2024
15220ac
added working friend request by name
synan798 Dec 10, 2024
105ee88
added error field
synan798 Dec 10, 2024
b9c6124
added modal for accepting friend requests
synan798 Dec 11, 2024
e6d9c43
added friend removal functionality
synan798 Dec 11, 2024
45fce37
fixed condition for opening modal
synan798 Dec 11, 2024
dc3d0b0
fixed size of content
synan798 Dec 11, 2024
6f57df3
added automatic refresh on action
synan798 Dec 11, 2024
aba96c8
added cancel of sent request
synan798 Dec 11, 2024
9050e6f
fixed vue warning
synan798 Dec 11, 2024
93cec65
fixed ESLint warnings
synan798 Dec 11, 2024
e6ff093
added modal for sending friend requests
synan798 Dec 12, 2024
d75798c
fixed text moving with the user boxes
synan798 Dec 12, 2024
833e423
removed unnessacary code
synan798 Dec 12, 2024
6ab6fc6
fixed userbox margin
synan798 Dec 13, 2024
8ff3496
changed styling of modal
synan798 Dec 13, 2024
68da8d6
Merge branch 'feat/playlist-view' into feat/friend-requests
synan798 Dec 13, 2024
e24bae8
add small Add additional add friend button
Likqez Dec 13, 2024
ac75051
fixed non-plural naming in UsersView
Likqez Dec 15, 2024
cdc6b35
fix(layout): removed white borders of content
Likqez Dec 15, 2024
390ebce
fixed z-index for usermodal
synan798 Dec 15, 2024
6eb3876
Merge branch 'feat/friend-requests' of https://github.com/BeatBuzzer/…
synan798 Dec 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions components/UsersView.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type {GetFriendsResponse} from "@/types/api/user.friends";
import {type GetFriendsResponse, FriendshipStatus} from "@/types/api/user.friends";
import {UserViewType} from "@/types/components/users.view";
import type {GetUserResponse} from "@/types/api/users";

Expand All @@ -15,24 +15,30 @@ const props = defineProps({
}
});

const emit = defineEmits(['refresh']);

const friendshipId = ref(0);
const friendshipStatus = ref(FriendshipStatus.ACCEPTED);

const default_avatar = ref('https://t4.ftcdn.net/jpg/05/49/98/39/360_F_549983970_bRCkYfk0P6PP5fKbMhZMIb07mCJ6esXL.jpg');

// Computed Classes
const containerClasses = computed(() => {
const baseClasses = 'w-full bg-gray-200 px-3 pb-1 mt-auto rounded-3xl mb-3';
if (props.viewType === UserViewType.USERTURN) return `${baseClasses} h-full overflow-y-hidden overflow-x-auto flex-grow-0`;
if (props.viewType === UserViewType.OPPONENTTURN || props.viewType === UserViewType.FRIENDS) return `${baseClasses} overflow-y-hidden`;
return '';
if (props.viewType === UserViewType.USERTURN) return `${baseClasses} h-full overflow-y-hidden overflow-x-hidden flex-grow-0`;
else return `${baseClasses} overflow-y-hidden`;
});

const userBoxContainerClasses = computed(() =>
props.viewType === UserViewType.USERTURN
? 'flex flex-col space-y-1 md:space-y-3 h-full overflow-y-auto'
: 'flex gap-1 md:gap-3 mt-6 md:mt-9'
: 'flex gap-1 md:gap-3 overflow-x-auto'
);


function isGetFriendsResponse(user: GetFriendsResponse | GetUserResponse): user is GetFriendsResponse {
friendshipId.value = user.friendship_id;
friendshipStatus.value = user.status;
return 'friend_id' in user;
}

Expand All @@ -59,20 +65,26 @@ const mappedUsers: Array<GetUserResponse> = computed(() => {
<div
:class="[
containerClasses,
((viewType === UserViewType.FRIENDS || viewType === UserViewType.OPPONENTTURN) && users.length > 3) ? 'pr-0' : ''
((viewType != UserViewType.USERTURN) && users.length > 3) ? 'pr-0' : ''
]"
>
<!-- Fixed Conditional Header -->
<div class="mb-1 text-xs md:text-base bg-gray-200 mt-2">
<p v-if="viewType === UserViewType.USERTURN">
Your Turn
</p>
<p v-else-if="viewType === UserViewType.OPPONENTTURN" class="fixed">
<p v-else-if="viewType === UserViewType.OPPONENTTURN">
Opponent's Turn
</p>
<p v-else-if="viewType === UserViewType.FRIENDS" class="fixed">
<p v-else-if="viewType === UserViewType.FRIENDS">
Friends
</p>
<p v-else-if="viewType === UserViewType.REQUESTS">
Friend Requests
</p>
<p v-else-if="viewType === UserViewType.SENTREQUESTS">
Sent Friend Requests
</p>
</div>

<!-- Scrollable User Boxes -->
Expand All @@ -87,17 +99,23 @@ const mappedUsers: Array<GetUserResponse> = computed(() => {
:name="user.username"
:user-turn="viewType === UserViewType.USERTURN"
:class="[
(viewType === UserViewType.FRIENDS || viewType === UserViewType.OPPONENTTURN)
(viewType != UserViewType.USERTURN)
? users.length === 3 ? 'w-1/3'
: users.length === 2 ? 'w-1/2'
: 'w-full'
: ''
]"
:style="(viewType === UserViewType.FRIENDS || viewType === UserViewType.OPPONENTTURN)
:style="(viewType != UserViewType.USERTURN)
? users.length > 3
? { width: 'calc(33.33% - .98rem)', flexShrink: 0 }
: {}
: {}"
:friend-request="viewType === UserViewType.REQUESTS"
:friendship-id="friendshipId"
:friends-status="friendshipStatus"
:friend-id="user.id"
:view-type="props.viewType"
@refresh="emit('refresh');"
/>
<!-- Placeholder for scrolling -->
<div v-if="users.length > 3" class="px-1 py-4"/>
Expand Down
108 changes: 67 additions & 41 deletions components/home/Users/UserBox.vue
Original file line number Diff line number Diff line change
@@ -1,52 +1,78 @@
<script setup lang="ts">
import { ref } from 'vue';
import { FriendshipStatus } from '@/types/api/user.friends';
import { UserViewType } from '@/types/components/users.view';

const props = defineProps({
profilePicture: {
type: String,
default: 'https://t4.ftcdn.net/jpg/05/49/98/39/360_F_549983970_bRCkYfk0P6PP5fKbMhZMIb07mCJ6esXL.jpg'
},
name: {
type: String,
default: 'User'
},
userTurn: {
type: Boolean,
default: false
},
friendRequest: {
type: Boolean,
default: false
},
friendshipId: {
type: Number,
default: 0
},
friendsStatus: {
type: String,
default: FriendshipStatus.PENDING
},
friendId: {
type: String,
required: true
},
viewType: {
type: Number,
required: true,
},
});

const emit = defineEmits(['refresh']);

const showModal = ref(false);

const props = defineProps({
profilePicture: {
type: String,
default: 'https://t4.ftcdn.net/jpg/05/49/98/39/360_F_549983970_bRCkYfk0P6PP5fKbMhZMIb07mCJ6esXL.jpg'
},
name: {
type: String,
default: 'User'
},
userTurn: {
type: Boolean,
default: false
}
});
</script>

<template>
<div
<div>
<div
:class="[
'bg-blue-600 rounded-3xl px-3 w-full',
props.userTurn
? 'flex items-center'
: 'flex flex-col items-center justify-center mb-3 py-2'
]"
>
'bg-blue-600 rounded-3xl px-3 w-full hover:bg-sky-700',
props.userTurn
? 'flex items-center'
: 'flex flex-col items-center justify-center mb-3 py-2'
]"
@click="showModal = true">
<!-- Profile Picture -->
<NuxtImg
:class="[
'rounded-full',
'w-10 h-10 sm:w-12 sm:h-12 md:w-14 md:h-14',
props.userTurn ? 'mr-3' : 'mb-0'
]"
:src="props.profilePicture.toString()"
:alt="props.name"
/>

<NuxtImg :class="[

Check warning on line 58 in components/home/Users/UserBox.vue

View workflow job for this annotation

GitHub Actions / eslint

Expected a linebreak before this attribute

Check warning on line 58 in components/home/Users/UserBox.vue

View workflow job for this annotation

GitHub Actions / eslint

Expected a linebreak before this attribute

Check warning on line 58 in components/home/Users/UserBox.vue

View workflow job for this annotation

GitHub Actions / eslint

Expected a linebreak before this attribute
'rounded-full',
'w-10 h-10 sm:w-12 sm:h-12 md:w-14 md:h-14',
props.userTurn ? 'mr-3' : 'mb-0'
]" :src="props.profilePicture.toString()" :alt="props.name" />

<!-- User Name -->
<p class="text-white text-sm sm:text-base md:text-lg" v-text="props.name"/>
<p class="text-white text-sm sm:text-base md:text-lg" v-text="props.name" />

<!-- Play Button -->
<button
v-if="props.userTurn"
class="ml-auto p-2 sm:p-3 md:p-4 lg:p-5"
@click="console.log(props.name)"
>
<Icon name="mdi:play" class="w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12 lg:w-14 lg:h-14 text-white"/>
<button v-if="props.userTurn" class="ml-auto p-2 sm:p-3 md:p-4 lg:p-5" @click="console.log(props.name)">
<Icon name="mdi:play" class="w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12 lg:w-14 lg:h-14 text-white" />
</button>
</div>
</template>

<ProfileUserModal
v-if="viewType === UserViewType.FRIENDS || viewType === UserViewType.REQUESTS || viewType === UserViewType.SENTREQUESTS"
v-show="showModal" :profile-picture="props.profilePicture" :name="props.name" :friendship-id="props.friendshipId"
:friends-status="props.friendsStatus" :friend-id="props.friendId" :view-type="props.viewType"
@close-modal="showModal = false" @refresh="emit('refresh')" />
</div>
</template>
68 changes: 68 additions & 0 deletions components/playlists/PlaylistBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<script setup lang="ts">

const props = defineProps({
cover: {
type: Object as () => URL,
default: new URL('https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/eb777e7a-7d3c-487e-865a-fc83920564a1/d7kpm65-437b2b46-06cd-4a86-9041-cc8c3737c6f0.jpg/v1/fit/w_800,h_800,q_70,strp/no_album_art__no_cover___placeholder_picture_by_cmdrobot_d7kpm65-414w-2x.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9ODAwIiwicGF0aCI6IlwvZlwvZWI3NzdlN2EtN2QzYy00ODdlLTg2NWEtZmM4MzkyMDU2NGExXC9kN2twbTY1LTQzN2IyYjQ2LTA2Y2QtNGE4Ni05MDQxLWNjOGMzNzM3YzZmMC5qcGciLCJ3aWR0aCI6Ijw9ODAwIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.8yjX5CrFjxVH06LB59TpJLu6doZb0wz8fGQq4tM64mg')
},
name: {
type: String,
default: 'Playlist',
required: true
},
controlElement: {
type: String,
default: null
}
});
</script>

<template>
<div
:class="[
'bg-blue-600 rounded-3xl p-3 mr-3 mb-3 inline-block w-24 md:w-28'
]"
>
<!-- Playlist Cover -->
<div class="flex flex-col items-center justify-center">
<Icon
v-if="controlElement" :name="props.controlElement" :class="[
'w-16 h-16 sm:w-18 sm:h-18 md:w-20 md:h-20 rounded-2xl text-white'
]"/>
<NuxtImg
v-else
:class="[
'w-16 h-16 sm:w-18 sm:h-18 md:w-20 md:h-20 rounded-2xl'
]"
:src="props.cover.toString()"
:alt="props.name"
/>
</div>

<!-- Horizontally Scrolling Text -->
<div class="overflow-hidden">
<p :class="['text-center text-sm md:text-base', props.name.length > 12 ? 'scrolling-text' : '']">{{ props.name }}</p>
</div>
</div>
</template>

<style scoped>
.scrolling-text {
display: inline-block;
animation: scrollText 5s linear infinite;
white-space: nowrap;
}

/* Scroll animation keyframe */
@keyframes scrollText {
0% {
transform: translateX(0%); /* Start at beginning */
}
100% {
transform: translateX(-100%); /* Scroll completely to the left */
}
}
</style>



61 changes: 61 additions & 0 deletions components/playlists/PlaylistView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script setup lang="ts">
import type { GetPlaylistResponse } from "@/types/api/playlists"

const playlists = ref()

const session = useSupabaseSession()

onMounted(async () => {
if (session.value) {
await getPlaylists()
}
})

async function getPlaylists() {
$fetch<GetPlaylistResponse[]>('http://localhost:3000/api/v1/playlist')
.then((data) => {
playlists.value = [...data]
});
}

// Computed Classes
const containerClasses = computed(() => {
const baseClasses = 'w-full bg-gray-200 px-3 pb-1 mt-auto rounded-3xl mb-3';
return `${baseClasses}`;
});


function addPlaylist() {
const newFriend = {
friend_username: "sfsdf",
}
playlists.value.push(newFriend)
}

</script>

<template>
<div :class="[containerClasses]">
<!-- Fixed Header -->
<div class="mb-1 text-xs md:text-base mt-2 pt-2">
<p>Genre</p>
</div>

<!-- Scrollable Playlist Boxes with constrained height -->
<div class="overflow-y-auto h-[calc(100%-5rem)]"> <!-- Adjust height based on parent header -->
<PlaylistsPlaylistBox
v-for="item in playlists"
:key="item.id"
:name="item.name"
v-bind="item.cover ? { cover: item.cover } : {}"
/>
<button
@click="addPlaylist"
>
<PlaylistsPlaylistBox name="Add Playlist" control-element="mdi:plus"/>
</button>
</div>

</div>
</template>

Loading
Loading