Implement active user tiers, class-based Tailwind theme switcher, 3-tiled static dashboard layout, Minio object storage integration, school & state settings database sync, and streak wishes onboarding modal
This commit is contained in:
@@ -4,16 +4,19 @@ import { useEffect, useState } from "react"
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
|
||||
import { GraduationCap, MapPin, RefreshCw } from "lucide-react"
|
||||
|
||||
const USER_ID = "b0e17378-864d-439e-8806-708dc48a891b"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
export function CollegePredictorCard() {
|
||||
const [data, setData] = useState<any>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const { userId, loading: userLoading } = useActiveUser();
|
||||
|
||||
useEffect(() => {
|
||||
if (userLoading || !userId) return;
|
||||
|
||||
async function fetchReadiness() {
|
||||
try {
|
||||
const res = await fetch(`http://localhost:8000/api/ai-coach/readiness/${USER_ID}`)
|
||||
const res = await fetch(`/api/ai-coach/readiness/${userId}`)
|
||||
if (!res.ok) throw new Error("Failed to fetch")
|
||||
const json = await res.json()
|
||||
setData(json)
|
||||
@@ -28,7 +31,7 @@ export function CollegePredictorCard() {
|
||||
}
|
||||
}
|
||||
fetchReadiness()
|
||||
}, [])
|
||||
}, [userId, userLoading])
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
||||
@@ -4,16 +4,19 @@ import { useEffect, useState } from "react"
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
|
||||
import { Activity, RefreshCw } from "lucide-react"
|
||||
|
||||
const USER_ID = "b0e17378-864d-439e-8806-708dc48a891b"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
export function ReadinessGauge() {
|
||||
const [data, setData] = useState<any>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const { userId, loading: userLoading } = useActiveUser();
|
||||
|
||||
useEffect(() => {
|
||||
if (userLoading || !userId) return;
|
||||
|
||||
async function fetchReadiness() {
|
||||
try {
|
||||
const res = await fetch(`http://localhost:8000/api/ai-coach/readiness/${USER_ID}`)
|
||||
const res = await fetch(`/api/ai-coach/readiness/${userId}`)
|
||||
if (!res.ok) throw new Error("Failed to fetch")
|
||||
const json = await res.json()
|
||||
setData(json)
|
||||
@@ -34,7 +37,7 @@ export function ReadinessGauge() {
|
||||
}
|
||||
}
|
||||
fetchReadiness()
|
||||
}, [])
|
||||
}, [userId, userLoading])
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
||||
@@ -5,16 +5,18 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/com
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Link as LinkIcon, Share2, Check, Gift } from "lucide-react"
|
||||
|
||||
const USER_ID = "b0e17378-864d-439e-8806-708dc48a891b"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
export function ReferralCard() {
|
||||
const { userId, loading: userLoading } = useActiveUser();
|
||||
const [data, setData] = useState<any>(null)
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (userLoading || !userId) return;
|
||||
async function fetchReferral() {
|
||||
try {
|
||||
const res = await fetch(`http://localhost:8000/api/growth/referral/${USER_ID}`)
|
||||
const res = await fetch(`/api/growth/referral/${userId}`)
|
||||
if (res.ok) {
|
||||
const json = await res.json()
|
||||
setData(json)
|
||||
@@ -24,9 +26,9 @@ export function ReferralCard() {
|
||||
}
|
||||
}
|
||||
fetchReferral()
|
||||
}, [])
|
||||
}, [userId, userLoading])
|
||||
|
||||
const link = data?.referral_link || "https://pragativeer.com/join/demo"
|
||||
const link = data?.referral_link || `https://pragativeer.com/join/${userId || "demo"}`
|
||||
const message = data?.share_message || "Join me on PragatiVeer! Use my link to get 7 days of the AI Coach for free."
|
||||
|
||||
const copyToClipboard = () => {
|
||||
|
||||
@@ -5,16 +5,19 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/com
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { CalendarClock, CheckCircle2, Circle, Clock, Loader2, PlayCircle, RefreshCw, XCircle } from "lucide-react"
|
||||
|
||||
const USER_ID = "b0e17378-864d-439e-8806-708dc48a891b"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
export function StudyPlanCard() {
|
||||
const [tasks, setTasks] = useState<any[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const { userId, loading: userLoading } = useActiveUser();
|
||||
|
||||
useEffect(() => {
|
||||
if (userLoading || !userId) return;
|
||||
|
||||
async function fetchPlan() {
|
||||
try {
|
||||
const res = await fetch(`http://localhost:8000/api/ai-coach/study-plan/today?user_id=${USER_ID}`)
|
||||
const res = await fetch(`/api/ai-coach/study-plan/today?user_id=${userId}`)
|
||||
if (!res.ok) throw new Error("No plan")
|
||||
const data = await res.json()
|
||||
setTasks(data.tasks || [])
|
||||
@@ -31,7 +34,7 @@ export function StudyPlanCard() {
|
||||
}
|
||||
}
|
||||
fetchPlan()
|
||||
}, [])
|
||||
}, [userId, userLoading])
|
||||
|
||||
const toggleTask = (idx: number, newStatus: string) => {
|
||||
setTasks(prev => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import remarkMath from "remark-math"
|
||||
import rehypeKatex from "rehype-katex"
|
||||
import "katex/dist/katex.min.css"
|
||||
|
||||
const USER_ID = "b0e17378-864d-439e-8806-708dc48a891b"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
interface Message {
|
||||
role: "user" | "assistant"
|
||||
@@ -24,6 +24,8 @@ export function TutorChat() {
|
||||
const [input, setInput] = useState("")
|
||||
const [streaming, setStreaming] = useState(false)
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const { userId, loading: userLoading } = useActiveUser();
|
||||
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" })
|
||||
@@ -35,7 +37,7 @@ export function TutorChat() {
|
||||
|
||||
const handleSend = async (e?: React.FormEvent) => {
|
||||
e?.preventDefault()
|
||||
if (!input.trim() || streaming) return
|
||||
if (!input.trim() || streaming || userLoading || !userId) return
|
||||
|
||||
const userMsg = input.trim()
|
||||
setInput("")
|
||||
@@ -46,10 +48,10 @@ export function TutorChat() {
|
||||
setStreaming(true)
|
||||
|
||||
try {
|
||||
const res = await fetch("http://localhost:8000/api/ai-coach/chat/stream", {
|
||||
const res = await fetch("/api/ai-coach/chat/stream", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ user_id: USER_ID, message: userMsg })
|
||||
body: JSON.stringify({ user_id: userId, message: userMsg })
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
|
||||
Reference in New Issue
Block a user