Add README and initial project structure for WebSocket chat application

* Created README.md for project overview and setup instructions.
* Updated App component to use selector for todo items.
* Enhanced TodoItemComponent styling and structure.
* Introduced new Redux selectors for better state management.
* Added initial configuration files for RequireJS and Bun.
* Established project structure for WebSocket chat application with server and frontend components.
* Included necessary dependencies and configurations for TypeScript and Vite.
This commit is contained in:
2025-09-30 03:19:52 -04:00
parent 0cc0ce13e7
commit 0345f3d2d0
71 changed files with 996 additions and 1065 deletions

View File

@@ -0,0 +1,84 @@
const websocketStatus = document.getElementById('websocket-status') as HTMLSpanElement;
const messages = document.getElementById('messages') as HTMLUListElement;
const messageInput = document.getElementById('message-input') as HTMLInputElement;
const sendButton = document.getElementById('send-button') as HTMLButtonElement;
const loginDialog = document.getElementById('login-dialog') as HTMLDialogElement;
const usernameInput = document.getElementById('username-input') as HTMLInputElement;
const loginForm = document.getElementById('login-form') as HTMLFormElement;
let username: string = '';
let websocket: WebSocket;
window.addEventListener('beforeunload', () => {
disconnect(websocket);
});
function connect(): Promise<WebSocket> {
return new Promise((resolve, reject) => {
websocket = new WebSocket(`ws://${window.location.hostname}:4444`)
websocket.onopen = () => {
websocketStatus.textContent = 'Connected';
websocket.send(JSON.stringify({
type: 'login',
username
}));
resolve(websocket);
};
websocket.onerror = (event) => {
reject(event);
};
websocket.onclose = () => {
websocketStatus.textContent = 'Offline';
};
websocket.onclose = () => {
websocketStatus.textContent = 'Offline';
};
websocket.onerror = (event: Event) => {
websocketStatus.textContent = `Error [${event.toString()}]`;
};
websocket.onmessage = (event) => {
console.log('WebSocket message received:', event.data);
const message = document.createElement('li');
message.textContent = event.data;
messages.appendChild(message);
};
sendButton.onclick = () => sendMessage(websocket, messageInput.value);
});
}
function disconnect(websocket: WebSocket) {
websocket.close();
}
function login() {
connect();
loginDialog.close();
}
function sendMessage(websocket: WebSocket, message: string) {
if (!message) {
return;
}
console.log('Sending message:', message);
websocket.send(message);
messageInput.value = '';
}
loginForm.onsubmit = (event) => {
event.preventDefault();
loginDialog.close();
login(usernameInput.value);
};
loginDialog.showModal();

View File

@@ -0,0 +1,49 @@
body {
background-color: #f0f0f0;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
h3 {
text-align: center;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.flex-column-container {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.flex-row-container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.flex-item {
flex: 1;
}
#login-button {
margin: 10px auto;
width: 100%;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
#login-button:hover {
background-color: #0056b3;
}

View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />