import { LogOut, Edit2, CheckCircle2, Clock, XCircle, TrendingUp, Play, Camera } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { motion } from "motion/react"; import profileIcon from "../../assets/image 5.png"; import coinImage from "figma:asset/f7664d355c12b1003ad460ff44c8f22cfb1bbf5a.png"; import { logout, getUserInfo } from "../../utils/auth"; import { useEffect, useState } from "react"; import { getUserProfile, getCachedProfile, saveUserProfile, getUserProfileData, type UserProfile, type ProfileChallenge, type ProfileCoinTransaction, type ProfilePost } from "../../services/profileService"; import { PostCard } from "./PostCard"; import { AvatarSelectionModal } from "./AvatarSelectionModal"; import { getProfileImageUrl, getFeedImageUrl, getVideoUrl, getAudioUrl, isImageFile, getMagicBagFileUrl, getAvatarUrl, bumpAvatarCacheBust } from "../../services/feedService"; import { ImageWithFallback } from "./figma/ImageWithFallback"; import { usePageTracking } from "../../hooks/usePageTracking"; import { getMissionTypeToTopicId } from "../../utils/topicMapper"; import { useProfile } from "../context/ProfileContext"; const getStatusBadge = (status: string) => { if (status === "انجام شده") { return { icon: , text: "انجام شده", gradient: "linear-gradient(135deg, rgba(34, 197, 94, 0.9) 0%, rgba(22, 163, 74, 0.9) 100%)", border: "rgba(34, 197, 94, 0.5)", shadow: "0 2px 8px rgba(34, 197, 94, 0.4)", }; } else if (status === "تایید شده") { return { icon: , text: "تایید شده", gradient: "linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(37, 99, 235, 0.9) 100%)", border: "rgba(59, 130, 246, 0.5)", shadow: "0 2px 8px rgba(59, 130, 246, 0.4)", }; } else if (status === "در حال انجام") { return { icon: , text: "در حال انجام", gradient: "linear-gradient(135deg, rgba(255, 193, 7, 0.9) 0%, rgba(255, 160, 0, 0.9) 100%)", border: "rgba(255, 193, 7, 0.5)", shadow: "0 2px 8px rgba(255, 193, 7, 0.4)", }; } else if (status === "رد شده") { return { icon: , text: "رد شده", gradient: "linear-gradient(135deg, rgba(239, 68, 68, 0.9) 0%, rgba(220, 38, 38, 0.9) 100%)", border: "rgba(239, 68, 68, 0.5)", shadow: "0 2px 8px rgba(239, 68, 68, 0.4)", }; } else { return { icon: , text: status, gradient: "linear-gradient(135deg, rgba(156, 163, 175, 0.9) 0%, rgba(107, 114, 128, 0.9) 100%)", border: "rgba(156, 163, 175, 0.5)", shadow: "0 2px 8px rgba(156, 163, 175, 0.4)", }; } }; export function ProfilePage() { const navigate = useNavigate(); usePageTracking("پروفایل"); const { refreshProfile } = useProfile(); const [userInfo, setUserInfo] = useState<{ Name: string; Family: string; Username: string } | null>(null); const [userProfile, setUserProfile] = useState(null); const [isLoggingOut, setIsLoggingOut] = useState(false); const [isLoadingProfile, setIsLoadingProfile] = useState(true); const [activeTab, setActiveTab] = useState<"challenges" | "coins" | "posts">("challenges"); const [showAvatarModal, setShowAvatarModal] = useState(false); const [challenges, setChallenges] = useState([]); const [coinTransactions, setCoinTransactions] = useState([]); const [posts, setPosts] = useState([]); const [isLoadingData, setIsLoadingData] = useState(false); useEffect(() => { const info = getUserInfo(); setUserInfo(info); loadProfile(); }, []); const loadProfile = async () => { setIsLoadingProfile(true); try { const cachedProfile = getCachedProfile(); if (cachedProfile) { setUserProfile(cachedProfile); } const profile = await getUserProfile(); if (profile) { setUserProfile(profile); } } catch (error) { // خطاها در سطح سرویس مدیریت می‌شوند } finally { setIsLoadingProfile(false); } // بارگذاری داده‌های کامل پروفایل loadProfileData(); }; const loadProfileData = async () => { setIsLoadingData(true); try { const data = await getUserProfileData(); if (data) { setChallenges(data.challenges); setCoinTransactions(data.coin_transaction); setPosts(data.posts); } } catch (error) { console.error("خطا در بارگذاری داده‌های پروفایل:", error); } finally { setIsLoadingData(false); } }; const handleLogout = async () => { setIsLoggingOut(true); try { await logout(); navigate("/login", { state: { error: "شما با موفقیت از سیستم خارج شدید" } }); } catch (error) { console.error("خطا در خروج:", error); navigate("/login", { state: { error: "شما با موفقیت از سیستم خارج شدید" } }); } finally { setIsLoggingOut(false); } }; const toPersianNumber = (num: number | null | undefined): string => { if (num === null || num === undefined) return "۰"; const persianDigits = "۰۱۲۳۴۵۶۷۸۹"; return String(num).replace(/\d/g, (digit) => persianDigits[parseInt(digit)]); }; const handleAvatarSelect = async (imageFilename: string) => { // imageFilename از AvatarSelectionModal نام فایل آپلود شده به سرور است console.log("handleAvatarSelect called with:", imageFilename); // ذخیره در پروفایل if (userProfile) { // به‌روزرسانی state موقت setUserProfile({ ...userProfile, image: imageFilename }); // ذخیره در سرور try { const username = userProfile.username; const saveData = { WorkflowID: userProfile.user_workflowID, user: { username: username, name: userProfile.name, family: userProfile.family, education_level: userProfile.education_level, base: userProfile.base, image: imageFilename, }, }; console.log("Saving profile with data:", JSON.stringify(saveData)); const result = await saveUserProfile(saveData); console.log("Save profile result:", result); if (result) { bumpAvatarCacheBust(); } // بارگذاری مجدد پروفایل از سرور console.log("Reloading profile from server..."); await refreshProfile(); console.log("Profile reloaded successfully"); } catch (error) { console.error("Error saving avatar:", error); alert("خطا در ذخیره تصویر پروفایل"); } } else { console.error("No userProfile available"); } }; const handleDeletePost = (postId: string) => { // حذف پست از لیست setPosts((prevPosts) => prevPosts.filter((post) => post.workflow_ID !== postId)); }; const navLikePanelStyle = { backgroundImage: ` linear-gradient(180deg, #2E1B3D 0%, #23183E 100%), linear-gradient(120deg, #7c3aed 0%, #f97316 58%, #facc15 100%) `, backgroundOrigin: "border-box", backgroundClip: "padding-box, border-box", boxShadow: "0 -7px 20px rgba(7, 0, 18, 0.5), 0 6px 14px rgba(5, 2, 12, 0.26), inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 2px 5px rgba(255, 222, 255, 0.09), inset 0 -2px 0 rgba(12, 7, 27, 0.72), inset 0 -8px 14px rgba(8, 4, 18, 0.34), inset 0 0 0 1px rgba(255, 255, 255, 0.045), inset 0 0 0 2px rgba(17, 10, 35, 0.32)", backdropFilter: "blur(14px)", WebkitBackdropFilter: "blur(14px)", } as const; return (
{/* Avatar & Info Section */} {/* Avatar with Edit Button */}
{userProfile?.image ? ( ) : ( پروفایل )}
{/* دکمه تغییر عکس */} setShowAvatarModal(true)} className="absolute bottom-0 right-0 w-8 h-8 rounded-full flex items-center justify-center" style={{ background: "linear-gradient(135deg, rgba(255, 193, 7, 0.95) 0%, rgba(255, 152, 0, 0.95) 100%)", boxShadow: "0 3px 10px rgba(255, 193, 7, 0.6), 0 0 16px rgba(255, 193, 7, 0.4)", border: "2px solid rgba(255, 255, 255, 0.9)", }} >
{/* Name */}

{isLoadingProfile ? "در حال بارگذاری..." : userProfile ? `${userProfile.name} ${userProfile.family}` : userInfo ? `${userInfo.Name} ${userInfo.Family}` : "کاربر گرامی"}

{/* Education Info */} {userProfile && (
{userProfile.education_level} - پایه {userProfile.base}
)} {/* Stats */}
{[ { label: "چالش‌ها", value: toPersianNumber(challenges.filter(c => c.status === "انجام شده").length) }, { label: "سکه‌ها", value: toPersianNumber(userProfile?.coin_count) }, { label: "پست‌ها", value: toPersianNumber(posts.length) }, ].map((stat, index) => (
{stat.value}
{stat.label}
))}
{/* Action Buttons */}
{/* Edit Profile Button */} {userProfile?.user_workflowID ? ( navigate("/edit-profile")} className="flex-1 flex items-center justify-center gap-1.5 px-4 py-2 rounded-2xl font-bold text-xs" style={{ background: "linear-gradient(135deg, rgba(76, 175, 80, 0.9) 0%, rgba(56, 142, 60, 0.9) 100%)", boxShadow: "0 3px 12px rgba(76, 175, 80, 0.4)", color: "#FFFFFF", textShadow: "0 1px 3px rgba(0, 0, 0, 0.5)", }} > ویرایش ) : !isLoadingProfile ? ( navigate("/edit-profile")} className="flex-1 flex items-center justify-center gap-1.5 px-4 py-2 rounded-2xl font-bold text-xs" style={{ background: "linear-gradient(135deg, rgba(255, 193, 7, 0.9) 0%, rgba(255, 160, 0, 0.9) 100%)", boxShadow: "0 3px 12px rgba(255, 193, 7, 0.4)", color: "#FFFFFF", textShadow: "0 1px 3px rgba(0, 0, 0, 0.5)", }} > تکمیل پروفایل ) : null} {/* Logout Button */} {isLoggingOut ? "خروج..." : "خروج"}
{/* Tab Switcher */}
setActiveTab("challenges")} className="flex-1 py-2 rounded-2xl font-bold text-[11px] flex items-center justify-center gap-1" style={{ background: activeTab === "challenges" ? "linear-gradient(135deg, rgba(255, 183, 0, 0.95) 0%, rgba(255, 140, 0, 0.95) 100%)" : "linear-gradient(135deg, rgba(50, 107, 118, 0.6) 0%, rgba(32, 76, 106, 0.6) 100%)", boxShadow: activeTab === "challenges" ? "0 3px 12px rgba(255, 165, 0, 0.5)" : "0 2px 6px rgba(0, 0, 0, 0.3)", border: activeTab === "challenges" ? "1.5px solid rgba(255, 200, 50, 0.5)" : "1.5px solid rgba(138, 206, 224, 0.3)", color: activeTab === "challenges" ? "#5A3800" : "#FFFFFF", textShadow: activeTab === "challenges" ? "0 1px 0 rgba(255, 255, 255, 0.2)" : "none", }} > سابقه چالش‌ها setActiveTab("coins")} className="flex-1 py-2 rounded-2xl font-bold text-[11px] flex items-center justify-center gap-1" style={{ background: activeTab === "coins" ? "linear-gradient(135deg, rgba(255, 183, 0, 0.95) 0%, rgba(255, 140, 0, 0.95) 100%)" : "linear-gradient(135deg, rgba(50, 107, 118, 0.6) 0%, rgba(32, 76, 106, 0.6) 100%)", boxShadow: activeTab === "coins" ? "0 3px 12px rgba(255, 165, 0, 0.5)" : "0 2px 6px rgba(0, 0, 0, 0.3)", border: activeTab === "coins" ? "1.5px solid rgba(255, 200, 50, 0.5)" : "1.5px solid rgba(138, 206, 224, 0.3)", color: activeTab === "coins" ? "#5A3800" : "#FFFFFF", textShadow: activeTab === "coins" ? "0 1px 0 rgba(255, 255, 255, 0.2)" : "none", }} > سابقه سکه‌ها setActiveTab("posts")} className="flex-1 py-2 rounded-2xl font-bold text-[11px] flex items-center justify-center gap-1" style={{ background: activeTab === "posts" ? "linear-gradient(135deg, rgba(255, 183, 0, 0.95) 0%, rgba(255, 140, 0, 0.95) 100%)" : "linear-gradient(135deg, rgba(50, 107, 118, 0.6) 0%, rgba(32, 76, 106, 0.6) 100%)", boxShadow: activeTab === "posts" ? "0 3px 12px rgba(255, 165, 0, 0.5)" : "0 2px 6px rgba(0, 0, 0, 0.3)", border: activeTab === "posts" ? "1.5px solid rgba(255, 200, 50, 0.5)" : "1.5px solid rgba(138, 206, 224, 0.3)", color: activeTab === "posts" ? "#5A3800" : "#FFFFFF", textShadow: activeTab === "posts" ? "0 1px 0 rgba(255, 255, 255, 0.2)" : "none", }} > پست‌ها
{/* Challenges Tab */} {activeTab === "challenges" && (
{isLoadingData ? (
در حال بارگذاری...
) : challenges.length === 0 ? (
هنوز چالشی ثبت نشده است
) : ( challenges.map((challenge, index) => { const statusBadge = getStatusBadge(challenge.status); const coins = parseInt(challenge.coin_count || "0"); const isInProgress = challenge.status === "در حال انجام"; return ( { if (isInProgress && challenge.mission_id) { const topicId = getMissionTypeToTopicId(challenge.mission_type); navigate(`/chatbot/${topicId}?missionId=${challenge.mission_id}&missionType=${encodeURIComponent(challenge.mission_type)}&continueMode=true`); } }} className={`rounded-2xl p-4 ${isInProgress ? 'cursor-pointer' : ''}`} style={{ background: isInProgress ? "linear-gradient(135deg, rgba(255, 193, 7, 0.15) 0%, rgba(255, 152, 0, 0.15) 100%)" : "linear-gradient(135deg, rgba(32, 76, 106, 0.5) 0%, rgba(20, 40, 60, 0.5) 100%)", border: isInProgress ? "1.5px solid rgba(255, 193, 7, 0.4)" : "1.5px solid rgba(138, 206, 224, 0.3)", boxShadow: isInProgress ? "0 4px 16px rgba(255, 193, 7, 0.3)" : "0 4px 12px rgba(0, 0, 0, 0.3)", }} whileHover={isInProgress ? { scale: 1.02, y: -2 } : {}} whileTap={isInProgress ? { scale: 0.98 } : {}} >

{challenge.mission_title}

{isInProgress && ( )}
{statusBadge.icon} {statusBadge.text}
{challenge.datetime1} {isInProgress && ( {challenge.mission_type} )}
{(challenge.status === "انجام شده" || challenge.status === "تایید شده") && coins > 0 && (
سکه +{toPersianNumber(coins)}
)} {isInProgress ? ( برای ادامه کلیک کنید ← ) : ( {challenge.mission_type} )}
); }) )}
)} {/* Coins Tab */} {activeTab === "coins" && (
{/* Total Coins Summary */}

مجموع سکه‌های دریافتی

سکه {toPersianNumber(userProfile?.coin_count)}
{/* Coin History */} {isLoadingData ? (
در حال بارگذاری...
) : coinTransactions.length === 0 ? (
هنوز تراکنشی ثبت نشده است
) : ( coinTransactions.map((item, index) => { const coins = parseInt(item.coin_count || "0"); const isNegative = coins < 0; const absCoins = Math.abs(coins); return (

{item.description}

سکه {isNegative ? "-" : "+"}{toPersianNumber(absCoins)}
); }) )}
)} {/* Posts Tab */} {activeTab === "posts" && (
{isLoadingData ? (
در حال بارگذاری...
) : posts.length === 0 ? (
هنوز پستی منتشر نشده است
) : ( posts.map((post, index) => { // تعیین نوع مدیا let mediaType: 'image' | 'video' | 'audio' = 'image'; let mediaUrl: string | undefined; let imageUrl: string; if (post.film) { mediaType = 'video'; mediaUrl = getVideoUrl(post.StageID); imageUrl = post.image ? getFeedImageUrl(post.StageID) : ''; } else if (post.audio) { mediaType = 'audio'; mediaUrl = getAudioUrl(post.StageID); imageUrl = post.image ? getFeedImageUrl(post.StageID) : ''; } else { mediaType = 'image'; imageUrl = post.image ? getFeedImageUrl(post.StageID) : ''; } return (
{/* Simple Topic Label with Line */}
{post.mission_type}
{/* Post Card */}
); }) )}
)} {/* Avatar Selection Modal */} setShowAvatarModal(false)} onSelectAvatar={handleAvatarSelect} currentAvatar={userProfile?.image ? getProfileImageUrl(userProfile.image, userProfile.user_stage_id) : undefined} />
); }