241 lines
7.9 KiB
C#
241 lines
7.9 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using DramaLing.Api.Models.Entities;
|
|
using DramaLing.Api.Repositories;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
namespace DramaLing.Api.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/flashcards")]
|
|
[AllowAnonymous]
|
|
public class FlashcardsController : ControllerBase
|
|
{
|
|
private readonly IFlashcardRepository _flashcardRepository;
|
|
private readonly ILogger<FlashcardsController> _logger;
|
|
|
|
public FlashcardsController(
|
|
IFlashcardRepository flashcardRepository,
|
|
ILogger<FlashcardsController> logger)
|
|
{
|
|
_flashcardRepository = flashcardRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
private Guid GetUserId()
|
|
{
|
|
// 暫時使用固定測試用戶 ID
|
|
return Guid.Parse("00000000-0000-0000-0000-000000000001");
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task<ActionResult> GetFlashcards(
|
|
[FromQuery] string? search = null,
|
|
[FromQuery] bool favoritesOnly = false)
|
|
{
|
|
try
|
|
{
|
|
var userId = GetUserId();
|
|
var flashcards = await _flashcardRepository.GetByUserIdAsync(userId, search, favoritesOnly);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = new
|
|
{
|
|
Flashcards = flashcards.Select(f => new
|
|
{
|
|
f.Id,
|
|
f.Word,
|
|
f.Translation,
|
|
f.Definition,
|
|
f.PartOfSpeech,
|
|
f.Pronunciation,
|
|
f.Example,
|
|
f.ExampleTranslation,
|
|
f.IsFavorite,
|
|
f.DifficultyLevel,
|
|
f.CreatedAt,
|
|
f.UpdatedAt
|
|
}),
|
|
Count = flashcards.Count()
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting flashcards");
|
|
return StatusCode(500, new { Success = false, Error = "Failed to load flashcards" });
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
public async Task<ActionResult> CreateFlashcard([FromBody] CreateFlashcardRequest request)
|
|
{
|
|
try
|
|
{
|
|
var userId = GetUserId();
|
|
|
|
var flashcard = new Flashcard
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UserId = userId,
|
|
Word = request.Word,
|
|
Translation = request.Translation,
|
|
Definition = request.Definition ?? "",
|
|
PartOfSpeech = request.PartOfSpeech,
|
|
Pronunciation = request.Pronunciation,
|
|
Example = request.Example,
|
|
ExampleTranslation = request.ExampleTranslation,
|
|
DifficultyLevel = "A2", // 預設等級
|
|
CreatedAt = DateTime.UtcNow,
|
|
UpdatedAt = DateTime.UtcNow
|
|
};
|
|
|
|
await _flashcardRepository.AddAsync(flashcard);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = flashcard,
|
|
Message = "詞卡創建成功"
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error creating flashcard");
|
|
return StatusCode(500, new { Success = false, Error = "Failed to create flashcard" });
|
|
}
|
|
}
|
|
|
|
[HttpGet("{id}")]
|
|
public async Task<ActionResult> GetFlashcard(Guid id)
|
|
{
|
|
try
|
|
{
|
|
var userId = GetUserId();
|
|
|
|
var flashcard = await _flashcardRepository.GetByUserIdAndFlashcardIdAsync(userId, id);
|
|
|
|
if (flashcard == null)
|
|
{
|
|
return NotFound(new { Success = false, Error = "Flashcard not found" });
|
|
}
|
|
|
|
return Ok(new { Success = true, Data = flashcard });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting flashcard {FlashcardId}", id);
|
|
return StatusCode(500, new { Success = false, Error = "Failed to get flashcard" });
|
|
}
|
|
}
|
|
|
|
[HttpPut("{id}")]
|
|
public async Task<ActionResult> UpdateFlashcard(Guid id, [FromBody] CreateFlashcardRequest request)
|
|
{
|
|
try
|
|
{
|
|
var userId = GetUserId();
|
|
|
|
var flashcard = await _flashcardRepository.GetByUserIdAndFlashcardIdAsync(userId, id);
|
|
|
|
if (flashcard == null)
|
|
{
|
|
return NotFound(new { Success = false, Error = "Flashcard not found" });
|
|
}
|
|
|
|
// 更新詞卡資訊
|
|
flashcard.Word = request.Word;
|
|
flashcard.Translation = request.Translation;
|
|
flashcard.Definition = request.Definition ?? "";
|
|
flashcard.PartOfSpeech = request.PartOfSpeech;
|
|
flashcard.Pronunciation = request.Pronunciation;
|
|
flashcard.Example = request.Example;
|
|
flashcard.ExampleTranslation = request.ExampleTranslation;
|
|
flashcard.UpdatedAt = DateTime.UtcNow;
|
|
|
|
await _flashcardRepository.UpdateAsync(flashcard);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = flashcard,
|
|
Message = "詞卡更新成功"
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error updating flashcard {FlashcardId}", id);
|
|
return StatusCode(500, new { Success = false, Error = "Failed to update flashcard" });
|
|
}
|
|
}
|
|
|
|
[HttpDelete("{id}")]
|
|
public async Task<ActionResult> DeleteFlashcard(Guid id)
|
|
{
|
|
try
|
|
{
|
|
var userId = GetUserId();
|
|
|
|
var flashcard = await _flashcardRepository.GetByUserIdAndFlashcardIdAsync(userId, id);
|
|
|
|
if (flashcard == null)
|
|
{
|
|
return NotFound(new { Success = false, Error = "Flashcard not found" });
|
|
}
|
|
|
|
await _flashcardRepository.DeleteAsync(flashcard);
|
|
|
|
return Ok(new { Success = true, Message = "詞卡已刪除" });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error deleting flashcard {FlashcardId}", id);
|
|
return StatusCode(500, new { Success = false, Error = "Failed to delete flashcard" });
|
|
}
|
|
}
|
|
|
|
[HttpPost("{id}/favorite")]
|
|
public async Task<ActionResult> ToggleFavorite(Guid id)
|
|
{
|
|
try
|
|
{
|
|
var userId = GetUserId();
|
|
|
|
var flashcard = await _flashcardRepository.GetByUserIdAndFlashcardIdAsync(userId, id);
|
|
|
|
if (flashcard == null)
|
|
{
|
|
return NotFound(new { Success = false, Error = "Flashcard not found" });
|
|
}
|
|
|
|
flashcard.IsFavorite = !flashcard.IsFavorite;
|
|
flashcard.UpdatedAt = DateTime.UtcNow;
|
|
|
|
await _flashcardRepository.UpdateAsync(flashcard);
|
|
|
|
return Ok(new {
|
|
Success = true,
|
|
IsFavorite = flashcard.IsFavorite,
|
|
Message = flashcard.IsFavorite ? "已加入收藏" : "已取消收藏"
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error toggling favorite for flashcard {FlashcardId}", id);
|
|
return StatusCode(500, new { Success = false, Error = "Failed to toggle favorite" });
|
|
}
|
|
}
|
|
}
|
|
|
|
// DTO 類別
|
|
public class CreateFlashcardRequest
|
|
{
|
|
public string Word { get; set; } = string.Empty;
|
|
public string Translation { get; set; } = string.Empty;
|
|
public string Definition { get; set; } = string.Empty;
|
|
public string PartOfSpeech { get; set; } = string.Empty;
|
|
public string Pronunciation { get; set; } = string.Empty;
|
|
public string Example { get; set; } = string.Empty;
|
|
public string? ExampleTranslation { get; set; }
|
|
} |