Migration vers architecture Svelte + Kirby inspirée de design-to-pack

- Mise en place de Svelte 4 avec Vite pour le frontend (SPA)
- Simplification des templates PHP (header/footer minimalistes)
- Création de templates JSON pour API (home, about, expertise, portfolio, jouer, game, blog, article, project)
- Ajout d'un controller de site pour définir genericData globalement
- Structure des stores Svelte (page, navigation, locale, site)
- Router avec navaid pour navigation SPA et interception des liens
- Composants layout (Header, Footer, Cursor) et vues de base
- Build Vite vers assets/dist/ (index.js/css)
- Header PHP détecte assets/dist pour basculer dev/prod

Architecture fonctionnelle de base établie, à améliorer et compléter.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-02-06 16:30:15 +01:00
parent c4456d587c
commit cbe89acb21
53 changed files with 3348 additions and 772 deletions

View file

@ -0,0 +1,34 @@
<?php
$specificData = [
'intro' => [
'title' => $page->intro_title()->value(),
'text' => $page->intro_text()->value()
],
'mission' => [
'title' => $page->mission_title()->value(),
'text' => $page->mission_text()->toBlocks()
],
'manifesto' => [
'title' => $page->manifesto_title()->value(),
'text' => $page->manifesto_text()->toBlocks()
],
'team' => [
'title' => $page->team_title()->value(),
'members' => $page->team_members()->toStructure()->map(function($member) {
return [
'name' => $member->name()->value(),
'role' => $member->role()->value(),
'bio' => $member->bio()->value(),
'photo' => $member->photo()->toFile()?->url(),
'linkedin' => $member->linkedin()->value(),
'twitter' => $member->twitter()->value()
];
})->values()
]
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,81 +1,2 @@
<?php snippet('header') ?>
<main class="about">
<!-- Intro Section -->
<section class="about__intro">
<h1 class="about__title"><?= $page->intro_title() ?></h1>
<?php if ($page->intro_text()->isNotEmpty()): ?>
<p class="about__subtitle"><?= $page->intro_text() ?></p>
<?php endif ?>
</section>
<!-- Mission Section -->
<?php if ($page->mission_text()->isNotEmpty()): ?>
<section class="about__mission">
<h2 class="about__section-title"><?= $page->mission_title() ?></h2>
<div class="about__section-content">
<?= $page->mission_text()->toBlocks() ?>
</div>
</section>
<?php endif ?>
<!-- Manifesto Section -->
<?php if ($page->manifesto_text()->isNotEmpty()): ?>
<section class="about__manifesto">
<h2 class="about__section-title"><?= $page->manifesto_title() ?></h2>
<div class="about__section-content">
<?= $page->manifesto_text()->toBlocks() ?>
</div>
</section>
<?php endif ?>
<!-- Team Section -->
<?php if ($page->team_members()->isNotEmpty()): ?>
<section class="about__team">
<h2 class="about__section-title"><?= $page->team_title() ?></h2>
<div class="about__team-grid">
<?php foreach ($page->team_members()->toStructure() as $member): ?>
<article class="team-card">
<?php if ($photo = $member->photo()->toFile()): ?>
<div class="team-card__photo">
<img src="<?= $photo->url() ?>" alt="<?= $member->name() ?>">
</div>
<?php endif ?>
<div class="team-card__info">
<h3 class="team-card__name"><?= $member->name() ?></h3>
<p class="team-card__role"><?= $member->role() ?></p>
<?php if ($member->bio()->isNotEmpty()): ?>
<p class="team-card__bio"><?= $member->bio() ?></p>
<?php endif ?>
<div class="team-card__social">
<?php if ($member->linkedin()->isNotEmpty()): ?>
<a href="<?= $member->linkedin() ?>" target="_blank" class="team-card__social-link">
LinkedIn
</a>
<?php endif ?>
<?php if ($member->twitter()->isNotEmpty()): ?>
<a href="<?= $member->twitter() ?>" target="_blank" class="team-card__social-link">
Twitter
</a>
<?php endif ?>
</div>
</div>
</article>
<?php endforeach ?>
</div>
<nav class="about__team-nav">
<button class="about__team-prev">&larr; Précédent</button>
<button class="about__team-next">Suivant &rarr;</button>
</nav>
</section>
<?php endif ?>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,34 @@
<?php
$related = $page->related_articles()->toPages();
if ($related->isEmpty()) {
$related = $page->siblings()->listed()->not($page)->shuffle()->limit(3);
}
$specificData = [
'date' => $page->date()->toDate('Y-m-d'),
'date_formatted' => $page->date()->toDate('d/m/Y'),
'intro' => $page->intro()->value(),
'author' => [
'name' => $page->author_name()->value(),
'role' => $page->author_role()->value(),
'photo' => $page->author_photo()->toFile()?->url()
],
'cover' => $page->cover()->toFile()?->url(),
'content' => $page->article_content()->toBlocks(),
'tags' => $page->tags()->split(),
'related' => $related->map(function($rec) {
return [
'title' => $rec->title()->value(),
'url' => $rec->url(),
'category' => $rec->category()->value(),
'cover' => $rec->cover()->toFile()?->thumb(['width' => 400])->url()
];
})->values(),
'parent_url' => $page->parent()->url()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,101 +1,2 @@
<?php snippet('header') ?>
<main class="article">
<article class="article__content">
<!-- Header -->
<header class="article__header">
<?php if ($page->date()->isNotEmpty()): ?>
<time class="article__date" datetime="<?= $page->date()->toDate('Y-m-d') ?>">
Publié le <?= $page->date()->toDate('d/m/Y') ?>
</time>
<?php endif ?>
<h1 class="article__title"><?= $page->title() ?></h1>
<?php if ($page->intro()->isNotEmpty()): ?>
<p class="article__intro"><?= $page->intro() ?></p>
<?php endif ?>
</header>
<!-- Author -->
<?php if ($page->author_name()->isNotEmpty()): ?>
<div class="article__author">
<?php if ($photo = $page->author_photo()->toFile()): ?>
<img src="<?= $photo->url() ?>" alt="<?= $page->author_name() ?>" class="article__author-photo">
<?php endif ?>
<div class="article__author-info">
<span class="article__author-name"><?= $page->author_name() ?></span>
<?php if ($page->author_role()->isNotEmpty()): ?>
<span class="article__author-role"><?= $page->author_role() ?></span>
<?php endif ?>
</div>
</div>
<?php endif ?>
<!-- Cover Image -->
<?php if ($cover = $page->cover()->toFile()): ?>
<figure class="article__cover">
<img src="<?= $cover->url() ?>" alt="<?= $page->title() ?>">
</figure>
<?php endif ?>
<!-- Content -->
<div class="article__body">
<?= $page->article_content()->toBlocks() ?>
</div>
<!-- Tags -->
<?php if ($page->tags()->isNotEmpty()): ?>
<div class="article__tags">
<?php foreach ($page->tags()->split() as $tag): ?>
<span class="article__tag"><?= $tag ?></span>
<?php endforeach ?>
</div>
<?php endif ?>
</article>
<!-- Recommendations -->
<?php
$related = $page->related_articles()->toPages();
if ($related->isEmpty()) {
$related = $page->siblings()->listed()->not($page)->shuffle()->limit(3);
}
?>
<?php if ($related->isNotEmpty()): ?>
<section class="article__recommendations">
<h2 class="article__recommendations-title">Nos recommandations</h2>
<a href="<?= $page->parent()->url() ?>" class="article__recommendations-link">Voir tous les articles &rarr;</a>
<div class="article__recommendations-grid">
<?php foreach ($related as $rec): ?>
<article class="recommendation-card">
<?php if ($cover = $rec->cover()->toFile()): ?>
<div class="recommendation-card__cover">
<img src="<?= $cover->thumb(['width' => 400])->url() ?>" alt="<?= $rec->title() ?>">
</div>
<?php endif ?>
<?php if ($rec->category()->isNotEmpty()): ?>
<span class="recommendation-card__category"><?= $rec->category() ?></span>
<?php endif ?>
<h3 class="recommendation-card__title">
<a href="<?= $rec->url() ?>"><?= $rec->title() ?></a>
</h3>
</article>
<?php endforeach ?>
</div>
</section>
<?php endif ?>
<!-- Navigation -->
<nav class="article__nav">
<a href="<?= $page->parent()->url() ?>" class="article__nav-back">
&larr; Tous les articles
</a>
</nav>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,26 @@
<?php
$specificData = [
'intro' => [
'title' => $page->intro_title()->value(),
'text' => $page->intro_text()->value()
],
'articles' => $page->children()->listed()->sortBy('date', 'desc')->map(function($article) {
return [
'title' => $article->title()->value(),
'slug' => $article->slug(),
'url' => $article->url(),
'date' => $article->date()->toDate('Y-m-d'),
'date_formatted' => $article->date()->toDate('d/m/Y'),
'intro' => $article->intro()->excerpt(200),
'cover' => $article->cover()->toFile()?->url(),
'author_name' => $article->author_name()->value(),
'author_photo' => $article->author_photo()->toFile()?->url()
];
})->values()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,61 +1,2 @@
<?php snippet('header') ?>
<main class="blog">
<!-- Intro Section -->
<section class="blog__intro">
<h1 class="blog__title"><?= $page->intro_title() ?></h1>
<?php if ($page->intro_text()->isNotEmpty()): ?>
<p class="blog__subtitle"><?= $page->intro_text() ?></p>
<?php endif ?>
</section>
<!-- Articles List -->
<section class="blog__articles">
<?php foreach ($page->children()->listed()->sortBy('date', 'desc') as $article): ?>
<article class="article-card">
<!-- Date -->
<?php if ($article->date()->isNotEmpty()): ?>
<time class="article-card__date" datetime="<?= $article->date()->toDate('Y-m-d') ?>">
<?= $article->date()->toDate('d/m/Y') ?>
</time>
<?php endif ?>
<!-- Content -->
<div class="article-card__content">
<h2 class="article-card__title">
<a href="<?= $article->url() ?>"><?= $article->title() ?></a>
</h2>
<?php if ($article->intro()->isNotEmpty()): ?>
<p class="article-card__intro"><?= $article->intro()->excerpt(200) ?></p>
<?php endif ?>
<a href="<?= $article->url() ?>" class="article-card__link">
Lire la suite &rarr;
</a>
</div>
<!-- Author -->
<div class="article-card__author">
<?php if ($photo = $article->author_photo()->toFile()): ?>
<img src="<?= $photo->url() ?>" alt="<?= $article->author_name() ?>" class="article-card__author-photo">
<?php endif ?>
<?php if ($article->author_name()->isNotEmpty()): ?>
<span class="article-card__author-name"><?= $article->author_name() ?></span>
<?php endif ?>
</div>
<!-- Cover Image -->
<?php if ($cover = $article->cover()->toFile()): ?>
<div class="article-card__cover">
<img src="<?= $cover->url() ?>" alt="<?= $article->title() ?>">
</div>
<?php endif ?>
</article>
<?php endforeach ?>
</section>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,10 @@
<?php
$specificData = [
'body' => $page->body()->toBlocks()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1 +1,2 @@
<h1><?= $page->title() ?></h1>
<?php snippet('header') ?>
<?php snippet('footer') ?>

View file

@ -0,0 +1,24 @@
<?php
$specificData = [
'intro' => [
'title' => $page->intro_title()->value(),
'text' => $page->intro_text()->value()
],
'sections' => $page->expertise_sections()->toStructure()->map(function($section) {
return [
'title' => $section->title()->value(),
'icon' => $section->icon()->value(),
'content' => $section->content()->toBlocks()
];
})->values(),
'objective' => [
'title' => $page->objective_title()->value(),
'text' => $page->objective_text()->value()
]
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,36 +1,2 @@
<?php snippet('header') ?>
<main class="expertise">
<!-- Intro Section -->
<section class="expertise__intro">
<h1 class="expertise__title"><?= $page->intro_title() ?></h1>
<?php if ($page->intro_text()->isNotEmpty()): ?>
<p class="expertise__text"><?= $page->intro_text() ?></p>
<?php endif ?>
</section>
<!-- Expertise Sections -->
<?php if ($page->expertise_sections()->isNotEmpty()): ?>
<div class="expertise__sections">
<?php foreach ($page->expertise_sections()->toStructure() as $section): ?>
<section class="expertise-section expertise-section--<?= $section->icon() ?>">
<h2 class="expertise-section__title"><?= $section->title() ?></h2>
<div class="expertise-section__content">
<?= $section->content()->toBlocks() ?>
</div>
</section>
<?php endforeach ?>
</div>
<?php endif ?>
<!-- Objective Section -->
<?php if ($page->objective_text()->isNotEmpty()): ?>
<section class="expertise__objective">
<h2 class="expertise__objective-title"><?= $page->objective_title() ?></h2>
<p class="expertise__objective-text"><?= $page->objective_text() ?></p>
</section>
<?php endif ?>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,16 @@
<?php
$specificData = [
'description' => $page->description()->value(),
'rules' => $page->rules()->toBlocks(),
'game_status' => $page->game_status()->value(),
'is_embedded' => $page->is_embedded()->toBool(),
'play_link' => $page->play_link()->value(),
'cover' => $page->cover()->toFile()?->url(),
'parent_url' => $page->parent()->url()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,58 +1,2 @@
<?php snippet('header') ?>
<main class="game">
<article class="game__content">
<!-- Info -->
<div class="game__info">
<h1 class="game__title"><?= $page->title() ?></h1>
<?php if ($page->description()->isNotEmpty()): ?>
<p class="game__description"><?= $page->description() ?></p>
<?php endif ?>
<!-- Rules -->
<?php if ($page->rules()->isNotEmpty()): ?>
<div class="game__rules">
<?= $page->rules()->toBlocks() ?>
</div>
<?php endif ?>
<!-- Status Button -->
<?php if ($page->game_status()->value() !== 'available'): ?>
<div class="game__status">
<span class="btn btn--disabled">
<?= $page->game_status()->value() === 'coming_soon' ? 'Bientôt disponible' : 'En maintenance' ?>
</span>
</div>
<?php endif ?>
</div>
<!-- Game Area -->
<div class="game__area">
<?php if ($page->game_status()->value() === 'available'): ?>
<?php if ($page->is_embedded()->toBool() && $page->play_link()->isNotEmpty()): ?>
<iframe src="<?= $page->play_link() ?>" class="game__iframe" frameborder="0"></iframe>
<?php elseif ($page->play_link()->isNotEmpty()): ?>
<a href="<?= $page->play_link() ?>" class="game__external-link btn btn--large" target="_blank">
Jouer maintenant
</a>
<?php endif ?>
<?php if ($cover = $page->cover()->toFile()): ?>
<div class="game__cover">
<img src="<?= $cover->url() ?>" alt="<?= $page->title() ?>">
</div>
<?php endif ?>
<?php endif ?>
</div>
</article>
<!-- Back Navigation -->
<nav class="game__nav">
<a href="<?= $page->parent()->url() ?>" class="game__nav-back">
&larr; Retour aux jeux
</a>
</nav>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,24 @@
<?php
$specificData = [
'hero' => [
'title' => $page->hero_title()->value(),
'title_highlight' => $page->hero_title_highlight()->value(),
'subtitle' => $page->hero_subtitle()->value(),
'cta_text' => $page->hero_cta_text()->value(),
'cta_link' => $page->hero_cta_link()->toPage()?->url() ?? '#',
'image' => $page->hero_image()->toFile()?->url()
],
'background_video' => $page->background_video()->toFile()?->url(),
'floating_bubbles' => $page->floating_bubbles()->toStructure()->map(function($bubble) {
return [
'text' => $bubble->text()->value(),
'position' => $bubble->position()->value()
];
})->values()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,49 +1,2 @@
<?php snippet('header') ?>
<main class="home">
<!-- Hero Section -->
<section class="hero">
<div class="hero__content">
<h1 class="hero__title">
<?php
$title = $page->hero_title()->value();
$highlight = $page->hero_title_highlight()->value();
if ($highlight) {
echo str_replace($highlight, '<span class="highlight">' . $highlight . '</span>', $title);
} else {
echo $title;
}
?>
</h1>
<?php if ($page->hero_subtitle()->isNotEmpty()): ?>
<p class="hero__subtitle"><?= $page->hero_subtitle() ?></p>
<?php endif ?>
<?php if ($page->hero_cta_text()->isNotEmpty()): ?>
<a href="<?= $page->hero_cta_link()->toPage()?->url() ?? '#' ?>" class="hero__cta btn">
<?= $page->hero_cta_text() ?>
</a>
<?php endif ?>
</div>
<?php if ($hero = $page->hero_image()->toFile()): ?>
<div class="hero__image">
<img src="<?= $hero->url() ?>" alt="<?= $page->hero_title() ?>">
</div>
<?php endif ?>
<!-- Floating Bubbles -->
<?php if ($page->floating_bubbles()->isNotEmpty()): ?>
<div class="hero__bubbles">
<?php foreach ($page->floating_bubbles()->toStructure() as $bubble): ?>
<div class="bubble bubble--<?= $bubble->position() ?>">
<?= $bubble->text() ?>
</div>
<?php endforeach ?>
</div>
<?php endif ?>
</section>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,33 @@
<?php
$specificData = [
'intro' => [
'title' => $page->intro_title()->value(),
'text' => $page->intro_text()->value()
],
'games' => $page->children()->listed()->map(function($game) {
$badgeValue = $game->badge()->value();
$badgeLabel = 'none';
if ($badgeValue === 'new') {
$badgeLabel = 'NEW';
} elseif ($badgeValue === 'coming_soon') {
$badgeLabel = 'INCOMING';
}
return [
'title' => $game->title()->value(),
'slug' => $game->slug(),
'url' => $game->url(),
'description' => $game->description()->value(),
'cover' => $game->cover()->toFile()?->url(),
'badge' => $badgeValue,
'badge_label' => $badgeLabel,
'game_status' => $game->game_status()->value()
];
})->values()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,57 +1,2 @@
<?php snippet('header') ?>
<main class="jouer">
<!-- Intro Section -->
<section class="jouer__intro">
<?php if ($page->intro_title()->isNotEmpty()): ?>
<h1 class="jouer__title"><?= $page->intro_title() ?></h1>
<?php endif ?>
<?php if ($page->intro_text()->isNotEmpty()): ?>
<p class="jouer__text"><?= $page->intro_text() ?></p>
<?php endif ?>
</section>
<!-- Games List -->
<section class="jouer__games">
<?php foreach ($page->children()->listed() as $game): ?>
<article class="game-card">
<!-- Badge -->
<?php if ($game->badge()->isNotEmpty() && $game->badge()->value() !== 'none'): ?>
<span class="game-card__badge game-card__badge--<?= $game->badge() ?>">
<?= $game->badge()->value() === 'new' ? 'NEW' : ($game->badge()->value() === 'coming_soon' ? 'INCOMING' : $game->badge()) ?>
</span>
<?php endif ?>
<!-- Cover -->
<?php if ($cover = $game->cover()->toFile()): ?>
<div class="game-card__cover">
<img src="<?= $cover->url() ?>" alt="<?= $game->title() ?>">
</div>
<?php endif ?>
<!-- Info -->
<div class="game-card__info">
<h2 class="game-card__title"><?= $game->title() ?></h2>
<?php if ($game->description()->isNotEmpty()): ?>
<p class="game-card__description"><?= $game->description() ?></p>
<?php endif ?>
<!-- Play Button -->
<?php if ($game->game_status()->value() === 'available'): ?>
<a href="<?= $game->url() ?>" class="game-card__play btn">
Jouer
</a>
<?php else: ?>
<span class="game-card__status btn btn--disabled">
Bientôt disponible
</span>
<?php endif ?>
</div>
</article>
<?php endforeach ?>
</section>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,32 @@
<?php
$specificData = [
'intro' => [
'title' => $page->intro_title()->value(),
'text' => $page->intro_text()->value()
],
'projects' => $page->children()->listed()->map(function($project) {
return [
'title' => $project->title()->value(),
'slug' => $project->slug(),
'url' => $project->url(),
'tagline' => $project->tagline()->value(),
'description' => $project->description()->value(),
'cover' => $project->cover()->toFile()?->url(),
'cover_thumb' => $project->cover()->toFile()?->thumb(['width' => 100])->url(),
'gallery' => $project->files()->filterBy('template', 'image')->limit(5)->map(function($img) {
return $img->url();
})->values(),
'impact' => $project->impact()->split(','),
'category' => $project->category()->value(),
'platforms' => $project->platforms()->split(','),
'apple_link' => $project->apple_link()->value(),
'android_link' => $project->android_link()->value()
];
})->values()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,109 +1,2 @@
<?php snippet('header') ?>
<main class="portfolio">
<!-- Intro Section -->
<section class="portfolio__intro">
<?php if ($page->intro_title()->isNotEmpty()): ?>
<h1 class="portfolio__title"><?= $page->intro_title() ?></h1>
<?php endif ?>
<?php if ($page->intro_text()->isNotEmpty()): ?>
<p class="portfolio__text"><?= $page->intro_text() ?></p>
<?php endif ?>
</section>
<!-- Projects Grid -->
<section class="portfolio__projects">
<?php
$projects = $page->children()->listed();
$total = $projects->count();
$index = 0;
?>
<?php foreach ($projects as $project): ?>
<?php $index++ ?>
<article class="project-card" data-index="<?= $index ?>">
<!-- Project Gallery -->
<div class="project-card__gallery">
<?php if ($cover = $project->cover()->toFile()): ?>
<img src="<?= $cover->url() ?>" alt="<?= $project->title() ?>" class="project-card__cover">
<?php endif ?>
<?php foreach ($project->files()->filterBy('template', 'image')->limit(5) as $image): ?>
<img src="<?= $image->url() ?>" alt="" class="project-card__image">
<?php endforeach ?>
</div>
<!-- Project Info -->
<div class="project-card__info">
<h2 class="project-card__title"><?= $project->title() ?></h2>
<?php if ($project->tagline()->isNotEmpty()): ?>
<p class="project-card__tagline"><?= $project->tagline() ?></p>
<?php endif ?>
<?php if ($project->description()->isNotEmpty()): ?>
<p class="project-card__description"><?= $project->description() ?></p>
<?php endif ?>
<!-- Meta -->
<div class="project-card__meta">
<?php if ($project->impact()->isNotEmpty()): ?>
<div class="project-card__impact">
<span class="label">Impact:</span>
<?= $project->impact()->join(', ') ?>
</div>
<?php endif ?>
<?php if ($project->category()->isNotEmpty()): ?>
<div class="project-card__category">
<span class="label">Catégorie:</span>
<?= $project->category()->value() ?>
</div>
<?php endif ?>
<?php if ($project->platforms()->isNotEmpty()): ?>
<div class="project-card__platforms">
<span class="label">Plateformes:</span>
<?= $project->platforms()->join(' / ') ?>
</div>
<?php endif ?>
</div>
<!-- Links -->
<div class="project-card__links">
<?php if ($project->apple_link()->isNotEmpty()): ?>
<a href="<?= $project->apple_link() ?>" class="btn btn--apple" target="_blank">
Apple
</a>
<?php endif ?>
<?php if ($project->android_link()->isNotEmpty()): ?>
<a href="<?= $project->android_link() ?>" class="btn btn--android" target="_blank">
Android
</a>
<?php endif ?>
</div>
</div>
<!-- Counter -->
<div class="project-card__counter">
<?= str_pad($index, 2, '0', STR_PAD_LEFT) ?>/<?= str_pad($total, 2, '0', STR_PAD_LEFT) ?>
</div>
</article>
<?php endforeach ?>
</section>
<!-- Thumbnails Navigation -->
<nav class="portfolio__thumbnails">
<?php foreach ($projects as $project): ?>
<a href="#<?= $project->slug() ?>" class="portfolio__thumbnail">
<?php if ($cover = $project->cover()->toFile()): ?>
<img src="<?= $cover->thumb(['width' => 100])->url() ?>" alt="<?= $project->title() ?>">
<?php endif ?>
</a>
<?php endforeach ?>
</nav>
</main>
<?php snippet('footer') ?>

View file

@ -0,0 +1,31 @@
<?php
$specificData = [
'tagline' => $page->tagline()->value(),
'description' => $page->description()->kt(),
'cover' => $page->cover()->toFile()?->url(),
'gallery' => $page->files()->filterBy('template', 'image')->map(function($img) {
return $img->url();
})->values(),
'impact' => $page->impact()->split(','),
'category' => $page->category()->value(),
'platforms' => $page->platforms()->split(','),
'client_name' => $page->client_name()->value(),
'apple_link' => $page->apple_link()->value(),
'android_link' => $page->android_link()->value(),
'web_link' => $page->web_link()->value(),
'prev' => $page->prev() ? [
'title' => $page->prev()->title()->value(),
'url' => $page->prev()->url()
] : null,
'next' => $page->next() ? [
'title' => $page->next()->title()->value(),
'url' => $page->next()->url()
] : null,
'parent_url' => $page->parent()->url()
];
$pageData = array_merge($genericData, $specificData);
header('Content-Type: application/json');
echo json_encode($pageData);

View file

@ -1,104 +1,2 @@
<?php snippet('header') ?>
<main class="project">
<article class="project__content">
<!-- Gallery -->
<div class="project__gallery">
<?php if ($cover = $page->cover()->toFile()): ?>
<img src="<?= $cover->url() ?>" alt="<?= $page->title() ?>" class="project__cover">
<?php endif ?>
<?php foreach ($page->files()->filterBy('template', 'image') as $image): ?>
<img src="<?= $image->url() ?>" alt="" class="project__image">
<?php endforeach ?>
</div>
<!-- Info -->
<div class="project__info">
<h1 class="project__title"><?= $page->title() ?></h1>
<?php if ($page->tagline()->isNotEmpty()): ?>
<p class="project__tagline"><?= $page->tagline() ?></p>
<?php endif ?>
<?php if ($page->description()->isNotEmpty()): ?>
<div class="project__description">
<?= $page->description()->kt() ?>
</div>
<?php endif ?>
<!-- Meta -->
<div class="project__meta">
<?php if ($page->impact()->isNotEmpty()): ?>
<div class="project__impact">
<span class="label">Impact:</span>
<?= $page->impact()->join(', ') ?>
</div>
<?php endif ?>
<?php if ($page->category()->isNotEmpty()): ?>
<div class="project__category">
<span class="label">Catégorie:</span>
<?= $page->category()->value() ?>
</div>
<?php endif ?>
<?php if ($page->platforms()->isNotEmpty()): ?>
<div class="project__platforms">
<span class="label">Plateformes:</span>
<?= $page->platforms()->join(' / ') ?>
</div>
<?php endif ?>
<?php if ($page->client_name()->isNotEmpty()): ?>
<div class="project__client">
<span class="label">Client:</span>
<?= $page->client_name() ?>
</div>
<?php endif ?>
</div>
<!-- Links -->
<div class="project__links">
<?php if ($page->apple_link()->isNotEmpty()): ?>
<a href="<?= $page->apple_link() ?>" class="btn btn--apple" target="_blank">
App Store
</a>
<?php endif ?>
<?php if ($page->android_link()->isNotEmpty()): ?>
<a href="<?= $page->android_link() ?>" class="btn btn--android" target="_blank">
Play Store
</a>
<?php endif ?>
<?php if ($page->web_link()->isNotEmpty()): ?>
<a href="<?= $page->web_link() ?>" class="btn btn--web" target="_blank">
Voir le site
</a>
<?php endif ?>
</div>
</div>
</article>
<!-- Navigation -->
<nav class="project__nav">
<?php if ($prev = $page->prev()): ?>
<a href="<?= $prev->url() ?>" class="project__nav-prev">
&larr; <?= $prev->title() ?>
</a>
<?php endif ?>
<a href="<?= $page->parent()->url() ?>" class="project__nav-back">
Tous les projets
</a>
<?php if ($next = $page->next()): ?>
<a href="<?= $next->url() ?>" class="project__nav-next">
<?= $next->title() ?> &rarr;
</a>
<?php endif ?>
</nav>
</main>
<?php snippet('footer') ?>