+ {/* 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}
+ />
+
+ );
+}
diff --git a/src/app/components/ProtectedFeedPage.tsx b/src/app/components/ProtectedFeedPage.tsx
new file mode 100644
index 0000000..6e9f476
--- /dev/null
+++ b/src/app/components/ProtectedFeedPage.tsx
@@ -0,0 +1,10 @@
+import { ProtectedRoute } from "./ProtectedRoute";
+import { FeedPage } from "./FeedPage";
+
+export function ProtectedFeedPage() {
+ return (
+