Ignore:
Timestamp:
09/01/26 06:11:34 (4 weeks ago)
Author:
mmilevski <markomilevski3@…>
Branches:
main
Children:
d2eccb3
Parents:
08aefc6
Message:

Added major improvements.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • KernelRecordsMVC.Web/Views/Release/Index.cshtml

    r08aefc6 rfa0fbaf  
    11@model IEnumerable<KernelRecordsMVC.Models.Release>
    22
    3 <div class="d-flex justify-content-between align-items-center mb-4">
    4 
    5     <div>
    6         <h1>Music Store</h1>
    7         <p class="text-muted">
    8             Browse CDs, vinyl records and cassettes.
    9         </p>
     3@{
     4    ViewData["Title"] = "Browse Releases";
     5}
     6
     7<div class="releases-page">
     8
     9    <!-- =====================================================
     10         HEADER
     11         ===================================================== -->
     12
     13    <div class="releases-header">
     14
     15        <div>
     16            <span class="page-eyebrow">KERNEL RECORDS</span>
     17
     18            <h1>Browse Releases</h1>
     19
     20            <p>
     21                Explore vinyl, CDs and cassettes from our collection.
     22            </p>
     23        </div>
     24
     25        <div class="release-count">
     26            @Model.Count() releases
     27        </div>
     28
    1029    </div>
    1130
     31
     32    <!-- =====================================================
     33         FILTERS
     34         ===================================================== -->
     35
     36    <form asp-action="Index"
     37          method="get"
     38          class="release-filters">
     39
     40        <div class="filter-search">
     41
     42            <label>Search</label>
     43
     44            <input type="text"
     45                   name="search"
     46                   value="@ViewBag.Search"
     47                   placeholder="Search by title or artist..." />
     48
     49        </div>
     50
     51
     52        <div>
     53
     54            <label>Genre</label>
     55
     56            <select name="genre">
     57
     58                <option value="">All Genres</option>
     59
     60                @foreach (var item in ViewBag.Genres)
     61                {
     62                    <option value="@item"
     63                            selected="@(ViewBag.Genre == item ? "selected" : null)">
     64                        @item
     65                    </option>
     66                }
     67
     68            </select>
     69
     70        </div>
     71
     72
     73        <div>
     74
     75            <label>Format</label>
     76
     77            <select name="format">
     78
     79                <option value="">All Formats</option>
     80
     81                @foreach (var item in ViewBag.Formats)
     82                {
     83                    <option value="@item"
     84                            selected="@(ViewBag.Format == item ? "selected" : null)">
     85                        @item
     86                    </option>
     87                }
     88
     89            </select>
     90
     91        </div>
     92
     93
     94        <div>
     95
     96            <label>Type</label>
     97
     98            <select name="type">
     99
     100                <option value="">All Types</option>
     101
     102                <option value="Album"
     103                        selected="@(ViewBag.Type == "Album" ? "selected" : null)">
     104                    Album
     105                </option>
     106
     107                <option value="Single"
     108                        selected="@(ViewBag.Type == "Single" ? "selected" : null)">
     109                    Single
     110                </option>
     111
     112            </select>
     113
     114        </div>
     115
     116
     117        <div>
     118
     119            <label>Sort</label>
     120
     121            <select name="sort">
     122
     123                <option value="">Title A–Z</option>
     124
     125                <option value="titleDesc"
     126                        selected="@(ViewBag.Sort == "titleDesc" ? "selected" : null)">
     127                    Title Z–A
     128                </option>
     129
     130                <option value="newest"
     131                        selected="@(ViewBag.Sort == "newest" ? "selected" : null)">
     132                    Newest
     133                </option>
     134
     135                <option value="oldest"
     136                        selected="@(ViewBag.Sort == "oldest" ? "selected" : null)">
     137                    Oldest
     138                </option>
     139
     140                <option value="format"
     141                        selected="@(ViewBag.Sort == "format" ? "selected" : null)">
     142                    Format
     143                </option>
     144
     145                <option value="priceAsc"
     146                        selected="@(ViewBag.Sort == "priceAsc" ? "selected" : null)">
     147                    Price: Low to High
     148                </option>
     149
     150                <option value="priceDesc"
     151                        selected="@(ViewBag.Sort == "priceDesc" ? "selected" : null)">
     152                    Price: High to Low
     153                </option>
     154
     155            </select>
     156
     157        </div>
     158
     159
     160        <div class="filter-button">
     161
     162            <button type="submit"
     163                    class="store-button primary">
     164
     165                Apply Filters
     166
     167            </button>
     168
     169        </div>
     170
     171
     172        @if (!string.IsNullOrWhiteSpace(ViewBag.Search as string) ||
     173             !string.IsNullOrWhiteSpace(ViewBag.Genre as string) ||
     174             !string.IsNullOrWhiteSpace(ViewBag.Format as string) ||
     175             !string.IsNullOrWhiteSpace(ViewBag.Type as string) ||
     176             !string.IsNullOrWhiteSpace(ViewBag.Sort as string))
     177        {
     178            <div class="clear-filter">
     179
     180                <a asp-action="Index">
     181                    Clear all filters
     182                </a>
     183
     184            </div>
     185        }
     186
     187    </form>
     188
     189
     190    <!-- =====================================================
     191         RELEASE GRID
     192         ===================================================== -->
     193
     194    @if (!Model.Any())
     195    {
     196        <div class="empty-store">
     197
     198            <div class="empty-store-icon">
     199                ♪
     200            </div>
     201
     202            <h2>No releases found</h2>
     203
     204            <p>
     205                Try changing your search or filters.
     206            </p>
     207
     208            <a asp-action="Index"
     209               class="store-button primary">
     210                View All Releases
     211            </a>
     212
     213        </div>
     214    }
     215    else
     216    {
     217        <div class="release-grid">
     218
     219            @foreach (var release in Model)
     220            {
     221                var isAlbum = release.Album != null;
     222                var isSingle = release.SingleRelease != null;
     223
     224                var releaseType =
     225                    isAlbum ? "ALBUM" :
     226                    isSingle ? "SINGLE" :
     227                    "RELEASE";
     228
     229                var artists = string.Join(
     230                    ", ",
     231                    release.ReleaseArtists
     232                        .OrderBy(x => x.ReleaseOrdinal)
     233                        .Select(x => x.Artist.ArtistName)
     234                );
     235
     236                var lowestPrice = release.Products
     237                    .Select(x => (decimal?)x.Price)
     238                    .Min();
     239
     240                <article class="release-card">
     241
     242                    <a asp-action="Details"
     243                       asp-route-id="@release.ReleaseId"
     244                       class="release-card-cover">
     245
     246                        @if (!string.IsNullOrWhiteSpace(release.CoverPhoto))
     247                        {
     248                            <img src="@release.CoverPhoto"
     249                                 alt="@release.Title" />
     250                        }
     251                        else
     252                        {
     253                            <div class="release-no-cover">
     254                                <span>♪</span>
     255                            </div>
     256                        }
     257
     258                        <span class="release-type-badge">
     259                            @releaseType
     260                        </span>
     261
     262                    </a>
     263
     264
     265                    <div class="release-card-body">
     266
     267                        <div class="release-card-meta">
     268
     269                            <span>
     270                                @release.Genre
     271                            </span>
     272
     273                            <span>
     274                                @release.ReleaseDate.ToString("yyyy")
     275                            </span>
     276
     277                        </div>
     278
     279
     280                        <h2>
     281
     282                            <a asp-action="Details"
     283                               asp-route-id="@release.ReleaseId">
     284
     285                                @release.Title
     286
     287                            </a>
     288
     289                        </h2>
     290
     291
     292                        <p class="release-card-artist">
     293
     294                            @artists
     295
     296                        </p>
     297
     298
     299                        <div class="format-list">
     300
     301                            @foreach (var product in release.Products
     302                                .GroupBy(x => x.Format)
     303                                .Select(x => x.First()))
     304                            {
     305                                <span class="format-pill">
     306                                    @product.Format
     307                                </span>
     308                            }
     309
     310                        </div>
     311
     312
     313                        <div class="release-card-bottom">
     314
     315                            <div class="release-starting">
     316
     317                                Starting at
     318
     319                                <strong>
     320                                    @(lowestPrice?.ToString("C") ?? "N/A")
     321                                </strong>
     322
     323                            </div>
     324
     325
     326                            <a asp-action="Details"
     327                               asp-route-id="@release.ReleaseId"
     328                               class="store-button primary small">
     329
     330                                View
     331
     332                            </a>
     333
     334                        </div>
     335
     336                    </div>
     337
     338                </article>
     339            }
     340
     341        </div>
     342    }
     343
    12344</div>
    13 
    14 
    15 <!-- SEARCH -->
    16 
    17 <form asp-action="Index"
    18       method="get"
    19       class="row g-2 mb-4">
    20 
    21     <div class="col-md-6">
    22 
    23         <input type="text"
    24                name="search"
    25                value="@ViewBag.Search"
    26                class="form-control"
    27                placeholder="Search releases..." />
    28 
    29     </div>
    30 
    31 
    32     <div class="col-md-3">
    33 
    34         <select name="genre"
    35                 class="form-select">
    36 
    37             <option value="">
    38                 All genres
    39             </option>
    40 
    41             @foreach (var genre in ViewBag.Genres)
    42             {
    43                 <option value="@genre"
    44                         selected="@(ViewBag.Genre == genre)">
    45 
    46                     @genre
    47 
    48                 </option>
    49             }
    50 
    51         </select>
    52 
    53     </div>
    54 
    55 
    56     <div class="col-md-3">
    57 
    58         <button type="submit"
    59                 class="btn btn-primary w-100">
    60 
    61             Search
    62 
    63         </button>
    64 
    65     </div>
    66 
    67 </form>
    68 
    69 
    70 <!-- RELEASES -->
    71 
    72 <div class="row">
    73 
    74 @foreach (var release in Model)
    75 {
    76     <div class="col-md-4 mb-4">
    77 
    78         <div class="card h-100 shadow-sm">
    79 
    80             @if (!string.IsNullOrEmpty(release.CoverPhoto))
    81             {
    82                 <img src="@release.CoverPhoto"
    83                      class="card-img-top"
    84                      style="height:300px; object-fit:cover;"
    85                      alt="@release.Title" />
    86             }
    87 
    88             <div class="card-body">
    89 
    90                 <h4 class="card-title">
    91                     @release.Title
    92                 </h4>
    93 
    94                 <p class="text-muted mb-1">
    95                     @release.Genre
    96                 </p>
    97 
    98                 <p class="small">
    99                     @release.ReleaseDate.ToString("yyyy")
    100                 </p>
    101 
    102 
    103                 <!-- ARTISTS -->
    104 
    105                 <p>
    106 
    107                     @string.Join(
    108                         ", ",
    109                         release.ReleaseArtists
    110                             .OrderBy(x => x.ReleaseOrdinal)
    111                             .Select(x => x.Artist.ArtistName)
    112                     )
    113 
    114                 </p>
    115 
    116 
    117                 <!-- AVAILABLE FORMATS -->
    118 
    119                 <div class="mb-3">
    120 
    121                     @foreach (var product in release.Products)
    122                     {
    123                         <span class="badge bg-secondary me-1">
    124 
    125                             @product.Format
    126 
    127                         </span>
    128                     }
    129 
    130                 </div>
    131 
    132 
    133                 <a asp-action="Details"
    134                    asp-route-id="@release.ReleaseId"
    135                    class="btn btn-primary">
    136 
    137                     View Release
    138 
    139                 </a>
    140 
    141             </div>
    142 
    143         </div>
    144 
    145     </div>
    146 }
    147 
    148 </div>
Note: See TracChangeset for help on using the changeset viewer.