123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- <template>
- <div
- class="border border-divider rounded flex flex-col flex-1"
- @contextmenu.prevent="!compact ? $refs.options.tippy().show() : null"
- >
- <div
- class="flex flex-1 items-start"
- :class="
- compact
- ? team.myRole === 'OWNER'
- ? 'cursor-pointer hover:bg-primaryDark transition hover:border-dividerDark focus-visible:border-dividerDark'
- : 'cursor-not-allowed bg-primaryLight'
- : ''
- "
- @click="
- compact
- ? team.myRole === 'OWNER'
- ? $emit('invite-team')
- : noPermission()
- : ''
- "
- >
- <div class="p-4">
- <label
- class="font-semibold text-secondaryDark"
- :class="{ 'cursor-pointer': compact && team.myRole === 'OWNER' }"
- >
- {{ team.name || t("state.nothing_found") }}
- </label>
- <div class="flex -space-x-1 mt-2 overflow-hidden">
- <img
- v-for="(member, index) in team.teamMembers"
- :key="`member-${index}`"
- v-tippy="{ theme: 'tooltip' }"
- :title="member.user.displayName"
- :src="member.user.photoURL || undefined"
- :alt="member.user.displayName"
- class="rounded-full h-5 ring-primary ring-2 w-5 inline-block"
- loading="lazy"
- />
- </div>
- </div>
- </div>
- <div v-if="!compact" class="flex flex-shrink-0 items-end justify-between">
- <span>
- <ButtonSecondary
- v-if="team.myRole === 'OWNER'"
- svg="edit"
- class="rounded-none"
- :label="t('action.edit')"
- @click.native="
- () => {
- $emit('edit-team')
- }
- "
- />
- <ButtonSecondary
- v-if="team.myRole === 'OWNER'"
- svg="user-plus"
- class="rounded-none"
- :label="t('team.invite')"
- @click.native="
- () => {
- emit('invite-team')
- }
- "
- />
- </span>
- <span>
- <tippy ref="options" interactive trigger="click" theme="popover" arrow>
- <template #trigger>
- <ButtonSecondary
- v-tippy="{ theme: 'tooltip' }"
- :title="t('action.more')"
- svg="more-vertical"
- />
- </template>
- <SmartItem
- v-if="team.myRole === 'OWNER'"
- svg="edit"
- :label="t('action.edit')"
- @click.native="
- () => {
- $emit('edit-team')
- $refs.options.tippy().hide()
- }
- "
- />
- <SmartItem
- v-if="team.myRole === 'OWNER'"
- svg="trash-2"
- color="red"
- :label="t('action.delete')"
- @click.native="
- () => {
- confirmRemove = true
- $refs.options.tippy().hide()
- }
- "
- />
- <SmartItem
- v-if="!(team.myRole === 'OWNER' && team.ownersCount == 1)"
- svg="trash"
- :label="t('team.exit')"
- @click.native="
- () => {
- confirmExit = true
- $refs.options.tippy().hide()
- }
- "
- />
- </tippy>
- </span>
- </div>
- <SmartConfirmModal
- :show="confirmRemove"
- :title="t('confirm.remove_team')"
- @hide-modal="confirmRemove = false"
- @resolve="deleteTeam()"
- />
- <SmartConfirmModal
- :show="confirmExit"
- :title="t('confirm.exit_team')"
- @hide-modal="confirmExit = false"
- @resolve="exitTeam()"
- />
- </div>
- </template>
- <script setup lang="ts">
- import { ref } from "@nuxtjs/composition-api"
- import { pipe } from "fp-ts/function"
- import * as TE from "fp-ts/TaskEither"
- import { TeamMemberRole } from "~/helpers/backend/graphql"
- import {
- deleteTeam as backendDeleteTeam,
- leaveTeam,
- } from "~/helpers/backend/mutations/Team"
- import { useI18n, useToast } from "~/helpers/utils/composables"
- const t = useI18n()
- const props = defineProps<{
- team: {
- name: string
- myRole: TeamMemberRole
- ownersCount: number
- teamMembers: Array<{
- user: {
- displayName: string
- photoURL: string | null
- }
- }>
- }
- teamID: string
- compact: boolean
- }>()
- const emit = defineEmits<{
- (e: "edit-team"): void
- }>()
- const toast = useToast()
- const confirmRemove = ref(false)
- const confirmExit = ref(false)
- const deleteTeam = () => {
- pipe(
- backendDeleteTeam(props.teamID),
- TE.match(
- (err) => {
- // TODO: Better errors ? We know the possible errors now
- toast.error(`${t("error.something_went_wrong")}`)
- console.error(err)
- },
- () => {
- toast.success(`${t("team.deleted")}`)
- }
- )
- )() // Tasks (and TEs) are lazy, so call the function returned
- }
- const exitTeam = () => {
- pipe(
- leaveTeam(props.teamID),
- TE.match(
- (err) => {
- // TODO: Better errors ?
- toast.error(`${t("error.something_went_wrong")}`)
- console.error(err)
- },
- () => {
- toast.success(`${t("team.left")}`)
- }
- )
- )() // Tasks (and TEs) are lazy, so call the function returned
- }
- const noPermission = () => {
- toast.error(`${t("profile.no_permission")}`)
- }
- </script>
|