File size: 3,726 Bytes
7484271
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// ================================================
// SGE — Error System + Sound Engine
// ================================================

const ERRORS = {
  'err-001': 'Conexiune Firebase eșuată. Verifică internetul.',
  'err-002': 'Elevul nu a fost găsit în baza de date.',
  'err-003': 'Cod VPass incorect.',
  'err-004': 'Cont neînregistrat. Apasă ÎNREGISTRARE.',
  'err-005': 'Cerere de înregistrare deja în așteptare.',
  'err-006': 'Cod de confirmare expirat. Solicită unul nou.',
  'err-007': 'Cod de confirmare incorect.',
  'err-008': 'Parola trebuie să aibă minimum 6 caractere.',
  'err-009': 'Upload eșuat — eroare rețea.',
  'err-010': 'Fișierul depășește limita de 50MB.',
  'err-011': 'Niciun fișier selectat.',
  'err-012': 'Selectează o materie înainte de upload.',
  'err-013': 'Sesiune expirată. Reconectează-te.',
  'err-014': 'Acces neautorizat.',
  'err-015': 'Timeout server. Încearcă din nou.',
  'err-016': 'B2 autentificare eșuată.',
  'err-017': 'B2 upload URL indisponibil.',
  'err-018': 'Listare fișiere eșuată.',
  'err-019': 'Ștergere fișier eșuată.',
  'err-020': 'Parolă administrator incorectă.',
  'err-021': 'Câmpuri obligatorii incomplete.',
  'err-022': 'PIN-ul trebuie să fie exact 6 cifre.',
  'err-023': 'Elev deja înregistrat. Folosește login normal.',
  'err-024': 'Cerere respinsă de administrator.',
  'err-025': 'Eroare scriere Firestore.',
  'err-026': 'Eroare citire Firestore.',
  'err-027': 'Eroare rețea generală.',
  'err-028': 'Notificare negăsită.',
  'err-029': 'Codul de confirmare trebuie să fie 4 cifre.',
  'err-030': 'Sesiune signup expirată. Revino la login.',
};

// Warm ambient error sound — 220Hz sine wave, soft fade
let _audioCtx = null;
function playErrorSound() {
  try {
    if (!_audioCtx) _audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const ctx = _audioCtx;

    // Two oscillators for warm, mysterious feel
    const osc1 = ctx.createOscillator();
    const osc2 = ctx.createOscillator();
    const gain1 = ctx.createGain();
    const gain2 = ctx.createGain();
    const master = ctx.createGain();

    osc1.type = 'sine';
    osc1.frequency.setValueAtTime(196, ctx.currentTime); // G3
    osc1.frequency.exponentialRampToValueAtTime(174, ctx.currentTime + 0.6); // F3

    osc2.type = 'sine';
    osc2.frequency.setValueAtTime(293, ctx.currentTime); // D4 — minor feel
    osc2.frequency.exponentialRampToValueAtTime(261, ctx.currentTime + 0.6);

    // Envelope: soft attack, slow decay
    master.gain.setValueAtTime(0, ctx.currentTime);
    master.gain.linearRampToValueAtTime(0.12, ctx.currentTime + 0.08);
    master.gain.linearRampToValueAtTime(0.06, ctx.currentTime + 0.35);
    master.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.9);

    gain1.gain.value = 0.7;
    gain2.gain.value = 0.3;

    osc1.connect(gain1); gain1.connect(master);
    osc2.connect(gain2); gain2.connect(master);
    master.connect(ctx.destination);

    osc1.start(ctx.currentTime);
    osc2.start(ctx.currentTime);
    osc1.stop(ctx.currentTime + 1);
    osc2.stop(ctx.currentTime + 1);
  } catch(e) { /* silently fail on browsers without AudioContext */ }
}

// Show error with code, sound, and description
function showError(containerId, code, extraMsg) {
  playErrorSound();
  const el = document.getElementById(containerId);
  if (!el) return;
  const msg = ERRORS[code] || 'Eroare necunoscută.';
  el.innerHTML = `<span class="err-code">${code}</span> ${msg}${extraMsg ? ' — ' + extraMsg : ''}`;
  el.classList.add('show');
}

function hideError(containerId) {
  const el = document.getElementById(containerId);
  if (el) el.classList.remove('show');
}