nordabiz/templates/pwa_install.html
Maciej Pienczyn caa6cc45be
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
feat: add mobile PWA installation guide with smart banner
Mobile-only install instructions at /zainstaluj-aplikacje with
auto-detected iPhone/Android tabs, CSS UI mockups, and step-by-step
guide. Smart banner appears after 3s on mobile (dismissible via
localStorage), hidden in standalone mode. Footer link and login
page hint also mobile-only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:48:35 +01:00

530 lines
17 KiB
HTML

{% extends "base.html" %}
{% block title %}Zainstaluj aplikację - Norda Biznes Partner{% endblock %}
{% block extra_css %}
<style>
.pwa-page {
max-width: 540px;
margin: 0 auto;
padding: var(--spacing-xl) var(--spacing-md) var(--spacing-2xl);
}
.pwa-header {
text-align: center;
margin-bottom: var(--spacing-xl);
}
.pwa-header h1 {
font-size: var(--font-size-2xl);
color: var(--text-primary);
margin-bottom: var(--spacing-sm);
}
.pwa-header p {
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
/* Desktop fallback message */
.pwa-desktop-msg {
display: none;
text-align: center;
padding: var(--spacing-2xl) var(--spacing-lg);
background: var(--surface);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-md);
}
.pwa-desktop-msg .phone-icon {
font-size: 48px;
margin-bottom: var(--spacing-md);
}
.pwa-desktop-msg h2 {
font-size: var(--font-size-xl);
margin-bottom: var(--spacing-sm);
}
.pwa-desktop-msg p {
color: var(--text-secondary);
}
/* Tab switcher */
.pwa-tabs {
display: flex;
gap: var(--spacing-sm);
margin-bottom: var(--spacing-xl);
background: var(--surface);
border-radius: var(--radius-lg);
padding: 4px;
box-shadow: var(--shadow-sm);
}
.pwa-tab {
flex: 1;
padding: var(--spacing-md);
border: none;
background: transparent;
border-radius: var(--radius);
font-family: var(--font-family);
font-size: var(--font-size-base);
font-weight: 600;
cursor: pointer;
transition: var(--transition);
color: var(--text-secondary);
display: flex;
align-items: center;
justify-content: center;
gap: var(--spacing-sm);
}
.pwa-tab.active {
background: var(--primary);
color: white;
box-shadow: var(--shadow-sm);
}
.pwa-tab:not(.active):hover {
background: var(--background);
}
.pwa-tab-icon {
width: 20px;
height: 20px;
}
/* Step cards */
.pwa-steps {
display: none;
}
.pwa-steps.active {
display: block;
}
.pwa-step {
background: var(--surface);
border-radius: var(--radius-xl);
padding: var(--spacing-lg);
margin-bottom: var(--spacing-md);
box-shadow: var(--shadow-sm);
display: flex;
gap: var(--spacing-lg);
align-items: flex-start;
}
.pwa-step-number {
width: 48px;
height: 48px;
min-width: 48px;
border-radius: 50%;
background: var(--primary);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-size-xl);
font-weight: 700;
}
.pwa-step-content {
flex: 1;
}
.pwa-step-content h3 {
font-size: var(--font-size-base);
margin-bottom: var(--spacing-xs);
color: var(--text-primary);
}
.pwa-step-content p {
color: var(--text-secondary);
font-size: var(--font-size-sm);
margin-bottom: var(--spacing-sm);
}
/* CSS mockups */
.mockup-container {
display: flex;
justify-content: center;
margin-top: var(--spacing-sm);
}
/* iOS Share icon mockup */
.mockup-share-ios {
width: 32px;
height: 32px;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
.mockup-share-ios::before {
content: '';
width: 18px;
height: 18px;
border: 2.5px solid #007AFF;
border-top: none;
border-radius: 0 0 4px 4px;
position: absolute;
bottom: 2px;
}
.mockup-share-ios::after {
content: '';
width: 2.5px;
height: 16px;
background: #007AFF;
position: absolute;
top: 0;
}
.mockup-share-ios .arrow-head {
position: absolute;
top: -1px;
width: 10px;
height: 10px;
border-left: 2.5px solid #007AFF;
border-top: 2.5px solid #007AFF;
transform: rotate(45deg);
}
/* Android 3-dot menu mockup */
.mockup-dots-android {
display: flex;
flex-direction: column;
gap: 4px;
padding: 6px;
}
.mockup-dots-android span {
width: 5px;
height: 5px;
border-radius: 50%;
background: #5f6368;
}
/* Mockup button pill */
.mockup-btn {
display: inline-flex;
align-items: center;
gap: var(--spacing-sm);
padding: 8px 16px;
border-radius: 20px;
font-size: var(--font-size-sm);
font-weight: 600;
font-family: var(--font-family);
border: none;
pointer-events: none;
}
.mockup-btn-ios {
background: #007AFF;
color: white;
}
.mockup-btn-android {
background: #1a73e8;
color: white;
}
/* Pulse animation on key elements */
.pulse-highlight {
animation: pulseGlow 2s ease-in-out infinite;
}
@keyframes pulseGlow {
0%, 100% { box-shadow: 0 0 0 0 rgba(46, 72, 114, 0.4); }
50% { box-shadow: 0 0 0 8px rgba(46, 72, 114, 0); }
}
/* Mockup menu item highlight */
.mockup-menu-item {
background: var(--background);
border-radius: var(--radius);
padding: 8px 14px;
font-size: var(--font-size-sm);
color: var(--text-primary);
display: inline-flex;
align-items: center;
gap: var(--spacing-sm);
}
.mockup-menu-item.highlight {
background: #e8f0fe;
color: #1a73e8;
font-weight: 600;
}
/* Success section */
.pwa-success {
background: var(--surface);
border-radius: var(--radius-xl);
padding: var(--spacing-xl);
text-align: center;
box-shadow: var(--shadow-sm);
border: 2px solid var(--success);
}
.pwa-success h3 {
color: var(--success);
margin-bottom: var(--spacing-sm);
}
.pwa-success p {
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.pwa-success-icon-wrapper {
display: flex;
justify-content: center;
margin-bottom: var(--spacing-md);
}
.pwa-app-icon-mockup {
width: 64px;
height: 64px;
border-radius: 14px;
overflow: hidden;
box-shadow: var(--shadow-md);
}
.pwa-app-icon-mockup img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Safari warning for iOS */
.pwa-warning {
background: #FFF7ED;
border: 1px solid #FDBA74;
border-radius: var(--radius-lg);
padding: var(--spacing-md);
margin-bottom: var(--spacing-lg);
font-size: var(--font-size-sm);
color: #9A3412;
display: flex;
gap: var(--spacing-sm);
align-items: flex-start;
}
.pwa-warning-icon {
font-size: var(--font-size-xl);
line-height: 1;
flex-shrink: 0;
}
/* Mobile-only: show steps, hide desktop msg */
@media (max-width: 768px) {
.pwa-desktop-msg { display: none !important; }
.pwa-mobile-content { display: block !important; }
}
/* Desktop: show desktop msg, hide steps */
@media (min-width: 769px) {
.pwa-desktop-msg { display: block !important; }
.pwa-mobile-content { display: none !important; }
}
</style>
{% endblock %}
{% block content %}
<div class="pwa-page">
<div class="pwa-header">
<h1>Zainstaluj aplikację</h1>
<p>Norda Biznes Partner na ekranie Twojego telefonu</p>
</div>
<!-- Desktop fallback -->
<div class="pwa-desktop-msg">
<div class="phone-icon">📱</div>
<h2>Otwórz tę stronę na telefonie</h2>
<p>Instrukcja instalacji jest przeznaczona dla urządzeń mobilnych. Wejdź na <strong>nordabiznes.pl/zainstaluj-aplikacje</strong> w przeglądarce na swoim telefonie.</p>
</div>
<!-- Mobile content -->
<div class="pwa-mobile-content" style="display: none;">
<!-- Tab switcher -->
<div class="pwa-tabs">
<button class="pwa-tab active" data-target="ios" onclick="switchPwaTab('ios')">
<svg class="pwa-tab-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/></svg>
iPhone
</button>
<button class="pwa-tab" data-target="android" onclick="switchPwaTab('android')">
<svg class="pwa-tab-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"/></svg>
Android
</button>
</div>
<!-- iOS steps -->
<div class="pwa-steps active" id="pwa-ios">
<div class="pwa-warning">
<span class="pwa-warning-icon">⚠️</span>
<div><strong>Ważne:</strong> Na iPhonie instalacja działa <strong>tylko w Safari</strong>. Jeśli używasz Chrome lub innej przeglądarki, otwórz najpierw Safari.</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number">1</div>
<div class="pwa-step-content">
<h3>Otwórz Safari</h3>
<p>Wejdź na <strong>nordabiznes.pl</strong> w przeglądarce Safari na swoim iPhonie.</p>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number pulse-highlight">2</div>
<div class="pwa-step-content">
<h3>Stuknij przycisk „Udostępnij"</h3>
<p>Na dole ekranu znajdziesz ikonkę kwadratu ze strzałką w górę.</p>
<div class="mockup-container">
<div class="mockup-share-ios pulse-highlight" style="border-radius: 8px; padding: 8px; background: #f0f0f0;">
<span class="arrow-head"></span>
</div>
</div>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number">3</div>
<div class="pwa-step-content">
<h3>Przewiń menu w dół</h3>
<p>Znajdź opcję:</p>
<div class="mockup-container">
<span class="mockup-menu-item highlight">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1a73e8" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
Dodaj do ekranu początkowego
</span>
</div>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number">4</div>
<div class="pwa-step-content">
<h3>Potwierdź „Dodaj"</h3>
<p>Stuknij przycisk <strong>Dodaj</strong> w prawym górnym rogu.</p>
<div class="mockup-container">
<span class="mockup-btn mockup-btn-ios">Dodaj</span>
</div>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number" style="background: var(--success);"></div>
<div class="pwa-step-content">
<h3>Gotowe!</h3>
<p>Ikona Norda Biznes pojawi się na Twoim ekranie głównym.</p>
</div>
</div>
<div class="pwa-success">
<div class="pwa-success-icon-wrapper">
<div class="pwa-app-icon-mockup">
<img src="{{ url_for('static', filename='img/favicon-192.png') }}" alt="Ikona Norda Biznes">
</div>
</div>
<h3>Norda Biznes Partner</h3>
<p>Aplikacja otworzy się w trybie pełnoekranowym — tak jak prawdziwa aplikacja ze sklepu!</p>
</div>
</div>
<!-- Android steps -->
<div class="pwa-steps" id="pwa-android">
<div class="pwa-step">
<div class="pwa-step-number">1</div>
<div class="pwa-step-content">
<h3>Otwórz Chrome</h3>
<p>Wejdź na <strong>nordabiznes.pl</strong> w przeglądarce Chrome na swoim telefonie.</p>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number pulse-highlight">2</div>
<div class="pwa-step-content">
<h3>Stuknij menu (trzy kropki)</h3>
<p>W prawym górnym rogu ekranu znajdziesz ikonkę trzech kropek.</p>
<div class="mockup-container">
<div class="mockup-dots-android pulse-highlight" style="border-radius: 8px; padding: 10px 8px; background: #f0f0f0;">
<span></span>
<span></span>
<span></span>
</div>
</div>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number">3</div>
<div class="pwa-step-content">
<h3>Wybierz „Zainstaluj aplikację"</h3>
<p>Na niektórych telefonach opcja może nazywać się „Dodaj do ekranu głównego".</p>
<div class="mockup-container">
<span class="mockup-menu-item highlight">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1a73e8" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
Zainstaluj aplikację
</span>
</div>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number">4</div>
<div class="pwa-step-content">
<h3>Potwierdź „Zainstaluj"</h3>
<p>Stuknij przycisk <strong>Zainstaluj</strong> w okienku potwierdzenia.</p>
<div class="mockup-container">
<span class="mockup-btn mockup-btn-android">Zainstaluj</span>
</div>
</div>
</div>
<div class="pwa-step">
<div class="pwa-step-number" style="background: var(--success);"></div>
<div class="pwa-step-content">
<h3>Gotowe!</h3>
<p>Ikona Norda Biznes pojawi się na Twoim ekranie głównym.</p>
</div>
</div>
<div class="pwa-success">
<div class="pwa-success-icon-wrapper">
<div class="pwa-app-icon-mockup">
<img src="{{ url_for('static', filename='img/favicon-192.png') }}" alt="Ikona Norda Biznes">
</div>
</div>
<h3>Norda Biznes Partner</h3>
<p>Aplikacja otworzy się w trybie pełnoekranowym — tak jak prawdziwa aplikacja ze sklepu!</p>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
// Auto-detect platform
(function() {
var ua = navigator.userAgent || '';
var isIOS = /iPad|iPhone|iPod/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
if (!isIOS && /Android/i.test(ua)) {
switchPwaTab('android');
}
})();
function switchPwaTab(platform) {
// Update tabs
document.querySelectorAll('.pwa-tab').forEach(function(tab) {
tab.classList.toggle('active', tab.getAttribute('data-target') === platform);
});
// Update step panels
document.querySelectorAll('.pwa-steps').forEach(function(panel) {
panel.classList.toggle('active', panel.id === 'pwa-' + platform);
});
}
{% endblock %}