ProfilePrivacyDialog.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <q-dialog
  3. ref="dialogRef"
  4. maximized
  5. persistent
  6. transition-hide="slide-right"
  7. transition-show="slide-left"
  8. >
  9. <div class="bg-page full-height column no-shadow">
  10. <div
  11. class="row items-center q-px-md q-pt-md q-pb-sm bg-white shadow-profile bg-surface"
  12. >
  13. <q-btn
  14. v-close-popup
  15. class="header-back-btn"
  16. color="primary"
  17. dense
  18. flat
  19. icon="mdi-chevron-left"
  20. round
  21. />
  22. <q-space />
  23. <span
  24. class="text-subtitle1 text-primary font16 fontbold gradient-diarista"
  25. >
  26. {{ $t("profile.privacy.title") }}
  27. </span>
  28. <q-space />
  29. <div style="width: 32px"></div>
  30. </div>
  31. <div
  32. v-if="loading"
  33. class="col flex flex-center"
  34. >
  35. <q-spinner
  36. color="primary"
  37. size="3em"
  38. />
  39. </div>
  40. <div
  41. v-else-if="blocks.length === 0"
  42. class="col column items-center justify-center q-px-xl q-pb-xl"
  43. >
  44. <q-img
  45. class="q-mb-lg"
  46. fit="contain"
  47. style="width: 220px; height: 220px"
  48. :src="diarinho"
  49. />
  50. <p class="text-center q-mb-xs font16 fontbold text-primary">
  51. {{ $t("profile.privacy.empty_message") }}
  52. </p>
  53. <p class="text-grey-6 text-center q-mb-xl font12 fontregular">
  54. {{ $t("profile.privacy.empty_sub") }}
  55. </p>
  56. </div>
  57. <div
  58. v-else
  59. class="col overflow-auto q-pb-xl"
  60. >
  61. <div class="q-px-md q-mt-md">
  62. <p class="text-primary q-mb-md font16 fontbold gradient-diarista">
  63. {{ $t("profile.privacy.blocked_title") }}
  64. </p>
  65. <div
  66. v-for="block in blocks"
  67. :key="block.id"
  68. class="block-item row items-center no-wrap q-mb-md"
  69. >
  70. <q-avatar
  71. class="flex-shrink-0 q-mr-sm"
  72. size="48px"
  73. >
  74. <span
  75. class="full-width full-height flex flex-center"
  76. style="border-radius: 50%"
  77. :style="avatarStyle(block)"
  78. >
  79. {{ block.provider_name?.slice(0, 2).toUpperCase() ?? "??" }}
  80. </span>
  81. </q-avatar>
  82. <div class="col column no-wrap overflow-hidden">
  83. <span
  84. class="font12 fontbold text-text"
  85. style="line-height: 1.3"
  86. >
  87. {{ block.provider_name }}
  88. </span>
  89. <span
  90. v-if="block.provider_district"
  91. class="text-grey-7 font9 fontbold"
  92. >
  93. {{ block.provider_district }}
  94. </span>
  95. <div
  96. v-if="block.provider_rating"
  97. class="row items-center q-mt-xs"
  98. >
  99. <q-icon
  100. class="q-mr-xs"
  101. color="amber"
  102. name="mdi-star"
  103. size="12px"
  104. />
  105. <span class="text-grey-7 font9 fontregular">
  106. {{ Number(block.provider_rating).toFixed(1) }}
  107. </span>
  108. </div>
  109. </div>
  110. <q-btn
  111. class="flex-shrink-0"
  112. color="primary"
  113. no-caps
  114. padding="4px 12px"
  115. rounded
  116. size="sm"
  117. :label="$t('profile.privacy.unblock_btn')"
  118. :loading="unblockingId === block.id"
  119. @click="unblock(block)"
  120. />
  121. </div>
  122. </div>
  123. </div>
  124. </div>
  125. </q-dialog>
  126. </template>
  127. <script setup>
  128. import diarinho from "src/assets/diarinho_perfil_cliente_favoritos.svg";
  129. import { avatarColorsWithPurple as avatarColors } from "src/helpers/avatarColors";
  130. import {
  131. deleteClientProviderBlock,
  132. getClientProviderBlocks,
  133. } from "src/api/clientProviderBlock";
  134. import { onMounted, ref } from "vue";
  135. import { useDialogPluginComponent } from "quasar";
  136. import { userStore } from "src/stores/user";
  137. defineEmits([...useDialogPluginComponent.emits]);
  138. const { dialogRef } = useDialogPluginComponent();
  139. const store = userStore();
  140. const blocks = ref([]);
  141. const loading = ref(false);
  142. const unblockingId = ref(null);
  143. const avatarStyle = (block) => {
  144. const idx = (block?.provider_id ?? 0) % avatarColors.length;
  145. return avatarColors[idx];
  146. };
  147. const unblock = async (block) => {
  148. unblockingId.value = block.id;
  149. try {
  150. await deleteClientProviderBlock(block.id);
  151. blocks.value = blocks.value.filter((b) => b.id !== block.id);
  152. } finally {
  153. unblockingId.value = null;
  154. }
  155. };
  156. onMounted(async () => {
  157. loading.value = true;
  158. try {
  159. blocks.value = (await getClientProviderBlocks(store.user.client.id)) ?? [];
  160. } finally {
  161. loading.value = false;
  162. }
  163. });
  164. </script>
  165. <style scoped lang="scss">
  166. .shadow-profile {
  167. box-shadow: 0px 1px 8px rgba(0, 0, 0, 0.1);
  168. }
  169. .block-item {
  170. border-radius: 12px;
  171. padding: 12px;
  172. }
  173. .flex-shrink-0 {
  174. flex-shrink: 0;
  175. }
  176. </style>