nordabiz/templates/admin/chat_analytics.html
Maciej Pienczyn 6e4e7c2240 Sync: Current production state
- Added CompanyRecommendation system
- Made company pages public (removed @login_required)
- CSS refactor: inline styles instead of external fluent CSS
- Added release notes page
- Added admin recommendations panel
- Company logos (webp format)
- Docker compose configuration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 12:26:22 +01:00

224 lines
7.0 KiB
HTML
Executable File

{% extends "base.html" %}
{% block title %}Analityka Chatu AI - Norda Biznes Hub{% endblock %}
{% block extra_css %}
<style>
.analytics-header {
margin-bottom: var(--spacing-xl);
}
.analytics-header h1 {
font-size: var(--font-size-3xl);
color: var(--text-primary);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--spacing-lg);
margin-bottom: var(--spacing-2xl);
}
.stat-card {
background: var(--surface);
padding: var(--spacing-lg);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
text-align: center;
}
.stat-value {
font-size: var(--font-size-3xl);
font-weight: 700;
color: var(--primary);
}
.stat-value.positive { color: var(--success); }
.stat-value.negative { color: var(--error); }
.stat-value.neutral { color: var(--secondary); }
.stat-label {
color: var(--text-secondary);
font-size: var(--font-size-sm);
margin-top: var(--spacing-xs);
}
.section {
background: var(--surface);
padding: var(--spacing-xl);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
margin-bottom: var(--spacing-xl);
}
.section h2 {
font-size: var(--font-size-xl);
margin-bottom: var(--spacing-lg);
color: var(--text-primary);
border-bottom: 2px solid var(--border);
padding-bottom: var(--spacing-sm);
}
.query-list {
list-style: none;
}
.query-item {
padding: var(--spacing-md);
border-bottom: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
}
.query-item:last-child {
border-bottom: none;
}
.query-text {
flex: 1;
font-size: var(--font-size-base);
}
.query-meta {
color: var(--text-secondary);
font-size: var(--font-size-sm);
text-align: right;
}
.feedback-badge {
display: inline-flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius);
font-size: var(--font-size-sm);
font-weight: 500;
}
.feedback-badge.positive {
background: rgba(16, 185, 129, 0.1);
color: var(--success);
}
.feedback-badge.negative {
background: rgba(239, 68, 68, 0.1);
color: var(--error);
}
.satisfaction-bar {
height: 8px;
background: var(--border);
border-radius: 4px;
overflow: hidden;
margin-top: var(--spacing-sm);
}
.satisfaction-fill {
height: 100%;
background: linear-gradient(90deg, var(--error), var(--warning), var(--success));
transition: width 0.3s ease;
}
.response-preview {
background: var(--background);
padding: var(--spacing-md);
border-radius: var(--radius);
margin-top: var(--spacing-sm);
font-size: var(--font-size-sm);
color: var(--text-secondary);
max-height: 100px;
overflow: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="analytics-header">
<h1>Analityka Chatu AI</h1>
<p class="text-muted">Monitoruj jakość odpowiedzi i zachowania użytkowników</p>
</div>
<!-- Stats Grid -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">{{ total_conversations }}</div>
<div class="stat-label">Rozmów</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ total_user_messages }}</div>
<div class="stat-label">Zapytań użytkowników</div>
</div>
<div class="stat-card">
<div class="stat-value positive">{{ positive_feedback }}</div>
<div class="stat-label">Pozytywnych ocen</div>
</div>
<div class="stat-card">
<div class="stat-value negative">{{ negative_feedback }}</div>
<div class="stat-label">Negatywnych ocen</div>
</div>
<div class="stat-card">
<div class="stat-value {% if satisfaction_rate >= 70 %}positive{% elif satisfaction_rate >= 40 %}neutral{% else %}negative{% endif %}">
{{ satisfaction_rate }}%
</div>
<div class="stat-label">Satysfakcja</div>
<div class="satisfaction-bar">
<div class="satisfaction-fill" style="width: {{ satisfaction_rate }}%"></div>
</div>
</div>
</div>
<!-- Recent Queries -->
<div class="section">
<h2>Ostatnie zapytania użytkowników</h2>
{% if recent_queries %}
<ul class="query-list">
{% for query in recent_queries %}
<li class="query-item">
<div class="query-text">{{ query.content }}</div>
<div class="query-meta">
{{ query.created_at.strftime('%d.%m %H:%M') }}
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p class="text-muted">Brak zapytań</p>
{% endif %}
</div>
<!-- Feedback Section -->
<div class="section">
<h2>Odpowiedzi z oceną</h2>
{% if recent_feedback %}
<ul class="query-list">
{% for msg in recent_feedback %}
<li class="query-item" style="flex-direction: column; align-items: flex-start;">
<div style="display: flex; justify-content: space-between; width: 100%; align-items: center;">
<span class="feedback-badge {% if msg.feedback_rating == 2 %}positive{% else %}negative{% endif %}">
{% if msg.feedback_rating == 2 %}
<svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20"><path d="M2 10.5a1.5 1.5 0 113 0v6a1.5 1.5 0 01-3 0v-6zM6 10.333v5.43a2 2 0 001.106 1.79l.05.025A4 4 0 008.943 18h5.416a2 2 0 001.962-1.608l1.2-6A2 2 0 0015.56 8H12V4a2 2 0 00-2-2 1 1 0 00-1 1v.667a4 4 0 01-.8 2.4L6.8 7.933a4 4 0 00-.8 2.4z"/></svg>
Pomocne
{% else %}
<svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20"><path d="M18 9.5a1.5 1.5 0 11-3 0v-6a1.5 1.5 0 013 0v6zM14 9.667v-5.43a2 2 0 00-1.105-1.79l-.05-.025A4 4 0 0011.055 2H5.64a2 2 0 00-1.962 1.608l-1.2 6A2 2 0 004.44 12H8v4a2 2 0 002 2 1 1 0 001-1v-.667a4 4 0 01.8-2.4l1.4-1.866a4 4 0 00.8-2.4z"/></svg>
Do poprawy
{% endif %}
</span>
<span class="query-meta">{{ msg.feedback_at.strftime('%d.%m %H:%M') if msg.feedback_at else '' }}</span>
</div>
<div class="response-preview">{{ msg.content[:300] }}{% if msg.content|length > 300 %}...{% endif %}</div>
{% if msg.feedback_comment %}
<div style="margin-top: var(--spacing-sm); font-size: var(--font-size-sm);">
<strong>Komentarz:</strong> {{ msg.feedback_comment }}
</div>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<p class="text-muted">Brak ocen - poproś użytkowników o feedback!</p>
{% endif %}
</div>
{% endblock %}