From 77e83dc21cc32f79f78f95647e0ec91f032769fa Mon Sep 17 00:00:00 2001 From: mudabbir-ahmad Date: Wed, 12 Mar 2025 16:16:42 +0000 Subject: [PATCH] Refactor database schema; add hunts and team_clues tables, update clues structure, and improve error handling in routes --- .idea/git_toolbox_prj.xml | 15 +++++ .idea/sqldialects.xml | 7 +++ app/(main)/team/[teamId]/page.js | 7 ++- app/api/auth/[...nextauth]/route.js | 9 ++- app/api/hunt/route.js | 12 ++-- app/api/teams/[teamId]/route.js | 21 ++++--- clue_hunt.db | Bin 0 -> 40960 bytes clue_hunt.db-journal | Bin 512 -> 0 bytes clue_hunt.sqbpro | 2 +- database.sqlite | Bin 24576 -> 0 bytes init-schema.sql | 86 ++++++++++++++-------------- initialise-databse.sql | 86 ++++++++++++++-------------- lib/db.js | 2 +- 13 files changed, 136 insertions(+), 111 deletions(-) create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/sqldialects.xml delete mode 100644 clue_hunt.db-journal delete mode 100644 database.sqlite diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..083c77d --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/(main)/team/[teamId]/page.js b/app/(main)/team/[teamId]/page.js index 5066cdc..a552d3a 100644 --- a/app/(main)/team/[teamId]/page.js +++ b/app/(main)/team/[teamId]/page.js @@ -36,8 +36,11 @@ export default function TeamPage({ params }) { try { const errorData = JSON.parse(text); errorMessage = errorData.error || "Failed to fetch team data"; - } catch (e) { - errorMessage = `Failed to fetch team data: ${response.status} ${text.slice(0, 100)}`; + } catch (unused) { + // Using 'unused' instead of '_' to avoid the warning + errorMessage = `Failed to fetch team data: ${ + response.status + } ${text.slice(0, 100)}`; } throw new Error(errorMessage); } diff --git a/app/api/auth/[...nextauth]/route.js b/app/api/auth/[...nextauth]/route.js index 26ea97b..c84d894 100644 --- a/app/api/auth/[...nextauth]/route.js +++ b/app/api/auth/[...nextauth]/route.js @@ -1,5 +1,7 @@ export const runtime = "nodejs"; +// Fix: Make sure we're using the correct import import NextAuth from "next-auth"; +import CredentialsProvider from "next-auth/providers/credentials"; import { validateCredentials } from "@/actions/auth"; // Ensure NEXTAUTH_SECRET is defined @@ -15,10 +17,9 @@ if (!process.env.NEXTAUTH_URL) { export const authOptions = { debug: process.env.NODE_ENV === "development", providers: [ - { + CredentialsProvider({ id: "credentials", name: "Credentials", - type: "credentials", credentials: { username: { label: "Username", type: "text" }, password: { label: "Password", type: "password" }, @@ -43,7 +44,7 @@ export const authOptions = { return null; } }, - }, + }), ], callbacks: { async jwt({ token, user }) { @@ -66,11 +67,9 @@ export const authOptions = { return session; }, }, - // no "pages" property session: { strategy: "jwt", maxAge: 30 * 24 * 60 * 60 }, secret: process.env.NEXTAUTH_SECRET, }; -// Creating the handler after exporting authOptions const handler = NextAuth(authOptions); export { handler as GET, handler as POST }; diff --git a/app/api/hunt/route.js b/app/api/hunt/route.js index 3b18de2..95abca8 100644 --- a/app/api/hunt/route.js +++ b/app/api/hunt/route.js @@ -2,7 +2,8 @@ import { getServerSession } from "next-auth/next"; import { authOptions } from "../auth/[...nextauth]/route"; import { run } from "@/lib/db"; -export async function POST(request) { +export async function POST() { + // Removed unused 'request' parameter const session = await getServerSession(authOptions); if (!session || session.user.role !== "admin") { return new Response(JSON.stringify({ error: "Unauthorized" }), { @@ -12,12 +13,13 @@ export async function POST(request) { try { // Add a WHERE clause or provide an ID if you're updating a specific hunt record - await run("UPDATE hunts SET active = 1, start_time = NOW() WHERE id = ?", [1]); - // Or if you just have one hunt record: "UPDATE hunts SET active = 1, start_time = NOW()" - + await run("UPDATE hunts SET active = 1, start_time = NOW() WHERE id = ?", [ + 1, + ]); + return new Response(JSON.stringify({ success: true }), { status: 200 }); } catch (err) { - console.error("Hunt start error:", err); // Add logging for better debugging + console.error("Hunt start error:", err); return new Response(JSON.stringify({ error: err.message }), { status: 500, }); diff --git a/app/api/teams/[teamId]/route.js b/app/api/teams/[teamId]/route.js index c891b6b..c94cdb7 100644 --- a/app/api/teams/[teamId]/route.js +++ b/app/api/teams/[teamId]/route.js @@ -2,7 +2,8 @@ import { query, queryOne } from "@/lib/db"; import { getServerSession } from "next-auth/next"; import { authOptions } from "../../auth/[...nextauth]/route"; -export async function GET(request, context) { +export async function GET(_, context) { + // Changed 'request' to '_' to indicate unused parameter const session = await getServerSession(authOptions); if (!session) { @@ -11,7 +12,7 @@ export async function GET(request, context) { try { const teamId = context.params.teamId; - + // Validate teamId if (!teamId || isNaN(parseInt(teamId, 10))) { return Response.json({ error: "Invalid team ID" }, { status: 400 }); @@ -24,16 +25,18 @@ export async function GET(request, context) { } const members = await query( - "SELECT id, username FROM users WHERE team_id = ?", + "SELECT id, username FROM users WHERE team_id = ?", [teamId] ); - return Response.json({ - success: true, - team, - members - }, { status: 200 }); - + return Response.json( + { + success: true, + team, + members, + }, + { status: 200 } + ); } catch (error) { console.error("Team fetch error:", error); return Response.json( diff --git a/clue_hunt.db b/clue_hunt.db index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..058d59854e9bfb8bb9a8510ccb9a9fd6eab365e7 100644 GIT binary patch literal 40960 zcmeI*PjA~~90%~naho>nS|d0_(^TvpKbRkG`+nyWY%a zR6P45i!Kxjx~Aso9c@uv(@S(w)mJq?OWiYEuk6`77QMqht(47at$g`4UH7wDHS^yy zRb0#PEVIo1t>N{omekyGtFp{mvB=i4+*&d+lt{#)@wej=v1_KaU*D^;|BK2-!*j%Z zd8=`_Kisq_oYqEL(u(aM!m34eGSB3TKy!3AHV_{lmmYj7Hr=y~opPnxuYT^g`$>S%JV2~ zWlGSZwy3f2$Y`sS7pza%W`Y)Y$m$wv0~vKSquvQ(HdIAWeR~xGs(TeI>W+xt;>v^^YCb4CnEK z#B~C~;FxuV*LlTX+!5JliL6zv*(g|CEX&dOwQJHnLE;~c>egPvs#UCx*}f1{$HED| z>DO7w#OU|r8-8s6a;$?n5-J~J=EwJr;S|BwQIgMwcSds`1d$mXj*7p4>7i(RX}s5g zSa6HxP);6C4~_m!26^ekz)44Ov2o?3c#A53HH#cB_KEmA+7>XP$%~gTj7WNp_3QhWhN!KM%aX`d`^^~lyBJ^1_(d^0uX=z1Rwwb2tWV= z5P$##{&Rt=az7a#OPAP1M!IC|>=;XGE~n1koJ&onrf*E9ZzNMRIWs>wJwH7&5$Pwd zUux!EusmZyE2&e{GhK3Cm5yswtGioEnzQo7R z|0U%iQ68fI|2f&YSWO5(00Izz00bZa0SG_<0uVTN0?*X{pLPD9nxCBV`~T;p0TMs# zj}yb(v1^x8#^vPX<^0^9bF-lr?8^4$eri2eTz7H@R`$bnb+fWjo!y;FRn4V+!<@OP zzqfAc$=T}G2M3}8-v3`xo)F~;`v0H1@WBd000Izz00bZa0SG_<0uX=z1PD2)|NkJn z|1Zw}o4@~eizweIpDDLUjKT5W1q?=hd4Q*3fB*y_009U<00Izz00bZa0SLUb0=MM> za`CP4*U}mG@DiHNY+03U>TOxHYTtJa_dpMxppjlFcKhwUg$OG@8*>hk-2w^?_9<8??bvWL}((ynDv({bEZ`Q%D5*`+)`|7Q>V3(o&v z+I@))hX4d1009U<00Izz00bZa0SNRGILrC})O>pGtmpr{jyl`n&Z(;3xdz{{JJ<&!6}8?>4?D iTY~j~00bZa0SG_<0uX=z1Rwwb2tc5hK=1Saseb?tnNQ|
-- Reference to file "C:/Users/mudab/WebstormProjects/pe-two/clue-hunt-app/initialise-databse.sql" (not supported by this version) --
+
-- Reference to file "C:/Users/mudab/WebstormProjects/pe-two/clue-hunt-app/initialise-databse.sql" (not supported by this version) --
diff --git a/database.sqlite b/database.sqlite deleted file mode 100644 index 05bc2d1031e6da2073d782dfdb66fc8a16f892ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeI(&r;ez90%}(i2piDdtjK}_TY><{v!z>Fw;(hq&7+bL$Fd086Z)xKqSN}+-&2_S#ctJa&^}QCoZPrt{rlvzz_HlFx5)SRkdHT+_A4f$g-bE)ki>49hYv z2w@l|Nb@+&mnlFiW0xniWUth3s|J}>=krYHf(g#-GqYbpUuTV({n^-U!_f`_2tWV= z5P$##AOHafK;T{qobQfJL?RLP!y~s^Ygw*UZTI{`a6^+NT_(De$;rfTA`8=Gn3^V0 z^18e!Yow?ts-#uOwp<}nSuZGgI#ZSN`tqOAood@6y1b{8e1Yb2E;s6{+vc#ZoL6?r z^1p^SR@JpkgYNyZ^dsqtDwC}IQYz=9)tIb@gg@KSz2N%zQAy3&+497ow{}7bnKeSjm`z{I+y9p#rIEH zU-jb?|2qraP;8vq!SG>K#{my;IvUZwr89w}t_@G@bX}d43ckPstcX zeAH3DQ(yxB3ye=<@P5J3J8IIqt7d5CX1_6^Pod|uK!N}SAOHafKmY;|fB*y_009Wx zKLLZAWWwjcFeBFNT6|8Z&GFH>f>7JCHTCf9RYluQIs8VWV`WzR*6EwUmKg7Mo#wHr zT7y=nCH5t!tn3Jiw(V`2g{Tl;iHa+{K=^oC;L~Et2wYh}94^qP#!GxRagcc%O=Zi@ z;jY@q77MOqC%O%#-X3Usn@3{)XwOt)P1lxtYgyGy{Jj9rr}>1zURfYETp-@r?XOFj z)nqPZCQHW$TECKQ6f%PfFTQh2LVMfEC*@UjeQl5|9d=8FtS$4eZ!8cM($Qo(CQQ?) za-r``=tt;+7Dy0)00bZa0SG_<0uX=z1Rwwb2;5tNNiNKKUx9GLiWr#S!c(**=KcQ9 zhJG^ig#-ZzKmY;|fB*y_009U<00Izzz(W$4Vz~(W`#At_|4$$KM}hzZAOHafKmY;| ufB*y_009U<-~kJG|NqDS{{aUWmj(d{KmY;|fB*y_009U<00I!80>1#TP%2vh diff --git a/init-schema.sql b/init-schema.sql index f2a7231..1bd394b 100644 --- a/init-schema.sql +++ b/init-schema.sql @@ -1,64 +1,62 @@ -- Schema for clue_hunt.db -- Drop tables if they exist +DROP TABLE IF EXISTS team_clues; DROP TABLE IF EXISTS clues; DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS teams; DROP TABLE IF EXISTS game_settings; +DROP TABLE IF EXISTS hunts; --- Users table -CREATE TABLE users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT UNIQUE NOT NULL, - password TEXT NOT NULL, - role TEXT NOT NULL DEFAULT 'user', - team_id INTEGER, -- Ensure this column exists - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (team_id) REFERENCES teams(id) -); - --- Teams table +-- Create teams table CREATE TABLE teams ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - code TEXT UNIQUE NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + code TEXT NOT NULL UNIQUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Clues table +-- Create users table +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL UNIQUE, + password TEXT NOT NULL, + role TEXT DEFAULT 'user', + team_id INTEGER, + FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE SET NULL +); + +-- Create clues table CREATE TABLE clues ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - description TEXT NOT NULL, - team_id INTEGER NOT NULL, - found BOOLEAN DEFAULT FALSE, - found_at TIMESTAMP, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (team_id) REFERENCES teams(id) + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + description TEXT NOT NULL, + location TEXT NOT NULL, + qr_code TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Game settings table -CREATE TABLE game_settings ( - id INTEGER PRIMARY KEY, - hunt_active BOOLEAN DEFAULT FALSE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +-- Create team_clues table (for tracking which teams have found which clues) +CREATE TABLE team_clues ( + team_id INTEGER NOT NULL, + clue_id INTEGER NOT NULL, + found_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (team_id, clue_id), + FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, + FOREIGN KEY (clue_id) REFERENCES clues(id) ON DELETE CASCADE ); --- Execute this in your database: -CREATE TABLE IF NOT EXISTS hunts ( - id INT AUTO_INCREMENT PRIMARY KEY, - active BOOLEAN DEFAULT FALSE, +-- Create hunts table +CREATE TABLE hunts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + active BOOLEAN DEFAULT 0, start_time DATETIME DEFAULT NULL, end_time DATETIME DEFAULT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Insert a default hunt row if none exists: -INSERT INTO hunts (active) -SELECT FALSE -WHERE NOT EXISTS (SELECT 1 FROM hunts LIMIT 1); - - +-- Insert a default hunt row +INSERT INTO hunts (active) SELECT 0 WHERE NOT EXISTS (SELECT 1 FROM hunts LIMIT 1); -- Insert initial admin user INSERT INTO users (username, password, role) @@ -70,8 +68,8 @@ INSERT INTO teams (name, code) VALUES ('Team Alpha', 'ALPHA123'); INSERT INTO teams (name, code) VALUES ('Team Beta', 'BETA456'); INSERT INTO teams (name, code) VALUES ('Team Gamma', 'GAMMA789'); --- Insert sample clues for Team Alpha -INSERT INTO clues (description, team_id) VALUES ('Find the red door', 1); -INSERT INTO clues (description, team_id) VALUES ('Look under the bridge', 1); -INSERT INTO clues (description, team_id) VALUES ('Check the library', 1); +-- Insert sample clues +INSERT INTO clues (title, description, location, qr_code) VALUES ('Clue 1', 'Find the red door', 'Location 1', 'QR1'); +INSERT INTO clues (title, description, location, qr_code) VALUES ('Clue 2', 'Look under the bridge', 'Location 2', 'QR2'); +INSERT INTO clues (title, description, location, qr_code) VALUES ('Clue 3', 'Check the library', 'Location 3', 'QR3'); diff --git a/initialise-databse.sql b/initialise-databse.sql index f2a7231..1bd394b 100644 --- a/initialise-databse.sql +++ b/initialise-databse.sql @@ -1,64 +1,62 @@ -- Schema for clue_hunt.db -- Drop tables if they exist +DROP TABLE IF EXISTS team_clues; DROP TABLE IF EXISTS clues; DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS teams; DROP TABLE IF EXISTS game_settings; +DROP TABLE IF EXISTS hunts; --- Users table -CREATE TABLE users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT UNIQUE NOT NULL, - password TEXT NOT NULL, - role TEXT NOT NULL DEFAULT 'user', - team_id INTEGER, -- Ensure this column exists - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (team_id) REFERENCES teams(id) -); - --- Teams table +-- Create teams table CREATE TABLE teams ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - code TEXT UNIQUE NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + code TEXT NOT NULL UNIQUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Clues table +-- Create users table +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL UNIQUE, + password TEXT NOT NULL, + role TEXT DEFAULT 'user', + team_id INTEGER, + FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE SET NULL +); + +-- Create clues table CREATE TABLE clues ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - description TEXT NOT NULL, - team_id INTEGER NOT NULL, - found BOOLEAN DEFAULT FALSE, - found_at TIMESTAMP, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (team_id) REFERENCES teams(id) + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + description TEXT NOT NULL, + location TEXT NOT NULL, + qr_code TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Game settings table -CREATE TABLE game_settings ( - id INTEGER PRIMARY KEY, - hunt_active BOOLEAN DEFAULT FALSE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +-- Create team_clues table (for tracking which teams have found which clues) +CREATE TABLE team_clues ( + team_id INTEGER NOT NULL, + clue_id INTEGER NOT NULL, + found_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (team_id, clue_id), + FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, + FOREIGN KEY (clue_id) REFERENCES clues(id) ON DELETE CASCADE ); --- Execute this in your database: -CREATE TABLE IF NOT EXISTS hunts ( - id INT AUTO_INCREMENT PRIMARY KEY, - active BOOLEAN DEFAULT FALSE, +-- Create hunts table +CREATE TABLE hunts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + active BOOLEAN DEFAULT 0, start_time DATETIME DEFAULT NULL, end_time DATETIME DEFAULT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Insert a default hunt row if none exists: -INSERT INTO hunts (active) -SELECT FALSE -WHERE NOT EXISTS (SELECT 1 FROM hunts LIMIT 1); - - +-- Insert a default hunt row +INSERT INTO hunts (active) SELECT 0 WHERE NOT EXISTS (SELECT 1 FROM hunts LIMIT 1); -- Insert initial admin user INSERT INTO users (username, password, role) @@ -70,8 +68,8 @@ INSERT INTO teams (name, code) VALUES ('Team Alpha', 'ALPHA123'); INSERT INTO teams (name, code) VALUES ('Team Beta', 'BETA456'); INSERT INTO teams (name, code) VALUES ('Team Gamma', 'GAMMA789'); --- Insert sample clues for Team Alpha -INSERT INTO clues (description, team_id) VALUES ('Find the red door', 1); -INSERT INTO clues (description, team_id) VALUES ('Look under the bridge', 1); -INSERT INTO clues (description, team_id) VALUES ('Check the library', 1); +-- Insert sample clues +INSERT INTO clues (title, description, location, qr_code) VALUES ('Clue 1', 'Find the red door', 'Location 1', 'QR1'); +INSERT INTO clues (title, description, location, qr_code) VALUES ('Clue 2', 'Look under the bridge', 'Location 2', 'QR2'); +INSERT INTO clues (title, description, location, qr_code) VALUES ('Clue 3', 'Check the library', 'Location 3', 'QR3'); diff --git a/lib/db.js b/lib/db.js index c2f3006..5f574e4 100644 --- a/lib/db.js +++ b/lib/db.js @@ -4,7 +4,7 @@ let db = null; export function getDb() { if (!db) { - db = new sqlite3.Database("./database.sqlite", (err) => { + db = new sqlite3.Database("./clue_hunt.db", (err) => { if (err) { console.error("Error connecting to database:", err); } else {