| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- <script setup>
- import AppLayout from "@/Layouts/AppLayout.vue";
- import {router, useForm} from "@inertiajs/vue3";
- import ChatInput from "@/Components/ChatInput.vue";
- import {useEcho} from "@laravel/echo-vue";
- import Message from "@/Components/Message.vue";
- import {nextTick, onMounted} from "vue";
- const {chat} = defineProps({chat: {type: Object}})
- const form = useForm({message: null})
- const submit = () => {
- form.post(route('chats.messages.store', chat.id), {
- preserveScroll: true,
- onSuccess: () => {
- scroll()
- form.reset()
- }
- })
- }
- useEcho(`App.Models.Chat.${chat.id}`, '.MessageCreated', (e) => {
- if (e?.data?.role !== 'human') reload()
- });
- useEcho(`App.Models.Chat.${chat.id}`, '.MessageUpdated', () => reload());
- const reload = () => {
- router.reload({preserveScroll: true, only: ['chat'], onSuccess: () => scroll()})
- }
- const scroll = () => {
- window.scrollBy({
- top: document.body.scrollHeight,
- behavior: 'smooth'
- });
- }
- onMounted(() => nextTick(() => scroll()))
- </script>
- <template>
- <AppLayout page-class="">
- <div class="max-w-5xl mx-auto flex flex-col h-full">
- <div class="flex-1 my-2">
- <div class="space-y-4">
- <div v-for="message in chat.messages">
- <div v-if="message.role === 'human'" class="flex">
- <div class="ml-auto border bg-card text-card-foreground p-2 rounded-lg max-w-[75%] text-sm"
- v-html="message.content.replaceAll('\n', '<br />')"></div>
- </div>
- <Message v-else :message="message"/>
- </div>
- </div>
- </div>
- <div class="shrink-0 sticky bottom-2 mt-100">
- <!-- // TODO: If Last Message Not In Canceled Failed or Completed -->
- <ChatInput v-model="form.message" :disabled="form.processing" @submit="submit"/>
- </div>
- </div>
- </AppLayout>
- </template>
- <style scoped>
- </style>
|