peux tu essayer de rempalcer la barre vertical par une barre latéral minimaliste et impeu deétaché comportant un bouton pour le home un bouton pour voires les conversation un bouton pour voir qui veut nours fais des demandes pour nous parler et un bouton recherche je veux aussi que tu donne un style d'écrocher par exemple la possibilité de cliquer sur un profile pour récupperer sa bio ainsi que la derneir case qui permet dêtre le bouton mais pour la bio:
// Chat.jsx
import React, { useEffect, useState, useContext, useRef } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import axios from '../../utils/api';
import { AuthContext } from '../../contexts/AuthContext';
import { IoSend, IoMenu, IoSearch, IoEllipsisVertical, IoAdd } from 'react-icons/io5';
import styles from './Chat.module.css';

// Importer le composant Modal
import CreateConversationModal from './CreateConversationModal';

function Chat() {
  const { conversationId } = useParams();
  const { user } = useContext(AuthContext);
  const navigate = useNavigate();
  const [conversations, setConversations] = useState([]);
  const [currentConversation, setCurrentConversation] = useState(null);
  const [message, setMessage] = useState('');
  const [searchQuery, setSearchQuery] = useState('');
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
  const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); // État pour le modal
  const messagesEndRef = useRef(null);

  // Animation variants
  const sidebarVariants = {
    hidden: { x: -300, opacity: 0 },
    visible: { x: 0, opacity: 1, transition: { type: "spring", damping: 25 } }
  };

  const messageVariants = {
    hidden: { opacity: 0, y: 20 },
    visible: { opacity: 1, y: 0 },
    exit: { opacity: 0, x: -100 }
  };

  useEffect(() => {
    fetchConversations();
    const interval = setInterval(fetchConversations, 5000);
    return () => clearInterval(interval);
  }, []);

  useEffect(() => {
    if (conversationId) {
      fetchCurrentConversation();
      const interval = setInterval(fetchCurrentConversation, 3000);
      return () => clearInterval(interval);
    } else {
      setCurrentConversation(null); // Réinitialiser si pas de conversation sélectionnée
    }
  }, [conversationId]);

  useEffect(() => {
    scrollToBottom();
  }, [currentConversation?.messages]);

  const fetchConversations = async () => {
    try {
      const response = await axios.get('/conversations');
      setConversations(response.data);
    } catch (error) {
      console.error('Error fetching conversations:', error);
    }
  };

  const fetchCurrentConversation = async () => {
    try {
      const response = await axios.get(`/conversations/${conversationId}`);
      setCurrentConversation({
        ...response.data,
        messages: response.data.messages || []
      });
    } catch (error) {
      console.error('Error fetching conversation:', error);
    }
  };

  const handleSendMessage = async (e) => {
    e.preventDefault();
    if (!message.trim()) return;

    try {
      const newMessage = {
        content: message,
        sender: user.id,
        timestamp: new Date().toISOString()
      };

      await axios.post(`/conversations/${conversationId}/messages`, newMessage);
      setMessage('');
      fetchCurrentConversation();
    } catch (error) {
      console.error('Error sending message:', error);
    }
  };

  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  };

  const filteredConversations = conversations.filter(conv => {
    const conversationName = conv.name || '';
    return conversationName.toLowerCase().includes(searchQuery.toLowerCase());
  });

  const formatTime = (timestamp) => {
    return new Date(timestamp).toLocaleTimeString([], {
      hour: '2-digit',
      minute: '2-digit'
    });
  };

  // Fonction pour ouvrir le modal de création
  const openCreateModal = () => {
    setIsCreateModalOpen(true);
  };

  // Fonction pour fermer le modal de création
  const closeCreateModal = () => {
    setIsCreateModalOpen(false);
  };

  // Fonction pour créer une nouvelle conversation
  const handleCreateConversation = async (conversationData) => {
    try {
      const response = await axios.post('/conversations', conversationData);
      // Actualiser la liste des conversations
      fetchConversations();
      closeCreateModal();
      // Naviguer vers la nouvelle conversation
      navigate(`/chat/${response.data.id}`);
    } catch (error) {
      console.error('Error creating conversation:', error);
    }
  };

  return (
    <div className={styles.container}>
      {/* Sidebar */}
      <motion.aside
        className={`${styles.sidebar} ${isMobileMenuOpen ? styles.sidebarOpen : ''}`}
        variants={sidebarVariants}
        initial="hidden"
        animate="visible"
      >
        <div className={styles.sidebarHeader}>
          <motion.div
            className={styles.userProfile}
            whileHover={{ scale: 1.05 }}
            whileTap={{ scale: 0.95 }}
            onClick={() => navigate('/profile')}
          >
            <div className={styles.userAvatar}>{user.name[0]}</div>
            <h3>{user.name}</h3>
          </motion.div>
        </div>

        <div className={styles.searchContainer}>
          <IoSearch className={styles.searchIcon} />
          <input
            type="text"
            placeholder="Rechercher une conversation..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            className={styles.searchInput}
          />
        </div>

        <div className={styles.newConversationButton}>
          <button onClick={openCreateModal}>
            <IoAdd /> Nouvelle Conversation
          </button>
        </div>

        <div className={styles.conversationsList}>
          <AnimatePresence>
            {filteredConversations.map((conv) => (
              <motion.div
                key={conv.id}
                className={`${styles.conversationItem} ${
                  conv.id === conversationId ? styles.active : ''
                }`}
                variants={messageVariants}
                initial="hidden"
                animate="visible"
                exit="exit"
                whileHover={{ x: 5 }}
                onClick={() => {
                  navigate(`/chat/${conv.id}`);
                  setIsMobileMenuOpen(false);
                }}
              >
                <div className={styles.conversationAvatar}>
                  {(conv.name || '?')[0]}
                </div>
                <div className={styles.conversationInfo}>
                  <h4>{conv.name || 'Conversation sans nom'}</h4>
                  <p>{conv.lastMessage?.content || 'Nouvelle conversation'}</p>
                </div>
                {conv.unreadCount > 0 && (
                  <div className={styles.unreadBadge}>
                    {conv.unreadCount}
                  </div>
                )}
              </motion.div>
            ))}
          </AnimatePresence>
        </div>
      </motion.aside>

      {/* Main Chat Area */}
      <main className={styles.chatArea}>
        {currentConversation ? (
          <>
            <header className={styles.chatHeader}>
              <button
                className={styles.menuButton}
                onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
              >
                <IoMenu />
              </button>
              <div className={styles.chatInfo}>
                <h2>{currentConversation.name}</h2>
                <span>{currentConversation.participants.length} participants</span>
              </div>
              <button className={styles.optionsButton}>
                <IoEllipsisVertical />
              </button>
            </header>

            <div className={styles.messagesContainer}>
              <AnimatePresence>
                {(currentConversation.messages || []).map((msg, index) => (
                  <motion.div
                    key={index}
                    className={`${styles.message} ${
                      msg.sender === user.id ? styles.sent : styles.received
                    }`}
                    variants={messageVariants}
                    initial="hidden"
                    animate="visible"
                    exit="exit"
                  >
                    <p>{msg.content}</p>
                    <span className={styles.timestamp}>
                      {formatTime(msg.timestamp)}
                    </span>
                  </motion.div>
                ))}
              </AnimatePresence>
              <div ref={messagesEndRef} />
            </div>

            <form onSubmit={handleSendMessage} className={styles.messageForm}>
              <motion.input
                type="text"
                value={message}
                onChange={(e) => setMessage(e.target.value)}
                placeholder="Écrivez votre message..."
                whileFocus={{ scale: 1.01 }}
              />
              <motion.button
                type="submit"
                disabled={!message.trim()}
                whileHover={{ scale: 1.05 }}
                whileTap={{ scale: 0.95 }}
              >
                <IoSend />
              </motion.button>
            </form>
          </>
        ) : (
          <motion.div
            className={styles.welcomeScreen}
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.5 }}
          >
            <div className={styles.welcomeContent}>
              <h2>Bienvenue sur votre messagerie</h2>
              <p>Sélectionnez une conversation pour commencer à discuter</p>
            </div>
          </motion.div>
        )}
      </main>

      {/* Mobile Overlay */}
      {isMobileMenuOpen && (
        <motion.div
          className={styles.overlay}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          onClick={() => setIsMobileMenuOpen(false)}
        />
      )}

      {/* Modal pour la création de conversation */}
      {isCreateModalOpen && (
        <CreateConversationModal
          onClose={closeCreateModal}
          onCreate={handleCreateConversation}
        />
      )}
    </div>
  );
}

export default Chat;

// CreateConversationModal.jsx
import React, { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import styles from './CreateConversationModal.module.css';
import axios from '../../utils/api';

function CreateConversationModal({ onClose, onCreate }) {
  const [name, setName] = useState('');
  const [participants, setParticipants] = useState([]);
  const [allUsers, setAllUsers] = useState([]);
  const [searchUser, setSearchUser] = useState('');

  useEffect(() => {
    fetchAllUsers();
  }, []);

  const fetchAllUsers = async () => {
    try {
      const response = await axios.get('/users');
      setAllUsers(response.data);
    } catch (error) {
      console.error('Error fetching users:', error);
    }
  };

  const handleAddParticipant = (user) => {
    if (!participants.find(p => p.id === user.id)) {
      setParticipants([...participants, user]);
    }
  };

  const handleRemoveParticipant = (user) => {
    setParticipants(participants.filter(p => p.id !== user.id));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!name.trim() || participants.length === 0) return;

    const participantIds = participants.map(p => p.id);

    const conversationData = {
      name: name.trim(),
      participants: participantIds
    };

    onCreate(conversationData);
  };

  const filteredUsers = allUsers.filter(user =>
    user.name.toLowerCase().includes(searchUser.toLowerCase())
  );

  return (
    <div className={styles.overlay}>
      <motion.div
        className={styles.modal}
        initial={{ opacity: 0, scale: 0.9 }}
        animate={{ opacity: 1, scale: 1 }}
      >
        <h2>Créer une nouvelle conversation</h2>
        <form onSubmit={handleSubmit}>
          <div className={styles.inputGroup}>
            <label>Nom de la conversation</label>
            <input
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
              required
            />
          </div>

          <div className={styles.inputGroup}>
            <label>Ajouter des participants</label>
            <input
              type="text"
              placeholder="Rechercher des utilisateurs..."
              value={searchUser}
              onChange={(e) => setSearchUser(e.target.value)}
            />
            <div className={styles.usersList}>
              {filteredUsers.map(user => (
                <div key={user.id} className={styles.userItem}>
                  <span>{user.name}</span>
                  <button type="button" onClick={() => handleAddParticipant(user)}>
                    Ajouter
                  </button>
                </div>
              ))}
            </div>
          </div>

          <div className={styles.participants}>
            <h3>Participants :</h3>
            {participants.map(user => (
              <div key={user.id} className={styles.participantItem}>
                <span>{user.name}</span>
                <button type="button" onClick={() => handleRemoveParticipant(user)}>
                  Retirer
                </button>
              </div>
            ))}
          </div>

          <div className={styles.buttonGroup}>
            <button type="button" onClick={onClose} className={styles.cancelButton}>
              Annuler
            </button>
            <button type="submit" className={styles.createButton}>
              Créer
            </button>
          </div>
        </form>
      </motion.div>
    </div>
  );
}

export default CreateConversationModal;

/* Chat.module.css */

.container {
  min-height: 100vh;
  width: 100%;
  background: #0a0a0a;
  display: flex;
  position: relative;
  overflow: hidden;
}

/* Arrière-plan avec gradients animés */
.background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.gradient1, .gradient2, .gradient3 {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
}

.gradient1 {
  width: 50%;
  height: 50%;
  background: rgba(255, 65, 108, 0.15);
  top: -10%;
  left: -10%;
  animation: moveGradient1 15s infinite alternate;
}

.gradient2 {
  width: 60%;
  height: 60%;
  background: rgba(59, 130, 246, 0.15);
  top: 30%;
  right: -20%;
  animation: moveGradient2 20s infinite alternate;
}

.gradient3 {
  width: 40%;
  height: 40%;
  background: rgba(46, 213, 115, 0.15);
  bottom: -10%;
  left: 20%;
  animation: moveGradient3 17s infinite alternate;
}

/* Sidebar avec effet Glassmorphism */
.sidebar {
  width: 300px;
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(10px);
  border-right: 1px solid rgba(255, 255, 255, 0.1);
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  transition: all 0.3s ease;
}

.sidebarOpen {
  transform: translateX(0);
}

.sidebarHeader {
  padding: 2rem;
  text-align: center;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.userProfile {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.userAvatar {
  width: 60px;
  height: 60px;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  color: white;
  border-radius: 50%;
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 1rem;
  transition: transform 0.3s ease;
}

.userAvatar:hover {
  transform: scale(1.05);
}

.userProfile h3 {
  color: white;
  font-size: 1.5rem;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.searchContainer {
  padding: 1rem 2rem;
  display: flex;
  align-items: center;
  position: relative;
}

.searchIcon {
  position: absolute;
  left: 2.5rem;
  font-size: 1.2rem;
  color: rgba(255, 255, 255, 0.5);
}

.searchInput {
  width: 100%;
  padding: 0.5rem 1rem 0.5rem 2.5rem;
  background: rgba(255, 255, 255, 0.05);
  border: none;
  border-radius: 20px;
  color: white;
  font-size: 1rem;
  transition: all 0.3s ease;
}

.searchInput::placeholder {
  color: rgba(255, 255, 255, 0.5);
}

.searchInput:focus {
  outline: none;
  border-color: #FF416C;
  box-shadow: 0 0 10px rgba(255, 65, 108, 0.2);
}

.conversationsList {
  flex-grow: 1;
  overflow-y: auto;
  padding: 0 1rem;
}

.conversationItem {
  display: flex;
  align-items: center;
  padding: 1rem;
  border-radius: 10px;
  margin-bottom: 0.5rem;
  cursor: pointer;
  transition: background 0.3s ease;
}

.conversationItem:hover {
  background: rgba(255, 255, 255, 0.1);
}

.active {
  background: rgba(255, 255, 255, 0.15);
}

.conversationAvatar {
  width: 50px;
  height: 50px;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  color: white;
  border-radius: 50%;
  font-size: 1.3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 1rem;
}

.conversationInfo h4 {
  color: white;
  font-size: 1rem;
  margin-bottom: 0.3rem;
}

.conversationInfo p {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9rem;
}

.unreadBadge {
  background: #FF416C;
  color: white;
  border-radius: 10px;
  padding: 0.2rem 0.5rem;
  font-size: 0.8rem;
  margin-left: auto;
}

/* Zone principale de chat */
.chatArea {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  position: relative;
}

/* En-tête de chat */
.chatHeader {
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(10px);
  padding: 1rem 2rem;
  display: flex;
  align-items: center;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.menuButton, .optionsButton {
  background: none;
  border: none;
  color: white;
  font-size: 1.5rem;
  cursor: pointer;
  transition: transform 0.3s ease;
}

.menuButton:hover, .optionsButton:hover {
  transform: scale(1.1);
}

.menuButton:focus, .optionsButton:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 65, 108, 0.3);
}

.chatInfo {
  flex-grow: 1;
  text-align: center;
}

.chatInfo h2 {
  color: white;
  font-size: 1.5rem;
}

.chatInfo span {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9rem;
}

/* Conteneur des messages */
.messagesContainer {
  flex-grow: 1;
  overflow-y: auto;
  padding: 1rem 2rem;
  background: #0a0a0a;
  position: relative;
}

.message {
  max-width: 70%;
  margin-bottom: 1rem;
  padding: 0.8rem 1rem;
  border-radius: 10px;
  position: relative;
  animation: fadeIn 0.5s ease-out;
}

.sent {
  margin-left: auto;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  color: white;
}

.received {
  margin-right: auto;
  background: rgba(255, 255, 255, 0.1);
  color: white;
}

.message p {
  margin: 0;
}

.timestamp {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.7);
  text-align: right;
}

/* Formulaire pour envoyer un message */
.messageForm {
  display: flex;
  padding: 1rem 2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(10px);
}

.messageForm input[type="text"] {
  flex-grow: 1;
  padding: 0.8rem 1rem;
  border: none;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.1);
  color: white;
  font-size: 1rem;
  transition: all 0.3s ease;
}

.messageForm input[type="text"]::placeholder {
  color: rgba(255, 255, 255, 0.7);
}

.messageForm input[type="text"]:focus {
  outline: none;
  border-color: #FF416C;
  box-shadow: 0 0 10px rgba(255, 65, 108, 0.2);
}

.messageForm button {
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  border: none;
  border-radius: 50%;
  color: white;
  width: 50px;
  height: 50px;
  margin-left: 1rem;
  cursor: pointer;
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.messageForm button:hover {
  box-shadow: 0 5px 15px rgba(255, 65, 108, 0.4);
}

.messageForm button:active {
  transform: scale(0.95);
}

.messageForm button:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 65, 108, 0.3);
}

/* Écran d'accueil */
.welcomeScreen {
  flex-grow: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  text-align: center;
  animation: fadeIn 0.6s ease-out;
}

.welcomeContent h2 {
  color: white;
  font-size: 2rem;
  margin-bottom: 1rem;
}

.welcomeContent p {
  color: rgba(255, 255, 255, 0.7);
  font-size: 1rem;
}

/* Overlay pour le menu mobile */
.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  z-index: 2;
}

/* Animations */
@keyframes moveGradient1 {
  0% { transform: translate(0, 0); }
  100% { transform: translate(100px, 50px); }
}

@keyframes moveGradient2 {
  0% { transform: translate(0, 0); }
  100% { transform: translate(-100px, -50px); }
}

@keyframes moveGradient3 {
  0% { transform: translate(0, 0); }
  100% { transform: translate(50px, -100px); }
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Scrollbar personnalisée */
::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(45deg, #FF4B2B, #FF416C);
}

/* Sélection de texte */
::selection {
  background: rgba(255, 65, 108, 0.3);
  color: white;
}

/* Transitions globales */
* {
  transition: all 0.3s ease;
}

/* Responsive Design */
@media (max-width: 768px) {
  .sidebar {
    position: fixed;
    left: -300px;
    top: 0;
    height: 100%;
    z-index: 3;
    transition: transform 0.3s ease;
  }

  .sidebarOpen {
    transform: translateX(300px);
  }

  .chatArea {
    width: 100%;
  }

  .chatHeader .chatInfo h2 {
    font-size: 1.2rem;
  }

  .chatInfo span {
    font-size: 0.8rem;
  }
}

@media (max-width: 480px) {
  .userAvatar {
    width: 50px;
    height: 50px;
    font-size: 1rem;
  }

  .userProfile h3 {
    font-size: 1rem;
  }

  .searchInput {
    font-size: 0.9rem;
  }

  .conversationInfo h4 {
    font-size: 0.9rem;
  }

  .conversationInfo p {
    font-size: 0.8rem;
  }

  .chatHeader {
    padding: 0.5rem 1rem;
  }

  .chatInfo h2 {
    font-size: 1.2rem;
  }

  .messagesContainer {
    padding: 0.5rem 1rem;
  }

  .messageForm {
    padding: 0.5rem 1rem;
  }

  .messageForm input[type="text"] {
    font-size: 0.9rem;
  }

  .messageForm button {
    width: 40px;
    height: 40px;
    font-size: 1.2rem;
  }
}

/* Optimisations de performance */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
/* Chat.module.css */

.newConversationButton {
  padding: 1rem 2rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.newConversationButton button {
  width: 100%;
  padding: 0.8rem 1rem;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  color: white;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  transition: all 0.3s ease;
}

.newConversationButton button:hover {
  box-shadow: 0 5px 15px rgba(255, 65, 108, 0.4);
}

.newConversationButton button:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 65, 108, 0.3);
}

/* CreateConversationModal.module.css */

.overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  
  .modal {
    background: #0a0a0a;
    border-radius: 20px;
    padding: 2rem;
    width: 100%;
    max-width: 500px;
    position: relative;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
  
  .modal h2 {
    color: white;
    margin-bottom: 1.5rem;
  }
  
  .inputGroup {
    margin-bottom: 1.5rem;
  }
  
  .inputGroup label {
    color: white;
    display: block;
    margin-bottom: 0.5rem;
  }
  
  .inputGroup input {
    width: 100%;
    padding: 0.8rem 1rem;
    background: rgba(255, 255, 255, 0.05);
    border: none;
    border-radius: 10px;
    color: white;
    font-size: 1rem;
    transition: all 0.3s ease;
  }
  
  .inputGroup input::placeholder {
    color: rgba(255, 255, 255, 0.7);
  }
  
  .inputGroup input:focus {
    outline: none;
    border-color: #FF416C;
    box-shadow: 0 0 10px rgba(255, 65, 108, 0.2);
  }
  
  .usersList {
    max-height: 150px;
    overflow-y: auto;
    margin-top: 0.5rem;
  }
  
  .userItem {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: rgba(255, 255, 255, 0.05);
    padding: 0.5rem 1rem;
    border-radius: 8px;
    margin-bottom: 0.3rem;
  }
  
  .userItem span {
    color: white;
  }
  
  .userItem button {
    background: #2ed573;
    color: white;
    border: none;
    padding: 0.3rem 0.8rem;
    border-radius: 5px;
    cursor: pointer;
    transition: transform 0.3s ease;
  }
  
  .userItem button:hover {
    transform: scale(1.05);
  }
  
  .participants {
    margin-bottom: 1.5rem;
  }
  
  .participants h3 {
    color: white;
    margin-bottom: 0.5rem;
  }
  
  .participantItem {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: rgba(255, 255, 255, 0.05);
    padding: 0.5rem 1rem;
    border-radius: 8px;
    margin-bottom: 0.3rem;
  }
  
  .participantItem span {
    color: white;
  }
  
  .participantItem button {
    background: #ff4757;
    color: white;
    border: none;
    padding: 0.3rem 0.8rem;
    border-radius: 5px;
    cursor: pointer;
    transition: transform 0.3s ease;
  }
  
  .participantItem button:hover {
    transform: scale(1.05);
  }
  
  .buttonGroup {
    display: flex;
    justify-content: flex-end;
    gap: 1rem;
  }
  
  .cancelButton {
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: none;
    padding: 0.8rem 2rem;
    border-radius: 10px;
    cursor: pointer;
    transition: all 0.3s ease;
  }
  
  .createButton {
    background: linear-gradient(45deg, #FF416C, #FF4B2B);
    color: white;
    border: none;
    padding: 0.8rem 2rem;
    border-radius: 10px;
    cursor: pointer;
    transition: all 0.3s ease;
  }
  
  .cancelButton:hover {
    background: rgba(255, 255, 255, 0.2);
  }
  
  .createButton:hover {
    box-shadow: 0 5px 15px rgba(255, 65, 108, 0.4);
  }
  
  @media (max-width: 480px) {
    .modal {
      padding: 1.5rem;
    }
  
    .inputGroup input {
      font-size: 0.9rem;
    }
  
    .userItem button,
    .participantItem button {
      padding: 0.3rem 0.6rem;
      font-size: 0.9rem;
    }
  
    .cancelButton,
    .createButton {
      padding: 0.6rem 1.5rem;
      font-size: 0.9rem;
    }
  }


// Profile.jsx
import React, { useState, useEffect, useContext } from 'react';
import axios from '../../utils/api';
import { AuthContext } from '../../contexts/AuthContext';
import styles from './Profile.module.css';

function Profile() {
  const { user } = useContext(AuthContext);
  const [bio, setBio] = useState('');
  const [editing, setEditing] = useState(false);

  useEffect(() => {
    const fetchBio = async () => {
      try {
        const response = await axios.get(`/users/${user.name}`);
        setBio(response.data.bio || '');
      } catch (error) {
        console.error('Erreur lors du chargement de la bio:', error);
      }
    };
    fetchBio();
  }, [user.name]);

  const handleSave = async () => {
    try {
      await axios.put('/users/me/bio', { bio });
      setEditing(false);
    } catch (error) {
      console.error('Erreur lors de la sauvegarde de la bio:', error);
    }
  };

  return (
    <div className={styles.container}>
      <div className={styles.background}>
        <div className={styles.gradient1}></div>
        <div className={styles.gradient2}></div>
        <div className={styles.gradient3}></div>
      </div>
      
      <div className={styles.glassOverlay}>
        <div className={styles.profileHeader}>
          <div className={styles.avatarContainer}>
            <div className={styles.avatarRing}></div>
            <div className={styles.avatar}>
              {user.name.charAt(0).toUpperCase()}
            </div>
          </div>
          <h1 className={styles.username}>{user.name}</h1>
          <div className={styles.statusBadge}>En ligne</div>
        </div>

        <div className={styles.bioSection}>
          {editing ? (
            <div className={styles.editContainer}>
              <textarea
                value={bio}
                onChange={(e) => setBio(e.target.value)}
                className={styles.bioInput}
                placeholder="Écrivez quelque chose à propos de vous..."
              />
              <div className={styles.buttonGroup}>
                <button onClick={() => setEditing(false)} className={styles.cancelButton}>
                  Annuler
                </button>
                <button onClick={handleSave} className={styles.saveButton}>
                  Sauvegarder
                </button>
              </div>
            </div>
          ) : (
            <div className={styles.bioContainer}>
              <p className={styles.bioText}>{bio || "Aucune bio définie."}</p>
              <button onClick={() => setEditing(true)} className={styles.editButton}>
                Éditer le profil
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

export default Profile;

/* Profile.module.css */
.container {
    min-height: 100vh;
    width: 100%;
    background: #0a0a0a;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 2rem;
    position: relative;
    overflow: hidden;
  }
  
  .background {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
  }
  
  .gradient1, .gradient2, .gradient3 {
    position: absolute;
    border-radius: 50%;
    filter: blur(80px);
  }
  
  .gradient1 {
    width: 50%;
    height: 50%;
    background: rgba(255, 65, 108, 0.15);
    top: -10%;
    left: -10%;
    animation: moveGradient1 15s infinite alternate;
  }
  
  .gradient2 {
    width: 60%;
    height: 60%;
    background: rgba(59, 130, 246, 0.15);
    top: 30%;
    right: -20%;
    animation: moveGradient2 20s infinite alternate;
  }
  
  .gradient3 {
    width: 40%;
    height: 40%;
    background: rgba(46, 213, 115, 0.15);
    bottom: -10%;
    left: 20%;
    animation: moveGradient3 17s infinite alternate;
  }
  
  .glassOverlay {
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(10px);
    border-radius: 20px;
    padding: 3rem;
    width: 100%;
    max-width: 600px;
    position: relative;
    z-index: 1;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  }
  
  .profileHeader {
    text-align: center;
    margin-bottom: 3rem;
  }
  
  .avatarContainer {
    position: relative;
    width: 120px;
    height: 120px;
    margin: 0 auto 1.5rem;
  }
  
  .avatarRing {
    position: absolute;
    inset: -3px;
    border-radius: 50%;
    background: linear-gradient(45deg, #FF416C, #FF4B2B);
    animation: spin 10s linear infinite;
  }
  
  .avatar {
    position: absolute;
    inset: 3px;
    background: #1a1a1a;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.5rem;
    color: white;
    z-index: 1;
    transition: transform 0.3s ease;
  }
  
  .avatar:hover {
    transform: scale(1.05);
  }
  
  .username {
    font-size: 2rem;
    color: white;
    margin: 1rem 0;
    background: linear-gradient(45deg, #FF416C, #FF4B2B);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: fadeIn 0.6s ease-out;
  }
  
  .statusBadge {
    display: inline-block;
    padding: 0.5rem 1rem;
    background: rgba(46, 213, 115, 0.2);
    color: #2ed573;
    border-radius: 20px;
    font-size: 0.9rem;
    animation: pulse 2s infinite;
  }
  
  .bioSection {
    margin-top: 2rem;
  }
  
  .bioInput {
    width: 100%;
    min-height: 120px;
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    padding: 1rem;
    color: white;
    font-size: 1rem;
    resize: vertical;
    transition: all 0.3s ease;
  }
  
  .bioInput:focus {
    outline: none;
    border-color: #FF416C;
    box-shadow: 0 0 20px rgba(255, 65, 108, 0.2);
  }
  
  .buttonGroup {
    display: flex;
    gap: 1rem;
    margin-top: 1rem;
    justify-content: flex-end;
  }
  
  .editButton, .saveButton {
    padding: 0.8rem 2rem;
    background: linear-gradient(45deg, #FF416C, #FF4B2B);
    color: white;
    border: none;
    border-radius: 10px;
    cursor: pointer;
    transition: all 0.3s ease;
    font-weight: 500;
  }
  
  .cancelButton {
    padding: 0.8rem 2rem;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: none;
    border-radius: 10px;
    cursor: pointer;
    transition: all 0.3s ease;
    font-weight: 500;
  }
  
  .editButton:hover, .saveButton:hover {
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(255, 65, 108, 0.4);
  }
  
  .cancelButton:hover {
    background: rgba(255, 255, 255, 0.2);
    transform: translateY(-2px);
  }
  
  .bioText {
    color: rgba(255, 255, 255, 0.9);
    line-height: 1.6;
    font-size: 1.1rem;
    margin-bottom: 2rem;
  }
  
  @keyframes moveGradient1 {
    0% { transform: translate(0, 0); }
    100% { transform: translate(100px, 50px); }
  }
  
  @keyframes moveGradient2 {
    0% { transform: translate(0, 0); }
    100% { transform: translate(-100px, -50px); }
  }
  
  @keyframes moveGradient3 {
    0% { transform: translate(0, 0); }
    100% { transform: translate(50px, -100px); }
  }
  
  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
  
  @keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
  }
  
  @keyframes pulse {
    0% { box-shadow: 0 0 0 0 rgba(46, 213, 115, 0.4); }
    70% { box-shadow: 0 0 0 10px rgba(46, 213, 115, 0); }
    100% { box-shadow: 0 0 0 0 rgba(46, 213, 115, 0); }
  }
  
  @media (max-width: 768px) {
    .container {
      padding: 1rem;
    }
  
    .glassOverlay {
      padding: 2rem;
    }
  
    .username {
      font-size: 1.8rem;
    }
  
    .avatarContainer {
      width: 100px;
      height: 100px;
    }
  
    .avatar {
      font-size: 2rem;
    }
  
    .buttonGroup {
      flex-direction: column;
    }
  
    .editButton, .saveButton, .cancelButton {
      width: 100%;
    }
  }
  
/* Suite du CSS précédent... */

/* Scrollbar personnalisée */
::-webkit-scrollbar {
    width: 8px;
  }
  
  ::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 4px;
  }
  
  ::-webkit-scrollbar-thumb {
    background: linear-gradient(45deg, #FF416C, #FF4B2B);
    border-radius: 4px;
  }
  
  ::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(45deg, #FF4B2B, #FF416C);
  }
  
  /* Sélection de texte */
  ::selection {
    background: rgba(255, 65, 108, 0.3);
    color: white;
  }
  
  /* Animations supplémentaires */
  .bioContainer {
    animation: fadeIn 0.6s ease-out;
  }
  
  .editContainer {
    animation: fadeIn 0.6s ease-out;
  }
  
  /* Focus styles */
  .bioInput:focus {
    outline: none;
    border-color: #FF416C;
    box-shadow: 0 0 20px rgba(255, 65, 108, 0.2);
    transform: translateY(-2px);
  }
  
  button:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(255, 65, 108, 0.3);
  }
  
  /* Hover effects améliorés */
  .glassOverlay:hover {
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
    transform: translateY(-2px);
    transition: all 0.3s ease;
  }
  
  .avatarContainer:hover .avatarRing {
    animation: spin 5s linear infinite;
  }
  
  /* États actifs des boutons */
  .editButton:active,
  .saveButton:active,
  .cancelButton:active {
    transform: scale(0.98);
  }
  
  /* Transitions globales */
  * {
    transition: all 0.3s ease;
  }
  
  /* Styles pour les grands écrans */
  @media (min-width: 1200px) {
    .glassOverlay {
      max-width: 700px;
      padding: 4rem;
    }
  
    .username {
      font-size: 2.5rem;
    }
  
    .avatarContainer {
      width: 150px;
      height: 150px;
    }
  
    .avatar {
      font-size: 3rem;
    }
  }
  
  /* Styles pour les très petits écrans */
  @media (max-width: 480px) {
    .container {
      padding: 0.5rem;
    }
  
    .glassOverlay {
      padding: 1.5rem;
      border-radius: 15px;
    }
  
    .username {
      font-size: 1.5rem;
    }
  
    .avatarContainer {
      width: 80px;
      height: 80px;
    }
  
    .avatar {
      font-size: 1.8rem;
    }
  
    .statusBadge {
      padding: 0.4rem 0.8rem;
      font-size: 0.8rem;
    }
  
    .bioInput {
      min-height: 100px;
      font-size: 0.9rem;
    }
  
    .editButton,
    .saveButton,
    .cancelButton {
      padding: 0.6rem 1.5rem;
      font-size: 0.9rem;
    }
  }
  
  /* Animations de chargement */
  @keyframes shimmer {
    0% {
      background-position: -468px 0;
    }
    100% {
      background-position: 468px 0;
    }
  }
  
  .loading {
    background: linear-gradient(
      to right,
      rgba(255, 255, 255, 0.1) 8%,
      rgba(255, 255, 255, 0.2) 18%,
      rgba(255, 255, 255, 0.1) 33%
    );
    background-size: 800px 104px;
    animation: shimmer 1.5s linear infinite;
  }
  
  /* Optimisations de performance */
  @media (prefers-reduced-motion: reduce) {
    * {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }

import React, { useContext, useEffect, useState, useRef } from 'react';
import { AuthContext } from '../contexts/AuthContext';
import { useNavigate } from 'react-router-dom';
import styles from './Home.module.css';
import backgroundVideo from './Space.mp4';


function Home() {
  const { user } = useContext(AuthContext);
  const navigate = useNavigate();
  const [scrollProgress, setScrollProgress] = useState(0);
  const sectionsRef = useRef([]);

  const handleLogin = () => navigate('/login');
  const handleSignUp = () => navigate('/signup');
  const handleStartChat = () => navigate('/conversations');

  useEffect(() => {
    const handleScroll = () => {
      // Calculate scroll progress (0 to 1)
      const totalHeight = document.documentElement.scrollHeight - window.innerHeight;
      const progress = window.scrollY / totalHeight;
      setScrollProgress(progress);

      // Check each section for visibility
      sectionsRef.current.forEach(section => {
        if (!section) return;
        const rect = section.getBoundingClientRect();
        const isVisible = rect.top < window.innerHeight * 0.75;
        if (isVisible) {
          section.classList.add(styles.revealed);
        }
      });
    };

    window.addEventListener('scroll', handleScroll);
    handleScroll(); // Initial check

    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  // Progress line width calculation
  const progressWidth = `${scrollProgress * 100}%`;

  return (
    <div className={styles.mainContainer}>
      {/* Progress Line */}
      <div className={styles.progressLine}>
        <div className={styles.progressFill} style={{ width: progressWidth }} />
      </div>

      {/* Background Video */}
      <div className={styles.videoOverlay} style={{ 
        opacity: Math.min(0.4 + scrollProgress * 0.4, 0.8) 
      }} />
      <video
        autoPlay
        muted
        loop
        playsInline
        className={styles.backgroundVideo}
      >
        <source src={backgroundVideo} type="video/mp4" />
      </video>

      {/* Hero Section */}
      <section 
        className={`${styles.section} ${styles.heroSection}`}
        ref={el => sectionsRef.current[0] = el}
      >
        <div className={styles.contentWrapper}>
          {user ? (
            <div className={styles.authenticatedContent}>
              <div className={styles.avatarWrapper}>
                <div className={styles.avatar}>
                  {user.name.charAt(0).toUpperCase()}
                </div>
              </div>
              <h1 className={styles.welcomeText}>
                Ravi de vous revoir, <span className={styles.userName}>{user.name}</span>
              </h1>
              <button className={styles.mainButton} onClick={handleStartChat}>
                Accéder aux conversations
              </button>
            </div>
          ) : (
            <div className={styles.unauthenticatedContent}>
              <h1 className={styles.heroTitle}>Connectez-vous pour commencer</h1>
              <p className={styles.heroText}>
                Rejoignez une communauté dynamique et échangez en temps réel
              </p>
              <div className={styles.actionButtons}>
                <button className={styles.mainButton} onClick={handleLogin}>
                  Se connecter
                </button>
                <button className={styles.mainButton} onClick={handleSignUp}>
                  Créer un compte
                </button>
              </div>
            </div>
          )}
        </div>
      </section>

      {/* Features Section */}
      <section 
        className={`${styles.section} ${styles.featuresSection}`}
        ref={el => sectionsRef.current[1] = el}
      >
        <div className={styles.contentWrapper}>
          <h2 className={styles.sectionTitle}>Nos Fonctionnalités</h2>
          <div className={styles.featuresGrid}>
            {[
              { icon: '🔒', title: 'Sécurisé', desc: 'Protection de bout en bout' },
              { icon: '⚡', title: 'Rapide', desc: 'Communication en temps réel' },
              { icon: '🌐', title: 'Global', desc: 'Accessible partout' },
              { icon: '📱', title: 'Mobile', desc: 'Application responsive' },
            ].map((feature, index) => (
              <div 
                key={index}
                className={styles.featureCard}
                style={{ transitionDelay: `${index * 0.1}s` }}
              >
                <span className={styles.featureIcon}>{feature.icon}</span>
                <h3>{feature.title}</h3>
                <p>{feature.desc}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* Stats Section */}
      <section 
        className={`${styles.section} ${styles.statsSection}`}
        ref={el => sectionsRef.current[2] = el}
      >
        <div className={styles.contentWrapper}>
          <h2 className={styles.sectionTitle}>Nos Chiffres</h2>
          <div className={styles.statsGrid}>
            {[
              { number: <span style={{ fontFamily: 'serif' }}>&#x221A;100%</span>, label: 'de satisfaction client' },
              { number: <span style={{ fontFamily: 'serif' }}>10MD<sup>0</sup></span>, label: 'Messages' },
              { number: '99.9%', label: 'indisponibilité' },
            ].map((stat, index) => (
              <div 
                key={index}
                className={styles.statCard}
                style={{ transitionDelay: `${index * 0.1}s` }}
              >
                <span className={styles.statNumber}>{stat.number}</span>
                <span className={styles.statLabel}>{stat.label}</span>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* Contact Section */}
      <section 
        className={`${styles.section} ${styles.contactSection}`}
        ref={el => sectionsRef.current[3] = el}
      >
        <div className={styles.contentWrapper}>
          <h2 className={styles.sectionTitle}>Contactez-nous</h2>
          <div className={styles.contactContent}>
            <p className={styles.contactText}>
              Prêt a nous rejoindre !
            </p>
            <button className={styles.mainButton}>
              Commencer
            </button>
          </div>
        </div>
      </section>
    </div>
  );
}

export default Home;

/* Home.module.css */
.mainContainer {
  position: relative;
  min-height: 100vh;
  color: #FFFFFF;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}

/* Progress Line */
.progressLine {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: rgba(255, 255, 255, 0.1);
  z-index: 1000;
}

.progressFill {
  height: 100%;
  background: linear-gradient(90deg, #FF416C, #FF4B2B);
  transition: width 0.1s ease-out;
}

/* Video Background */
.backgroundVideo {
  position: fixed;
  right: 0;
  bottom: 0;
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  z-index: -2;
  object-fit: cover;
}

.videoOverlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000;
  z-index: -1;
  transition: opacity 0.5s ease;
}

/* Sections Common Styles */
.section {
  min-height: 100vh;
  padding: 80px 20px;
  opacity: 0;
  transform: translateY(50px);
  transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

.section.revealed {
  opacity: 1;
  transform: translateY(0);
}

.contentWrapper {
  max-width: 1200px;
  margin: 0 auto;
  position: relative;
}

/* Hero Section */
.heroSection {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.heroTitle {
  font-size: 3.5rem;
  margin-bottom: 1rem;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.2s;
}

.revealed .heroTitle {
  opacity: 1;
  transform: translateY(0);
}

.heroText {
  font-size: 1.5rem;
  margin-bottom: 2rem;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.4s;
}

.revealed .heroText {
  opacity: 1;
  transform: translateY(0);
}

/* Features Section */
.featuresGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 30px;
  margin-top: 50px;
}

.featureCard {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
  border-radius: 20px;
  padding: 30px;
  text-align: center;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.revealed .featureCard {
  opacity: 1;
  transform: translateY(0);
}

.featureCard:hover {
  transform: translateY(-10px);
  background: rgba(255, 255, 255, 0.15);
}

.featureIcon {
  font-size: 3rem;
  margin-bottom: 1rem;
  display: block;
}

/* Stats Section */
.statsGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 30px;
  margin-top: 50px;
}

.statCard {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
  border-radius: 20px;
  padding: 30px;
  text-align: center;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.revealed .statCard {
  opacity: 1;
  transform: translateY(0);
}

.statNumber {
  font-size: 3rem;
  font-weight: bold;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  display: block;
  margin-bottom: 0.5rem;
}

.statLabel {
  font-size: 1.2rem;
  color: rgba(255, 255, 255, 0.8);
}

/* Contact Section */
.contactSection {
  text-align: center;
}

.contactContent {
  max-width: 600px;
  margin: 0 auto;
}

.contactText {
  font-size: 1.5rem;
  margin-bottom: 2rem;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.2s;
}

.revealed .contactText {
  opacity: 1;
  transform: translateY(0);
}

/* Section Titles */
.sectionTitle {
  font-size: 2.5rem;
  margin-bottom: 2rem;
  text-align: center;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.revealed .sectionTitle {
  opacity: 1;
  transform: translateY(0);
}

/* Buttons */
.mainButton {
  padding: 15px 30px;
  font-size: 1.1rem;
  font-weight: 600;
  border: none;
  border-radius: 25px;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  color: white;
  cursor: pointer;
  transition: all 0.3s ease;
  opacity: 0;
  transform: translateY(30px);
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.6s;
}

.revealed .mainButton {
  opacity: 1;
  transform: translateY(0);
}

.mainButton:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(255, 65, 108, 0.3);
}

.actionButtons {
  display: flex;
  gap: 20px;
  justify-content: center;
  margin-top: 2rem;
}

/* Responsive Design */
@media (max-width: 768px) {
  .heroTitle {
    font-size: 2.5rem;
  }
  
  .heroText {
    font-size: 1.2rem;
  }
  
  .section {
    padding: 60px 20px;
  }
  
  .statNumber {
    font-size: 2.5rem;
  }
  
  .actionButtons {
    flex-direction: column;
  }
}

/* Animation Keyframes */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0.9);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* Smooth Scroll */
html {
  scroll-behavior: smooth;
}

// src/components/Navbar.jsx
import React, { useContext } from 'react';
import { Link } from 'react-router-dom';
import { AuthContext } from '../contexts/AuthContext';
import styles from './Navbar.module.css';

function Navbar() {
  const { user, logout } = useContext(AuthContext);

  return (
    <nav className={styles.navbar}>
      <div className={styles.navbarContainer}>
        <Link to="/" className={styles.navbarLogo}>
          ChatApp
        </Link>

        <div className={styles.navbarContent}>
          {user ? (
            <div className={styles.authenticatedNav}>
              <div className={styles.navLinks}>
                <Link to="/conversations" className={styles.navLink}>
                  Conversations
                </Link>
                <Link to="/profile" className={styles.navLink}>
                  Profil
                </Link>
              </div>

              <div className={styles.userSection}>
                <div className={styles.userInfo}>
                  <div className={styles.userAvatar}>
                    {user.name ? user.name.charAt(0).toUpperCase() : '?'}
                  </div>
                  <span className={styles.userName}>{user.name}</span>
                </div>
                <button onClick={logout} className={styles.logoutButton}>
                  Déconnexion
                </button>
              </div>
            </div>
          ) : (
            <div className={styles.authButtons}>
              <Link to="/login" className={styles.loginButton}>
                Se connecter
              </Link>
              <Link to="/signup" className={styles.signupButton}>
                S'inscrire
              </Link>
            </div>
          )}
        </div>
      </div>
    </nav>
  );
}

export default Navbar;

/* Navbar.module.css */
.navbar {
  background-color: rgba(28, 28, 30, 0.8);
  backdrop-filter: blur(10px);
  padding: 15px 0;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
}

.navbarContainer {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;
}

.navbarLogo {
  font-size: 24px;
  font-weight: 600;
  text-decoration: none;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: opacity 0.3s ease;
}

.navbarLogo:hover {
  opacity: 0.8;
}

.navbarContent {
  display: flex;
  align-items: center;
}

.authenticatedNav {
  display: flex;
  align-items: center;
}

.navLinks {
  display: flex;
  margin-right: 20px;
}

.navLink {
  color: #FFFFFF;
  text-decoration: none;
  margin-right: 20px;
  font-weight: 500;
  transition: color 0.3s ease;
}

.navLink:hover {
  color: #FF416C;
}

.userSection {
  display: flex;
  align-items: center;
}

.userInfo {
  display: flex;
  align-items: center;
  margin-right: 20px;
}

.userAvatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: bold;
  color: #FFFFFF;
  margin-right: 10px;
}

.userName {
  color: #FFFFFF;
  font-weight: 500;
}

.logoutButton,
.loginButton,
.signupButton {
  padding: 8px 16px;
  border-radius: 20px;
  font-weight: 600;
  text-decoration: none;
  transition: all 0.3s ease;
  cursor: pointer;
}

.logoutButton {
  background: transparent;
  color: #FFFFFF;
  border: 1px solid #FF416C;
}

.logoutButton:hover {
  background: rgba(255, 65, 108, 0.1);
}

.loginButton,
.signupButton {
  background: linear-gradient(45deg, #FF416C, #FF4B2B);
  color: #FFFFFF;
  border: none;
  margin-left: 10px;
}

.loginButton:hover,
.signupButton:hover {
  background: linear-gradient(45deg, #FF4B2B, #FF416C);
  transform: translateY(-2px);
  box-shadow: 0 4px 6px rgba(255, 65, 108, 0.2);
}

@keyframes gradientShift {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.loginButton,
.signupButton {
  background-size: 200% 200%;
  animation: gradientShift 3s ease infinite;
}

// src/contexts/AuthContext.js
import React, { createContext, useState, useEffect } from 'react';
import axios from '../utils/api';

export const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  // Charger l'utilisateur depuis le localStorage au démarrage
  useEffect(() => {
    const storedUser = localStorage.getItem('user');
    const storedToken = localStorage.getItem('token');
    if (storedUser && storedToken) {
      setUser(JSON.parse(storedUser));
      axios.defaults.headers.common['Authorization'] = `Bearer ${storedToken}`;
    }
  }, []);

  const login = async (username, password) => {
    const response = await axios.post('/login', {
      name: username,
      password: password,
    });
    const { access_token } = response.data;
    localStorage.setItem('token', access_token);
    axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;

    // Récupérer les informations de l'utilisateur courant
    const userResponse = await axios.get('/users/me');
    localStorage.setItem('user', JSON.stringify(userResponse.data));
    setUser(userResponse.data);
  };

  const signup = async (username, password) => {
    await axios.post('/signup', {
      name: username,
      password: password,
    });
    // Après l'inscription, connecter l'utilisateur
    await login(username, password);
  };

  const logout = () => {
    localStorage.removeItem('user');
    localStorage.removeItem('token');
    delete axios.defaults.headers.common['Authorization'];
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, signup, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

// src/utils/api.js
import axios from 'axios';

const instance = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
});

export default instance;

// src/App.js
import React, { useContext } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { AuthContext } from './contexts/AuthContext';
import Login from './components/Auth/Login';
import Signup from './components/Auth/Signup';
import Home from './components/Home';
import Chat from './components/Chat/Chat';
import Profile from './components/Profile/Profile';
import Navbar from './components/Navbar';

function App() {
  const { user } = useContext(AuthContext);

  return (
    <Router>
      <Navbar />
      <Routes>
        <Route path="/" element={user ? <Navigate to="/conversations" /> : <Home />} />
        <Route path="/login" element={user ? <Navigate to="/conversations" /> : <Login />} />
        <Route path="/signup" element={user ? <Navigate to="/conversations" /> : <Signup />} />
        <Route path="/profile" element={user ? <Profile /> : <Navigate to="/login" />} />
        <Route path="/conversations" element={user ? <Chat /> : <Navigate to="/login" />} />
        <Route path="/chat/:conversationId" element={user ? <Chat /> : <Navigate to="/login" />} />
        {/* Redirection pour les chemins non définis */}
        <Route path="*" element={<Navigate to="/" replace />} />
      </Routes>
    </Router>
  );
}

export default App;

.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}


// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { AuthProvider } from './contexts/AuthContext';

ReactDOM.render(
  <AuthProvider>
    <App />
  </AuthProvider>,
  document.getElementById('root')
);

# models.py
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime

# Modèles pour l'utilisateur
class UserBase(BaseModel):
    name: str
    bio: Optional[str] = None  # Ajout du champ bio

class UserCreate(UserBase):
    password: str

class UserInDB(UserBase):
    hashed_password: str

class User(UserBase):
    id: str

# Modèles pour les messages
class Message(BaseModel):
    sender: str
    message: str
    timestamp: datetime = Field(default_factory=datetime.utcnow)

# Modèles pour les conversations
class Conversation(BaseModel):
    id: str
    name: Optional[str] = None  # Nom du groupe (optionnel)
    participants: List[str]
    messages: List[Message] = []

# database.py
from pymongo import MongoClient
from config import MONGODB_URI

client = MongoClient(MONGODB_URI)
db = client["FIRSTSERv"]
users_collection = db["users"]
conversations_collection = db["conversations"]

# config.py
import os
from dotenv import load_dotenv

# Charger les variables d'environnement depuis un fichier .env
load_dotenv()

MONGODB_URI = os.environ.get("MONGODB_URI")
SECRET_KEY = os.environ.get("SECRET_KEY")
ALGORITHM = os.environ.get("ALGORITHM", "HS256")
ACCESS_TOKEN_EXPIRE_MINUTES = int(os.environ.get("ACCESS_TOKEN_EXPIRE_MINUTES", 30))

# authentication.py
from datetime import datetime, timedelta
from typing import Optional
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from database import users_collection
from models import UserInDB
from config import SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES
import bcrypt

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# Fonction pour vérifier le mot de passe
def verify_password(plain_password, hashed_password):
    return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))

# Fonction pour récupérer un utilisateur depuis la base de données
def get_user(db, username: str):
    user = db.find_one({"name": username})
    if user:
        return UserInDB(name=user["name"], hashed_password=user["password"])
    return None

# Fonction pour authentifier un utilisateur
def authenticate_user(db, username: str, password: str):
    user = get_user(db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user

# Fonction pour créer un token JWT
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    expire = datetime.utcnow() + (expires_delta if expires_delta else timedelta(minutes=15))
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

# Dépendance pour obtenir l'utilisateur courant
async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=401,
        detail="Impossible de valider les informations d'identification",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        user = get_user(users_collection, username)
        if user is None:
            raise credentials_exception
        return user
    except JWTError:
        raise credentials_exception

# main.py ou app.py
from fastapi import FastAPI, Depends, HTTPException, status
from typing import List, Optional
from fastapi.middleware.cors import CORSMiddleware
from models import *
from authentication import *
from config import *
from database import *
from bson.objectid import ObjectId
import bcrypt
from pydantic import BaseModel

app = FastAPI()

# Configuration CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # À ajuster en production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
def read_root():
    return {"message": "Hello, world!"}

# Modèle pour la mise à jour de la bio
class BioUpdate(BaseModel):
    bio: str

# Inscription d'un nouvel utilisateur
@app.post("/signup", response_model=User)
def signup(user: UserCreate):
    # Vérifier si l'utilisateur existe déjà
    if users_collection.find_one({"name": user.name}):
        raise HTTPException(status_code=400, detail="Un utilisateur avec ce nom existe déjà.")

    # Hasher le mot de passe
    hashed_password = bcrypt.hashpw(user.password.encode('utf-8'), bcrypt.gensalt())

    # Créer l'utilisateur
    user_doc = {
        "name": user.name,
        "password": hashed_password.decode('utf-8'),
        "bio": user.bio or ""  # Initialiser la bio
    }
    result = users_collection.insert_one(user_doc)
    return User(id=str(result.inserted_id), name=user.name, bio=user.bio or "")

# Connexion d'un utilisateur
@app.post("/login")
def login(form_data: UserCreate):
    user = authenticate_user(users_collection, form_data.name, form_data.password)
    if not user:
        raise HTTPException(status_code=400, detail="Nom d'utilisateur ou mot de passe incorrect")

    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.name}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

# ---- Gestion des bios ----

# Récupérer le profil de l'utilisateur courant
@app.get("/users/me", response_model=UserBase)
def read_current_user(current_user: UserInDB = Depends(get_current_user)):
    user = users_collection.find_one({"name": current_user.name})
    return UserBase(name=user["name"], bio=user.get("bio", ""))

# Mettre à jour la bio de l'utilisateur courant
@app.put("/users/me/bio", response_model=UserBase)
def update_bio(bio_update: BioUpdate, current_user: UserInDB = Depends(get_current_user)):
    users_collection.update_one(
        {"name": current_user.name},
        {"$set": {"bio": bio_update.bio}}
    )
    updated_user = users_collection.find_one({"name": current_user.name})
    return UserBase(
        name=updated_user["name"],
        bio=updated_user.get("bio", "")
    )

# Récupérer le profil d'un utilisateur par nom
@app.get("/users/{username}", response_model=UserBase)
def get_user_profile(username: str, current_user: UserInDB = Depends(get_current_user)):
    user = users_collection.find_one({"name": username})
    if not user:
        raise HTTPException(status_code=404, detail="Utilisateur non trouvé")
    return UserBase(
        name=user["name"],
        bio=user.get("bio", "")
    )

# Récupérer tous les utilisateurs
@app.get("/users", response_model=List[UserBase])
def get_all_users(current_user: UserInDB = Depends(get_current_user)):
    users = users_collection.find({})
    return [UserBase(name=user["name"], bio=user.get("bio", "")) for user in users]

# ---- Gestion des conversations ----

# Modèle pour la création d'une conversation
class ConversationCreate(BaseModel):
    participants: List[str]
    name: Optional[str] = None

@app.post("/conversations", response_model=Conversation)
def create_conversation(convo: ConversationCreate, current_user: UserInDB = Depends(get_current_user)):
    participants = convo.participants
    if current_user.name not in participants:
        participants.append(current_user.name)

    # Vérifier que les utilisateurs existent
    for name in participants:
        if not users_collection.find_one({"name": name}):
            raise HTTPException(status_code=404, detail=f"Utilisateur {name} introuvable")

    # Si c'est une conversation individuelle sans nom, vérifier si elle existe déjà
    if len(participants) == 2 and not convo.name:
        existing_convo = conversations_collection.find_one({
            "participants": {"$all": participants},
            "name": {"$exists": False}
        })
        if existing_convo:
            raise HTTPException(status_code=400, detail="La conversation existe déjà")

    # Créer la conversation
    conversation_doc = {
        "participants": participants,
        "messages": [],
    }
    if convo.name:
        conversation_doc["name"] = convo.name

    result = conversations_collection.insert_one(conversation_doc)
    return Conversation(
        id=str(result.inserted_id),
        name=convo.name,
        participants=participants
    )

# Récupérer les conversations de l'utilisateur courant
@app.get("/conversations", response_model=List[Conversation])
def get_user_conversations(current_user: UserInDB = Depends(get_current_user)):
    conversations = conversations_collection.find({"participants": current_user.name})
    convo_list = []
    for convo in conversations:
        convo_list.append(Conversation(
            id=str(convo['_id']),
            name=convo.get("name"),
            participants=convo["participants"]
        ))
    return convo_list

# Récupérer une conversation par son ID
@app.get("/conversations/{conversation_id}", response_model=Conversation)
def get_conversation(conversation_id: str, current_user: UserInDB = Depends(get_current_user)):
    conversation = conversations_collection.find_one({"_id": ObjectId(conversation_id)})
    if not conversation:
        raise HTTPException(status_code=404, detail="Conversation non trouvée")
    if current_user.name not in conversation["participants"]:
        raise HTTPException(status_code=403, detail="Accès refusé")
    messages = [Message(**msg) for msg in conversation.get("messages", [])]
    return Conversation(
        id=str(conversation['_id']),
        name=conversation.get("name"),
        participants=conversation["participants"],
        messages=messages
    )

# Envoyer un message dans une conversation
@app.post("/conversations/{conversation_id}/messages", response_model=Message)
def send_message(conversation_id: str, message: Message, current_user: UserInDB = Depends(get_current_user)):
    conversation = conversations_collection.find_one({"_id": ObjectId(conversation_id)})
    if not conversation:
        raise HTTPException(status_code=404, detail="Conversation non trouvée")
    if current_user.name not in conversation["participants"]:
        raise HTTPException(status_code=403, detail="Accès refusé")

    message_doc = message.dict()
    message_doc["timestamp"] = message.timestamp

    conversations_collection.update_one(
        {"_id": ObjectId(conversation_id)},
        {"$push": {"messages": message_doc}}
    )
    return message

# Supprimer une conversation
@app.delete("/conversations/{conversation_id}")
def delete_conversation(conversation_id: str, current_user: UserInDB = Depends(get_current_user)):
    conversation = conversations_collection.find_one({"_id": ObjectId(conversation_id)})
    if not conversation:
        raise HTTPException(status_code=404, detail="Conversation non trouvée")
    if current_user.name not in conversation["participants"]:
        raise HTTPException(status_code=403, detail="Accès refusé")

    conversations_collection.delete_one({"_id": ObjectId(conversation_id)})
    return {"detail": "Conversation supprimée"}

# Vous pouvez retirer le code suivant si vous utilisez un serveur ASGI comme Uvicorn ou Gunicorn en production
# if __name__ == "__main__":
#     import uvicorn
#     uvicorn.run(app, host="0.0.0.0", port=8000)