fix: demo name, trial flow, signup profile fields, docker pgbouncer/frontend
- page.tsx: hero mock shows 'Neha Verma' + 'AI Coach Plan' (was 'Demo Student') - backend/main.py: demo login maps to Neha Verma UUID (33333333-...) - backend/main.py: register endpoint stores exam/class/medium/school + trial_end from admin settings - backend/main.py: register checks allow_new_registrations setting - backend/main.py: admin student list includes trial_end field - useActiveUser.ts: rewrite trial logic using real created_at date - useActiveUser.ts: add computeTrialInfo(), isDemoUser() helpers + expose trialInfo from hook - useActiveUser.ts: hasAccessTo() now uses effectiveTier from trial logic - dashboard/layout.tsx: hide demo switcher for real users (only show for known demo accounts) - dashboard/layout.tsx: trial badge in top header (Day N/15 Trial · Xd left) - dashboard/layout.tsx: trial day shown in sidebar user card and dropdown - signup/page.tsx: wire step 2 selects (exam/class/medium/school) to state + send to backend - signup/page.tsx: success screen shows 'Day 1 of your Free Trial has started!' - userlist.txt: was empty directory causing pgbouncer mount failure; replaced with proper file - pgbouncer.ini: added DB credentials in connection string; fixed admin_users - Dockerfile: added ARG NEXT_PUBLIC_API_URL baked at build time (needed for standalone) - docker-compose.yml: frontend build arg http://backend:8000; pgbouncer healthcheck; backend waits for pgbouncer
This commit is contained in:
@@ -19,6 +19,10 @@ export default function SignupPage() {
|
||||
const [lastName, setLastName] = useState("")
|
||||
const [phone, setPhone] = useState("")
|
||||
const [termsAccepted, setTermsAccepted] = useState(false)
|
||||
const [targetExam, setTargetExam] = useState("JEE_Main")
|
||||
const [studentClass, setStudentClass] = useState("12")
|
||||
const [medium, setMedium] = useState("English")
|
||||
const [schoolName, setSchoolName] = useState("")
|
||||
|
||||
// Validation temporarily relaxed: phone length check and OTP verification removed for now.
|
||||
// Original: firstName.trim() !== "" && lastName.trim() !== "" && email.trim() !== "" && phone.length === 10 && termsAccepted
|
||||
@@ -34,7 +38,15 @@ export default function SignupPage() {
|
||||
const res = await fetch("/api/auth/register", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name: `${firstName} ${lastName}`, email, password })
|
||||
body: JSON.stringify({
|
||||
name: `${firstName} ${lastName}`,
|
||||
email,
|
||||
password,
|
||||
target_exam: targetExam,
|
||||
student_class: studentClass,
|
||||
medium,
|
||||
school: schoolName || undefined,
|
||||
})
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
@@ -97,13 +109,19 @@ export default function SignupPage() {
|
||||
<Card className="border-border bg-secondary/10 backdrop-blur-xl shadow-[0_0_50px_-20px_var(--color-primary)] rounded-[2rem] overflow-hidden text-center py-8">
|
||||
<CardContent className="space-y-6 pt-4 flex flex-col items-center">
|
||||
<CheckCircle2 size={64} className="text-primary mb-4" />
|
||||
<h2 className="text-3xl font-black tracking-tight text-foreground">Thanks for registering!</h2>
|
||||
<p className="text-muted-foreground text-sm font-medium px-4 leading-relaxed">
|
||||
Thank you for the registration. Our team will contact you shortly.
|
||||
</p>
|
||||
<h2 className="text-3xl font-black tracking-tight text-foreground">Welcome, {firstName}! 🎉</h2>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-primary/10 border border-primary/20 text-primary font-bold text-sm">
|
||||
<span className="size-2 rounded-full bg-primary animate-pulse"></span>
|
||||
Day 1 of your Free Trial has started!
|
||||
</div>
|
||||
<p className="text-muted-foreground text-sm font-medium px-4 leading-relaxed">
|
||||
You have full AI Coach access for your trial period. Let's build your streak starting today.
|
||||
</p>
|
||||
</div>
|
||||
<Link href="/dashboard" className="w-full mt-4">
|
||||
<Button className="w-full rounded-xl h-12 font-bold text-base bg-primary text-primary-foreground hover:bg-primary/90 transition-all shadow-[0_0_20px_-5px_var(--color-primary)]">
|
||||
Go to Dashboard
|
||||
Start Day 1 → Go to Dashboard
|
||||
</Button>
|
||||
</Link>
|
||||
</CardContent>
|
||||
@@ -208,16 +226,21 @@ export default function SignupPage() {
|
||||
<div className="space-y-4 animate-in fade-in slide-in-from-right-8">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold text-foreground">Target Exam</label>
|
||||
<select className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer">
|
||||
<option value="jee_main" className="bg-background text-foreground font-medium">JEE Main</option>
|
||||
<option value="jee_adv" className="bg-background text-foreground font-medium">JEE Advanced</option>
|
||||
<option value="neet" className="bg-background text-foreground font-medium">NEET</option>
|
||||
<option value="jee_neet" className="bg-background text-foreground font-medium">JEE + NEET</option>
|
||||
<select
|
||||
value={targetExam}
|
||||
onChange={(e) => setTargetExam(e.target.value)}
|
||||
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer">
|
||||
<option value="JEE_Main" className="bg-background text-foreground font-medium">JEE Main</option>
|
||||
<option value="JEE_Advanced" className="bg-background text-foreground font-medium">JEE Advanced</option>
|
||||
<option value="NEET" className="bg-background text-foreground font-medium">NEET</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold text-foreground">Current Class</label>
|
||||
<select className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer">
|
||||
<select
|
||||
value={studentClass}
|
||||
onChange={(e) => setStudentClass(e.target.value)}
|
||||
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer">
|
||||
<option value="11" className="bg-background text-foreground font-medium">Class 11th</option>
|
||||
<option value="12" className="bg-background text-foreground font-medium">Class 12th</option>
|
||||
<option value="dropper" className="bg-background text-foreground font-medium">Dropper</option>
|
||||
@@ -225,15 +248,23 @@ export default function SignupPage() {
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold text-foreground">Study Medium</label>
|
||||
<select className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer">
|
||||
<option value="en" className="bg-background text-foreground font-medium">English</option>
|
||||
<option value="hi" className="bg-background text-foreground font-medium">Hindi (हिंदी)</option>
|
||||
<option value="bi" className="bg-background text-foreground font-medium">Bilingual (English + Hindi)</option>
|
||||
<select
|
||||
value={medium}
|
||||
onChange={(e) => setMedium(e.target.value)}
|
||||
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer">
|
||||
<option value="English" className="bg-background text-foreground font-medium">English</option>
|
||||
<option value="Hindi" className="bg-background text-foreground font-medium">Hindi (हिंदी)</option>
|
||||
<option value="Bilingual" className="bg-background text-foreground font-medium">Bilingual (English + Hindi)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold text-foreground">School / Coaching Name <span className="text-muted-foreground font-normal">(Optional)</span></label>
|
||||
<input type="text" placeholder="e.g. DPS R.K. Puram" className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"/>
|
||||
<input
|
||||
type="text"
|
||||
value={schoolName}
|
||||
onChange={(e) => setSchoolName(e.target.value)}
|
||||
placeholder="e.g. DPS R.K. Puram"
|
||||
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user