@@ -9,6 +9,10 @@ document.addEventListener('DOMContentLoaded', function() {
99 const prevYearBtn = document . getElementById ( 'prevYear' ) ;
1010 const nextYearBtn = document . getElementById ( 'nextYear' ) ;
1111
12+ // Variable para controlar solicitudes simultáneas
13+ let currentRequest = null ;
14+ let isLoading = false ;
15+
1216 // Initialize select elements if they exist
1317 if ( ! yearSelect || ! monthSelect || ! logTable ) {
1418 console . error ( 'Required DOM elements not found' ) ;
@@ -49,15 +53,67 @@ document.addEventListener('DOMContentLoaded', function() {
4953 }
5054 yearSelect . value = currentYear ;
5155
56+ // Function to show loading state
57+ function showLoading ( ) {
58+ isLoading = true ;
59+ // Disable navigation controls
60+ prevMonthBtn . disabled = true ;
61+ nextMonthBtn . disabled = true ;
62+ prevYearBtn . disabled = true ;
63+ nextYearBtn . disabled = true ;
64+ yearSelect . disabled = true ;
65+ monthSelect . disabled = true ;
66+
67+ // Change cursor to indicate loading
68+ document . body . style . cursor = 'wait' ;
69+
70+ // Show loading indicator
71+ logTable . innerHTML = '<tr><td colspan="4" class="text-center">Loading data...</td></tr>' ;
72+ }
73+
74+ // Function to hide loading state
75+ function hideLoading ( ) {
76+ isLoading = false ;
77+ // Enable navigation controls
78+ prevMonthBtn . disabled = false ;
79+ nextMonthBtn . disabled = false ;
80+ prevYearBtn . disabled = false ;
81+ nextYearBtn . disabled = false ;
82+ yearSelect . disabled = false ;
83+ monthSelect . disabled = false ;
84+
85+ // Reset cursor
86+ document . body . style . cursor = 'default' ;
87+ }
88+
5289 // Function to load monthly logs
5390 async function loadMonthlyLogs ( ) {
91+ // Prevent multiple simultaneous requests
92+ if ( isLoading ) {
93+ console . log ( 'Already loading data, request ignored' ) ;
94+ return ;
95+ }
96+
97+ showLoading ( ) ;
98+
5499 console . log ( 'Loading monthly logs' ) ;
55100 const year = yearSelect . value ;
56101 const month = monthSelect . value ;
57102
58103 try {
59104 console . log ( `Fetching logs for ${ year } /${ month } ` ) ;
60- const response = await fetch ( `/logs/monthly/${ year } /${ month } ` ) ;
105+
106+ // Cancel any existing request
107+ if ( currentRequest ) {
108+ currentRequest . abort ( ) ;
109+ }
110+
111+ // Use fetch with AbortController
112+ const controller = new AbortController ( ) ;
113+ const signal = controller . signal ;
114+ currentRequest = controller ;
115+
116+ const response = await fetch ( `/logs/monthly/${ year } /${ month } ` , { signal } ) ;
61117
62118 if ( ! response . ok ) {
63119 throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
@@ -66,15 +122,11 @@ document.addEventListener('DOMContentLoaded', function() {
66122 const logsData = await response . json ( ) ;
67123 console . log ( 'Logs data:' , logsData ) ;
68124
69- // Clear the table
70- logTable . innerHTML = '' ;
71-
72125 // Display log entries
73126 if ( logsData . length === 0 ) {
74- const row = document . createElement ( 'tr' ) ;
75- row . innerHTML = '<td colspan="4" class="text-center">No time entries found for this month</td>' ;
76- logTable . appendChild ( row ) ;
127+ logTable . innerHTML = '<tr><td colspan="4" class="text-center">No time entries found for this month</td></tr>' ;
77128 } else {
129+ logTable . innerHTML = '' ;
78130 logsData . forEach ( log => {
79131 const row = document . createElement ( 'tr' ) ;
80132
@@ -105,13 +157,34 @@ document.addEventListener('DOMContentLoaded', function() {
105157 } ) ;
106158 }
107159 } catch ( error ) {
108- console . error ( 'Error loading logs:' , error ) ;
109- logTable . innerHTML = `<tr><td colspan="4" class="text-center text-danger">Error loading data: ${ error . message } </td></tr>` ;
160+ if ( error . name === 'AbortError' ) {
161+ console . log ( 'Fetch aborted' ) ;
162+ } else {
163+ console . error ( 'Error loading logs:' , error ) ;
164+ logTable . innerHTML = `<tr><td colspan="4" class="text-center text-danger">Error loading data: ${ error . message } </td></tr>` ;
165+ }
166+ } finally {
167+ hideLoading ( ) ;
168+ currentRequest = null ;
110169 }
111170 }
112171
113- // Navigation functions
172+ // Navigation functions with throttling
173+ function throttle ( func , delay ) {
174+ let lastCall = 0 ;
175+ return function ( ...args ) {
176+ const now = new Date ( ) . getTime ( ) ;
177+ if ( now - lastCall < delay ) {
178+ return ;
179+ }
180+ lastCall = now ;
181+ return func ( ...args ) ;
182+ } ;
183+ }
184+
114185 function navigateToPreviousMonth ( ) {
186+ if ( isLoading ) return ;
187+
115188 let month = parseInt ( monthSelect . value ) ;
116189 let year = parseInt ( yearSelect . value ) ;
117190
@@ -129,6 +202,8 @@ document.addEventListener('DOMContentLoaded', function() {
129202 }
130203
131204 function navigateToNextMonth ( ) {
205+ if ( isLoading ) return ;
206+
132207 let month = parseInt ( monthSelect . value ) ;
133208 let year = parseInt ( yearSelect . value ) ;
134209
@@ -146,6 +221,8 @@ document.addEventListener('DOMContentLoaded', function() {
146221 }
147222
148223 function navigateToPreviousYear ( ) {
224+ if ( isLoading ) return ;
225+
149226 let year = parseInt ( yearSelect . value ) ;
150227 year -- ;
151228
@@ -156,6 +233,8 @@ document.addEventListener('DOMContentLoaded', function() {
156233 }
157234
158235 function navigateToNextYear ( ) {
236+ if ( isLoading ) return ;
237+
159238 let year = parseInt ( yearSelect . value ) ;
160239 year ++ ;
161240
@@ -165,11 +244,11 @@ document.addEventListener('DOMContentLoaded', function() {
165244 }
166245 }
167246
168- // Add navigation button event listeners
169- prevMonthBtn . addEventListener ( 'click' , navigateToPreviousMonth ) ;
170- nextMonthBtn . addEventListener ( 'click' , navigateToNextMonth ) ;
171- prevYearBtn . addEventListener ( 'click' , navigateToPreviousYear ) ;
172- nextYearBtn . addEventListener ( 'click' , navigateToNextYear ) ;
247+ // Add navigation button event listeners with throttling
248+ prevMonthBtn . addEventListener ( 'click' , throttle ( navigateToPreviousMonth , 300 ) ) ;
249+ nextMonthBtn . addEventListener ( 'click' , throttle ( navigateToNextMonth , 300 ) ) ;
250+ prevYearBtn . addEventListener ( 'click' , throttle ( navigateToPreviousYear , 300 ) ) ;
251+ nextYearBtn . addEventListener ( 'click' , throttle ( navigateToNextYear , 300 ) ) ;
173252
174253 // Load data when changing year or month manually
175254 yearSelect . addEventListener ( 'change' , loadMonthlyLogs ) ;
0 commit comments