@@ -355,10 +355,11 @@ <h3 class="card-title" title="${item.title}">${item.title}</h3>
355355 }
356356
357357 // Filter and display items
358- function filterAndDisplayItems ( resetPage = true ) {
358+ let isInitialLoad = true ;
359+
360+ function filterAndDisplayItems ( resetPage = true , updateHistory = true ) {
359361 if ( resetPage ) currentPage = 1 ;
360362
361- // Apply filters
362363 let filtered = [ ...allItems ] ;
363364
364365 if ( currentFilter === 'game' || currentFilter === 'tool' ) {
@@ -371,8 +372,8 @@ <h3 class="card-title" title="${item.title}">${item.title}</h3>
371372 filtered = filtered . filter ( item => isNewItem ( item ) ) ;
372373 }
373374
374-
375375 statsContainer . style . display = currentCategory === 'all' && currentFilter === 'all' ? 'flex' : 'none' ;
376+
376377 if ( currentCategory !== 'all' ) {
377378 filtered = filtered . filter ( item => getCategory ( item ) === currentCategory ) ;
378379 }
@@ -388,54 +389,144 @@ <h3 class="card-title" title="${item.title}">${item.title}</h3>
388389 clearSearch . style . display = 'none' ;
389390 }
390391
391- // Apply sorting
392392 filtered = sortItems ( filtered , currentSort ) ;
393-
394- // Update title
395393 updateTitle ( filtered ) ;
396394
397- // Check if no results
395+ if ( updateHistory && ! isInitialLoad ) {
396+ const params = new URLSearchParams ( ) ;
397+ if ( currentFilter !== 'all' ) params . set ( 'filter' , currentFilter ) ;
398+ if ( currentCategory !== 'all' ) params . set ( 'category' , currentCategory ) ;
399+ if ( currentSort !== 'featured' ) params . set ( 'sort' , currentSort ) ;
400+ if ( currentSearch ) params . set ( 'search' , currentSearch ) ;
401+ if ( isListView ) params . set ( 'view' , 'list' ) ;
402+
403+ const url = params . toString ( ) ? `?${ params . toString ( ) } ` : window . location . pathname ;
404+ history . pushState ( { filter : currentFilter , category : currentCategory , sort : currentSort ,
405+ search : currentSearch , view : isListView ? 'list' : 'grid' , page : currentPage } , '' , url ) ;
406+ }
407+
398408 if ( filtered . length === 0 ) {
399409 mainGrid . innerHTML = '' ;
400410 emptyState . style . display = 'block' ;
401411 return ;
402412 }
403413
404- // Show results
405414 emptyState . style . display = 'none' ;
406415 displayedItems = filtered ;
407416
408- // Paginate
409417 const end = currentPage * itemsPerPage ;
410418 const itemsToShow = filtered . slice ( 0 , end ) ;
411419
412- // Set view class
413420 mainGrid . className = isListView ? 'list-view' : 'grid-view' ;
414-
415- // Render cards
416421 mainGrid . innerHTML = itemsToShow . map ( createCard ) . join ( '' ) ;
417422
418- // Set up read more buttons
419423 document . querySelectorAll ( '.read-more' ) . forEach ( btn => {
420424 btn . addEventListener ( 'click' , function ( ) {
421- const id = this . getAttribute ( 'data-id' ) ;
422425 const descContainer = this . previousElementSibling ;
423426 descContainer . classList . toggle ( 'truncated' ) ;
424427 this . textContent = descContainer . classList . contains ( 'truncated' ) ? 'Read more' : 'Read less' ;
425428 } ) ;
426429 } ) ;
427430
428- // make full card clickable
429431 document . querySelectorAll ( '.card' ) . forEach ( card => {
430432 card . addEventListener ( 'click' , e => {
431- if ( ! e . target . closest ( '.read-more' ) ) {
432- console . log ( e . currentTarget ) ;
433- card . querySelector ( 'a' ) . click ( ) ;
434- }
433+ if ( ! e . target . closest ( '.read-more' ) ) card . querySelector ( 'a' ) . click ( ) ;
435434 } ) ;
436- } )
435+ } ) ;
436+ }
437+
438+ async function fetchData ( ) {
439+ try {
440+ const [ gamesResponse , toolsResponse ] = await Promise . all ( [
441+ fetch ( 'data/games.json' ) ,
442+ fetch ( 'data/tools.json' )
443+ ] ) ;
444+
445+ const gamesData = await gamesResponse . json ( ) ;
446+ const toolsData = await toolsResponse . json ( ) ;
447+
448+ allItems = [ ...gamesData , ...toolsData ] ;
449+ updateStats ( ) ;
450+
451+ const params = new URLSearchParams ( window . location . search ) ;
452+
453+ if ( params . get ( 'filter' ) ) {
454+ currentFilter = params . get ( 'filter' ) ;
455+ filterButtons . forEach ( btn => {
456+ btn . classList . toggle ( 'active' , btn . getAttribute ( 'data-filter' ) === currentFilter ) ;
457+ } ) ;
458+ }
459+
460+ if ( params . get ( 'category' ) ) {
461+ currentCategory = params . get ( 'category' ) ;
462+ categoryFilter . value = currentCategory ;
463+ }
464+
465+ if ( params . get ( 'sort' ) ) {
466+ currentSort = params . get ( 'sort' ) ;
467+ sortSelect . value = currentSort ;
468+ }
469+
470+ if ( params . get ( 'search' ) ) {
471+ currentSearch = params . get ( 'search' ) ;
472+ searchInput . value = currentSearch ;
473+ }
474+
475+ if ( params . get ( 'view' ) === 'list' ) {
476+ isListView = true ;
477+ listViewBtn . classList . add ( 'active' ) ;
478+ gridViewBtn . classList . remove ( 'active' ) ;
479+ }
480+
481+ filterAndDisplayItems ( true , false ) ;
482+
483+ const stateParams = new URLSearchParams ( ) ;
484+ if ( currentFilter !== 'all' ) stateParams . set ( 'filter' , currentFilter ) ;
485+ if ( currentCategory !== 'all' ) stateParams . set ( 'category' , currentCategory ) ;
486+ if ( currentSort !== 'featured' ) stateParams . set ( 'sort' , currentSort ) ;
487+ if ( currentSearch ) stateParams . set ( 'search' , currentSearch ) ;
488+ if ( isListView ) stateParams . set ( 'view' , 'list' ) ;
489+
490+ const url = stateParams . toString ( ) ? `?${ stateParams . toString ( ) } ` : window . location . pathname ;
491+ history . replaceState ( { filter : currentFilter , category : currentCategory , sort : currentSort ,
492+ search : currentSearch , view : isListView ? 'list' : 'grid' , page : currentPage } , '' , url ) ;
493+
494+ isInitialLoad = false ;
495+ } catch ( error ) {
496+ console . error ( 'Error fetching data:' , error ) ;
497+ mainGrid . innerHTML = `<div class="empty-state"><i class="fas fa-exclamation-circle"></i><h3>Error loading data</h3><p>Please try again later</p></div>` ;
498+ }
437499 }
438500
501+ window . addEventListener ( 'popstate' , function ( event ) {
502+ if ( event . state ) {
503+ currentFilter = event . state . filter || 'all' ;
504+ currentCategory = event . state . category || 'all' ;
505+ currentSort = event . state . sort || 'featured' ;
506+ currentSearch = event . state . search || '' ;
507+ isListView = event . state . view === 'list' ;
508+ currentPage = event . state . page || 1 ;
509+
510+ filterButtons . forEach ( btn => {
511+ btn . classList . toggle ( 'active' , btn . getAttribute ( 'data-filter' ) === currentFilter ) ;
512+ } ) ;
513+
514+ categoryFilter . value = currentCategory ;
515+ sortSelect . value = currentSort ;
516+ searchInput . value = currentSearch ;
517+
518+ if ( isListView ) {
519+ listViewBtn . classList . add ( 'active' ) ;
520+ gridViewBtn . classList . remove ( 'active' ) ;
521+ } else {
522+ gridViewBtn . classList . add ( 'active' ) ;
523+ listViewBtn . classList . remove ( 'active' ) ;
524+ }
525+
526+ filterAndDisplayItems ( false , false ) ;
527+ }
528+ } ) ;
529+
439530 // Sort items
440531 function sortItems ( items , sortMethod ) {
441532 switch ( sortMethod ) {
@@ -506,30 +597,6 @@ <h3 class="card-title" title="${item.title}">${item.title}</h3>
506597 window . location . href = randomItem . url ;
507598 }
508599
509- // Fetch data
510- async function fetchData ( ) {
511- try {
512- const [ gamesResponse , toolsResponse ] = await Promise . all ( [
513- fetch ( 'data/games.json' ) ,
514- fetch ( 'data/tools.json' )
515- ] ) ;
516-
517- const gamesData = await gamesResponse . json ( ) ;
518- const toolsData = await toolsResponse . json ( ) ;
519-
520- allItems = [ ...gamesData , ...toolsData ] ;
521-
522- // Update statistics
523- updateStats ( ) ;
524-
525- // Initial display - featured items first, then newest
526- filterAndDisplayItems ( ) ;
527- } catch ( error ) {
528- console . error ( 'Error fetching data:' , error ) ;
529- mainGrid . innerHTML = `<div class="empty-state"><i class="fas fa-exclamation-circle"></i><h3>Error loading data</h3><p>Please try again later</p></div>` ;
530- }
531- }
532-
533600 // Event listeners
534601 searchInput . addEventListener ( 'input' , function ( ) {
535602 currentSearch = this . value . trim ( ) ;
0 commit comments