- Mutare și reorganizare foldere proiecte - Actualizare path-uri în TOOLS.md - Sincronizare configurații agenți - 79 fișiere actualizate
498 lines
17 KiB
HTML
498 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ro">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Echo · Grup Sprijin</title>
|
|
<link rel="stylesheet" href="common.css">
|
|
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
|
<style>
|
|
.main {
|
|
max-width: 1000px;
|
|
margin: 0 auto;
|
|
padding: var(--space-5);
|
|
}
|
|
|
|
.page-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: var(--space-6);
|
|
flex-wrap: wrap;
|
|
gap: var(--space-4);
|
|
}
|
|
|
|
.page-title {
|
|
font-size: var(--text-xl);
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.search-bar input {
|
|
width: 250px;
|
|
}
|
|
|
|
.filters {
|
|
display: flex;
|
|
gap: var(--space-2);
|
|
flex-wrap: wrap;
|
|
margin-bottom: var(--space-4);
|
|
}
|
|
|
|
.filter-btn {
|
|
padding: var(--space-2) var(--space-3);
|
|
border-radius: var(--radius-md);
|
|
border: 1px solid var(--border);
|
|
background: var(--bg-surface);
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
font-size: var(--text-sm);
|
|
transition: all var(--transition-fast);
|
|
}
|
|
|
|
.filter-btn:hover {
|
|
background: var(--bg-surface-hover);
|
|
}
|
|
|
|
.filter-btn.active {
|
|
background: var(--accent);
|
|
color: white;
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.items-grid {
|
|
display: grid;
|
|
gap: var(--space-4);
|
|
}
|
|
|
|
.item-card {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--space-4);
|
|
cursor: pointer;
|
|
transition: all var(--transition-fast);
|
|
}
|
|
|
|
.item-card:hover {
|
|
border-color: var(--accent);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.item-card.used {
|
|
opacity: 0.7;
|
|
border-left: 3px solid var(--success);
|
|
}
|
|
|
|
.item-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: var(--space-2);
|
|
}
|
|
|
|
.item-title {
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.item-type {
|
|
font-size: var(--text-xs);
|
|
padding: var(--space-1) var(--space-2);
|
|
border-radius: var(--radius-sm);
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.item-type.exercitiu { background: rgba(59, 130, 246, 0.2); color: #3b82f6; }
|
|
.item-type.meditatie { background: rgba(139, 92, 246, 0.2); color: #8b5cf6; }
|
|
.item-type.intrebare { background: rgba(20, 184, 166, 0.2); color: #14b8a6; }
|
|
.item-type.reflectie { background: rgba(249, 115, 22, 0.2); color: #f97316; }
|
|
|
|
.item-tags {
|
|
display: flex;
|
|
gap: var(--space-1);
|
|
flex-wrap: wrap;
|
|
margin-top: var(--space-2);
|
|
}
|
|
|
|
.tag {
|
|
font-size: var(--text-xs);
|
|
padding: 2px 6px;
|
|
background: var(--bg-surface-hover);
|
|
border-radius: var(--radius-sm);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.item-used {
|
|
font-size: var(--text-xs);
|
|
color: var(--success);
|
|
margin-top: var(--space-2);
|
|
}
|
|
|
|
/* Modal */
|
|
.modal {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0,0,0,0.7);
|
|
z-index: 1000;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.modal.open {
|
|
display: flex;
|
|
}
|
|
|
|
.modal-content {
|
|
background: #1a1a2e;
|
|
border-radius: var(--radius-lg);
|
|
max-width: 600px;
|
|
width: 90%;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
padding: var(--space-5);
|
|
box-shadow: 0 20px 50px rgba(0,0,0,0.5);
|
|
}
|
|
|
|
[data-theme="light"] .modal-content {
|
|
background: #ffffff;
|
|
}
|
|
|
|
.modal-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: var(--space-4);
|
|
}
|
|
|
|
.modal-title {
|
|
font-size: var(--text-lg);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.modal-close {
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
padding: var(--space-1);
|
|
}
|
|
|
|
.modal-body {
|
|
color: var(--text-secondary);
|
|
line-height: 1.6;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.modal-actions {
|
|
margin-top: var(--space-4);
|
|
display: flex;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.btn {
|
|
padding: var(--space-2) var(--space-4);
|
|
border-radius: var(--radius-md);
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--accent);
|
|
color: white;
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: var(--bg-surface);
|
|
color: var(--text-secondary);
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.stats {
|
|
display: flex;
|
|
gap: var(--space-4);
|
|
margin-bottom: var(--space-4);
|
|
font-size: var(--text-sm);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.error-msg {
|
|
background: rgba(239, 68, 68, 0.1);
|
|
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
color: #ef4444;
|
|
padding: var(--space-4);
|
|
border-radius: var(--radius-md);
|
|
text-align: center;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="header">
|
|
<a href="index.html" class="logo">
|
|
<i data-lucide="circle-dot"></i>
|
|
Echo
|
|
</a>
|
|
<nav class="nav">
|
|
<a href="index.html" class="nav-item">
|
|
<i data-lucide="layout-list"></i>
|
|
<span>Tasks</span>
|
|
</a>
|
|
<a href="notes.html" class="nav-item">
|
|
<i data-lucide="file-text"></i>
|
|
<span>Notes</span>
|
|
</a>
|
|
<a href="files.html" class="nav-item">
|
|
<i data-lucide="folder"></i>
|
|
<span>Files</span>
|
|
</a>
|
|
<a href="grup-sprijin.html" class="nav-item active">
|
|
<i data-lucide="heart-handshake"></i>
|
|
<span>Grup</span>
|
|
</a>
|
|
<button class="theme-toggle" onclick="toggleTheme()" title="Schimbă tema">
|
|
<i data-lucide="sun" id="themeIcon"></i>
|
|
</button>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="main">
|
|
<div class="page-header">
|
|
<h1 class="page-title">Grup Sprijin - Exerciții & Întrebări</h1>
|
|
<div class="search-bar">
|
|
<input type="text" class="input" placeholder="Caută..." id="searchInput">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stats" id="stats"></div>
|
|
|
|
<div class="fise-section" id="fiseSection" style="margin-bottom: var(--space-5); display: none;">
|
|
<h2 style="font-size: var(--text-lg); margin-bottom: var(--space-3); color: var(--text-primary);">Fișe întâlniri</h2>
|
|
<div class="fise-list" id="fiseList" style="display: flex; gap: var(--space-2); flex-wrap: wrap;"></div>
|
|
</div>
|
|
|
|
<div class="filters" id="filters">
|
|
<button class="filter-btn active" data-filter="all">Toate</button>
|
|
<button class="filter-btn" data-filter="exercitiu">Exerciții</button>
|
|
<button class="filter-btn" data-filter="meditatie">Meditații</button>
|
|
<button class="filter-btn" data-filter="intrebare">Întrebări</button>
|
|
<button class="filter-btn" data-filter="reflectie">Reflecții</button>
|
|
<button class="filter-btn" data-filter="unused">Nefolosite</button>
|
|
<button class="filter-btn" data-filter="used">Folosite</button>
|
|
</div>
|
|
|
|
<div class="items-grid" id="itemsGrid">
|
|
<p>Se încarcă...</p>
|
|
</div>
|
|
</main>
|
|
|
|
<div class="modal" id="modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<div>
|
|
<h2 class="modal-title" id="modalTitle"></h2>
|
|
<span class="item-type" id="modalType"></span>
|
|
</div>
|
|
<button class="modal-close" onclick="closeModal()">
|
|
<i data-lucide="x"></i>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body" id="modalBody"></div>
|
|
<div class="item-tags" id="modalTags"></div>
|
|
<div class="modal-actions">
|
|
<button class="btn btn-primary" id="markUsedBtn" onclick="toggleUsed()">Marchează folosit</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Theme
|
|
function toggleTheme() {
|
|
const body = document.body;
|
|
const current = body.getAttribute('data-theme') || 'dark';
|
|
const next = current === 'dark' ? 'light' : 'dark';
|
|
body.setAttribute('data-theme', next);
|
|
localStorage.setItem('theme', next);
|
|
updateThemeIcon();
|
|
}
|
|
|
|
function updateThemeIcon() {
|
|
const theme = document.body.getAttribute('data-theme') || 'dark';
|
|
const icon = document.getElementById('themeIcon');
|
|
if (icon) {
|
|
icon.setAttribute('data-lucide', theme === 'dark' ? 'sun' : 'moon');
|
|
lucide.createIcons();
|
|
}
|
|
}
|
|
|
|
// Load saved theme
|
|
const savedTheme = localStorage.getItem('theme') || 'dark';
|
|
document.body.setAttribute('data-theme', savedTheme);
|
|
|
|
// Data
|
|
const API_BASE = window.location.pathname.includes('/echo/') ? '/echo' : '';
|
|
let items = [];
|
|
let currentFilter = 'all';
|
|
let currentItem = null;
|
|
|
|
async function loadItems() {
|
|
try {
|
|
const response = await fetch('grup-sprijin/index.json?t=' + Date.now());
|
|
if (!response.ok) throw new Error('Nu am găsit fișierul');
|
|
items = await response.json();
|
|
render();
|
|
} catch (e) {
|
|
console.error('Error loading items:', e);
|
|
document.getElementById('itemsGrid').innerHTML = `
|
|
<div class="error-msg">
|
|
Eroare la încărcare: ${e.message}<br>
|
|
<small>Verifică dacă fișierul grup-sprijin/index.json există</small>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
function render() {
|
|
const search = document.getElementById('searchInput').value.toLowerCase();
|
|
|
|
let filtered = items.filter(item => {
|
|
if (search && !item.title.toLowerCase().includes(search) &&
|
|
!item.content.toLowerCase().includes(search) &&
|
|
!item.tags.some(t => t.toLowerCase().includes(search))) {
|
|
return false;
|
|
}
|
|
|
|
if (currentFilter === 'all') return true;
|
|
if (currentFilter === 'used') return item.used;
|
|
if (currentFilter === 'unused') return !item.used;
|
|
return item.type === currentFilter;
|
|
});
|
|
|
|
const total = items.length;
|
|
const used = items.filter(i => i.used).length;
|
|
document.getElementById('stats').innerHTML = `
|
|
<span>Total: ${total}</span>
|
|
<span>Folosite: ${used}</span>
|
|
<span>Nefolosite: ${total - used}</span>
|
|
`;
|
|
|
|
const grid = document.getElementById('itemsGrid');
|
|
if (filtered.length === 0) {
|
|
grid.innerHTML = '<p style="color: var(--text-muted);">Niciun rezultat</p>';
|
|
return;
|
|
}
|
|
|
|
grid.innerHTML = filtered.map(item => `
|
|
<div class="item-card ${item.used ? 'used' : ''}" onclick="openModal('${item.id}')">
|
|
<div class="item-header">
|
|
<span class="item-title">${item.title}</span>
|
|
<span class="item-type ${item.type}">${item.type}</span>
|
|
</div>
|
|
<div class="item-tags">
|
|
${item.tags.map(t => `<span class="tag">${t}</span>`).join('')}
|
|
</div>
|
|
${item.used ? `<div class="item-used">✓ Folosit: ${item.used}</div>` : ''}
|
|
</div>
|
|
`).join('');
|
|
|
|
lucide.createIcons();
|
|
}
|
|
|
|
function openModal(id) {
|
|
currentItem = items.find(i => i.id === id);
|
|
if (!currentItem) return;
|
|
|
|
document.getElementById('modalTitle').textContent = currentItem.title;
|
|
document.getElementById('modalType').textContent = currentItem.type;
|
|
document.getElementById('modalType').className = `item-type ${currentItem.type}`;
|
|
document.getElementById('modalBody').textContent = currentItem.content;
|
|
document.getElementById('modalTags').innerHTML = currentItem.tags.map(t => `<span class="tag">${t}</span>`).join('');
|
|
document.getElementById('markUsedBtn').textContent = currentItem.used ? 'Marchează nefolosit' : 'Marchează folosit';
|
|
|
|
document.getElementById('modal').classList.add('open');
|
|
lucide.createIcons();
|
|
}
|
|
|
|
function closeModal() {
|
|
document.getElementById('modal').classList.remove('open');
|
|
currentItem = null;
|
|
}
|
|
|
|
async function toggleUsed() {
|
|
if (!currentItem) return;
|
|
|
|
const idx = items.findIndex(i => i.id === currentItem.id);
|
|
if (idx === -1) return;
|
|
|
|
if (items[idx].used) {
|
|
items[idx].used = null;
|
|
} else {
|
|
items[idx].used = new Date().toLocaleDateString('ro-RO');
|
|
}
|
|
|
|
try {
|
|
await fetch(`${API_BASE}/api/files`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
path: 'grup-sprijin/index.json',
|
|
content: JSON.stringify(items, null, 2)
|
|
})
|
|
});
|
|
} catch (e) {
|
|
console.error('Error saving:', e);
|
|
}
|
|
|
|
closeModal();
|
|
render();
|
|
}
|
|
|
|
document.querySelectorAll('.filter-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
currentFilter = btn.dataset.filter;
|
|
render();
|
|
});
|
|
});
|
|
|
|
document.getElementById('searchInput').addEventListener('input', render);
|
|
|
|
document.getElementById('modal').addEventListener('click', (e) => {
|
|
if (e.target.id === 'modal') closeModal();
|
|
});
|
|
|
|
// Load fise
|
|
async function loadFise() {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/api/files?path=kanban/grup-sprijin&action=list`);
|
|
const data = await response.json();
|
|
if (data.items) {
|
|
const fise = data.items.filter(f => f.name.startsWith('fisa-') && f.name.endsWith('.md'));
|
|
if (fise.length > 0) {
|
|
document.getElementById('fiseSection').style.display = 'block';
|
|
document.getElementById('fiseList').innerHTML = fise.map(f => `
|
|
<a href="files.html#kanban/grup-sprijin/${f.name}" class="filter-btn" style="text-decoration: none;">
|
|
${f.name.replace('fisa-', '').replace('.md', '')}
|
|
</a>
|
|
`).join('');
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log('No fise yet');
|
|
}
|
|
}
|
|
|
|
// Init
|
|
loadItems();
|
|
loadFise();
|
|
lucide.createIcons();
|
|
updateThemeIcon();
|
|
</script>
|
|
</body>
|
|
</html>
|