profileShare

rasmusjy / splitapp-backend-modular-monolith

Read-only snapshot

No repository description.

main default branch 418 files Expires Sep 13, 2026, 9:06 AM
Index.cshtml 7,918 bytes
1 @model List<SplitApp.WebApp.Controllers.WishlistItemViewModel>
2
3 @{
4 ViewData["Title"] = Localizer["Wishlist"];
5 var tripId = (Guid)ViewData["TripId"]!;
6 var tripName = (string)ViewData["TripName"]!;
7 var currentUserId = (Guid)ViewData["CurrentUserId"]!;
8 }
9
10 <!-- Page Header -->
11 <div class="sa-gradient-header" style="background: linear-gradient(135deg, var(--sa-accent) 0%, #f97316 100%);">
12 <div class="d-flex justify-content-between align-items-center flex-wrap gap-3">
13 <div>
14 <h1 style="margin-bottom: 4px;">@Localizer["Wishlist"]</h1>
15 <p class="text-muted mb-0">@tripName</p>
16 </div>
17 <div class="d-flex gap-2">
18 <a asp-action="Create" 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);">
19 <i class="bi bi-plus-lg"></i> @Localizer["Add Item"]
20 </a>
21 <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);">
22 <i class="bi bi-arrow-left"></i>
23 </a>
24 </div>
25 </div>
26 </div>
27
28 @if (!Model.Any())
29 {
30 <div class="sa-empty">
31 <div class="sa-empty-icon"><i class="bi bi-star"></i></div>
32 <div class="sa-empty-title">@Localizer["No wishlist items yet"]</div>
33 <p class="sa-empty-text">@Localizer["Add places, activities, or restaurants you want to visit."]</p>
34 <a asp-action="Create" asp-route-tripId="@tripId" class="sa-btn sa-btn-accent sa-btn-pill">
35 <i class="bi bi-plus-lg"></i> @Localizer["Add Item"]
36 </a>
37 </div>
38 }
39 else
40 {
41 <div class="row g-3">
42 @{ var idx = 0; }
43 @foreach (var item in Model.OrderByDescending(i => i.VoteCount).ThenBy(i => i.IsCompleted))
44 {
45 var categoryColor = item.Category switch
46 {
47 EWishlistCategory.Place => "var(--sa-info)",
48 EWishlistCategory.Activity => "var(--sa-success)",
49 EWishlistCategory.Restaurant => "var(--sa-accent)",
50 _ => "var(--sa-gray-400)"
51 };
52 var categoryBadge = item.Category switch
53 {
54 EWishlistCategory.Place => "sa-badge-info",
55 EWishlistCategory.Activity => "sa-badge-success",
56 EWishlistCategory.Restaurant => "sa-badge-accent",
57 _ => "sa-badge-neutral"
58 };
59 var priorityBadge = item.Priority switch
60 {
61 EWishlistPriority.MustDo => "sa-badge-danger",
62 EWishlistPriority.NiceToHave => "sa-badge-info",
63 _ => "sa-badge-neutral"
64 };
65
66 <div class="col-md-6 col-lg-4 sa-animate-slide-up sa-stagger-@(Math.Min(idx + 1, 6))">
67 <div class="sa-card h-100 @(item.IsCompleted ? "" : "")" style="@(item.IsCompleted ? "opacity: 0.7;" : "")">
68 <div style="height: 4px; background: @categoryColor;"></div>
69 <div class="sa-card-body">
70 <div class="d-flex justify-content-between align-items-start mb-2">
71 <h5 style="font-weight: 700; font-size: 1rem; margin: 0; @(item.IsCompleted ? "text-decoration: line-through; color: var(--sa-gray-400);" : "")">
72 @if (item.IsCompleted) { <i class="bi bi-check-circle-fill me-1" style="color: var(--sa-success);"></i> }
73 @item.Title
74 </h5>
75 <span class="sa-badge @categoryBadge" style="flex-shrink: 0;">@SplitApp.WebApp.Hosting.Helpers.EnumHelper.GetDisplayName(item.Category)</span>
76 </div>
77
78 @if (!string.IsNullOrEmpty(item.Description))
79 {
80 <p style="font-size: 0.875rem; color: var(--sa-gray-600); margin-bottom: var(--sa-space-3); line-height: 1.5;">
81 @item.Description
82 </p>
83 }
84
85 <div class="d-flex flex-wrap gap-2 mb-3">
86 <span class="sa-badge @priorityBadge">@SplitApp.WebApp.Hosting.Helpers.EnumHelper.GetDisplayName(item.Priority)</span>
87 @if (item.EstimatedCost.HasValue)
88 {
89 <span class="sa-badge sa-badge-neutral">~@item.EstimatedCost.Value.ToString("N2")</span>
90 }
91 </div>
92
93 @if (!string.IsNullOrEmpty(item.Location))
94 {
95 <div style="font-size: 0.85rem; color: var(--sa-gray-500); margin-bottom: 4px;">
96 <i class="bi bi-geo-alt-fill me-1" style="color: var(--sa-primary);"></i> @item.Location
97 </div>
98 }
99
100 @if (!string.IsNullOrEmpty(item.Url))
101 {
102 <div style="font-size: 0.85rem; margin-bottom: 4px;">
103 <a href="@item.Url" target="_blank" rel="noopener" style="color: var(--sa-secondary);">
104 <i class="bi bi-link-45deg me-1"></i>@Localizer["View Link"]
105 </a>
106 </div>
107 }
108
109 <div style="font-size: 0.8rem; color: var(--sa-gray-400); margin-top: var(--sa-space-2);">
110 @Localizer["Added by"] @item.AddedByName
111 </div>
112 </div>
113 <div class="sa-card-footer d-flex justify-content-between align-items-center">
114 <form asp-action="Vote" asp-route-id="@item.Id" method="post" style="display:inline">
115 <button type="submit" class="sa-vote-btn @(item.UserHasVoted ? "sa-vote-btn-active" : "")">
116 <i class="bi @(item.UserHasVoted ? "bi-heart-fill" : "bi-heart")"></i>
117 @item.VoteCount
118 </button>
119 </form>
120 <div class="d-flex align-items-center gap-2">
121 <form asp-action="Complete" asp-route-id="@item.Id" method="post" style="display:inline">
122 <button type="submit" class="sa-btn sa-btn-sm sa-btn-pill @(item.IsCompleted ? "sa-btn-success" : "sa-btn-ghost")">
123 <i class="bi @(item.IsCompleted ? "bi-check-circle-fill" : "bi-circle")"></i>
124 @(item.IsCompleted ? Localizer["Done"] : Localizer["Mark Done"])
125 </button>
126 </form>
127 @if (item.AddedByUserId == currentUserId)
128 {
129 <a asp-action="Edit" asp-route-id="@item.Id" class="sa-btn sa-btn-ghost sa-btn-icon sa-btn-sm" title="@Localizer["Edit"]">
130 <i class="bi bi-pencil"></i>
131 </a>
132 <a asp-action="Delete" asp-route-id="@item.Id" class="sa-btn sa-btn-ghost sa-btn-icon sa-btn-sm" title="@Localizer["Delete"]" style="color: var(--sa-danger);">
133 <i class="bi bi-trash3"></i>
134 </a>
135 }
136 </div>
137 </div>
138 </div>
139 </div>
140 idx++;
141 }
142 </div>
143 }
144
145 <a asp-action="Create" asp-route-tripId="@tripId" class="sa-fab sa-hide-desktop" title="@Localizer["Add Item"]">
146 <i class="bi bi-plus-lg"></i>
147 </a>
148