diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx index 3c87a8c..b3d9144 100644 --- a/src/app/chat/page.tsx +++ b/src/app/chat/page.tsx @@ -1,5 +1,12 @@ -import Chat from "@/sections/chat/Chat"; +import type { Metadata } from 'next'; +import Chat from '@/sections/chat/Chat'; + +export const metadata: Metadata = { + title: 'Asistente AI', + description: + 'Interactúa con nuestra inteligencia artificial para resolver dudas sobre SCADA, BMS y AIIoT.', +}; export default async function Index() { - return ; + return ; } diff --git a/src/app/industrias/page.tsx b/src/app/industrias/page.tsx index d7e180f..7539ef5 100644 --- a/src/app/industrias/page.tsx +++ b/src/app/industrias/page.tsx @@ -1,16 +1,23 @@ -import { Box } from "@mui/material"; -import { IndustrySlider } from "@/sections/industries/IndustrySlider"; -import { IndustryCards } from "@/sections/industries/IndustryCards"; -import { IndustryTitle } from "@/sections/industries/IndustryTitle"; -import { IndustryFooter } from "@/sections/industries/IndustryFooter"; +import type { Metadata } from 'next'; +import { Box } from '@mui/material'; +import { IndustrySlider } from '@/sections/industries/IndustrySlider'; +import { IndustryCards } from '@/sections/industries/IndustryCards'; +import { IndustryTitle } from '@/sections/industries/IndustryTitle'; +import { IndustryFooter } from '@/sections/industries/IndustryFooter'; + +export const metadata: Metadata = { + title: 'Soluciones por Industria', + description: + 'Descubre cómo LogOS optimiza operaciones en Smart Cities, gestión de edificios y entornos industriales.', +}; export default function Industrias() { - return ( - - - - - - - ); + return ( + + + + + + + ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 05e527e..ad704bc 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,91 +1,74 @@ -import { MuiRootProvider } from "@/providers/MuiRootProvider"; -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; -import InitColorSchemeScript from "@mui/material/InitColorSchemeScript"; +import { MuiRootProvider } from '@/providers/MuiRootProvider'; +import type { Metadata } from 'next'; +import { Geist, Geist_Mono } from 'next/font/google'; +import InitColorSchemeScript from '@mui/material/InitColorSchemeScript'; const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], + variable: '--font-geist-sans', + subsets: ['latin'], }); const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], + variable: '--font-geist-mono', + subsets: ['latin'], }); export const metadata: Metadata = { - title: "LogOS", - description: - "Mejora tu eficiencia usando nuestro sistema de gestión inteligente. SCADA, BMS, AIIoT", - applicationName: "LogOS", - keywords: [ - "SCADA", - "industrial", - "AIIoT", - "AI", - "IIoT", - "BMS", - "HMI", - "SEEED", - "KUNBUS", - "Smart Cities", - "Smart City", - "Building Management System", - "Building", - "Management", - "System", - "events", - "alarms", - "bylogosio", - "logosia", - "bylogosia", - "bylogosiot", - "logosio", - "logosiot", - "IoT", - "automatización", - "LogOS", - "ByLogos", - "IA", - "Logos", - "monitorización", - "solución", - "local-first", - "software", - "hardware", - ], - robots: { - googleBot: { - index: true, - follow: true, - }, - }, - authors: [ - { name: "LogOS", url: "https://www.linkedin.com/company/bylogos/" }, - ], - creator: "Javier Vargas", - metadataBase: new URL("https://bylogos.io"), + title: { + default: 'Inteligencia Industrial SCADA, BMS, AIIoT | LogOS', + template: '%s | LogOS', + }, + description: + 'LogOS: Sistema de gestión inteligente para SCADA, BMS y AIIoT. Mejora la eficiencia operacional en Smart Cities e industria.', + applicationName: 'LogOS', + keywords: [ + 'LogOS', + 'SCADA', + 'BMS', + 'AIIoT', + 'IIoT', + 'Industrial AI', + 'Smart Cities', + 'Automatización Industrial', + 'Monitorización en Tiempo Real', + 'Gestión de Edificios', + 'HMI', + 'ByLogos', + ], + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + }, + }, + authors: [ + { name: 'LogOS', url: 'https://www.linkedin.com/company/bylogos/' }, + ], + creator: 'Javier Vargas', + metadataBase: new URL('https://bylogos.io'), }; -import { ConditionalHeader } from "@/sections/layout/ConditionalHeader"; -import { ConditionalFooter } from "@/sections/layout/ConditionalFooter"; +import { ConditionalHeader } from '@/sections/layout/ConditionalHeader'; +import { ConditionalFooter } from '@/sections/layout/ConditionalFooter'; export default function RootLayout({ - children, + children, }: Readonly<{ - children: React.ReactNode; + children: React.ReactNode; }>) { - return ( - - - - - - {children} - - - - - ); + return ( + + + + + + {children} + + + + + ); } diff --git a/src/app/news/[slug]/page.tsx b/src/app/news/[slug]/page.tsx index 8b4dd72..0f34068 100644 --- a/src/app/news/[slug]/page.tsx +++ b/src/app/news/[slug]/page.tsx @@ -1,42 +1,44 @@ -import { news } from "@/velite"; -import { notFound } from "next/navigation"; -import { Metadata } from "next"; -import { NewsPost } from "@/sections/news/NewsPost"; +import { news } from '@/velite'; +import { notFound } from 'next/navigation'; +import { Metadata } from 'next'; +import { NewsPost } from '@/sections/news/NewsPost'; interface PageProps { - params: Promise<{ slug: string }>; + params: Promise<{ slug: string }>; } export async function generateStaticParams() { - return news.map((post) => ({ - slug: post.slug.split("/").pop(), // "news/my-post" -> "my-post" - })); + return news.map((post) => ({ + slug: post.slug.split('/').pop(), // "news/my-post" -> "my-post" + })); } export async function generateMetadata({ - params, + params, }: PageProps): Promise { - const resolvedParams = await params; - // Velite slug is "news/slug", params.slug is "slug" - const post = news.find((p) => p.slug === `news/${resolvedParams.slug}`); - - if (!post) { - return {}; - } - - return { - title: `${post.title} | Logos News`, - description: post.description, - }; + const resolvedParams = await params; + // Velite slug is 'news/slug', params.slug is 'slug' + const post = news.find((p) => p.slug === `news/${resolvedParams.slug}`); + + if (!post) { + return { + title: 'Noticia no encontrada', + }; + } + + return { + title: post.title, + description: post.description, + }; } export default async function NewsPostPage({ params }: PageProps) { - const resolvedParams = await params; - const post = news.find((p) => p.slug === `news/${resolvedParams.slug}`); + const resolvedParams = await params; + const post = news.find((p) => p.slug === `news/${resolvedParams.slug}`); - if (!post) { - notFound(); - } + if (!post) { + notFound(); + } - return ; + return ; } diff --git a/src/app/news/page.tsx b/src/app/news/page.tsx index daaa5ad..d7169fe 100644 --- a/src/app/news/page.tsx +++ b/src/app/news/page.tsx @@ -1,9 +1,10 @@ -import { news } from "@/velite"; // Using alias -import { Box } from "@mui/material"; -import { NewsTitle } from "@/sections/news/NewsTitle"; -import { NewsSlider } from "@/sections/news/NewsSlider"; -import { NewsPosts } from "@/sections/news/NewsPosts"; -import { IndustryFooter } from "@/sections/industries/IndustryFooter"; // Reusing footer as requested ('mismo footer') - actually prompt said "same header and footer as most sections" which usually means global layout, but Industry page has IndustryFooter. +import { news } from '@/velite'; // Using alias +import { Box } from '@mui/material'; +import { NewsTitle } from '@/sections/news/NewsTitle'; +import { NewsSlider } from '@/sections/news/NewsSlider'; +import { NewsPosts } from '@/sections/news/NewsPosts'; +import { IndustryFooter } from '@/sections/industries/IndustryFooter'; // Reusing footer as requested ('mismo footer') - actually prompt said "same header and footer as most sections" which usually means global layout, but Industry page has IndustryFooter. +import { Metadata } from 'next'; // User said: "usará mismo header y footer que la mayoria de las secciones del website" // Industry page uses `IndustryFooter`. Global layout likely handles Header/Footer if not overridden. // Industries page explicitly imports `IndustryFooter`. I will check if I should use that or default. @@ -52,26 +53,26 @@ export default function Industrias() { // Better yet, I'll just write the page without footer first, as that's safer for "most sections". // But I need to sort the news. -export const metadata = { - title: "Noticias y Novedades | Logos", - description: - "Mantente informado con las últimas noticias sobre tecnología industrial, IA e IoT.", +export const metadata: Metadata = { + title: 'Noticias y Blog', + description: + 'Mantente informado con las últimas noticias sobre tecnología industrial, IA e IoT de la mano de LogOS.', }; export default function NewsPage() { - // Sort posts by date descending (newest first) - const sortedPosts = news.sort((a, b) => { - return new Date(b.date).getTime() - new Date(a.date).getTime(); - }); + // Sort posts by date descending (newest first) + const sortedPosts = news.sort((a, b) => { + return new Date(b.date).getTime() - new Date(a.date).getTime(); + }); - // Top 5 for slider - const sliderPosts = sortedPosts.slice(0, 5); + // Top 5 for slider + const sliderPosts = sortedPosts.slice(0, 5); - return ( - - - - - - ); + return ( + + + + + + ); } diff --git a/src/app/nosotros/page.tsx b/src/app/nosotros/page.tsx index 095e00a..9dee9d8 100644 --- a/src/app/nosotros/page.tsx +++ b/src/app/nosotros/page.tsx @@ -1,15 +1,22 @@ -import { Container, Typography } from "@mui/material"; +import type { Metadata } from 'next'; +import { Container, Typography } from '@mui/material'; + +export const metadata: Metadata = { + title: 'Sobre Nosotros', + description: + 'Conoce al equipo detrás de LogOS y nuestra misión de transformar la gestión industrial mediante IA y AIIoT.', +}; export default function Nosotros() { - return ( - - - Nosotros - - - Esta página está en construcción. Pronto conocerás más sobre LogOS y - nuestro equipo. - - - ); + return ( + + + Nosotros + + + Esta página está en construcción. Pronto conocerás más sobre LogOS y + nuestro equipo. + + + ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 9e421a1..bf8a234 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,43 +1,14 @@ -"use client"; +import type { Metadata } from 'next'; +import { LandingPage } from '@/components/layout/LandingPage'; -import { Box, useTheme } from "@mui/material"; -import { Hero } from "@/sections/landing/Hero"; -import { Features } from "@/sections/landing/Features"; -import { HardwareAlternatives } from "@/sections/landing/HardwareAlternatives"; -import { Stack } from "@/sections/landing/Stack"; -import { Testimonials } from "@/sections/landing/Testimonials"; -import { Newsletter } from "@/sections/landing/Newsletter"; +export const metadata: Metadata = { + title: { + absolute: 'LogOS | Inteligencia Industrial SCADA, BMS, AIIoT', + }, + description: + 'Sistema de gestión inteligente LogOS. Soluciones avanzadas de SCADA, BMS y AIIoT para mejorar la eficiencia operacional en industrias y ciudades inteligentes.', +}; export default function Home() { - const theme = useTheme(); - - return ( - - - - - - - - - - - - - {/* Spacer para el efecto de revelación del footer */} - - - ); + return ; } diff --git a/src/app/precios/page.tsx b/src/app/precios/page.tsx index cd04e98..b70e1d9 100644 --- a/src/app/precios/page.tsx +++ b/src/app/precios/page.tsx @@ -1,15 +1,22 @@ -import { Container, Typography } from "@mui/material"; +import type { Metadata } from 'next'; +import { Container, Typography } from '@mui/material'; + +export const metadata: Metadata = { + title: 'Planes y Precios', + description: + 'Encuentra el plan que mejor se adapte a tus necesidades industriales. Precios competitivos para soluciones SCADA y BMS de última generación.', +}; export default function Precios() { - return ( - - - Precios - - - Esta página está en construcción. Pronto encontrarás nuestros planes y - tarifas. - - - ); + return ( + + + Precios + + + Esta página está en construcción. Pronto encontrarás nuestros planes y + tarifas. + + + ); } diff --git a/src/app/soluciones/page.tsx b/src/app/soluciones/page.tsx index 7a1195d..960c716 100644 --- a/src/app/soluciones/page.tsx +++ b/src/app/soluciones/page.tsx @@ -1,15 +1,22 @@ -import { Container, Typography } from "@mui/material"; +import type { Metadata } from 'next'; +import { Container, Typography } from '@mui/material'; + +export const metadata: Metadata = { + title: 'Nuestras Soluciones', + description: + 'Explora nuestras soluciones Edge y Cloud para el control y monitorización inteligente de activos.', +}; export default function Soluciones() { - return ( - - - Soluciones - - - Esta página está en construcción. Pronto verás todos nuestros servicios - Edge y Cloud. - - - ); + return ( + + + Soluciones + + + Esta página está en construcción. Pronto verás todos nuestros servicios + Edge y Cloud. + + + ); } diff --git a/src/app/terms/page.tsx b/src/app/terms/page.tsx index 9320a20..f1314dc 100644 --- a/src/app/terms/page.tsx +++ b/src/app/terms/page.tsx @@ -1,181 +1,181 @@ -"use client"; +'use client'; -import Link from "next/link"; -import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import Link from 'next/link'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { - Box, - Container, - Typography, - Stack, - Button, - useTheme, - alpha, -} from "@mui/material"; + Box, + Container, + Typography, + Stack, + Button, + useTheme, + alpha, +} from '@mui/material'; export default function Terms() { - const theme = useTheme(); + const theme = useTheme(); - const sections = [ - { - title: "Aceptación de los Términos", - content: - "Al utilizar el software Logos, desarrollado por ByLogos SpA, el usuario acepta estos Términos y Condiciones en su totalidad. Si no está de acuerdo, no debe utilizar la plataforma ni los servicios asociados.", - }, - { - title: "Licencia de Uso", - list: [ - "Logos otorga al usuario una licencia limitada, no exclusiva e intransferible para utilizar el software conforme a estos Términos.", - "El software y todos sus componentes, incluidos algoritmos de IA, interfaces, documentación y datos generados, son propiedad exclusiva de ByLogos SpA.", - "Está prohibida la copia, modificación, distribución o sublicencia del software sin autorización explícita de ByLogos SpA.", - ], - }, - { - title: "Uso del Software", - list: [ - "El usuario se compromete a utilizar Logos únicamente para fines legales y conforme a las instrucciones de operación.", - "Queda prohibido interferir con el funcionamiento de Logos, intentar acceder a sistemas no autorizados o manipular datos de terceros.", - "La ejecución de Logos en entornos Edge Computing garantiza que los datos permanezcan locales; cualquier transmisión de información se realizará conforme a la política de privacidad vigente.", - ], - }, - { - title: "Responsabilidad y Garantías", - list: [ - "Logos se proporciona “tal cual” y no garantiza resultados específicos de optimización de consumo eléctrico o predicciones de IA.", - "ByLogos SpA no será responsable por daños directos, indirectos, incidentales, consecuentes o pérdidas derivadas del uso del software.", - "El usuario es responsable de implementar medidas de seguridad adicionales según sus necesidades industriales y legales.", - ], - }, - { - title: "Actualizaciones y Modificaciones", - list: [ - "ByLogos SpA puede actualizar Logos en cualquier momento, incluyendo nuevas funcionalidades, mejoras de seguridad y correcciones de errores.", - "El usuario acepta que las actualizaciones pueden aplicarse automáticamente y sin previo aviso.", - ], - }, - { - title: "Propiedad Intelectual", - list: [ - "Todos los derechos de propiedad intelectual relacionados con Logos, sus algoritmos, interfaces gráficas, documentación y contenido generado por la IA pertenecen exclusivamente a ByLogos SpA.", - "El uso no autorizado, reproducción, distribución o ingeniería inversa de cualquier componente está prohibido.", - ], - }, - { - title: "Terminación", - list: [ - "ByLogos SpA puede suspender o cancelar el acceso al software en caso de incumplimiento de estos Términos.", - "Tras la terminación, el usuario deberá eliminar todas las copias del software y cualquier dato derivado de él, salvo que la ley exija su retención.", - ], - }, - { - title: "Contacto", - customContent: ( - - Consultas sobre estos Términos pueden enviarse a:{" "} - - - ), - }, - ]; + const sections = [ + { + title: 'Aceptación de los Términos', + content: + 'Al utilizar el software Logos, desarrollado por ByLogos SpA, el usuario acepta estos Términos y Condiciones en su totalidad. Si no está de acuerdo, no debe utilizar la plataforma ni los servicios asociados.', + }, + { + title: 'Licencia de Uso', + list: [ + 'Logos otorga al usuario una licencia limitada, no exclusiva e intransferible para utilizar el software conforme a estos Términos.', + 'El software y todos sus componentes, incluidos algoritmos de IA, interfaces, documentación y datos generados, son propiedad exclusiva de ByLogos SpA.', + 'Está prohibida la copia, modificación, distribución o sublicencia del software sin autorización explícita de ByLogos SpA.', + ], + }, + { + title: 'Uso del Software', + list: [ + 'El usuario se compromete a utilizar Logos únicamente para fines legales y conforme a las instrucciones de operación.', + 'Queda prohibido interferir con el funcionamiento de Logos, intentar acceder a sistemas no autorizados o manipular datos de terceros.', + 'La ejecución de Logos en entornos Edge Computing garantiza que los datos permanezcan locales; cualquier transmisión de información se realizará conforme a la política de privacidad vigente.', + ], + }, + { + title: 'Responsabilidad y Garantías', + list: [ + 'Logos se proporciona “tal cual” y no garantiza resultados específicos de optimización de consumo eléctrico o predicciones de IA.', + 'ByLogos SpA no será responsable por daños directos, indirectos, incidentales, consecuentes o pérdidas derivadas del uso del software.', + 'El usuario es responsable de implementar medidas de seguridad adicionales según sus necesidades industriales y legales.', + ], + }, + { + title: 'Actualizaciones y Modificaciones', + list: [ + 'ByLogos SpA puede actualizar Logos en cualquier momento, incluyendo nuevas funcionalidades, mejoras de seguridad y correcciones de errores.', + 'El usuario acepta que las actualizaciones pueden aplicarse automáticamente y sin previo aviso.', + ], + }, + { + title: 'Propiedad Intelectual', + list: [ + 'Todos los derechos de propiedad intelectual relacionados con Logos, sus algoritmos, interfaces gráficas, documentación y contenido generado por la IA pertenecen exclusivamente a ByLogos SpA.', + 'El uso no autorizado, reproducción, distribución o ingeniería inversa de cualquier componente está prohibido.', + ], + }, + { + title: 'Terminación', + list: [ + 'ByLogos SpA puede suspender o cancelar el acceso al software en caso de incumplimiento de estos Términos.', + 'Tras la terminación, el usuario deberá eliminar todas las copias del software y cualquier dato derivado de él, salvo que la ley exija su retención.', + ], + }, + { + title: 'Contacto', + customContent: ( + + Consultas sobre estos Términos pueden enviarse a:{' '} + + + ), + }, + ]; - return ( - - - + return ( + + + - - Términos y Condiciones - + + Términos y Condiciones + - - {sections.map((section, index) => ( - - - {section.title} - + + {sections.map((section, index) => ( + + + {section.title} + - {section.content && ( - - {section.content} - - )} + {section.content && ( + + {section.content} + + )} - {section.list && ( - - {section.list.map((item, i) => ( - - {item} - - ))} - - )} + {section.list && ( + + {section.list.map((item, i) => ( + + {item} + + ))} + + )} - {section.customContent} - - ))} - - - - ); + {section.customContent} + + ))} + + + + ); } diff --git a/src/components/MdxContent.tsx b/src/components/MdxContent.tsx index 6116f8e..957a45a 100644 --- a/src/components/MdxContent.tsx +++ b/src/components/MdxContent.tsx @@ -1,11 +1,18 @@ -import * as runtime from 'react/jsx-runtime' +import React, { useMemo } from 'react'; +import * as runtime from 'react/jsx-runtime'; -const useMDX = (code: string) => { - const fn = new Function(code) - return fn({ ...runtime }).default -} +const evaluateMDX = (code: string) => { + const fn = new Function(code); + return fn({ ...runtime }).default; +}; -export const MDXContent = ({ code, components }: { code: string, components?: any }) => { - const Component = useMDX(code) - return -} +export const MDXContent = ({ + code, + components, +}: { + code: string; + components?: any; +}) => { + const MDXComponent = useMemo(() => evaluateMDX(code), [code]); + return React.createElement(MDXComponent, { components }); +}; diff --git a/src/components/layout/LandingPage.tsx b/src/components/layout/LandingPage.tsx new file mode 100644 index 0000000..3969905 --- /dev/null +++ b/src/components/layout/LandingPage.tsx @@ -0,0 +1,41 @@ +'use client'; + +import { Box } from '@mui/material'; +import { Hero } from '@/sections/landing/Hero'; +import { Features } from '@/sections/landing/Features'; +import { HardwareAlternatives } from '@/sections/landing/HardwareAlternatives'; +import { Stack } from '@/sections/landing/Stack'; +import { Testimonials } from '@/sections/landing/Testimonials'; +import { Newsletter } from '@/sections/landing/Newsletter'; + +export function LandingPage() { + return ( + + + + + + + + + + + + + {/* Spacer para el efecto de revelación del footer */} + + + ); +} diff --git a/src/sections/chat/Chat.tsx b/src/sections/chat/Chat.tsx index ba4cb55..7dbd9d7 100644 --- a/src/sections/chat/Chat.tsx +++ b/src/sections/chat/Chat.tsx @@ -1,424 +1,426 @@ -"use client"; -import { useState, useEffect, useRef } from "react"; +'use client'; +import { useState, useEffect, useRef } from 'react'; // MUI Icons - Outlined version -import SendOutlinedIcon from "@mui/icons-material/SendOutlined"; -import ArrowBackOutlinedIcon from "@mui/icons-material/ArrowBackOutlined"; -import PersonOutlineOutlinedIcon from "@mui/icons-material/PersonOutlineOutlined"; +import SendOutlinedIcon from '@mui/icons-material/SendOutlined'; +import ArrowBackOutlinedIcon from '@mui/icons-material/ArrowBackOutlined'; +import PersonOutlineOutlinedIcon from '@mui/icons-material/PersonOutlineOutlined'; -import ReactMarkdown from "react-markdown"; -import { useChatContext } from "@/providers/ChatProvider"; -import Link from "next/link"; -import Image from "next/image"; -import Logos from "@public/icon.svg"; -import { motion } from "framer-motion"; +import ReactMarkdown from 'react-markdown'; +import { useChatContext } from '@/providers/ChatProvider'; +import Link from 'next/link'; +import Image from 'next/image'; +import Logos from '@public/icon.svg'; +import { motion } from 'framer-motion'; import { - Box, - Button, - TextField, - Typography, - alpha, - useTheme, - IconButton, -} from "@mui/material"; -import { CopyButton } from "@/components/CopyButton"; + Box, + Button, + TextField, + Typography, + alpha, + useTheme, + IconButton, +} from '@mui/material'; +import { CopyButton } from '@/components/CopyButton'; const Chat = () => { - const theme = useTheme(); - const [input, setInput] = useState(""); - const { messages, sendMessage, status } = useChatContext(); - const isLoading = status === "streaming" || status === "submitted"; + const theme = useTheme(); + const [input, setInput] = useState(''); + const { messages, sendMessage, status } = useChatContext(); + const isLoading = status === 'streaming' || status === 'submitted'; - const messagesEndRef = useRef(null); + const messagesEndRef = useRef(null); - const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); - }; + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }; - useEffect(() => { - scrollToBottom(); - }, [messages, messages[messages.length - 1]?.parts]); + const lastMessageParts = messages[messages.length - 1]?.parts; - const handleSend = () => { - if (!input.trim() || isLoading) return; + useEffect(() => { + scrollToBottom(); + }, [messages, lastMessageParts]); - sendMessage({ text: input }) - .then(() => setInput("")) - .catch((error: any) => - console.error("❌ [Server Action] Error in chat.tsx:", error), - ); - }; + const handleSend = () => { + if (!input.trim() || isLoading) return; - return ( - - {/* Main Chat Area */} - - {/* Header */} - - - - - - Volver al inicio - - - - - Logos Logo - - + sendMessage({ text: input }) + .then(() => setInput('')) + .catch((error: any) => + console.error('❌ [Server Action] Error in chat.tsx:', error), + ); + }; - {messages.length === 0 && ( - - - - Chatbot - {" "} - - de LogOS - - - - ¡Pregunta lo que desees saber sobre LogOS! - - - )} + return ( + + {/* Main Chat Area */} + + {/* Header */} + + + + + + Volver al inicio + + + + + Logos Logo + + - {/* Messages */} - - - - {messages.map((message: any, index: number) => ( - - {message.role !== "user" && ( - - LogOS - - )} - - - ( -