rozbicie na moduły, poprawki i komendy cli

This commit is contained in:
Mateusz Gruszczyński
2026-03-20 10:43:40 +01:00
parent c5295fa49c
commit bbfb3e0887
48 changed files with 2125 additions and 1676 deletions

View File

@@ -0,0 +1,223 @@
{% extends 'base.html' %}
{% block title %}Ustawienia globalne{% endblock %}
{% block content %}
<div class="container my-4">
<!-- Nagłówek -->
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-4">
<div>
<h2 class="mb-1">Ustawienia globalne</h2>
<p class="text-muted mb-0">Konfiguracja systemu, płatności i wyglądu</p>
</div>
<div class="d-flex flex-wrap gap-2">
<a href="{{ url_for('admin_statystyki') }}" class="btn btn-outline-light">
Statystyki
</a>
<a href="{{ url_for('admin_dashboard') }}" class="btn btn-outline-light">
← Panel Admina
</a>
</div>
</div>
<form method="post" novalidate id="form-global-settings">
<!-- SEKCJA: Dane płatności -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-secondary text-white d-flex align-items-center justify-content-between gap-2">
<h3 class="card-title mb-0">Dane płatności</h3>
<small class="opacity-75">Wartości domyślne dla zbiórek</small>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-12">
<label for="numer_konta" class="form-label">Globalny numer konta (IBAN)</label>
<div class="input-group">
<span class="input-group-text">PL</span>
<input type="text" class="form-control" id="numer_konta" name="numer_konta"
value="{{ settings.numer_konta if settings else '' }}" inputmode="numeric" autocomplete="off"
placeholder="12 3456 7890 1234 5678 9012 3456" required aria-describedby="ibanHelp">
</div>
<div id="ibanHelp" class="form-text">Wpisz ciąg cyfr — spacje dodadzą się automatycznie co 4 znaki</div>
</div>
<div class="col-12 col-md-6">
<label for="numer_telefonu_blik" class="form-label">Globalny numer telefonu BLIK</label>
<div class="input-group">
<span class="input-group-text">+48</span>
<input type="tel" class="form-control" id="numer_telefonu_blik" name="numer_telefonu_blik"
value="{{ settings.numer_telefonu_blik if settings else '' }}" inputmode="tel" pattern="[0-9 ]{9,13}"
placeholder="123 456 789" required aria-describedby="blikHelp">
</div>
<div id="blikHelp" class="form-text">9 cyfr. Format 3-3-3 dla czytelności</div>
</div>
</div>
</div>
</div>
<!-- SEKCJA: Dostępy / biała lista IP -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-secondary text-white d-flex align-items-center justify-content-between gap-2">
<h3 class="card-title mb-0">Kontrola dostępu</h3>
<small class="opacity-75">Biała lista IP/hostów dla logowania</small>
</div>
<div class="card-body">
<!-- Wiersz z inputem i przyciskiem dodawania -->
<div class="row g-3 align-items-end">
<div class="col-12 col-lg-8">
<label for="host_input" class="form-label">Dodaj IP/host</label>
<div class="input-group">
<input type="text" class="form-control" id="host_input"
placeholder="np. 203.0.113.42 lub corp.example.com" aria-describedby="hostAddHelp">
<button type="button" class="btn btn-outline-light" id="btn-add-host">
Dodaj
</button>
</div>
<div id="hostAddHelp" class="form-text">Po wpisaniu kliknij „Dodaj". Duplikaty są pomijane</div>
</div>
<div class="col-12 col-lg-4">
<div class="d-flex flex-wrap gap-2 justify-content-lg-end">
<button type="button" class="btn btn-light text-dark" id="btn-add-my-ip" data-my-ip="{{ client_ip }}">
Dodaj moje IP ({{ client_ip }})
</button>
<button type="button" class="btn btn-outline-light" id="btn-dedupe">
Usuń duplikaty
</button>
</div>
</div>
</div>
<div class="mt-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<label for="dozwolone_hosty_logowania" class="form-label mb-0">
Dozwolone hosty logowania (jeden na linię lub rozdzielone przecinkami)
</label>
<span class="badge text-bg-secondary">Pozycji: <span id="hostsCount">0</span></span>
</div>
<textarea class="form-control" id="dozwolone_hosty_logowania" name="dozwolone_hosty_logowania" rows="6"
placeholder="Adresy IP lub nazwy domen — każdy w osobnej linii lub rozdzielony przecinkiem">{{ settings.dozwolone_hosty_logowania if settings and settings.dozwolone_hosty_logowania else '' }}</textarea>
<small class="text-muted d-block mt-1">
Akceptowane separatory: przecinek (`,`), średnik (`;`) i nowa linia
</small>
</div>
</div>
</div>
<!-- SEKCJA: Kolejność list rezerwowych -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-secondary text-white d-flex align-items-center justify-content-between gap-2">
<h3 class="card-title mb-0">Kolejność wyświetlania</h3>
<small class="opacity-75">Pozycja list rezerwowych na stronie głównej</small>
</div>
<div class="card-body">
<div class="mb-3">
<label for="kolejnosc_rezerwowych" class="form-label fw-semibold">Kolejność list rezerwowych</label>
<select class="form-select" id="kolejnosc_rezerwowych" name="kolejnosc_rezerwowych">
<option value="id" {% if settings and settings.kolejnosc_rezerwowych == 'id' %}selected{% endif %}>
Według ID (domyślnie)
</option>
<option value="first" {% if settings and settings.kolejnosc_rezerwowych == 'first' %}selected{% endif %}>
Jako pierwsze
</option>
<option value="last" {% if settings and settings.kolejnosc_rezerwowych == 'last' %}selected{% endif %}>
Jako ostatnie
</option>
</select>
<small class="text-muted d-block mt-1">Określa, gdzie na stronie głównej będą wyświetlane listy rezerwowe względem standardowych zbiórek</small>
</div>
</div>
</div>
<!-- SEKCJA: Branding -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-secondary text-white d-flex align-items-center justify-content-between gap-2">
<h3 class="card-title mb-0">Branding</h3>
<small class="opacity-75">Logo i tytuły wyświetlane w menu i stopce</small>
</div>
<div class="card-body">
<!-- Wspólne zasoby: logo + tytuł serwisu -->
<div class="row g-3 align-items-end">
<div class="col-md-6">
<label for="logo_url" class="form-label">Logo (URL PNG/SVG)</label>
<input type="text" class="form-control" id="logo_url" name="logo_url"
value="{{ settings.logo_url if settings else '' }}" placeholder="https://example.com/logo.svg">
<div class="form-text">Transparentne, do ~60px wysokości</div>
{% if settings and settings.logo_url %}
<div class="mt-2">
<img src="{{ settings.logo_url }}" alt="Logo preview" style="max-height:50px">
</div>
{% endif %}
</div>
<div class="col-md-6">
<label for="tytul_strony" class="form-label">Tytuł serwisu</label>
<input type="text" class="form-control" id="tytul_strony" name="tytul_strony"
value="{{ settings.tytul_strony if settings else '' }}" placeholder="Np. Zbiórki unitraklub.pl">
</div>
</div>
<hr class="my-4">
<!-- NAVBAR -->
<div class="row g-3">
<div class="col-md-6">
<h6 class="mb-2">Menu (navbar)</h6>
<div class="form-check">
<input class="form-check-input" type="radio" name="typ_navbar" id="navbar_mode_logo" value="logo" {% if
settings and settings.typ_navbar=='logo' or (settings and settings.pokaz_logo_w_navbar) %}checked{%
endif %}>
<label class="form-check-label" for="navbar_mode_logo">Pokaż logo</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="typ_navbar" id="navbar_mode_text" value="text" {% if
not settings or (settings and settings.typ_navbar !='logo' and not settings.pokaz_logo_w_navbar)
%}checked{% endif %}>
<label class="form-check-label" for="navbar_mode_text">Pokaż tekst</label>
</div>
<div class="form-text mt-1">Jeśli wybierzesz logo, użyjemy adresu z pola "Logo URL"</div>
</div>
<!-- STOPKA -->
<div class="col-md-6">
<h6 class="mb-2">Stopka</h6>
<div class="form-check">
<input class="form-check-input" type="radio" name="typ_stopka" id="footer_mode_logo" value="logo" {% if
settings and settings.typ_stopka=='logo' %}checked{% endif %}>
<label class="form-check-label" for="footer_mode_logo">Logo</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="typ_stopka" id="footer_mode_text" value="text" {% if
not settings or (settings and settings.typ_stopka !='logo' ) %}checked{% endif %}>
<label class="form-check-label" for="footer_mode_text">Tekst</label>
</div>
<label for="stopka_text" class="form-label mt-2">Tekst w stopce (gdy wybrano „Tekst")</label>
<input type="text" class="form-control" id="stopka_text" name="stopka_text"
value="{{ settings.stopka_text if settings and settings.stopka_text else '' }}"
placeholder="Np. © {{ now().year if now else '2025' }} Zbiórki">
<div class="form-text">Pozostaw pusty, by użyć domyślnego</div>
</div>
</div>
</div>
</div>
<!-- CTA -->
<div class="d-flex justify-content-between">
<a href="{{ url_for('admin_dashboard') }}" class="btn btn-outline-light">Powrót</a>
<button type="submit" class="btn btn-success">Zapisz ustawienia</button>
</div>
</form>
</div>
{% endblock %}
{% block extra_scripts %}
{{ super() }}
<script src="{{ asset_url('js/ustawienia.js') }}"></script>
{% endblock %}