1- const API_BASE = 'http://localhost:8082 /api' ;
1+ const API_BASE = 'http://localhost:8090 /api' ;
22
33const todoForm = document . getElementById ( 'todo-form' ) ;
44const todoInput = document . getElementById ( 'todo-input' ) ;
5+ const searchInput = document . getElementById ( 'search-input' ) ;
6+ const filterButtons = document . querySelectorAll ( '.filter-btn' ) ;
57const todoList = document . getElementById ( 'todo-list' ) ;
68const statusDiv = document . getElementById ( 'status' ) ;
7- const initBtn = document . getElementById ( 'init-btn' ) ;
9+
10+ let currentFilter = 'all' ;
811
912// Show status message
1013function showStatus ( message , isError = false ) {
@@ -30,25 +33,15 @@ async function api(endpoint, options = {}) {
3033 return res . json ( ) ;
3134}
3235
33- // Initialize database
34- async function initDatabase ( ) {
35- try {
36- initBtn . disabled = true ;
37- await api ( '/init' , { method : 'POST' } ) ;
38- showStatus ( 'Database initialized!' ) ;
39- loadTodos ( ) ;
40- } catch ( err ) {
41- showStatus ( 'Init failed: ' + err . message , true ) ;
42- } finally {
43- initBtn . disabled = false ;
44- }
45- }
46-
47- // Load all todos
48- async function loadTodos ( ) {
36+ // Load todos with optional search and filter
37+ async function loadTodos ( search = '' , filter = 'all' ) {
4938 try {
5039 todoList . classList . add ( 'loading' ) ;
51- const todos = await api ( '/todos' ) ;
40+ const params = new URLSearchParams ( ) ;
41+ if ( search ) params . set ( 'q' , search ) ;
42+ if ( filter && filter !== 'all' ) params . set ( 'filter' , filter ) ;
43+ const query = params . toString ( ) ? `?${ params } ` : '' ;
44+ const todos = await api ( `/todos${ query } ` ) ;
5245 renderTodos ( todos ) ;
5346 } catch ( err ) {
5447 showStatus ( 'Failed to load: ' + err . message , true ) ;
@@ -84,7 +77,7 @@ async function addTodo(title) {
8477 body : JSON . stringify ( { title } ) ,
8578 } ) ;
8679 todoInput . value = '' ;
87- loadTodos ( ) ;
80+ loadTodos ( searchInput . value , currentFilter ) ;
8881 } catch ( err ) {
8982 showStatus ( 'Failed to add: ' + err . message , true ) ;
9083 } finally {
@@ -101,31 +94,51 @@ async function toggleTodo(id, completed) {
10194 method : 'PUT' ,
10295 body : JSON . stringify ( { ...todo , completed } ) ,
10396 } ) ;
104- loadTodos ( ) ;
97+ loadTodos ( searchInput . value , currentFilter ) ;
10598 } catch ( err ) {
10699 showStatus ( 'Failed to update: ' + err . message , true ) ;
107- loadTodos ( ) ;
100+ loadTodos ( searchInput . value , currentFilter ) ;
108101 }
109102}
110103
111104// Delete todo
112105async function deleteTodo ( id ) {
113106 try {
114107 await api ( `/todos/${ id } ` , { method : 'DELETE' } ) ;
115- loadTodos ( ) ;
108+ loadTodos ( searchInput . value , currentFilter ) ;
116109 } catch ( err ) {
117110 showStatus ( 'Failed to delete: ' + err . message , true ) ;
118111 }
119112}
120113
114+ // Debounce helper
115+ function debounce ( fn , delay ) {
116+ let timeout ;
117+ return ( ...args ) => {
118+ clearTimeout ( timeout ) ;
119+ timeout = setTimeout ( ( ) => fn ( ...args ) , delay ) ;
120+ } ;
121+ }
122+
121123// Event listeners
122124todoForm . addEventListener ( 'submit' , ( e ) => {
123125 e . preventDefault ( ) ;
124126 const title = todoInput . value . trim ( ) ;
125127 if ( title ) addTodo ( title ) ;
126128} ) ;
127129
128- initBtn . addEventListener ( 'click' , initDatabase ) ;
130+ searchInput . addEventListener ( 'input' , debounce ( ( e ) => {
131+ loadTodos ( e . target . value , currentFilter ) ;
132+ } , 300 ) ) ;
133+
134+ filterButtons . forEach ( btn => {
135+ btn . addEventListener ( 'click' , ( ) => {
136+ filterButtons . forEach ( b => b . classList . remove ( 'active' ) ) ;
137+ btn . classList . add ( 'active' ) ;
138+ currentFilter = btn . dataset . filter ;
139+ loadTodos ( searchInput . value , currentFilter ) ;
140+ } ) ;
141+ } ) ;
129142
130143// Initial load
131144loadTodos ( ) ;
0 commit comments