fix: production readiness bugfix batch

- Security: JWT fallback removed, auth checks on unprotected endpoints
- Build: tsconfig excludes tests, ESLint flat config fixed
- Money: Cashout deducts balance in transaction, UI refreshes
- Core Chat: Nur page wired to send/receive messages
- Profile: Replaced hardcoded data with useAuth()
- Forum: Fixed thread detail query, premium check on posts
- Misc: /dua→/prayer, forum thread API handles ?id= param

QA gate: pending
This commit is contained in:
FalahMobile
2026-07-06 20:20:31 +08:00
parent 9f33038c37
commit d7b2d19359
13 changed files with 382 additions and 53 deletions
+38 -19
View File
@@ -1,10 +1,9 @@
'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
import { useAuth } from '@/lib/AuthContext'
import {
Pencil,
ChevronRight,
ShoppingBag,
HandHeart,
@@ -33,7 +32,7 @@ const SETTINGS = [
{
icon: Flame,
label: 'Spirituality Stats',
value: '124-day streak',
value: 'N/A',
color: 'text-orange-400',
},
{
@@ -61,6 +60,7 @@ const SETTINGS = [
export default function ProfilePage() {
const router = useRouter()
const { user, loading } = useAuth()
const handleSignOut = () => {
if (typeof window !== 'undefined') {
@@ -69,6 +69,19 @@ export default function ProfilePage() {
router.push('/login')
}
if (loading) {
return (
<div className="min-h-dvh bg-[#0a0a0f] flex items-center justify-center">
<div className="w-8 h-8 rounded-full border-2 border-[#D4AF37]/30 border-t-[#D4AF37] animate-spin" />
</div>
)
}
const displayName = user?.name || 'Guest'
const initial = displayName.charAt(0).toUpperCase()
const flhBalance = user?.flhBalance ?? 0
const usdValue = (flhBalance * 0.004).toFixed(2)
return (
<div className="min-h-dvh bg-[#0a0a0f] pb-32 select-none">
{/* Scrollable content */}
@@ -78,27 +91,31 @@ export default function ProfilePage() {
<div className="flex items-center gap-4">
{/* Avatar */}
<div className="w-[60px] h-[60px] rounded-full bg-[#D4AF37]/20 border-2 border-[#D4AF37]/30 flex items-center justify-center shrink-0">
<span className="text-xl font-bold text-[#D4AF37]">A</span>
<span className="text-xl font-bold text-[#D4AF37]">{initial}</span>
</div>
{/* Name + badges */}
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
<h2 className="text-white font-bold text-lg truncate">Ahmad</h2>
<button className="w-7 h-7 rounded-full bg-[#111118] border border-[#222] flex items-center justify-center active:scale-90 transition-transform shrink-0">
<Pencil size={12} className="text-[#999]" />
</button>
<h2 className="text-white font-bold text-lg truncate">{displayName}</h2>
</div>
<p className="text-[#999] text-sm truncate">ahmad@email.com</p>
<p className="text-[#999] text-sm truncate">{user?.email}</p>
<div className="flex items-center gap-2 mt-2">
{/* Premium badge */}
<span className="text-[10px] font-bold text-white bg-[#D4AF37] rounded-full px-2.5 py-0.5 uppercase tracking-wider">
Premium
</span>
{/* Level badge */}
<span className="text-[10px] font-bold text-white bg-[#10B981] rounded-full px-2.5 py-0.5 uppercase tracking-wider">
Lvl 7
</span>
{user?.isPremium && (
<span className="text-[10px] font-bold text-white bg-[#D4AF37] rounded-full px-2.5 py-0.5 uppercase tracking-wider">
Premium
</span>
)}
{user?.isPro && (
<span className="text-[10px] font-bold text-white bg-[#10B981] rounded-full px-2.5 py-0.5 uppercase tracking-wider">
Pro
</span>
)}
{user?.experienceLevel && (
<span className="text-[10px] font-bold text-white bg-[#10B981] rounded-full px-2.5 py-0.5 uppercase tracking-wider">
{user.experienceLevel}
</span>
)}
</div>
</div>
</div>
@@ -120,8 +137,10 @@ export default function ProfilePage() {
FLH Wallet
</p>
<div className="flex items-baseline gap-2">
<span className="text-xl font-bold text-[#D4AF37]">1,250</span>
<span className="text-xs text-[#999]"> .50 USD</span>
<span className="text-xl font-bold text-[#D4AF37]">
{flhBalance.toLocaleString()}
</span>
<span className="text-xs text-[#999]"> ${usdValue} USD</span>
</div>
</div>
</div>