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:
@@ -105,6 +105,10 @@ class RegisterPayload(BaseModel):
|
||||
name: str
|
||||
email: str
|
||||
password: str
|
||||
target_exam: Optional[str] = "JEE_Main"
|
||||
student_class: Optional[str] = "12"
|
||||
medium: Optional[str] = "English"
|
||||
school: Optional[str] = None
|
||||
|
||||
class LoginPayload(BaseModel):
|
||||
email: str
|
||||
@@ -118,19 +122,65 @@ def register(payload: RegisterPayload, session: Session = Depends(get_session)):
|
||||
existing = session.exec(select(models.User).where(models.User.email == payload.email)).first()
|
||||
if existing:
|
||||
raise HTTPException(status_code=400, detail="Email already registered")
|
||||
|
||||
# Check if new registrations are allowed
|
||||
settings = session.get(models.SystemSettings, "global")
|
||||
if not settings:
|
||||
settings = models.SystemSettings()
|
||||
session.add(settings)
|
||||
session.commit()
|
||||
session.refresh(settings)
|
||||
|
||||
if not settings.allow_new_registrations:
|
||||
raise HTTPException(status_code=403, detail="New registrations are currently disabled.")
|
||||
|
||||
hashed_password = bcrypt.hashpw(payload.password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
|
||||
# Creating a dummy user with default enums since the payload is simplified
|
||||
# Map exam string to enum safely
|
||||
exam_map = {
|
||||
"JEE_Main": models.ExamEnum.JEE_MAIN,
|
||||
"JEE_Advanced": models.ExamEnum.JEE_ADVANCED,
|
||||
"NEET": models.ExamEnum.NEET,
|
||||
"jee_main": models.ExamEnum.JEE_MAIN,
|
||||
"jee_adv": models.ExamEnum.JEE_ADVANCED,
|
||||
"neet": models.ExamEnum.NEET,
|
||||
}
|
||||
class_map = {
|
||||
"11": models.ClassEnum.ELEVENTH,
|
||||
"12": models.ClassEnum.TWELFTH,
|
||||
"dropper": models.ClassEnum.DROPPER,
|
||||
"Dropper": models.ClassEnum.DROPPER,
|
||||
}
|
||||
medium_map = {
|
||||
"English": models.MediumEnum.ENGLISH,
|
||||
"Hindi": models.MediumEnum.HINDI,
|
||||
"Bilingual": models.MediumEnum.BILINGUAL,
|
||||
"en": models.MediumEnum.ENGLISH,
|
||||
"hi": models.MediumEnum.HINDI,
|
||||
"bi": models.MediumEnum.BILINGUAL,
|
||||
}
|
||||
|
||||
target_exam = exam_map.get(payload.target_exam or "JEE_Main", models.ExamEnum.JEE_MAIN)
|
||||
student_class = class_map.get(payload.student_class or "12", models.ClassEnum.TWELFTH)
|
||||
medium = medium_map.get(payload.medium or "English", models.MediumEnum.ENGLISH)
|
||||
|
||||
# Calculate trial_end based on admin settings
|
||||
trial_end = None
|
||||
if settings.enable_free_trial and settings.trial_duration_days > 0:
|
||||
trial_end = datetime.utcnow() + timedelta(days=settings.trial_duration_days)
|
||||
|
||||
new_user = models.User(
|
||||
name=payload.name,
|
||||
email=payload.email,
|
||||
password_hash=hashed_password,
|
||||
student_class=models.ClassEnum.TWELFTH,
|
||||
target_exam=models.ExamEnum.JEE_MAIN,
|
||||
medium=models.MediumEnum.ENGLISH,
|
||||
student_class=student_class,
|
||||
target_exam=target_exam,
|
||||
medium=medium,
|
||||
school=payload.school,
|
||||
city="Unknown",
|
||||
state="Unknown"
|
||||
state="Unknown",
|
||||
trial_end=trial_end,
|
||||
streak_count=0,
|
||||
)
|
||||
|
||||
session.add(new_user)
|
||||
@@ -138,23 +188,26 @@ def register(payload: RegisterPayload, session: Session = Depends(get_session)):
|
||||
session.refresh(new_user)
|
||||
|
||||
# Send welcome email in background (non-blocking)
|
||||
from fastapi.background import BackgroundTasks as BT
|
||||
send_welcome_email(payload.email, payload.name)
|
||||
|
||||
return {"success": True, "message": "User registered successfully"}
|
||||
return {"success": True, "message": "User registered successfully", "trial_end": trial_end.isoformat() if trial_end else None}
|
||||
|
||||
@app.post("/api/auth/login", tags=["Authentication"])
|
||||
def login(payload: LoginPayload, session: Session = Depends(get_session)):
|
||||
import bcrypt
|
||||
|
||||
# Allow demo/admin mock logic to still work if needed
|
||||
# demo@pragativeer.com → Neha Verma (AI Coach demo account)
|
||||
NEHA_UUID = "33333333-3333-3333-3333-333333333333"
|
||||
if payload.email == "demo@pragativeer.com" and payload.password == "Pv9#kL2$mQ8!vX4@":
|
||||
demo_user = session.exec(select(models.User).where((models.User.email == "demo@pragativeer.com") | (models.User.email == "student@pragativeer.com"))).first()
|
||||
if demo_user and demo_user.email != "demo@pragativeer.com":
|
||||
demo_user.email = "demo@pragativeer.com"
|
||||
session.add(demo_user)
|
||||
session.commit()
|
||||
token_id = str(demo_user.id) if demo_user else "b0e17378-864d-439e-8806-708dc48a891b"
|
||||
import uuid as _uuid
|
||||
demo_user = session.get(models.User, _uuid.UUID(NEHA_UUID))
|
||||
if not demo_user:
|
||||
# Fallback: look for any demo-tagged user
|
||||
demo_user = session.exec(select(models.User).where(
|
||||
(models.User.email == "demo@pragativeer.com") | (models.User.name == "Neha Verma")
|
||||
)).first()
|
||||
token_id = str(demo_user.id) if demo_user else NEHA_UUID
|
||||
return {"success": True, "role": "user", "token": token_id}
|
||||
if payload.email == "admin@pragativeer.com" and payload.password == "admin123":
|
||||
return {"success": True, "role": "admin", "token": "admin"}
|
||||
@@ -1047,6 +1100,7 @@ def list_all_students(session: Session = Depends(get_session)):
|
||||
"longest_streak": u.longest_streak,
|
||||
"last_active": u.last_active.isoformat(),
|
||||
"created_at": u.created_at.isoformat(),
|
||||
"trial_end": u.trial_end.isoformat() if u.trial_end else None,
|
||||
"total_tests": len(attempt_count),
|
||||
"avg_accuracy": avg_accuracy,
|
||||
"total_mistakes": len(mistake_count),
|
||||
|
||||
Reference in New Issue
Block a user