diff --git a/src/GmRelay.Web/Components/Pages/PublicClub.razor b/src/GmRelay.Web/Components/Pages/PublicClub.razor index 7283a24..0e31dde 100644 --- a/src/GmRelay.Web/Components/Pages/PublicClub.razor +++ b/src/GmRelay.Web/Components/Pages/PublicClub.razor @@ -167,12 +167,6 @@ else if (club is not null) if (club is null) return; - if (string.IsNullOrWhiteSpace(applicationMessage)) - { - applicationError = "Введите сообщение или оставьте поле пустым."; - return; - } - try { isSubmittingApplication = true; diff --git a/src/GmRelay.Web/Services/SessionService.cs b/src/GmRelay.Web/Services/SessionService.cs index caf35dc..79e5f29 100644 --- a/src/GmRelay.Web/Services/SessionService.cs +++ b/src/GmRelay.Web/Services/SessionService.cs @@ -2707,6 +2707,7 @@ public sealed class SessionService( public async Task LeaveClubMembershipAsync(Guid membershipId, Guid playerId) { await using var conn = await dataSource.OpenConnectionAsync(); + // Active membership: withdraw by setting status = 'Left'. var rows = await conn.ExecuteAsync( """ UPDATE club_memberships @@ -2714,9 +2715,22 @@ public sealed class SessionService( WHERE id = @MembershipId AND player_id = @PlayerId AND status = 'Active' """, new { MembershipId = membershipId, PlayerId = playerId }); - if (rows == 0) + if (rows > 0) { - throw new InvalidOperationException($"Active membership {membershipId} not found for player."); + return; + } + + // Pending application: cancel by setting status = 'Rejected' so the user can re-apply later. + var cancelled = await conn.ExecuteAsync( + """ + UPDATE club_memberships + SET status = 'Rejected', decided_at = now() + WHERE id = @MembershipId AND player_id = @PlayerId AND status = 'Pending' + """, + new { MembershipId = membershipId, PlayerId = playerId }); + if (cancelled == 0) + { + throw new InvalidOperationException($"Membership {membershipId} is not Active or Pending for this player."); } }