ProfileEditDialog.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <template>
  2. <q-dialog ref="dialogRef" persistent maximized transition-show="slide-left" transition-hide="slide-right">
  3. <q-card class="bg-white full-width full-height">
  4. <div class="row items-center q-px-md q-pb-sm bg-white shadow-profile dialog-safe-header">
  5. <q-btn flat round dense icon="mdi-chevron-left" color="primary" @click="onDialogCancel" />
  6. <q-space />
  7. <span class="font16 fontbold gradient-diarista">{{ $t('profile.edit_data') }}</span>
  8. <q-space />
  9. <div style="width: 32px"></div>
  10. </div>
  11. <div v-if="loading" class="flex flex-center q-pa-xl">
  12. <q-spinner color="primary" size="3em" />
  13. </div>
  14. <template v-else>
  15. <q-scroll-area class="col" style="height: calc(100vh - 72px)">
  16. <div class="column items-center q-mt-xl q-mb-md">
  17. <q-avatar size="140px" class="shadow-1" :style="!profilePhoto ? avatarStyle : undefined">
  18. <img v-if="profilePhoto" :src="profilePhoto" style="object-fit:cover;width:100%;height:100%;border-radius:50%" />
  19. <span v-else style="color: #7a154f">{{ form.name ? form.name.slice(0, 2).toUpperCase() : '' }}</span>
  20. </q-avatar>
  21. <q-btn flat no-caps color="grey-6" class="q-mt-sm font12 fontregular" :label="$t('profile.change_photo')" />
  22. </div>
  23. <div class="q-px-xl q-gutter-y-lg">
  24. <div>
  25. <div class="text-grey-8 q-mb-sm font12 fontbold">{{ $t('profile.full_name') }}</div>
  26. <q-input
  27. v-model="form.name"
  28. outlined
  29. dense
  30. input-class="text-text"
  31. :placeholder="$t('profile.placeholder_name')"
  32. />
  33. </div>
  34. <div>
  35. <div class="text-grey-8 q-mb-sm font12 fontbold">{{ $t('profile.email') }}</div>
  36. <q-input
  37. v-model="form.email"
  38. outlined
  39. dense
  40. input-class="text-text"
  41. :placeholder="$t('profile.placeholder_email')"
  42. />
  43. </div>
  44. <div>
  45. <div class="text-grey-8 q-mb-sm font12 fontbold">{{ $t('profile.phone') }}</div>
  46. <q-input
  47. v-model="form.phone"
  48. outlined
  49. dense
  50. input-class="text-text"
  51. mask="(##) #####-####"
  52. unmasked-value
  53. :placeholder="$t('profile.placeholder_phone')"
  54. />
  55. </div>
  56. </div>
  57. <q-space/>
  58. <div class="q-pa-xl q-mt-md">
  59. <q-btn
  60. unelevated
  61. rounded
  62. no-caps
  63. padding="8px 16px"
  64. class="full-width q-py-md"
  65. :label="$t('profile.update')"
  66. :color="hasUpdatedFields ? 'primary' : 'grey-4'"
  67. :disable="!hasUpdatedFields"
  68. :loading="submitting"
  69. @click="submitUpdate"
  70. />
  71. </div>
  72. </q-scroll-area>
  73. </template>
  74. </q-card>
  75. </q-dialog>
  76. </template>
  77. <script setup>
  78. import { ref, onMounted } from 'vue';
  79. import { useDialogPluginComponent } from 'quasar';
  80. import { updateUser } from 'src/api/user';
  81. import { useFormUpdateTracker } from 'src/composables/useFormUpdateTracker';
  82. const avatarStyle = {
  83. background: 'linear-gradient(135deg, #ffd7e8 0%, #ff9acc 100%)',
  84. color: '#7a154f',
  85. };
  86. const profilePhoto = ref(null);
  87. const props = defineProps({
  88. userData: {
  89. type: Object,
  90. default: null
  91. }
  92. });
  93. defineEmits([...useDialogPluginComponent.emits]);
  94. const { dialogRef, onDialogOK, onDialogCancel } = useDialogPluginComponent();
  95. const loading = ref(false);
  96. const submitting = ref(false);
  97. const userId = ref(null);
  98. const { form, hasUpdatedFields, setUpdateFormAsOriginal } = useFormUpdateTracker({
  99. name: '',
  100. email: '',
  101. phone: ''
  102. });
  103. const submitUpdate = async () => {
  104. if (!hasUpdatedFields.value) return;
  105. submitting.value = true;
  106. try {
  107. const data = await updateUser({
  108. name: form.name,
  109. email: form.email,
  110. phone: form.phone
  111. }, userId.value);
  112. console.log(data)
  113. setUpdateFormAsOriginal(data);
  114. onDialogOK(data);
  115. } catch (error) {
  116. console.error('Erro ao atualizar perfil:', error);
  117. } finally {
  118. submitting.value = false;
  119. }
  120. };
  121. onMounted(async () => {
  122. if (props.userData) {
  123. const data = props.userData;
  124. userId.value = data.id;
  125. form.name = data.name || '';
  126. form.email = data.email || '';
  127. form.phone = data.phone || '';
  128. profilePhoto.value = data.profile_photo || null;
  129. setUpdateFormAsOriginal(data);
  130. return;
  131. }
  132. loading.value = true;
  133. });
  134. </script>
  135. <style scoped lang="scss">
  136. :deep(.q-field--outlined .q-field__control) {
  137. border-radius: 8px;
  138. &::before { border: 1px solid #e0e0e0; }
  139. }
  140. </style>