Team.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <div class="border border-dividerLight rounded flex flex-1 items-end">
  3. <div class="flex flex-1 items-start">
  4. <div class="p-4">
  5. <label
  6. class="cursor-pointer transition hover:text-secondaryDark"
  7. @click="team.myRole === 'OWNER' ? emit('edit-team') : ''"
  8. >
  9. {{ team.name || $t("state.nothing_found") }}
  10. </label>
  11. <div class="flex -space-x-1 mt-2 overflow-hidden">
  12. <img
  13. v-for="(member, index) in team.members"
  14. :key="`member-${index}`"
  15. v-tippy="{ theme: 'tooltip' }"
  16. :title="member.user.displayName"
  17. :src="member.user.photoURL || undefined"
  18. :alt="member.user.displayName"
  19. class="rounded-full h-5 ring-primary ring-2 w-5 inline-block"
  20. />
  21. </div>
  22. </div>
  23. </div>
  24. <span>
  25. <tippy ref="options" interactive trigger="click" theme="popover" arrow>
  26. <template #trigger>
  27. <ButtonSecondary
  28. v-tippy="{ theme: 'tooltip' }"
  29. :title="$t('action.more')"
  30. svg="more-vertical"
  31. />
  32. </template>
  33. <SmartItem
  34. v-if="team.myRole === 'OWNER'"
  35. svg="edit"
  36. :label="$t('action.edit').toString()"
  37. @click.native="
  38. () => {
  39. emit('edit-team')
  40. $refs.options.tippy().hide()
  41. }
  42. "
  43. />
  44. <SmartItem
  45. v-if="team.myRole === 'OWNER'"
  46. svg="trash-2"
  47. color="red"
  48. :label="$t('action.delete').toString()"
  49. @click.native="
  50. () => {
  51. deleteTeam()
  52. $refs.options.tippy().hide()
  53. }
  54. "
  55. />
  56. <SmartItem
  57. v-if="!(team.myRole === 'OWNER' && team.ownersCount == 1)"
  58. svg="trash"
  59. :label="$t('team.exit').toString()"
  60. @click.native="
  61. () => {
  62. exitTeam()
  63. $refs.options.tippy().hide()
  64. }
  65. "
  66. />
  67. </tippy>
  68. </span>
  69. </div>
  70. </template>
  71. <script setup lang="ts">
  72. import { useContext } from "@nuxtjs/composition-api"
  73. import { pipe } from "fp-ts/function"
  74. import * as TE from "fp-ts/TaskEither"
  75. import {
  76. deleteTeam as backendDeleteTeam,
  77. leaveTeam,
  78. } from "~/helpers/backend/mutations/Team"
  79. import { TeamMemberRole } from "~/helpers/backend/types/TeamMemberRole"
  80. const props = defineProps<{
  81. team: {
  82. name: string
  83. myRole: TeamMemberRole
  84. ownersCount: number
  85. members: Array<{
  86. user: {
  87. displayName: string
  88. photoURL: string | null
  89. }
  90. }>
  91. }
  92. teamID: string
  93. }>()
  94. const emit = defineEmits<{
  95. (e: "edit-team"): void
  96. }>()
  97. const {
  98. app: { i18n },
  99. $toast,
  100. } = useContext()
  101. const t = i18n.t.bind(i18n)
  102. const deleteTeam = () => {
  103. if (!confirm(t("confirm.remove_team").toString())) return
  104. pipe(
  105. backendDeleteTeam(props.teamID),
  106. TE.match(
  107. (err) => {
  108. // TODO: Better errors ? We know the possible errors now
  109. $toast.error(t("error.something_went_wrong").toString(), {
  110. icon: "error_outline",
  111. })
  112. console.error(err)
  113. },
  114. () => {
  115. $toast.success(t("team.deleted").toString(), {
  116. icon: "done",
  117. })
  118. }
  119. )
  120. )() // Tasks (and TEs) are lazy, so call the function returned
  121. }
  122. const exitTeam = () => {
  123. if (!confirm("Are you sure you want to exit this team?")) return
  124. pipe(
  125. leaveTeam(props.teamID),
  126. TE.match(
  127. (err) => {
  128. // TODO: Better errors ?
  129. $toast.error(t("error.something_went_wrong").toString(), {
  130. icon: "error_outline",
  131. })
  132. console.error(err)
  133. },
  134. () => {
  135. $toast.success(t("team.left").toString(), {
  136. icon: "done",
  137. })
  138. }
  139. )
  140. )() // Tasks (and TEs) are lazy, so call the function returned
  141. }
  142. </script>