209 lines
7.9 KiB
Vue
209 lines
7.9 KiB
Vue
<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>
|