a391c51761
For non-managers /listsessions now shows player-friendly actions: - ✅ Записаться <date> when not registered - ✖️ Выйти <date> when already active - ✖️ Выйти из ожидания <date> when waitlisted Extend SessionListItemDto and the shared SQL query with IsUserActive and IsUserWaitlisted flags so the renderer can choose the right button. Update tests to cover all three player states.
88 lines
3.8 KiB
C#
88 lines
3.8 KiB
C#
using Dapper;
|
|
using GmRelay.Shared.Domain;
|
|
using GmRelay.Shared.Platform;
|
|
using Npgsql;
|
|
|
|
namespace GmRelay.Shared.Features.Sessions.ListSessions;
|
|
|
|
public sealed record SessionListItemDto(
|
|
Guid Id,
|
|
string Title,
|
|
DateTime ScheduledAt,
|
|
string Status,
|
|
int? MaxPlayers,
|
|
int PlayerCount,
|
|
int WaitlistCount,
|
|
bool CanManage,
|
|
bool IsUserActive,
|
|
bool IsUserWaitlisted);
|
|
|
|
public sealed record SessionListResult(
|
|
IReadOnlyList<SessionListItemDto> Sessions,
|
|
bool CanManage);
|
|
|
|
public sealed class ListSessionsHandler(
|
|
NpgsqlDataSource dataSource)
|
|
{
|
|
public async Task<SessionListResult> HandleAsync(ListSessionsCommand command, CancellationToken cancellationToken)
|
|
{
|
|
await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);
|
|
|
|
var sessions = await connection.QueryAsync<SessionListItemDto>(
|
|
@"SELECT s.id as Id, s.title as Title, s.scheduled_at as ScheduledAt, s.status as Status, s.max_players as MaxPlayers,
|
|
COUNT(sp.id) FILTER (WHERE sp.is_gm = false AND sp.registration_status = @Active) as PlayerCount,
|
|
COUNT(sp.id) FILTER (WHERE sp.is_gm = false AND sp.registration_status = @Waitlisted) as WaitlistCount,
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM group_managers gm
|
|
JOIN players manager_player ON manager_player.id = gm.player_id
|
|
WHERE gm.group_id = s.group_id
|
|
AND manager_player.platform = @Platform
|
|
AND manager_player.external_user_id = @ExternalUserId
|
|
) AS CanManage,
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM session_participants user_sp
|
|
JOIN players user_p ON user_p.id = user_sp.player_id
|
|
WHERE user_sp.session_id = s.id
|
|
AND user_sp.is_gm = false
|
|
AND user_sp.registration_status = @Active
|
|
AND user_p.platform = @Platform
|
|
AND user_p.external_user_id = @ExternalUserId
|
|
) AS IsUserActive,
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM session_participants user_sp
|
|
JOIN players user_p ON user_p.id = user_sp.player_id
|
|
WHERE user_sp.session_id = s.id
|
|
AND user_sp.is_gm = false
|
|
AND user_sp.registration_status = @Waitlisted
|
|
AND user_p.platform = @Platform
|
|
AND user_p.external_user_id = @ExternalUserId
|
|
) AS IsUserWaitlisted
|
|
FROM sessions s
|
|
JOIN game_groups g ON s.group_id = g.id
|
|
LEFT JOIN session_participants sp ON s.id = sp.session_id
|
|
WHERE g.platform = @Platform
|
|
AND g.external_group_id = @ExternalGroupId
|
|
AND s.status != @Cancelled
|
|
AND s.scheduled_at > NOW()
|
|
GROUP BY s.id, s.title, s.scheduled_at, s.status, s.max_players, s.group_id
|
|
ORDER BY s.scheduled_at ASC",
|
|
new
|
|
{
|
|
Platform = command.Group.Platform.ToString(),
|
|
ExternalGroupId = command.Group.ExternalGroupId,
|
|
ExternalUserId = command.User.ExternalUserId,
|
|
Cancelled = SessionStatus.Cancelled,
|
|
Active = ParticipantRegistrationStatus.Active,
|
|
Waitlisted = ParticipantRegistrationStatus.Waitlisted
|
|
});
|
|
|
|
var sessionsList = sessions.ToList();
|
|
var canManage = sessionsList.Count > 0 && sessionsList.First().CanManage;
|
|
|
|
return new SessionListResult(sessionsList, canManage);
|
|
}
|
|
}
|