Add flashcards feature with spaced repetition scheduling
Adds a full flashcards system: FSRS-based scheduling, cloze/basic card types, CSV import/export, media storage, and study UI, wired into navigation and the dashboard alongside existing question flows.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using QuestionsApi.Models;
|
||||
|
||||
namespace QuestionsApi.Services.Flashcards;
|
||||
|
||||
public sealed class FlashcardMediaStore
|
||||
{
|
||||
private readonly IMongoCollection<FlashcardMediaAsset> _assets;
|
||||
|
||||
public FlashcardMediaStore(MongoDatabaseProvider mongo)
|
||||
{
|
||||
_assets = mongo.Database.GetCollection<FlashcardMediaAsset>("FlashcardMediaAssets");
|
||||
_assets.Indexes.CreateOne(new CreateIndexModel<FlashcardMediaAsset>(
|
||||
Builders<FlashcardMediaAsset>.IndexKeys.Ascending(v => v.UserId),
|
||||
new CreateIndexOptions { Name = "flashcard_media_user" }));
|
||||
}
|
||||
|
||||
public async Task<FlashcardMediaAsset> CreateAsync(string userId, string fileName, string contentType, byte[] bytes)
|
||||
{
|
||||
var asset = new FlashcardMediaAsset
|
||||
{
|
||||
UserId = userId,
|
||||
FileName = fileName,
|
||||
ContentType = contentType,
|
||||
Bytes = bytes,
|
||||
CreatedUtc = DateTime.UtcNow
|
||||
};
|
||||
await _assets.InsertOneAsync(asset);
|
||||
return asset;
|
||||
}
|
||||
|
||||
public async Task<FlashcardMediaAsset?> GetAsync(string userId, string id)
|
||||
{
|
||||
if (!ObjectId.TryParse(id, out _)) return null;
|
||||
return await _assets.Find(v => v.UserId == userId && v.Id == id).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public Task<long> DeleteAsync(string userId, string id) =>
|
||||
_assets.DeleteOneAsync(v => v.UserId == userId && v.Id == id).ContinueWith(t => t.Result.DeletedCount);
|
||||
}
|
||||
Reference in New Issue
Block a user