forked from Tadrisino/MathApp_frontend
Subscriptions only: no question credits anywhere; Bazaar bridge is subscribeProduct only (bazaarBuy(sku, orderId, token), bazaarPrices(skusJson)), no consume
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,13 +25,13 @@ export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number;
|
||||
const chat = useAskState();
|
||||
const [input, setInput] = useState('');
|
||||
const [busy, setBusy] = useState(false);
|
||||
// «X سوالِ رایگانِ امروز + Y سوالِ خریدهشده»؛ پیش از اولین سوال از سرور، بعد از هر جواب از خودِ جواب.
|
||||
const [quota, setQuota] = useState<{ free: number; credits: number } | null>(null);
|
||||
// «X سوالِ امروز»؛ پیش از اولین سوال از سرور، بعد از هر جواب از خودِ جواب.
|
||||
const [quota, setQuota] = useState<number | null>(null);
|
||||
const [quotaDone, setQuotaDone] = useState(false);
|
||||
useEffect(() => {
|
||||
api.ai
|
||||
.quota()
|
||||
.then((q) => setQuota({ free: q.remainingQuota, credits: q.credits }))
|
||||
.then((q) => setQuota(q.remainingQuota))
|
||||
.catch((err: unknown) => console.warn('ai quota lookup failed', err))
|
||||
.finally(() => setQuotaDone(true));
|
||||
}, []);
|
||||
@@ -109,7 +109,7 @@ export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number;
|
||||
diagram: done.diagram ?? null,
|
||||
});
|
||||
askStore.setConversation(done.conversationId);
|
||||
setQuota((q) => ({ free: done.remainingQuota, credits: done.credits ?? q?.credits ?? 0 }));
|
||||
setQuota(done.remainingQuota);
|
||||
} catch (err) {
|
||||
// سقفِ روزانه (نه throttleِ چندثانیهای): «دوباره» تا فردا بیفایده است.
|
||||
const quotaReached = err instanceof ApiError && err.isRateLimited && err.detail.includes('سوال');
|
||||
@@ -117,7 +117,7 @@ export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number;
|
||||
text: friendlyError(err, 'جوابی نرسید'),
|
||||
...(quotaReached ? { quotaReached: true } : { failedQuestion: question }),
|
||||
});
|
||||
if (quotaReached) setQuota({ free: 0, credits: 0 });
|
||||
if (quotaReached) setQuota(0);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ export function AskScreen({ lessonId, questionId, prompt }: { lessonId?: number;
|
||||
mascot={{ mood: busy ? 'excited' : 'idle', size: 60 }}
|
||||
>
|
||||
<div className="mt-3 flex flex-wrap items-center gap-2">
|
||||
{quota !== null && <QuotaPills free={quota.free} credits={quota.credits} />}
|
||||
{quota !== null && <QuotaPills free={quota} />}
|
||||
{!empty && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -355,23 +355,21 @@ function Message({
|
||||
}
|
||||
|
||||
/**
|
||||
* شمارنده در سربرگِ دستیار: سوالهای رایگانِ باقیِ امروز، و اگر از بستههای قدیمی سوالی خریده و مانده، آن هم جدا.
|
||||
* بسته از ۲۰۲۶-۱۰-۱۲ فروخته نمیشود؛ وقتی رایگانِ امروز تمام شد، دکمهی دوم به فروشگاهِ اشتراک میبرد.
|
||||
* شمارنده در سربرگِ دستیار: سوالهای باقیِ امروز. وقتی تمام شد، دکمهی دوم به فروشگاهِ اشتراک میبرد
|
||||
* (سوال جدا فروخته نمیشود؛ مشترک فردا دوباره سهم دارد).
|
||||
*/
|
||||
function QuotaPills({ free, credits }: { free: number; credits: number }) {
|
||||
function QuotaPills({ free }: { free: number }) {
|
||||
const nav = useNav();
|
||||
return (
|
||||
<>
|
||||
<span className={`rounded-full px-3 py-1.5 text-xs font-black ${free > 0 ? 'bg-white text-[#2E7D5B]' : 'bg-white/15 text-white/80'}`}>
|
||||
{free > 0 ? <>{toFa(free)} سوالِ امروز</> : 'سوالهای امروز تموم شد'}
|
||||
</span>
|
||||
{credits > 0 ? (
|
||||
<span className="rounded-full bg-white px-3 py-1.5 text-xs font-black text-violet">{toFa(credits)} سوالِ خریدهشده</span>
|
||||
) : free === 0 ? (
|
||||
{free === 0 && (
|
||||
<button type="button" onClick={() => nav.switchTab('subscription')} className="rounded-full bg-white/15 px-3 py-1.5 text-xs font-black text-white">
|
||||
سوالِ بیشتر با اشتراک
|
||||
</button>
|
||||
) : null}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user