feat: finish entire friends menu
This commit is contained in:
parent
34976b4f50
commit
0562127e4a
7 changed files with 243 additions and 5 deletions
63
components/Me/AddFriend.vue
Normal file
63
components/Me/AddFriend.vue
Normal file
|
@ -0,0 +1,63 @@
|
|||
<template>
|
||||
<div style="text-align: left;">
|
||||
<h3>Add a Friend</h3>
|
||||
Enter a friend's Gorb ID to send them a friend request.
|
||||
</div>
|
||||
|
||||
<div id="add-friend-search-bar">
|
||||
<input id="add-friend-search-input" ref="inputField"
|
||||
placeholder="blahaj.enjoyer?" maxlength="32" @keypress.enter="sendRequest"/> <!-- REMEMBER TO CHANGE THIS WHEN WE ADD FEDERATION-->
|
||||
<Button id="friend-request-button" :callback="sendRequest" text="Send Friend Request"></Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Button from '../UserInterface/Button.vue';
|
||||
|
||||
const inputField = ref<HTMLInputElement>();
|
||||
const { addFriend } = useApi();
|
||||
|
||||
|
||||
async function sendRequest() {
|
||||
if (inputField.value) {
|
||||
try {
|
||||
await addFriend(inputField.value.value)
|
||||
alert("Friend request sent!")
|
||||
} catch {
|
||||
alert("Request failed :(")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
#add-friend-search-bar {
|
||||
display: flex;
|
||||
|
||||
text-align: left;
|
||||
margin-top: .8em;
|
||||
padding: .3em .3em;
|
||||
|
||||
border-radius: 1em;
|
||||
border: 1px solid var(--accent-color);
|
||||
}
|
||||
|
||||
#add-friend-search-input {
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
|
||||
margin: 0 .2em;
|
||||
|
||||
flex-grow: 1;
|
||||
|
||||
color: inherit;
|
||||
background-color: unset;
|
||||
font-weight: medium;
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
|
||||
#add-friend-search-input:empty:before {
|
||||
content: attr(placeholder);
|
||||
color: gray;
|
||||
}
|
||||
</style>
|
|
@ -5,24 +5,24 @@
|
|||
<h3>Direct Messages</h3>
|
||||
</div>
|
||||
<VerticalSpacer />
|
||||
|
||||
<NuxtLink class="user-item" :href="`/me/friends`" tabindex="0">
|
||||
<Icon class="user-avatar" name="lucide:user" />
|
||||
<span class="user-display-name">Friends</span>
|
||||
</NuxtLink>
|
||||
<VerticalSpacer />
|
||||
|
||||
<div id="direct-message-list">
|
||||
<UserEntry v-for="user of friends" :user="user" :name="user.display_name || user.username"
|
||||
:href="`/me/${user.uuid}`"/>
|
||||
<!-- <Channel v-for="channel of channels" :name="channel.name"
|
||||
:uuid="channel.uuid" :current-uuid="(route.params.channelId as string)"
|
||||
:href="`/servers/${route.params.serverId}/channels/${channel.uuid}`" /> -->
|
||||
:href="`/me/${user.uuid}`"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import VerticalSpacer from './UserInterface/VerticalSpacer.vue';
|
||||
import VerticalSpacer from '~/components/UserInterface/VerticalSpacer.vue';
|
||||
|
||||
|
||||
const { fetchFriends } = useApi();
|
||||
|
61
components/Me/FriendsList.vue
Normal file
61
components/Me/FriendsList.vue
Normal file
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<input id="search-friend-bar" placeholder="search"/>
|
||||
|
||||
<!-- we aren't checking for the #all hash, since this is the default and fallback one -->
|
||||
|
||||
<p v-if="props.variant === '#online'" style="text-align: left;">Online – {{ "N/A" }}</p>
|
||||
<p v-else-if="props.variant === '#pending'" style="text-align: left;">Friend Requests – {{ "N/A" }}</p>
|
||||
<p v-else style="text-align: left;">Friends – {{ friends?.length || "N/A" }}</p>
|
||||
|
||||
<div id="friends-list">
|
||||
<div v-if="props.variant === '#online'">
|
||||
Not Implemented
|
||||
</div>
|
||||
|
||||
<div v-else-if="props.variant === '#pending'">
|
||||
Not Implemented
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<UserEntry v-for="user of friends" :user="user" :name="user.display_name || user.username"
|
||||
:href="`/me/${user.uuid}`"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const { fetchFriends } = useApi();
|
||||
|
||||
const friends = await fetchFriends()
|
||||
|
||||
const props = defineProps<{
|
||||
variant: string
|
||||
}>();
|
||||
|
||||
console.log("props", props.variant)
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#search-friend-bar {
|
||||
text-align: left;
|
||||
margin-top: .8em;
|
||||
padding: .3em .5em;
|
||||
width: 100%;
|
||||
|
||||
border-radius: 1em;
|
||||
border: 1px solid var(--accent-color);
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
color: inherit;
|
||||
background-color: unset;
|
||||
font-weight: medium;
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
|
||||
#search-friend-bar:empty:before {
|
||||
content: attr(placeholder);
|
||||
color: gray;
|
||||
}
|
||||
</style>
|
|
@ -37,6 +37,14 @@ export const useApi = () => {
|
|||
return await fetchWithApi('/me/friends')
|
||||
}
|
||||
|
||||
async function addFriend(username: string): Promise<void> {
|
||||
await fetchWithApi('/me/friends', { method: "POST", body: { username } });
|
||||
}
|
||||
|
||||
async function removeFriend(userId: string): Promise<void> {
|
||||
await fetchWithApi(`/me/friends/${userId}`, { method: "DELETE" });
|
||||
}
|
||||
|
||||
async function fetchMessages(channelId: string, options?: { amount?: number, offset?: number }): Promise<MessageResponse[] | undefined> {
|
||||
return await fetchWithApi(`/channels/${channelId}/messages`, { query: { amount: options?.amount ?? 100, offset: options?.offset ?? 0 } });
|
||||
}
|
||||
|
@ -64,6 +72,8 @@ export const useApi = () => {
|
|||
fetchUsers,
|
||||
fetchUser,
|
||||
fetchFriends,
|
||||
addFriend,
|
||||
removeFriend,
|
||||
fetchMessages,
|
||||
fetchMessage,
|
||||
fetchInstanceStats,
|
||||
|
|
20
pages/me/[userId].vue
Normal file
20
pages/me/[userId].vue
Normal file
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<NuxtLayout name="client">
|
||||
<DirectMessagesSidebar />
|
||||
<MessageArea channel-url="channels/01970e8c-a09c-76a0-9c98-80a43364bea7"/>
|
||||
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import DirectMessagesSidebar from '~/components/Me/DirectMessagesSidebar.vue';
|
||||
|
||||
definePageMeta({
|
||||
layout: "client"
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
82
pages/me/friends.vue
Normal file
82
pages/me/friends.vue
Normal file
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<NuxtLayout name="client">
|
||||
<DirectMessagesSidebar />
|
||||
<div id="friends-page-content">
|
||||
<div id="navigation-bar">
|
||||
<NuxtLink class="friends-sub-page-button" @click.prevent="updateHash('all')">All Friends</NuxtLink>
|
||||
<NuxtLink class="friends-sub-page-button" @click.prevent="updateHash('online')">Online</NuxtLink>
|
||||
<NuxtLink class="friends-sub-page-button" @click.prevent="updateHash('pending')">Pending</NuxtLink>
|
||||
<NuxtLink class="friends-sub-page-button friend-primary-button" @click.prevent="updateHash('addfriend')">Add Friend</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<AddFriend v-if="windowHash == '#addfriend'"></AddFriend>
|
||||
<FriendsList v-else :variant="windowHash"></FriendsList>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import AddFriend from '~/components/Me/AddFriend.vue';
|
||||
import DirectMessagesSidebar from '~/components/Me/DirectMessagesSidebar.vue';
|
||||
import FriendsList from '~/components/Me/FriendsList.vue';
|
||||
|
||||
let windowHash = ref(window.location.hash)
|
||||
|
||||
|
||||
function updateHash(newHash: string) {
|
||||
window.location.hash = newHash
|
||||
windowHash.value = `#${newHash}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#friends-page-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
flex-grow: 1;
|
||||
|
||||
margin: .75em;
|
||||
}
|
||||
|
||||
#navigation-bar {
|
||||
display: flex;
|
||||
align-items: left;
|
||||
text-align: left;
|
||||
flex-direction: row;
|
||||
|
||||
gap: .5em;
|
||||
}
|
||||
|
||||
.friends-sub-page-button {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
font-weight: medium;
|
||||
|
||||
padding: 0.2em .5em;
|
||||
|
||||
flex-shrink: 0;
|
||||
border-radius: 1em;
|
||||
background-color: var(--accent-color);
|
||||
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
transition: background-color 300ms;
|
||||
}
|
||||
.friends-sub-page-button:hover {
|
||||
background-color: var(--accent-highlighted-color);
|
||||
}
|
||||
|
||||
.friend-primary-button {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
.friend-primary-button:hover {
|
||||
background-color: var(--primary-highlighted-color);
|
||||
}
|
||||
</style>
|
|
@ -5,6 +5,8 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import DirectMessagesSidebar from '~/components/Me/DirectMessagesSidebar.vue';
|
||||
|
||||
|
||||
definePageMeta({
|
||||
layout: "client"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue