Skip to content

Commit b999025

Browse files
committed
Add comprehensive database diagnostic tool
1 parent 3427e3c commit b999025

1 file changed

Lines changed: 223 additions & 0 deletions

File tree

src/app/db-diagnostic/page.tsx

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
import { db } from "@/lib/firebase/config";
5+
import { collection, getDocs, query, where } from "firebase/firestore";
6+
7+
export default function DatabaseDiagnostic() {
8+
const [results, setResults] = useState<any>({});
9+
const [loading, setLoading] = useState(true);
10+
const [error, setError] = useState<string | null>(null);
11+
12+
useEffect(() => {
13+
runDiagnostics();
14+
}, []);
15+
16+
async function runDiagnostics() {
17+
const diagnostics: any = {};
18+
19+
try {
20+
// Test 1: Departments
21+
console.log("🔍 Testing Departments...");
22+
const deptSnapshot = await getDocs(collection(db, "departments"));
23+
diagnostics.departments = {
24+
count: deptSnapshot.size,
25+
data: deptSnapshot.docs.map(d => ({ id: d.id, ...d.data() }))
26+
};
27+
28+
// Test 2: Batches
29+
console.log("🔍 Testing Batches...");
30+
try {
31+
const batchSnapshot = await getDocs(collection(db, "batches"));
32+
diagnostics.batches = {
33+
count: batchSnapshot.size,
34+
data: batchSnapshot.docs.map(d => ({ id: d.id, ...d.data() }))
35+
};
36+
} catch (err: any) {
37+
diagnostics.batches = { error: err.message, blocked: true };
38+
}
39+
40+
// Test 3: Semesters
41+
console.log("🔍 Testing Semesters...");
42+
const semSnapshot = await getDocs(collection(db, "semesters"));
43+
diagnostics.semesters = {
44+
count: semSnapshot.size,
45+
data: semSnapshot.docs.map(d => ({ id: d.id, ...d.data() }))
46+
};
47+
48+
// Test 4: Subjects
49+
console.log("🔍 Testing Subjects...");
50+
const subSnapshot = await getDocs(collection(db, "subjects"));
51+
diagnostics.subjects = {
52+
count: subSnapshot.size,
53+
data: subSnapshot.docs.map(d => ({ id: d.id, ...d.data() }))
54+
};
55+
56+
// Test 5: Notes (uploaded files)
57+
console.log("🔍 Testing Notes...");
58+
const notesSnapshot = await getDocs(collection(db, "notes"));
59+
diagnostics.notes = {
60+
count: notesSnapshot.size,
61+
data: notesSnapshot.docs.map(d => ({ id: d.id, ...d.data() }))
62+
};
63+
64+
// Test 6: Folders
65+
console.log("🔍 Testing Folders...");
66+
const folderSnapshot = await getDocs(collection(db, "folders"));
67+
diagnostics.folders = {
68+
count: folderSnapshot.size,
69+
data: folderSnapshot.docs.map(d => ({ id: d.id, ...d.data() }))
70+
};
71+
72+
setResults(diagnostics);
73+
console.log("✅ Diagnostics complete:", diagnostics);
74+
} catch (err: any) {
75+
console.error("❌ Diagnostic error:", err);
76+
setError(err.message);
77+
} finally {
78+
setLoading(false);
79+
}
80+
}
81+
82+
if (loading) {
83+
return <div style={{ padding: "2rem" }}>🔍 Running diagnostics...</div>;
84+
}
85+
86+
if (error) {
87+
return (
88+
<div style={{ padding: "2rem", maxWidth: "800px", margin: "0 auto" }}>
89+
<h1>❌ Diagnostic Error</h1>
90+
<div style={{ padding: "1rem", background: "#fee2e2", borderRadius: "8px" }}>
91+
<strong>Error:</strong> {error}
92+
</div>
93+
</div>
94+
);
95+
}
96+
97+
const totalFiles = results.notes?.count || 0;
98+
const hasData = Object.values(results).some((r: any) => r.count > 0);
99+
100+
return (
101+
<div style={{ padding: "2rem", maxWidth: "1200px", margin: "0 auto" }}>
102+
<h1>🔬 Database Diagnostic Report</h1>
103+
104+
{/* Summary */}
105+
<div style={{
106+
padding: "1.5rem",
107+
background: hasData ? "#d1fae5" : "#fef3c7",
108+
borderRadius: "8px",
109+
marginBottom: "2rem"
110+
}}>
111+
<h2 style={{ marginTop: 0 }}>Summary</h2>
112+
<p><strong>Total Uploaded Files:</strong> {totalFiles}</p>
113+
<p><strong>Database Status:</strong> {hasData ? "✅ Contains Data" : "⚠️ Empty Database"}</p>
114+
</div>
115+
116+
{/* Detailed Results */}
117+
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))", gap: "1rem" }}>
118+
{Object.entries(results).map(([collection, data]: [string, any]) => (
119+
<div key={collection} style={{
120+
padding: "1rem",
121+
border: "1px solid #e5e7eb",
122+
borderRadius: "8px",
123+
background: data.blocked ? "#fee2e2" : data.count > 0 ? "#f0fdf4" : "#f9fafb"
124+
}}>
125+
<h3 style={{ marginTop: 0, textTransform: "capitalize" }}>{collection}</h3>
126+
127+
{data.blocked ? (
128+
<div>
129+
<p style={{ color: "#dc2626" }}>🚫 <strong>BLOCKED BY FIRESTORE RULES</strong></p>
130+
<p style={{ fontSize: "0.9rem" }}>Error: {data.error}</p>
131+
<div style={{ marginTop: "1rem", padding: "0.75rem", background: "#fff", borderRadius: "4px" }}>
132+
<strong>Fix:</strong> Deploy updated firestore.rules to Firebase Console
133+
</div>
134+
</div>
135+
) : (
136+
<>
137+
<p><strong>Count:</strong> {data.count}</p>
138+
{data.count > 0 && (
139+
<details>
140+
<summary style={{ cursor: "pointer", color: "#2563eb" }}>View Data</summary>
141+
<pre style={{
142+
marginTop: "0.5rem",
143+
padding: "0.5rem",
144+
background: "#f3f4f6",
145+
borderRadius: "4px",
146+
fontSize: "0.75rem",
147+
overflow: "auto",
148+
maxHeight: "200px"
149+
}}>
150+
{JSON.stringify(data.data, null, 2)}
151+
</pre>
152+
</details>
153+
)}
154+
</>
155+
)}
156+
</div>
157+
))}
158+
</div>
159+
160+
{/* Recommendations */}
161+
<div style={{ marginTop: "2rem", padding: "1.5rem", background: "#eff6ff", borderRadius: "8px" }}>
162+
<h2>📋 Recommendations</h2>
163+
164+
{results.batches?.blocked && (
165+
<div style={{ marginBottom: "1rem", padding: "1rem", background: "#fee2e2", borderRadius: "4px" }}>
166+
<strong>🔴 CRITICAL:</strong> Batches collection is blocked by Firestore rules.
167+
<br />
168+
<strong>Action:</strong> Deploy updated firestore.rules via Firebase Console
169+
</div>
170+
)}
171+
172+
{!hasData && (
173+
<div style={{ marginBottom: "1rem", padding: "1rem", background: "#fef3c7", borderRadius: "4px" }}>
174+
<strong>⚠️ WARNING:</strong> Database is empty.
175+
<br />
176+
<strong>Action:</strong> Go to <a href="/dashboard/manage">/dashboard/manage</a> to create structure
177+
</div>
178+
)}
179+
180+
{totalFiles === 0 && hasData && (
181+
<div style={{ marginBottom: "1rem", padding: "1rem", background: "#fef3c7", borderRadius: "4px" }}>
182+
<strong>⚠️ INFO:</strong> Structure exists but no files uploaded.
183+
<br />
184+
<strong>Action:</strong> Go to <a href="/dashboard">/dashboard</a> to upload files
185+
</div>
186+
)}
187+
188+
{totalFiles > 0 && (
189+
<div style={{ padding: "1rem", background: "#d1fae5", borderRadius: "4px" }}>
190+
<strong>✅ SUCCESS:</strong> {totalFiles} files found in database!
191+
<br />
192+
<strong>Next:</strong> Check if they're linked to correct departments/batches/semesters
193+
</div>
194+
)}
195+
</div>
196+
197+
{/* Data Integrity Check */}
198+
{totalFiles > 0 && (
199+
<div style={{ marginTop: "2rem", padding: "1.5rem", background: "#f9fafb", borderRadius: "8px" }}>
200+
<h2>🔍 Data Integrity Check</h2>
201+
{results.notes.data.map((note: any, idx: number) => (
202+
<div key={idx} style={{
203+
marginBottom: "0.5rem",
204+
padding: "0.75rem",
205+
background: "#fff",
206+
border: "1px solid #e5e7eb",
207+
borderRadius: "4px",
208+
fontSize: "0.85rem"
209+
}}>
210+
<strong>{note.title}</strong>
211+
<div style={{ marginTop: "0.25rem", color: "#6b7280" }}>
212+
Dept: {note.departmentId || "❌ Missing"} |
213+
Batch: {note.batchId || "❌ Missing"} |
214+
Sem: {note.semesterId || "❌ Missing"} |
215+
Subject: {note.subjectId || "❌ Missing"}
216+
</div>
217+
</div>
218+
))}
219+
</div>
220+
)}
221+
</div>
222+
);
223+
}

0 commit comments

Comments
 (0)