Spaces:
Sleeping
Sleeping
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>
|