1- import { loadProjects } from ' ./projects.js' ;
1+ import { loadProjects } from " ./projects.js" ;
22
3- const searchEl = document . getElementById ( ' search' ) ;
4- const categoryEl = document . getElementById ( ' categoryFilter' ) ;
5- const gridEl = document . getElementById ( ' projects' ) ;
3+ const searchEl = document . getElementById ( " search" ) ;
4+ const categoryEl = document . getElementById ( " categoryFilter" ) ;
5+ const gridEl = document . getElementById ( " projects" ) ;
66
77let allProjects = [ ] ;
88
99function render ( projects ) {
10- gridEl . innerHTML = '' ;
11- if ( ! projects . length ) {
12- gridEl . innerHTML = ' <p>No projects found.</p>' ;
13- return ;
14- }
10+ gridEl . innerHTML = "" ;
11+ if ( ! projects . length ) {
12+ gridEl . innerHTML = " <p>No projects found.</p>" ;
13+ return ;
14+ }
1515
16- for ( const p of projects ) {
17- const card = document . createElement ( ' article' ) ;
18- card . className = ' card' ;
19- card . innerHTML = `
16+ for ( const p of projects ) {
17+ const card = document . createElement ( " article" ) ;
18+ card . className = " card" ;
19+ card . innerHTML = `
2020 <h3>${ p . title } </h3>
2121 <p>${ p . description } </p>
2222 <div class="meta">
2323 <span>${ p . category } </span>
24- ${ p . difficulty ? `<span>Level: ${ p . difficulty } </span>` : '' }
24+ ${ p . difficulty ? `<span>Level: ${ p . difficulty } </span>` : "" }
2525 </div>
2626 <a href="${ p . href } ">Open project</a>
2727 ` ;
28- gridEl . appendChild ( card ) ;
29- }
28+ gridEl . appendChild ( card ) ;
29+ }
3030}
3131
3232function applyFilters ( ) {
33- const q = searchEl . value . trim ( ) . toLowerCase ( ) ;
34- const cat = categoryEl . value ;
35- const filtered = allProjects . filter ( p => {
36- const inCat = cat === 'all' || p . categoryKey === cat ;
37- const inText = ! q || p . title . toLowerCase ( ) . includes ( q ) || p . description . toLowerCase ( ) . includes ( q ) ;
38- return inCat && inText ;
39- } ) ;
40- render ( filtered ) ;
33+ const q = searchEl . value . trim ( ) . toLowerCase ( ) ;
34+ const cat = categoryEl . value ;
35+ const filtered = allProjects . filter ( ( p ) => {
36+ const inCat = cat === "all" || p . categoryKey === cat ;
37+ const inText =
38+ ! q ||
39+ p . title . toLowerCase ( ) . includes ( q ) ||
40+ p . description . toLowerCase ( ) . includes ( q ) ;
41+ return inCat && inText ;
42+ } ) ;
43+ render ( filtered ) ;
4144}
4245
4346( async function init ( ) {
44- try {
45- allProjects = await loadProjects ( ) ;
46- render ( allProjects ) ;
47- searchEl . addEventListener ( 'input' , applyFilters ) ;
48- categoryEl . addEventListener ( 'change' , applyFilters ) ;
49- } catch ( err ) {
50- console . error ( 'Failed to load projects' , err ) ;
51- gridEl . innerHTML = '<p>Failed to load projects list.</p>' ;
52- }
47+ try {
48+ allProjects = await loadProjects ( ) ;
49+ render ( allProjects ) ;
50+
51+ searchEl . addEventListener ( "input" , applyFilters ) ;
52+ categoryEl . addEventListener ( "change" , applyFilters ) ;
53+ } catch ( err ) {
54+ console . error ( "Failed to load projects" , err ) ;
55+ gridEl . innerHTML = "<p>Failed to load projects list.</p>" ;
56+ }
5357} ) ( ) ;
5458
55-
56- const themeToggle = document . getElementById ( 'themeToggle' ) ;
57- const body = document . body ;
59+ const themeToggle = document . getElementById ( "themeToggle" ) ;
60+ const body = document . body ;
61+
62+ const currentTheme = localStorage . getItem ( "theme" ) || "light" ;
63+ if ( currentTheme === "dark" ) {
64+ body . classList . add ( "dark-mode" ) ;
65+ }
5866
59-
60- const currentTheme = localStorage . getItem ( 'theme' ) || 'light' ;
61- if ( currentTheme === 'dark' ) {
62- body . classList . add ( 'dark-mode' ) ;
63- }
67+ themeToggle . addEventListener ( "click" , ( ) => {
68+ body . classList . toggle ( "dark-mode" ) ;
6469
65- themeToggle . addEventListener ( 'click' , ( ) => {
66- body . classList . toggle ( 'dark-mode' ) ;
67-
68-
69- const theme = body . classList . contains ( 'dark-mode' ) ? 'dark' : 'light' ;
70- localStorage . setItem ( 'theme' , theme ) ;
71- } ) ;
70+ const theme = body . classList . contains ( "dark-mode" ) ? "dark" : "light" ;
71+ localStorage . setItem ( "theme" , theme ) ;
72+ } ) ;
73+ document . addEventListener ( "keydown" , ( e ) => {
74+ if ( e . key . toLowerCase ( ) == "x" ) {
75+ e . preventDefault ( ) ;
76+ searchEl . focus ( ) ;
77+ }
78+ if ( e . key === "Escape" ) {
79+ e . preventDefault ( ) ;
80+ searchEl . blur ( ) ;
81+ }
82+ } ) ;
0 commit comments