PendingInvites.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <template>
  2. <div class="border rounded divide-y divide-dividerLight border-divider my-8">
  3. <div v-if="fetching" class="flex items-center justify-center p-4">
  4. <HoppSmartSpinner />
  5. </div>
  6. <div v-else>
  7. <div v-if="team" class="divide-y divide-dividerLight">
  8. <div
  9. v-for="(invitee, index) in pendingInvites"
  10. :key="`invitee-${index}`"
  11. class="flex divide-x divide-dividerLight"
  12. >
  13. <input
  14. v-if="invitee"
  15. class="flex flex-1 px-4 py-2 bg-transparent text-secondaryLight"
  16. placeholder="Email"
  17. :name="'param' + index"
  18. :value="invitee.inviteeEmail"
  19. readonly
  20. />
  21. <input
  22. class="flex flex-1 px-4 py-2 bg-transparent text-secondaryLight"
  23. placeholder="Permissions"
  24. :name="'value' + index"
  25. :value="invitee.inviteeRole"
  26. readonly
  27. />
  28. <div class="flex">
  29. <HoppButtonSecondary
  30. v-tippy="{ theme: 'tooltip' }"
  31. title="Remove"
  32. :icon="IconTrash"
  33. color="red"
  34. :loading="isLoadingIndex === index"
  35. @click="removeInvitee(invitee.id, index)"
  36. />
  37. </div>
  38. </div>
  39. </div>
  40. <div
  41. v-if="team && pendingInvites?.length === 0"
  42. class="flex flex-col items-center justify-center p-4 text-secondaryLight"
  43. >
  44. <span class="text-center"> No pending invites </span>
  45. </div>
  46. <div v-if="!fetching && error" class="flex flex-col items-center p-4">
  47. <icon-lucide-help-circle class="mb-4 svg-icons" />
  48. Something went wrong. Please try again later.
  49. </div>
  50. </div>
  51. </div>
  52. </template>
  53. <script setup lang="ts">
  54. import IconTrash from '~icons/lucide/trash';
  55. import { useMutation, useClientHandle } from '@urql/vue';
  56. import { ref, onMounted } from 'vue';
  57. import {
  58. RevokeTeamInvitationDocument,
  59. TeamInfoDocument,
  60. TeamInfoQuery,
  61. } from '~/helpers/backend/graphql';
  62. import { useToast } from '~/composables/toast';
  63. import { useRoute } from 'vue-router';
  64. const toast = useToast();
  65. // Get details of the team
  66. const fetching = ref(true);
  67. const error = ref(false);
  68. const { client } = useClientHandle();
  69. const route = useRoute();
  70. const team = ref<TeamInfoQuery['admin']['teamInfo'] | undefined>();
  71. const pendingInvites = ref<
  72. TeamInfoQuery['admin']['teamInfo']['teamInvitations'] | undefined
  73. >();
  74. const getTeamInfo = async () => {
  75. fetching.value = true;
  76. const result = await client
  77. .query(TeamInfoDocument, { teamID: route.params.id.toString() })
  78. .toPromise();
  79. if (result.error) {
  80. error.value = true;
  81. return toast.error('Unable to load team details..');
  82. }
  83. if (result.data?.admin.teamInfo) {
  84. team.value = result.data.admin.teamInfo;
  85. pendingInvites.value = team.value.teamInvitations;
  86. }
  87. fetching.value = false;
  88. };
  89. onMounted(async () => await getTeamInfo());
  90. // Remove Invitation
  91. const isLoadingIndex = ref<null | number>(null);
  92. const revokeInvitationMutation = useMutation(RevokeTeamInvitationDocument);
  93. const revokeTeamInvitation = (inviteID: string) =>
  94. revokeInvitationMutation.executeMutation({ inviteID });
  95. const removeInvitee = async (id: string, index: number) => {
  96. isLoadingIndex.value = index;
  97. const result = await revokeTeamInvitation(id);
  98. if (result.error) {
  99. toast.error('Removal of invitee failed!!');
  100. } else {
  101. if (pendingInvites.value) {
  102. pendingInvites.value = pendingInvites.value.filter(
  103. (invite: { id: string }) => {
  104. return invite.id !== id;
  105. }
  106. );
  107. toast.success('Removal of invitee is successfull!!');
  108. }
  109. }
  110. isLoadingIndex.value = null;
  111. };
  112. </script>