Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Add profile links to usernames and avatars across forum, classifieds, announcements, company recommendations, board members, and group messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
465 lines
14 KiB
HTML
465 lines
14 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Strefa RADA - Norda Biznes Partner{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.meetings-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: var(--spacing-xl);
|
|
}
|
|
|
|
.meetings-header h1 {
|
|
font-size: var(--font-size-2xl);
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--spacing-md);
|
|
}
|
|
|
|
.meetings-header h1 svg {
|
|
color: #f59e0b;
|
|
}
|
|
|
|
.btn-new-meeting {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 20px;
|
|
background: var(--primary);
|
|
color: white;
|
|
border-radius: var(--radius-md);
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.btn-new-meeting:hover {
|
|
background: var(--primary-dark);
|
|
}
|
|
|
|
.btn-new-meeting svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
}
|
|
|
|
.meetings-grid {
|
|
display: grid;
|
|
gap: var(--spacing-md);
|
|
}
|
|
|
|
.meeting-card {
|
|
background: white;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--spacing-lg);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.meeting-card:hover {
|
|
border-color: var(--primary);
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.meeting-info {
|
|
flex: 1;
|
|
}
|
|
|
|
.meeting-title {
|
|
font-size: var(--font-size-lg);
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
margin-bottom: var(--spacing-xs);
|
|
}
|
|
|
|
.meeting-meta {
|
|
display: flex;
|
|
gap: var(--spacing-lg);
|
|
color: var(--text-secondary);
|
|
font-size: var(--font-size-sm);
|
|
}
|
|
|
|
.meeting-meta span {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.meeting-meta svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
|
|
.meeting-status {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 4px 12px;
|
|
border-radius: var(--radius-full);
|
|
font-size: var(--font-size-xs);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.meeting-status.draft {
|
|
background: #fef3c7;
|
|
color: #92400e;
|
|
}
|
|
|
|
.meeting-status.agenda_published {
|
|
background: #dbeafe;
|
|
color: #1e40af;
|
|
}
|
|
|
|
.meeting-status.protocol_draft {
|
|
background: #e0e7ff;
|
|
color: #3730a3;
|
|
}
|
|
|
|
.meeting-status.protocol_published {
|
|
background: #d1fae5;
|
|
color: #065f46;
|
|
}
|
|
|
|
a.meeting-status {
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
a.meeting-status:hover {
|
|
filter: brightness(0.9);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.meeting-actions {
|
|
display: flex;
|
|
gap: var(--spacing-sm);
|
|
}
|
|
|
|
.btn-view-meeting {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 8px 16px;
|
|
background: var(--bg-secondary);
|
|
color: var(--text-primary);
|
|
border-radius: var(--radius-md);
|
|
text-decoration: none;
|
|
font-size: var(--font-size-sm);
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.btn-view-meeting:hover {
|
|
background: var(--bg-tertiary);
|
|
}
|
|
|
|
.btn-view-meeting svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
|
|
.quick-actions {
|
|
display: flex;
|
|
gap: 4px;
|
|
}
|
|
|
|
.btn-quick {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 32px;
|
|
height: 32px;
|
|
background: var(--bg-secondary);
|
|
color: var(--text-secondary);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-md);
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-quick:hover {
|
|
background: var(--bg-tertiary);
|
|
color: var(--primary);
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.btn-quick svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
|
|
.btn-quick[title]:hover::after {
|
|
content: attr(title);
|
|
position: absolute;
|
|
bottom: -30px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
padding: 4px 8px;
|
|
background: #333;
|
|
color: white;
|
|
font-size: 11px;
|
|
border-radius: 4px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: var(--spacing-3xl);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.empty-state svg {
|
|
width: 64px;
|
|
height: 64px;
|
|
margin-bottom: var(--spacing-md);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.empty-state h3 {
|
|
color: var(--text-primary);
|
|
margin-bottom: var(--spacing-sm);
|
|
}
|
|
|
|
/* Board Members Section */
|
|
.board-members-section {
|
|
margin-top: var(--spacing-3xl);
|
|
padding-top: var(--spacing-xl);
|
|
border-top: 1px solid var(--border-color);
|
|
}
|
|
|
|
.board-members-section h2 {
|
|
font-size: var(--font-size-xl);
|
|
color: var(--text-primary);
|
|
margin-bottom: var(--spacing-lg);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--spacing-sm);
|
|
}
|
|
|
|
.board-members-section h2 svg {
|
|
width: 24px;
|
|
height: 24px;
|
|
color: #f59e0b;
|
|
}
|
|
|
|
.members-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
gap: var(--spacing-md);
|
|
}
|
|
|
|
.member-card {
|
|
background: white;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-md);
|
|
padding: var(--spacing-md);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--spacing-md);
|
|
}
|
|
|
|
.member-avatar {
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: 600;
|
|
color: #92400e;
|
|
font-size: var(--font-size-lg);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.member-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.member-name {
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.member-company {
|
|
font-size: var(--font-size-sm);
|
|
color: var(--text-secondary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.member-count {
|
|
font-size: var(--font-size-sm);
|
|
color: var(--text-muted);
|
|
margin-left: var(--spacing-sm);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.members-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="meetings-header">
|
|
<h1>
|
|
<svg width="32" height="32" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
Strefa RADA
|
|
</h1>
|
|
</div>
|
|
|
|
<!-- Board sub-navigation -->
|
|
<div style="display:flex;gap:0;margin-bottom:var(--spacing-xl);border-bottom:2px solid var(--border);align-items:flex-end;justify-content:space-between;">
|
|
<div style="display:flex;gap:0;">
|
|
<a href="{{ url_for('board.index') }}" style="padding:10px 20px;font-weight:500;font-size:var(--font-size-sm);text-decoration:none;border-bottom:2px solid {% if request.endpoint == 'board.index' %}var(--primary);color:var(--primary);margin-bottom:-2px;{% else %}transparent;color:var(--text-secondary);{% endif %}">Posiedzenia</a>
|
|
<a href="{{ url_for('board.board_fees') }}" style="padding:10px 20px;font-weight:500;font-size:var(--font-size-sm);text-decoration:none;border-bottom:2px solid {% if request.endpoint == 'board.board_fees' %}var(--primary);color:var(--primary);margin-bottom:-2px;{% else %}transparent;color:var(--text-secondary);{% endif %}">Składki członkowskie</a>
|
|
</div>
|
|
{% if can_manage %}
|
|
<a href="{{ url_for('board.meeting_create') }}" class="btn-new-meeting" style="margin-bottom:8px;">
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M12 4v16m8-8H4"/>
|
|
</svg>
|
|
Nowe posiedzenie
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if meetings %}
|
|
<div class="meetings-grid">
|
|
{% for meeting in meetings %}
|
|
<div class="meeting-card">
|
|
<div class="meeting-info">
|
|
<div class="meeting-title">
|
|
Posiedzenie nr {{ meeting.meeting_identifier }}
|
|
</div>
|
|
<div class="meeting-meta">
|
|
{% if meeting.meeting_date %}
|
|
<span>
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
{{ meeting.meeting_date.strftime('%d.%m.%Y') }}
|
|
</span>
|
|
{% endif %}
|
|
{% if meeting.start_time %}
|
|
<span>
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
{{ meeting.start_time.strftime('%H:%M') }}{% if meeting.end_time %} - {{ meeting.end_time.strftime('%H:%M') }}{% endif %}
|
|
</span>
|
|
{% endif %}
|
|
<span>
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
|
|
<path d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
|
|
</svg>
|
|
{{ meeting.location or 'Siedziba Izby' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="meeting-actions">
|
|
{% if meeting.status == 'agenda_published' %}
|
|
<a href="{{ url_for('board.meeting_view', meeting_id=meeting.id) }}#agenda" class="meeting-status {{ meeting.status }}">
|
|
Zobacz program
|
|
</a>
|
|
{% elif meeting.status == 'protocol_published' %}
|
|
<a href="{{ url_for('board.meeting_view', meeting_id=meeting.id) }}#proceedings" class="meeting-status {{ meeting.status }}">
|
|
Zobacz protokół
|
|
</a>
|
|
{% else %}
|
|
<span class="meeting-status {{ meeting.status }}">
|
|
{{ meeting.status_label }}
|
|
</span>
|
|
{% endif %}
|
|
<div class="quick-actions">
|
|
{% if can_manage %}
|
|
<a href="{{ url_for('board.meeting_edit', meeting_id=meeting.id) }}" class="btn-quick" title="Edytuj">
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
|
</svg>
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
{% if meeting.status not in ('agenda_published', 'protocol_published') %}
|
|
<a href="{{ url_for('board.meeting_view', meeting_id=meeting.id) }}" class="btn-view-meeting">
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
|
<path d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
|
|
</svg>
|
|
Zobacz
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="empty-state">
|
|
<svg fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
<h3>Brak posiedzeń</h3>
|
|
<p>Nie utworzono jeszcze żadnego posiedzenia Rady Izby.</p>
|
|
{% if can_manage %}
|
|
<a href="{{ url_for('board.meeting_create') }}" class="btn-new-meeting" style="margin-top: var(--spacing-md);">
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M12 4v16m8-8H4"/>
|
|
</svg>
|
|
Utwórz pierwsze posiedzenie
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Board Members Section -->
|
|
<div class="board-members-section">
|
|
<h2>
|
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
|
|
<circle cx="9" cy="7" r="4"/>
|
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
|
|
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
|
</svg>
|
|
Członkowie Rady Izby
|
|
<span class="member-count">({{ board_members|length }} osób)</span>
|
|
</h2>
|
|
|
|
<div class="members-grid">
|
|
{% for member in board_members %}
|
|
<a href="{{ url_for('public.user_profile', user_id=member.id) }}" class="member-card" style="text-decoration:none;color:inherit;">
|
|
<div class="member-avatar">
|
|
{% if member.avatar_path %}
|
|
<img src="{{ url_for('static', filename=member.avatar_path) }}" alt="{{ member.name }}" style="width:100%;height:100%;border-radius:50%;object-fit:cover;">
|
|
{% else %}
|
|
{{ member.name[:1].upper() if member.name else member.email[:1].upper() }}
|
|
{% endif %}
|
|
</div>
|
|
<div class="member-info">
|
|
<div class="member-name">{{ member.name or member.email.split('@')[0] }}</div>
|
|
{% if member.company %}
|
|
<div class="member-company">{{ member.company.name }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</a>
|
|
{% else %}
|
|
<p class="empty-state">Brak przypisanych członków Rady.</p>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|