feat(membership): visual tracker + event history — parcel tracking style
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
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
This commit is contained in:
parent
73abb76c9e
commit
8441dc47db
@ -538,6 +538,110 @@
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
/* Tracker — parcel tracking style */
|
||||
.tracker-bar {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: 16px 0;
|
||||
}
|
||||
.tracker-step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 90px;
|
||||
}
|
||||
.tracker-dot {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: #e2e8f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
color: #94a3b8;
|
||||
border: 3px solid #e2e8f0;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.tracker-step.done .tracker-dot {
|
||||
background: #16a34a;
|
||||
border-color: #16a34a;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
}
|
||||
.tracker-step.current .tracker-dot {
|
||||
background: #2563eb;
|
||||
border-color: #2563eb;
|
||||
color: white;
|
||||
box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.2);
|
||||
}
|
||||
.tracker-step.rejected .tracker-dot {
|
||||
background: #dc2626;
|
||||
border-color: #dc2626;
|
||||
color: white;
|
||||
box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.2);
|
||||
}
|
||||
.tracker-label {
|
||||
margin-top: 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #94a3b8;
|
||||
text-align: center;
|
||||
}
|
||||
.tracker-step.done .tracker-label,
|
||||
.tracker-step.current .tracker-label { color: #1e293b; }
|
||||
.tracker-step.rejected .tracker-label { color: #dc2626; }
|
||||
.tracker-line {
|
||||
flex: 1;
|
||||
height: 3px;
|
||||
background: #e2e8f0;
|
||||
margin-top: 20px;
|
||||
min-width: 30px;
|
||||
}
|
||||
.tracker-line.done { background: #16a34a; }
|
||||
.tracker-note {
|
||||
text-align: center;
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.tracker-note.warning { background: #fef3c7; color: #92400e; }
|
||||
.tracker-note.info { background: #dbeafe; color: #1e40af; }
|
||||
|
||||
/* History list */
|
||||
.history-list { padding-left: 8px; }
|
||||
.history-item {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 8px 0;
|
||||
border-left: 2px solid #e2e8f0;
|
||||
padding-left: 16px;
|
||||
margin-left: 6px;
|
||||
position: relative;
|
||||
}
|
||||
.history-item:last-child { border-left-color: transparent; }
|
||||
.history-dot {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
position: absolute;
|
||||
left: -8px;
|
||||
top: 12px;
|
||||
}
|
||||
.dot-blue { background: #3b82f6; }
|
||||
.dot-yellow { background: #eab308; }
|
||||
.dot-green { background: #16a34a; }
|
||||
.dot-red { background: #dc2626; }
|
||||
.dot-orange { background: #f97316; }
|
||||
.dot-gray { background: #94a3b8; }
|
||||
.history-content { flex: 1; }
|
||||
.history-title { font-weight: 600; font-size: 13px; color: #1e293b; }
|
||||
.history-meta { font-size: 11px; color: #94a3b8; margin-top: 2px; }
|
||||
.history-comment { font-size: 12px; color: #64748b; font-style: italic; margin-top: 4px; }
|
||||
|
||||
/* Print styles */
|
||||
@media print {
|
||||
/* NUCLEAR: hide everything that isn't .print-header or .main-content */
|
||||
@ -970,79 +1074,93 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Historia workflow -->
|
||||
{% if application.workflow_history %}
|
||||
<!-- Tracker statusu deklaracji — styl "śledzenie paczki" -->
|
||||
<div class="section">
|
||||
<h2>Historia workflow</h2>
|
||||
<div class="workflow-timeline">
|
||||
{% for event in application.workflow_history %}
|
||||
{% if event.event == 'admin_proposed_changes' %}
|
||||
<div class="workflow-event sub-event">
|
||||
<div class="workflow-event-title">
|
||||
<span class="workflow-arrow">↓</span>
|
||||
Propozycja zmian
|
||||
</div>
|
||||
<div class="workflow-event-meta">
|
||||
Od: <strong>{{ event.user_name }}</strong>
|
||||
<br>{{ event.timestamp[:16].replace('T', ' ') }}
|
||||
{% if event.details.source %}
|
||||
<br>Źródło: {{ event.details.source }}
|
||||
<h2>Status deklaracji</h2>
|
||||
<div class="tracker">
|
||||
{% set steps = [
|
||||
{'key': 'submitted', 'icon': '📝', 'label': 'Złożona'},
|
||||
{'key': 'under_review', 'icon': '🔍', 'label': 'Rozpatrywana'},
|
||||
{'key': 'approved', 'icon': '✅', 'label': 'Zatwierdzona'},
|
||||
] %}
|
||||
{% set status_order = {'draft': 0, 'submitted': 1, 'under_review': 2, 'changes_requested': 2, 'pending_user_approval': 2, 'approved': 3, 'rejected': 3} %}
|
||||
{% set current_step = status_order.get(application.status, 0) %}
|
||||
|
||||
<div class="tracker-bar">
|
||||
{% for step in steps %}
|
||||
{% set step_num = loop.index %}
|
||||
{% set is_done = step_num <= current_step %}
|
||||
{% set is_current = step_num == current_step %}
|
||||
{% set is_rejected = application.status == 'rejected' and step_num == 3 %}
|
||||
|
||||
<div class="tracker-step {{ 'done' if is_done else '' }} {{ 'current' if is_current else '' }} {{ 'rejected' if is_rejected else '' }}">
|
||||
<div class="tracker-dot">
|
||||
{% if is_done and not is_current %}
|
||||
<span>✓</span>
|
||||
{% elif is_current %}
|
||||
<span>{{ step.icon }}</span>
|
||||
{% else %}
|
||||
<span>{{ loop.index }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if event.details.comment %}
|
||||
<div class="workflow-event-comment">
|
||||
„{{ event.details.comment }}"
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if event.details.changes %}
|
||||
<div style="font-size: var(--font-size-xs); margin-top: var(--spacing-xs); color: var(--text-secondary);">
|
||||
{% for change in event.details.changes %}
|
||||
<div>{{ change }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="tracker-label">{{ step.label }}</div>
|
||||
</div>
|
||||
{% elif event.event == 'user_accepted_changes' %}
|
||||
<div class="workflow-event sub-event">
|
||||
<div class="workflow-event-title">
|
||||
<span class="workflow-arrow">↑</span>
|
||||
Zmiany zaakceptowane
|
||||
</div>
|
||||
<div class="workflow-event-meta">
|
||||
Przez: <strong>{{ event.user_name }}</strong>
|
||||
<br>{{ event.timestamp[:16].replace('T', ' ') }}
|
||||
</div>
|
||||
</div>
|
||||
{% elif event.event == 'user_rejected_changes' %}
|
||||
<div class="workflow-event sub-event" style="border-color: var(--warning);">
|
||||
<div class="workflow-event-title" style="color: var(--warning);">
|
||||
<span class="workflow-arrow" style="color: var(--warning);">↑</span>
|
||||
Zmiany odrzucone
|
||||
</div>
|
||||
<div class="workflow-event-meta">
|
||||
Przez: <strong>{{ event.user_name }}</strong>
|
||||
<br>{{ event.timestamp[:16].replace('T', ' ') }}
|
||||
</div>
|
||||
{% if event.details.reason %}
|
||||
<div class="workflow-event-comment">
|
||||
„{{ event.details.reason }}"
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not loop.last %}
|
||||
<div class="tracker-line {{ 'done' if step_num < current_step else '' }}"></div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if application.status == 'rejected' %}
|
||||
<div class="tracker-line"></div>
|
||||
<div class="tracker-step current rejected">
|
||||
<div class="tracker-dot"><span>✗</span></div>
|
||||
<div class="tracker-label">Odrzucona</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{# Current pending status #}
|
||||
{% if application.status == 'pending_user_approval' %}
|
||||
<div class="workflow-event sub-event pending">
|
||||
<div class="workflow-event-title">
|
||||
<span class="workflow-arrow">⏳</span>
|
||||
Oczekuje na akceptację użytkownika
|
||||
</div>
|
||||
{% if application.status == 'changes_requested' %}
|
||||
<div class="tracker-note warning">
|
||||
⚠️ Poproszono o poprawki — oczekuje na korektę od zgłaszającego
|
||||
</div>
|
||||
{% elif application.status == 'pending_user_approval' %}
|
||||
<div class="tracker-note info">
|
||||
⏳ Zaproponowano zmiany z rejestru — oczekuje na akceptację użytkownika
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Historia zdarzeń (szczegóły) -->
|
||||
{% if application.workflow_history %}
|
||||
<div class="section">
|
||||
<h2>Historia zdarzeń</h2>
|
||||
<div class="history-list">
|
||||
{% for event in application.workflow_history|reverse %}
|
||||
<div class="history-item">
|
||||
<div class="history-dot
|
||||
{% if event.event == 'submitted' %}dot-blue
|
||||
{% elif event.event == 'start_review' %}dot-yellow
|
||||
{% elif event.event == 'approved' %}dot-green
|
||||
{% elif event.event == 'rejected' %}dot-red
|
||||
{% elif event.event == 'changes_requested' %}dot-orange
|
||||
{% else %}dot-gray{% endif %}
|
||||
"></div>
|
||||
<div class="history-content">
|
||||
<div class="history-title">{{ event.get('action_label', event.event) }}</div>
|
||||
<div class="history-meta">
|
||||
{{ event.timestamp[:16].replace('T', ' ') }}
|
||||
{% if event.user_name %} · {{ event.user_name }}{% endif %}
|
||||
</div>
|
||||
{% if event.get('details', {}).get('comment') %}
|
||||
<div class="history-comment">„{{ event.details.comment }}"</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Info o zgłaszającym -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user