nordabiz/templates/events.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

392 lines
12 KiB
HTML
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% block title %}Aktualności członków - Norda Biznes Hub{% endblock %}
{% block extra_css %}
<style>
.events-header {
margin-bottom: var(--spacing-xl);
}
.events-header h1 {
font-size: var(--font-size-3xl);
color: var(--text-primary);
margin-bottom: var(--spacing-md);
}
.events-meta {
color: var(--text-secondary);
font-size: var(--font-size-lg);
margin-bottom: var(--spacing-lg);
}
/* Filters */
.events-filters {
background: white;
padding: var(--spacing-lg);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
margin-bottom: var(--spacing-xl);
display: flex;
gap: var(--spacing-md);
flex-wrap: wrap;
align-items: center;
}
.filter-group {
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
}
.filter-group label {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--text-secondary);
}
.filter-group select {
padding: var(--spacing-sm) var(--spacing-md);
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: var(--font-size-base);
background: white;
cursor: pointer;
}
.filter-group select:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
/* Timeline */
.events-timeline {
position: relative;
padding-left: var(--spacing-xl);
}
.events-timeline::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2px;
background: var(--border);
}
.event-item {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
box-shadow: var(--shadow);
margin-bottom: var(--spacing-lg);
position: relative;
transition: var(--transition);
}
.event-item::before {
content: '';
position: absolute;
left: calc(-1 * var(--spacing-xl) - 6px);
top: var(--spacing-lg);
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--primary);
border: 3px solid white;
box-shadow: 0 0 0 2px var(--border);
}
.event-item:hover {
box-shadow: var(--shadow-lg);
transform: translateX(4px);
}
.event-type {
display: inline-block;
padding: var(--spacing-xs) var(--spacing-sm);
background-color: var(--background);
color: var(--text-secondary);
font-size: var(--font-size-sm);
border-radius: var(--radius);
margin-bottom: var(--spacing-sm);
font-weight: 500;
}
.event-type.product_launch { background-color: #dbeafe; color: #1e40af; }
.event-type.company_milestone { background-color: #dcfce7; color: #166534; }
.event-type.company_news { background-color: #fef3c7; color: #92400e; }
.event-type.education_event { background-color: #e0e7ff; color: #3730a3; }
.event-type.company_info { background-color: #f3f4f6; color: #374151; }
.event-type.financial_report { background-color: #d1fae5; color: #065f46; }
.event-type.contract_win { background-color: #ccfbf1; color: #115e59; }
.event-type.event { background-color: #fae8ff; color: #86198f; }
.event-company {
font-size: var(--font-size-sm);
color: var(--text-secondary);
margin-bottom: var(--spacing-sm);
}
.event-company a {
color: var(--primary);
text-decoration: none;
font-weight: 500;
}
.event-company a:hover {
text-decoration: underline;
}
.event-title {
font-size: var(--font-size-xl);
font-weight: 600;
color: var(--text-primary);
margin-bottom: var(--spacing-md);
line-height: 1.4;
}
.event-description {
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: var(--spacing-md);
}
.event-meta {
display: flex;
gap: var(--spacing-lg);
font-size: var(--font-size-sm);
color: var(--text-secondary);
padding-top: var(--spacing-md);
border-top: 1px solid var(--border);
}
.event-date {
display: flex;
align-items: center;
gap: var(--spacing-xs);
}
.event-source {
display: flex;
align-items: center;
gap: var(--spacing-xs);
}
.event-source a {
color: var(--primary);
text-decoration: none;
}
.event-source a:hover {
text-decoration: underline;
}
/* Pagination */
.pagination {
display: flex;
justify-content: center;
gap: var(--spacing-sm);
margin-top: var(--spacing-2xl);
align-items: center;
}
.pagination a,
.pagination span {
padding: var(--spacing-sm) var(--spacing-md);
border: 1px solid var(--border);
border-radius: var(--radius);
text-decoration: none;
color: var(--text-primary);
transition: var(--transition);
}
.pagination a:hover {
background: var(--background);
border-color: var(--primary);
}
.pagination .current {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.pagination .disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Empty state */
.empty-state {
text-align: center;
padding: var(--spacing-2xl);
background: white;
border-radius: var(--radius-xl);
box-shadow: var(--shadow);
}
@media (max-width: 768px) {
.events-filters {
flex-direction: column;
align-items: stretch;
}
.events-timeline {
padding-left: var(--spacing-md);
}
.event-item::before {
left: calc(-1 * var(--spacing-md) - 6px);
}
}
</style>
{% endblock %}
{% block content %}
<div class="events-header">
<h1>Aktualności członków</h1>
<p class="events-meta">
<strong>{{ total_events }}</strong> wydarzeń z życia firm członkowskich
</p>
</div>
<!-- Filters -->
<form class="events-filters" method="get" action="{{ url_for('events') }}">
<div class="filter-group">
<label>Typ wydarzenia</label>
<select name="type" onchange="this.form.submit()">
<option value="">Wszystkie typy</option>
{% for event_type, count in event_types %}
<option value="{{ event_type }}" {% if event_type_filter == event_type %}selected{% endif %}>
{% if event_type == 'product_launch' %}Nowe produkty/usługi{% endif %}
{% if event_type == 'company_milestone' %}Kamienie milowe{% endif %}
{% if event_type == 'company_news' %}Aktualności{% endif %}
{% if event_type == 'education_event' %}Szkolenia{% endif %}
{% if event_type == 'company_info' %}Informacje{% endif %}
{% if event_type == 'financial_report' %}Raporty finansowe{% endif %}
{% if event_type == 'contract_win' %}Nowe kontrakty{% endif %}
{% if event_type == 'event' %}Wydarzenia{% endif %}
({{ count }})
</option>
{% endfor %}
</select>
</div>
<div class="filter-group">
<label>Firma</label>
<select name="company" onchange="this.form.submit()">
<option value="">Wszystkie firmy</option>
{% for company in companies_with_events %}
<option value="{{ company.id }}" {% if company_id == company.id %}selected{% endif %}>
{{ company.name }}
</option>
{% endfor %}
</select>
</div>
{% if event_type_filter or company_id %}
<div class="filter-group" style="align-self: flex-end;">
<a href="{{ url_for('events') }}" class="btn btn-outline">Wyczyść filtry</a>
</div>
{% endif %}
</form>
<!-- Events Timeline -->
{% if events %}
<div class="events-timeline">
{% for event in events %}
<div class="event-item">
<span class="event-type {{ event.event_type }}">
{% if event.event_type == 'product_launch' %}📦 Nowy produkt{% endif %}
{% if event.event_type == 'company_milestone' %}🏆 Kamień milowy{% endif %}
{% if event.event_type == 'company_news' %}📰 Aktualność{% endif %}
{% if event.event_type == 'education_event' %}🎓 Szkolenie{% endif %}
{% if event.event_type == 'company_info' %} Informacja{% endif %}
{% if event.event_type == 'financial_report' %}💰 Raport finansowy{% endif %}
{% if event.event_type == 'contract_win' %}🤝 Nowy kontrakt{% endif %}
{% if event.event_type == 'event' %}📅 Wydarzenie{% endif %}
</span>
<div class="event-company">
<a href="{{ url_for('company_detail', company_id=event.company.id) }}">
{{ event.company.name }}
</a>
</div>
<h2 class="event-title">{{ event.title }}</h2>
<div class="event-description">
{{ event.description }}
</div>
<div class="event-meta">
{% if event.event_date %}
<div class="event-date">
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="12" height="12" rx="2"/>
<path d="M2 7h12M6 3v2M10 3v2"/>
</svg>
{{ event.event_date.strftime('%d.%m.%Y') }}
</div>
{% endif %}
{% if event.source_url %}
<div class="event-source">
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 2l4 4-4 4M2 6h10"/>
</svg>
<a href="{{ event.source_url }}" target="_blank" rel="noopener noreferrer">
Źródło
</a>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
{% if total_pages > 1 %}
<div class="pagination">
{% if page > 1 %}
<a href="{{ url_for('events', type=event_type_filter, company=company_id, page=page-1) }}">← Poprzednia</a>
{% else %}
<span class="disabled">← Poprzednia</span>
{% endif %}
{% for p in range(1, total_pages + 1) %}
{% if p == page %}
<span class="current">{{ p }}</span>
{% elif p <= 3 or p >= total_pages - 2 or (p >= page - 1 and p <= page + 1) %}
<a href="{{ url_for('events', type=event_type_filter, company=company_id, page=p) }}">{{ p }}</a>
{% elif p == 4 or p == total_pages - 3 %}
<span>...</span>
{% endif %}
{% endfor %}
{% if page < total_pages %}
<a href="{{ url_for('events', type=event_type_filter, company=company_id, page=page+1) }}">Następna →</a>
{% else %}
<span class="disabled">Następna →</span>
{% endif %}
</div>
{% endif %}
{% else %}
<div class="empty-state">
<svg width="120" height="120" viewBox="0 0 120 120" fill="none" style="opacity: 0.3; margin-bottom: var(--spacing-md);">
<circle cx="60" cy="60" r="50" stroke="currentColor" stroke-width="4"/>
<path d="M40 50h40M40 70h20" stroke="currentColor" stroke-width="4" stroke-linecap="round"/>
</svg>
<h2>Brak wydarzeń</h2>
<p style="color: var(--text-secondary); margin-bottom: var(--spacing-lg);">
Nie znaleziono wydarzeń spełniających wybrane kryteria.
</p>
<a href="{{ url_for('events') }}" class="btn btn-primary">Pokaż wszystkie</a>
</div>
{% endif %}
{% endblock %}