File size: 6,338 Bytes
040db21
37619a6
040db21
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
040db21
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
 
 
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0abab50
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
0abab50
c0834c0
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
 
 
 
 
 
 
0d2d16d
c0834c0
 
 
 
 
 
37619a6
c0834c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
040db21
0d2d16d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mariam AI</title>
  <!-- Intégration de Tailwind CSS -->
  <script src="https://cdn.tailwindcss.com"></script>
  <!-- Intégration d'Animate.css pour les animations -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
  <style>
    /* Loader personnalisé */
    .loader {
      border-top-color: #3498db;
      animation: spin 1s linear infinite;
    }
    @keyframes spin {
      to { transform: rotate(360deg); }
    }
  </style>
</head>
<body class="bg-gradient-to-r from-blue-500 to-purple-600 min-h-screen flex items-center justify-center">
  <div class="bg-white rounded-xl shadow-2xl overflow-hidden w-full max-w-4xl">
    <!-- En-tête -->
    <header class="bg-gradient-to-r from-purple-600 to-blue-500 p-6 flex justify-between items-center">
      <h1 class="text-white text-3xl font-bold">Mariam AI</h1>
      <div class="flex space-x-4">
        <label class="flex items-center text-white">
          <input type="checkbox" id="webSearchToggle" class="mr-2">
          Activer la recherche web
        </label>
        <button onclick="clearChat()" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded transition duration-200">
          Effacer le chat
        </button>
      </div>
    </header>

    <!-- Contenu principal -->
    <main class="p-6 flex flex-col h-96">
      <!-- Upload de fichier -->
      <div class="mb-4 flex items-center">
        <input type="file" id="fileUpload" class="hidden" accept=".jpg,.jpeg,.png,.pdf,.txt,.mp3,.mp4">
        <label for="fileUpload" class="cursor-pointer bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded transition duration-200">
          Télécharger un fichier
        </label>
        <span id="fileName" class="ml-2 text-gray-600"></span>
      </div>
      <!-- Zone des messages -->
      <div id="chatMessages" class="flex-1 overflow-y-auto space-y-4 mb-4">
        {% for message in messages %}
        <div class="flex {% if message.role == 'user' %}justify-end{% else %}justify-start{% endif %} animate__animated animate__fadeIn">
          <div class="max-w-3/4 p-3 rounded-lg {% if message.role == 'user' %}bg-blue-500 text-white{% else %}bg-gray-200 text-gray-800{% endif %}">
            {{ message.content }}
          </div>
        </div>
        {% endfor %}
      </div>
      <!-- Loader animé -->
      <div id="loader" class="hidden flex justify-center my-4">
        <div class="loader border-8 border-t-8 border-gray-200 rounded-full h-12 w-12"></div>
      </div>
      <!-- Zone de saisie -->
      <div class="border-t pt-4">
        <div class="flex space-x-4">
          <input type="text" id="messageInput" class="flex-1 border rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Écrivez votre message...">
          <button onclick="sendMessage()" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-lg transition duration-200 transform hover:scale-105">
            Envoyer
          </button>
        </div>
      </div>
    </main>
  </div>

  <!-- Scripts -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.2/marked.min.js"></script>
  <script>
    const messageInput = document.getElementById('messageInput');
    const chatMessages = document.getElementById('chatMessages');
    const webSearchToggle = document.getElementById('webSearchToggle');
    const fileUpload = document.getElementById('fileUpload');
    const fileName = document.getElementById('fileName');
    const loader = document.getElementById('loader');

    function addMessage(content, isUser = false) {
      const messageDiv = document.createElement('div');
      messageDiv.className = `flex ${isUser ? 'justify-end' : 'justify-start'} animate__animated animate__fadeIn`;
      
      const innerDiv = document.createElement('div');
      innerDiv.className = `max-w-3/4 p-3 rounded-lg ${isUser ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'}`;
      innerDiv.innerHTML = marked.parse(content);
      
      messageDiv.appendChild(innerDiv);
      chatMessages.appendChild(messageDiv);
      chatMessages.scrollTop = chatMessages.scrollHeight;
    }

    async function sendMessage() {
      const message = messageInput.value.trim();
      if (!message) return;
      
      addMessage(message, true);
      messageInput.value = '';
      
      loader.classList.remove('hidden');  // Afficher le loader
      
      try {
        const response = await fetch('/send_message', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            message: message,
            web_search: webSearchToggle.checked
          })
        });
        
        const data = await response.json();
        loader.classList.add('hidden');  // Masquer le loader
        
        if (data.error) {
          addMessage(`Erreur: ${data.error}`);
        } else {
          addMessage(data.response);
        }
      } catch (error) {
        loader.classList.add('hidden');
        addMessage(`Erreur: ${error.message}`);
      }
    }

    messageInput.addEventListener('keypress', (e) => {
      if (e.key === 'Enter') {
        sendMessage();
      }
    });

    fileUpload.addEventListener('change', async (e) => {
      const file = e.target.files[0];
      if (!file) return;
      
      fileName.textContent = file.name;
      const formData = new FormData();
      formData.append('file', file);
      
      try {
        const response = await fetch('/upload', {
          method: 'POST',
          body: formData
        });
        
        const data = await response.json();
        if (data.error) {
          alert(`Erreur: ${data.error}`);
        } else {
          addMessage(`Fichier téléchargé: ${file.name}`);
        }
      } catch (error) {
        alert(`Erreur: ${error.message}`);
      }
    });

    async function clearChat() {
      try {
        await fetch('/clear_chat', { method: 'POST' });
        chatMessages.innerHTML = '';
        location.reload();
      } catch (error) {
        alert(`Erreur: ${error.message}`);
      }
    }
  </script>
</body>
</html>