File size: 5,617 Bytes
a3cafd5
 
 
 
 
 
 
 
44f6b36
a3cafd5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<!DOCTYPE html>
<html lang="en" x-data="{ theme: localStorage.getItem('theme') || 'dark' }" :data-theme="theme">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{% block title %}TasteEngine{% endblock %}</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
  <link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
  <link rel="stylesheet" href="/static/css/style.css">
  <script src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js" defer></script>
  <script src="https://unpkg.com/htmx.org@2.0.3/dist/htmx.min.js" defer></script>
  <script src="https://unpkg.com/lucide@0.468.0/dist/umd/lucide.js" defer></script>
  {% block head_extra %}{% endblock %}
</head>
<body data-page="{{ active_page|default('home') }}">
  <div class="ambient-bg">
    <div class="ambient-blob ambient-blob-1"></div>
    <div class="ambient-blob ambient-blob-2"></div>
    <div class="ambient-blob ambient-blob-3"></div>
  </div>

  {% from "macros.html" import nav %}
  {{ nav(active_page|default('home')) }}

  <div class="container">
    {% block breadcrumb %}{% endblock %}
    {% block content %}{% endblock %}
  </div>

  <div id="toastContainer" class="toast-container"></div>

  <script>
    function toggleTheme() {
      const html = document.documentElement;
      const current = html.getAttribute('data-theme') || 'dark';
      const next = current === 'dark' ? 'light' : 'dark';
      html.setAttribute('data-theme', next);
      localStorage.setItem('theme', next);
      document.getElementById('themeIcon').textContent = next === 'dark' ? 'πŸŒ™' : 'β˜€οΈ';
    }

    function toast(message, type = 'info', duration = 3000) {
      const container = document.getElementById('toastContainer');
      const icons = { success: 'βœ“', error: 'βœ•', info: 'β„Ή', warning: '⚠' };
      const t = document.createElement('div');
      t.className = `toast toast-${type}`;
      t.innerHTML = `
        <span class="toast-icon">${icons[type] || 'β„Ή'}</span>
        <span>${message}</span>
        <button class="toast-close" onclick="this.parentElement.remove()">Γ—</button>
      `;
      container.appendChild(t);
      setTimeout(() => { if (t.parentElement) t.remove(); }, duration);
    }

    function copyToClipboard(text) {
      navigator.clipboard.writeText(text).then(() => toast('Copied!', 'success'));
    }

    document.addEventListener('DOMContentLoaded', function() {
      const theme = localStorage.getItem('theme') || 'dark';
      document.documentElement.setAttribute('data-theme', theme);
      document.getElementById('themeIcon').textContent = theme === 'dark' ? 'πŸŒ™' : 'β˜€οΈ';
    });

    document.addEventListener('htmx:beforeRequest', function() {
      document.querySelectorAll('.btn.htmx-request').forEach(function(btn) {
        btn.disabled = true;
      });
    });
    document.addEventListener('htmx:afterRequest', function() {
      document.querySelectorAll('.btn.htmx-request').forEach(function(btn) {
        btn.disabled = false;
      });
    });
    document.addEventListener('htmx:responseError', function(evt) {
      toast('Request failed: ' + (evt.detail.xhr.statusText || 'Unknown error'), 'error');
    });

    function getCategoryIcon(category) {
      const icons = {
        'Electronics': 'πŸ’»',
        'Clothing': 'πŸ‘•',
        'Home & Kitchen': '🏠',
        'Books': 'πŸ“š',
        'Sports': '⚽',
        'Beauty': 'πŸ’„',
        'Toys': '🧸',
        'Automotive': 'πŸš—'
      };
      return icons[category] || 'πŸ“¦';
    }

    function stars(rating) {
      const f = Math.floor(rating);
      return 'β˜…'.repeat(f) + 'β˜†'.repeat(5 - f);
    }

    function syncScroll(source) {
      const container = source.closest('.synced-scroll');
      if (!container) return;
      const pct = source.scrollTop / (source.scrollHeight - source.clientHeight);
      container.querySelectorAll('.compare-column').forEach(col => {
        if (col !== source) col.scrollTop = pct * (col.scrollHeight - col.clientHeight);
      });
    }

    document.addEventListener('keydown', function(e) {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT' || e.target.tagName === 'TEXTAREA') return;
      const page = document.body.getAttribute('data-page');
      if (e.key === '1' && page === 'recommend') {
        const btn = document.querySelector('.btn-approach[data-approach="cf"]');
        if (btn) { btn.click(); toast('Selected Collaborative Filtering', 'info', 1500); }
      }
      if (e.key === '2' && page === 'recommend') {
        const btn = document.querySelector('.btn-approach[data-approach="content"]');
        if (btn) { btn.click(); toast('Selected Content-Based', 'info', 1500); }
      }
      if (e.key === '3' && page === 'recommend') {
        const btn = document.querySelector('.btn-approach[data-approach="knowledge"]');
        if (btn) { btn.click(); toast('Selected Knowledge-Based', 'info', 1500); }
      }
      if ((e.key === 'r' || e.key === 'Enter') && page === 'recommend') {
        const genBtn = document.querySelector('.btn-primary');
        if (genBtn && !genBtn.disabled) genBtn.click();
      }
      if (e.key === 'e' && page !== 'evaluate') { window.location.href = '/evaluate'; }
      if (e.key === 'h' && page !== 'home') { window.location.href = '/'; }
    });

    {% block page_globals %}{% endblock %}
  </script>

  {% block scripts %}{% endblock %}
</body>
</html>