parent report page with two charts, Jalali birth date picker, user ID and invoices in profile
- the parents section is gone: no parent login, invite codes or "I'm a parent" button; "گزارشِ والدین" in the profile shows the week against the previous one (praise line, six tiles, minutes-per-day and right/wrong-per-day charts, a table of the numbers) - birth date as day / month / year selects (Jalali, leap Esfand handled) instead of age; adults (19+) are asked which grade's math they want to learn - user ID under the name, copyable - "پرداختها و فاکتورها": every order with invoice number, discount, amount and reference code - tutor: when the free daily quota runs out, a button to the subscription page instead of "retry" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { motion } from 'motion/react';
|
||||
import { BookOpen, MessageSquarePlus, RotateCw, Send, ThumbsDown, ThumbsUp } from 'lucide-react';
|
||||
import { api } from '@/api';
|
||||
import { api, ApiError } from '@/api';
|
||||
import { useAppData } from '@/state/AppData';
|
||||
import { askStore, useAskState, type ChatMessage } from '@/state/askStore';
|
||||
import { useNav } from '@/nav/Navigator';
|
||||
import { SeyarMascot } from '@/mascots/SeyarMascot';
|
||||
import { useToast } from '@/components/Toast';
|
||||
import { Screen, ScreenHeader } from '@/components/ui';
|
||||
@@ -92,10 +93,13 @@ export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number;
|
||||
askStore.setConversation(done.conversationId);
|
||||
setQuota(done.remainingQuota);
|
||||
} catch (err) {
|
||||
// سقفِ روزانه (نه throttleِ چندثانیهای): «دوباره» تا فردا بیفایده است.
|
||||
const quotaReached = err instanceof ApiError && err.isRateLimited && err.detail.includes('سوال');
|
||||
askStore.update(replyId, {
|
||||
text: friendlyError(err, 'جوابی نرسید'),
|
||||
failedQuestion: question,
|
||||
...(quotaReached ? { quotaReached: true } : { failedQuestion: question }),
|
||||
});
|
||||
if (quotaReached) setQuota(0);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
@@ -263,6 +267,7 @@ function Message({
|
||||
onFollowUp: (q: string) => void;
|
||||
}) {
|
||||
const toast = useToast();
|
||||
const nav = useNav();
|
||||
|
||||
if (message.role === 'user') return <Bubble role="user"><MathText text={message.text} /></Bubble>;
|
||||
|
||||
@@ -286,7 +291,11 @@ function Message({
|
||||
<MathText text={message.text} />
|
||||
</Bubble>
|
||||
<div className="flex flex-wrap items-center gap-2 pr-10">
|
||||
{message.failedQuestion ? (
|
||||
{message.quotaReached ? (
|
||||
<button type="button" onClick={() => nav.switchTab('subscription')} className="rounded-full bg-violet px-3 py-1 text-xs font-bold text-white">
|
||||
دیدنِ اشتراکها
|
||||
</button>
|
||||
) : message.failedQuestion ? (
|
||||
<button type="button" disabled={busy} onClick={() => onRetry(message)} className="flex items-center gap-1 rounded-full bg-white px-3 py-1 text-xs font-bold text-coral ring-1 ring-line disabled:opacity-50">
|
||||
<RotateCw size={12} /> دوباره امتحان کن
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user