Browse Source

feat: :sparkles: feat(agendamento-sobre-medida) adicionando componentes novos e suas requisições

ajustado payload juntamente com componentes para listar e pucar as infoesta retornando o principal endereço do cliente, tipos de serviços e especialidades puxando do cadastro, criação de permissões e criação do agendamento

fase:dev | origin:escopo
kayo henrique 2 weeks ago
parent
commit
150358ae07

+ 8 - 0
src/api/address.js

@@ -60,3 +60,11 @@ export const searchAddressByCEP = async (cep) => {
     return null;
   }
 };
+
+export function getClientAddresses (clientId, source) {
+  return api.get(`/addresses?source=${source}&source_id=${clientId}`)
+}
+
+export function getPrimaryAddress (clientId, source) {
+  return api.get(`/addresses-primary?source=${source}&source_id=${clientId}`)
+}

+ 6 - 0
src/api/serviceTypes.js

@@ -0,0 +1,6 @@
+import api from 'src/api'
+
+export const getPublicServiceTypes = async () => {
+  const { data } = await api.get('/service-types')
+  return data.payload
+}

+ 6 - 0
src/api/specialties.js

@@ -0,0 +1,6 @@
+import api from 'src/api'
+
+export const getPublicSpecialties = async () => {
+  const { data } = await api.get('/specialities')
+  return data.payload
+}

+ 127 - 83
src/pages/schedules/SobMedidaPage.vue

@@ -4,11 +4,15 @@
     <div class="page-shell">
       <span class="page-title gradient-diarista">Serviço Sob Medida</span>
 
-      <!-- Seu pedido -->
-      <q-card flat bordered class=" figma-card compact-card">
-        <div class="field-label text-center gradient-diarista">
-  Quantidade de serviço
-</div>
+     <q-card flat bordered class="figma-card compact-card">
+  <div class="card-title text-center gradient-diarista">
+    Seu pedido
+  </div>
+
+  <div class="field-label text-center gradient-diarista">
+    Quantidade de serviço
+  </div>
+
 
 <div class="quantity-stepper">
   <q-btn
@@ -30,36 +34,38 @@
     class="quantity-btn"
     @click="increaseQuantity"
   />
+
+</div>
+ <div class="options-grid gradient-diarista">
+  <div
+    v-for="option in addressTypesOptions"
+    :key="option.value"
+    class="option-col"
+  >
+    <q-radio
+      v-model="selectedOption"
+      :val="option.value"
+      :label="option.label"
+      color="purple"
+      dense
+    />
+  </div>
 </div>
-        <div class="card-title gradient-diarista">Seu pedido</div>
-
-        <div class="options-grid">
-          <div
-            v-for="tipo in option"
-            :key="tipo"
-            class="option-col"
-          >
-            <q-radio
-              v-model="selectedOption"
-              :val="tipo"
-              :label="tipo"
-              color="purple"
-              dense
-            />
-          </div>
-        </div>
 
-        <div class="field-label text-center gradient-diarista">Tipo de serviço</div>
-<div class="options-grid">
+ <div class="field-label text-center gradient-diarista">
+  Tipo de serviço
+</div>
+
+<div class="service-type-inline">
   <div
-    v-for="tipo in selectedServiceTypes"
-    :key="tipo"
+    v-for="serviceType in serviceTypes"
+    :key="serviceType.id"
     class="option-col"
   >
     <q-radio
       v-model="selectedServiceType"
-      :val="tipo"
-      :label="tipo"
+      :val="serviceType.id"
+      :label="serviceType.description"
       color="purple"
       dense
     />
@@ -67,23 +73,25 @@
 </div>
 
 <div class="field-label text-center gradient-diarista">Especialidade preferencial?</div>
+<div class="options-grid">
 <div class="options-grid">
   <div
     v-for="item in specialties"
-    :key="item"
+    :key="item.id"
     class="option-col"
   >
     <q-checkbox
       v-model="selectedSpecialties"
-      :val="item"
-      :label="item"
+      :val="item.id"
+      :label="item.description"
       color="purple"
       dense
     />
   </div>
+</div>
 </div>
 
-        i<div class="field-label text-center gradient-diarista">
+        <div class="field-label text-center gradient-diarista">
           Descreva detalhes do pedido
           <span class="optional">(opcional)</span>
         </div>
@@ -150,47 +158,52 @@
 </template>
 
 <script setup>
-import { ref, computed, watch } from 'vue'
+import { ref, computed, watch, onMounted } from 'vue'
 import { useQuasar } from 'quasar'
 
 import ServiceSelectionSheet from 'src/pages/search/components/ServiceSelectionSheet.vue'
 import ServiceTimeSelectionDialog from 'src/pages/search/components/ServiceTimeSelectionDialog.vue'
 
 import { createCustomSchedule } from 'src/api/customSchedules'
+import { getPrimaryAddress } from 'src/api/address'
+import { getPublicServiceTypes } from 'src/api/serviceTypes'
+import { getPublicSpecialties } from 'src/api/specialties'
 import { userStore } from 'src/stores/user'
 import { calculateDailyPrices } from 'src/helpers/utils'
 
 const $q = useQuasar()
-const user =userStore();
-
-const option = ['Residencial', 'Comercial']
-
-const selectedServiceTypes = [
-  'Limpeza',
-  'Pré-mudança',
-  'Evento',
-  'Pós-obra'
-]
-
-const specialties = [
-  'Passar roupa',
-  'Limpar vidros',
-  'Lavar roupa',
-  'Cozinhar'
-]
-
-const selectedOption = ref('Residencial')
-const selectedServiceType = ref('Limpeza')
+const user = userStore()
+
+const addressTypesOptions = computed(() => [
+  { label: 'Residencial', value: 'home' },
+  { label: 'Comercial', value: 'commercial' }
+])
+
+// listas vindas da API
+const serviceTypes = ref([])
+const specialties = ref([])
+
+// seleções do usuário
+const selectedServiceType = ref(null)
 const selectedSpecialties = ref([])
+const selectedOption = ref('home')
+
+// campos do formulário
+const address = ref([])
 const description = ref('')
-const priceRange = ref({ min: 150, max: 300 })
 const selectedDate = ref(null)
+const quantity = ref(1)
 
 const PRICE_LIMITS = Object.freeze({
   min: 100,
   max: 500
 })
 
+const priceRange = ref({
+  min: 150,
+  max: 300
+})
+
 const minPosition = computed(() =>
   ((priceRange.value.min - PRICE_LIMITS.min) /
     (PRICE_LIMITS.max - PRICE_LIMITS.min)) * 100
@@ -201,13 +214,28 @@ const maxPosition = computed(() =>
     (PRICE_LIMITS.max - PRICE_LIMITS.min)) * 100
 )
 
+onMounted(async () => {
+  const { data } = await getPrimaryAddress(user.user.client.id, 'client')
+  address.value = data.payload
+
+  const publicServiceTypes = await getPublicServiceTypes()
+  serviceTypes.value = publicServiceTypes
+
+  const publicSpecialties = await getPublicSpecialties()
+  specialties.value = publicSpecialties
+})
 
 
+watch(selectedDate, (newDate, oldDate) => {
+  if (!newDate || newDate === oldDate) return
+  openServiceSelection()
+})
+
 function openServiceSelection () {
   $q.dialog({
     component: ServiceSelectionSheet,
     componentProps: {
-      provider: providerMock.value,
+      provider: calculateDailyPrices(priceRange.value.max * quantity.value),
       selectedDate: selectedDate.value
     }
   }).onOk((payload) => {
@@ -225,34 +253,30 @@ function openServiceTimeSelection (serviceType) {
       provider: calculateDailyPrices(priceRange.value.max * quantity.value),
       selectedDate: selectedDate.value
     }
-  }).onOk(async (payloadFinal) => {
-  await saveFinalOrder(payloadFinal)
-})
+  }).onOk(saveFinalOrder)
 }
 
-/**
- * abre modal somente quando usuário escolher um dia
- */
-watch(selectedDate, (newDate, previousDate) => {
-  if (!newDate) return
-  if (newDate === previousDate) return
+async function saveFinalOrder (payloadFinal) {
+  let [startHour, endHour] = payloadFinal.slot.split('-')
 
-  openServiceSelection()
-})
+  if(startHour < 10) {
+    startHour = '0' + startHour
+  }
 
-async function saveFinalOrder (payloadFinal) {
-  const [startHour, endHour] = payloadFinal.slot.split('-')
+  if(endHour < 10) {
+    endHour = '0' + endHour
+  }
 
   const payload = {
     client_id: user.user.client.id,
-  // address_id: 1,endereço principal do cliente, por enquanto hardcoded
-    // quantity: 1,pegar do tipo de serviço escolhido, por enquanto hardcoded
+    address_id: address.value?.id,
+    quantity: quantity.value,
     date: payloadFinal.date,
     period_type: String(payloadFinal.serviceType.hoursCount),
-    start_time: `${startHour}:00:00`,
-    end_time: `${endHour}:00:00`,
+    start_time: `${startHour}:00`,
+    end_time: `${endHour}:00`,
     address_type: selectedOption.value.toLowerCase(),
-    // service_type_id: 1 pega do cadastro do tipo de serviço, por enquanto hardcoded
+    service_type_id: selectedServiceType.value,
     description: description.value,
     min_price: priceRange.value.min,
     max_price: priceRange.value.max,
@@ -268,16 +292,12 @@ async function saveFinalOrder (payloadFinal) {
   })
 }
 
-const quantity = ref(1)
-
 function increaseQuantity () {
   quantity.value++
 }
 
 function decreaseQuantity () {
-  if (quantity.value > 1) {
-    quantity.value--
-  }
+  if (quantity.value > 1) quantity.value--
 }
 </script>
 
@@ -319,6 +339,26 @@ function decreaseQuantity () {
   margin-bottom: 16px;
 }
 
+.options-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 12px 20px;
+  justify-items: center;
+  margin-bottom: 12px;
+
+  :deep(.q-radio__label),
+  :deep(.q-checkbox__label) {
+    color: #000 !important;
+    font-size: 14px;
+    font-weight: 400;
+  }
+
+  :deep(.q-checkbox__inner),
+  :deep(.q-radio__inner) {
+    color: #a78bfa !important;
+  }
+}
+
 .section-title {
   margin-left: 16px;
 }
@@ -335,11 +375,7 @@ function decreaseQuantity () {
   font-weight: 400;
 }
 
-.options-grid {
-  display: grid;
-  grid-template-columns: repeat(2, 1fr);
-  gap: 12px 20px;
-}
+
 
 .option-col {
   min-width: 0;
@@ -351,6 +387,7 @@ function decreaseQuantity () {
 
 .description-box :deep(textarea) {
   min-height: 90px;
+  resize: none;
 }
 
 /* CARD */
@@ -488,6 +525,13 @@ function decreaseQuantity () {
   font-weight: 700;
 }
 
+.service-type-inline {
+  display: grid;
+  grid-template-columns: repeat(2, 160px);
+  gap: 12px 24px;
+  justify-content: center;
+  margin: 0 auto 16px;
+}
 /* hover individual do balão */
 .price-pin:hover {
   background: linear-gradient(180deg, #7b68ff, #5f46d8);

+ 1 - 1
src/pages/search/components/ServiceTimeSelectionDialog.vue

@@ -119,7 +119,7 @@ const timeSlots = computed(() => {
     const end = start + h;
     slots.push({
       value: `${start}-${end}`,
-      label: `${start}h às ${end}h`,
+      label: `${start >= 10 ? start : '0' + start}h às ${end >= 10 ? end : '0' + end}h`,
     });
   }
   return slots;