nordabiz/templates/admin/announcements.html
Maciej Pienczyn 6d589407be Sync local repo with production state
- Add MembershipFee and MembershipFeeConfig models
- Add /health endpoint for monitoring
- Add Microsoft Fluent Design CSS
- Update templates with new CSS structure
- Add Announcement model
- Update .gitignore to exclude analysis files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 22:23:28 +01:00

195 lines
6.1 KiB
HTML

{% extends "base.html" %}
{% block title %}Zarzadzanie Ogloszeniami - Norda Biznes Hub{% endblock %}
{% block extra_css %}
<style>
.admin-header {
margin-bottom: var(--spacing-xl);
display: flex;
justify-content: space-between;
align-items: center;
}
.admin-header h1 {
font-size: var(--font-size-3xl);
color: var(--text-primary);
}
.section {
background: var(--surface);
padding: var(--spacing-xl);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
}
.announcements-table {
width: 100%;
border-collapse: collapse;
}
.announcements-table th,
.announcements-table td {
padding: var(--spacing-md);
text-align: left;
border-bottom: 1px solid var(--border);
}
.announcements-table th {
font-weight: 600;
color: var(--text-secondary);
font-size: var(--font-size-sm);
text-transform: uppercase;
background: var(--background);
}
.announcements-table tr:hover {
background: var(--background);
}
.status-badge {
display: inline-block;
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-full);
font-size: var(--font-size-xs);
font-weight: 600;
}
.status-published { background: var(--success-bg); color: var(--success); }
.status-draft { background: var(--warning-bg); color: var(--warning); }
.status-expired { background: var(--surface-secondary); color: var(--text-secondary); }
.type-badge {
display: inline-block;
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-sm);
font-size: var(--font-size-xs);
font-weight: 500;
background: var(--primary-bg);
color: var(--primary);
}
.type-fees { background: var(--warning-bg); color: var(--warning); }
.type-important { background: var(--error-bg); color: var(--error); }
.type-urgent { background: var(--error); color: white; }
.pinned-icon {
color: var(--warning);
margin-left: var(--spacing-xs);
}
.btn-small {
padding: var(--spacing-xs) var(--spacing-sm);
font-size: var(--font-size-xs);
}
.actions-cell {
white-space: nowrap;
}
.empty-state {
text-align: center;
padding: var(--spacing-2xl);
color: var(--text-secondary);
}
</style>
{% endblock %}
{% block content %}
<div class="container">
<div class="admin-header">
<h1>Zarzadzanie Ogloszeniami</h1>
<a href="{{ url_for('admin_announcements_new') }}" class="btn btn-primary">
+ Nowe ogloszenie
</a>
</div>
<div class="section">
{% if announcements %}
<table class="announcements-table">
<thead>
<tr>
<th>Tytul</th>
<th>Typ</th>
<th>Status</th>
<th>Autor</th>
<th>Utworzono</th>
<th>Akcje</th>
</tr>
</thead>
<tbody>
{% for ann in announcements %}
<tr>
<td>
{{ ann.title }}
{% if ann.is_pinned %}<span class="pinned-icon" title="Przypiety">&#128204;</span>{% endif %}
</td>
<td>
<span class="type-badge type-{{ ann.announcement_type }}">
{% if ann.announcement_type == 'general' %}Ogolne
{% elif ann.announcement_type == 'fees' %}Skladki
{% elif ann.announcement_type == 'event' %}Wydarzenie
{% elif ann.announcement_type == 'important' %}Wazne
{% elif ann.announcement_type == 'urgent' %}Pilne
{% else %}{{ ann.announcement_type }}
{% endif %}
</span>
</td>
<td>
{% if not ann.is_published %}
<span class="status-badge status-draft">Wersja robocza</span>
{% elif ann.expire_date and ann.expire_date < now %}
<span class="status-badge status-expired">Wygaslo</span>
{% else %}
<span class="status-badge status-published">Opublikowane</span>
{% endif %}
</td>
<td>{{ ann.author.name if ann.author else '-' }}</td>
<td>{{ ann.created_at.strftime('%Y-%m-%d %H:%M') if ann.created_at else '-' }}</td>
<td class="actions-cell">
<a href="{{ url_for('admin_announcements_edit', id=ann.id) }}" class="btn btn-secondary btn-small">
Edytuj
</a>
<button class="btn btn-error btn-small" onclick="deleteAnnouncement({{ ann.id }})">
Usun
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="empty-state">
<p>Brak ogloszen. Utworz pierwsze ogloszenie klikajac przycisk powyzej.</p>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block extra_js %}
const now = new Date();
function deleteAnnouncement(id) {
if (!confirm('Czy na pewno chcesz usunac to ogloszenie?')) {
return;
}
fetch('/admin/announcements/' + id + '/delete', {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token() }}'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Blad: ' + data.error);
}
})
.catch(err => alert('Blad: ' + err));
}
{% endblock %}