1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useContext } from "https://esm.sh/react@18.2.0";
3import { AuthContext } from "./App.tsx";
4
10 const [loading, setLoading] = useState(false);
11
12 const handleSubmit = async (e: React.FormEvent) => {
13 e.preventDefault();
14
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0";
3import { User, Task, Notification } from "../../shared/types.ts";
4import Login from "./Login.tsx";
12
13// Auth context
14export const AuthContext = React.createContext<{
15 user: User | null;
16 token: string | null;
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from "https://esm.sh/react@18.2.0";
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
4import App from "./components/App.tsx";
5
53 <div id="root"></div>
54
55 <!-- React and dependencies -->
56 <script type="module" src="/frontend/index.tsx"></script>
57
18โ โโโ index.ts # Main entry point for the backend
19โโโ frontend/
20โ โโโ components/ # React components
21โ โโโ index.html # Main HTML template
22โ โโโ index.tsx # Frontend entry point
28
29- **Backend**: Hono.js, SQLite
30- **Frontend**: React, Tailwind CSS
31- **Authentication**: JWT
32- **Real-time Updates**: Server-Sent Events
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState } from 'https://esm.sh/react@18.2.0';
3
4interface LoginFormProps {
7}
8
9const LoginForm: React.FC<LoginFormProps> = ({ onLogin, onCancel }) => {
10 const [username, setUsername] = useState('');
11 const [isLoading, setIsLoading] = useState(false);
12 const [error, setError] = useState<string | null>(null);
13
14 const handleSubmit = async (e: React.FormEvent) => {
15 e.preventDefault();
16
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from 'https://esm.sh/react@18.2.0';
3import { ChatRoom } from '../../shared/types.ts';
4
9}
10
11const ChatRoomList: React.FC<ChatRoomListProps> = ({ rooms, onSelectRoom, isLoading }) => {
12 // Get category emoji
13 const getCategoryEmoji = (category: string): string => {
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect, useRef } from 'https://esm.sh/react@18.2.0';
3import { ChatRoom as ChatRoomType, Message, User } from '../../shared/types.ts';
4
9}
10
11const ChatRoom: React.FC<ChatRoomProps> = ({ room, user, onClose }) => {
12 const [messages, setMessages] = useState<Message[]>([]);
13 const [newMessage, setNewMessage] = useState('');
47 };
48
49 const handleSendMessage = async (e: React.FormEvent) => {
50 e.preventDefault();
51
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState } from 'https://esm.sh/react@18.2.0';
3import { OpportunityInput, CATEGORIES } from '../../shared/types.ts';
4
8}
9
10const OpportunityForm: React.FC<OpportunityFormProps> = ({ onSubmit, onCancel }) => {
11 const [formData, setFormData] = useState<OpportunityInput>({
12 title: '',
20 const [error, setError] = useState<string | null>(null);
21
22 const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
23 const { name, value } = e.target;
24 setFormData(prev => ({ ...prev, [name]: value }));
25 };
26
27 const handleSubmit = async (e: React.FormEvent) => {
28 e.preventDefault();
29 setError(null);
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from 'https://esm.sh/react@18.2.0';
3import { Opportunity, formatDate } from '../../shared/types.ts';
4
7}
8
9const OpportunityCard: React.FC<OpportunityCardProps> = ({ opportunity }) => {
10 const categoryEmoji = getCategoryEmoji(opportunity.category);
11