LoginStepThreePanel.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <template>
  2. <q-card-section class="no-padding">
  3. <div>
  4. <div class="text-text">
  5. <span class="font14 fontbold">{{ $t('auth.full_name') }}</span>
  6. </div>
  7. <q-input
  8. v-model="form.name"
  9. no-error-icon
  10. outlined
  11. rounded
  12. bg-color="surface"
  13. class="q-mt-sm q-mb-md"
  14. input-class="text-text"
  15. :placeholder="$t('auth.full_name')"
  16. hide-bottom-space
  17. :rules="[inputRules.required]"
  18. lazy-rules
  19. />
  20. </div>
  21. <div>
  22. <div class="text-text">
  23. <span class="font14 fontbold">{{ $t('common.terms.cpf') }}</span>
  24. </div>
  25. <q-input
  26. v-model="form.document"
  27. no-error-icon
  28. outlined
  29. rounded
  30. bg-color="surface"
  31. class="q-mt-sm q-mb-md"
  32. input-class="text-text"
  33. placeholder="000.000.000-00"
  34. hide-bottom-space
  35. :rules="[inputRules.required, inputRules.cpf]"
  36. lazy-rules
  37. mask="###.###.###-##"
  38. />
  39. </div>
  40. <div>
  41. <div class="text-text">
  42. <span class="font14 fontbold">{{ $t('common.terms.cep') }}</span>
  43. </div>
  44. <q-input
  45. v-model="form.zip_code"
  46. no-error-icon
  47. outlined
  48. rounded
  49. bg-color="surface"
  50. class="q-mt-sm q-mb-md"
  51. input-class="text-text"
  52. placeholder="00000-000"
  53. hide-bottom-space
  54. :rules="[inputRules.required, inputRules.cep]"
  55. lazy-rules
  56. mask="#####-###"
  57. :loading="loadingCep"
  58. @update:model-value="onCepChange"
  59. />
  60. </div>
  61. <div>
  62. <div class="text-text">
  63. <span class="font14 fontbold">{{ $t('common.terms.address') }}</span>
  64. </div>
  65. <q-input
  66. v-model="form.address"
  67. no-error-icon
  68. outlined
  69. rounded
  70. bg-color="surface"
  71. class="q-mt-sm q-mb-md"
  72. input-class="text-text"
  73. :placeholder="`${$t('common.terms.address')}...`"
  74. hide-bottom-space
  75. :rules="[inputRules.required]"
  76. lazy-rules
  77. readonly
  78. />
  79. </div>
  80. <div class="row q-col-gutter-sm">
  81. <div class="col-4">
  82. <div class="text-text">
  83. <span class="font14 fontbold">{{ $t('common.terms.address_number') }}</span>
  84. </div>
  85. <q-input
  86. v-model="form.number"
  87. no-error-icon
  88. outlined
  89. rounded
  90. bg-color="surface"
  91. class="q-mt-sm q-mb-md"
  92. input-class="text-text"
  93. placeholder="0000"
  94. hide-bottom-space
  95. :rules="[inputRules.required]"
  96. lazy-rules
  97. />
  98. </div>
  99. <div class="col-8">
  100. <div class="text-text">
  101. <span class="font14 fontbold">{{ $t('common.terms.district') }}</span>
  102. </div>
  103. <q-input
  104. v-model="form.district"
  105. no-error-icon
  106. outlined
  107. rounded
  108. bg-color="surface"
  109. class="q-mt-sm q-mb-md"
  110. input-class="text-text"
  111. :placeholder="`${$t('common.terms.district')}...`"
  112. hide-bottom-space
  113. readonly
  114. />
  115. </div>
  116. </div>
  117. <div class="row q-col-gutter-sm">
  118. <div class="col-8">
  119. <div class="text-text">
  120. <span class="font14 fontbold">{{ $t('common.terms.city') }}</span>
  121. </div>
  122. <q-input
  123. v-model="form.city"
  124. no-error-icon
  125. outlined
  126. rounded
  127. bg-color="surface"
  128. class="q-mt-sm q-mb-md"
  129. input-class="text-text"
  130. readonly
  131. />
  132. </div>
  133. <div class="col-4">
  134. <div class="text-text">
  135. <span class="font14 fontbold">{{ $t('common.terms.state') }}</span>
  136. </div>
  137. <q-input
  138. v-model="form.state"
  139. no-error-icon
  140. outlined
  141. rounded
  142. bg-color="surface"
  143. class="q-mt-sm q-mb-md"
  144. input-class="text-text"
  145. hide-bottom-space
  146. readonly
  147. />
  148. </div>
  149. </div>
  150. <div>
  151. <q-checkbox
  152. v-model="form.no_complement"
  153. :label="$t('auth.no_complement')"
  154. color="primary"
  155. keep-color
  156. class="q-mb-md text-text font14 fontbold"
  157. />
  158. </div>
  159. <div>
  160. <template v-if="!form.no_complement">
  161. <div class="text-text">
  162. <span class="font14 fontbold">{{ $t('common.terms.complement') }}</span>
  163. </div>
  164. <q-input
  165. v-model="form.complement"
  166. no-error-icon
  167. outlined
  168. rounded
  169. bg-color="surface"
  170. class="q-mt-sm q-mb-md"
  171. input-class="text-text"
  172. :placeholder="`${$t('common.ui.misc.example')}: Apartamento, Conjunto, Casa`"
  173. hide-bottom-space
  174. :rules="!form.no_complement ? [inputRules.required] : []"
  175. lazy-rules
  176. />
  177. </template>
  178. </div>
  179. <div>
  180. <div class="text-text">
  181. <span class="font14 fontbold">{{ $t('auth.address_nickname') }}</span>
  182. </div>
  183. <q-input
  184. v-model="form.nickname"
  185. no-error-icon
  186. outlined
  187. rounded
  188. bg-color="surface"
  189. class="q-mt-sm q-mb-md"
  190. input-class="text-text"
  191. :placeholder="`${$t('common.ui.misc.example')}: Casa`"
  192. hide-bottom-space
  193. lazy-rules
  194. />
  195. </div>
  196. <div>
  197. <div class="text-text">
  198. <span class="font14 fontbold">{{ $t('auth.address_instructions') }}</span>
  199. </div>
  200. <q-input
  201. v-model="form.instructions"
  202. no-error-icon
  203. outlined
  204. rounded
  205. bg-color="surface"
  206. class="q-mt-sm q-mb-md"
  207. input-class="text-text"
  208. type="textarea"
  209. rows="3"
  210. autogrow
  211. hide-bottom-space
  212. lazy-rules
  213. />
  214. </div>
  215. <div>
  216. <div class="row q-gutter-sm q-mt-xs">
  217. <q-chip
  218. v-for="type in addressTypes"
  219. :key="type.value"
  220. :selected="form.address_type === type.value"
  221. clickable
  222. color="primary"
  223. :outline="form.address_type !== type.value"
  224. text-color="surface"
  225. :icon="type.icon"
  226. :icon-selected="type.icon"
  227. @click="form.address_type = type.value"
  228. >
  229. {{ $t(type.label) }}
  230. </q-chip>
  231. </div>
  232. </div>
  233. </q-card-section>
  234. </template>
  235. <script setup>
  236. import { ref } from 'vue';
  237. import { useInputRules } from 'src/composables/useInputRules';
  238. import axios from 'axios';
  239. const form = defineModel({ type: Object, required: true });
  240. const { inputRules } = useInputRules();
  241. const loadingCep = ref(false);
  242. const addressTypes = [
  243. { value: 'home', label: 'auth.address_type_home', icon: 'mdi-home-outline' },
  244. { value: 'commercial', label: 'auth.address_type_commercial', icon: 'mdi-briefcase-variant-outline' },
  245. { value: 'other', label: 'auth.address_type_other', icon: 'mdi-map-marker-outline' },
  246. ];
  247. const fetchCep = async (rawCep) => {
  248. const cleaned = rawCep.replace(/\D/g, '');
  249. if (cleaned.length !== 8) return;
  250. loadingCep.value = true;
  251. try {
  252. const { data } = await axios.get(`https://viacep.com.br/ws/${cleaned}/json/`);
  253. if (!data.erro) {
  254. form.value.address = data.logradouro ?? '';
  255. form.value.district = data.bairro ?? '';
  256. form.value.city = data.localidade ?? '';
  257. form.value.state = data.uf ?? '';
  258. } else {
  259. form.value.address = '';
  260. form.value.district = '';
  261. form.value.city = '';
  262. form.value.state = '';
  263. }
  264. } catch {
  265. form.value.address = '';
  266. form.value.district = '';
  267. form.value.city = '';
  268. form.value.state = '';
  269. } finally {
  270. loadingCep.value = false;
  271. }
  272. };
  273. const onCepChange = (val) => {
  274. const cleaned = val?.replace(/\D/g, '') ?? '';
  275. if (cleaned.length === 8) {
  276. fetchCep(val);
  277. } else {
  278. form.value.address = '';
  279. form.value.district = '';
  280. form.value.city = '';
  281. form.value.state = '';
  282. }
  283. };
  284. </script>