// src/components/admin/UserProfileView.tsx import { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useLanguage } from '../../lib/languageContext'; import { translations } from '../../lib/translations'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '../ui/card'; import { Button } from '../ui/button'; import { Badge } from '../ui/badge'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '../ui/alert-dialog'; import { Progress } from '../ui/progress'; import { Separator } from '../ui/separator'; import { toast } from 'sonner'; import { ArrowLeft, Mail, Calendar, MapPin, Award, Clock, DollarSign, Star, Users, Ban, Trash2, CheckCircle, AlertTriangle, Video, BookOpen, Target, Loader2, } from 'lucide-react'; // Import API import adminUserManagementApi, { type StudentDtoAdmin, type SheikhDtoAdmin, type UserManagementApiError, type StudentProfileResponse, type SheikhProfileResponse, type SessionHistoryDto, } from '../../lib/api/adminUserManagementApi'; // ─── Types & Interfaces ────────────────────────────────────────────────────── type UserType = 'student' | 'sheikh' | 'admin'; interface DisplayUser { id: number; name: string; email: string; registrationDate: string; type: UserType; status: string; // Student fields streak?: number | null; totalSessions?: number | null; // Sheikh fields numberOfSessions?: number | null; totalRevenue?: number | null; averageRating?: number | null; } interface StudentProfileData { profile: StudentProfileResponse['studentProfile']; sessions: SessionHistoryDto[]; } interface SheikhProfileData { profile: SheikhProfileResponse['sheikhProfile']; sessions: SessionHistoryDto[]; } // ─── Helpers ────────────────────────────────────────────────────────────────── function formatDate(dateString: string, locale: string): string { const d = new Date(dateString); return d.toLocaleDateString(locale === 'ar' ? 'ar-EG' : 'en-US', { year: 'numeric', month: 'long', day: 'numeric', }); } function formatNumber(value: number | null | undefined, locale: string): string { if (value === null || value === undefined) return '—'; return value.toLocaleString(locale === 'ar' ? 'ar-EG' : 'en-US'); } function formatCurrency(value: number | null | undefined, locale: string): string { if (value === null || value === undefined) return '—'; return `${value.toLocaleString(locale === 'ar' ? 'ar-EG' : 'en-US')} ${locale === 'ar' ? 'ج.م' : 'EGP'}`; } function formatRating(value: number | null | undefined): string { if (value === null || value === undefined) return '—'; return value.toFixed(1); } function formatDuration(minutes: number): string { const hours = Math.floor(minutes / 60); const mins = minutes % 60; if (hours === 0) return `${mins} ${mins === 1 ? 'min' : 'mins'}`; if (mins === 0) return `${hours} ${hours === 1 ? 'hr' : 'hrs'}`; return `${hours}h ${mins}m`; } // ─── Main Component ─────────────────────────────────────────────────────────── export function UserProfileView() { const { userId } = useParams<{ userId: string }>(); const navigate = useNavigate(); const { language } = useLanguage(); const t = translations[language]; const isArabic = language === 'ar'; const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [userType, setUserType] = useState(null); const [studentData, setStudentData] = useState(null); const [sheikhData, setSheikhData] = useState(null); const [actionLoading, setActionLoading] = useState(false); // ── Load user profile ───────────────────────────────────────────────────── useEffect(() => { loadUserProfile(); }, [userId]); const loadUserProfile = async () => { if (!userId) { setError('User ID not provided'); setLoading(false); return; } setLoading(true); setError(null); try { // Try to load as student first try { const studentProfile = await adminUserManagementApi.fetchStudentProfile(parseInt(userId)); setUserType('student'); setStudentData({ profile: studentProfile.studentProfile, sessions: studentProfile.sessionHistories, }); setLoading(false); return; } catch (err) { // Not a student, continue to try sheikh } // Try to load as sheikh try { const sheikhProfile = await adminUserManagementApi.fetchSheikhProfile(parseInt(userId)); setUserType('sheikh'); setSheikhData({ profile: sheikhProfile.sheikhProfile, sessions: sheikhProfile.sessionHistories, }); setLoading(false); return; } catch (err) { // Not a sheikh either if (err instanceof UserManagementApiError) { if (err.status === 404) { setError(isArabic ? 'المستخدم غير موجود' : 'User not found'); } else if (err.status === 403) { setError(isArabic ? 'صلاحية المسؤول مطلوبة' : 'Admin access required'); } else { setError(err.message); } } else { setError(isArabic ? 'فشل تحميل بيانات المستخدم' : 'Failed to load user data'); } } } finally { setLoading(false); } }; // ── Actions ─────────────────────────────────────────────────────────────── const handleBlock = async () => { if (!userId) return; setActionLoading(true); try { await adminUserManagementApi.blockUser(parseInt(userId)); toast.success( isArabic ? 'تم حظر المستخدم بنجاح' : 'User has been blocked' ); // Refresh data await loadUserProfile(); } catch (err) { console.error('Block failed:', err); toast.error( isArabic ? 'فشل حظر المستخدم' : 'Failed to block user' ); } finally { setActionLoading(false); } }; const handleUnblock = async () => { if (!userId) return; setActionLoading(true); try { await adminUserManagementApi.unblockUser(parseInt(userId)); toast.success( isArabic ? 'تم إلغاء حظر المستخدم بنجاح' : 'User has been unblocked' ); // Refresh data await loadUserProfile(); } catch (err) { console.error('Unblock failed:', err); toast.error( isArabic ? 'فشل إلغاء حظر المستخدم' : 'Failed to unblock user' ); } finally { setActionLoading(false); } }; const handleDelete = async () => { if (!userId) return; setActionLoading(true); try { // Note: Delete API not available yet toast.error( isArabic ? 'حذف المستخدمين غير متاح حالياً' : 'Delete user not available yet' ); } catch (err) { console.error('Delete failed:', err); } finally { setActionLoading(false); } }; const handleBack = () => { navigate('/admin/users'); }; // ── Loading State ───────────────────────────────────────────────────────── if (loading) { return (

{isArabic ? 'جاري تحميل الملف الشخصي...' : 'Loading profile...'}

); } // ── Error State ─────────────────────────────────────────────────────────── if (error || !userType) { return (
{isArabic ? 'خطأ' : 'Error'} {error || (isArabic ? 'المستخدم غير موجود' : 'User not found')}
); } const isStudent = userType === 'student'; const isSheikh = userType === 'sheikh'; const currentStatus = isStudent ? studentData?.profile.status : sheikhData?.profile.status; const isBlocked = currentStatus === 'BLOCKED'; const student = studentData?.profile; const sheikh = sheikhData?.profile; const sessions = studentData?.sessions || sheikhData?.sessions || []; return (
{/* Header + Actions */}

{isArabic ? 'الملف الشخصي' : 'User Profile'}

{isStudent ? student?.name : sheikh?.name}

{isBlocked ? (isArabic ? 'إلغاء حظر المستخدم؟' : 'Unblock User?') : (isArabic ? 'حظر المستخدم؟' : 'Block User?')} {isBlocked ? (isArabic ? 'سيُعاد للمستخدم الوصول إلى المنصة.' : "This will restore the user's access to the platform.") : (isArabic ? 'سيمنع هذا الإجراء المستخدم من الوصول إلى المنصة. يمكن إلغاء الحظر لاحقًا.' : 'This will prevent the user from accessing the platform. They can be unblocked later.')} {isArabic ? 'إلغاء' : 'Cancel'} {isBlocked ? (isArabic ? 'إلغاء الحظر' : 'Unblock') : (isArabic ? 'حظر' : 'Block')} {isArabic ? 'حذف المستخدم نهائيًا؟' : 'Delete User Permanently?'} {isArabic ? 'هذا الإجراء لا يمكن التراجع عنه. سيتم حذف الحساب وجميع البيانات المرتبطة به نهائيًا.' : 'This action cannot be undone. This will permanently delete the user account and all associated data.'} {isArabic ? 'إلغاء' : 'Cancel'} {isArabic ? 'حذف نهائي' : 'Delete Permanently'}
{/* Main User Card */}
{/* Avatar */}
{(isStudent ? student?.name : sheikh?.name)?.charAt(0).toUpperCase() || '?'}
{/* Info */}

{isStudent ? student?.name : sheikh?.name}

{userType.toUpperCase()} {!isBlocked ? ( <> {isArabic ? 'نشط' : 'Active'} ) : ( <> {isArabic ? 'محظور' : 'Blocked'} )}
{isStudent ? student?.email : sheikh?.email}
{isSheikh && sheikh?.country && (
{sheikh.country}
)}
{isArabic ? 'انضم في ' : 'Joined '} {formatDate( isStudent ? student?.registrationDate || '' : sheikh?.registrationDate || '', language )}
{isSheikh && sheikh?.bio && (

{sheikh.bio}

)}
{/* Right side stats */} {isSheikh && sheikh && (
{formatCurrency(sheikh.totalEarnings, language)}
{isArabic ? 'الأرباح' : 'Earnings'}
{formatRating(sheikh.averageRating)}
)} {isStudent && student && (
{formatNumber(student.sessionCount, language)}
{isArabic ? 'الجلسات' : 'Sessions'}
{student.streak ?? 0} 🔥
)}
{/* Statistics Cards Grid */} {isStudent && student && (
{isArabic ? 'إجمالي الجلسات' : 'Total Sessions'}
{formatNumber(student.sessionCount, language)}
{isArabic ? 'الجلسات المكتملة' : 'Completed Sessions'}
{formatNumber(student.numberOfCompletedSessions, language)}
{isArabic ? 'وقت التعلم' : 'Learning Time'}
{formatDuration(student.totalSpentTime)}
{isArabic ? 'السلسلة' : 'Streak'}
{student.streak ?? 0} 🔥
)} {isSheikh && sheikh && (
{isArabic ? 'إجمالي الجلسات' : 'Total Sessions'}
{formatNumber(sheikh.numberOfCompletedSessions, language)}
{isArabic ? 'عدد الطلاب' : 'Students'}
{formatNumber(sheikh.numberOfStudents, language)}
{isArabic ? 'التقييم' : 'Rating'}
{formatRating(sheikh.averageRating)}
{isArabic ? 'سعر الساعة' : 'Hourly Rate'}
{formatCurrency(sheikh.hourlyRate, language)}
)} {/* Session History */} {isArabic ? 'سجل الجلسات' : 'Session History'} {isArabic ? 'آخر الجلسات والأنشطة' : 'Recent sessions and activities'} {sessions.length === 0 ? (
{isArabic ? 'لا توجد جلسات سابقة' : 'No session history'}
) : (
{sessions.map((session) => (

{isStudent ? session.sheikhName : session.studentName}

{formatDate(session.date, language)} {session.durationInMinutes && ( · {formatDuration(session.durationInMinutes)} )}

{formatCurrency(session.price, language)}

{session.status === 'COMPLETED' ? (isArabic ? 'مكتملة' : 'Completed') : session.status === 'CANCELLED' ? (isArabic ? 'ملغية' : 'Cancelled') : (isArabic ? 'معلقة' : 'Pending')}
))}
)}
); }