policy : add privacy policy page
All checks were successful
Deploy Production / Deploy to Production (push) Successful in 28s

Blueprint, PHP templates, Svelte view (static title + body blocks), i18n key and App routing. Page is unlisted, excluded from frontend navigation, and all panel change options are disabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-05-12 18:10:54 +02:00
parent 12227dc50c
commit bf041f4f7a
7 changed files with 193 additions and 1 deletions

View file

@ -0,0 +1,45 @@
title: Confidentialité
icon: lock
image:
back: rgba(0,0,0, 0)
color: var(--color-green)
query: false
options:
delete: false
duplicate: false
move: false
changeTemplate: false
changeStatus: false
tabs:
content:
label: Contenu
icon: text
fields:
body:
label: Corps
type: blocks
fieldsets:
heading:
extends: blocks/heading
fields:
level:
default: h3
options:
h3: Titre H3
text:
extends: blocks/text
fields:
text:
headings:
- 3
nodes:
- heading
marks:
- bold
- italic
- underline
- strike
- link
list:
extends: blocks/list
seo: seo/page

View file

@ -31,7 +31,7 @@ return [
'a-propos' => menuItem('a-propos', 'À propos', 'users', 'pages/a-propos'),
'blog' => menuItem('blog', 'Blog', 'text', 'pages/blog'),
'white-papers' => menuItem('livres-blancs', 'Livres blancs', 'book', 'pages/livres-blancs'),
'confidentialite' => menuItem('confidentialite', 'Confidentialité', 'lock', 'pages/confidentialite'),
'confidentialite' => menuItem('confidentialite', 'Confidentialité', 'lock', 'pages/policy'),
'-',
'users',
'system',

View file

@ -0,0 +1,20 @@
<?php
$bodyBlocks = [];
foreach ($page->body()->toBlocks() as $block) {
if ($block->type() === 'text') {
$bodyBlocks[] = [
'type' => 'text',
'html' => $block->content()->text()->value(),
];
}
}
$specificData = [
'body' => $bodyBlocks,
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -0,0 +1,2 @@
<?php snippet('header') ?>
<?php snippet('footer') ?>

View file

@ -19,6 +19,7 @@
import Article from '@views/Article.svelte'
import WhitePapers from '@views/WhitePapers.svelte'
import Privacy from '@views/Privacy.svelte'
import Policy from '@views/Policy.svelte'
import Default from '@views/Default.svelte'
const templates = {
@ -33,6 +34,7 @@
article: Article,
'white-papers': WhitePapers,
privacy: Privacy,
policy: Policy,
default: Default
}
@ -45,6 +47,7 @@
about: [6, 8, 11, 14, 16],
portfolio: [11, 16],
privacy: [6, 8, 11, 14, 16],
policy: [6, 8, 11, 14, 16],
}
const ALL_COLS = [6, 8, 11, 14, 16]
const activeTemplate = $derived(slides.standalone?.template ?? slides.active?.template)

View file

@ -45,6 +45,7 @@ const dict = {
legal: { fr: "Mentions légales", en: "Legal notice" },
cookies: { fr: "Préférences cookies", en: "Cookie preferences" },
privacy: { fr: "Confidentialité", en: "Privacy" },
policy_title: { fr: "Confidentialité", en: "Policy" },
// About
our_team: { fr: "NOTRE ÉQUIPE", en: "OUR TEAM" },
prev_slide: { fr: "← PRÉCÉDENT", en: "← BEFORE" },

121
src/views/Policy.svelte Normal file
View file

@ -0,0 +1,121 @@
<script>
import { navigation } from '@state/navigation.svelte'
import { t } from '@i18n'
let { data } = $props()
const body = $derived(data?.body ?? [])
let sectionEl = $state(null)
</script>
<div
class="policy golden-grid page-scrollable"
bind:this={sectionEl}
onscroll={() => navigation.setScrolled(sectionEl.scrollTop > 100)}
>
<div class="page-container">
<h1 class="policy-title">{t('policy_title')}</h1>
{#if body.length > 0}
<section class="policy-body">
{#each body as block}
{#if block.type === 'text'}
<div class="policy-body-block">
{@html block.html}
</div>
{/if}
{/each}
</section>
{/if}
</div>
</div>
<style>
.policy {
min-height: 100vh;
color: #fff;
overflow-y: auto;
overflow-x: hidden;
}
.page-container {
grid-area: 6/6 / span 7 / span 10;
display: flex;
flex-direction: column;
width: 100%;
overflow: visible;
padding-bottom: 4rem;
}
.policy-title {
font-family: "Terminal", sans-serif;
font-size: var(--font-size-title-main);
color: white;
margin-bottom: 40px;
}
.policy-body {
width: 100%;
}
.policy-body-block {
border-left: 2px solid #04fea0;
padding-left: 20px;
margin: 3rem 0;
text-align: left;
font-family: "Danzza", sans-serif;
font-size: var(--font-size-paragraph);
font-weight: normal;
white-space: pre-line;
line-height: 1.6;
}
.policy-body-block :global(h3) {
font-family: Danzza Medium, sans-serif;
font-size: var(--font-size-paragraph);
margin-bottom: 1rem;
}
.policy-body-block :global(h3::before) {
content: '';
display: inline-block;
width: .6rem;
height: .6rem;
background-color: var(--color-primary);
margin-right: .6rem;
margin-bottom: .1rem;
}
.policy-body-block :global(p) {
opacity: 0.9;
margin-bottom: 0.75rem;
}
.policy-body-block :global(a) {
color: #04fea0;
}
/* ── Mobile (≤700px) ── */
@media (max-width: 700px) {
.page-container {
grid-area: auto;
width: 100vw;
padding-top: 6rem;
}
.policy-body {
padding: 0 1.25rem 2rem;
}
.policy-body-block {
font-size: var(--font-size-paragraph-small, 0.875rem);
}
}
/* ── Tablet (701px912px) ── */
@media (min-width: 701px) and (max-width: 912px) {
.policy-body-block {
font-size: var(--font-size-paragraph);
}
}
</style>