diff --git a/app/components/ChatBot.js b/app/components/ChatBot.js index 1525d04..12913e3 100644 --- a/app/components/ChatBot.js +++ b/app/components/ChatBot.js @@ -1,65 +1,59 @@ -import { useState, useEffect } from "react"; +import { useState } from "react"; import { askAI } from "../utils/askAI"; -export default function ChatBot() { +export default function ChatBot({ onClose }) { const [question, setQuestion] = useState(""); const [messages, setMessages] = useState([]); - - // Afficher le message d'introduction une seule fois au chargement du chatbot - useEffect(() => { - const introMessage = { - sender: "bot", - text: "Bonjour ! Je suis GrasBot, une intelligence artificielle locale basée sur Mistral 7B et hébergée sur un serveur Windows. Je suis là pour répondre à vos questions. Posez-moi votre question ! 😊" - }; - setMessages([introMessage]); - }, []); + const [isWaiting, setIsWaiting] = useState(false); const handleAsk = async () => { - if (!question.trim()) return; // Évite d'envoyer un message vide + if (!question.trim()) return; const userMessage = { sender: "user", text: question }; - setMessages((prevMessages) => [...prevMessages, userMessage]); // Ajoute le message utilisateur + setMessages([...messages, userMessage]); - setQuestion(""); // Réinitialise le champ après l'envoi + setQuestion(""); + setIsWaiting(true); try { const botResponse = await askAI(question); const botMessage = { sender: "bot", text: botResponse }; - setMessages((prevMessages) => [...prevMessages, botMessage]); // Ajoute la réponse du bot + setMessages((prevMessages) => [...prevMessages, botMessage]); } catch (error) { - setMessages((prevMessages) => [ - ...prevMessages, - { sender: "bot", text: "❌ Erreur de réponse. Réessayez plus tard." } - ]); + setMessages([...messages, { sender: "bot", text: "❌ Erreur de réponse. Réessayez plus tard." }]); + } finally { + setIsWaiting(false); } }; return (
- {/* En-tête du chatbot */}
- 💬 GrasBot - + 💬 GrasBot +
- {/* Zone d'affichage des messages */}
{messages.map((msg, index) => (
{msg.text}
))} + {isWaiting && ( +
+ wait... +
+ )}
- {/* Zone d'entrée utilisateur */}
setQuestion(e.target.value)} @@ -73,4 +67,4 @@ export default function ChatBot() {
); -} +} \ No newline at end of file diff --git a/app/components/ContentSectionCompetences.tsx b/app/components/ContentSectionCompetences.tsx index a5106e4..3dfbebe 100644 --- a/app/components/ContentSectionCompetences.tsx +++ b/app/components/ContentSectionCompetences.tsx @@ -148,7 +148,7 @@ export default function ContentSectionCompetences({ {/* 🔥 Chatbot affiché uniquement si isChatbotOpen est vrai */} {isChatbotOpen && (
- + setIsChatbotOpen(false)} />
)} diff --git a/app/globals.css b/app/globals.css index 0f75502..ae2bd46 100644 --- a/app/globals.css +++ b/app/globals.css @@ -40,3 +40,21 @@ body { .animate-fade-in { animation: fade-in 0.5s ease-out; /* Animation de 0.5s avec une courbe de transition */ } + +@keyframes blink { + 0% { opacity: 0; } + 50% { opacity: 1; } + 100% { opacity: 0; } +} + +.wait-animation .dot-1 { + animation: blink 1s infinite 0s; +} + +.wait-animation .dot-2 { + animation: blink 1s infinite 0.2s; +} + +.wait-animation .dot-3 { + animation: blink 1s infinite 0.4s; +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 35dc329..f07eccf 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,15 +1,31 @@ "use client"; -import React from "react"; +import React, { useEffect, useState } from "react"; import Footer from "./components/Footer"; import "./assets/main.css"; import NavLink from "./components/NavLink"; export default function RootLayout({ children }) { + const [visitCount, setVisitCount] = useState(0); + + useEffect(() => { + // Récupère le compteur de visites depuis localStorage + const visits = localStorage.getItem("visitCount"); + const newVisitCount = visits ? parseInt(visits) + 1 : 1; + localStorage.setItem("visitCount", newVisitCount.toString()); + setVisitCount(newVisitCount); + }, []); + return ( -
+
+ {/* Cercles animés */} +
+
+
+
+

Portfolio Gras-Calvet Fernand

@@ -25,13 +41,18 @@ export default function RootLayout({ children }) {
{/* Ne pas forcer de largeur ici, chaque page gère son `main` */} -
+
{children}
); -} +} \ No newline at end of file diff --git a/llm-api/__pycache__/api.cpython-313.pyc b/llm-api/__pycache__/api.cpython-313.pyc index ffddb41..05807ee 100644 Binary files a/llm-api/__pycache__/api.cpython-313.pyc and b/llm-api/__pycache__/api.cpython-313.pyc differ