Files
SportstimeAPI/templates/dashboard/review_queue.html
Trey t 63acf7accb feat: add Django web app, CloudKit sync, dashboard, and game_datetime_utc export
Adds the full Django application layer on top of sportstime_parser:
- core: Sport, Team, Stadium, Game models with aliases and league structure
- scraper: orchestration engine, adapter, job management, Celery tasks
- cloudkit: CloudKit sync client, sync state tracking, sync jobs
- dashboard: staff dashboard for monitoring scrapers, sync, review queue
- notifications: email reports for scrape/sync results
- Docker setup for deployment (Dockerfile, docker-compose, entrypoint)

Game exports now use game_datetime_utc (ISO 8601 UTC) instead of
venue-local date+time strings, matching the canonical format used
by the iOS app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:04:27 -06:00

97 lines
3.5 KiB
HTML

{% extends 'base.html' %}
{% block content %}
<div class="page-header">
<h2>Review Queue</h2>
<span class="badge {% if total_pending > 0 %}badge-warning{% else %}badge-success{% endif %}" style="font-size: 1rem; padding: 0.5rem 1rem;">
{{ total_pending }} Pending
</span>
</div>
{% if total_pending == 0 %}
<div class="alert alert-success">
No items pending review. All data has been validated.
</div>
{% endif %}
<!-- Summary by Sport and Type -->
{% if review_summary %}
<div class="card">
<div class="card-header">
<h3>Review Summary</h3>
</div>
<div class="stat-grid">
{% for item in review_summary %}
<div class="stat-card warning">
<div class="stat-value">{{ item.count }}</div>
<div class="stat-label">{{ item.sport__short_name }} - {{ item.item_type|title }}</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
<!-- Pending Items -->
<div class="card">
<div class="card-header">
<h3>Pending Reviews</h3>
<a href="{% url 'admin:scraper_manualreviewitem_changelist' %}?status__exact=pending" class="btn btn-primary">View in Admin</a>
</div>
<table class="table">
<thead>
<tr>
<th>Type</th>
<th>Sport</th>
<th>Raw Value</th>
<th>Matched To</th>
<th>Confidence</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for item in pending_items %}
<tr>
<td>
{% if item.item_type == 'team' %}
<span class="badge badge-info">Team</span>
{% elif item.item_type == 'stadium' %}
<span class="badge badge-secondary">Stadium</span>
{% elif item.item_type == 'game' %}
<span class="badge badge-warning">Game</span>
{% else %}
<span class="badge badge-secondary">{{ item.item_type }}</span>
{% endif %}
</td>
<td>{{ item.sport.short_name }}</td>
<td><strong>{{ item.raw_value }}</strong></td>
<td>
{% if item.matched_value %}
{{ item.matched_value }}
{% else %}
<span class="text-muted">No match</span>
{% endif %}
</td>
<td>
<div class="progress-bar" style="width: 80px;">
<div class="fill" style="width: {{ item.confidence }}%; background: {% if item.confidence >= 85 %}#28a745{% elif item.confidence >= 70 %}#ffc107{% else %}#dc3545{% endif %};"></div>
</div>
<small class="text-muted">{{ item.confidence }}%</small>
</td>
<td class="text-muted">{{ item.created_at|timesince }} ago</td>
<td>
<a href="{% url 'admin:scraper_manualreviewitem_change' item.id %}" class="btn btn-primary" style="padding: 0.25rem 0.5rem; font-size: 0.85rem;">
Review
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="7" class="text-muted">No pending reviews</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}