From f59ff542562696ddf69541baf0c26221d55de286 Mon Sep 17 00:00:00 2001 From: Amir Husayn Panahifar Date: Mon, 19 Oct 2026 18:38:43 +0330 Subject: [PATCH] feat: chapter labels, staff draft visibility, and chat FAB mobile fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename chapter labels from "هفتهٔ N" to "فصل N" in skill-tree - Show dashed "پیش‌نویس" badge on unpublished chapters/lessons for staff - Add isPublished to TreeLesson type (backend already exposes it) - Fix chat FAB and notification banner overlapping bottom nav on mobile --- frontend/src/components/mentor-chat.tsx | 6 ++++-- frontend/src/components/skill-tree.tsx | 22 ++++++++++++++++++++-- frontend/src/lib/types.ts | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/mentor-chat.tsx b/frontend/src/components/mentor-chat.tsx index d6d704e..a6bc217 100644 --- a/frontend/src/components/mentor-chat.tsx +++ b/frontend/src/components/mentor-chat.tsx @@ -3269,7 +3269,7 @@ ws.onmessage = (ev) => { setOpen(true); setNotif(null); }} - className="fixed bottom-24 start-5 end-5 z-[64] flex max-w-full items-center gap-2.5 rounded-2xl border-2 border-white/50 bg-card/85 p-2.5 text-right shadow-offset backdrop-blur-2xl sm:end-auto sm:max-w-[300px]" + className="fixed bottom-[calc(5.5rem+env(safe-area-inset-bottom,0px))] start-5 end-5 z-[64] flex max-w-full items-center gap-2.5 rounded-2xl border-2 border-white/50 bg-card/85 p-2.5 text-right shadow-offset backdrop-blur-2xl sm:bottom-24 sm:end-auto sm:max-w-[300px]" > @@ -3286,7 +3286,9 @@ ws.onmessage = (ev) => { {me && !open && ( -
+ // On mobile the bottom nav is 56px; lift FAB above it + safe area + gap. + // md:bottom-5 restores original position when the bottom nav is hidden. +
{unreadTotal > 0 && ( diff --git a/frontend/src/components/skill-tree.tsx b/frontend/src/components/skill-tree.tsx index f2fa626..b33c27b 100644 --- a/frontend/src/components/skill-tree.tsx +++ b/frontend/src/components/skill-tree.tsx @@ -21,6 +21,7 @@ import { } from "lucide-react"; import { useMemo, useState } from "react"; import type { TreeChapter, TreeData, TreeLesson } from "@/lib/types"; +import { useAuth } from "@/lib/auth-store"; import { cn, formatFaNumber } from "@/lib/utils"; const CHAPTER_ICONS: Record = { @@ -38,6 +39,8 @@ const CHAPTER_ICONS: Record = { export function SkillTree({ data, onSelect }: { data: TreeData; onSelect?: (id: number) => void }) { const router = useRouter(); + const role = useAuth((s) => s.user?.role); + const isStaff = role === "admin" || role === "mentor"; const chapters = useMemo(() => [...data.chapters].sort((a, b) => a.sortOrder - b.sortOrder), [data]); const byId = useMemo(() => { @@ -97,6 +100,7 @@ export function SkillTree({ data, onSelect }: { data: TreeData; onSelect?: (id: open={expanded.has(ch.id)} onToggle={() => toggle(ch.id)} onSelect={onSelect ?? ((id: number) => router.push(`/player/${id}`))} + isStaff={isStaff} /> ))}
@@ -110,12 +114,14 @@ function ChapterRow({ open, onToggle, onSelect, + isStaff, }: { ch: TreeChapter; byId: Map; open: boolean; onToggle: () => void; onSelect: (id: number) => void; + isStaff: boolean; }) { const lessons = [...(ch.lessons ?? [])].sort((a, b) => a.y - b.y || a.x - b.x); const done = lessons.filter((l) => l.progress?.passedQuiz).length; @@ -147,8 +153,13 @@ function ChapterRow({ کامل شد )} + {isStaff && !ch.isPublished && ( + + پیش‌نویس + + )} - هفتهٔ {ch.sortOrder} + فصل {ch.sortOrder}

{ch.description}

@@ -173,7 +184,7 @@ function ChapterRow({
{lessons.map((lesson) => ( - + ))}
@@ -186,10 +197,12 @@ function LessonRow({ lesson, byId, onSelect, + isStaff, }: { lesson: TreeLesson; byId: Map; onSelect: (id: number) => void; + isStaff: boolean; }) { const passed = !!lesson.progress?.passedQuiz; const locked = lesson.locked; @@ -254,6 +267,11 @@ function LessonRow({
{s.pillText} + {isStaff && lesson.isPublished === false && ( + + پیش‌نویس + + )} {inProgress && (
diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index f63060b..c7e1efa 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -117,6 +117,7 @@ export interface TreeLesson { xpReward: number; durationSeconds: number; chapterId: number; + isPublished?: boolean; } export interface TreeChapter extends Chapter {