+ + @Body @@ -21,3 +17,108 @@ Reload 🗙 + + + diff --git a/MovieActorLookup/Components/Layout/NavMenu.razor b/MovieActorLookup/Components/Layout/NavMenu.razor index 93cb4ed..b27deaa 100644 --- a/MovieActorLookup/Components/Layout/NavMenu.razor +++ b/MovieActorLookup/Components/Layout/NavMenu.razor @@ -1,39 +1,106 @@ - - - I Know Them! - - +@* NavMenu.razor *@ + + + + 🎬 + I Know Them! + - - - - - - - Home - - - - - - - - - - Search Movies - - - - - - - - TV Show Search - - + + + + 🏠 + Home + + + 🎭 + Movies + + + 📺 + TV Shows + + diff --git a/MovieActorLookup/Components/Pages/SearchShows.razor b/MovieActorLookup/Components/Pages/SearchShows.razor index a4c943d..839ae33 100644 --- a/MovieActorLookup/Components/Pages/SearchShows.razor +++ b/MovieActorLookup/Components/Pages/SearchShows.razor @@ -1,6 +1,7 @@ @page "/searchshows" @using MovieActorLookup.Models @inject ShowService ShowService +@inject IJSRuntime JSRuntime @rendermode InteractiveServer @@ -77,6 +78,12 @@ @_matchedShow.ShowTitle as @_matchedShow.CharacterName + @if (!string.IsNullOrEmpty(_matchedShow.Overview?.Trim())) + { + + @_matchedShow.Overview.Trim() + + } First aired: @_matchedShow.FirstAirDate @@ -115,7 +122,17 @@ as @show.CharacterName @if (!string.IsNullOrEmpty(show.Overview)) { - @(show.Overview.Length > 120 ? show.Overview.Substring(0, 120) + "..." : show.Overview) + + + @show.Overview + + @if (show.Overview.Length > 150) + { + ToggleOverview(show.ShowTitle)"> + @(IsOverviewExpanded(show.ShowTitle) ? "Show less" : "Read more") + + } + } @show.FirstAirDate @@ -254,22 +271,8 @@ border: 2px solid rgba(255,255,255,0.3); border-top: 2px solid white; border-radius: 50%; - animation: spin 1s linear infinite; } -/* keyframes spin { - 0% - - { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } - - } */ - .loading-state, .welcome-state, .no-results { text-align: center; padding: 3rem 2rem; @@ -288,31 +291,8 @@ height: 8px; background: #667eea; border-radius: 50%; - animation: bounce 1.4s ease-in-out infinite both; } - .loading-dot:nth-child(1) { - animation-delay: -0.32s; - } - - .loading-dot:nth-child(2) { - animation-delay: -0.16s; - } - -/* keyframes bounce { - 0%, 80%, 100% - - - { - transform: scale(0); - } - - 40% { - transform: scale(1); - } - - } */ - .welcome-icon, .no-results-icon { font-size: 3rem; margin-bottom: 1rem; @@ -376,7 +356,7 @@ .shows-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; } @@ -407,14 +387,16 @@ .poster-container { position: relative; - height: 200px; + width: 100%; + aspect-ratio: 2/3; overflow: hidden; } .poster-image { width: 100%; height: 100%; - object-fit: cover; + object-fit: contain; + background-color: #f8f9fa; transition: transform 0.3s ease; } @@ -460,6 +442,34 @@ margin: 0.75rem 0; } + .show-overview.truncated { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .show-overview.expanded { + display: block; + } + + .read-more-btn { + background: none; + border: none; + color: #667eea; + font-size: 0.85rem; + font-weight: 600; + cursor: pointer; + padding: 0.25rem 0; + margin-top: 0.5rem; + text-decoration: underline; + transition: color 0.3s ease; + } + + .read-more-btn:hover { + color: #4c63d2; + } + .air-date { color: #999; font-size: 0.85rem; @@ -495,12 +505,82 @@ } + + @code { private string _tvTitle = ""; private string _characterName = ""; private Actor _actor; private TvCharacter _matchedShow; private bool _isSearching = false; + private HashSet _expandedOverviews = new HashSet(); + + private bool IsOverviewExpanded(string showTitle) + { + return _expandedOverviews.Contains(showTitle); + } + + private void ToggleOverview(string showTitle) + { + if (_expandedOverviews.Contains(showTitle)) + { + _expandedOverviews.Remove(showTitle); + } + else + { + _expandedOverviews.Add(showTitle); + } + } private async Task SearchForActorAndCharacters() { @@ -512,6 +592,10 @@ _matchedShow = null; StateHasChanged(); + // Start animations after a small delay to ensure DOM is ready + await Task.Delay(100); + await JSRuntime.InvokeVoidAsync("startAnimations"); + try { var shows = await ShowService.GetShowsByTitle(_tvTitle); diff --git a/MovieActorLookup/wwwroot/app.css b/MovieActorLookup/wwwroot/app.css index 9bd14ab..14c42a0 100644 --- a/MovieActorLookup/wwwroot/app.css +++ b/MovieActorLookup/wwwroot/app.css @@ -52,6 +52,12 @@ h1:focus { border-color: #929292; } +.page .content { + padding-top: 24px !important; + margin: 0 auto !important; + max-width: 1200px !important; +} + /*movie card styling*/ .movie-poster {