fixed a bit

This commit is contained in:
bobbert committed 2025-03-12 01:46:45 +00:00
1 parent c62413eafa
commit 4ed0480d08
10 files changed
+76 -87

No files matched your search

+3 -3
View File
@@ -5,7 +5,7 @@ import { useRouter } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
export default function TeamPage({ params }) { export default function TeamPage({ params }) {
const { data: session, status } = useSession(); const { status } = useSession();
const [team, setTeam] = useState(null); const [team, setTeam] = useState(null);
const [teamMembers, setTeamMembers] = useState([]); const [teamMembers, setTeamMembers] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
@@ -88,9 +88,9 @@ export default function TeamPage({ params }) {
<div className="add-users-button">Add Users</div> <div className="add-users-button">Add Users</div>
<div className="users-container"> <div className="users-container">
{teamMembers.map((member, index) => ( {teamMembers.map((member) => (
<div key={member.id} className="user-card"> <div key={member.id} className="user-card">
User #{index + 1} {member.username}
</div> </div>
))} ))}
+23 -12
View File
@@ -1,29 +1,40 @@
// app/(main)/team/[teamId]/route.js
import { queryOne, query } from "../../../../lib/db";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../../../api/auth/[...nextauth]/route";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
import { queryOne, query } from "@/lib/db";
export async function GET(request, context) { export async function GET(_, context) {
const session = await getServerSession(authOptions); const session = await getServerSession(authOptions);
if (!session) { if (!session) {
// Redirect to login page instead of returning JSON
return redirect("/login"); return redirect("/login");
} }
try { try {
const { teamId } = context.params; const params = await context.params;
const teamId = params.teamId;
// Instead of returning JSON, we should let the page component handle rendering const team = await queryOne("SELECT * FROM teams WHERE id = ?", [teamId]);
// This route.js file should only be used for API endpoints, not page rendering
// Redirect to the page component if (!team) {
return redirect(`/team/${teamId}`); return new Response(
JSON.stringify({ success: false, error: "Team not found" }),
{ status: 404 }
);
}
const members = await query(
"SELECT id, username FROM users WHERE team_id = ?",
[teamId]
);
return new Response(JSON.stringify({ success: true, team, members }), {
status: 200,
});
} catch (error) { } catch (error) {
console.error("Team fetch error:", error); console.error("Team fetch error:", error);
return new Response( return new Response(
JSON.stringify({ error: "Failed to fetch team details" }), JSON.stringify({ success: false, error: "Failed to fetch team" }),
{ status: 500 } { status: 500 }
); );
} }
+16 -10
View File
@@ -1,17 +1,18 @@
// app/api/auth/[...nextauth]/route.js import NextAuth from "next-auth";
import NextAuth from 'next-auth'; import CredentialsProvider from "next-auth/providers/credentials";
import CredentialsProvider from 'next-auth/providers/credentials'; import { validateCredentials } from "@/actions/auth";
import { validateCredentials } from '../../../actions/auth';
export const authOptions = { export const authOptions = {
providers: [ providers: [
CredentialsProvider({ CredentialsProvider({
name: 'Credentials', id: "credentials",
name: "Credentials",
credentials: { credentials: {
username: { label: "Username", type: "text" }, username: { label: "Username", type: "text" },
password: { label: "Password", type: "password" } password: { label: "Password", type: "password" },
}, },
async authorize(credentials) { async authorize(credentials) {
try {
if (!credentials?.username || !credentials?.password) { if (!credentials?.username || !credentials?.password) {
return null; return null;
} }
@@ -22,8 +23,12 @@ export const authOptions = {
); );
return user; return user;
} catch (error) {
console.error("Auth error:", error);
return null;
} }
}) },
}),
], ],
callbacks: { callbacks: {
async jwt({ token, user }) { async jwt({ token, user }) {
@@ -44,14 +49,15 @@ export const authOptions = {
session.user.teamId = token.teamId; session.user.teamId = token.teamId;
} }
return session; return session;
} },
}, },
pages: { pages: {
signIn: '/login', signIn: "/login",
}, },
session: { session: {
strategy: "jwt", strategy: "jwt",
} },
secret: process.env.NEXTAUTH_SECRET,
}; };
const handler = NextAuth(authOptions); const handler = NextAuth(authOptions);
+1 -2
View File
@@ -1,9 +1,8 @@
// app/api/teams/[teamId]/route.js
import { queryOne, query } from "../../../../lib/db"; import { queryOne, query } from "../../../../lib/db";
import { getServerSession } from "next-auth/next"; import { getServerSession } from "next-auth/next";
import { authOptions } from "../../auth/[...nextauth]/route"; import { authOptions } from "../../auth/[...nextauth]/route";
export async function GET(request, { params }) { export async function GET({ params }) {
const session = await getServerSession(authOptions); const session = await getServerSession(authOptions);
if (!session) { if (!session) {
+2 -14
View File
@@ -1,4 +1,4 @@
import { queryOne, run } from "../../../../lib/db"; import { queryOne, run } from "@/lib/db";
import { getServerSession } from "next-auth/next"; import { getServerSession } from "next-auth/next";
import { authOptions } from "../../auth/[...nextauth]/route"; import { authOptions } from "../../auth/[...nextauth]/route";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
@@ -7,9 +7,6 @@ export async function POST(request) {
try { try {
const session = await getServerSession(authOptions); const session = await getServerSession(authOptions);
// Debugging: Log the session
console.log("Session:", session);
if (!session) { if (!session) {
return new Response( return new Response(
JSON.stringify({ success: false, error: "Unauthorised" }), JSON.stringify({ success: false, error: "Unauthorised" }),
@@ -17,7 +14,6 @@ export async function POST(request) {
); );
} }
// Ensure the user is not an admin
if (session.user.role === "admin") { if (session.user.role === "admin") {
return new Response( return new Response(
JSON.stringify({ success: false, error: "Admins cannot create teams" }), JSON.stringify({ success: false, error: "Admins cannot create teams" }),
@@ -34,27 +30,19 @@ export async function POST(request) {
); );
} }
// Generate a unique team code (6 characters)
const teamCode = nanoid(6).toUpperCase(); const teamCode = nanoid(6).toUpperCase();
// Insert the new team await run("INSERT INTO teams (name, code) VALUES (?, ?)", [name, teamCode]);
const result = await run("INSERT INTO teams (name, code) VALUES (?, ?)", [
name,
teamCode,
]);
// Fetch the newly created team ID
const newTeam = await queryOne("SELECT id FROM teams WHERE code = ?", [ const newTeam = await queryOne("SELECT id FROM teams WHERE code = ?", [
teamCode, teamCode,
]); ]);
// Update the user's team_id
await run("UPDATE users SET team_id = ? WHERE id = ?", [ await run("UPDATE users SET team_id = ? WHERE id = ?", [
newTeam.id, newTeam.id,
userId, userId,
]); ]);
// Update the session with the new teamId
session.user.teamId = newTeam.id; session.user.teamId = newTeam.id;
return new Response(JSON.stringify({ success: true, teamId: newTeam.id }), { return new Response(JSON.stringify({ success: true, teamId: newTeam.id }), {
+2 -2
View File
@@ -1,6 +1,6 @@
import { queryOne, query } from "../../../../lib/db"; import { queryOne } from "@/lib/db";
import { getServerSession } from "next-auth/next"; import { getServerSession } from "next-auth/next";
import { authOptions } from "../../auth/[...nextauth]/route"; import { authOptions } from "@/app/api/auth/[...nextauth]/route";
export async function POST(request) { export async function POST(request) {
const session = await getServerSession(authOptions); const session = await getServerSession(authOptions);
+2 -2
View File
@@ -1,5 +1,5 @@
import './globals.css'; import "./globals.css";
import { NextAuthProvider } from './providers'; import { NextAuthProvider } from "./providers";
export default function RootLayout({ children }) { export default function RootLayout({ children }) {
return ( return (
+24 -41
View File
@@ -1,69 +1,52 @@
// lib/db.js import sqlite3 from "sqlite3";
let sqlite3;
// Only import sqlite3 on server-side let db = null;
if (typeof window === 'undefined') {
sqlite3 = require('sqlite3').verbose();
}
// Initialize the database connection export function getDb() {
function getDb() { if (!db) {
if (!sqlite3) { db = new sqlite3.Database("./database.sqlite", (err) => {
console.error('Cannot access SQLite on the client side');
return null;
}
return new sqlite3.Database('./sqlite.db', (err) => {
if (err) { if (err) {
console.error('Error opening database:', err.message); console.error("Error connecting to database:", err);
} else { } else {
console.log('Connected to the SQLite database.'); console.log("Connected to the SQLite database.");
} }
}); });
} }
return db;
// Helper function to run queries with results
async function query(sql, params = []) {
if (typeof window !== 'undefined') {
throw new Error('Database queries cannot be executed on the client side');
} }
const db = getDb(); export function queryOne(sql, params = []) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.all(sql, params, (err, rows) => { getDb().get(sql, params, (err, row) => {
if (err) {
reject(err);
} else {
resolve(row);
}
});
});
}
export function query(sql, params = []) {
return new Promise((resolve, reject) => {
getDb().all(sql, params, (err, rows) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
resolve(rows); resolve(rows);
} }
db.close(); // Close the database connection
}); });
}); });
} }
// Helper for single row queries export function run(sql, params = []) {
async function queryOne(sql, params = []) {
const rows = await query(sql, params);
return rows && rows.length > 0 ? rows[0] : null;
}
// Helper for insert/update/delete operations
async function run(sql, params = []) {
if (typeof window !== 'undefined') {
throw new Error('Database operations cannot be executed on the client side');
}
const db = getDb();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.run(sql, params, function(err) { getDb().run(sql, params, function (err) {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
resolve({ lastID: this.lastID, changes: this.changes }); resolve({ lastID: this.lastID, changes: this.changes });
} }
db.close(); // Close the database connection
}); });
}); });
} }
module.exports = { query, queryOne, run };
+3 -1
View File
@@ -2,11 +2,13 @@
"name": "clue-hunt-app", "name": "clue-hunt-app",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"type": "module",
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint",
"init-db": "node lib/init-db.js"
}, },
"dependencies": { "dependencies": {
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
BIN
View File
Binary file not shown.