Subject bar under the header in Quizzes and Lessons, synced between tabs; bidi fix for Latin math in RTL text
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,8 @@ const STARTERS = ['این فصل دربارهی چیه؟', 'یه مثالِ
|
||||
|
||||
/** «از {همراه} بپرس»: دستیارِ ریاضی که از روی کتابِ پایهی کاربر جواب میدهد؛ چهره و نامش همراهِ انتخابیِ کاربر است. */
|
||||
export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number; questionId?: string; prompt?: string }) {
|
||||
const { profile } = useAppData();
|
||||
const { profile, home } = useAppData();
|
||||
const subjectTitle = home?.subject?.title;
|
||||
const companion = useCompanion();
|
||||
const chat = useAskState();
|
||||
const [input, setInput] = useState('');
|
||||
@@ -90,6 +91,9 @@ export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number;
|
||||
userQuestion: question,
|
||||
conversationId: askStore.get().conversationId ?? undefined,
|
||||
lessonId: askStore.get().lessonId ?? undefined,
|
||||
// بیدرس، کتابِ انتخابیِ دانشآموز (هندسه، گسسته، …) را میفرستیم تا دستیار از همان کتاب جواب بدهد؛
|
||||
// با درس، سرور کتاب را از خودِ درس درمیآورد.
|
||||
subject: askStore.get().lessonId ? undefined : subjectTitle,
|
||||
questionId: forQuestionId,
|
||||
},
|
||||
(delta) => {
|
||||
|
||||
@@ -14,6 +14,7 @@ import { MathText } from '@/lib/MathText';
|
||||
import { BrandFooter } from '@/components/BrandFooter';
|
||||
import { BrandMark } from '@/components/BrandMark';
|
||||
import { StreakFlame, flameState } from '@/components/StreakFlame';
|
||||
import { SubjectBar } from '@/components/SubjectBar';
|
||||
|
||||
/**
|
||||
* خانه = خودِ مسیر، مثلِ دولینگو: همهی فصلهای پایه پشتِ هم، و جزیرهی فعلی با
|
||||
@@ -108,6 +109,8 @@ export function HomeScreen() {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<SubjectBar />
|
||||
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
{!home ? (
|
||||
homeError ? <ErrorState error={homeError} onRetry={() => void refreshHome()} /> : <LoadingState text="دارم مسیرت رو میارم…" />
|
||||
|
||||
@@ -12,6 +12,7 @@ import { iconFor } from '@/components/NodeIcon';
|
||||
import { toFa } from '@/lib/format';
|
||||
import { MathText } from '@/lib/MathText';
|
||||
import { useFirstVisit } from '@/lib/firstVisit';
|
||||
import { SubjectBar } from '@/components/SubjectBar';
|
||||
|
||||
/**
|
||||
* تبِ «درسها»: فصل ← جزیره ← درس. فصلها اول بستهاند و بالای صفحه یک کارتِ «ادامه بده» هست.
|
||||
@@ -53,6 +54,8 @@ export function LessonsScreen() {
|
||||
)}
|
||||
</ScreenHeader>
|
||||
|
||||
<SubjectBar />
|
||||
|
||||
<div className="flex-1 overflow-y-auto px-4 pb-6 pt-4">
|
||||
{!home ? (
|
||||
homeError ? <ErrorState error={homeError} onRetry={() => void refreshHome()} /> : <LoadingState text="دارم درسها رو میارم…" />
|
||||
|
||||
@@ -256,7 +256,7 @@ function GradeSheet({ open, onClose }: { open: boolean; onClose: () => void }) {
|
||||
await api.profile.setGrade(gradeId);
|
||||
setProfile({ ...profile, gradeId });
|
||||
askStore.reset(null);
|
||||
await Promise.all([refreshHome(), refreshSummary()]);
|
||||
await Promise.all([refreshHome(gradeId), refreshSummary()]);
|
||||
toast('پایهت عوض شد', 'success');
|
||||
onClose();
|
||||
} catch (err) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AnimatePresence, motion } from 'motion/react';
|
||||
import { Brain, Check, ChevronLeft, Coins, Compass, Flag, Heart, Infinity as InfinityIcon, Lightbulb, Ruler, Sparkles, Star, Target, ThumbsUp, X, Zap, type LucideIcon } from 'lucide-react';
|
||||
import { api, ApiError, type AnswerResult, type Hearts, type Question, type ReportReason } from '@/api';
|
||||
import { useAppData } from '@/state/AppData';
|
||||
import { fetchHome } from '@/state/subject';
|
||||
import { findNode, findNodeOfLesson, nextLessonOf, unitColor } from '@/state/curriculum';
|
||||
import { useNav } from '@/nav/Navigator';
|
||||
import { newIdempotencyKey } from '@/api/http';
|
||||
@@ -449,7 +450,7 @@ function Result({
|
||||
result, total, correct, lessonId, nodeId, color, streakUp,
|
||||
}: { result: QuizResult; total: number; correct: number; lessonId?: number; nodeId?: string; color: string; streakUp: { from: number; to: number } | null }) {
|
||||
const nav = useNav();
|
||||
const { companion } = useAppData();
|
||||
const { companion, profile } = useAppData();
|
||||
const [loadingNext, setLoadingNext] = useState(false);
|
||||
// بعد از نتیجه، اگر زنجیره امروز روشن شد، یک صفحهی جشنِ جدا (مثلِ دولینگو) و بعد مقصدِ انتخابشده.
|
||||
const [streakThen, setStreakThen] = useState<(() => void) | null>(null);
|
||||
@@ -468,7 +469,7 @@ function Result({
|
||||
}
|
||||
setLoadingNext(true);
|
||||
try {
|
||||
const fresh = await api.home();
|
||||
const fresh = await fetchHome(profile.gradeId);
|
||||
const ref = findNode(fresh, nodeId) ?? findNodeOfLesson(fresh, lessonId!);
|
||||
const next = ref ? nextLessonOf(ref.node) : null;
|
||||
if (ref && ref.node.status !== 'completed' && next != null && next !== lessonId) {
|
||||
|
||||
Reference in New Issue
Block a user