# Conversation Bone

# Introducción

Éste componente no está encargado de renderizar, es de uso interno del IrConversation. Guía de uso parte lógica

# Código fuente

<script>
const propsLocal = {
  messages: {
    type: Array,
    default: () => []
  },
  messages_fcn: {
    type: String,
    required: false
  },
  refreshTimer: {
    type: Object,
    default: () => ({
      repeat_time: 5000,
      loops: -1
    })
  },
  args_messages_fcn: {
    type: Array,
    default: () => []
  },
  cache_messages: {
    type: Boolean,
    default: true
  },
  id_resolver: {
    type: String,
    required: false
  }
}
import {
  normalizeProps,
  assignCamelToSnake
} from '../../helpers/propsGenerator'
import Vue, { ref, h, onBeforeUnmount } from 'vue'
const mergedProps = normalizeProps(propsLocal)
import { IrConversationName, externalDBEndpoint } from '../../constants'
export default {
  name: IrConversationName + 'Bone',
  props: mergedProps,
  setup(props, { slots, emit, expose }) {
    const iclAxios = Vue.prototype.$iclAxios
    const iclstore = Vue.prototype.$iclstore
    const iclRouter = Vue.prototype.$iclRouter
    const detectResponseStructErrors = Vue.prototype.$detectResponseStructErrors
    const loading = ref(false)
    const refreshed = ref(false)
    const loopInterval = ref(null)
    const firstTime = ref(true)

    /*** Separa los mensajes por fecha.
     *
     * @param {Array} mensajes - La lista de mensajes a ser procesados.
     * @returns {Array} Un array de objetos con propiedades 'date' y 'messages'.
     */
    const separatePerDate = (mensajes) => {
      const mensajesPorDia = {}
      mensajes.forEach((mensaje) => {
        try {
          const fecha = new Date(mensaje.date).toISOString().split('T')[0]
          if (!mensajesPorDia[fecha]) mensajesPorDia[fecha] = []
          mensajesPorDia[fecha].push(mensaje)
        } catch (error) {
          console.log('No se pudo conseguir la fecha del mensaje', mensaje)
          console.log(error)
        }
      })
      return Object.values(mensajesPorDia).map((messages, index) => {
        return { date: Object.keys(mensajesPorDia)[index], messages }
      })
    }

    /**
     * Obtiene mensajes mediante una solicitud a un punto final externo.
     */
    const getMessages = async () => {
      loading.value = true
      const params = {
        args: props.args_messages_fcn,
        id_usuario: iclstore.state.id_usuario,
        id_resolver: props.id_resolver
          ? props.id_resolver
          : iclRouter.currentRoute.path
      }
      try {
        const rsp = await iclAxios.post(externalDBEndpoint + props.messages_fcn, [JSON.stringify(params)])
        const paramsDetectErrors = [
          props.messages_fcn,
          [],
          IrConversationName,
          '{type: String, props: Object}',
          'https://icl.iridiumrobotics.com.ar/components/ir-conversation.html#uso'
        ]
        detectResponseStructErrors(rsp, ...paramsDetectErrors) //En caso de detección de errores en la respuesta NO interrumpe la ejecución del componente, solo loguea.
        emit('uploaded-messages', rsp || [])
      } catch (error) {
        console.log(error)
        emit('uploaded-messages', props.messages)
      } finally {
        loading.value = false
      }
    }

    const manageRefreshRepeater = () => {
      const { repeat_time, loops } = props.refreshTimer
      const isInfiniteLoop = loops === -1
      let countingDown = loops
      if (repeat_time && (countingDown > 0 || isInfiniteLoop)) {
        refreshed.value = true
        loopInterval.value = setInterval(async () => {
          if (!isInfiniteLoop) countingDown -= 1
          await getMessages()
          if (!isInfiniteLoop && countingDown <= 0) clearInterval(loopInterval.value)
        }, repeat_time)
      }
    }

    /**
     * Asynchronously manages messages retrieval.
     * @async
     * @function manageMessagesGetter
     */
    const manageMessagesGetter = async () => {
      if (props.messages_fcn && iclAxios) {
        const params = {
          args: props.args_messages_fcn,
          id_usuario: iclstore.state.id_usuario,
          id_resolver: props.id_resolver
            ? props.id_resolver
            : iclRouter.currentRoute.path
        }
        const datosSitio = iclstore.getters.getDatosSitios({
          sitio: iclRouter.app._route.path,
          query: props.messages_fcn,
          method: 'post',
          params: [JSON.stringify(params)]
        })
        if (datosSitio && props.cache_messages && datosSitio.response) {
          // los busca en el store, si los encuentra los guarda en itemsLocal hasta que se termine de hacer la consulta por los items
          emit('uploaded-messages', [...datosSitio.response])
        }
        await getMessages()
      } else {
        // si no se envía messages_fcn se envía al FE la propiedad messages
        emit('uploaded-messages', props.messages)
      }
      if (firstTime.value && props.refreshTimer && props.messages_fcn) {
        firstTime.value = false
        manageRefreshRepeater()
      }
    }

    assignCamelToSnake(mergedProps, props)
    manageMessagesGetter()

    onBeforeUnmount(() => {
      if (loopInterval.value) {
        clearInterval(loopInterval.value)
      }
    })

    expose({
      separatePerDate
    })

    return () => {
      return h(
        'div', // Contenedor como nodo raíz
        [
          slots.default({
            separatePerDate: separatePerDate,
            loading: loading.value
          })
        ]
      )
    }
  }
}
</script>
Last Updated: 4/5/2024, 4:52:19 PM