Koperization commited on
Commit
bd86cee
·
verified ·
1 Parent(s): 46b9ae2

**1. PAGE STRUCTURE & LAYOUT**

Browse files

- **Container**: 100% width, max-width 1200px, centered
- **Header Section**: Existing site header (unchanged)
- **Filter/Search Section**: 80px tall, #121212 background, 1px #333333 border-bottom
- **Team Sections**: Organized sequentially with animated transitions
- **Player Rows**: Individual animated cards with complete profiles
- **Footer**: Existing site footer (unchanged)

**2. FILTER & SEARCH SYSTEM (Detailed Specifications)**
- **Search Bar**:
* Dimensions: 100% width (max 600px), 48px height
* Background: #1e1e1e with 8px border-radius
* Text: 16px #f8f9fa, Open Sans
* Placeholder: "Search by name, jersey #, or position..."
* Animation: Smooth 0.3s width expansion on focus
* Icon: Magnifying glass (#5ec0cc) with 0.2s color transition on hover
* Live search with 300ms debounce and loading spinner during search

Files changed (1) hide show
  1. volleyball.html +111 -102
volleyball.html CHANGED
@@ -26,10 +26,18 @@
26
  font-family: 'Open Sans', sans-serif;
27
  background-color: #121212;
28
  color: #ffffff;
 
 
29
  }
30
  h1, h2, h3, h4, h5, h6 {
31
  font-family: 'Montserrat', sans-serif;
32
  }
 
 
 
 
 
 
33
  .hero-image {
34
  position: absolute;
35
  top: 0;
@@ -39,9 +47,12 @@
39
  object-fit: cover;
40
  z-index: -1;
41
  }
 
 
 
 
42
  .player-card:hover {
43
  transform: translateY(-5px);
44
- transition: all 0.3s ease;
45
  }
46
  .tab-active {
47
  background-color: #5ec0cc;
@@ -61,6 +72,13 @@
61
  transform: translateY(-5px);
62
  box-shadow: 0 10px 25px rgba(94, 192, 204, 0.2);
63
  }
 
 
 
 
 
 
 
64
  .starter {
65
  border-left: 4px solid #5ECCA2;
66
  }
@@ -112,17 +130,20 @@
112
  cursor: pointer;
113
  color: #5ec0cc;
114
  }
115
- /* New filter/search styles */
116
- .filter-search-container {
117
  background-color: #121212;
118
  border-bottom: 1px solid #333333;
119
  padding: 16px 0;
 
 
 
120
  }
121
  .search-container {
122
  position: relative;
123
- max-width: 600px;
124
  width: 100%;
125
- margin: 0 auto 16px;
 
126
  }
127
  .search-input {
128
  width: 100%;
@@ -130,10 +151,10 @@
130
  background-color: #1e1e1e;
131
  border-radius: 8px;
132
  border: none;
133
- padding: 0 16px 0 48px;
134
  color: #f8f9fa;
135
- font-family: 'Open Sans', sans-serif;
136
  font-size: 16px;
 
137
  transition: width 0.3s ease;
138
  }
139
  .search-input:focus {
@@ -142,7 +163,7 @@
142
  }
143
  .search-icon {
144
  position: absolute;
145
- left: 16px;
146
  top: 50%;
147
  transform: translateY(-50%);
148
  color: #5ec0cc;
@@ -151,39 +172,19 @@
151
  .search-icon:hover {
152
  color: #4ab3c6;
153
  }
154
- .filter-group {
155
- display: flex;
156
- justify-content: center;
157
- gap: 16px;
158
- }
159
- .filter-dropdown {
160
- width: 180px;
161
- height: 48px;
162
- background-color: #1e1e1e;
163
- border: 1px solid #333333;
164
- border-radius: 4px;
165
- color: white;
166
- padding: 0 12px;
167
- font-family: 'Open Sans', sans-serif;
168
- font-size: 16px;
169
- transition: border-color 0.2s ease;
170
- }
171
- .filter-dropdown:focus {
172
- outline: none;
173
- border-color: #5ec0cc;
174
- box-shadow: 0 0 0 2px rgba(94, 192, 204, 0.2);
175
- }
176
  .loading-spinner {
177
- display: none;
178
  position: absolute;
179
- right: 16px;
180
  top: 50%;
181
  transform: translateY(-50%);
 
 
 
 
 
 
182
  width: 20px;
183
  height: 20px;
184
- border: 2px solid #5ec0cc;
185
- border-top: 2px solid transparent;
186
- border-radius: 50%;
187
  animation: spin 1s linear infinite;
188
  }
189
  @keyframes spin {
@@ -196,19 +197,22 @@
196
  transition: opacity 0.5s ease, transform 0.5s ease;
197
  }
198
  .team-section.hidden {
 
 
 
199
  opacity: 0;
200
- transform: translateY(20px);
201
  }
202
- .player-card {
203
  transition: all 0.3s ease;
204
  }
205
- .player-card.filtered-out {
206
- opacity: 0.3;
207
  }
208
  </style>
209
  </head>
210
  <body class="bg-dark text-white">
211
- <!-- Navigation -->
212
  <header class="fixed w-full z-50 bg-dark border-b border-primary">
213
  <div class="container mx-auto px-4 py-3 flex justify-between items-center">
214
  <div class="flex items-center">
@@ -300,49 +304,48 @@
300
  </div>
301
  </section>
302
  <!-- Filter/Search Section -->
303
- <section class="filter-search-container">
304
- <div class="container mx-auto px-4">
305
  <div class="search-container">
306
  <i data-feather="search" class="search-icon"></i>
307
  <input type="text" id="playerSearch" class="search-input" placeholder="Search by name, jersey #, or position...">
308
- <div class="loading-spinner" id="searchSpinner"></div>
309
- </div>
310
- <div class="filter-group">
311
- <select id="genderFilter" class="filter-dropdown">
312
- <option value="all">All Players</option>
313
- <option value="female">Female</option>
314
- <option value="male">Male</option>
315
- </select>
316
- <select id="statusFilter" class="filter-dropdown">
317
- <option value="all">All Statuses</option>
318
- <option value="starter">Starters</option>
319
- <option value="substitute">Substitutes</option>
320
- </select>
321
- <select id="teamFilter" class="filter-dropdown">
322
- <option value="all">All Teams</option>
323
- <option value="senior-female-a">Senior Female A</option>
324
- <option value="senior-male-a">Senior Male A</option>
325
- <option value="senior-female-b">Senior Female B</option>
326
- <option value="senior-male-b">Senior Male B</option>
327
- <option value="junior-female-a">Junior Female A</option>
328
- <option value="junior-male-a">Junior Male A</option>
329
- <option value="junior-female-b">Junior Female B</option>
330
- <option value="junior-male-b">Junior Male B</option>
331
- </select>
332
  </div>
333
  </div>
334
  </section>
 
335
  <!-- Team Structure Section -->
336
  <section class="py-16 border-b border-[#2e2e2e] bg-[#0a0a0a]">
337
  <div class="container mx-auto px-4">
338
  <h2 class="text-3xl font-bold text-primary mb-8">OUR TEAMS</h2>
339
 
340
- <!-- Tabs -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  <div class="flex mb-8 border-b border-[#2e2e2e]">
342
  <button id="seniorsTab" class="tab-active py-2 px-6 font-bold rounded-t">Seniors (Grades 9-12)</button>
343
  <button id="juniorsTab" class="py-2 px-6 font-bold rounded-t">Juniors (Grades 6-8)</button>
344
  </div>
345
- <!-- Seniors Content -->
346
  <div id="seniorsContent">
347
  <div class="columns-1 md:columns-3 gap-8">
348
  <!-- Senior Female A Team -->
@@ -1516,21 +1519,18 @@
1516
  document.getElementById('juniorsContent').classList.remove('hidden');
1517
  document.getElementById('seniorsContent').classList.add('hidden');
1518
  });
1519
- // Search and filter functionality
1520
- let searchTimeout;
1521
 
 
1522
  function applyFilters() {
1523
- const searchTerm = document.getElementById('playerSearch').value.toLowerCase();
1524
  const genderFilter = document.getElementById('genderFilter').value;
1525
  const statusFilter = document.getElementById('statusFilter').value;
1526
- const teamFilter = document.getElementById('teamFilter').value;
1527
 
1528
  // Get all player cards
1529
  const playerCards = document.querySelectorAll('.player-card');
1530
 
1531
  playerCards.forEach(card => {
1532
- const playerName = card.querySelector('h4').textContent.toLowerCase();
1533
- const playerInfo = card.querySelector('p').textContent.toLowerCase();
1534
  const isStarter = card.classList.contains('starter');
1535
  const isSubstitute = card.classList.contains('substitute');
1536
 
@@ -1538,7 +1538,7 @@
1538
  const teamColumn = card.closest('.team-column');
1539
  let teamInfo = '';
1540
  if (teamColumn) {
1541
- teamInfo = teamColumn.querySelector('h3').textContent.toLowerCase().replace(/\s+/g, '-');
1542
  }
1543
 
1544
  // Gender check
@@ -1561,49 +1561,57 @@
1561
  }
1562
  }
1563
 
1564
- // Team check
1565
- let teamMatch = true;
1566
- if (teamFilter !== 'all') {
1567
- teamMatch = teamInfo.includes(teamFilter);
1568
- }
1569
-
1570
- // Search term check
1571
- let searchMatch = true;
1572
- if (searchTerm) {
1573
- searchMatch = playerName.includes(searchTerm) || playerInfo.includes(searchTerm);
1574
- }
1575
-
1576
  // Apply filters
1577
- if (genderMatch && statusMatch && teamMatch && searchMatch) {
1578
- card.classList.remove('filtered-out');
1579
  } else {
1580
- card.classList.add('filtered-out');
1581
  }
1582
  });
1583
  }
1584
 
1585
- // Debounced search
1586
- document.getElementById('playerSearch').addEventListener('input', function() {
1587
- const spinner = document.getElementById('searchSpinner');
 
 
 
 
 
 
 
1588
  spinner.style.display = 'block';
1589
 
1590
- clearTimeout(searchTimeout);
1591
  searchTimeout = setTimeout(() => {
1592
- applyFilters();
1593
  spinner.style.display = 'none';
1594
  }, 300);
1595
  });
1596
 
1597
- // Add event listeners to filters
1598
- document.getElementById('genderFilter').addEventListener('change', applyFilters);
1599
- document.getElementById('statusFilter').addEventListener('change', applyFilters);
1600
- document.getElementById('teamFilter').addEventListener('change', applyFilters);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1601
  // Player modal functionality
1602
  function openPlayerModal(playerId) {
1603
  const modal = document.getElementById('playerModal');
1604
  const content = document.getElementById('playerProfileContent');
1605
-
1606
- // Sample player data - in a real implementation, this would come from a database
1607
  let playerData;
1608
  if (playerId === 'thay-sethean') {
1609
  playerData = {
@@ -1698,7 +1706,8 @@
1698
  closePlayerModal();
1699
  }
1700
  });
1701
- // Mobile menu toggle
 
1702
  document.getElementById('menu-toggle').addEventListener('click', function() {
1703
  document.getElementById('mobile-menu').classList.remove('hidden');
1704
  });
 
26
  font-family: 'Open Sans', sans-serif;
27
  background-color: #121212;
28
  color: #ffffff;
29
+ margin: 0;
30
+ padding: 0;
31
  }
32
  h1, h2, h3, h4, h5, h6 {
33
  font-family: 'Montserrat', sans-serif;
34
  }
35
+ .container {
36
+ width: 100%;
37
+ max-width: 1200px;
38
+ margin: 0 auto;
39
+ padding: 0 20px;
40
+ }
41
  .hero-image {
42
  position: absolute;
43
  top: 0;
 
47
  object-fit: cover;
48
  z-index: -1;
49
  }
50
+ .player-card {
51
+ transition: all 0.3s ease;
52
+ cursor: pointer;
53
+ }
54
  .player-card:hover {
55
  transform: translateY(-5px);
 
56
  }
57
  .tab-active {
58
  background-color: #5ec0cc;
 
72
  transform: translateY(-5px);
73
  box-shadow: 0 10px 25px rgba(94, 192, 204, 0.2);
74
  }
75
+ .filter-dropdown {
76
+ background-color: #1e1e1e;
77
+ border: 1px solid #5ec0cc;
78
+ color: white;
79
+ padding: 0.5rem;
80
+ border-radius: 0.25rem;
81
+ }
82
  .starter {
83
  border-left: 4px solid #5ECCA2;
84
  }
 
130
  cursor: pointer;
131
  color: #5ec0cc;
132
  }
133
+ /* New Filter/Search Styles */
134
+ .filter-search-section {
135
  background-color: #121212;
136
  border-bottom: 1px solid #333333;
137
  padding: 16px 0;
138
+ height: 80px;
139
+ display: flex;
140
+ align-items: center;
141
  }
142
  .search-container {
143
  position: relative;
 
144
  width: 100%;
145
+ max-width: 600px;
146
+ margin: 0 auto;
147
  }
148
  .search-input {
149
  width: 100%;
 
151
  background-color: #1e1e1e;
152
  border-radius: 8px;
153
  border: none;
154
+ padding: 0 20px 0 50px;
155
  color: #f8f9fa;
 
156
  font-size: 16px;
157
+ font-family: 'Open Sans', sans-serif;
158
  transition: width 0.3s ease;
159
  }
160
  .search-input:focus {
 
163
  }
164
  .search-icon {
165
  position: absolute;
166
+ left: 20px;
167
  top: 50%;
168
  transform: translateY(-50%);
169
  color: #5ec0cc;
 
172
  .search-icon:hover {
173
  color: #4ab3c6;
174
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  .loading-spinner {
 
176
  position: absolute;
177
+ right: 20px;
178
  top: 50%;
179
  transform: translateY(-50%);
180
+ display: none;
181
+ }
182
+ .spinner {
183
+ border: 2px solid #f3f3f3;
184
+ border-top: 2px solid #5ec0cc;
185
+ border-radius: 50%;
186
  width: 20px;
187
  height: 20px;
 
 
 
188
  animation: spin 1s linear infinite;
189
  }
190
  @keyframes spin {
 
197
  transition: opacity 0.5s ease, transform 0.5s ease;
198
  }
199
  .team-section.hidden {
200
+ display: none;
201
+ }
202
+ .team-section.fade-out {
203
  opacity: 0;
204
+ transform: translateY(-20px);
205
  }
206
+ .player-row {
207
  transition: all 0.3s ease;
208
  }
209
+ .player-row.hidden {
210
+ display: none;
211
  }
212
  </style>
213
  </head>
214
  <body class="bg-dark text-white">
215
+ <!-- Navigation -->
216
  <header class="fixed w-full z-50 bg-dark border-b border-primary">
217
  <div class="container mx-auto px-4 py-3 flex justify-between items-center">
218
  <div class="flex items-center">
 
304
  </div>
305
  </section>
306
  <!-- Filter/Search Section -->
307
+ <section class="filter-search-section">
308
+ <div class="container">
309
  <div class="search-container">
310
  <i data-feather="search" class="search-icon"></i>
311
  <input type="text" id="playerSearch" class="search-input" placeholder="Search by name, jersey #, or position...">
312
+ <div class="loading-spinner" id="loadingSpinner">
313
+ <div class="spinner"></div>
314
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  </div>
316
  </div>
317
  </section>
318
+
319
  <!-- Team Structure Section -->
320
  <section class="py-16 border-b border-[#2e2e2e] bg-[#0a0a0a]">
321
  <div class="container mx-auto px-4">
322
  <h2 class="text-3xl font-bold text-primary mb-8">OUR TEAMS</h2>
323
 
324
+ <!-- Filter Controls -->
325
+ <div class="mb-8 flex flex-wrap gap-4">
326
+ <div>
327
+ <label class="block mb-2">Gender</label>
328
+ <select id="genderFilter" class="filter-dropdown">
329
+ <option value="all">All</option>
330
+ <option value="male">Male</option>
331
+ <option value="female">Female</option>
332
+ </select>
333
+ </div>
334
+ <div>
335
+ <label class="block mb-2">Status</label>
336
+ <select id="statusFilter" class="filter-dropdown">
337
+ <option value="all">All Players</option>
338
+ <option value="starter">Starters</option>
339
+ <option value="substitute">Substitutes</option>
340
+ </select>
341
+ </div>
342
+ </div>
343
+ <!-- Tabs -->
344
  <div class="flex mb-8 border-b border-[#2e2e2e]">
345
  <button id="seniorsTab" class="tab-active py-2 px-6 font-bold rounded-t">Seniors (Grades 9-12)</button>
346
  <button id="juniorsTab" class="py-2 px-6 font-bold rounded-t">Juniors (Grades 6-8)</button>
347
  </div>
348
+ <!-- Seniors Content -->
349
  <div id="seniorsContent">
350
  <div class="columns-1 md:columns-3 gap-8">
351
  <!-- Senior Female A Team -->
 
1519
  document.getElementById('juniorsContent').classList.remove('hidden');
1520
  document.getElementById('seniorsContent').classList.add('hidden');
1521
  });
 
 
1522
 
1523
+ // Filter functionality
1524
  function applyFilters() {
 
1525
  const genderFilter = document.getElementById('genderFilter').value;
1526
  const statusFilter = document.getElementById('statusFilter').value;
 
1527
 
1528
  // Get all player cards
1529
  const playerCards = document.querySelectorAll('.player-card');
1530
 
1531
  playerCards.forEach(card => {
1532
+ const playerName = card.querySelector('h4').textContent;
1533
+ const playerInfo = card.querySelector('p').textContent;
1534
  const isStarter = card.classList.contains('starter');
1535
  const isSubstitute = card.classList.contains('substitute');
1536
 
 
1538
  const teamColumn = card.closest('.team-column');
1539
  let teamInfo = '';
1540
  if (teamColumn) {
1541
+ teamInfo = teamColumn.querySelector('h3').textContent.toLowerCase();
1542
  }
1543
 
1544
  // Gender check
 
1561
  }
1562
  }
1563
 
 
 
 
 
 
 
 
 
 
 
 
 
1564
  // Apply filters
1565
+ if (genderMatch && statusMatch) {
1566
+ card.style.display = 'block';
1567
  } else {
1568
+ card.style.display = 'none';
1569
  }
1570
  });
1571
  }
1572
 
1573
+ // Add event listeners to filters
1574
+ document.getElementById('genderFilter').addEventListener('change', applyFilters);
1575
+ document.getElementById('statusFilter').addEventListener('change', applyFilters);
1576
+ // Search functionality with debounce
1577
+ let searchTimeout;
1578
+ const searchInput = document.getElementById('playerSearch');
1579
+
1580
+ searchInput.addEventListener('input', function() {
1581
+ clearTimeout(searchTimeout);
1582
+ const spinner = document.getElementById('loadingSpinner');
1583
  spinner.style.display = 'block';
1584
 
 
1585
  searchTimeout = setTimeout(() => {
1586
+ performSearch(this.value);
1587
  spinner.style.display = 'none';
1588
  }, 300);
1589
  });
1590
 
1591
+ function performSearch(query) {
1592
+ const playerCards = document.querySelectorAll('.player-card');
1593
+ const searchTerm = query.toLowerCase().trim();
1594
+
1595
+ playerCards.forEach(card => {
1596
+ const playerName = card.querySelector('h4').textContent.toLowerCase();
1597
+ const playerInfo = card.querySelector('p').textContent.toLowerCase();
1598
+
1599
+ if (searchTerm === '' ||
1600
+ playerName.includes(searchTerm) ||
1601
+ playerInfo.includes(searchTerm)) {
1602
+ card.parentElement.classList.remove('hidden');
1603
+ card.style.display = 'block';
1604
+ } else {
1605
+ card.style.display = 'none';
1606
+ }
1607
+ });
1608
+ }
1609
+
1610
  // Player modal functionality
1611
  function openPlayerModal(playerId) {
1612
  const modal = document.getElementById('playerModal');
1613
  const content = document.getElementById('playerProfileContent');
1614
+ // Sample player data - in a real implementation, this would come from a database
 
1615
  let playerData;
1616
  if (playerId === 'thay-sethean') {
1617
  playerData = {
 
1706
  closePlayerModal();
1707
  }
1708
  });
1709
+
1710
+ // Mobile menu toggle
1711
  document.getElementById('menu-toggle').addEventListener('click', function() {
1712
  document.getElementById('mobile-menu').classList.remove('hidden');
1713
  });