diff --git a/backend/pom.xml b/backend/pom.xml index cb8a5ee..90aa2a4 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -23,12 +23,6 @@ spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-thymeleaf - - de.kherud diff --git a/backend/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java b/backend/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java deleted file mode 100644 index 11b8986..0000000 --- a/backend/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.pablotj.ia.chat.boot.adapter.controller; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@RequestMapping("/chat") -public class ChatPageController { - - private static final Logger LOGGER = LogManager.getLogger(ChatPageController.class); - - @GetMapping - public String showChat(Model model) { - LOGGER.debug("Accessing to chat"); - return "chat"; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/pablotj/ia/chat/boot/application/prompt/PromptBuilder.java b/backend/src/main/java/com/pablotj/ia/chat/boot/application/prompt/PromptBuilder.java index ce858f7..65bdb84 100644 --- a/backend/src/main/java/com/pablotj/ia/chat/boot/application/prompt/PromptBuilder.java +++ b/backend/src/main/java/com/pablotj/ia/chat/boot/application/prompt/PromptBuilder.java @@ -2,7 +2,7 @@ package com.pablotj.ia.chat.boot.application.prompt; import java.util.ArrayList; import java.util.List; -import org.thymeleaf.util.StringUtils; +import org.springframework.util.StringUtils; public class PromptBuilder { diff --git a/backend/src/main/resources/static/css/styles.css b/backend/src/main/resources/static/css/styles.css deleted file mode 100644 index b7cbbe2..0000000 --- a/backend/src/main/resources/static/css/styles.css +++ /dev/null @@ -1,297 +0,0 @@ -/* Base y fuente */ -html, body { - margin: 0; - padding: 0; - height: 100%; - background: #121217; - color: #e0e4e8; - font-family: 'Segoe UI Variable', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -body { - margin: 0; - padding: 0; - height: 100vh; - background-color: #121217; -} - -/* Layout general */ -.layout-container { - display: flex; - height: 100vh; - width: 100vw; - overflow: hidden; -} - -/* Menú lateral izquierdo */ -#sidebar { - width: 25%; - min-width: 200px; - background-color: #1b1d23; - color: #ffffff; - padding: 1.5rem 1rem; - box-sizing: border-box; - border-right: 1px solid #2c2e34; - display: flex; - flex-direction: column; -} - -#sidebar h2 { - font-size: 1.25rem; - margin-bottom: 1rem; - color: #5a90ff; -} - -#chat-list { - list-style: none; - padding: 0; - margin: 0; - overflow-y: auto; - flex-grow: 1; -} - -#chat-list li { - padding: 0.5rem 0.75rem; - cursor: pointer; - border-radius: 8px; - transition: background-color 0.2s ease; - font-size: 0.95rem; -} - -#chat-list li:hover { - background-color: #2c2f3a; -} - -#chat-list li.active { - background-color: #3451d1; - color: white; - font-weight: bold; -} - -/* Área principal del chat */ -#main-content { - width: 75%; - box-sizing: border-box; - display: flex; - flex-direction: column; - padding: 2rem 1.25rem 1rem; - background-color: #121217; - overflow: hidden; -} - -/* Título */ -h1 { - text-align: center; - margin-bottom: 1.25rem; - color: #5a90ff; - font-weight: 700; - font-size: 1.75rem; - letter-spacing: 0.05em; - user-select: none; -} - -/* Contenedor de mensajes */ -#chat-log { - flex: 1 1 auto; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 12px; - padding: 1.25rem 1.5rem; - box-sizing: border-box; - background-color: #1a1c22; - border-radius: 16px; - scrollbar-width: thin; - scrollbar-color: #5a90ff33 transparent; -} - -#chat-log::-webkit-scrollbar { - width: 6px; -} - -#chat-log::-webkit-scrollbar-thumb { - background-color: #5a90ff55; - border-radius: 3px; -} - -/* Burbujas comunes */ -.bubble { - max-width: 75%; - padding: 14px 18px; - border-radius: 20px; - line-height: 1.5; - font-size: 1rem; - word-wrap: break-word; - user-select: text; - transition: background-color 0.3s ease, color 0.3s ease; - opacity: 0; - transform: translateY(10px); - animation: slideFadeIn 0.3s forwards; -} - -@keyframes slideFadeIn { - to { - opacity: 1; - transform: translateY(0); - } -} - -/* Burbuja del usuario */ -.user { - background-color: #3451d1; - align-self: flex-end; - color: #ffffff; - border-radius: 20px 20px 4px 20px; -} - -/* Burbuja del bot */ -.bot { - background-color: #2a2d35; - align-self: flex-start; - color: #a4c8ff; - font-style: italic; - border-radius: 20px 20px 20px 4px; -} - -/* Formulario de entrada */ -form { - flex-shrink: 0; - margin-top: 1.25rem; - display: flex; - gap: 12px; - padding: 0; - box-sizing: border-box; - background: transparent; - border-radius: 0; -} - -/* Textarea */ -textarea { - flex-grow: 1; - min-height: 4.25rem; - border-radius: 16px; - border: 1px solid #2d2f36; - padding: 1rem 1.25rem; - font-size: 1rem; - resize: none; - outline: none; - background-color: #1c1e24; - color: #e6e9ef; - font-family: inherit; - max-width: 100%; - overflow-y: auto; - box-sizing: border-box; - transition: border-color 0.25s ease, background-color 0.25s ease; -} - -textarea::placeholder { - color: #6a6e7c; - font-style: italic; - opacity: 0.9; -} - -textarea:focus { - border-color: #5a90ff; - background-color: #20232a; -} - -/* Botón */ -button#send-btn { - background-color: #5a90ff; - border: none; - border-radius: 14px; - color: #ffffff; - padding: 0 1.75rem; - font-weight: 600; - font-size: 1rem; - cursor: pointer; - transition: background-color 0.25s ease, transform 0.1s ease; - white-space: nowrap; -} - -button#send-btn:hover:not(:disabled) { - background-color: #4076e0; -} - -button#send-btn:active:not(:disabled) { - transform: translateY(1px); - background-color: #305dc0; -} - -button#send-btn:disabled { - opacity: 0.5; - cursor: not-allowed; - background-color: #3a4a6a; -} - -#spinner { - display: none; - 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); - } -} - -/* Texto "Pensando..." */ -#thinking-text { - text-align: center; - color: #5a90ff; - font-style: italic; - margin-top: 0.5rem; - font-weight: 600; - display: none; - user-select: none; -} - -.timestamp { - display: block; - text-align: right; - font-size: 0.75rem; - color: #999; - margin-top: 6px; - font-style: normal; - opacity: 0.7; - user-select: none; -} - -#new-chat-btn { - margin-bottom: 10px; - padding: 8px; - font-size: 14px; - cursor: pointer; - background-color: #f0f0f0; - border: 1px solid #ccc; - border-radius: 4px; -} - -#new-chat-btn:hover { - background-color: #e0e0e0; -} - -/* Responsive */ -@media (max-width: 768px) { - .layout-container { - flex-direction: column; - } - - #sidebar { - width: 100%; - border-right: none; - border-bottom: 1px solid #2c2e34; - } - - #main-content { - width: 100%; - } -} \ No newline at end of file diff --git a/backend/src/main/resources/static/js/main.js b/backend/src/main/resources/static/js/main.js deleted file mode 100644 index f39358d..0000000 --- a/backend/src/main/resources/static/js/main.js +++ /dev/null @@ -1,167 +0,0 @@ -let chatId = ''; - -document.addEventListener("DOMContentLoaded", async () => { - const newChatBtn = document.getElementById("new-chat-btn"); - const chatList = document.getElementById("chat-list"); - const form = document.getElementById('chat-form'); - const promptInput = document.getElementById('prompt'); - const chatLog = document.getElementById('chat-log'); - const sendBtn = document.getElementById('send-btn'); - const spinner = document.getElementById('spinner'); - const thinkingText = document.getElementById('thinking-text'); - - await loadHistory(); - - async function loadHistory() { - try { - const response = await fetch("/api/v1/chats", { method: "GET" }); - const data = await response.json(); - - chatList.innerHTML = ""; - - data.forEach(chat => { - const li = document.createElement("li"); - li.textContent = chat.name; - li.setAttribute("data-chat-id", chat.id); - if (chat.id === chatId) { - li.classList.add("active"); - } - - li.addEventListener("click", async () => { - const selectedId = chat.id; - if (selectedId !== chatId) { - chatId = selectedId; - highlightActiveChat(li); - await loadMessages(chatId); - } - }); - - chatList.appendChild(li); - }); - - // Autoabrir primer chat si no hay chatId activo - if (!chatId && data.length > 0) { - chatId = data[0].id; - const firstLi = chatList.querySelector('li'); - if (firstLi) { - firstLi.classList.add("active"); - await loadMessages(chatId); - } - } - - } catch (error) { - console.error("Error cargando historial:", error); - } - } - - async function loadMessages(chatId) { - try { - const response = await fetch(`/api/v1/chats/${chatId}`); - const messages = await response.json(); - - chatLog.innerHTML = ""; - - messages.forEach(msg => { - appendMessage(msg.role, msg.text, msg.date); - }); - - } catch (error) { - appendMessage("bot", "❌ Error cargando mensajes del chat."); - console.error("Error al cargar mensajes:", error); - } - } - - function highlightActiveChat(selectedLi) { - const lis = chatList.querySelectorAll("li"); - lis.forEach(li => li.classList.remove("active")); - selectedLi.classList.add("active"); - } - - function appendMessage(role, text, date) { - const bubble = document.createElement('div'); - bubble.className = `bubble ${role}`; - bubble.textContent = text; - chatLog.appendChild(bubble); - - const timestamp = document.createElement('em'); - timestamp.className = 'timestamp'; - timestamp.textContent = date; - bubble.appendChild(timestamp); - - chatLog.scrollTop = chatLog.scrollHeight; - } - - async function createNewChat() { - try { - const response = await fetch("/api/v1/chats", { - method: "POST" - }); - chatId = await response.text(); - - await loadHistory(); - await loadMessages(chatId); - - const li = chatList.querySelector(`li[data-chat-id="${chatId}"]`); - if (li) highlightActiveChat(li); - - } catch (error) { - console.error("Error al crear nuevo chat:", error); - appendMessage("bot", "❌ Error creando nuevo chat."); - } - } - newChatBtn.addEventListener("click", async () => { - await createNewChat() - }); - - form.addEventListener('submit', async function (e) { - e.preventDefault(); - - if (chatId === undefined || chatId === null || chatId === '') { - await createNewChat(); - } - - const prompt = promptInput.value.trim(); - if (!prompt) return; - - appendMessage("user", prompt, formatDate(new Date())); - promptInput.value = ""; - sendBtn.disabled = true; - spinner.style.display = 'block'; - thinkingText.style.display = 'block'; - - try { - const response = await fetch(`/api/v1/chats/${chatId}`, { - method: "PUT", - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - body: new URLSearchParams({ prompt }) - }); - - const data = await response.json(); - chatId = data.chatId; - - appendMessage("bot", data.text, data.date); - - await loadHistory(); - - } catch (error) { - appendMessage("bot", "❌ Error procesando la respuesta."); - console.error(error); - } finally { - sendBtn.disabled = false; - spinner.style.display = 'none'; - thinkingText.style.display = 'none'; - } - }); - - function formatDate(date) { - const day = date.getDate().toString().padStart(2, '0'); - const month = (date.getMonth() + 1).toString().padStart(2, '0'); - const year = date.getFullYear(); - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - - return `${day}/${month}/${year} ${hours}:${minutes}`; - } -}); \ No newline at end of file diff --git a/backend/src/main/resources/templates/chat.html b/backend/src/main/resources/templates/chat.html deleted file mode 100644 index 8124509..0000000 --- a/backend/src/main/resources/templates/chat.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - Chat IA Offline - - - -
- - - - - -
-

🤖 Chat IA Offline

- -
-
- - -
-
-
-
Pensando...
- -
- - -
-
- -
- - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index e1ff610..b3c61a2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,6 +4,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + com.pablotj + chat-ia-offline + 0.0.1-SNAPSHOT + pom org.springframework.boot @@ -12,11 +16,6 @@ - com.pablotj - chat-ia-offline - 0.0.1-SNAPSHOT - pom - backend frontend