This commit is contained in:
@@ -426,16 +426,19 @@ public enum SettingKey {
|
|||||||
"Linia w stopce: nazwa spółki, adres, numery rejestrowe.",
|
"Linia w stopce: nazwa spółki, adres, numery rejestrowe.",
|
||||||
Requirement.OPTIONAL_EMPTY),
|
Requirement.OPTIONAL_EMPTY),
|
||||||
/*
|
/*
|
||||||
* Adresy dokumentow, a nie ich tresc. Regulamin i polityka prywatnosci
|
* NADPISANIE adresu dokumentu, a nie jego tresc. Platforma ma wbudowany
|
||||||
* bywaja wspolne dla calej firmy i utrzymywane poza ta aplikacja, wiec
|
* regulamin (UswiadUE) i polityke prywatnosci (RODO), skladane z danych
|
||||||
* wskazanie adresu jest tansze niz przepisywanie dokumentu do panelu.
|
* firmy: strony `/regulamin` i `/polityka-prywatnosci` istnieja zawsze.
|
||||||
* Puste ukrywa odnosnik: lepiej go nie pokazac, niz prowadzic donikad.
|
* Te dwa klucze sluza wylacznie instancji, ktora utrzymuje wspolny dla
|
||||||
|
* calej firmy dokument poza ta aplikacja i chce na niego kierowac.
|
||||||
|
* Puste NIE ukrywa juz odnosnika: stopka prowadzi wtedy do strony
|
||||||
|
* wbudowanej, ktora zawsze ma tresc.
|
||||||
*/
|
*/
|
||||||
ACADEMY_TERMS_URL(SettingType.STRING, "",
|
ACADEMY_TERMS_URL(SettingType.STRING, "",
|
||||||
"Adres regulaminu. Puste ukrywa odnośnik w stopce.",
|
"Zewnętrzny adres regulaminu. Puste = wbudowany regulamin platformy.",
|
||||||
Requirement.OPTIONAL_EMPTY),
|
Requirement.OPTIONAL_EMPTY),
|
||||||
ACADEMY_PRIVACY_URL(SettingType.STRING, "",
|
ACADEMY_PRIVACY_URL(SettingType.STRING, "",
|
||||||
"Adres polityki prywatności. Puste ukrywa odnośnik w stopce.",
|
"Zewnętrzny adres polityki prywatności. Puste = wbudowana polityka platformy.",
|
||||||
Requirement.OPTIONAL_EMPTY),
|
Requirement.OPTIONAL_EMPTY),
|
||||||
/*
|
/*
|
||||||
* Prog uznania lekcji wideo za obejrzana. Wartosc domyslna jest nizsza niz
|
* Prog uznania lekcji wideo za obejrzana. Wartosc domyslna jest nizsza niz
|
||||||
|
|||||||
@@ -206,11 +206,17 @@ function initials(firstName: string | null, lastName: string | null) {
|
|||||||
* wybrano 1a, bo miesci odnosniki serwisowe i dane spolki, ktore i tak
|
* wybrano 1a, bo miesci odnosniki serwisowe i dane spolki, ktore i tak
|
||||||
* musza gdzies byc, a jednolinijkowa wersja wypycha je do tresci strony.
|
* musza gdzies byc, a jednolinijkowa wersja wypycha je do tresci strony.
|
||||||
*
|
*
|
||||||
* KAZDY ODNOSNIK JEST OPCJONALNY.
|
* REGULAMIN I POLITYKA ZAWSZE MAJA DOKAD PROWADZIC.
|
||||||
* ---------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------
|
||||||
* Pusty adres regulaminu UKRYWA odnosnik, zamiast prowadzic pod pusta
|
* Platforma ma WBUDOWANE dokumenty prawne (`/regulamin`,
|
||||||
* sciezke: odnosnik donikad jest gorszy niz jego brak. Znika sam odnosnik,
|
* `/polityka-prywatnosci`): regulamin wedlug UswiadUE i polityke wedlug RODO,
|
||||||
* nie cala stopka.
|
* skladane z danych firmy z ustawien. Odnosnik prowadzi wiec domyslnie do
|
||||||
|
* naszej wlasnej strony i NIGDY nie jest martwy.
|
||||||
|
*
|
||||||
|
* Adres zewnetrzny (`termsUrl`/`privacyUrl` z ustawien) jest wylacznie
|
||||||
|
* NADPISANIEM dla instancji, ktora utrzymuje wspolny dla firmy dokument poza
|
||||||
|
* ta aplikacja. Pusty adres nie ukrywa juz odnosnika: kieruje go na strone
|
||||||
|
* wbudowana, ktora zawsze istnieje.
|
||||||
*/
|
*/
|
||||||
export function AcademyFooter({
|
export function AcademyFooter({
|
||||||
text,
|
text,
|
||||||
@@ -218,7 +224,9 @@ export function AcademyFooter({
|
|||||||
privacyUrl,
|
privacyUrl,
|
||||||
}: {
|
}: {
|
||||||
text?: string
|
text?: string
|
||||||
|
/** Zewnetrzny adres regulaminu. Puste = strona wbudowana `/regulamin`. */
|
||||||
termsUrl?: string
|
termsUrl?: string
|
||||||
|
/** Zewnetrzny adres polityki. Puste = strona wbudowana `/polityka-prywatnosci`. */
|
||||||
privacyUrl?: string
|
privacyUrl?: string
|
||||||
}) {
|
}) {
|
||||||
const { brandName } = usePublicConfig()
|
const { brandName } = usePublicConfig()
|
||||||
@@ -262,31 +270,16 @@ export function AcademyFooter({
|
|||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-semibold text-white">Dokumenty</p>
|
<p className="text-sm font-semibold text-white">Dokumenty</p>
|
||||||
<nav className="mt-3 flex flex-col gap-2 text-sm">
|
<nav className="mt-3 flex flex-col gap-2 text-sm">
|
||||||
{/* Pusty adres ukrywa sam odnosnik, nie cala kolumne. */}
|
{/*
|
||||||
{termsUrl ? (
|
Odnosnik prowadzi domyslnie do strony wbudowanej, ktora zawsze
|
||||||
<a
|
istnieje; adres zewnetrzny z ustawien tylko go nadpisuje.
|
||||||
href={termsUrl}
|
*/}
|
||||||
target="_blank"
|
<LegalLink internalPath="/regulamin" externalUrl={termsUrl}>
|
||||||
rel="noopener noreferrer"
|
Regulamin
|
||||||
className="text-slate-400 transition-colors duration-fast hover:text-white"
|
</LegalLink>
|
||||||
>
|
<LegalLink internalPath="/polityka-prywatnosci" externalUrl={privacyUrl}>
|
||||||
Regulamin
|
Polityka prywatności
|
||||||
</a>
|
</LegalLink>
|
||||||
) : (
|
|
||||||
<span className="text-slate-500">Regulamin</span>
|
|
||||||
)}
|
|
||||||
{privacyUrl ? (
|
|
||||||
<a
|
|
||||||
href={privacyUrl}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-slate-400 transition-colors duration-fast hover:text-white"
|
|
||||||
>
|
|
||||||
Polityka prywatności
|
|
||||||
</a>
|
|
||||||
) : (
|
|
||||||
<span className="text-slate-500">Polityka prywatności</span>
|
|
||||||
)}
|
|
||||||
<Link
|
<Link
|
||||||
to="/certyfikat"
|
to="/certyfikat"
|
||||||
className="text-slate-400 transition-colors duration-fast hover:text-white"
|
className="text-slate-400 transition-colors duration-fast hover:text-white"
|
||||||
@@ -307,3 +300,38 @@ export function AcademyFooter({
|
|||||||
</footer>
|
</footer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Odnosnik do dokumentu prawnego w stopce.
|
||||||
|
*
|
||||||
|
* Bez adresu zewnetrznego prowadzi do strony WBUDOWANEJ (react-router `Link`,
|
||||||
|
* bez przeladowania). Z adresem zewnetrznym otwiera go w nowej karcie
|
||||||
|
* (`<a target="_blank">` z `rel="noopener noreferrer"`, bo adres pochodzi
|
||||||
|
* z ustawien i wskazuje obca domene). W obu przypadkach odnosnik istnieje:
|
||||||
|
* nie ma juz wariantu wyszarzonego, bo dokument wbudowany zawsze jest.
|
||||||
|
*/
|
||||||
|
function LegalLink({
|
||||||
|
internalPath,
|
||||||
|
externalUrl,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
internalPath: string
|
||||||
|
externalUrl?: string
|
||||||
|
children: ReactNode
|
||||||
|
}) {
|
||||||
|
const className =
|
||||||
|
'text-slate-400 transition-colors duration-fast hover:text-white'
|
||||||
|
|
||||||
|
if (externalUrl && externalUrl.trim()) {
|
||||||
|
return (
|
||||||
|
<a href={externalUrl} target="_blank" rel="noopener noreferrer" className={className}>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Link to={internalPath} className={className}>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { PublicLayout } from './PublicLayout'
|
import { Link } from 'react-router-dom'
|
||||||
|
import { AcademyLayout } from '../../academy/AcademyLayout'
|
||||||
|
import { Icon } from '../../components/Icon'
|
||||||
import { useLegal } from '../../lib/useLegal'
|
import { useLegal } from '../../lib/useLegal'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,6 +11,15 @@ import { useLegal } from '../../lib/useLegal'
|
|||||||
* obecne, a w miejsce danych firmy podstawiane sa wartosci z konfiguracji.
|
* obecne, a w miejsce danych firmy podstawiane sa wartosci z konfiguracji.
|
||||||
* Obowiazek informacyjny RODO jest juz czescia tresci polityki, wiec strona
|
* Obowiazek informacyjny RODO jest juz czescia tresci polityki, wiec strona
|
||||||
* tylko ja wyswietla.
|
* tylko ja wyswietla.
|
||||||
|
*
|
||||||
|
* UZYWA `AcademyLayout`, nie `PublicLayout`.
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
* Regulamin i polityka to strony serwisu, do ktorych uzytkownik trafia ze
|
||||||
|
* stopki strony glownej, wiec maja miec ten sam naglowek i te sama stopke co
|
||||||
|
* strona glowna: pasek nawigacji (Kursy/Webinary/Cennik), odnosnik do panelu
|
||||||
|
* albo konta zaleznie od zalogowania oraz logo linkujace do strony glownej.
|
||||||
|
* `PublicLayout` jest waski i pozbawiony nawigacji - pasuje do formularza
|
||||||
|
* zapisu otwieranego z linku w mailu, nie do samodzielnej strony serwisu.
|
||||||
*/
|
*/
|
||||||
export function LegalPage({ kind }: { kind: 'terms' | 'privacy' }) {
|
export function LegalPage({ kind }: { kind: 'terms' | 'privacy' }) {
|
||||||
const legal = useLegal()
|
const legal = useLegal()
|
||||||
@@ -17,8 +28,17 @@ export function LegalPage({ kind }: { kind: 'terms' | 'privacy' }) {
|
|||||||
const html = kind === 'terms' ? legal.data?.termsHtml : legal.data?.privacyHtml
|
const html = kind === 'terms' ? legal.data?.termsHtml : legal.data?.privacyHtml
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PublicLayout wide>
|
<AcademyLayout>
|
||||||
<article className="space-y-6">
|
<article className="space-y-6">
|
||||||
|
{/* Wyrazny powrot do strony glownej nad tytulem, obok logo w naglowku. */}
|
||||||
|
<Link
|
||||||
|
to="/"
|
||||||
|
className="inline-flex items-center gap-1.5 text-sm text-slate-500 transition-colors duration-fast hover:text-slate-900"
|
||||||
|
>
|
||||||
|
<Icon name="arrow-left" size={16} />
|
||||||
|
Strona główna
|
||||||
|
</Link>
|
||||||
|
|
||||||
<h1 className="text-2xl font-semibold text-slate-900">{title}</h1>
|
<h1 className="text-2xl font-semibold text-slate-900">{title}</h1>
|
||||||
|
|
||||||
{legal.isPending ? (
|
{legal.isPending ? (
|
||||||
@@ -32,6 +52,6 @@ export function LegalPage({ kind }: { kind: 'terms' | 'privacy' }) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</article>
|
</article>
|
||||||
</PublicLayout>
|
</AcademyLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user