198 lines
6.2 KiB
Vue
198 lines
6.2 KiB
Vue
<template>
|
|
<div v-if="user.team" class="grid w-full grid-cols-12 gap-6">
|
|
<UModal v-model="isInviteModalOpen">
|
|
<UCard>
|
|
<template #header>
|
|
<h1 class="text-lg font-bold">Invite User</h1>
|
|
</template>
|
|
<div class="flex flex-col items-center divide-y divide-gray-700">
|
|
<div v-for="newUser in users" :key="newUser._id" class="flex w-full max-w-sm py-2">
|
|
<span class="mr-auto">
|
|
{{ newUser.username }}
|
|
</span>
|
|
<span v-if="newUser.team" class="text-gray-500">Already in Team</span>
|
|
<span v-if="!newUser.team && newUser.teamInvites.includes(team._id)" class="text-gray-500">Already invited</span>
|
|
<UButton v-if="!newUser.team && !newUser.teamInvites.includes(team._id)" :disabled="disableButtons" @click="inviteUser(newUser)">Invite</UButton>
|
|
</div>
|
|
</div>
|
|
<template #footer>
|
|
<UButton :disabled="disableButtons" @click="isInviteModalOpen = false">OK</UButton>
|
|
</template>
|
|
</UCard>
|
|
</UModal>
|
|
<UModal v-model="editModal.open">
|
|
<UCard>
|
|
<template #header>
|
|
<h1 class="text-lg font-bold">Edit Team</h1>
|
|
</template>
|
|
<form class="flex flex-col gap-y-5">
|
|
<UFormGroup name="name" label="Name" :error="teamNameError">
|
|
<UInput v-model="editModal.name" placeholder=" " />
|
|
</UFormGroup>
|
|
<UFormGroup name="color" label="Color" :error="teamColorError">
|
|
<div class="flex">
|
|
<input v-model="editModal.color" type="color" class="mr-2">
|
|
<UInput v-model="editModal.color" placeholder=" " class="w-full" />
|
|
</div>
|
|
</UFormGroup>
|
|
</form>
|
|
<template #footer>
|
|
<UButton :disabled="disableButtons" @click="submitEditTeam">Edit Team</UButton>
|
|
</template>
|
|
</UCard>
|
|
</UModal>
|
|
<div class="col-span-6 h-min rounded-lg border border-gray-700 bg-gray-800 p-5">
|
|
<h3 class="mb-2 text-xl font-bold">
|
|
Team Information
|
|
</h3>
|
|
<ul>
|
|
<li>Name: {{ user.team.name }}</li>
|
|
<li class="relative">
|
|
Color: <span :style="{ 'text-decoration-color': user.team.color }" class="underline underline-offset-4">{{ user.team.color }}</span>
|
|
</li>
|
|
</ul>
|
|
<div class="mt-5 space-x-3">
|
|
<UButton @click="openModal">Edit Team</UButton>
|
|
<UButton color="red" variant="outline" @click="leaveTeam">Leave Team</UButton>
|
|
</div>
|
|
</div>
|
|
<div v-if="team" class="col-span-6 rounded-lg border border-gray-700 bg-gray-800 p-5">
|
|
<h3 class="mb-2 text-xl font-bold">
|
|
Team Members
|
|
</h3>
|
|
<ul class="divide-y divide-gray-700">
|
|
<li v-for="member in team.members" :key="member._id" class="flex items-center py-3 text-lg">
|
|
<UAvatarGroup size="sm" class="mr-3">
|
|
<UAvatar :src="discordAvatarUrl(member)" alt="Discord Avatar" placeholder="DC" />
|
|
<UAvatar v-if="minecraftAvatarUrl(member)" :src="minecraftAvatarUrl(member)" alt="Minecraft Avatar" placeholder="MC" />
|
|
</UAvatarGroup>
|
|
{{ member.username }}
|
|
</li>
|
|
</ul>
|
|
<div class="my-2 rounded border-2 border-dashed border-gray-500 px-5 py-2 text-center font-bold hover:cursor-pointer hover:bg-gray-700" @click="isInviteModalOpen = true">Invite User</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
const disableButtons = ref(false)
|
|
|
|
const user = useState<IUser>('user')
|
|
const { data: team }: { data: any } = useFetch('/api/teams/@current')
|
|
const { data: users }: { data: any } = useFetch('/api/users')
|
|
|
|
const isInviteModalOpen = ref(false)
|
|
const editModal = ref({
|
|
open: false,
|
|
name: '',
|
|
color: ''
|
|
})
|
|
|
|
const teamNameError = computed(() => {
|
|
if (!editModal.value.name) {
|
|
return ''
|
|
}
|
|
if (!/^[a-zA-Z0-9]+$/.test(editModal.value.name)) {
|
|
return 'Team name must only include alfanumeric characters'
|
|
}
|
|
if (editModal.value.name.length < 3 || editModal.value.name.length > 16) {
|
|
return 'Team name must be between 3 and 16 characters'
|
|
}
|
|
})
|
|
|
|
const teamColorError = computed(() => {
|
|
if (!editModal.value.color) {
|
|
return ''
|
|
}
|
|
if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(editModal.value.color)) {
|
|
return 'Team color is not a valid hex code'
|
|
}
|
|
})
|
|
|
|
const discordAvatarUrl = (member: IUser) => {
|
|
return 'https://cdn.discordapp.com/avatars/' + member.discord.id + '/' + member.discord.avatarHash + '.png'
|
|
}
|
|
|
|
const minecraftAvatarUrl = (member: IUser) => {
|
|
if (!member.minecraft) {
|
|
return ''
|
|
}
|
|
return 'https://api.mineatar.io/face/' + member.minecraft.uuid + '?scale=16'
|
|
}
|
|
|
|
const leaveTeam = async () => {
|
|
disableButtons.value = true
|
|
|
|
try {
|
|
await $fetch('/api/teams/@current/members/@me', {
|
|
method: 'DELETE'
|
|
})
|
|
|
|
user.value.team = undefined
|
|
|
|
useToast().add({ title: 'Successfully left team', color: 'green' })
|
|
} catch (e: any) {
|
|
console.error(e)
|
|
|
|
useToast().add({ title: e.statusMessage, color: 'red' })
|
|
}
|
|
|
|
disableButtons.value = false
|
|
}
|
|
|
|
const inviteUser = async (newUser: IUser) => {
|
|
disableButtons.value = true
|
|
|
|
try {
|
|
await $fetch(`/api/users/${newUser._id}/teamInvites`, {
|
|
method: 'POST',
|
|
body: {
|
|
teamId: team.value._id
|
|
}
|
|
})
|
|
|
|
newUser.teamInvites.push(team.value._id)
|
|
|
|
useToast().add({ title: 'Successfully invited user to team', color: 'green' })
|
|
} catch (e: any) {
|
|
console.error(e)
|
|
|
|
useToast().add({ title: e.statusMessage, color: 'red' })
|
|
}
|
|
|
|
disableButtons.value = false
|
|
}
|
|
|
|
const openModal = () => {
|
|
editModal.value.name = team.value.name
|
|
editModal.value.color = team.value.color
|
|
editModal.value.open = true
|
|
}
|
|
|
|
const submitEditTeam = async () => {
|
|
disableButtons.value = true
|
|
|
|
try {
|
|
const response: any = await $fetch('/api/teams/@current', {
|
|
method: 'PUT',
|
|
body: {
|
|
teamName: editModal.value.name,
|
|
teamColor: editModal.value.color
|
|
}
|
|
})
|
|
|
|
user.value.team = response
|
|
|
|
useToast().add({ title: 'Successfully edited team', color: 'green' })
|
|
} catch (e: any) {
|
|
console.error(e)
|
|
|
|
useToast().add({ title: e.statusMessage, color: 'red' })
|
|
}
|
|
|
|
editModal.value = { open: false, name: '', color: '' }
|
|
|
|
disableButtons.value = false
|
|
}
|
|
</script>
|