Compare commits
8 Commits
146e738c09
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a805610cba | ||
|
|
40929b3604 | ||
|
|
6b73e91ddb | ||
|
|
abc3bd4d41 | ||
|
|
e0095ee10f | ||
|
|
bbb6742849 | ||
|
|
2c30704a11 | ||
|
|
95b308455c |
1425
astro-pages-dump.txt
1425
astro-pages-dump.txt
File diff suppressed because it is too large
Load Diff
95
astro.py
95
astro.py
@@ -1,95 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def iter_astro_files(root: Path) -> list[Path]:
|
|
||||||
"""Zwraca listę plików .astro w root (rekursywnie), posortowaną stabilnie."""
|
|
||||||
files = [p for p in root.rglob("*.astro") if p.is_file()]
|
|
||||||
# sortowanie po ścieżce względnej dla powtarzalności
|
|
||||||
files.sort(key=lambda p: str(p.as_posix()).lower())
|
|
||||||
return files
|
|
||||||
|
|
||||||
|
|
||||||
def read_text_fallback(p: Path) -> str:
|
|
||||||
"""
|
|
||||||
Czyta plik jako tekst:
|
|
||||||
- najpierw UTF-8
|
|
||||||
- jeśli się nie da, to z BOM/latin-1 jako awaryjne (bez crasha)
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return p.read_text(encoding="utf-8")
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
# Spróbuj UTF-8 z BOM
|
|
||||||
try:
|
|
||||||
return p.read_text(encoding="utf-8-sig")
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
# Ostatecznie: latin-1 (nie idealne, ale nie przerwie działania)
|
|
||||||
return p.read_text(encoding="latin-1")
|
|
||||||
|
|
||||||
|
|
||||||
def build_output(pages_dir: Path, files: list[Path]) -> str:
|
|
||||||
rel_root = pages_dir.parent.parent # zwykle ./src -> parent parent? NIEPEWNE, więc liczymy inaczej
|
|
||||||
# lepiej: relatywnie do katalogu projektu (cwd)
|
|
||||||
cwd = Path.cwd()
|
|
||||||
|
|
||||||
lines: list[str] = []
|
|
||||||
lines.append(f"ASTRO DUMP (root: {pages_dir.resolve()})")
|
|
||||||
lines.append(f"Found files: {len(files)}")
|
|
||||||
lines.append("=" * 80)
|
|
||||||
lines.append("")
|
|
||||||
|
|
||||||
for f in files:
|
|
||||||
rel = f.relative_to(cwd) if f.is_relative_to(cwd) else f
|
|
||||||
content = read_text_fallback(f)
|
|
||||||
|
|
||||||
lines.append(f"FILE: {rel.as_posix()}")
|
|
||||||
lines.append("-" * 80)
|
|
||||||
lines.append(content.rstrip("\n"))
|
|
||||||
lines.append("")
|
|
||||||
lines.append("=" * 80)
|
|
||||||
lines.append("")
|
|
||||||
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="Zrzuca wszystkie pliki .astro z ./src/pages do jednego pliku txt (ścieżka + zawartość)."
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--pages",
|
|
||||||
default="src/pages",
|
|
||||||
help="Ścieżka do katalogu pages (domyślnie: src/pages)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--out",
|
|
||||||
default="astro-pages-dump.txt",
|
|
||||||
help="Plik wyjściowy (domyślnie: astro-pages-dump.txt)",
|
|
||||||
)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
pages_dir = Path(args.pages).resolve()
|
|
||||||
out_file = Path(args.out).resolve()
|
|
||||||
|
|
||||||
if not pages_dir.exists() or not pages_dir.is_dir():
|
|
||||||
print(f"[ERR] Nie znaleziono katalogu: {pages_dir}", file=sys.stderr)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
files = iter_astro_files(pages_dir)
|
|
||||||
|
|
||||||
dump = build_output(pages_dir, files)
|
|
||||||
|
|
||||||
out_file.write_text(dump, encoding="utf-8")
|
|
||||||
print(f"[OK] Zapisano: {out_file} (files: {len(files)})")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, List, Set, Tuple
|
|
||||||
|
|
||||||
# --- Regexy do zbierania klas z CSS ---
|
|
||||||
# Łapie ".class-name" w selektorach (pomija np. ".5" i rzeczy z escapami – prosto, ale działa w praktyce)
|
|
||||||
CSS_CLASS_RE = re.compile(r'(?<![\\\w-])\.([a-zA-Z_-][\w-]*)')
|
|
||||||
|
|
||||||
# --- Regexy do zbierania stringów klas z Astro/JSX/TSX ---
|
|
||||||
# 1) class="..."
|
|
||||||
CLASS_ATTR_RE = re.compile(r'\bclass\s*=\s*("([^"]*)"|\'([^\']*)\')', re.IGNORECASE)
|
|
||||||
# 2) className="..."
|
|
||||||
CLASSNAME_ATTR_RE = re.compile(r'\bclassName\s*=\s*("([^"]*)"|\'([^\']*)\')', re.IGNORECASE)
|
|
||||||
|
|
||||||
# Astro: class:list={{ a: cond, "b c": cond2 }} / class:list={[...]} – tu łapiemy stringi w środku
|
|
||||||
STRING_LIT_RE = re.compile(r'("([^"]+)"|\'([^\']+)\')')
|
|
||||||
|
|
||||||
# Dla wyszukiwania tokenów klas (żeby "f-card" nie matchowało jako fragment "f-card-x")
|
|
||||||
def token_pattern(cls: str) -> re.Pattern:
|
|
||||||
return re.compile(r'(?<![\w-])' + re.escape(cls) + r'(?![\w-])')
|
|
||||||
|
|
||||||
def read_text(path: Path) -> str:
|
|
||||||
try:
|
|
||||||
return path.read_text(encoding="utf-8", errors="ignore")
|
|
||||||
except Exception:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def collect_css_classes(css_dir: Path) -> Tuple[Set[str], Dict[str, Set[Path]]]:
|
|
||||||
classes: Set[str] = set()
|
|
||||||
where: Dict[str, Set[Path]] = {}
|
|
||||||
|
|
||||||
for p in css_dir.rglob("*.css"):
|
|
||||||
txt = read_text(p)
|
|
||||||
for m in CSS_CLASS_RE.finditer(txt):
|
|
||||||
c = m.group(1)
|
|
||||||
classes.add(c)
|
|
||||||
where.setdefault(c, set()).add(p)
|
|
||||||
|
|
||||||
return classes, where
|
|
||||||
|
|
||||||
def collect_used_classes(code_dir: Path, candidates: Set[str]) -> Tuple[Set[str], Dict[str, Set[Path]]]:
|
|
||||||
used: Set[str] = set()
|
|
||||||
used_where: Dict[str, Set[Path]] = {c: set() for c in candidates}
|
|
||||||
|
|
||||||
exts = {".astro", ".jsx", ".tsx", ".js", ".ts"}
|
|
||||||
# prekompilacja patternów dla szybkości
|
|
||||||
patterns = {c: token_pattern(c) for c in candidates}
|
|
||||||
|
|
||||||
for p in code_dir.rglob("*"):
|
|
||||||
if not p.is_file():
|
|
||||||
continue
|
|
||||||
if p.suffix.lower() not in exts:
|
|
||||||
continue
|
|
||||||
|
|
||||||
txt = read_text(p)
|
|
||||||
if not txt:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# szybki filtr: jeśli żaden kandydat nie ma nawet prefiksu "f-" / "jmb-" itd,
|
|
||||||
# to i tak skan tokenowy jest ok, ale tu robimy prosty scan wszystkich.
|
|
||||||
for c, pat in patterns.items():
|
|
||||||
if pat.search(txt):
|
|
||||||
used.add(c)
|
|
||||||
used_where[c].add(p)
|
|
||||||
|
|
||||||
# usuń puste wpisy
|
|
||||||
used_where = {k: v for k, v in used_where.items() if v}
|
|
||||||
return used, used_where
|
|
||||||
|
|
||||||
def main():
|
|
||||||
ap = argparse.ArgumentParser(description="Znajdź potencjalnie nieużywane klasy CSS w projekcie Astro/JSX.")
|
|
||||||
ap.add_argument("--css", required=True, help="Katalog z plikami CSS (np. src/styles)")
|
|
||||||
ap.add_argument("--code", required=True, help="Katalog z kodem (np. src)")
|
|
||||||
ap.add_argument("--min-len", type=int, default=3, help="Minimalna długość nazwy klasy (domyślnie 3)")
|
|
||||||
ap.add_argument("--prefix", action="append", default=[], help="Filtruj klasy po prefiksie (np. --prefix f- --prefix jmb-)")
|
|
||||||
ap.add_argument("--show-where", action="store_true", help="Pokaż gdzie zdefiniowano klasę w CSS")
|
|
||||||
args = ap.parse_args()
|
|
||||||
|
|
||||||
css_dir = Path(args.css).resolve()
|
|
||||||
code_dir = Path(args.code).resolve()
|
|
||||||
|
|
||||||
if not css_dir.exists():
|
|
||||||
raise SystemExit(f"Brak katalogu CSS: {css_dir}")
|
|
||||||
if not code_dir.exists():
|
|
||||||
raise SystemExit(f"Brak katalogu code: {code_dir}")
|
|
||||||
|
|
||||||
all_classes, defined_where = collect_css_classes(css_dir)
|
|
||||||
|
|
||||||
# filtr długości + prefiksów
|
|
||||||
classes = {c for c in all_classes if len(c) >= args.min_len}
|
|
||||||
if args.prefix:
|
|
||||||
classes = {c for c in classes if any(c.startswith(px) for px in args.prefix)}
|
|
||||||
|
|
||||||
used, used_where = collect_used_classes(code_dir, classes)
|
|
||||||
unused = sorted(classes - used)
|
|
||||||
|
|
||||||
print(f"CSS katalog: {css_dir}")
|
|
||||||
print(f"CODE katalog: {code_dir}")
|
|
||||||
print(f"Klasy w CSS: {len(classes)} (po filtrach)")
|
|
||||||
print(f"Użyte w kodzie:{len(used)}")
|
|
||||||
print(f"NIEUŻYTE: {len(unused)}")
|
|
||||||
print("-" * 60)
|
|
||||||
|
|
||||||
for c in unused:
|
|
||||||
print(c)
|
|
||||||
if args.show_where:
|
|
||||||
files = sorted(defined_where.get(c, []))
|
|
||||||
for f in files:
|
|
||||||
rel = f.relative_to(css_dir.parent) if css_dir.parent in f.parents else f
|
|
||||||
print(f" defined in: {rel}")
|
|
||||||
print("-" * 60)
|
|
||||||
|
|
||||||
# opcjonalnie: pokaż top kilka użyć
|
|
||||||
# (jak chcesz, dopiszę flagę na raport "gdzie użyte")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
BIN
public/files/cennik_uslug_dodatkowych.pdf
Normal file
BIN
public/files/cennik_uslug_dodatkowych.pdf
Normal file
Binary file not shown.
BIN
public/files/cennik_uslug_tv.pdf
Normal file
BIN
public/files/cennik_uslug_tv.pdf
Normal file
Binary file not shown.
BIN
public/files/formularz_odstapienia_net.pdf
Normal file
BIN
public/files/formularz_odstapienia_net.pdf
Normal file
Binary file not shown.
BIN
public/files/informacje_przedumowne_net.pdf
Normal file
BIN
public/files/informacje_przedumowne_net.pdf
Normal file
Binary file not shown.
BIN
public/files/informacje_przedumowne_tv.pdf
Normal file
BIN
public/files/informacje_przedumowne_tv.pdf
Normal file
Binary file not shown.
BIN
public/files/informacje_urządzenia_net.pdf
Normal file
BIN
public/files/informacje_urządzenia_net.pdf
Normal file
Binary file not shown.
BIN
public/files/oświadczenia_net.pdf
Normal file
BIN
public/files/oświadczenia_net.pdf
Normal file
Binary file not shown.
BIN
public/files/podsumowanie_warunków_umowy_net.pdf
Normal file
BIN
public/files/podsumowanie_warunków_umowy_net.pdf
Normal file
Binary file not shown.
BIN
public/files/podsumowanie_warunków_umowy_tv.pdf
Normal file
BIN
public/files/podsumowanie_warunków_umowy_tv.pdf
Normal file
Binary file not shown.
BIN
public/files/umowa_internet.pdf
Normal file
BIN
public/files/umowa_internet.pdf
Normal file
Binary file not shown.
BIN
public/files/umowa_tv.pdf
Normal file
BIN
public/files/umowa_tv.pdf
Normal file
Binary file not shown.
@@ -1,21 +1,68 @@
|
|||||||
tytul: Dokumenty
|
tytul: Dokumenty
|
||||||
opis: Strona zawiera dokumnety do pobrania lub przeczytania
|
opis: |
|
||||||
|
Poniżej dostępne są dokumenty regulujące zasady świadczenia usług, w szczególności regulaminy, cenniki oraz obowiązujące umowy.
|
||||||
|
|
||||||
grupy:
|
grupy:
|
||||||
pobierz:
|
# Grupa 1: Polityki i regulaminy
|
||||||
tytul: Pobierz
|
polityki:
|
||||||
pliki:
|
tytul: Polityki i regulaminy
|
||||||
- nazwa: Lista kanałów EVIO TV
|
|
||||||
file: /public/files/EVIO TV.pdf
|
|
||||||
- nazwa: Lista kanałów JAMBOX TV
|
|
||||||
file: /public/files/EVIO TV.pdf
|
|
||||||
- nazwa: Lista kanałów coś
|
|
||||||
file: /public/files/EVIO TV.pdf
|
|
||||||
|
|
||||||
otworz:
|
|
||||||
tytul: Przeczytaj
|
|
||||||
pliki:
|
pliki:
|
||||||
- nazwa: Polityka prywatności
|
- nazwa: Polityka prywatności
|
||||||
slug: polityka-prywatnosci
|
slug: polityka-prywatnosci
|
||||||
- nazwa: Promocja przykład do wyswietlenia
|
|
||||||
slug: promocja
|
# - nazwa: Regulamin świadczenia usług
|
||||||
|
# slug: regulamin-uslug
|
||||||
|
|
||||||
|
# - nazwa: Informacja o przetwarzaniu danych osobowych
|
||||||
|
# slug: rodo
|
||||||
|
|
||||||
|
# Grupa 2: Internet
|
||||||
|
internet:
|
||||||
|
tytul: Internet
|
||||||
|
pliki:
|
||||||
|
- nazwa: Umowa Internet
|
||||||
|
file: /files/umowa_internet.pdf
|
||||||
|
|
||||||
|
- nazwa: Informacje przedumowne Internet
|
||||||
|
file: /files/informacje_przedumowne_net.pdf
|
||||||
|
|
||||||
|
- nazwa: Podsumowanie warunków umowy Internet
|
||||||
|
file: /files/podsumowanie_warunków_umowy_net.pdf
|
||||||
|
|
||||||
|
- nazwa: Oświadczenia Internet
|
||||||
|
file: /files/oświadczenia_net.pdf
|
||||||
|
|
||||||
|
- nazwa: Informacje urządzenia Internet
|
||||||
|
file: /files/informacje_urządzenia_net.pdf
|
||||||
|
|
||||||
|
- nazwa: Formularz odstąpienia Internet
|
||||||
|
file: /files/formularz_odstapienia_net.pdf
|
||||||
|
|
||||||
|
# Grupa 3: Telewizja
|
||||||
|
telewizja:
|
||||||
|
tytul: Internet i Telewizja
|
||||||
|
pliki:
|
||||||
|
- nazwa: Umowa TV
|
||||||
|
file: /files/umowa_tv.pdf
|
||||||
|
|
||||||
|
- nazwa: Podsumowanie warunków umowy TV
|
||||||
|
file: /files/podsumowanie_warunków_umowy_tv.pdf
|
||||||
|
|
||||||
|
- nazwa: Informacje przedumowne TV
|
||||||
|
file: /files/informacje_przedumowne_tv.pdf
|
||||||
|
|
||||||
|
- nazwa: Lista kanałów EVIO TV
|
||||||
|
file: /files/EVIO TV.pdf
|
||||||
|
|
||||||
|
- nazwa: Lista kanałów JAMBOX TV
|
||||||
|
file: /files/JAMBOX TV.pdf
|
||||||
|
|
||||||
|
# Grupa 4: Cenniki
|
||||||
|
cenniki:
|
||||||
|
tytul: Cenniki
|
||||||
|
pliki:
|
||||||
|
- nazwa: Cennik usług TV
|
||||||
|
file: /files/cennik_uslug_tv.pdf
|
||||||
|
|
||||||
|
- nazwa: Cennik usług dodatkowych
|
||||||
|
file: /files/cennik_uslug_dodatkowych.pdf
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
title: "Promocja świąteczna"
|
|
||||||
description: Przykładowo gdybysmy dodali promocję do dokumentów
|
|
||||||
visible: true
|
|
||||||
content: |
|
|
||||||
Jeśli kupujesz w sklepach internetowych, prawdopodobnie co pewien czas natykasz się na opisy, które nie zachęcają do zakupów.
|
|
||||||
Do najczęściej powtarzanych błędów opisów produktów należą:
|
|
||||||
|
|
||||||
- brak konkretów – klient chce wiedzieć, z czego produkt jest wykonany, jakie ma wymiary czy funkcje, a nie tylko, że jest „wysokiej jakości”;
|
|
||||||
- zbyt techniczny język – warto dostosować ton komunikacji do odbiorcy, unikając skomplikowanych terminów (i w drugą stronę – jeśli sprzedajesz towar skierowany do profesjonalistów, nie trzeba w opisie ze szczegółami wyjaśniać, jak działa czy do czego służy);
|
|
||||||
- brak narracji – storytelling w opisach produktów pomaga zbudować emocjonalne zaangażowanie klienta;
|
|
||||||
|
|
||||||
ignorowanie pytań klientów – warto analizować najczęstsze pytania i uwzględniać odpowiedzi w opisach; jeśli np. często dostajesz zapytania dotyczące tego, czy produkt jest wodoodporny, lepiej napisać o tym od razu w opisie;
|
|
||||||
|
|
||||||
zbyt długie i skomplikowane opisy – należy dbać o przejrzystość treści, używać krótkich akapitów i list wypunktowanych; klient poszukuje konkretów, a nie zawiłych opowieści, które trudno się czyta.
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
page:
|
page:
|
||||||
title: "Dokumenty - FUZ Adam Rojek | Regulaminy i Umowy"
|
title: "Dokumenty - FUZ Adam Rojek | Regulaminy i Umowy"
|
||||||
description: "Dokumenty FUZ: regulamin świadczenia usług, wzór umowy, cennik, polityka prywatności, warunki techniczne. Wszystkie dokumenty do pobrania w formacie PDF."
|
description: "Dokumenty i regulaminy, cenniki oraz umowy związane z usługami oferowanymi przez naszą firmę."
|
||||||
image: "/og/dokumenty-og.png"
|
image: "/og/dokumenty-og.png"
|
||||||
url: "/dokumenty"
|
url: "/dokumenty"
|
||||||
keywords:
|
keywords:
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ opis: |
|
|||||||
Wybierz rodzaj budynku i czas trwania umowy
|
Wybierz rodzaj budynku i czas trwania umowy
|
||||||
uwaga: |
|
uwaga: |
|
||||||
Powyższe „ceny brutto z Rabatami 15zł”
|
Powyższe „ceny brutto z Rabatami 15zł”
|
||||||
uwzględniają rabat -15 zł (z czego -5 zł - Rabat za wyrażenie zgody na otrzymywanie Rachunków/faktur VAT za świadczone
|
uwzględniają rabat -15 zł (z czego -5 zł - Rabat za wyrażenie zgody na otrzymywanie Rachunków/faktur VAT za świadczone przez Dostawcę Usług usługi telekomunikacyjne drogą elektroniczną na wskazany w umowie adres e-mail oraz za pośrednictwem EBOK;
|
||||||
przez Dostawcę Usług usługi telekomunikacyjne drogą elektroniczną na wskazany w umowie adres mail oraz za pośrednictwem EBOK; -10 zł - Rabat pod warunkiem
|
-10 zł - Rabat pod warunkiem złożenia wniosku o dostarczanie przez Dostawcę Usług treści każdej proponowanej zmiany warunków Umowy, w tym określonych w Umowie, Informacjach Przedumownych oraz danych Dostawcy Usług (chyba że przepisy powszechnie
|
||||||
złożenia wniosku o dostarczanie przez Dostawcę Usług treści każdej proponowanej zmiany warunków Umowy, w tym określonych w Umowie, Informacjach Przedumownych oraz danych Dostawcy Usług (chyba że przepisy powszechnie obowiązującego prawa przewidują wyłącznie zawiadomienia poprzez publiczne ogłoszenie), jak
|
obowiązującego prawa przewidują wyłącznie zawiadomienia poprzez publiczne ogłoszenie), jak również kontakt w ramach procedur reklamacyjnych, w tym w szczególności przesłania odpowiedzi na reklamację, na podany w Umowie adres poczty elektronicznej).
|
||||||
również kontaktowanie się ze mną w ramach procedur reklamacyjnych, w tym w szczególności przesłania odpowiedzi na reklamację, na podany w Umowie adres poczty
|
|
||||||
elektronicznej).
|
|
||||||
cena_opis: "zł/mies."
|
cena_opis: "zł/mies."
|
||||||
|
|
||||||
cards:
|
cards:
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ export default function JamboxMozliwosciSearch({ items = [] }) {
|
|||||||
className={`f-section-image ${reverse ? "md:order-1" : "md:order-2"}`}
|
className={`f-section-image ${reverse ? "md:order-1" : "md:order-2"}`}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
|
width="800"
|
||||||
|
height="600"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -6,72 +6,94 @@ import {
|
|||||||
normalizePublicHref,
|
normalizePublicHref,
|
||||||
type DocumentsYaml,
|
type DocumentsYaml,
|
||||||
} from "../../lib/astro-helpers";
|
} from "../../lib/astro-helpers";
|
||||||
|
import "../../styles/document.css";
|
||||||
|
|
||||||
const doc = loadYaml<DocumentsYaml>("./src/content/document/documents.yaml");
|
const doc = loadYaml<DocumentsYaml>("./src/content/document/documents.yaml");
|
||||||
const seo = loadYaml("./src/content/document/seo.yaml");
|
const seo = loadYaml("./src/content/document/seo.yaml");
|
||||||
|
|
||||||
const pageTitle = doc?.tytul ?? "Dokumenty";
|
const pageTitle = doc?.tytul ?? "Dokumenty";
|
||||||
const pageDesc = doc?.opis ?? "";
|
const pageDesc = doc?.opis ?? "";
|
||||||
|
|
||||||
const groups = doc?.grupy ?? {};
|
const groups = doc?.grupy ?? {};
|
||||||
const left = groups["otworz"] ?? {};
|
|
||||||
const right = groups["pobierz"] ?? {};
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<DefaultLayout seo={seo}>
|
<DefaultLayout seo={seo}>
|
||||||
{/* CONTENT */}
|
|
||||||
<section class="f-section">
|
<section class="f-section">
|
||||||
<div class="f-section-grid-top md:grid-cols-2 gap-10 items-start">
|
<div class="f-section-grid md:grid-cols-1">
|
||||||
{/* ===== LEWA – CZYTAJ ===== */}
|
<h1 class="f-section-title">{pageTitle}</h1>
|
||||||
<div>
|
{pageDesc && <Markdown text={pageDesc} />}
|
||||||
<h3 class="f-section-title">{left.tytul ?? "Przeczytaj"}</h3>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="f-section">
|
||||||
|
<div class="f-section-documents">
|
||||||
|
<div class="f-documents-columns">
|
||||||
{
|
{
|
||||||
!left.pliki?.length ? (
|
Object.entries(groups).map(([key, group]) => (
|
||||||
<p class="opacity-70 mt-4">Brak dokumentów.</p>
|
<div class="f-documents-group" key={key}>
|
||||||
) : (
|
<h3 class="f-section-title3">{group.tytul}</h3>
|
||||||
<div class="f-documents-grid">
|
|
||||||
{left.pliki.map((p) =>
|
{!group.pliki?.length ? (
|
||||||
p.slug ? (
|
<p class="f-documents-empty">Brak dokumentów.</p>
|
||||||
<a
|
) : (
|
||||||
class="f-document-card"
|
<div class="f-documents-list">
|
||||||
href={`/dokumenty/${p.slug}`}
|
{group.pliki.map((p) => {
|
||||||
title={p.nazwa}
|
// Określ czy to slug (czytaj) czy file (pobierz)
|
||||||
>
|
const isRead = !!p.slug;
|
||||||
<div class="f-document-title">{p.nazwa}</div>
|
const href = isRead
|
||||||
</a>
|
? `/dokumenty/${p.slug}`
|
||||||
) : null,
|
: normalizePublicHref(p.file);
|
||||||
|
|
||||||
|
if (!href) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
class="f-document-link"
|
||||||
|
href={href}
|
||||||
|
{...(isRead ? {} : { download: true })}
|
||||||
|
title={p.nazwa}
|
||||||
|
>
|
||||||
|
<span class="f-document-icon">
|
||||||
|
{isRead ? (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
|
||||||
|
<circle cx="12" cy="12" r="3" />
|
||||||
|
</svg>
|
||||||
|
) : (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
||||||
|
<polyline points="7 10 12 15 17 10" />
|
||||||
|
<line x1="12" x2="12" y1="15" y2="3" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span class="f-document-name">{p.nazwa}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
))
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 class="f-section-title">{right.tytul ?? "Pobierz"}</h3>
|
|
||||||
|
|
||||||
{
|
|
||||||
!right.pliki?.length ? (
|
|
||||||
<p class="opacity-70 mt-4">Brak plików.</p>
|
|
||||||
) : (
|
|
||||||
<div class="f-documents-grid">
|
|
||||||
{right.pliki.map((p) => {
|
|
||||||
const href = normalizePublicHref(p.file);
|
|
||||||
if (!href) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
class="f-document-card"
|
|
||||||
href={href}
|
|
||||||
download
|
|
||||||
title={p.nazwa}
|
|
||||||
>
|
|
||||||
<div class="f-document-title">{p.nazwa}</div>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,15 +1,37 @@
|
|||||||
.f-document-card {
|
.f-section-documents {
|
||||||
@apply flex items-center gap-2 text-lg;
|
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
|
||||||
}
|
}
|
||||||
.f-document-card:hover {
|
.f-documents-columns {
|
||||||
@apply shadow-sm;
|
@apply grid grid-cols-1 gap-8 mt-1;
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .f-document-icon {
|
@media (min-width: 768px) {
|
||||||
@apply text-2xl leading-none mt-1;
|
.f-documents-columns {
|
||||||
} */
|
@apply grid-cols-2;
|
||||||
|
}
|
||||||
.f-document-title {
|
|
||||||
@apply font-normal ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.f-documents-columns {
|
||||||
|
@apply grid-cols-3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-section-title3{
|
||||||
|
@apply border-b-[1px] border-[var(--f-offers-border)];
|
||||||
|
}
|
||||||
|
.f-documents-group {
|
||||||
|
@apply bg-[--f-bg] text-[--f-text] border border-[--f-offers-border] rounded-2xl shadow-md p-6 relative flex flex-col gap-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-documents-list {
|
||||||
|
@apply flex flex-col gap-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-document-link {
|
||||||
|
@apply flex items-center py-1 gap-2 rounded-lg text-[var(--f-text,#111827)] no-underline transition-all duration-200 bg-transparent border border-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-document-icon {
|
||||||
|
@apply flex-shrink-0 w-5 h-5 transition-all duration-200 text-[var(--f-text-muted,#6b7280)];
|
||||||
|
}
|
||||||
@@ -41,6 +41,10 @@
|
|||||||
@apply text-4xl md:text-5xl font-bold mb-2 text-[--f-header];
|
@apply text-4xl md:text-5xl font-bold mb-2 text-[--f-header];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.f-section-title3 {
|
||||||
|
@apply text-2xl md:text-2xl font-bold mb-2 text-[--f-header];
|
||||||
|
}
|
||||||
|
|
||||||
.f-section-nav {
|
.f-section-nav {
|
||||||
@apply mt-0 flex justify-center;
|
@apply mt-0 flex justify-center;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user