Es sollen es soll noch jemand eingeladen werden der seine Sprache wählen kann und dann soll der Chat stattfinden halt die Seite bitte ein bisschen mehr dunkel augenfreundlich und sag der Name ist wie folgt also wir ändern den Namen wie folgt
Browse files- components/invite-modal.js +133 -0
- index.html +73 -17
- style.css +2 -0
components/invite-modal.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class InviteModal extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
.modal-overlay {
|
| 7 |
+
position: fixed;
|
| 8 |
+
top: 0;
|
| 9 |
+
left: 0;
|
| 10 |
+
right: 0;
|
| 11 |
+
bottom: 0;
|
| 12 |
+
background: rgba(0, 0, 0, 0.8);
|
| 13 |
+
display: flex;
|
| 14 |
+
align-items: center;
|
| 15 |
+
justify-content: center;
|
| 16 |
+
z-index: 1000;
|
| 17 |
+
}
|
| 18 |
+
.modal-content {
|
| 19 |
+
background: #111;
|
| 20 |
+
border-radius: 12px;
|
| 21 |
+
padding: 24px;
|
| 22 |
+
width: 90%;
|
| 23 |
+
max-width: 500px;
|
| 24 |
+
border: 1px solid #333;
|
| 25 |
+
}
|
| 26 |
+
.modal-header {
|
| 27 |
+
margin-bottom: 20px;
|
| 28 |
+
text-align: center;
|
| 29 |
+
}
|
| 30 |
+
.modal-title {
|
| 31 |
+
font-size: 1.5rem;
|
| 32 |
+
margin: 0;
|
| 33 |
+
color: #fff;
|
| 34 |
+
}
|
| 35 |
+
.input-group {
|
| 36 |
+
margin-bottom: 15px;
|
| 37 |
+
}
|
| 38 |
+
label {
|
| 39 |
+
display: block;
|
| 40 |
+
margin-bottom: 8px;
|
| 41 |
+
color: #aaa;
|
| 42 |
+
font-size: 0.9rem;
|
| 43 |
+
}
|
| 44 |
+
input {
|
| 45 |
+
width: 100%;
|
| 46 |
+
padding: 12px;
|
| 47 |
+
background: #222;
|
| 48 |
+
border: 1px solid #333;
|
| 49 |
+
border-radius: 6px;
|
| 50 |
+
color: #fff;
|
| 51 |
+
font-size: 1rem;
|
| 52 |
+
}
|
| 53 |
+
.btn-group {
|
| 54 |
+
display: flex;
|
| 55 |
+
gap: 10px;
|
| 56 |
+
margin-top: 20px;
|
| 57 |
+
}
|
| 58 |
+
button {
|
| 59 |
+
flex: 1;
|
| 60 |
+
padding: 12px;
|
| 61 |
+
border-radius: 6px;
|
| 62 |
+
font-weight: 600;
|
| 63 |
+
cursor: pointer;
|
| 64 |
+
transition: all 0.2s;
|
| 65 |
+
}
|
| 66 |
+
.btn-primary {
|
| 67 |
+
background: #4f46e5;
|
| 68 |
+
color: white;
|
| 69 |
+
border: none;
|
| 70 |
+
}
|
| 71 |
+
.btn-primary:hover {
|
| 72 |
+
background: #4338ca;
|
| 73 |
+
}
|
| 74 |
+
.btn-secondary {
|
| 75 |
+
background: #222;
|
| 76 |
+
color: #fff;
|
| 77 |
+
border: 1px solid #333;
|
| 78 |
+
}
|
| 79 |
+
.btn-secondary:hover {
|
| 80 |
+
background: #333;
|
| 81 |
+
}
|
| 82 |
+
</style>
|
| 83 |
+
<div class="modal-overlay">
|
| 84 |
+
<div class="modal-content">
|
| 85 |
+
<div class="modal-header">
|
| 86 |
+
<h3 class="modal-title">Invite Partner</h3>
|
| 87 |
+
</div>
|
| 88 |
+
<div class="input-group">
|
| 89 |
+
<label>Partner's Name</label>
|
| 90 |
+
<input type="text" id="partner-name" placeholder="Enter partner's name">
|
| 91 |
+
</div>
|
| 92 |
+
<div class="input-group">
|
| 93 |
+
<label>Partner's Language</label>
|
| 94 |
+
<select id="partner-language" class="w-full px-4 py-2 bg-dark-700 border border-dark-600 rounded-md text-dark-100">
|
| 95 |
+
<option value="en">🇬🇧 English</option>
|
| 96 |
+
<option value="es">🇪🇸 Spanish</option>
|
| 97 |
+
<option value="fr">🇫🇷 French</option>
|
| 98 |
+
<option value="de">🇩🇪 German</option>
|
| 99 |
+
<option value="it">🇮🇹 Italian</option>
|
| 100 |
+
<option value="ja">🇯🇵 Japanese</option>
|
| 101 |
+
</select>
|
| 102 |
+
</div>
|
| 103 |
+
<div class="btn-group">
|
| 104 |
+
<button class="btn-secondary" id="cancel-btn">Cancel</button>
|
| 105 |
+
<button class="btn-primary" id="invite-btn">Invite</button>
|
| 106 |
+
</div>
|
| 107 |
+
</div>
|
| 108 |
+
</div>
|
| 109 |
+
`;
|
| 110 |
+
|
| 111 |
+
this.shadowRoot.getElementById('cancel-btn').addEventListener('click', () => {
|
| 112 |
+
this.remove();
|
| 113 |
+
});
|
| 114 |
+
|
| 115 |
+
this.shadowRoot.getElementById('invite-btn').addEventListener('click', () => {
|
| 116 |
+
const partnerName = this.shadowRoot.getElementById('partner-name').value.trim();
|
| 117 |
+
const partnerLanguage = this.shadowRoot.getElementById('partner-language').value;
|
| 118 |
+
|
| 119 |
+
if (partnerName) {
|
| 120 |
+
const event = new CustomEvent('partner-invited', {
|
| 121 |
+
detail: {
|
| 122 |
+
name: partnerName,
|
| 123 |
+
language: partnerLanguage
|
| 124 |
+
}
|
| 125 |
+
});
|
| 126 |
+
this.dispatchEvent(event);
|
| 127 |
+
this.remove();
|
| 128 |
+
}
|
| 129 |
+
});
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
customElements.define('invite-modal', InviteModal);
|
index.html
CHANGED
|
@@ -3,11 +3,12 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>
|
| 7 |
-
|
| 8 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
|
|
| 9 |
<script>
|
| 10 |
-
|
| 11 |
darkMode: 'class',
|
| 12 |
theme: {
|
| 13 |
extend: {
|
|
@@ -142,8 +143,8 @@
|
|
| 142 |
<div id="language-screen" class="flex flex-col items-center justify-center min-h-screen p-4">
|
| 143 |
<div class="w-full max-w-md bg-dark-800 rounded-xl shadow-xl overflow-hidden border border-dark-700">
|
| 144 |
<div class="gradient-bg text-white p-6 text-center">
|
| 145 |
-
<h1 class="text-3xl font-bold mb-2 text-glow">
|
| 146 |
-
|
| 147 |
</div>
|
| 148 |
|
| 149 |
<div class="p-6">
|
|
@@ -211,11 +212,15 @@
|
|
| 211 |
<label class="block text-sm font-medium text-dark-300 mb-2">Your Name</label>
|
| 212 |
<input type="text" id="user-name" placeholder="Enter your name" class="w-full px-4 py-2 bg-dark-700 border border-dark-600 rounded-md focus:ring-2 focus:ring-primary-500 focus:border-transparent text-dark-100 placeholder-dark-400">
|
| 213 |
</div>
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
</div>
|
| 220 |
</div>
|
| 221 |
|
|
@@ -223,8 +228,8 @@
|
|
| 223 |
<div id="chat-screen" class="hidden flex flex-col h-screen">
|
| 224 |
<div class="gradient-bg text-white p-4 flex justify-between items-center shadow-lg">
|
| 225 |
<div>
|
| 226 |
-
<h1 class="text-xl font-bold text-glow">
|
| 227 |
-
|
| 228 |
</div>
|
| 229 |
<div id="participants-display" class="flex space-x-2">
|
| 230 |
<!-- Participants will be shown here -->
|
|
@@ -460,11 +465,20 @@
|
|
| 460 |
closeModalBtn.addEventListener('click', () => joinModal.classList.add('hidden'));
|
| 461 |
|
| 462 |
micButton.addEventListener('click', toggleSpeechRecognition);
|
| 463 |
-
|
| 464 |
// Initialize speech recognition when the page loads
|
| 465 |
initSpeechRecognition();
|
| 466 |
-
|
| 467 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
function generateChatId() {
|
| 469 |
// Generate a random 6-character alphanumeric code
|
| 470 |
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
@@ -489,11 +503,53 @@
|
|
| 489 |
button.innerHTML = '<i class="fas fa-copy"></i>';
|
| 490 |
}, 2000);
|
| 491 |
}
|
| 492 |
-
|
| 493 |
-
function startChat() {
|
| 494 |
const userName = userNameInput.value.trim();
|
| 495 |
if (!userName) return;
|
| 496 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
// Generate chat ID
|
| 498 |
chatId = generateChatId();
|
| 499 |
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>PolyGlot Chat - Dark Mode</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 9 |
+
<script src="components/invite-modal.js"></script>
|
| 10 |
<script>
|
| 11 |
+
tailwind.config = {
|
| 12 |
darkMode: 'class',
|
| 13 |
theme: {
|
| 14 |
extend: {
|
|
|
|
| 143 |
<div id="language-screen" class="flex flex-col items-center justify-center min-h-screen p-4">
|
| 144 |
<div class="w-full max-w-md bg-dark-800 rounded-xl shadow-xl overflow-hidden border border-dark-700">
|
| 145 |
<div class="gradient-bg text-white p-6 text-center">
|
| 146 |
+
<h1 class="text-3xl font-bold mb-2 text-glow">PolyGlot</h1>
|
| 147 |
+
<p class="opacity-90">Select your languages to start chatting</p>
|
| 148 |
</div>
|
| 149 |
|
| 150 |
<div class="p-6">
|
|
|
|
| 212 |
<label class="block text-sm font-medium text-dark-300 mb-2">Your Name</label>
|
| 213 |
<input type="text" id="user-name" placeholder="Enter your name" class="w-full px-4 py-2 bg-dark-700 border border-dark-600 rounded-md focus:ring-2 focus:ring-primary-500 focus:border-transparent text-dark-100 placeholder-dark-400">
|
| 214 |
</div>
|
| 215 |
+
<div class="flex space-x-4 mt-4">
|
| 216 |
+
<button id="start-chat" class="flex-1 gradient-bg text-white py-3 rounded-md font-medium hover:opacity-90 transition duration-200 disabled:opacity-50 glow disabled:glow-none">
|
| 217 |
+
<i class="fas fa-comments mr-2"></i> Start Demo Chat
|
| 218 |
+
</button>
|
| 219 |
+
<button id="invite-partner" class="flex-1 bg-dark-600 text-white py-3 rounded-md font-medium hover:bg-dark-500 transition duration-200 border border-dark-500">
|
| 220 |
+
<i class="fas fa-user-plus mr-2"></i> Invite Partner
|
| 221 |
+
</button>
|
| 222 |
+
</div>
|
| 223 |
+
</div>
|
| 224 |
</div>
|
| 225 |
</div>
|
| 226 |
|
|
|
|
| 228 |
<div id="chat-screen" class="hidden flex flex-col h-screen">
|
| 229 |
<div class="gradient-bg text-white p-4 flex justify-between items-center shadow-lg">
|
| 230 |
<div>
|
| 231 |
+
<h1 class="text-xl font-bold text-glow">PolyGlot</h1>
|
| 232 |
+
<p class="text-xs opacity-80">Translating from <span id="from-lang" class="font-medium"></span> to <span id="to-lang" class="font-medium"></span></p>
|
| 233 |
</div>
|
| 234 |
<div id="participants-display" class="flex space-x-2">
|
| 235 |
<!-- Participants will be shown here -->
|
|
|
|
| 465 |
closeModalBtn.addEventListener('click', () => joinModal.classList.add('hidden'));
|
| 466 |
|
| 467 |
micButton.addEventListener('click', toggleSpeechRecognition);
|
|
|
|
| 468 |
// Initialize speech recognition when the page loads
|
| 469 |
initSpeechRecognition();
|
| 470 |
+
|
| 471 |
+
// Invite partner button
|
| 472 |
+
document.getElementById('invite-partner').addEventListener('click', () => {
|
| 473 |
+
const modal = document.createElement('invite-modal');
|
| 474 |
+
document.body.appendChild(modal);
|
| 475 |
+
|
| 476 |
+
modal.addEventListener('partner-invited', (e) => {
|
| 477 |
+
const { name, language } = e.detail;
|
| 478 |
+
startChatWithPartner(name, language);
|
| 479 |
+
});
|
| 480 |
+
});
|
| 481 |
+
// Functions
|
| 482 |
function generateChatId() {
|
| 483 |
// Generate a random 6-character alphanumeric code
|
| 484 |
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
|
|
| 503 |
button.innerHTML = '<i class="fas fa-copy"></i>';
|
| 504 |
}, 2000);
|
| 505 |
}
|
| 506 |
+
function startChatWithPartner(partnerName, partnerLanguage) {
|
|
|
|
| 507 |
const userName = userNameInput.value.trim();
|
| 508 |
if (!userName) return;
|
| 509 |
|
| 510 |
+
// Set current user
|
| 511 |
+
currentUser = {
|
| 512 |
+
id: 'user-' + Date.now(),
|
| 513 |
+
name: userName,
|
| 514 |
+
language: userLanguage
|
| 515 |
+
};
|
| 516 |
+
|
| 517 |
+
// Create partner
|
| 518 |
+
participants = [
|
| 519 |
+
currentUser,
|
| 520 |
+
{
|
| 521 |
+
id: 'partner-' + Date.now(),
|
| 522 |
+
name: partnerName,
|
| 523 |
+
language: partnerLanguage
|
| 524 |
+
}
|
| 525 |
+
];
|
| 526 |
+
|
| 527 |
+
// Update UI
|
| 528 |
+
languageScreen.classList.add('hidden');
|
| 529 |
+
chatScreen.classList.remove('hidden');
|
| 530 |
+
|
| 531 |
+
// Set language info
|
| 532 |
+
fromLangElement.textContent = languageData[userLanguage].name;
|
| 533 |
+
toLangElement.textContent = languageData[partnerLanguage].name;
|
| 534 |
+
welcomeMessage.textContent = `You're chatting in ${languageData[userLanguage].name} with ${partnerName} who speaks ${languageData[partnerLanguage].name}`;
|
| 535 |
+
|
| 536 |
+
// Update participants display
|
| 537 |
+
updateParticipantsDisplay();
|
| 538 |
+
|
| 539 |
+
// Update current user display
|
| 540 |
+
updateCurrentUserDisplay();
|
| 541 |
+
|
| 542 |
+
// Focus on input
|
| 543 |
+
messageInput.focus();
|
| 544 |
+
|
| 545 |
+
// Add welcome message
|
| 546 |
+
addSystemMessage(`${userName} started a chat with ${partnerName} (${languageData[userLanguage].name} ↔ ${languageData[partnerLanguage].name})`);
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
function startChat() {
|
| 550 |
+
const userName = userNameInput.value.trim();
|
| 551 |
+
if (!userName) return;
|
| 552 |
+
|
| 553 |
// Generate chat ID
|
| 554 |
chatId = generateChatId();
|
| 555 |
|
style.css
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
|
| 2 |
body {
|
| 3 |
font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
h1 {
|
| 6 |
font-size: 16px;
|
|
|
|
| 1 |
|
| 2 |
body {
|
| 3 |
font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
|
| 4 |
+
background-color: #0a0a0a;
|
| 5 |
+
color: #e5e5e5;
|
| 6 |
}
|
| 7 |
h1 {
|
| 8 |
font-size: 16px;
|