Skip to content

Commit 7773f95

Browse files
committed
Bomb Girao
1 parent 62190c2 commit 7773f95

File tree

173 files changed

+531
-344
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

173 files changed

+531
-344
lines changed

.github/workflows/dotnet.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ jobs:
2020
- name: Publish Blazor WebAssembly project
2121
run: dotnet publish TomAndJerry.csproj -c Release -o release --nologo
2222

23+
- name: Change base-tag in index.html from / to TomAndJerry
24+
run: sed -i 's/<base href="\/" \/>/<base href="\/TomAndJerry\/" \/>/g' release/wwwroot/index.html
25+
2326
- name: Add 404.html (for GitHub Pages SPA fallback)
2427
run: cp release/wwwroot/index.html release/wwwroot/404.html
2528

Component/AppBar.razor

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,4 @@
7373
StateService.OnStateChanged -= StateHasChanged;
7474
}
7575
}
76-

77-
7876

Component/ErrorPage.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@
2424
@code {
2525
void Home()
2626
{
27-
Nav.NavigateTo("/");
27+
Nav.NavigateTo("");
2828
}
2929
}

Component/RealTimeSearch.razor

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
@inject NavigationManager NavigationManager
55
@inject IJSRuntime JSRuntime
66

7-
<div class="relative">
7+
<div class="relative" @onclick:stopPropagation="true" data-search-component>
88
<div class="flex items-center bg-white border border-gray-300 rounded-full shadow-sm hover:shadow-md transition-shadow">
99
<input type="text"
1010
@bind="searchTerm"
@@ -22,7 +22,7 @@
2222
</div>
2323

2424
<!-- Search Suggestions Dropdown -->
25-
@if (showSuggestions && searchSuggestions.Any())
25+
@if (showSuggestions && searchSuggestions.Any() && !searchResults.Any())
2626
{
2727
<div class="absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-50 max-h-60 overflow-y-auto">
2828
@foreach (var suggestion in searchSuggestions)
@@ -40,16 +40,45 @@
4040
</div>
4141
}
4242

43-
<!-- Search Results Count -->
43+
<!-- Search Results Preview -->
4444
@if (!string.IsNullOrEmpty(searchTerm) && searchResults.Any())
4545
{
46-
<div class="absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-40 p-3">
47-
<div class="flex items-center justify-between text-sm text-gray-600">
48-
<span>@searchResults.Count() results found</span>
49-
<button class="text-red-600 hover:text-red-800 font-medium"
50-
@onclick="NavigateToSearchResults">
51-
View all results
52-
</button>
46+
<div class="absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-50 max-h-80 overflow-y-auto">
47+
<div class="p-3 border-b border-gray-200">
48+
<div class="flex items-center justify-between text-sm text-gray-600">
49+
<span>@searchResults.Count() results found</span>
50+
<button class="text-red-600 hover:text-red-800 font-medium"
51+
@onclick="NavigateToSearchResults">
52+
View all results
53+
</button>
54+
</div>
55+
</div>
56+
57+
<!-- Quick Results Preview -->
58+
<div class="p-3 space-y-2">
59+
@foreach (var video in searchResults.Take(3))
60+
{
61+
<div class="flex items-center space-x-3 p-2 hover:bg-gray-50 rounded-lg cursor-pointer"
62+
@onclick="() => NavigateToVideo(video)">
63+
<div class="w-12 h-8 bg-gray-200 rounded overflow-hidden flex-shrink-0">
64+
<img src="@video.Thumbnail" alt="@video.Description" class="w-full h-full object-cover" />
65+
</div>
66+
<div class="flex-1 min-w-0">
67+
<p class="text-sm font-medium text-gray-900 truncate">@GetCleanTitle(video.Description)</p>
68+
<p class="text-xs text-gray-500">Tom & Jerry</p>
69+
</div>
70+
</div>
71+
}
72+
73+
@if (searchResults.Count() > 3)
74+
{
75+
<div class="text-center pt-2">
76+
<button class="text-xs text-red-600 hover:text-red-800 font-medium"
77+
@onclick="NavigateToSearchResults">
78+
+@(searchResults.Count() - 3) more results
79+
</button>
80+
</div>
81+
}
5382
</div>
5483
</div>
5584
}
@@ -62,17 +91,33 @@
6291
private bool showSuggestions = false;
6392
private Timer? searchTimer;
6493

94+
protected override async Task OnAfterRenderAsync(bool firstRender)
95+
{
96+
if (firstRender)
97+
{
98+
await JSRuntime.InvokeVoidAsync("addClickOutsideHandler", DotNetObjectReference.Create(this));
99+
}
100+
}
101+
65102
protected override void OnInitialized()
66103
{
67104
SearchService.OnSearchResultsChanged += OnSearchResultsChanged;
68105

69-
// Initialize search timer for debouncing
106+
// Initialize search timer for debouncing (reduced to 150ms for better responsiveness)
70107
searchTimer = new Timer(async _ => await DebouncedSearch(), null, Timeout.Infinite, Timeout.Infinite);
71108
}
72109

73110
private void OnSearchResultsChanged(IEnumerable<TomAndJerry.Model.Video> results)
74111
{
75112
searchResults = results;
113+
114+
// Clear suggestions when we have search results
115+
if (searchResults.Any())
116+
{
117+
searchSuggestions = Enumerable.Empty<string>();
118+
showSuggestions = false;
119+
}
120+
76121
InvokeAsync(StateHasChanged);
77122
}
78123

@@ -87,58 +132,96 @@
87132
return;
88133
}
89134

90-
// Get search suggestions
91-
searchSuggestions = await SearchService.GetSearchSuggestionsAsync(searchTerm);
135+
// Perform immediate search for preview
136+
var immediateResults = await VideoService.SearchVideosAsync(searchTerm);
137+
searchResults = immediateResults;
92138

93-
// Perform search
139+
// Only show suggestions if no search results found and search term is long enough
140+
if (!searchResults.Any() && searchTerm.Length >= 2)
141+
{
142+
searchSuggestions = await SearchService.GetSearchSuggestionsAsync(searchTerm);
143+
showSuggestions = searchSuggestions.Any();
144+
}
145+
else
146+
{
147+
// Clear suggestions when we have results or search term is too short
148+
searchSuggestions = Enumerable.Empty<string>();
149+
showSuggestions = false;
150+
}
151+
152+
// Also trigger the debounced search for suggestions
94153
await SearchService.SearchAsync(searchTerm);
95154

96-
showSuggestions = searchSuggestions.Any();
97155
await InvokeAsync(StateHasChanged);
98156
}
99157

100-
private async Task HandleKeyDown(KeyboardEventArgs e)
158+
private void HandleKeyDown(KeyboardEventArgs e)
101159
{
102160
if (e.Key == "Enter")
103161
{
104162
PerformSearch();
105163
}
106164
else if (e.Key == "Escape")
107165
{
108-
showSuggestions = false;
109-
await InvokeAsync(StateHasChanged);
166+
CloseDropdown();
110167
}
111168
else
112169
{
113-
// Debounce search input
114-
searchTimer?.Change(300, Timeout.Infinite);
170+
// Debounce search input (reduced to 150ms for better responsiveness)
171+
searchTimer?.Change(150, Timeout.Infinite);
115172
}
116173
}
117174

118175
private void PerformSearch()
119176
{
120177
if (!string.IsNullOrEmpty(searchTerm))
121178
{
179+
CloseDropdown();
122180
NavigationManager.NavigateTo($"Search/{Uri.EscapeDataString(searchTerm)}");
123181
}
124-
showSuggestions = false;
125182
}
126183

127184
private void SelectSuggestion(string suggestion)
128185
{
129186
searchTerm = suggestion;
130-
showSuggestions = false;
187+
CloseDropdown();
131188
PerformSearch();
132189
}
133190

134191
private void NavigateToSearchResults()
135192
{
136193
if (!string.IsNullOrEmpty(searchTerm))
137194
{
195+
CloseDropdown();
138196
NavigationManager.NavigateTo($"Search/{Uri.EscapeDataString(searchTerm)}");
139197
}
140198
}
141199

200+
private void NavigateToVideo(TomAndJerry.Model.Video video)
201+
{
202+
CloseDropdown();
203+
NavigationManager.NavigateTo($"playmedia/{video.Id}");
204+
}
205+
206+
private void CloseDropdown()
207+
{
208+
showSuggestions = false;
209+
searchSuggestions = Enumerable.Empty<string>();
210+
searchResults = Enumerable.Empty<TomAndJerry.Model.Video>();
211+
InvokeAsync(StateHasChanged);
212+
}
213+
214+
private string GetCleanTitle(string description)
215+
{
216+
return string.Join(" ", description.Split(".").Where(x => x != "mkv").Select(x => x));
217+
}
218+
219+
[JSInvokable]
220+
public void OnClickOutside()
221+
{
222+
CloseDropdown();
223+
}
224+
142225
public void Dispose()
143226
{
144227
SearchService.OnSearchResultsChanged -= OnSearchResultsChanged;

Pages/Home.razor

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
@inject NavigationManager nav
44
@inject IVideoService VideoService
55
@inject IStateService StateService
6+
@inject IJSRuntime JSRuntime
67
<PageTitle>Home - Tom & Jerry</PageTitle>
78

89
<div class="min-h-screen bg-gray-50">
@@ -20,6 +21,27 @@
2021
The timeless adventures of the world's most famous cat and mouse duo
2122
</p>
2223

24+
<!-- Hero Search Bar -->
25+
<div class="max-w-md mx-auto mb-8">
26+
<div class="relative">
27+
<div class="flex items-center bg-white/10 backdrop-blur-sm border border-white/20 rounded-full shadow-lg">
28+
<input type="text"
29+
@bind="heroSearchTerm"
30+
@bind:event="oninput"
31+
@onkeydown="HandleHeroSearchKeyDown"
32+
class="flex-1 px-4 py-3 text-sm border-0 rounded-l-full focus:outline-none focus:ring-0 bg-transparent text-white placeholder-white/70"
33+
placeholder="Search episodes...">
34+
35+
<button class="px-4 py-3 text-white/80 hover:text-white hover:bg-white/10 rounded-r-full transition-colors"
36+
@onclick="PerformHeroSearch">
37+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
38+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
39+
</svg>
40+
</button>
41+
</div>
42+
</div>
43+
</div>
44+
2345
<!-- Stats -->
2446
<div class="grid grid-cols-1 sm:grid-cols-3 gap-6 max-w-md mx-auto">
2547
<div class="text-center">
@@ -39,6 +61,26 @@
3961
</div>
4062
</div>
4163

64+
<!-- Call to Action Section -->
65+
<div class="bg-white border-b border-gray-200">
66+
<div class="max-w-7xl mx-auto px-4 py-6">
67+
<div class="text-center">
68+
<h2 class="text-2xl font-bold text-gray-900 mb-2">Start Watching Now</h2>
69+
<p class="text-gray-600 mb-4">Discover your favorite Tom & Jerry episodes</p>
70+
<div class="flex flex-col sm:flex-row gap-3 justify-center">
71+
<button @onclick="ScrollToFeatured"
72+
class="px-6 py-3 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors font-medium shadow-lg hover:shadow-xl transform hover:-translate-y-1">
73+
Browse Episodes
74+
</button>
75+
<button @onclick="ScrollToAllEpisodes"
76+
class="px-6 py-3 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors font-medium">
77+
View All
78+
</button>
79+
</div>
80+
</div>
81+
</div>
82+
</div>
83+
4284
<!-- Main Content -->
4385
<div class="max-w-7xl mx-auto px-4 py-8">
4486
@if (StateService.IsLoading || !StateService.CurrentVideos.Any())
@@ -167,10 +209,10 @@
167209
else
168210
{
169211
<!-- Featured Section -->
170-
<div class="mb-12">
212+
<div id="featured" class="mb-12">
171213
<div class="flex items-center justify-between mb-6">
172214
<div class="flex items-center space-x-3">
173-
<div class="w-10 h-10 bg-red-600 rounded-full flex items-center justify-center">
215+
<div class="w-10 h-10 bg-gradient-to-r from-red-600 to-red-700 rounded-full flex items-center justify-center shadow-lg">
174216
<svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 20 20">
175217
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd"/>
176218
</svg>
@@ -180,6 +222,10 @@
180222
<p class="text-gray-600">Handpicked classics that never get old</p>
181223
</div>
182224
</div>
225+
<div class="hidden md:flex items-center space-x-2">
226+
<span class="text-sm text-gray-500">Popular this week</span>
227+
<div class="w-2 h-2 bg-red-500 rounded-full animate-pulse"></div>
228+
</div>
183229
</div>
184230

185231
<!-- Featured Video Grid -->
@@ -192,7 +238,7 @@
192238
</div>
193239

194240
<!-- All Episodes Section -->
195-
<div class="mb-12">
241+
<div id="all-episodes" class="mb-12">
196242
<div class="flex items-center justify-between mb-6">
197243
<div class="flex items-center space-x-3">
198244
<div class="w-10 h-10 bg-blue-600 rounded-full flex items-center justify-center">
@@ -235,11 +281,44 @@
235281

236282
@code
237283
{
284+
private string heroSearchTerm = string.Empty;
285+
238286
public void GoTOPage(Video video)
239287
{
240288
nav.NavigateTo($"playmedia/{video.Id}");
241289
}
242290

291+
private void PerformHeroSearch()
292+
{
293+
if (!string.IsNullOrEmpty(heroSearchTerm))
294+
{
295+
nav.NavigateTo($"Search/{Uri.EscapeDataString(heroSearchTerm)}");
296+
}
297+
}
298+
299+
private void HandleHeroSearchKeyDown(KeyboardEventArgs e)
300+
{
301+
if (e.Key == "Enter")
302+
{
303+
PerformHeroSearch();
304+
}
305+
}
306+
307+
private async Task ScrollToSection(string sectionId)
308+
{
309+
await JSRuntime.InvokeVoidAsync("scrollToElement", sectionId);
310+
}
311+
312+
private async Task ScrollToFeatured()
313+
{
314+
await ScrollToSection("featured");
315+
}
316+
317+
private async Task ScrollToAllEpisodes()
318+
{
319+
await ScrollToSection("all-episodes");
320+
}
321+
243322
protected override async Task OnInitializedAsync()
244323
{
245324
StateService.OnStateChanged += StateHasChanged;

0 commit comments

Comments
 (0)