Merge pull request 'Implement friends list and refactor components' (#28) from friends-list into main
All checks were successful
ci/woodpecker/push/build-and-publish Pipeline was successful
All checks were successful
ci/woodpecker/push/build-and-publish Pipeline was successful
Reviewed-on: #28 Reviewed-by: Radical <radical@radical.fun> Reviewed-by: SauceyRed <saucey@saucey.red>
This commit is contained in:
commit
1d1cfa0af2
25 changed files with 335 additions and 55 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 username 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>
|
41
components/Me/DirectMessagesSidebar.vue
Normal file
41
components/Me/DirectMessagesSidebar.vue
Normal file
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<div id="middle-left-column">
|
||||
<div id="friend-sidebar">
|
||||
<div>
|
||||
<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}`"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import VerticalSpacer from '~/components/UserInterface/VerticalSpacer.vue';
|
||||
|
||||
const { fetchFriends } = useApi();
|
||||
|
||||
const friends = await fetchFriends()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#middle-left-column {
|
||||
background: var(--optional-channel-list-background);
|
||||
background-color: var(--sidebar-background-color);
|
||||
}
|
||||
|
||||
#friend-sidebar {
|
||||
padding-left: .5em;
|
||||
padding-right: .5em;
|
||||
}
|
||||
</style>
|
58
components/Me/FriendsList.vue
Normal file
58
components/Me/FriendsList.vue
Normal file
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<input id="search-friend-bar" placeholder="search"/>
|
||||
|
||||
<!-- we aren't checking for the "all" variant, since this is the default and fallback one -->
|
||||
|
||||
<p v-if="props.variant === 'online'" style="text-align: left;">Online – 0</p>
|
||||
<p v-else-if="props.variant === 'pending'" style="text-align: left;">Friend Requests – 0</p>
|
||||
<p v-else style="text-align: left;">Friends – {{ friends?.length || 0 }}</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
|
||||
}>();
|
||||
</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>
|
|
@ -10,7 +10,6 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import type { GuildMemberResponse } from '~/types/interfaces';
|
||||
import UserPopup from './UserPopup.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
member: GuildMemberResponse
|
|
@ -17,7 +17,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Button from '~/components/Button.vue';
|
||||
import Button from '~/components/UserInterface/Button.vue';
|
||||
import type { UserResponse } from '~/types/interfaces';
|
||||
|
||||
const { fetchUser } = useAuth();
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Button from '~/components/Button.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import UserPopup from '~/components/User/UserPopup.vue';
|
||||
import Button from '~/components/UserInterface/Button.vue';
|
||||
|
||||
import type { UserResponse } from '~/types/interfaces';
|
||||
|
||||
let newPfpFile: File;
|
||||
|
|
40
components/User/UserEntry.vue
Normal file
40
components/User/UserEntry.vue
Normal file
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<NuxtLink class="user-item" :href="`/me/${user.uuid}`" tabindex="0">
|
||||
<img v-if="props.user.avatar" class="user-avatar" :src="props.user.avatar" :alt="props.user.display_name ?? props.user.username" />
|
||||
<Icon v-else class="user-avatar" name="lucide:user" />
|
||||
<span class="user-display-name">{{ props.user.display_name || props.user.username }}</span>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { UserResponse } from '~/types/interfaces';
|
||||
|
||||
const props = defineProps<{
|
||||
user: UserResponse
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.user-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
gap: .5em;
|
||||
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.user-item:hover {
|
||||
background-color: #00000020
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 2.3em;
|
||||
height: 2.3em;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
|
@ -1,20 +0,0 @@
|
|||
<template>
|
||||
<div id="user-panel">
|
||||
HELLO!!
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { UserResponse } from '~/types/interfaces';
|
||||
|
||||
const props = defineProps<{
|
||||
user: UserResponse,
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#user-panel {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
12
components/UserInterface/VerticalSpacer.vue
Normal file
12
components/UserInterface/VerticalSpacer.vue
Normal file
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<span class="spacer"></span>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.spacer {
|
||||
height: 0.2dvh;
|
||||
display: block;
|
||||
margin: 0.8dvh 0.2dvw;
|
||||
background-color: var(--padding-color);
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue