3import { setCookie, getCookie } from "https://esm.sh/hono@3.11.7/cookie";
4import { getUserByEmail, createUser } from "../database/queries.ts";
5import type { LoginRequest, SignupRequest, ApiResponse } from "../../shared/types.ts";
6import { validateEmail, validatePassword } from "../../shared/utils.ts";
73132if (!email || !password) {
33return c.json<ApiResponse>({
34success: false,
35error: "Email and password are required"
3839if (!validateEmail(email)) {
40return c.json<ApiResponse>({
41success: false,
42error: "Invalid email format"
46const user = await getUserByEmail(email);
47if (!user) {
48return c.json<ApiResponse>({
49success: false,
50error: "Invalid credentials"
54const isValidPassword = await verifyPassword(password, user.passwordHash);
55if (!isValidPassword) {
56return c.json<ApiResponse>({
57success: false,
58error: "Invalid credentials"
78const { passwordHash, ...userWithoutPassword } = user;
7980return c.json<ApiResponse>({
81success: true,
82data: {
88} catch (error) {
89console.error("Login error:", error);
90return c.json<ApiResponse>({
91success: false,
92error: "Internal server error"
102103if (!email || !password || !firstName || !lastName) {
104return c.json<ApiResponse>({
105success: false,
106error: "All fields are required"
109110if (!validateEmail(email)) {
111return c.json<ApiResponse>({
112success: false,
113error: "Invalid email format"
117const passwordValidation = validatePassword(password);
118if (!passwordValidation.isValid) {
119return c.json<ApiResponse>({
120success: false,
121error: passwordValidation.errors.join(", ")
126const existingUser = await getUserByEmail(email);
127if (existingUser) {
128return c.json<ApiResponse>({
129success: false,
130error: "User with this email already exists"
157});
158159return c.json<ApiResponse>({
160success: true,
161data: {
167} catch (error) {
168console.error("Signup error:", error);
169return c.json<ApiResponse>({
170success: false,
171error: "Internal server error"
183});
184185return c.json<ApiResponse>({
186success: true,
187message: "Logged out successfully"
195
196if (!token) {
197return c.json<ApiResponse>({
198success: false,
199error: "No authentication token provided"
205
206if (!user) {
207return c.json<ApiResponse>({
208success: false,
209error: "User not found"
213const { passwordHash, ...userWithoutPassword } = user;
214215return c.json<ApiResponse>({
216success: true,
217data: userWithoutPassword
219} catch (error) {
220console.error("Auth verification error:", error);
221return c.json<ApiResponse>({
222success: false,
223error: "Invalid or expired token"
232
233if (!token) {
234return c.json<ApiResponse>({
235success: false,
236error: "Authentication required"
243await next();
244} catch (error) {
245return c.json<ApiResponse>({
246success: false,
247error: "Invalid or expired token"
255
256if (!user || !user.isAdmin) {
257return c.json<ApiResponse>({
258success: false,
259error: "Admin access required"
112const checkAuth = async () => {
113try {
114const response = await fetch('/api/auth/me', {
115credentials: 'include'
116});
129const loadCart = async () => {
130try {
131const response = await fetch('/api/cart', {
132credentials: 'include'
133});
Jobpostingsindex.ts3 matches
15await runMigrations();
1617// API routes
18app.route("/api/jobs", jobsRouter);
19app.route("/api/chat", chatRouter);
2021// Serve static files
JobpostingsChatRoom.tsx5 matches
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect, useRef } from "https://esm.sh/react@18.2.0?deps=react@18.2.0";
3import type { ChatMessage, CreateChatMessageRequest, ApiResponse } from "../../shared/types.ts";
45export default function ChatRoom() {
19const fetchMessages = async () => {
20try {
21const response = await fetch('/api/chat/messages');
22const data: ApiResponse<ChatMessage[]> = await response.json();
23
24if (data.success && data.data) {
63};
6465const response = await fetch('/api/chat/messages', {
66method: 'POST',
67headers: {
71});
7273const data: ApiResponse<ChatMessage> = await response.json();
7475if (data.success) {
JobpostingsJobForm.tsx3 matches
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState } from "https://esm.sh/react@18.2.0?deps=react@18.2.0";
3import type { CreateJobRequest, ApiResponse, Job } from "../../shared/types.ts";
45interface JobFormProps {
2728try {
29const response = await fetch('/api/jobs', {
30method: 'POST',
31headers: {
35});
3637const data: ApiResponse<Job> = await response.json();
3839if (data.success) {
JobpostingsJobBoard.tsx5 matches
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0?deps=react@18.2.0";
3import JobForm from "./JobForm.tsx";
4import type { Job, ApiResponse } from "../../shared/types.ts";
56export default function JobBoard() {
14try {
15setLoading(true);
16const response = await fetch('/api/jobs');
17const data: ApiResponse<Job[]> = await response.json();
18
19if (data.success && data.data) {
4546try {
47const response = await fetch(`/api/jobs/${jobId}`, {
48method: 'DELETE',
49});
50
51const data: ApiResponse<{ deleted: boolean }> = await response.json();
52
53if (data.success) {
1import { Hono } from "https://esm.sh/hono@3.11.7";
2import { getRecentMessages, createMessage } from "../database/queries.ts";
3import type { CreateMessageRequest, ApiResponse } from "../../shared/types.ts";
45const chat = new Hono();
9try {
10const messages = await getRecentMessages();
11const response: ApiResponse<typeof messages> = {
12success: true,
13data: messages
15return c.json(response);
16} catch (error) {
17const response: ApiResponse<never> = {
18success: false,
19error: "Failed to fetch messages"
30// Basic validation
31if (!messageData.username || !messageData.message) {
32const response: ApiResponse<never> = {
33success: false,
34error: "Username and message are required"
4243if (messageData.username.length > 50) {
44const response: ApiResponse<never> = {
45success: false,
46error: "Username must be 50 characters or less"
5051if (messageData.message.length > 500) {
52const response: ApiResponse<never> = {
53success: false,
54error: "Message must be 500 characters or less"
5859if (messageData.message.length === 0) {
60const response: ApiResponse<never> = {
61success: false,
62error: "Message cannot be empty"
6667const newMessage = await createMessage(messageData);
68const response: ApiResponse<typeof newMessage> = {
69success: true,
70data: newMessage
72return c.json(response, 201);
73} catch (error) {
74const response: ApiResponse<never> = {
75success: false,
76error: "Failed to send message"
1import { Hono } from "https://esm.sh/hono@3.11.7";
2import { getAllJobs, createJob, deleteJob } from "../database/queries.ts";
3import type { CreateJobRequest, ApiResponse } from "../../shared/types.ts";
45const jobs = new Hono();
9try {
10const jobList = await getAllJobs();
11const response: ApiResponse<typeof jobList> = {
12success: true,
13data: jobList
15return c.json(response);
16} catch (error) {
17const response: ApiResponse<never> = {
18success: false,
19error: "Failed to fetch jobs"
31if (!jobData.title || !jobData.company || !jobData.description ||
32!jobData.location || !jobData.salary || !jobData.contact_email) {
33const response: ApiResponse<never> = {
34success: false,
35error: "All fields are required"
3940const newJob = await createJob(jobData);
41const response: ApiResponse<typeof newJob> = {
42success: true,
43data: newJob
45return c.json(response, 201);
46} catch (error) {
47const response: ApiResponse<never> = {
48success: false,
49error: "Failed to create job"
58const id = parseInt(c.req.param("id"));
59if (isNaN(id)) {
60const response: ApiResponse<never> = {
61success: false,
62error: "Invalid job ID"
67const deleted = await deleteJob(id);
68if (!deleted) {
69const response: ApiResponse<never> = {
70success: false,
71error: "Job not found"
74}
7576const response: ApiResponse<{ deleted: boolean }> = {
77success: true,
78data: { deleted: true }
80return c.json(response);
81} catch (error) {
82const response: ApiResponse<never> = {
83success: false,
84error: "Failed to delete job"
Jobpostingschat.ts9 matches
1import { Hono } from "https://esm.sh/hono@3.11.7";
2import { getChatMessages, createChatMessage } from "../database/queries.ts";
3import type { CreateChatMessageRequest, ApiResponse } from "../../shared/types.ts";
45const chat = new Hono();
10const limit = parseInt(c.req.query("limit") || "50");
11const messages = await getChatMessages(limit);
12return c.json({ success: true, data: messages } as ApiResponse<typeof messages>);
13} catch (error) {
14return c.json({ success: false, error: "Failed to fetch messages" } as ApiResponse<never>, 500);
15}
16});
26success: false,
27error: "Missing required fields: username, message"
28} as ApiResponse<never>, 400);
29}
3034success: false,
35error: "Message too long. Maximum 500 characters."
36} as ApiResponse<never>, 400);
37}
3842success: false,
43error: "Username too long. Maximum 50 characters."
44} as ApiResponse<never>, 400);
45}
4655success: false,
56error: "Username and message cannot be empty"
57} as ApiResponse<never>, 400);
58}
5960const newMessage = await createChatMessage(sanitizedMessage);
61return c.json({ success: true, data: newMessage } as ApiResponse<typeof newMessage>, 201);
62} catch (error) {
63return c.json({ success: false, error: "Failed to create message" } as ApiResponse<never>, 500);
64}
65});