Implement delete chat with confirmation dialog
This commit is contained in:
parent
3d7ba68511
commit
c5e72d5708
@ -6,6 +6,7 @@
|
|||||||
:current-chat-id="chatUuid"
|
:current-chat-id="chatUuid"
|
||||||
@select-chat="selectChat"
|
@select-chat="selectChat"
|
||||||
@create-chat="createNewChat"
|
@create-chat="createNewChat"
|
||||||
|
@delete-chat="deleteChat"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Área principal del chat -->
|
<!-- Área principal del chat -->
|
||||||
@ -48,6 +49,9 @@ const loadHistory = async () => {
|
|||||||
|
|
||||||
// Cargar mensajes de un chat específico
|
// Cargar mensajes de un chat específico
|
||||||
const loadMessages = async (selectedChatId) => {
|
const loadMessages = async (selectedChatId) => {
|
||||||
|
if (!chatUuid.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const data = await chatService.getChatMessages(selectedChatId)
|
const data = await chatService.getChatMessages(selectedChatId)
|
||||||
messages.value = data
|
messages.value = data
|
||||||
@ -76,6 +80,18 @@ const createNewChat = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eliminar un chat
|
||||||
|
const deleteChat = async () => {
|
||||||
|
try {
|
||||||
|
await chatService.deleteChat(chatUuid.value)
|
||||||
|
chatUuid.value = null;
|
||||||
|
await loadHistory()
|
||||||
|
await loadMessages(chatUuid.value)
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error al crear nuevo chat:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Enviar mensaje
|
// Enviar mensaje
|
||||||
const sendMessage = async (prompt) => {
|
const sendMessage = async (prompt) => {
|
||||||
// Crear nuevo chat si no existe
|
// Crear nuevo chat si no existe
|
||||||
|
@ -9,15 +9,31 @@
|
|||||||
v-for="chat in chats"
|
v-for="chat in chats"
|
||||||
:key="chat.conversationId"
|
:key="chat.conversationId"
|
||||||
:class="{ active: chat.conversationId === currentChatId }"
|
:class="{ active: chat.conversationId === currentChatId }"
|
||||||
@click="$emit('select-chat', chat.conversationId)"
|
@click="$emit('select-chat', chat.conversationId)">
|
||||||
>
|
<span class="chat-title">{{ chat.title }}</span>
|
||||||
{{ chat.title }}
|
<button
|
||||||
|
aria-label="Eliminar chat"
|
||||||
|
class="delete-btn"
|
||||||
|
title="Eliminar chat"
|
||||||
|
@click.stop="onDeleteClick(chat.conversationId)">
|
||||||
|
✖
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<ConfirmDialog
|
||||||
|
:visible="showConfirm"
|
||||||
|
message="¿Seguro que quieres eliminar este chat?"
|
||||||
|
title="Confirmar borrado"
|
||||||
|
@cancel="onCancel"
|
||||||
|
@confirm="onConfirm"
|
||||||
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import {ref} from "vue"
|
||||||
|
import ConfirmDialog from "./ConfirmDialog.vue"
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
chats: {
|
chats: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@ -29,7 +45,29 @@ defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
defineEmits(['select-chat', 'create-chat'])
|
const emit = defineEmits(['select-chat', 'create-chat', 'delete-chat'])
|
||||||
|
|
||||||
|
const showConfirm = ref(false)
|
||||||
|
const chatToDelete = ref(null)
|
||||||
|
|
||||||
|
function onDeleteClick(chatId) {
|
||||||
|
chatToDelete.value = chatId
|
||||||
|
showConfirm.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConfirm() {
|
||||||
|
showConfirm.value = false
|
||||||
|
if (chatToDelete.value) {
|
||||||
|
emit('delete-chat', chatToDelete.value)
|
||||||
|
chatToDelete.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCancel() {
|
||||||
|
showConfirm.value = false
|
||||||
|
chatToDelete.value = null
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@ -92,4 +130,51 @@ defineEmits(['select-chat', 'create-chat'])
|
|||||||
color: white;
|
color: white;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover {
|
||||||
|
background-color: #2c2f3a;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.active {
|
||||||
|
background-color: #3451d1;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-title {
|
||||||
|
flex-grow: 1;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: #c4c4c4;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
padding: 0 0.3rem;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease, color 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover .delete-btn {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn:hover {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
105
chat-web-client/src/components/ConfirmDialog.vue
Normal file
105
chat-web-client/src/components/ConfirmDialog.vue
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-if="visible" class="overlay" @click.self="cancel">
|
||||||
|
<div class="dialog">
|
||||||
|
<h3>{{ title }}</h3>
|
||||||
|
<p>{{ message }}</p>
|
||||||
|
<div class="buttons">
|
||||||
|
<button class="btn cancel" @click="cancel">Cancelar</button>
|
||||||
|
<button class="btn confirm" @click="confirm">Confirmar</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
visible: Boolean,
|
||||||
|
title: {type: String, default: "Confirmación"},
|
||||||
|
message: {type: String, default: "¿Estás seguro?"},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(["confirm", "cancel"])
|
||||||
|
|
||||||
|
const confirm = () => emit("confirm")
|
||||||
|
const cancel = () => emit("cancel")
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
background: white;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
width: 320px;
|
||||||
|
max-width: 90vw;
|
||||||
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
|
||||||
|
text-align: center;
|
||||||
|
animation: popin 0.2s ease-out;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 0.6rem 1.2rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.cancel {
|
||||||
|
background: #e0e0e0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.cancel:hover {
|
||||||
|
background: #d5d5d5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.confirm {
|
||||||
|
background: #e53935;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.confirm:hover {
|
||||||
|
background: #c62828;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active, .fade-leave-active {
|
||||||
|
transition: opacity 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from, .fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes popin {
|
||||||
|
from {
|
||||||
|
transform: scale(0.9);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -39,6 +39,22 @@ class ChatService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteChat(chatId) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/v1/conversations/${chatId}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
})
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error removing chat:", error)
|
||||||
|
toast.error("Could not removing chat")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getChatMessages(chatId) {
|
async getChatMessages(chatId) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/v1/conversations/${chatId}/messages`)
|
const response = await fetch(`/api/v1/conversations/${chatId}/messages`)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user