Compare commits

...

2 Commits

7 changed files with 96 additions and 31 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -10,8 +10,8 @@
<link rel="shortcut icon" href="/favicon/favicon.ico" /> <link rel="shortcut icon" href="/favicon/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" /> <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" /> <link rel="manifest" href="/site.webmanifest" />
<script type="module" crossorigin src="/assets/index-adnA05sT.js"></script> <script type="module" crossorigin src="/assets/index-lEa7rgri.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DTfx5B6F.css"> <link rel="stylesheet" crossorigin href="/assets/index-DIsRwQnG.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@@ -22,6 +22,7 @@ import { ref, onMounted } from 'vue'
import ChatSidebar from './ChatSidebar.vue' import ChatSidebar from './ChatSidebar.vue'
import ChatMain from './ChatMain.vue' import ChatMain from './ChatMain.vue'
import { chatService } from '../services/chatService.ts' import { chatService } from '../services/chatService.ts'
import { dateUtils } from '../utils/dateUtils.ts'
// Estado reactivo // Estado reactivo
const chatId = ref('') const chatId = ref('')
@@ -86,7 +87,7 @@ const sendMessage = async (prompt) => {
const userMessage = { const userMessage = {
role: "user", role: "user",
text: prompt, text: prompt,
date: new Date().toISOString() date: dateUtils.formatDate(new Date())
} }
messages.value.push(userMessage) messages.value.push(userMessage)

View File

@@ -7,17 +7,17 @@
v-show="msg.text" v-show="msg.text"
> >
<span>{{ msg.text }}</span> <span>{{ msg.text }}</span>
<em class="timestamp">{{ formatDate(msg.date) }}</em> <em class="timestamp">{{ msg.date }}</em>
</div> </div>
</div> </div>
<div v-if="isLoading" class="spinner"></div> <Spinner v-if="isLoading" :overlay="false" />
<div v-if="isLoading" class="thinking-text">Pensando...</div> <div v-if="isLoading" class="thinking-text">Pensando...</div>
</template> </template>
<script setup> <script setup>
import { ref, watch, nextTick } from 'vue' import { ref, watch, nextTick } from 'vue'
import { dateUtils } from '../utils/dateUtils.ts' import Spinner from './Spinner.vue'
const props = defineProps({ const props = defineProps({
messages: { messages: {
@@ -116,22 +116,6 @@ const formatDate = (date) => {
user-select: none; user-select: none;
} }
.spinner {
margin: 1rem auto;
width: 36px;
height: 36px;
border: 4px solid rgba(90, 144, 255, 0.2);
border-top-color: #5a90ff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.thinking-text { .thinking-text {
text-align: center; text-align: center;
color: #5a90ff; color: #5a90ff;

View File

@@ -0,0 +1,80 @@
<template>
<div class="spinner-container" :class="{ overlay }">
<svg
class="spinner"
width="50"
height="50"
viewBox="0 0 50 50"
aria-label="Cargando"
role="img"
>
<circle
class="spinner-path"
cx="25"
cy="25"
r="20"
fill="none"
stroke-width="5"
/>
</svg>
</div>
</template>
<script setup>
defineProps({
overlay: {
type: Boolean,
default: false,
},
})
</script>
<style scoped>
.spinner-container {
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
}
.spinner-container.overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(255, 255, 255, 0.6);
z-index: 9999;
}
.spinner {
animation: rotate 2s linear infinite;
}
.spinner-path {
stroke: #5a90ff;
stroke-linecap: round;
animation: dash 1.5s ease-in-out infinite;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dasharray: 1, 150;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -35;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -124;
}
}
</style>