Fix ordering giveaways, the stuck false label, add Regenerate deck
Ordering cards - Generation prompt now forbids dates, years, times, step numbers and ordinals in ordering items (spec + hard rules), and the server-side validation drops any ordering card whose items still contain them instead of shipping a giveaway. True/False - The 'false ✕' swipe label was permanently visible on the card: its opacity curve was inverted, so the clamp at rest was 1. Flipped the range (and tightened both ranges for the elastic drag) — each label now only fades in while swiping in that direction. Regenerate deck - Results screen gains a Regenerate deck button: rebuilds the activities from the deck's stored source notes, replaces the deck in storage (attempts/best score reset) and starts the fresh run from slide 1. - StudyFeed tracks the current deck so the header, export and messages use the regenerated title/activities. - Fixed a spurious 0% attempt recorded when a regenerated deck swapped in: scroll anchoring held the old results position, so the feed briefly reported 5/5 with zero answers. The scroll now resets before the new slides render, overflow-anchor is disabled on the feed, and a run with no answers is never recorded. Tests: new deck-fixes suite 15/15 (TF overlay at rest/drag, regenerate with loading state + storage reset, ordering guard drop/keep); retry 14/14, deck chrome 15/15, pwa 16/16, final-ux 12/12, security 8/8, contrast 20/20.
This commit is contained in:
parent
1bacf43ed2
commit
33967f9454
6 changed files with 122 additions and 16 deletions
|
|
@ -19,8 +19,13 @@ type TrueFalseActivity = Extract<Activity, { type: "true_false" }>;
|
|||
export function TrueFalse({ activity, onAnswered, onNext, isLast }: ActivityComponentProps<TrueFalseActivity>) {
|
||||
const [result, setResult] = useState<boolean | null>(null);
|
||||
const x = useMotionValue(0);
|
||||
const trueOpacity = useTransform(x, [30, 110], [0, 1]);
|
||||
const falseOpacity = useTransform(x, [-30, -110], [1, 0]);
|
||||
// The drag is elastic, so the card moves less than the pointer — these
|
||||
// ranges make each label reach full strength on a normal swipe.
|
||||
const trueOpacity = useTransform(x, [20, 70], [0, 1]);
|
||||
// Left drags go negative: at rest (0) this must be invisible, only fading
|
||||
// in as the card is dragged left. The old range was inverted, so the
|
||||
// "false ✕" label sat on the card permanently.
|
||||
const falseOpacity = useTransform(x, [-70, -20], [1, 0]);
|
||||
|
||||
const answer = (value: boolean) => {
|
||||
if (result !== null) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue