profileShare

rasmusjy / splitapp-backend-microservices

Read-only snapshot

No repository description.

main default branch 501 files Expires Sep 13, 2026, 9:06 AM
Index.cshtml 6,536 bytes
1 @model List<SplitApp.WebApp.Application.DTO.TripParticipantBllDto>
2
3 @{
4 ViewData["Title"] = Localizer["Members"];
5 var tripId = (Guid)ViewData["TripId"]!;
6 var tripName = (string)ViewData["TripName"]!;
7 var currentUserId = (Guid)ViewData["CurrentUserId"]!;
8 var isOrganizer = (bool)ViewData["IsOrganizer"]!;
9 var pendingInvitations = ViewData["PendingInvitations"] as List<SplitApp.WebApp.Application.DTO.TripInvitationBllDto> ?? new();
10 }
11
12 <!-- Page Header -->
13 <div class="sa-gradient-header" style="background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);">
14 <div class="d-flex justify-content-between align-items-center flex-wrap gap-3">
15 <div>
16 <h1 style="margin-bottom: 4px;">@Localizer["Members"]</h1>
17 <p class="text-muted mb-0">@tripName &middot; @Model.Count @Localizer["member(s)"]</p>
18 </div>
19 <div class="d-flex gap-2">
20 @if (isOrganizer)
21 {
22 <a asp-action="Invite" asp-route-tripId="@tripId" class="sa-btn sa-btn-sm" style="background: rgba(255,255,255,0.2); color: #fff; border: 1.5px solid rgba(255,255,255,0.4);">
23 <i class="bi bi-person-plus-fill"></i> @Localizer["Invite"]
24 </a>
25 }
26 <a asp-controller="Trips" asp-action="Details" asp-route-id="@tripId" class="sa-btn sa-btn-sm" style="background: rgba(255,255,255,0.1); color: rgba(255,255,255,0.9);">
27 <i class="bi bi-arrow-left"></i>
28 </a>
29 </div>
30 </div>
31 </div>
32
33 <!-- Members List -->
34 <div class="sa-card-static mb-4">
35 <div class="sa-card-header">
36 <i class="bi bi-people-fill me-2"></i>@Localizer["Current Members"]
37 </div>
38 <div>
39 @{ var pIdx = 0; }
40 @foreach (var participant in Model)
41 {
42 var name = participant.User != null ? $"{participant.User.FirstName} {participant.User.LastName}" : Localizer["Unknown"].Value;
43 var initial = participant.User != null ? $"{participant.User.FirstName?[0]}{participant.User.LastName?[0]}" : "?";
44 var email = participant.User?.Email ?? "-";
45
46 <div class="d-flex align-items-center gap-3 px-4 py-3" style="border-bottom: 1px solid var(--sa-gray-100);">
47 <span class="sa-avatar sa-avatar-@((pIdx % 8) + 1)" style="border: none;">@initial</span>
48 <div style="flex: 1; min-width: 0;">
49 <div style="font-weight: 600;">
50 @name
51 @if (!string.IsNullOrEmpty(participant.Nickname))
52 {
53 <small class="sa-text-muted">(@participant.Nickname)</small>
54 }
55 </div>
56 <div style="font-size: 0.85rem; color: var(--sa-gray-500);">@email</div>
57 </div>
58 <div class="d-flex align-items-center gap-2">
59 @if (participant.Role == EParticipantRole.Organizer)
60 {
61 <span class="sa-badge sa-badge-accent">
62 <i class="bi bi-star-fill" style="font-size: 0.6rem;"></i> @Localizer["Organizer"]
63 </span>
64 }
65 else
66 {
67 <span class="sa-badge sa-badge-neutral">@Localizer["Participant"]</span>
68 }
69 <span class="sa-text-muted sa-hide-mobile" style="font-size: 0.8rem;">
70 @participant.JoinedAt.ToString("MMM dd, yyyy")
71 </span>
72 @if (isOrganizer && participant.UserId != currentUserId && participant.Role != EParticipantRole.Organizer)
73 {
74 <form asp-action="Remove" method="post" style="display:inline"
75 onsubmit="return confirm('@Localizer["Are you sure you want to remove this member?"]');">
76 <input type="hidden" name="tripId" value="@tripId" />
77 <input type="hidden" name="participantId" value="@participant.Id" />
78 <button type="submit" class="sa-btn sa-btn-ghost sa-btn-icon sa-btn-sm" title="@Localizer["Remove"]" style="color: var(--sa-danger);">
79 <i class="bi bi-x-lg"></i>
80 </button>
81 </form>
82 }
83 </div>
84 </div>
85 pIdx++;
86 }
87 </div>
88 </div>
89
90 <!-- Pending Invitations -->
91 @if (isOrganizer && pendingInvitations.Any())
92 {
93 <div class="sa-card-static">
94 <div class="sa-card-header">
95 <i class="bi bi-hourglass-split me-2"></i>@Localizer["Pending Invitations"]
96 </div>
97 <div>
98 @foreach (var inv in pendingInvitations)
99 {
100 <div class="d-flex align-items-center gap-3 px-4 py-3" style="border-bottom: 1px solid var(--sa-gray-100);">
101 <div class="sa-expense-icon" style="background: var(--sa-info-light); color: var(--sa-info);">
102 <i class="bi bi-envelope-paper"></i>
103 </div>
104 <div style="flex: 1;">
105 <div style="font-weight: 500; font-size: 0.9rem;">
106 @Localizer["Invited by"] @(inv.InvitedByUser != null ? $"{inv.InvitedByUser.FirstName} {inv.InvitedByUser.LastName}" : "?")
107 </div>
108 <div style="font-size: 0.8rem; color: var(--sa-gray-500);">
109 @Localizer["Expires"] @inv.ExpiresAt.ToString("MMM dd, yyyy HH:mm")
110 </div>
111 </div>
112 <span class="sa-badge sa-badge-info">@SplitApp.WebApp.Hosting.Helpers.EnumHelper.GetDisplayName(inv.Status)</span>
113 <form asp-action="RevokeInvitation" method="post" style="display:inline;">
114 <input type="hidden" name="id" value="@inv.Id" />
115 <input type="hidden" name="tripId" value="@tripId" />
116 <button type="submit" class="sa-btn sa-btn-ghost sa-btn-icon sa-btn-sm" title="@Localizer["Revoke"]" style="color: var(--sa-danger);"
117 onclick="return confirm('@Localizer["AreYouSure"]');">
118 <i class="bi bi-x-circle"></i>
119 </button>
120 </form>
121 </div>
122 }
123 </div>
124 </div>
125 }
126