All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 1m58s
368 lines
11 KiB
HTML
368 lines
11 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block content %}
|
|
<style>
|
|
.stats-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-bottom: 3rem;
|
|
}
|
|
|
|
.stat-card {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
padding: 2rem;
|
|
border-radius: 1rem;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.stat-card.green {
|
|
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
|
|
}
|
|
|
|
.stat-card.orange {
|
|
background: linear-gradient(135deg, #ee0979 0%, #ff6a00 100%);
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 2.5rem;
|
|
font-weight: 700;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 0.875rem;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 1.5rem;
|
|
font-weight: 700;
|
|
color: var(--text-main);
|
|
}
|
|
|
|
.quick-start-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-bottom: 3rem;
|
|
}
|
|
|
|
.quick-start-card {
|
|
background: var(--glass-bg);
|
|
backdrop-filter: blur(12px);
|
|
border: 1px solid var(--glass-border);
|
|
border-radius: 1rem;
|
|
padding: 1.5rem;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.quick-start-card:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.quick-start-card::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 4px;
|
|
background: linear-gradient(90deg, var(--primary), #764ba2);
|
|
}
|
|
|
|
.card-icon {
|
|
font-size: 2rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 1.125rem;
|
|
font-weight: 600;
|
|
margin-bottom: 0.5rem;
|
|
color: var(--text-main);
|
|
}
|
|
|
|
.card-description {
|
|
font-size: 0.875rem;
|
|
color: var(--text-muted);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.card-count {
|
|
display: inline-block;
|
|
background: #f0f4ff;
|
|
color: var(--primary);
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 1rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.active-session-card {
|
|
background: white;
|
|
border: 2px solid var(--primary);
|
|
border-radius: 1rem;
|
|
padding: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.active-session-card:hover {
|
|
box-shadow: 0 8px 24px rgba(99, 102, 241, 0.2);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.session-badge {
|
|
display: inline-block;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
padding: 0.5rem 1rem;
|
|
border-radius: 2rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.custom-quiz-section {
|
|
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
border-radius: 1rem;
|
|
padding: 2rem;
|
|
margin-top: 3rem;
|
|
}
|
|
|
|
.filter-chips {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.filter-chip {
|
|
background: var(--primary);
|
|
color: white;
|
|
padding: 0.375rem 0.875rem;
|
|
border-radius: 1rem;
|
|
font-size: 0.875rem;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.btn-gradient {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
border: none;
|
|
color: white;
|
|
padding: 0.875rem 2rem;
|
|
border-radius: 0.5rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
}
|
|
|
|
.btn-gradient:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
|
}
|
|
</style>
|
|
|
|
<!-- Stats Overview -->
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{ total_questions }}</div>
|
|
<div class="stat-label">Totalt frågor</div>
|
|
</div>
|
|
<div class="stat-card green">
|
|
<div class="stat-value">{{ answered_count }}</div>
|
|
<div class="stat-label">Besvarade</div>
|
|
</div>
|
|
<div class="stat-card orange">
|
|
<div class="stat-value">{{ total_questions|add:answered_count|floatformat:0|add:"-" }}{{ answered_count }}</div>
|
|
<div class="stat-label">Återstående</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Active Sessions -->
|
|
{% if active_sessions %}
|
|
<div class="section-header">
|
|
<h2 class="section-title">🎯 Aktiva Quiz</h2>
|
|
</div>
|
|
|
|
{% for session in active_sessions %}
|
|
<div class="active-session-card">
|
|
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;">
|
|
<div>
|
|
<span class="session-badge">
|
|
{% if session.course %}{{ session.course.name }}{% else %}Blandat{% endif %}
|
|
</span>
|
|
<div style="font-size: 0.875rem; color: var(--text-muted); margin-top: 0.25rem;">
|
|
Startat {{ session.created_at|date:"Y-m-d H:i" }}
|
|
</div>
|
|
</div>
|
|
<form action="{% url 'close_quiz' session.id %}" method="post" hx-post="{% url 'close_quiz' session.id %}"
|
|
hx-target=".active-session-card" hx-swap="outerHTML">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-secondary" style="padding: 0.5rem 1rem; font-size: 0.875rem;">
|
|
✕ Stäng
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
{% if session.tags.exists %}
|
|
<div class="filter-chips" style="margin-bottom: 1rem;">
|
|
{% for tag in session.tags.all %}
|
|
<span class="filter-chip">🏷️ {{ tag.name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<a href="{% url 'quiz_mode' session.id %}" class="btn btn-primary" style="width: 100%; text-align: center; padding: 0.875rem;">
|
|
▶️ Fortsätt Quiz
|
|
</a>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
<!-- Quick Start Options -->
|
|
<div class="section-header" style="margin-top: 3rem;">
|
|
<h2 class="section-title">🚀 Snabbstart</h2>
|
|
</div>
|
|
|
|
<div class="quick-start-grid">
|
|
<!-- Tag-based quick starts -->
|
|
<div class="quick-start-card" onclick="startTagQuiz('anatomi')">
|
|
<div class="card-icon">🦴</div>
|
|
<div class="card-title">Anatomi</div>
|
|
<div class="card-description">Fokusera på anatomifrågor</div>
|
|
<span class="card-count" id="tag-anatomi-count">...</span>
|
|
</div>
|
|
|
|
<div class="quick-start-card" onclick="startTagQuiz('histologi')">
|
|
<div class="card-icon">🔬</div>
|
|
<div class="card-title">Histologi</div>
|
|
<div class="card-description">Fokusera på histologifrågor</div>
|
|
<span class="card-count" id="tag-histologi-count">...</span>
|
|
</div>
|
|
|
|
<div class="quick-start-card" onclick="startTagQuiz('cerebrum')">
|
|
<div class="card-icon">🧠</div>
|
|
<div class="card-title">Cerebrum</div>
|
|
<div class="card-description">Hjärnans frågor</div>
|
|
<span class="card-count" id="tag-cerebrum-count">...</span>
|
|
</div>
|
|
|
|
<div class="quick-start-card" onclick="startTagQuiz('oga')">
|
|
<div class="card-icon">👁️</div>
|
|
<div class="card-title">Öga</div>
|
|
<div class="card-description">Ögats anatomi & histologi</div>
|
|
<span class="card-count" id="tag-oga-count">...</span>
|
|
</div>
|
|
|
|
<div class="quick-start-card" onclick="startTagQuiz('ora')">
|
|
<div class="card-icon">👂</div>
|
|
<div class="card-title">Öra</div>
|
|
<div class="card-description">Örats anatomi & histologi</div>
|
|
<span class="card-count" id="tag-ora-count">...</span>
|
|
</div>
|
|
|
|
<div class="quick-start-card" onclick="startAllQuiz()">
|
|
<div class="card-icon">🎲</div>
|
|
<div class="card-title">Alla Frågor</div>
|
|
<div class="card-description">Blandat från hela kursen</div>
|
|
<span class="card-count">{{ total_questions }} frågor</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Custom Quiz Builder -->
|
|
<div class="custom-quiz-section">
|
|
<h2 style="margin-bottom: 1rem; color: var(--text-main);">🎨 Anpassat Quiz</h2>
|
|
<p style="color: var(--text-muted); margin-bottom: 1.5rem;">Skapa ett quiz med dina egna filter</p>
|
|
|
|
<form method="post" action="{% url 'create_quiz' %}" id="custom-quiz-form">
|
|
{% csrf_token %}
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem;">
|
|
<div class="form-group">
|
|
<label for="{{ form.course.id_for_label }}" style="font-weight: 600; margin-bottom: 0.5rem;">Kurs</label>
|
|
{{ form.course }}
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="{{ form.tags.id_for_label }}" style="font-weight: 600; margin-bottom: 0.5rem;">Taggar</label>
|
|
{{ form.tags }}
|
|
</div>
|
|
</div>
|
|
<button type="submit" class="btn-gradient">
|
|
✨ Skapa Anpassat Quiz
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
// Fetch tag counts on load
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
const tags = ['anatomi', 'histologi', 'cerebrum', 'oga', 'ora'];
|
|
|
|
for (const tag of tags) {
|
|
try {
|
|
const response = await fetch(`/api/tag-count/${tag}/`);
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
const el = document.getElementById(`tag-${tag}-count`);
|
|
if (el) el.textContent = `${data.count} frågor`;
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to fetch count for', tag);
|
|
}
|
|
}
|
|
});
|
|
|
|
function startTagQuiz(tagSlug) {
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = '{% url "create_quiz" %}';
|
|
|
|
const csrf = document.createElement('input');
|
|
csrf.type = 'hidden';
|
|
csrf.name = 'csrfmiddlewaretoken';
|
|
csrf.value = '{{ csrf_token }}';
|
|
form.appendChild(csrf);
|
|
|
|
const tagInput = document.createElement('input');
|
|
tagInput.type = 'hidden';
|
|
tagInput.name = 'tag_slug';
|
|
tagInput.value = tagSlug;
|
|
form.appendChild(tagInput);
|
|
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
|
|
function startAllQuiz() {
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = '{% url "create_quiz" %}';
|
|
|
|
const csrf = document.createElement('input');
|
|
csrf.type = 'hidden';
|
|
csrf.name = 'csrfmiddlewaretoken';
|
|
csrf.value = '{{ csrf_token }}';
|
|
form.appendChild(csrf);
|
|
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
</script>
|
|
{% endblock %} |