5## Structure
67- `utils.ts` - Shared types and utility functions
89## Contents
1011- TypeScript interfaces for Jobs and Messages
12- Utility functions for date formatting
13- HTML sanitization functions to prevent XSS attacks
14- Job posting form
15- Job listings display
16- Real-time chat functionality
1718## Technologies
8- `database/` - Database setup and queries
9- `migrations.ts` - Database schema definitions
10- `queries.ts` - Database query functions
1112## API Endpoints
3839// Check if user is logged in
40function checkAuth() {
41if (username) {
42loginScreen.classList.add("hidden");
49}
5051// Login functionality
52loginButton.addEventListener("click", () => {
53const inputUsername = usernameInput.value.trim();
68});
6970// Logout functionality
71logoutButton.addEventListener("click", () => {
72username = "";
7677// Load jobs from API
78async function loadJobs() {
79try {
80const response = await fetch("/api/jobs");
9091// Render jobs to the DOM
92function renderJobs() {
93if (jobs.length === 0) {
94jobsContainer.innerHTML = '<div class="text-gray-500 text-center">No jobs posted yet. Be the first!</div>';
142143// Load chat messages
144async function loadMessages() {
145try {
146const response = await fetch("/api/messages");
157158// Render messages to the DOM
159function renderMessages() {
160if (messages.length === 0) {
161chatContainer.innerHTML = '<div class="text-gray-500 text-center">No messages yet. Start the conversation!</div>';
211212// Poll for new messages every 5 seconds
213function startMessagePolling() {
214setInterval(loadMessages, 5000);
215}
1718// Format date for display
19export function formatDate(timestamp: number): string {
20return new Date(timestamp).toLocaleString();
21}
2223// Sanitize HTML to prevent XSS
24export function sanitizeHTML(str: string): string {
25return str
26.replace(/&/g, "&")
zayqueries.ts4 matches
2021// Job queries
22export async function getAllJobs(): Promise<Job[]> {
23const result = await sqlite.execute<Job>(
24`SELECT * FROM ${JOBS_TABLE} ORDER BY created_at DESC`
27}
2829export async function createJob(job: Omit<Job, "id" | "created_at">): Promise<Job> {
30const created_at = Date.now();
31const result = await sqlite.execute<{ id: number }>(
4445// Message queries
46export async function getRecentMessages(limit = 50): Promise<Message[]> {
47const result = await sqlite.execute<Message>(
48`SELECT * FROM ${MESSAGES_TABLE}
54}
5556export async function createMessage(message: Omit<Message, "id" | "created_at">): Promise<Message> {
57const created_at = Date.now();
58const result = await sqlite.execute<{ id: number }>(
zaymigrations.ts1 match
8* Initialize database tables
9*/
10export async function initDatabase() {
11// Create jobs table
12await sqlite.execute(`
27## Getting Started
2829Visit the app and start by entering a username to access the job board and chat functionality.
2// This Val serves a mobile-friendly web application to practice French numbers
34export default async function(req: Request): Promise<Response> {
5// HTML content with embedded JavaScript and CSS
6const html = `<!DOCTYPE html>
155156// Generate a random number between min and max (inclusive)
157function getRandomNumber(min, max) {
158return Math.floor(Math.random() * (max - min + 1)) + min;
159}
160161// Generate a new announcement
162function generateAnnouncement() {
163// Reset feedback
164document.getElementById('feedback').classList.add('hidden');
217218// Play the announcement using text-to-speech
219function playAnnouncement() {
220if (!window.speechSynthesis) {
221alert("Sorry, your browser doesn't support text-to-speech!");
235236// Check the user's answer
237function checkAnswer() {
238const userAnswer = document.getElementById('userAnswer').value.trim();
239const userNumbers = userAnswer.split(',').map(num => parseInt(num.trim())).filter(num => !isNaN(num));
8*/
910export default async function(req: Request): Promise<Response> {
11// Clone the request to safely read the body
12const reqClone = req.clone();