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}
+
+ {/* Affichage du compteur de visites */}
+
+ NV : {visitCount}
+
);
-}
+}
\ 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