pmirkovic commited on
Commit
faa5c3c
·
verified ·
1 Parent(s): cac8dd7

Delete collection

Browse files
Files changed (1) hide show
  1. collection/index.html +0 -420
collection/index.html DELETED
@@ -1,420 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>The Third Voice</title>
7
- <meta name="description" content="The Third Voice: AI-powered communication assistant for reframing messages with emotional intelligence.">
8
- <link rel="icon" href="/static/favicon.ico" type="image/x-icon">
9
- <style>
10
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
11
-
12
- :root {
13
- --primary-color: #007BFF;
14
- --secondary-color: #28A745;
15
- --text-color: #333;
16
- --bg-color: #F8F9FA;
17
- --card-bg: #FFFFFF;
18
- --border-color: #DEE2E6;
19
- --error-color: #DC3545;
20
- }
21
-
22
- body {
23
- font-family: 'Inter', sans-serif;
24
- line-height: 1.6;
25
- margin: 0;
26
- padding: 20px;
27
- background-color: var(--bg-color);
28
- color: var(--text-color);
29
- display: flex;
30
- flex-direction: column;
31
- align-items: center;
32
- min-height: 100vh;
33
- box-sizing: border-box;
34
- }
35
-
36
- .container {
37
- background-color: var(--card-bg);
38
- padding: 30px;
39
- border-radius: 12px;
40
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
41
- width: 100%;
42
- max-width: 700px;
43
- box-sizing: border-box;
44
- margin-bottom: 20px;
45
- }
46
-
47
- h1 {
48
- text-align: center;
49
- color: var(--primary-color);
50
- margin-bottom: 30px;
51
- font-weight: 700;
52
- font-size: 2em;
53
- }
54
-
55
- .logo-container {
56
- text-align: center;
57
- margin-bottom: 20px;
58
- }
59
- .logo {
60
- width: 60px;
61
- height: auto;
62
- }
63
-
64
- label {
65
- display: block;
66
- margin-bottom: 8px;
67
- font-weight: 600;
68
- color: var(--text-color);
69
- }
70
-
71
- textarea {
72
- width: 100%;
73
- padding: 12px;
74
- margin-bottom: 20px;
75
- border: 1px solid var(--border-color);
76
- border-radius: 8px;
77
- font-family: 'Inter', sans-serif;
78
- font-size: 1em;
79
- box-sizing: border-box;
80
- resize: vertical;
81
- min-height: 100px;
82
- }
83
-
84
- select {
85
- width: 100%;
86
- padding: 12px;
87
- margin-bottom: 20px;
88
- border: 1px solid var(--border-color);
89
- border-radius: 8px;
90
- font-family: 'Inter', sans-serif;
91
- font-size: 1em;
92
- box-sizing: border-box;
93
- background-color: var(--card-bg);
94
- color: var(--text-color);
95
- }
96
-
97
- button {
98
- display: block;
99
- width: 100%;
100
- padding: 15px;
101
- background-color: var(--primary-color);
102
- color: white;
103
- border: none;
104
- border-radius: 8px;
105
- font-size: 1.1em;
106
- font-weight: 700;
107
- cursor: pointer;
108
- transition: background-color 0.3s ease, transform 0.2s ease;
109
- }
110
-
111
- button:hover {
112
- background-color: #0056b3;
113
- transform: translateY(-2px);
114
- }
115
-
116
- button:disabled {
117
- background-color: #cccccc;
118
- cursor: not-allowed;
119
- transform: translateY(0);
120
- }
121
-
122
- .loader {
123
- border: 4px solid #f3f3f3;
124
- border-top: 4px solid var(--primary-color);
125
- border-radius: 50%;
126
- width: 20px;
127
- height: 20px;
128
- animation: spin 1s linear infinite;
129
- display: inline-block;
130
- vertical-align: middle;
131
- margin-left: 10px;
132
- display: none; /* Hidden by default */
133
- }
134
-
135
- button.loading .loader {
136
- display: inline-block;
137
- }
138
-
139
- button.loading span {
140
- display: none;
141
- }
142
-
143
- @keyframes spin {
144
- 0% { transform: rotate(0deg); }
145
- 100% { transform: rotate(360deg); }
146
- }
147
-
148
- #error-message {
149
- color: var(--error-color);
150
- text-align: center;
151
- margin-top: -10px;
152
- margin-bottom: 20px;
153
- font-weight: 600;
154
- display: none;
155
- }
156
-
157
- .result-container {
158
- background-color: var(--bg-color);
159
- padding: 25px;
160
- border-radius: 10px;
161
- border: 1px solid var(--border-color);
162
- margin-top: 30px;
163
- display: none; /* Hidden by default */
164
- }
165
-
166
- .result-container h2 {
167
- color: var(--primary-color);
168
- font-size: 1.4em;
169
- margin-top: 0;
170
- margin-bottom: 15px;
171
- }
172
-
173
- #rewritten-message {
174
- background-color: var(--card-bg);
175
- padding: 15px;
176
- border-radius: 8px;
177
- border: 1px solid var(--border-color);
178
- font-size: 1.1em;
179
- white-space: pre-wrap; /* Preserves whitespace and wraps text */
180
- word-wrap: break-word; /* Breaks long words if necessary */
181
- margin-bottom: 15px;
182
- }
183
-
184
- #tone-analysis, #suggestion {
185
- font-size: 0.95em;
186
- color: var(--text-color);
187
- margin-bottom: 10px;
188
- }
189
- #tone-analysis { font-weight: 600; }
190
- #suggestion { font-style: italic; }
191
-
192
- .disclaimer {
193
- font-size: 0.85em;
194
- color: #6c757d;
195
- text-align: center;
196
- margin-top: 20px;
197
- padding: 15px;
198
- border: 1px dashed #ced4da;
199
- border-radius: 8px;
200
- background-color: #e9ecef;
201
- }
202
- .disclaimer a {
203
- color: #007bff;
204
- text-decoration: none;
205
- }
206
- .disclaimer a:hover {
207
- text-decoration: underline;
208
- }
209
-
210
- footer {
211
- margin-top: auto; /* Pushes footer to the bottom */
212
- padding: 20px;
213
- font-size: 0.8em;
214
- color: #6c757d;
215
- text-align: center;
216
- }
217
- footer a {
218
- color: #007bff;
219
- text-decoration: none;
220
- }
221
- footer a:hover {
222
- text-decoration: underline;
223
- }
224
-
225
- /* Responsive Adjustments */
226
- @media (max-width: 600px) {
227
- body {
228
- padding: 10px;
229
- }
230
- .container {
231
- padding: 20px;
232
- }
233
- h1 {
234
- font-size: 1.8em;
235
- }
236
- button {
237
- padding: 12px;
238
- font-size: 1em;
239
- }
240
- .result-container {
241
- padding: 15px;
242
- }
243
- #rewritten-message {
244
- font-size: 1em;
245
- }
246
- }
247
- </style>
248
- </head>
249
- <body>
250
- <div class="container">
251
- <div class="logo-container">
252
- <img src="/static/favicon.ico" alt="The Third Voice Logo" class="logo">
253
- </div>
254
- <h1>The Third Voice</h1>
255
- <p class="disclaimer">
256
- The Third Voice is an AI-powered communication assistant. It rewrites your messages using emotional intelligence.
257
- <br>
258
- <small>Built with love by Predrag Mirkovic. <a href="https://thethirdvoice.ai/terms" target="_blank">Terms & Privacy</a> (Placeholder)</small>
259
- </p>
260
-
261
- <label for="message-input">Your Message:</label>
262
- <textarea id="message-input" placeholder="Type or paste your message here..."></textarea>
263
-
264
- <label for="tone-select">Choose a Tone:</label>
265
- <select id="tone-select">
266
- <option value="Kind">Kind</option>
267
- <option value="Direct">Direct</option>
268
- <option value="Neutral">Neutral</option>
269
- <option value="Empathetic">Empathetic</option>
270
- <option value="Professional">Professional</option>
271
- </select>
272
-
273
- <button id="rewrite-btn">
274
- <span>Rewrite It</span>
275
- <div class="loader"></div>
276
- </button>
277
-
278
- <div id="error-message"></div>
279
-
280
- <div id="result-container" class="result-container">
281
- <h2>Rewritten Message:</h2>
282
- <div id="rewritten-message"></div>
283
- <p id="tone-analysis"></p>
284
- <p id="suggestion"></p>
285
- </div>
286
- </div>
287
-
288
- <div class="disclaimer">
289
- This is an AI-powered prototype. Results may vary. Always review rewritten messages before sending.
290
- <br>
291
- For more information, visit <a href="https://thethirdvoice.ai" target="_blank">thethirdvoice.ai</a>
292
- </div>
293
-
294
- <footer>
295
- © 2025 The Third Voice. All rights reserved. <a href="https://thethirdvoice.ai/privacy" target="_blank">Privacy Policy</a> | <a href="https://thethirdvoice.ai/terms" target="_blank">Terms of Service</a>
296
- </footer>
297
-
298
- <script>
299
- const messageInput = document.getElementById('message-input');
300
- const toneSelect = document.getElementById('tone-select');
301
- const rewriteBtn = document.getElementById('rewrite-btn');
302
- const errorMessageDiv = document.getElementById('error-message');
303
- const resultDiv = document.getElementById('result-container');
304
- const rewrittenMessage = document.getElementById('rewritten-message');
305
- const toneAnalysis = document.getElementById('tone-analysis');
306
- const suggestion = document.getElementById('suggestion');
307
-
308
- let selectedTone = toneSelect.value;
309
-
310
- toneSelect.addEventListener('change', (event) => {
311
- selectedTone = event.target.value;
312
- });
313
-
314
- function showError(message) {
315
- errorMessageDiv.textContent = message;
316
- errorMessageDiv.style.display = 'block';
317
- }
318
-
319
- function hideError() {
320
- errorMessageDiv.style.display = 'none';
321
- errorMessageDiv.textContent = '';
322
- }
323
-
324
- // AI call now goes to the same Hugging Face Space
325
- const hfSpaceApiUrl = "/rewrite"; // <-- THIS IS THE CRUCIAL CHANGE!
326
-
327
- rewriteBtn.addEventListener('click', async () => {
328
- const message = messageInput.value.trim();
329
- if (!message) {
330
- showError('Please enter a message to rewrite.');
331
- return;
332
- }
333
-
334
- if (message.length < 5) {
335
- showError('Please enter a slightly longer message for better AI rewriting.');
336
- return;
337
- }
338
-
339
- hideError();
340
- rewriteBtn.classList.add('loading');
341
- rewriteBtn.textContent = 'Rewriting...';
342
- rewriteBtn.disabled = true;
343
- resultDiv.style.display = 'none'; // Hide previous results
344
-
345
- try {
346
- const response = await fetch(hfSpaceApiUrl, {
347
- method: 'POST',
348
- headers: {
349
- 'Content-Type': 'application/json',
350
- },
351
- body: JSON.stringify({ message: message, tone: selectedTone })
352
- });
353
-
354
- const data = await response.json();
355
-
356
- if (!response.ok) {
357
- console.error("AI API Error:", data.error || response.statusText);
358
- showError(`AI rewrite failed: ${data.error || 'Server error'}. Please try again later.`);
359
- return;
360
- }
361
-
362
- if (data.rewrittenText) {
363
- const rewritten = data.rewrittenText;
364
- const originalTone = analyzeOriginalTone(message);
365
-
366
- rewrittenMessage.textContent = rewritten;
367
- toneAnalysis.textContent = `Original Tone: ${originalTone} → Target Tone: ${selectedTone}`;
368
- suggestion.textContent = getSuggestion(selectedTone, originalTone, rewritten);
369
-
370
- resultDiv.style.display = 'block';
371
- resultDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
372
- } else {
373
- showError('AI did not return a valid rewritten message. Try again.');
374
- }
375
-
376
- } catch (error) {
377
- console.error('Network or API call error:', error);
378
- showError('Could not reach the AI service. Please check your internet or try again later.');
379
- } finally {
380
- rewriteBtn.classList.remove('loading');
381
- rewriteBtn.textContent = 'Rewrite It';
382
- rewriteBtn.disabled = false;
383
- }
384
- });
385
-
386
-
387
- // --- Helper Functions (Client-Side, used for UI display) ---
388
-
389
- // Simple client-side tone analysis
390
- function analyzeOriginalTone(message) {
391
- const lowerMessage = message.toLowerCase();
392
- if (lowerMessage.includes('hate') || lowerMessage.includes('angry') || lowerMessage.includes('frustrated')) {
393
- return 'Negative';
394
- } else if (lowerMessage.includes('love') || lowerMessage.includes('happy') || lowerMessage.includes('joy')) {
395
- return 'Positive';
396
- } else if (lowerMessage.includes('should') || lowerMessage.includes('must') || lowerMessage.includes('demand')) {
397
- return 'Demanding';
398
- } else if (lowerMessage.includes('perhaps') || lowerMessage.includes('maybe') || lowerMessage.includes('suggest')) {
399
- return 'Suggestive';
400
- }
401
- return 'Neutral/Unclear';
402
- }
403
-
404
- // Simple client-side suggestion based on tone
405
- function getSuggestion(targetTone, originalTone, rewritten) {
406
- if (originalTone === 'Negative' && targetTone === 'Kind') {
407
- return "Great job reframing negativity into kindness. Always review for genuine intent.";
408
- } else if (originalTone === 'Demanding' && targetTone === 'Empathetic') {
409
- return "Transforming demands into empathetic requests can significantly improve reception.";
410
- } else if (originalTone === 'Neutral/Unclear' && targetTone === 'Direct') {
411
- return "Sometimes clarity is key. This direct approach ensures your message is understood.";
412
- } else if (originalTone === 'Positive' && targetTone === 'Professional') {
413
- return "Even positive messages benefit from professional framing in certain contexts.";
414
- }
415
- return "Review the rewritten message to ensure it perfectly matches your desired impact.";
416
- }
417
-
418
- </script>
419
- </body>
420
- </html>