Files
game-library/app/templates/index.html
Claude Agent 66ae831c36 Rebuild extraction pipeline infrastructure (Faza 0 prep)
Implements the approved plan to replace the broken regex/index-master
extraction with an LLM-subagent pipeline. Four parallel lanes:

Lane A — scripts/extract_common.py (PDF/docx/doc/pptx/html/zip, no
  max_pages truncation), normalize_sources.py, chunk_sources.py
  (~20pg chunks + overlap, manifest registry), activity_schema.json.
Lane B — app/config_taxonomy.py (16 fixed category slugs), schema
  rebuilt from scratch in app/models/ with content_type, language,
  source_files, source_excerpt, normalized_name, extraction_confidence,
  needs_review; FTS5 + 3 triggers extended with materials_list and
  skills_developed.
Lane C — build_database.py (--rebuild, atomic swap, schema + fuzzy
  source_excerpt validation, dedup with needs_review band),
  validate_extractions.py, review_queue.py, new run_extraction.py
  orchestrator, SUBAGENT_PROMPT.md.
Lane D — search.py content_type/language filters (default search
  excludes non-game content), E7 schema-compat audit; fixed a NULL
  keywords AttributeError in _boost_search_relevance.

Removes 8 orphaned/dead scripts and app/services/parser.py +
indexer.py. Adds tests/ (70 passing, 1 skipped — libreoffice absent).

Note: Lane D made one additive edit to app/models/database.py
(_update_category_counts) to surface content_type/language in
get_filter_options, outside its nominal lane boundary but after
Lane B completed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:43:38 +00:00

177 lines
7.4 KiB
HTML

{% extends "base.html" %}
{% block title %}Căutare Activități - INDEX Sistem Jocuri{% endblock %}
{% block content %}
<div class="search-page">
<div class="search-header">
<h2 class="search-title">Căutare Activități Educaționale</h2>
<p class="search-subtitle">
Descoperă activități pentru copii și tineri din catalogul nostru de
{% if stats and stats.total_activities %}{{ stats.total_activities }}{% else %}500+{% endif %}
jocuri și exerciții.
</p>
</div>
<form method="POST" action="{{ url_for('main.search') }}" class="search-form">
<!-- Main search input -->
<div class="search-input-group">
<input
type="text"
name="search_query"
id="search_query"
class="search-input"
placeholder="Caută activități după nume, descriere sau cuvinte cheie..."
autocomplete="off"
>
<button type="submit" class="search-button">Căutare</button>
</div>
<!-- Dynamic filters -->
<div class="filters-grid">
{% if filters %}
{% if filters.category %}
<div class="filter-group">
<label for="category" class="filter-label">Categorie</label>
<select name="category" id="category" class="filter-select">
<option value="">Toate categoriile</option>
{% for category in filters.category %}
<option value="{{ category }}">{{ display_names.get(category, category) }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.content_type %}
<div class="filter-group">
<label for="content_type" class="filter-label">Tip conținut</label>
<select name="content_type" id="content_type" class="filter-select">
<option value="">Doar jocuri și activități</option>
{% for content_type in filters.content_type %}
<option value="{{ content_type }}">{{ display_names.get(content_type, content_type) }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.language %}
<div class="filter-group">
<label for="language" class="filter-label">Limbă</label>
<select name="language" id="language" class="filter-select">
<option value="">Toate limbile</option>
{% for language in filters.language %}
<option value="{{ language }}">{{ display_names.get(language, language) }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.age_group %}
<div class="filter-group">
<label for="age_group" class="filter-label">Grupa de vârstă</label>
<select name="age_group" id="age_group" class="filter-select">
<option value="">Toate vârstele</option>
{% for age_group in filters.age_group %}
<option value="{{ age_group }}">{{ age_group }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.participants %}
<div class="filter-group">
<label for="participants" class="filter-label">Participanți</label>
<select name="participants" id="participants" class="filter-select">
<option value="">Orice număr</option>
{% for participants in filters.participants %}
<option value="{{ participants }}">{{ participants }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.duration %}
<div class="filter-group">
<label for="duration" class="filter-label">Durata</label>
<select name="duration" id="duration" class="filter-select">
<option value="">Orice durată</option>
{% for duration in filters.duration %}
<option value="{{ duration }}">{{ duration }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.materials %}
<div class="filter-group">
<label for="materials" class="filter-label">Materiale</label>
<select name="materials" id="materials" class="filter-select">
<option value="">Orice materiale</option>
{% for materials in filters.materials %}
<option value="{{ materials }}">{{ materials }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if filters.difficulty %}
<div class="filter-group">
<label for="difficulty" class="filter-label">Dificultate</label>
<select name="difficulty" id="difficulty" class="filter-select">
<option value="">Orice nivel</option>
{% for difficulty in filters.difficulty %}
<option value="{{ difficulty }}">{{ difficulty }}</option>
{% endfor %}
</select>
</div>
{% endif %}
{% endif %}
</div>
<!-- Action buttons -->
<div class="search-actions">
<button type="submit" class="btn btn-primary">Aplică filtrele</button>
<button type="button" class="btn btn-secondary" onclick="clearFilters()">Resetează</button>
</div>
</form>
<!-- Quick stats -->
{% if stats and stats.categories %}
<div class="quick-stats">
<h3 class="stats-title">Categorii disponibile</h3>
<div class="stats-grid">
{% for category, count in stats.categories.items() %}
<div class="stat-item">
<span class="stat-label">{{ category }}</span>
<span class="stat-value">{{ count }}</span>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock %}
{% block scripts %}
<script>
function clearFilters() {
// Reset all form fields
document.getElementById('search_query').value = '';
const selects = document.querySelectorAll('.filter-select');
selects.forEach(select => select.selectedIndex = 0);
}
// Auto-submit on filter change for better UX
document.addEventListener('DOMContentLoaded', function() {
const filterSelects = document.querySelectorAll('.filter-select');
filterSelects.forEach(select => {
select.addEventListener('change', function() {
if (this.value) {
document.querySelector('.search-form').submit();
}
});
});
});
</script>
{% endblock %}