Some checks are pending
CI / validate (push) Waiting to run
Study-View:
- Graceful Backlog Recovery: Banner bei >30 fälligen Karten, Recovery-Queue
sortiert nach Stability aufsteigend (25er-Batch, ?recovery=true)
- Undo letzte Bewertung: 5s-Toast mit RAF-Fortschrittsbalken, Ctrl/Cmd+Z,
prevSnapshot-Spalte in reviews (Migration 0001, Prod deployed)
- FSRS-Tooltip nach Reveal: State / Stability / Difficulty als Popover
Deck-Edit:
- Neuer Abschnitt „Lern-Algorithmus" mit request_retention-Slider (50–99 %)
Header:
- Streak-Pill (🔥 N) + fällige-Karten-Pill via GET /api/v1/me/summary
Stats-Page:
- Difficulty-Distribution (5 Buckets, Farb-Bars)
- Deck-Fortschritt (Mastery % = stability>21, max 6 Decks)
API:
- GET /me/summary: streak_days + due_now (leichtgewichtiger Header-Endpoint)
- GET /reviews/due: ?recovery=true → stability-sort, Limit 25
- POST /reviews/:cardId/:subIndex/undo: prevSnapshot-Restore, 409 wenn leer
- /me/stats: difficulty_distribution + deck_mastery
Landing:
- 5 Blog-Artikel (Quizlet-Paywall, FSRS, Datenschutz, Anki, Lernkarten-Tipps)
- BlogTeaser-Komponente auf Startseite, Footer-Spalte „Artikel"
i18n: 11 neue Schlüssel in DE/EN/FR/IT/ES
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
28 lines
980 B
TypeScript
28 lines
980 B
TypeScript
import type { Card, Rating, Review } from '@cards/domain';
|
|
import { api } from './client.ts';
|
|
|
|
export type DueReview = Review & {
|
|
card?: Pick<Card, 'id' | 'deck_id' | 'type' | 'fields'>;
|
|
};
|
|
|
|
export function listDueReviews(opts: { deckId?: string; limit?: number; recovery?: boolean } = {}) {
|
|
const params = new URLSearchParams();
|
|
if (opts.deckId) params.set('deck_id', opts.deckId);
|
|
if (opts.limit) params.set('limit', String(opts.limit));
|
|
if (opts.recovery) params.set('recovery', 'true');
|
|
const qs = params.toString();
|
|
return api<{ reviews: DueReview[]; total: number }>(
|
|
`/api/v1/reviews/due${qs ? `?${qs}` : ''}`
|
|
);
|
|
}
|
|
|
|
export function gradeReview(cardId: string, subIndex: number, rating: Rating) {
|
|
return api<Review>(`/api/v1/reviews/${cardId}/${subIndex}/grade`, {
|
|
method: 'POST',
|
|
body: { rating },
|
|
});
|
|
}
|
|
|
|
export function undoReview(cardId: string, subIndex: number) {
|
|
return api<Review>(`/api/v1/reviews/${cardId}/${subIndex}/undo`, { method: 'POST' });
|
|
}
|