| Total Complexity | 6 |
| Complexity/F | 3 |
| Lines of Code | 55 |
| Function Count | 2 |
| Duplicated Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
| 1 | import { currentTranslations } from '../services/language'; |
||
| 2 | |||
| 3 | let toastTimeout: NodeJS.Timeout | null = null; |
||
| 4 | let clickCount = 0; |
||
| 5 | let clickResetTimeout: NodeJS.Timeout | null = null; |
||
| 6 | |||
| 7 | export function showDisabledBoxToast(): void { |
||
| 8 | clickCount++; |
||
| 9 | |||
| 10 | if (clickResetTimeout) { |
||
| 11 | clearTimeout(clickResetTimeout); |
||
| 12 | } |
||
| 13 | clickResetTimeout = setTimeout(() => { |
||
| 14 | clickCount = 0; |
||
| 15 | }, 2000); |
||
| 16 | |||
| 17 | // Show toast only after 2+ clicks |
||
| 18 | if (clickCount >= 2) { |
||
| 19 | showToast(currentTranslations.disabledBoxMessage); |
||
| 20 | clickCount = 0; |
||
| 21 | } |
||
| 22 | } |
||
| 23 | |||
| 24 | function showToast(message: string): void { |
||
| 25 | const existingToast = document.getElementById('toast-notification'); |
||
| 26 | if (existingToast) { |
||
| 27 | existingToast.remove(); |
||
| 28 | } |
||
| 29 | |||
| 30 | if (toastTimeout) { |
||
| 31 | clearTimeout(toastTimeout); |
||
| 32 | } |
||
| 33 | |||
| 34 | const toast = document.createElement('div'); |
||
| 35 | toast.id = 'toast-notification'; |
||
| 36 | toast.className = 'toast'; |
||
| 37 | toast.textContent = message; |
||
| 38 | toast.setAttribute('role', 'alert'); |
||
| 39 | toast.setAttribute('aria-live', 'polite'); |
||
| 40 | |||
| 41 | document.body.appendChild(toast); |
||
| 42 | |||
| 43 | // Use setTimeout instead of requestAnimationFrame for better testability |
||
| 44 | setTimeout(() => { |
||
| 45 | toast.classList.add('show'); |
||
| 46 | }, 0); |
||
| 47 | |||
| 48 | toastTimeout = setTimeout(() => { |
||
| 49 | toast.classList.remove('show'); |
||
| 50 | setTimeout(() => { |
||
| 51 | toast.remove(); |
||
| 52 | }, 300); // Wait for fade out animation |
||
| 53 | }, 3000); |
||
| 54 | } |
||
| 55 |