websockets implemented

This commit is contained in:
Torsten Schulz
2024-12-04 19:08:26 +01:00
parent d46a51db38
commit 069c97fa90
64 changed files with 2488 additions and 562 deletions

View File

@@ -0,0 +1,208 @@
<template>
<div>
<h2>{{ $t('friends.title') }}</h2>
<div class="tabs-container">
<div class="tab" v-for="(tab, index) in tabs" :key="tab.name" :class="{ active: activeTab === index }"
@click="selectTab(index)">
{{ $t(tab.label) }}
</div>
</div>
<div v-for="(tab, index) in tabs" v-show="activeTab === index" :key="tab.name">
<v-data-table :items="paginatedData(tab.data, tab.pagination.page)" :headers="headers"
:items-per-page="tab.pagination.itemsPerPage" class="elevation-1">
<template v-slot:body="{ items }">
<tr v-for="(item, index) in items" :key="index">
<td :class="'font-color-gender-' + item.user.gender.toLowerCase().replace(' ', '')">
{{ item.user.username }}
</td>
<td>{{ item.user.age }}</td>
<td>{{ $t(`gender.${item.user.gender}`) }}</td>
<td>
<template v-if="tab.name === 'existingFriends'">
<v-btn color="error" @click="endFriendship(item.user.hashedId)">{{ $t('friends.actions.end')
}}</v-btn>
</template>
<template v-if="tab.name === 'pendingFriends'">
<v-btn color="success" @click="acceptFriendship(item.user.hashedId)">{{
$t('friends.actions.accept') }}</v-btn>
<v-btn color="error" @click="rejectFriendship(item.user.hashedId)">{{
$t('friends.actions.reject') }}</v-btn>
</template>
<template v-if="tab.name === 'requestedFriends'">
<v-btn color="warning" @click="withdrawRequest(item.user.hashedId)">{{
$t('friends.actions.withdraw') }}</v-btn>
</template>
<template v-if="tab.name === 'rejectedFriends'">
<v-btn color="success" @click="acceptFriendship(item.user.hashedId)">{{
$t('friends.actions.accept') }}</v-btn>
</template>
</td>
</tr>
</template>
</v-data-table>
<v-pagination v-model="tab.pagination.page"
:length="Math.ceil(tab.data.length / tab.pagination.itemsPerPage)" :total-visible="5"
class="mt-4"></v-pagination>
</div>
</div>
</template>
<script>
import { getFriendships, endFriendship, acceptFriendship, rejectFriendship, withdrawRequest } from "@/api/friendshipApi";
import { mapActions, mapGetters } from 'vuex';
export default {
name: "FriendsView",
data() {
return {
activeTab: 0,
headers: [
{ text: this.$t("friends.headers.name"), value: "name" },
{ text: this.$t("friends.headers.age"), value: "age" },
{ text: this.$t("friends.headers.gender"), value: "gender" },
{ text: this.$t("friends.headers.actions"), value: "actions", sortable: false },
],
tabs: [
{ name: "existingFriends", label: "friends.tabs.existing", data: [], pagination: { page: 1, itemsPerPage: 10 } },
{ name: "pendingFriends", label: "friends.tabs.pending", data: [], pagination: { page: 1, itemsPerPage: 10 } },
{ name: "requestedFriends", label: "friends.tabs.requested", data: [], pagination: { page: 1, itemsPerPage: 10 } },
{ name: "rejectedFriends", label: "friends.tabs.rejected", data: [], pagination: { page: 1, itemsPerPage: 10 } },
],
};
},
computed: {
...mapGetters(['socket', 'user']),
},
methods: {
async fetchFriendships() {
try {
const friendships = await getFriendships(false);
this.distributeFriendships(friendships);
} catch (error) {
console.error("Error fetching friendships:", error);
}
},
distributeFriendships(friendships) {
this.tabs.forEach(tab => (tab.data = []));
friendships.forEach(friendship => {
if (friendship.accepted) {
this.tabs.find(tab => tab.name === "existingFriends").data.push(friendship);
} else if (friendship.denied) {
const tabName = friendship.initiatorId === this.$store.state.user.hashedId
? "requestedFriends"
: "rejectedFriends";
this.tabs.find(tab => tab.name === tabName).data.push(friendship);
} else if (friendship.withdrawn) {
this.tabs.find(tab => tab.name === "requestedFriends").data.push(friendship);
} else {
const tabName = friendship.isInitiator
? "requestedFriends"
: "pendingFriends";
this.tabs.find(tab => tab.name === tabName).data.push(friendship);
}
});
},
selectTab(index) {
this.activeTab = index;
},
paginatedData(data, page) {
const start = (page - 1) * 10;
const end = start + 10;
return data.slice(start, end);
},
async endFriendship(friendUserId) {
try {
await endFriendship(friendUserId);
this.fetchFriendships();
} catch (error) {
console.error("Error ending friendship:", error);
}
},
async acceptFriendship(friendUserId) {
try {
await acceptFriendship(friendUserId);
this.fetchFriendships();
} catch (error) {
console.error("Error accepting friendship:", error);
}
},
async rejectFriendship(friendUserId) {
try {
await rejectFriendship(friendUserId);
this.fetchFriendships();
} catch (error) {
console.error("Error rejecting friendship:", error);
}
},
async withdrawRequest(friendUserId) {
try {
await withdrawRequest(friendUserId);
this.fetchFriendships();
} catch (error) {
console.error("Error withdrawing request:", error);
}
},
setupSocketListener() {
if (this.socket) {
console.log("Setting up friendshipChanged listener");
this.socket.on("friendshipChanged", (data) => {
console.log("Friendship changed:", data);
this.fetchFriendships();
});
} else {
console.error("Socket not initialized");
}
},
},
mounted() {
this.fetchFriendships();
this.setupSocketListener();
},
beforeUnmount() {
if (this.socket) {
this.socket.off("friendshipChanged");
}
},
};
</script>
<style scoped>
.tabs-container {
display: flex;
border-bottom: 1px solid #999;
padding: 5px 0;
}
.tab {
padding: 2px 4px;
text-align: center;
cursor: pointer;
background-color: #fff;
color: #333;
font-weight: bold;
border: 1px solid #999;
transition: background-color 0.3s ease, color 0.3s ease;
}
.tab:not(.active):hover {
background-color: #ddd;
}
.tab.active {
background-color: #F9A22C;
color: #7E471B;
border-color: #F9A22C;
}
.font-color-gender-male {
color: #1E90FF;
}
.font-color-gender-female {
color: #FF69B4;
}
.font-color-gender-nonbinary {
color: #DAA520;
}
</style>

View File

@@ -82,6 +82,7 @@ import apiClient from '@/utils/axios.js';
import Multiselect from 'vue-multiselect';
import FolderItem from '../../components/FolderItem.vue';
import 'vue-multiselect/dist/vue-multiselect.min.css';
import { EventBus } from '@/utils/eventBus.js';
export default {
components: {
@@ -107,6 +108,10 @@ export default {
if (this.folders) {
this.selectFolder(this.folders);
}
EventBus.on('folderCreated', this.loadFolders);
},
beforeUnmount() {
EventBus.off('folderCreated', this.loadFolders);
},
methods: {
async loadFolders() {