Skip to content

Commit cb1503b

Browse files
committed
update code
1 parent 7931e8f commit cb1503b

6 files changed

Lines changed: 352 additions & 20 deletions

File tree

.firebaserc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "image-82e55"
4+
}
5+
}

firebase.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"firestore": {
3+
"rules": "firestore.rules"
4+
}
5+
}

firestore.rules

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,25 @@ service cloud.firestore {
55
return request.auth != null;
66
}
77

8-
// Departments, Batches, Semesters, Subjects: Public Read, Auth Write
8+
// Departments: Public Read, Auth Write
99
match /departments/{dept} {
1010
allow read: if true;
1111
allow write: if isAuthenticated();
1212
}
13-
13+
14+
// Batches: Public Read, Auth Write
1415
match /batches/{batch} {
1516
allow read: if true;
1617
allow write: if isAuthenticated();
1718
}
18-
19+
20+
// Semesters: Public Read, Auth Write
1921
match /semesters/{sem} {
2022
allow read: if true;
2123
allow write: if isAuthenticated();
2224
}
23-
25+
26+
// Subjects: Public Read, Auth Write
2427
match /subjects/{sub} {
2528
allow read: if true;
2629
allow write: if isAuthenticated();
@@ -32,7 +35,7 @@ service cloud.firestore {
3235
allow write: if isAuthenticated();
3336
}
3437

35-
// Notes: Public Read, Auth Write (with owner check for strictness if needed, but keeping simple for now)
38+
// Notes: Public Read, Auth Write
3639
match /notes/{note} {
3740
allow read: if true;
3841
allow create: if isAuthenticated();

src/app/db-diagnostic/page.tsx

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
import {
5+
getDepartments,
6+
getBatches,
7+
getSemesters,
8+
getSubjects,
9+
getNotes
10+
} from "@/lib/firebase/firestore";
11+
12+
export default function DBDiagnosticPage() {
13+
const [departments, setDepartments] = useState<any[]>([]);
14+
const [selectedDeptId, setSelectedDeptId] = useState<string>("");
15+
const [batches, setBatches] = useState<any[]>([]);
16+
const [selectedBatchId, setSelectedBatchId] = useState<string>("");
17+
const [semesters, setSemesters] = useState<any[]>([]);
18+
const [selectedSemId, setSelectedSemId] = useState<string>("");
19+
const [subjects, setSubjects] = useState<any[]>([]);
20+
const [selectedSubId, setSelectedSubId] = useState<string>("");
21+
const [notes, setNotes] = useState<any[]>([]);
22+
const [loading, setLoading] = useState(false);
23+
const [error, setError] = useState<string>("");
24+
25+
useEffect(() => {
26+
loadDepartments();
27+
}, []);
28+
29+
async function loadDepartments() {
30+
try {
31+
setLoading(true);
32+
const data = await getDepartments();
33+
console.log("Departments loaded:", data);
34+
setDepartments(data);
35+
} catch (err: any) {
36+
console.error("Error loading departments:", err);
37+
setError(err.message);
38+
} finally {
39+
setLoading(false);
40+
}
41+
}
42+
43+
async function loadBatches(deptId: string) {
44+
try {
45+
setLoading(true);
46+
setError("");
47+
console.log("Loading batches for department:", deptId);
48+
const data = await getBatches(deptId);
49+
console.log("Batches loaded:", data);
50+
setBatches(data);
51+
if (data.length === 0) {
52+
setError(`No batches found for department ID: ${deptId}`);
53+
}
54+
} catch (err: any) {
55+
console.error("Error loading batches:", err);
56+
setError(err.message);
57+
setBatches([]);
58+
} finally {
59+
setLoading(false);
60+
}
61+
}
62+
63+
async function loadSemesters(batchId: string) {
64+
try {
65+
setLoading(true);
66+
setError("");
67+
console.log("Loading semesters for batch:", batchId);
68+
const data = await getSemesters(batchId);
69+
console.log("Semesters loaded:", data);
70+
setSemesters(data);
71+
if (data.length === 0) {
72+
setError(`No semesters found for batch ID: ${batchId}`);
73+
}
74+
} catch (err: any) {
75+
console.error("Error loading semesters:", err);
76+
setError(err.message);
77+
setSemesters([]);
78+
} finally {
79+
setLoading(false);
80+
}
81+
}
82+
83+
async function loadSubjects(semId: string) {
84+
try {
85+
setLoading(true);
86+
setError("");
87+
console.log("Loading subjects for semester:", semId);
88+
const data = await getSubjects(semId);
89+
console.log("Subjects loaded:", data);
90+
setSubjects(data);
91+
if (data.length === 0) {
92+
setError(`No subjects found for semester ID: ${semId}`);
93+
}
94+
} catch (err: any) {
95+
console.error("Error loading subjects:", err);
96+
setError(err.message);
97+
setSubjects([]);
98+
} finally {
99+
setLoading(false);
100+
}
101+
}
102+
103+
async function loadNotes(subId: string) {
104+
try {
105+
setLoading(true);
106+
setError("");
107+
console.log("Loading notes for subject:", subId);
108+
const data = await getNotes(subId);
109+
console.log("Notes loaded:", data);
110+
setNotes(data);
111+
if (data.length === 0) {
112+
setError(`No notes found for subject ID: ${subId}`);
113+
}
114+
} catch (err: any) {
115+
console.error("Error loading notes:", err);
116+
setError(err.message);
117+
setNotes([]);
118+
} finally {
119+
setLoading(false);
120+
}
121+
}
122+
123+
return (
124+
<div style={{ padding: "2rem", maxWidth: "1200px", margin: "0 auto" }}>
125+
<h1 style={{ marginBottom: "2rem" }}>🔍 Firebase Database Diagnostic</h1>
126+
127+
{error && (
128+
<div style={{
129+
background: "#fee",
130+
border: "1px solid #fcc",
131+
padding: "1rem",
132+
borderRadius: "8px",
133+
marginBottom: "1rem",
134+
color: "#c00"
135+
}}>
136+
<strong>Error:</strong> {error}
137+
</div>
138+
)}
139+
140+
{loading && <p>Loading...</p>}
141+
142+
<div style={{ display: "grid", gap: "2rem" }}>
143+
{/* Departments */}
144+
<div>
145+
<h2>Departments ({departments.length})</h2>
146+
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
147+
{departments.map(d => (
148+
<button
149+
key={d.id}
150+
onClick={() => {
151+
setSelectedDeptId(d.id);
152+
loadBatches(d.id);
153+
setBatches([]);
154+
setSemesters([]);
155+
setSubjects([]);
156+
setNotes([]);
157+
}}
158+
style={{
159+
padding: "0.5rem 1rem",
160+
background: selectedDeptId === d.id ? "#3b82f6" : "#e5e7eb",
161+
color: selectedDeptId === d.id ? "white" : "black",
162+
border: "none",
163+
borderRadius: "6px",
164+
cursor: "pointer"
165+
}}
166+
>
167+
{d.name} (ID: {d.id})
168+
</button>
169+
))}
170+
</div>
171+
<pre style={{ background: "#f5f5f5", padding: "1rem", borderRadius: "6px", marginTop: "1rem", overflow: "auto" }}>
172+
{JSON.stringify(departments, null, 2)}
173+
</pre>
174+
</div>
175+
176+
{/* Batches */}
177+
{selectedDeptId && (
178+
<div>
179+
<h2>Batches for {selectedDeptId} ({batches.length})</h2>
180+
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
181+
{batches.map(b => (
182+
<button
183+
key={b.id}
184+
onClick={() => {
185+
setSelectedBatchId(b.id);
186+
loadSemesters(b.id);
187+
setSemesters([]);
188+
setSubjects([]);
189+
setNotes([]);
190+
}}
191+
style={{
192+
padding: "0.5rem 1rem",
193+
background: selectedBatchId === b.id ? "#3b82f6" : "#e5e7eb",
194+
color: selectedBatchId === b.id ? "white" : "black",
195+
border: "none",
196+
borderRadius: "6px",
197+
cursor: "pointer"
198+
}}
199+
>
200+
{b.name} (ID: {b.id})
201+
</button>
202+
))}
203+
</div>
204+
<pre style={{ background: "#f5f5f5", padding: "1rem", borderRadius: "6px", marginTop: "1rem", overflow: "auto" }}>
205+
{JSON.stringify(batches, null, 2)}
206+
</pre>
207+
</div>
208+
)}
209+
210+
{/* Semesters */}
211+
{selectedBatchId && (
212+
<div>
213+
<h2>Semesters for {selectedBatchId} ({semesters.length})</h2>
214+
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
215+
{semesters.map(s => (
216+
<button
217+
key={s.id}
218+
onClick={() => {
219+
setSelectedSemId(s.id);
220+
loadSubjects(s.id);
221+
setSubjects([]);
222+
setNotes([]);
223+
}}
224+
style={{
225+
padding: "0.5rem 1rem",
226+
background: selectedSemId === s.id ? "#3b82f6" : "#e5e7eb",
227+
color: selectedSemId === s.id ? "white" : "black",
228+
border: "none",
229+
borderRadius: "6px",
230+
cursor: "pointer"
231+
}}
232+
>
233+
{s.name} (ID: {s.id})
234+
</button>
235+
))}
236+
</div>
237+
<pre style={{ background: "#f5f5f5", padding: "1rem", borderRadius: "6px", marginTop: "1rem", overflow: "auto" }}>
238+
{JSON.stringify(semesters, null, 2)}
239+
</pre>
240+
</div>
241+
)}
242+
243+
{/* Subjects */}
244+
{selectedSemId && (
245+
<div>
246+
<h2>Subjects for {selectedSemId} ({subjects.length})</h2>
247+
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
248+
{subjects.map(s => (
249+
<button
250+
key={s.id}
251+
onClick={() => {
252+
setSelectedSubId(s.id);
253+
loadNotes(s.id);
254+
setNotes([]);
255+
}}
256+
style={{
257+
padding: "0.5rem 1rem",
258+
background: selectedSubId === s.id ? "#3b82f6" : "#e5e7eb",
259+
color: selectedSubId === s.id ? "white" : "black",
260+
border: "none",
261+
borderRadius: "6px",
262+
cursor: "pointer"
263+
}}
264+
>
265+
{s.name} (ID: {s.id})
266+
</button>
267+
))}
268+
</div>
269+
<pre style={{ background: "#f5f5f5", padding: "1rem", borderRadius: "6px", marginTop: "1rem", overflow: "auto" }}>
270+
{JSON.stringify(subjects, null, 2)}
271+
</pre>
272+
</div>
273+
)}
274+
275+
{/* Notes */}
276+
{selectedSubId && (
277+
<div>
278+
<h2>Notes for {selectedSubId} ({notes.length})</h2>
279+
<pre style={{ background: "#f5f5f5", padding: "1rem", borderRadius: "6px", marginTop: "1rem", overflow: "auto" }}>
280+
{JSON.stringify(notes, null, 2)}
281+
</pre>
282+
</div>
283+
)}
284+
</div>
285+
</div>
286+
);
287+
}

0 commit comments

Comments
 (0)