Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions backend/WizardRPG.Api/Controllers/AchievementController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WizardRPG.Api.DTOs.Achievement;
using WizardRPG.Api.Services;

namespace WizardRPG.Api.Controllers;

[ApiController]
[Route("api/achievement")]
[Authorize]
public class AchievementController : ControllerBase
{
private readonly IAchievementService _achievementService;

public AchievementController(IAchievementService achievementService) => _achievementService = achievementService;

private Guid CurrentPlayerId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")
?? throw new UnauthorizedAccessException());

/// <summary>Get the current player's achievements.</summary>
[HttpGet]
public async Task<ActionResult<List<AchievementResponse>>> GetMyAchievements()
{
var achievements = await _achievementService.GetPlayerAchievementsAsync(CurrentPlayerId);
return Ok(achievements);
}

/// <summary>Check and award achievements for the current player.</summary>
[HttpPost("check")]
public async Task<IActionResult> CheckAchievements()
{
await _achievementService.CheckAndAwardAchievementsAsync(CurrentPlayerId);
return Ok(new { message = "Achievements checked." });
}
}
45 changes: 45 additions & 0 deletions backend/WizardRPG.Api/Controllers/EquipmentController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WizardRPG.Api.DTOs.Equipment;
using WizardRPG.Api.Services;

namespace WizardRPG.Api.Controllers;

[ApiController]
[Route("api/equipment")]
[Authorize]
public class EquipmentController : ControllerBase
{
private readonly IEquipmentService _equipmentService;

public EquipmentController(IEquipmentService equipmentService) => _equipmentService = equipmentService;

private Guid CurrentPlayerId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")
?? throw new UnauthorizedAccessException());

/// <summary>Get the current player's equipment.</summary>
[HttpGet]
public async Task<ActionResult<EquipmentSlots>> GetMyEquipment()
{
var equipment = await _equipmentService.GetEquipmentAsync(CurrentPlayerId);
return Ok(equipment);
}

/// <summary>Equip an item from the bank.</summary>
[HttpPost("equip")]
public async Task<ActionResult<EquipmentSlots>> EquipItem([FromBody] EquipItemRequest request)
{
var equipment = await _equipmentService.EquipItemAsync(CurrentPlayerId, request.BankItemId);
return Ok(equipment);
}

/// <summary>Unequip an item from a slot.</summary>
[HttpPost("unequip")]
public async Task<ActionResult<EquipmentSlots>> UnequipItem([FromBody] UnequipItemRequest request)
{
var equipment = await _equipmentService.UnequipItemAsync(CurrentPlayerId, request.Slot);
return Ok(equipment);
}
}
60 changes: 60 additions & 0 deletions backend/WizardRPG.Api/Controllers/HouseController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WizardRPG.Api.DTOs.House;
using WizardRPG.Api.DTOs.Player;
using WizardRPG.Api.Services;

namespace WizardRPG.Api.Controllers;

[ApiController]
[Route("api/house")]
[Authorize]
public class HouseController : ControllerBase
{
private readonly IHouseService _houseService;

public HouseController(IHouseService houseService) => _houseService = houseService;

private Guid CurrentPlayerId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")
?? throw new UnauthorizedAccessException());

/// <summary>Get the house leaderboard.</summary>
[HttpGet("leaderboard")]
[AllowAnonymous]
public async Task<ActionResult<List<HouseLeaderboardEntry>>> GetLeaderboard()
{
var leaderboard = await _houseService.GetHouseLeaderboardAsync();
return Ok(leaderboard);
}

/// <summary>Get house points for a specific house.</summary>
[HttpGet("{house}/points")]
public async Task<ActionResult<List<HousePointsResponse>>> GetHousePoints(string house, [FromQuery] int limit = 50)
{
var points = await _houseService.GetHousePointsAsync(house, limit);
return Ok(points);
}

/// <summary>Select a house for the current player.</summary>
[HttpPost("select")]
public async Task<ActionResult<PlayerProfileResponse>> SelectHouse([FromBody] SelectHouseRequest request)
{
var profile = await _houseService.SelectHouseAsync(CurrentPlayerId, request.House);
return Ok(profile);
}

/// <summary>Award house points (admin only).</summary>
[HttpPost("points")]
public async Task<ActionResult<HousePointsResponse>> AwardPoints([FromBody] AwardHousePointsRequest request)
{
// Check admin
var isAdmin = User.FindFirstValue("isAdmin");
if (isAdmin != "true")
return Forbid();

var result = await _houseService.AwardHousePointsAsync(request.PlayerId, request.Points, request.Activity);
return Ok(result);
}
}
37 changes: 37 additions & 0 deletions backend/WizardRPG.Api/Controllers/LoginRewardController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WizardRPG.Api.DTOs.LoginReward;
using WizardRPG.Api.Services;

namespace WizardRPG.Api.Controllers;

[ApiController]
[Route("api/login-reward")]
[Authorize]
public class LoginRewardController : ControllerBase
{
private readonly ILoginRewardService _loginRewardService;

public LoginRewardController(ILoginRewardService loginRewardService) => _loginRewardService = loginRewardService;

private Guid CurrentPlayerId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")
?? throw new UnauthorizedAccessException());

/// <summary>Get the current player's login reward status.</summary>
[HttpGet("status")]
public async Task<ActionResult<LoginRewardStatus>> GetStatus()
{
var status = await _loginRewardService.GetLoginRewardStatusAsync(CurrentPlayerId);
return Ok(status);
}

/// <summary>Claim the daily login reward.</summary>
[HttpPost("claim")]
public async Task<ActionResult<LoginRewardResponse>> ClaimReward()
{
var reward = await _loginRewardService.ClaimDailyRewardAsync(CurrentPlayerId);
return Ok(reward);
}
}
53 changes: 53 additions & 0 deletions backend/WizardRPG.Api/Controllers/NotificationController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WizardRPG.Api.DTOs.Notification;
using WizardRPG.Api.Services;

namespace WizardRPG.Api.Controllers;

[ApiController]
[Route("api/notification")]
[Authorize]
public class NotificationController : ControllerBase
{
private readonly INotificationService _notificationService;

public NotificationController(INotificationService notificationService) => _notificationService = notificationService;

private Guid CurrentPlayerId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")
?? throw new UnauthorizedAccessException());

/// <summary>Get the current player's notifications.</summary>
[HttpGet]
public async Task<ActionResult<List<NotificationResponse>>> GetMyNotifications([FromQuery] int limit = 20)
{
var notifications = await _notificationService.GetPlayerNotificationsAsync(CurrentPlayerId, limit);
return Ok(notifications);
}

/// <summary>Get unread notification count.</summary>
[HttpGet("unread-count")]
public async Task<ActionResult<int>> GetUnreadCount()
{
var count = await _notificationService.GetUnreadCountAsync(CurrentPlayerId);
return Ok(count);
}

/// <summary>Mark a notification as read.</summary>
[HttpPost("{id:guid}/read")]
public async Task<IActionResult> MarkAsRead(Guid id)
{
await _notificationService.MarkAsReadAsync(CurrentPlayerId, id);
return Ok(new { message = "Notification marked as read." });
}

/// <summary>Mark all notifications as read.</summary>
[HttpPost("read-all")]
public async Task<IActionResult> MarkAllAsRead()
{
await _notificationService.MarkAllAsReadAsync(CurrentPlayerId);
return Ok(new { message = "All notifications marked as read." });
}
}
8 changes: 8 additions & 0 deletions backend/WizardRPG.Api/Controllers/PlayerController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,12 @@ public async Task<ActionResult<List<PlayerProfileResponse>>> GetLeaderboard([Fro
var leaderboard = await _playerService.GetLeaderboardAsync(top);
return Ok(leaderboard);
}

/// <summary>Get battle statistics for a player.</summary>
[HttpGet("battle-stats/{playerId:guid}")]
public async Task<ActionResult<BattleStatsResponse>> GetBattleStats(Guid playerId)
{
var stats = await _playerService.GetBattleStatsAsync(playerId);
return Ok(stats);
}
}
45 changes: 45 additions & 0 deletions backend/WizardRPG.Api/Controllers/QuestController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WizardRPG.Api.DTOs.Quest;
using WizardRPG.Api.Services;

namespace WizardRPG.Api.Controllers;

[ApiController]
[Route("api/quest")]
[Authorize]
public class QuestController : ControllerBase
{
private readonly IQuestService _questService;

public QuestController(IQuestService questService) => _questService = questService;

private Guid CurrentPlayerId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")
?? throw new UnauthorizedAccessException());

/// <summary>Get the current player's quests.</summary>
[HttpGet]
public async Task<ActionResult<List<QuestResponse>>> GetMyQuests()
{
var quests = await _questService.GetPlayerQuestsAsync(CurrentPlayerId);
return Ok(quests);
}

/// <summary>Generate daily quests for the current player.</summary>
[HttpPost("generate-daily")]
public async Task<IActionResult> GenerateDaily()
{
await _questService.GenerateDailyQuestsAsync(CurrentPlayerId);
return Ok(new { message = "Daily quests generated." });
}

/// <summary>Generate weekly quests for the current player.</summary>
[HttpPost("generate-weekly")]
public async Task<IActionResult> GenerateWeekly()
{
await _questService.GenerateWeeklyQuestsAsync(CurrentPlayerId);
return Ok(new { message = "Weekly quests generated." });
}
}
3 changes: 3 additions & 0 deletions backend/WizardRPG.Api/DTOs/Achievement/AchievementDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace WizardRPG.Api.DTOs.Achievement;

public record AchievementResponse(Guid Id, string Key, string Name, string Description, DateTime UnlockedAt);
2 changes: 1 addition & 1 deletion backend/WizardRPG.Api/DTOs/Auth/AuthDtos.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace WizardRPG.Api.DTOs.Auth;

public record RegisterRequest(string Username, string Email, string Password, string? ReferralCode);
public record RegisterRequest(string Username, string Email, string Password, string? ReferralCode, string? House);
public record LoginRequest(string Email, string Password);
public record RefreshTokenRequest(string RefreshToken);

Expand Down
15 changes: 15 additions & 0 deletions backend/WizardRPG.Api/DTOs/Equipment/EquipmentDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace WizardRPG.Api.DTOs.Equipment;

using WizardRPG.Api.Models;

public record EquipmentSlots(
EquippedItemResponse? Wand,
EquippedItemResponse? Robe,
EquippedItemResponse? Hat,
EquippedItemResponse? Amulet,
EquippedItemResponse? Broom);

public record EquippedItemResponse(Guid BankItemId, Guid ItemId, string Name, string Description, ItemType Type, int MagicBonus, int StrengthBonus, int WisdomBonus, int SpeedBonus);

public record EquipItemRequest(Guid BankItemId);
public record UnequipItemRequest(string Slot);
6 changes: 6 additions & 0 deletions backend/WizardRPG.Api/DTOs/House/HouseDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace WizardRPG.Api.DTOs.House;

public record HouseLeaderboardEntry(string House, long TotalPoints, int MemberCount);
public record HousePointsResponse(Guid Id, Guid PlayerId, string PlayerUsername, string House, int Points, string Activity, DateTime EarnedAt);
public record SelectHouseRequest(string House);
public record AwardHousePointsRequest(Guid PlayerId, int Points, string Activity);
4 changes: 4 additions & 0 deletions backend/WizardRPG.Api/DTOs/LoginReward/LoginRewardDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace WizardRPG.Api.DTOs.LoginReward;

public record LoginRewardResponse(int Day, long GoldReward, string? ItemReward, int LoginStreak);
public record LoginRewardStatus(int LoginStreak, bool CanClaimToday, DateTime? LastClaimDate);
3 changes: 3 additions & 0 deletions backend/WizardRPG.Api/DTOs/Notification/NotificationDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace WizardRPG.Api.DTOs.Notification;

public record NotificationResponse(Guid Id, string Title, string Message, string Type, bool IsRead, DateTime CreatedAt);
6 changes: 6 additions & 0 deletions backend/WizardRPG.Api/DTOs/Player/BattleStatsDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace WizardRPG.Api.DTOs.Player;

public record BattleStatsResponse(
int TotalBattles, int Wins, int Losses, double WinRate,
long TotalDamageDealt, long TotalDamageReceived,
string? MostUsedSpell, int CurrentWinStreak, int BestWinStreak);
8 changes: 7 additions & 1 deletion backend/WizardRPG.Api/DTOs/Player/PlayerDtos.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ public record PlayerProfileResponse(
int Speed,
string ReferralCode,
DateTime CreatedAt,
bool IsAdmin);
bool IsAdmin,
int EloRating,
string House,
string RankTier,
string RankBadge,
bool HasCompletedOnboarding,
int LoginStreak);

public record UpdateProfileRequest(string? Username, string? Email);

Expand Down
5 changes: 5 additions & 0 deletions backend/WizardRPG.Api/DTOs/Quest/QuestDtos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace WizardRPG.Api.DTOs.Quest;

using WizardRPG.Api.Models;

public record QuestResponse(Guid Id, string Title, string Description, QuestType Type, QuestStatus Status, int TargetCount, int CurrentCount, long GoldReward, int XpReward, DateTime ExpiresAt);
Loading