Files
conference/templates/organizer/dashboard.html
T
2026-04-18 14:53:41 +00:00

307 lines
12 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ 'dashboard'|t }} - {{ 'organizer'|t }} - NetEvents{% endblock %}
{% block content %}
<style>
.progress-bar-container {
background: #e9ecef;
border-radius: 4px;
height: 20px;
width: 100%;
overflow: hidden;
margin-top: 5px;
}
.progress-bar-fill {
height: 100%;
background: #28a745;
transition: width 0.3s ease;
}
.progress-bar-fill.warning {
background: #ffc107;
}
.progress-bar-fill.full {
background: #dc3545;
}
.event-capacity {
font-size: 14px;
color: #666;
margin-top: 3px;
}
.breakout-sessions-list {
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #e9ecef;
width: 100%;
}
.breakout-session-item {
background: #f8f9fa;
border-radius: 6px;
padding: 10px 12px;
margin-bottom: 8px;
}
.breakout-session-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.breakout-session-name {
font-weight: 500;
color: #495057;
}
.breakout-session-capacity {
font-size: 13px;
color: #666;
}
.event-item-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 10px;
width: 100%;
}
.event-item {
display: flex;
flex-direction: column;
width: 100%;
}
.event-actions-inline {
display: flex;
gap: 8px;
}
.event-actions-inline .btn {
padding: 4px 10px;
font-size: 12px;
}
.section-toggle {
cursor: pointer;
padding: 8px 12px;
background: #e9ecef;
border-radius: 4px;
margin-bottom: 5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.section-toggle:hover {
background: #dee2e6;
}
.section-toggle::after {
content: '▼';
font-size: 10px;
}
.section-toggle.collapsed::after {
content: '▶';
}
.section-content {
padding: 10px 0;
width: 100%;
box-sizing: border-box;
}
.section-content.collapsed {
display: none;
}
.item-list {
display: flex;
flex-direction: column;
gap: 5px;
width: 100%;
}
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
background: #f8f9fa;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
}
.list-item-info {
flex: 1;
}
.list-item-actions {
display: flex;
gap: 5px;
}
/* Wide screen - spread content */
@media (min-width: 1400px) {
.dashboard {
max-width: 100%;
}
.events-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
.event-item {
padding: 20px 25px;
}
.event-info {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.breakout-sessions-list {
grid-column: 1 / -1;
}
}
@media (min-width: 1800px) {
.events-list {
grid-template-columns: repeat(4, 1fr);
}
}
</style>
<script>
function toggleSection(id) {
const content = document.getElementById(id);
const toggle = content.previousElementSibling;
content.classList.toggle('collapsed');
toggle.classList.toggle('collapsed');
}
</script>
<div class="dashboard">
<h1>{{ 'dashboard'|t }} - {{ 'organizer'|t }}</h1>
<div class="dashboard-actions">
<a href="{{ url_for('create_event') }}" class="btn btn-primary">{{ 'create_event'|t }}</a>
</div>
<section class="my-events">
<h2>{{ 'my_events'|t }}</h2>
{% if events %}
<div class="events-list">
{% for event in events %}
<div class="event-item">
<div class="event-item-header">
<h3>{{ event.name }}</h3>
<div class="event-actions-inline">
<a href="{{ url_for('event_detail', code=event.code) }}" class="btn btn-sm btn-outline">{{ 'details'|t }}</a>
</div>
</div>
<div class="event-info">
<p class="event-date">{{ event.start_time|localized_date if event.start_time else 'TBD' }}</p>
<p class="event-location">{{ event.location }}</p>
{% if event.max_attendees %}
{% set percent = (event.attendee_count / event.max_attendees * 100)|round|int %}
<div class="event-capacity">
<span>{{ event.attendee_count }} / {{ event.max_attendees }} {{ 'attendees'|t }}</span>
<span>({{ percent }}%)</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar-fill {% if percent >= 100 %}full{% elif percent >= 80 %}warning{% endif %}"
style="width: {{ percent if percent <= 100 else 100 }}%"></div>
</div>
{% else %}
<div class="event-capacity">
<span>{{ event.attendee_count }} {{ 'attendees'|t }} ({{ 'unlimited'|t }})</span>
</div>
{% endif %}
</div>
{% if event.staff %}
<div class="breakout-sessions-list">
<div class="section-toggle" onclick="toggleSection('staff-{{ event.id }}')">
<strong>Staff ({{ event.staff|length }})</strong>
</div>
<div id="staff-{{ event.id }}" class="section-content collapsed">
<div class="item-list">
{% for s in event.staff %}
<div class="list-item">
<div class="list-item-info">
<strong>{{ s.first_name }} {{ s.last_name }}</strong>
<span style="color: #666; font-size: 12px;">{{ s.email }}</span>
</div>
<div class="list-item-actions">
<a href="{{ url_for('edit_staff', event_id=event.id, staff_id=s.id) }}" class="btn btn-sm btn-outline">Edit</a>
<form method="POST" action="{{ url_for('delete_staff', event_id=event.id, staff_id=s.id) }}" style="display: inline;" onsubmit="return confirm('Remove {{ s.first_name }} {{ s.last_name }}?');">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
{% if event.breakout_sessions %}
<div class="breakout-sessions-list">
<div class="section-toggle" onclick="toggleSection('sessions-{{ event.id }}')">
<strong>{{ 'breakout_sessions'|t }} ({{ event.breakout_sessions|length }})</strong>
</div>
<div id="sessions-{{ event.id }}" class="section-content collapsed">
<div class="item-list">
{% for session in event.breakout_sessions %}
<div class="list-item">
<div class="list-item-info">
<strong>{{ session.name }}</strong>
{% if session.max_attendees %}
<span style="color: #666; font-size: 12px;">{{ session.rsvp_count }} / {{ session.max_attendees }}</span>
{% else %}
<span style="color: #666; font-size: 12px;">{{ session.rsvp_count }} registered</span>
{% endif %}
</div>
<div class="list-item-actions">
<a href="{{ url_for('edit_breakout_session', session_id=session.id) }}" class="btn btn-sm btn-outline">Edit</a>
<form method="POST" action="{{ url_for('delete_breakout_session', session_id=session.id) }}" style="display: inline;" onsubmit="return confirm('Delete {{ session.name }}?');">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
{% if event.attendees %}
<div class="breakout-sessions-list">
<div class="section-toggle" onclick="toggleSection('attendees-{{ event.id }}')">
<strong>{{ 'attendees'|t }} ({{ event.attendees|length }})</strong>
</div>
<div id="attendees-{{ event.id }}" class="section-content collapsed">
<div class="item-list">
{% for att in event.attendees %}
<div class="list-item">
<div class="list-item-info">
<strong>{{ att.first_name }} {{ att.last_name }}</strong>
<span style="color: #666; font-size: 12px;">{{ att.email }}</span>
{% if att.checked_in %}
<span class="badge badge-success" style="font-size: 10px;">Checked In</span>
{% endif %}
</div>
<div class="list-item-actions">
<a href="{{ url_for('edit_attendee', attendee_id=att.id) }}" class="btn btn-sm btn-outline">Edit</a>
<form method="POST" action="{{ url_for('delete_attendee', attendee_id=att.id) }}" style="display: inline;" onsubmit="return confirm('Remove {{ att.first_name }} {{ att.last_name }}?');">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<p class="no-events">{{ 'no_events_yet'|t }}
<a href="{{ url_for('create_event') }}">{{ 'create_first_event'|t }}</a>
</p>
{% endif %}
</section>
</div>
{% endblock %}