feat: Add JWT authentication to backend, configure frontend API client, fix streak layout
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { BrainCircuit, Play, CheckCircle2, Download, Filter, Lock, FileText, Eye, ShieldAlert, X, Sparkles, Share2, Maximize2, Minimize2 } from "lucide-react"
|
||||
@@ -25,14 +26,14 @@ export default function AIDailyPracticePage() {
|
||||
try {
|
||||
const pattern = user.target_exam || "JEE_Main";
|
||||
// Also fetch from the correct Next.js proxied route instead of localhost:8000
|
||||
const res = await fetch(`/api/tests?type=DPS&exam_pattern=${pattern}`);
|
||||
const res = await fetchWithAuth(`/api/tests?type=DPS&exam_pattern=${pattern}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
setDpps(data)
|
||||
}
|
||||
|
||||
if (userId) {
|
||||
const attemptsRes = await fetch(`/api/users/${userId}/attempts`);
|
||||
const attemptsRes = await fetchWithAuth(`/api/users/${userId}/attempts`);
|
||||
if (attemptsRes.ok) {
|
||||
const attemptsData = await attemptsRes.json();
|
||||
setAttempts(attemptsData);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { useEffect, useState } from "react"
|
||||
import { MistakeHeatmap } from "@/components/AI/MistakeHeatmap"
|
||||
import { StudyPlanCard } from "@/components/AI/StudyPlanCard"
|
||||
@@ -39,7 +40,7 @@ export default function AICoachDashboard() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!userLoading && userId) {
|
||||
fetch(`/api/users/${userId}/stats`)
|
||||
fetchWithAuth(`/api/users/${userId}/stats`)
|
||||
.then(res => res.ok ? res.json() : null)
|
||||
.then(data => setStats(data))
|
||||
.catch(() => setStats(null))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -37,7 +38,7 @@ export default function CBTPage() {
|
||||
|
||||
async function loadUser() {
|
||||
try {
|
||||
const userRes = await fetch(`/api/users/${userId}`);
|
||||
const userRes = await fetchWithAuth(`/api/users/${userId}`);
|
||||
if (!userRes.ok) throw new Error("Failed to load user target exam");
|
||||
const userData = await userRes.json();
|
||||
const pattern = userData.target_exam;
|
||||
@@ -75,7 +76,7 @@ export default function CBTPage() {
|
||||
setExams(testsData);
|
||||
}
|
||||
|
||||
const attemptsRes = await fetch(`/api/users/${userId}/attempts`);
|
||||
const attemptsRes = await fetchWithAuth(`/api/users/${userId}/attempts`);
|
||||
if (attemptsRes.ok) {
|
||||
const attemptsData = await attemptsRes.json();
|
||||
setAttempts(attemptsData);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { BrainCircuit, Play, CheckCircle2, Download, Filter, Lock, FileText, Eye, ShieldAlert, X, Sparkles, Share2, Maximize2, Minimize2 } from "lucide-react"
|
||||
@@ -25,14 +26,14 @@ export default function DPPPage() {
|
||||
try {
|
||||
const pattern = user.target_exam || "JEE_Main";
|
||||
// Also fetch from the correct Next.js proxied route instead of localhost:8000
|
||||
const res = await fetch(`/api/tests?type=DPS&exam_pattern=${pattern}`);
|
||||
const res = await fetchWithAuth(`/api/tests?type=DPS&exam_pattern=${pattern}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
setDpps(data)
|
||||
}
|
||||
|
||||
if (userId) {
|
||||
const attemptsRes = await fetch(`/api/users/${userId}/attempts`);
|
||||
const attemptsRes = await fetchWithAuth(`/api/users/${userId}/attempts`);
|
||||
if (attemptsRes.ok) {
|
||||
const attemptsData = await attemptsRes.json();
|
||||
setAttempts(attemptsData);
|
||||
|
||||
@@ -335,7 +335,7 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => window.dispatchEvent(new CustomEvent("pragativeer-show-streak-animation"))}
|
||||
className="hover:opacity-85 transition-opacity cursor-pointer border-none bg-transparent p-0"
|
||||
className="flex items-center justify-center hover:opacity-85 transition-opacity cursor-pointer border-none bg-transparent p-0"
|
||||
title="View Streak Celebration"
|
||||
>
|
||||
<StreakCounter streak={user.streak_count} />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { useRef, useState, useEffect } from "react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
@@ -26,7 +27,7 @@ export default function DashboardPage() {
|
||||
}
|
||||
async function fetchStats() {
|
||||
try {
|
||||
const res = await fetch(`/api/users/${currentUserId}/stats`)
|
||||
const res = await fetchWithAuth(`/api/users/${currentUserId}/stats`)
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
setUserStats(data)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -50,7 +51,7 @@ export default function SettingsPage() {
|
||||
formData.append("file", file);
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/users/${userId}/avatar`, {
|
||||
const res = await fetchWithAuth(`/api/users/${userId}/avatar`, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
@@ -72,7 +73,7 @@ export default function SettingsPage() {
|
||||
if (!userId) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
const res = await fetch(`/api/users/${userId}`, {
|
||||
const res = await fetchWithAuth(`/api/users/${userId}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { useState, useEffect } from "react"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { Flame, Gift, Star, Trophy, Target, ArrowRight, CheckCircle2 } from "lucide-react"
|
||||
@@ -20,7 +21,7 @@ export default function StreaksPage() {
|
||||
}
|
||||
async function loadStats() {
|
||||
try {
|
||||
const res = await fetch(`/api/users/${user?.id}/stats`)
|
||||
const res = await fetchWithAuth(`/api/users/${user?.id}/stats`)
|
||||
if (res.ok) {
|
||||
const stats = await res.json()
|
||||
if (!stats.is_new_user) {
|
||||
|
||||
Reference in New Issue
Block a user