Abmacode12 commited on
Commit
23feeb3
·
verified ·
1 Parent(s): cd11d79

OPENAI_API_KEY=sk-votre_cle_api_ici

Browse files
Files changed (3) hide show
  1. index.html +6 -9
  2. script.js +40 -26
  3. styles.css +38 -16
index.html CHANGED
@@ -31,12 +31,11 @@
31
  <link rel="stylesheet" href="styles.css" />
32
  </head>
33
  <body class="h-full bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-slate-100 transition-colors">
34
-
35
  <div class="container">
36
 
37
- <!-- Colonne 1 : Navigation -->
38
  <aside class="sidebar">
39
- <div class="flex items-center justify-between mb-6">
40
  <a href="#" class="logo">
41
  <i class="fa-solid fa-code"></i>
42
  <span>Espace Codage</span>
@@ -66,10 +65,9 @@
66
  </ul>
67
  </div>
68
  </aside>
69
-
70
- <!-- Colonne 2 : Chat IA Rosalinda -->
71
  <main class="chat">
72
- <div class="chat-header">
73
  <h2>Espace Codage – Rosalinda</h2>
74
  <div class="activity-monitor">
75
  <span id="aiActivityDot" class="dot"></span>
@@ -102,10 +100,9 @@
102
  </button>
103
  </div>
104
  </main>
105
-
106
- <!-- Colonne 3 : Résultat & Code -->
107
  <section class="output">
108
- <div class="output-tabs">
109
  <button class="tab-btn active" data-tab="code">
110
  <i class="fas fa-code"></i> Code
111
  </button>
 
31
  <link rel="stylesheet" href="styles.css" />
32
  </head>
33
  <body class="h-full bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-slate-100 transition-colors">
 
34
  <div class="container">
35
 
36
+ <!-- Colonne 1 : Menu -->
37
  <aside class="sidebar">
38
+ <div class="flex items-center justify-between mb-6">
39
  <a href="#" class="logo">
40
  <i class="fa-solid fa-code"></i>
41
  <span>Espace Codage</span>
 
65
  </ul>
66
  </div>
67
  </aside>
68
+ <!-- Colonne 2 : Chat -->
 
69
  <main class="chat">
70
+ <div class="chat-header">
71
  <h2>Espace Codage – Rosalinda</h2>
72
  <div class="activity-monitor">
73
  <span id="aiActivityDot" class="dot"></span>
 
100
  </button>
101
  </div>
102
  </main>
103
+ <!-- Colonne 3 : Code & Résultats -->
 
104
  <section class="output">
105
+ <div class="output-tabs">
106
  <button class="tab-btn active" data-tab="code">
107
  <i class="fas fa-code"></i> Code
108
  </button>
script.js CHANGED
@@ -1,9 +1,5 @@
1
-
2
  console.log("Interface Espace Codage chargée.");
3
 
4
- // ===== Configuration API OpenAI =====
5
- const OPENAI_API_KEY = "sk-votre_cle_api_ici"; // Remplacez par votre clé API
6
-
7
  // ===== Thème (light/dark) =====
8
  const themeToggle = document.getElementById('themeToggle');
9
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
@@ -116,16 +112,6 @@ function setAIActivity(text, active = true) {
116
  aiActivityText.textContent = text;
117
  aiActivityDot.style.background = active ? 'rgb(34,197,94)' : 'rgb(100,116,139)'; // emerald vs slate
118
  }
119
- function getChatHistory() {
120
- const messages = [];
121
- const nodes = chatMessages.querySelectorAll('.msg');
122
- nodes.forEach(node => {
123
- const role = node.classList.contains('msg-user') ? 'user' : 'assistant';
124
- const text = node.querySelector('.bubble').textContent.trim();
125
- messages.push({ role, content: text });
126
- });
127
- return messages;
128
- }
129
  function addMessage(role, content) {
130
  const msg = document.createElement('div');
131
  msg.className = 'msg ' + (role === 'user' ? 'msg-user' : 'msg-ai');
@@ -157,36 +143,60 @@ async function sendMessage() {
157
  if (!text) return;
158
  addMessage('user', text);
159
  chatInput.value = '';
 
160
  setAIActivity('Rosalinda réfléchit...', true);
 
161
  try {
162
  const response = await fetch('https://api.openai.com/v1/chat/completions', {
163
  method: 'POST',
164
  headers: {
165
  'Content-Type': 'application/json',
166
- 'Authorization': `Bearer ${OPENAI_API_KEY}`
167
  },
168
  body: JSON.stringify({
169
  model: 'gpt-3.5-turbo',
170
  messages: [
171
- { role: 'system', content: 'Tu es Rosalinda, une assistante IA utiles et concise.' },
172
- ...getChatHistory(),
173
- { role: 'user', content: text }
 
 
 
 
 
174
  ],
175
  temperature: 0.7
176
  })
177
  });
 
178
  if (!response.ok) {
179
- throw new Error(`Erreur API: ${response.status} ${response.statusText}`);
180
  }
 
181
  const data = await response.json();
182
- const assistantMessage = data.choices?.[0]?.message?.content ?? 'Désolé, aucune réponse.';
183
- setAIActivity('IA en veille', false);
184
- addMessage('ai', assistantMessage);
185
- codeOutput.textContent = assistantMessage;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  } catch (error) {
187
- console.error(error);
 
 
188
  setAIActivity('IA en veille', false);
189
- addMessage('ai', 'Une erreur est survenue lors de la communication avec l\'IA.');
190
  }
191
  }
192
  sendBtn.addEventListener('click', sendMessage);
@@ -197,7 +207,11 @@ micBtn.addEventListener('click', () => {
197
  alert('Fonction "Micro" à implémenter (Web Speech API, Whisper, etc.).');
198
  });
199
  connectBtn.addEventListener('click', () => {
200
- alert('Fonction "Connexion" à implémenter (OAuth, clés API, etc.).');
 
 
 
 
201
  });
202
  attachBtn.addEventListener('click', () => {
203
  alert('Fonction "Ajouter un fichier" à implémenter (FileReader, uploads, etc.).');
 
 
1
  console.log("Interface Espace Codage chargée.");
2
 
 
 
 
3
  // ===== Thème (light/dark) =====
4
  const themeToggle = document.getElementById('themeToggle');
5
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
 
112
  aiActivityText.textContent = text;
113
  aiActivityDot.style.background = active ? 'rgb(34,197,94)' : 'rgb(100,116,139)'; // emerald vs slate
114
  }
 
 
 
 
 
 
 
 
 
 
115
  function addMessage(role, content) {
116
  const msg = document.createElement('div');
117
  msg.className = 'msg ' + (role === 'user' ? 'msg-user' : 'msg-ai');
 
143
  if (!text) return;
144
  addMessage('user', text);
145
  chatInput.value = '';
146
+
147
  setAIActivity('Rosalinda réfléchit...', true);
148
+
149
  try {
150
  const response = await fetch('https://api.openai.com/v1/chat/completions', {
151
  method: 'POST',
152
  headers: {
153
  'Content-Type': 'application/json',
154
+ 'Authorization': `Bearer ${localStorage.getItem('OPENAI_API_KEY') || 'sk-votre_cle_api_ici'}`
155
  },
156
  body: JSON.stringify({
157
  model: 'gpt-3.5-turbo',
158
  messages: [
159
+ {
160
+ role: 'system',
161
+ content: 'Tu es Rosalinda, une assistante IA spécialisée en programmation. Réponds en français de manière concise et technique. Si tu génères du code, utilise des blocs de code avec la syntaxe appropriée.'
162
+ },
163
+ {
164
+ role: 'user',
165
+ content: text
166
+ }
167
  ],
168
  temperature: 0.7
169
  })
170
  });
171
+
172
  if (!response.ok) {
173
+ throw new Error(`Erreur API: ${response.status}`);
174
  }
175
+
176
  const data = await response.json();
177
+ const aiResponse = data.choices[0].message.content;
178
+ addMessage('ai', aiResponse);
179
+
180
+ // Extract and display code if any
181
+ const codeMatch = aiResponse.match(/```(\w+)?\n([\s\S]*?)\n```/);
182
+ if (codeMatch) {
183
+ codeOutput.textContent = `// ${text}\n${codeMatch[2]}`;
184
+ document.querySelector('.result-output').innerHTML = `
185
+ <h3>Résultat</h3>
186
+ <p>Voir le code généré ci-dessus.</p>
187
+ `;
188
+ } else {
189
+ codeOutput.textContent = `// ${text}\n/* Pas de code généré dans cette réponse */`;
190
+ document.querySelector('.result-output').innerHTML = `
191
+ <h3>Résultat</h3>
192
+ <p>${aiResponse}</p>
193
+ `;
194
+ }
195
  } catch (error) {
196
+ addMessage('ai', `Désolé, une erreur s'est produite: ${error.message}. Vérifiez votre clé API dans les paramètres.`);
197
+ codeOutput.textContent = `// Erreur\nconsole.error("${error.message}");`;
198
+ } finally {
199
  setAIActivity('IA en veille', false);
 
200
  }
201
  }
202
  sendBtn.addEventListener('click', sendMessage);
 
207
  alert('Fonction "Micro" à implémenter (Web Speech API, Whisper, etc.).');
208
  });
209
  connectBtn.addEventListener('click', () => {
210
+ const apiKey = prompt('Entrez votre clé API OpenAI:', localStorage.getItem('OPENAI_API_KEY') || '');
211
+ if (apiKey !== null) {
212
+ localStorage.setItem('OPENAI_API_KEY', apiKey);
213
+ alert('Clé API enregistrée avec succès!');
214
+ }
215
  });
216
  attachBtn.addEventListener('click', () => {
217
  alert('Fonction "Ajouter un fichier" à implémenter (FileReader, uploads, etc.).');
styles.css CHANGED
@@ -11,16 +11,20 @@ body { margin: 0; font-family: Inter, ui-sans-serif, system-ui, -apple-system, S
11
 
12
  /* Container principal en 3 colonnes */
13
  .container {
14
- display: flex;
 
15
  height: 100vh;
 
 
 
 
 
16
  }
17
-
18
  /* Colonne 1 : Sidebar */
19
  .sidebar {
20
- width: 20%;
21
- min-width: 240px;
22
  background: rgb(248 250 252); /* slate-50 */
23
- border-right: 1px solid rgb(226 232 240); /* slate-200 */
24
  padding: 16px;
25
  display: flex;
26
  flex-direction: column;
@@ -88,9 +92,7 @@ body { margin: 0; font-family: Inter, ui-sans-serif, system-ui, -apple-system, S
88
 
89
  /* Colonne 2 : Chat */
90
  .chat {
91
- width: 45%;
92
- min-width: 320px;
93
- display: flex;
94
  flex-direction: column;
95
  padding: 16px;
96
  gap: 12px;
@@ -183,10 +185,9 @@ body { margin: 0; font-family: Inter, ui-sans-serif, system-ui, -apple-system, S
183
 
184
  /* Colonne 3 : Output */
185
  .output {
186
- width: 35%;
187
- min-width: 300px;
188
  background: rgb(252 252 252);
189
- border-left: 1px solid rgb(226 232 240);
190
  display: flex;
191
  flex-direction: column;
192
  padding: 16px;
@@ -275,8 +276,29 @@ body { margin: 0; font-family: Inter, ui-sans-serif, system-ui, -apple-system, S
275
 
276
  /* Responsive */
277
  @media (max-width: 1100px) {
278
- .container { flex-direction: column; }
279
- .sidebar { width: 100%; border-right: none; border-bottom: 1px solid rgb(226 232 240); }
280
- .chat { width: 100%; }
281
- .output { width: 100%; }
282
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  /* Container principal en 3 colonnes */
13
  .container {
14
+ display: grid;
15
+ grid-template-columns: 20% 30% 50%;
16
  height: 100vh;
17
+ gap: 1px;
18
+ background: rgb(226 232 240);
19
+ }
20
+ .dark .container {
21
+ background: rgb(30 41 59);
22
  }
 
23
  /* Colonne 1 : Sidebar */
24
  .sidebar {
25
+ width: 100%;
 
26
  background: rgb(248 250 252); /* slate-50 */
27
+ border-right: 1px solid rgb(226 232 240); /* slate-200 */
28
  padding: 16px;
29
  display: flex;
30
  flex-direction: column;
 
92
 
93
  /* Colonne 2 : Chat */
94
  .chat {
95
+ display: flex;
 
 
96
  flex-direction: column;
97
  padding: 16px;
98
  gap: 12px;
 
185
 
186
  /* Colonne 3 : Output */
187
  .output {
188
+ width: 100%;
 
189
  background: rgb(252 252 252);
190
+ border-left: 1px solid rgb(226 232 240);
191
  display: flex;
192
  flex-direction: column;
193
  padding: 16px;
 
276
 
277
  /* Responsive */
278
  @media (max-width: 1100px) {
279
+ .container {
280
+ grid-template-columns: 1fr;
281
+ grid-template-rows: auto 1fr auto;
282
+ }
283
+ .sidebar {
284
+ width: 100%;
285
+ border-right: none;
286
+ border-bottom: 1px solid rgb(226 232 240);
287
+ }
288
+ .output {
289
+ width: 100%;
290
+ border-left: none;
291
+ border-top: 1px solid rgb(226 232 240);
292
+ }
293
+ }
294
+
295
+ /* Ensure minimum widths for columns */
296
+ .sidebar {
297
+ min-width: 200px;
298
+ }
299
+ .chat {
300
+ min-width: 300px;
301
+ }
302
+ .output {
303
+ min-width: 400px;
304
+ }