profile.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <template>
  2. <div>
  3. <div class="container">
  4. <div class="p-4">
  5. <div
  6. v-if="currentUser === null"
  7. class="flex flex-col items-center justify-center"
  8. >
  9. <img
  10. :src="`/images/states/${$colorMode.value}/login.svg`"
  11. loading="lazy"
  12. class="inline-flex flex-col object-contain object-center w-24 h-24 my-4"
  13. :alt="`${t('empty.parameters')}`"
  14. />
  15. <p class="text-secondaryLight pb-4 text-center">
  16. {{ t("empty.profile") }}
  17. </p>
  18. <ButtonPrimary
  19. :label="t('auth.login')"
  20. class="mb-4"
  21. @click.native="showLogin = true"
  22. />
  23. </div>
  24. <div v-else class="space-y-8">
  25. <div
  26. class="bg-primaryLight md:h-32 -mb-11 h-24 rounded"
  27. style="background-image: url('/images/cover.svg')"
  28. ></div>
  29. <div class="md:flex-row flex flex-col justify-between px-4 space-y-8">
  30. <div class="flex items-end">
  31. <img
  32. v-if="currentUser.photoURL"
  33. :src="currentUser.photoURL"
  34. class="ring-4 ring-primary w-16 h-16 rounded-lg"
  35. :alt="currentUser.displayName"
  36. />
  37. <SmartIcon v-else name="user" class="svg-icons" />
  38. <div class="ml-4">
  39. <label class="heading">
  40. {{ currentUser.displayName || t("state.nothing_found") }}
  41. </label>
  42. <p class="text-secondaryLight flex items-center">
  43. {{ currentUser.email }}
  44. <SmartIcon
  45. v-if="currentUser.emailVerified"
  46. name="verified"
  47. class="svg-icons ml-2 text-green-500"
  48. />
  49. </p>
  50. </div>
  51. </div>
  52. <div class="flex items-end space-x-2">
  53. <div>
  54. <SmartItem
  55. to="/settings"
  56. svg="settings"
  57. :label="t('profile.app_settings')"
  58. outline
  59. />
  60. </div>
  61. <FirebaseLogout outline />
  62. </div>
  63. </div>
  64. <SmartTabs>
  65. <SmartTab
  66. :id="'sync'"
  67. :label="t('settings.account')"
  68. :selected="true"
  69. >
  70. <section class="p-4">
  71. <h4 class="text-secondaryDark font-semibold">
  72. {{ t("settings.profile") }}
  73. </h4>
  74. <div class="text-secondaryLight mt-1">
  75. {{ t("settings.profile_description") }}
  76. </div>
  77. <div class="py-4">
  78. <label for="displayName">
  79. {{ t("settings.profile_name") }}
  80. </label>
  81. <form
  82. class="md:max-w-sm flex mt-2"
  83. @submit.prevent="updateDisplayName"
  84. >
  85. <input
  86. id="displayName"
  87. v-model="displayName"
  88. class="input"
  89. :placeholder="`${t('settings.profile_name')}`"
  90. type="text"
  91. autocomplete="off"
  92. required
  93. />
  94. <ButtonPrimary
  95. :label="t('action.save')"
  96. class="min-w-16 ml-2"
  97. type="submit"
  98. :loading="updatingDisplayName"
  99. />
  100. </form>
  101. </div>
  102. </section>
  103. <section class="p-4">
  104. <h4 class="text-secondaryDark font-semibold">
  105. {{ t("settings.sync") }}
  106. </h4>
  107. <div class="text-secondaryLight mt-1">
  108. {{ t("settings.sync_description") }}
  109. </div>
  110. <div class="py-4 space-y-4">
  111. <div class="flex items-center">
  112. <SmartToggle
  113. :on="SYNC_COLLECTIONS"
  114. @change="toggleSetting('syncCollections')"
  115. >
  116. {{ t("settings.sync_collections") }}
  117. </SmartToggle>
  118. </div>
  119. <div class="flex items-center">
  120. <SmartToggle
  121. :on="SYNC_ENVIRONMENTS"
  122. @change="toggleSetting('syncEnvironments')"
  123. >
  124. {{ t("settings.sync_environments") }}
  125. </SmartToggle>
  126. </div>
  127. <div class="flex items-center">
  128. <SmartToggle
  129. :on="SYNC_HISTORY"
  130. @change="toggleSetting('syncHistory')"
  131. >
  132. {{ t("settings.sync_history") }}
  133. </SmartToggle>
  134. </div>
  135. </div>
  136. </section>
  137. </SmartTab>
  138. <SmartTab :id="'teams'" :label="t('team.title')">
  139. <AppSection label="teams">
  140. <Teams :modal="false" />
  141. </AppSection>
  142. </SmartTab>
  143. </SmartTabs>
  144. </div>
  145. </div>
  146. <FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
  147. </div>
  148. </div>
  149. </template>
  150. <script setup lang="ts">
  151. import { ref, useMeta, defineComponent } from "@nuxtjs/composition-api"
  152. import { currentUser$, setDisplayName } from "~/helpers/fb/auth"
  153. import { useReadonlyStream, useI18n } from "~/helpers/utils/composables"
  154. import { toggleSetting, useSetting } from "~/newstore/settings"
  155. const t = useI18n()
  156. const showLogin = ref(false)
  157. const SYNC_COLLECTIONS = useSetting("syncCollections")
  158. const SYNC_ENVIRONMENTS = useSetting("syncEnvironments")
  159. const SYNC_HISTORY = useSetting("syncHistory")
  160. const currentUser = useReadonlyStream(currentUser$, null)
  161. const displayName = ref(currentUser$.value?.displayName)
  162. const updatingDisplayName = ref(false)
  163. const updateDisplayName = () => {
  164. updatingDisplayName.value = true
  165. setDisplayName(displayName.value).finally(() => {
  166. updatingDisplayName.value = false
  167. })
  168. }
  169. useMeta({
  170. title: `${t("navigation.profile")} • Hoppscotch`,
  171. })
  172. </script>
  173. <script lang="ts">
  174. export default defineComponent({
  175. head: {},
  176. })
  177. </script>