feat: add next live announcement with multi-timezone display
This commit is contained in:
@@ -24,6 +24,10 @@ temp/
|
||||
# Fichiers de cache
|
||||
cache/
|
||||
|
||||
# Dossier pour les images d'annonces (tout ignorer sauf .gitkeep)
|
||||
uploads/*
|
||||
!uploads/.gitkeep
|
||||
|
||||
# Fichiers de dépendances (si nécessaire)
|
||||
# vendor/
|
||||
# node_modules/
|
||||
|
||||
+66
@@ -26,6 +26,7 @@ kaubuntu.re est une interface web responsive qui permet de consulter et recherch
|
||||
- 📰 *Intégration WordPress* : Affichage des articles depuis un site WordPress via REST API
|
||||
- 💝 *Système de dons* : Interface PayPal Me configurable pour collecter des dons
|
||||
- ⏰ *Système de countdown* : Page de lancement configurable avec compte à rebours multi-fuseaux
|
||||
- 📺 *Annonce du prochain live* : Affichage dynamique avec multi-fuseaux horaires et image personnalisable
|
||||
|
||||
== 🛠️ Technologies utilisées
|
||||
|
||||
@@ -157,6 +158,71 @@ cp mentions-legales.php.sample mentions-legales.php
|
||||
|
||||
Ces fichiers sont listés dans le `.gitignore` afin que vos modifications ne soient pas suivies par Git, ce qui vous permet de personnaliser votre instance sans affecter le code source principal.
|
||||
|
||||
== 📺 Annonce du prochain live
|
||||
|
||||
kaubuntu.re intègre un système d'annonce configurable qui s'affiche automatiquement lorsqu'il n'y a pas de diffusion en direct en cours.
|
||||
|
||||
=== ✨ Fonctionnalités
|
||||
|
||||
- 📅 *Date et heure dynamiques* : Génération automatique à partir de `NEXT_LIVE_DATE`
|
||||
- 🌍 *Multi-fuseaux horaires* : Affichage automatique pour 5 territoires (Ma'ohi Nui, Martinique/Guadeloupe, Guyane, France, Kanaky)
|
||||
- ⏰ *Décalage UTC* : Affichage du fuseau horaire de référence (UTC+04:00 pour La Réunion)
|
||||
- 📅 *Indicateurs de jour* : Affichage des décalages de jour (+1j/-1j) si nécessaire
|
||||
- 🖼️ *Image personnalisable* : Support des formats Instagram (portrait 4:5, carré 1:1) et paysage (16:9)
|
||||
- 📱 *Responsive complet* : Layouts adaptés pour desktop (50/50), tablette (vertical), et mobile
|
||||
- 🔄 *Flexbox intelligent* : Réorganisation automatique des fuseaux horaires selon la largeur d'écran
|
||||
|
||||
=== ⚙️ Configuration
|
||||
|
||||
Pour configurer l'annonce du prochain live, ajoutez dans votre `config.local.php` :
|
||||
|
||||
[source,php]
|
||||
----
|
||||
// Activer l'annonce du prochain live
|
||||
define('NEXT_LIVE_ENABLED', true);
|
||||
|
||||
// Titre (la date sera ajoutée automatiquement)
|
||||
define('NEXT_LIVE_TITLE', 'Prochain live');
|
||||
|
||||
// Description (l'heure sera ajoutée automatiquement)
|
||||
define('NEXT_LIVE_DESCRIPTION', 'Constitution du futur état réunionnais & Hommage à Thomas Sankara.');
|
||||
|
||||
// Date du prochain live au format Y-m-d H:i:s
|
||||
define('NEXT_LIVE_DATE', '2025-10-11 10:00:00');
|
||||
|
||||
// Chemin vers l'image d'annonce (optionnel)
|
||||
define('NEXT_LIVE_IMAGE', 'uploads/next-live.jpg');
|
||||
----
|
||||
|
||||
=== 📁 Gestion des images
|
||||
|
||||
. Placez vos images dans le dossier `uploads/` (non tracké par Git)
|
||||
. Formats recommandés :
|
||||
* Portrait 4:5 : 1080×1350px ou 1280×1600px - *Idéal*
|
||||
* Carré 1:1 : 1080×1080px - *Parfait*
|
||||
* Paysage 16:9 : 1920×1080px
|
||||
. Optimisez vos images (< 500 Ko recommandé)
|
||||
|
||||
=== 🎯 Affichage
|
||||
|
||||
*Desktop (≥1700px)* : Layout 50/50 (image à gauche, informations à droite)
|
||||
|
||||
*Tablette (1025-1699px)* : Hero seul sur une ligne, Mastodon et WordPress côte à côte en dessous
|
||||
|
||||
*Mobile (<769px)* : Stack vertical avec scroll si nécessaire
|
||||
|
||||
=== 🌍 Fuseaux horaires affichés
|
||||
|
||||
L'annonce calcule automatiquement les heures locales pour :
|
||||
|
||||
- *Ma'ohi Nui* (Polynésie française) - UTC-10:00
|
||||
- *Martinique / Guadeloupe* - UTC-04:00
|
||||
- *Guyane* - UTC-03:00
|
||||
- *France* - UTC+02:00
|
||||
- *Kanaky* (Nouvelle-Calédonie) - UTC+11:00
|
||||
|
||||
L'heure de référence (La Réunion, UTC+04:00) est affichée dans le badge principal.
|
||||
|
||||
== 💝 Système de dons
|
||||
|
||||
kaubuntu.re intègre un système de dons configurable qui permet de collecter des contributions via PayPal Me.
|
||||
|
||||
+407
-8
@@ -584,21 +584,32 @@ img {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* Responsive breakpoint intermédiaire pour les 3 éléments */
|
||||
@media (max-width: 1200px) and (min-width: 1025px) {
|
||||
/* Responsive breakpoint pour écrans entre 1025px et 1699px */
|
||||
@media (max-width: 1699px) and (min-width: 1025px) {
|
||||
.hero-mastodon-wrapper {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
grid-column: 1 / -1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.timeline-wordpress-container {
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 15px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.timeline-wordpress-container .wordpress-section {
|
||||
width: 100%;
|
||||
#mt-container {
|
||||
grid-column: 1 / 2;
|
||||
}
|
||||
|
||||
.wordpress-section {
|
||||
grid-column: 2 / 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,6 +740,116 @@ img {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* Annonce du prochain live dans le hero (page d'accueil) - Split gauche/droite */
|
||||
.hero-next-live {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-next-live-image-container {
|
||||
flex: 0 0 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--bg-dark);
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.hero-next-live-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.hero-next-live-content {
|
||||
flex: 0 0 50%;
|
||||
padding: 20px 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.95) 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hero-next-live-content i.fa-calendar-alt {
|
||||
font-size: 35px;
|
||||
margin-bottom: 8px;
|
||||
color: var(--primary-red);
|
||||
}
|
||||
|
||||
.hero-next-live-content h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: white;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.hero-next-live-content p {
|
||||
font-size: 14px;
|
||||
margin: 0 auto 12px;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.hero-next-live-date {
|
||||
font-size: 15px !important;
|
||||
font-weight: 600;
|
||||
color: white !important;
|
||||
background: var(--primary-red);
|
||||
padding: 7px 14px;
|
||||
border-radius: 8px;
|
||||
display: inline-block;
|
||||
margin-bottom: 12px !important;
|
||||
box-shadow: 0 4px 12px rgba(255, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.hero-next-live-date i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.hero-next-live-datetime {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hero-next-live-timezones {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
margin-top: 12px;
|
||||
padding: 12px 16px;
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.hero-timezone-item {
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
white-space: nowrap;
|
||||
line-height: 1.5;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
flex: 0 1 auto;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.hero-timezone-item strong {
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#mt-container {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
@@ -1983,6 +2104,16 @@ img {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
/* Augmenter la hauteur du hero quand il y a une annonce */
|
||||
.hero:has(.hero-next-live) {
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
/* Augmenter aussi la hauteur du hero pour "no-live" pour cohérence */
|
||||
.hero:has(.hero-no-live) {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.hero-mastodon-wrapper #mt-container {
|
||||
height: 600px;
|
||||
}
|
||||
@@ -2342,6 +2473,129 @@ i.icon-mastodon,
|
||||
margin: 0 auto 30px;
|
||||
}
|
||||
|
||||
/* Annonce du prochain live - Split gauche/droite */
|
||||
.next-live-announcement {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background-color: var(--card-bg);
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.next-live-image-container {
|
||||
flex: 0 0 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--bg-dark);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.next-live-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
max-height: 600px;
|
||||
}
|
||||
|
||||
.next-live-content {
|
||||
flex: 0 0 50%;
|
||||
padding: 50px 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, var(--card-bg) 0%, var(--bg-dark) 100%);
|
||||
}
|
||||
|
||||
.next-live-content i.fa-calendar-alt {
|
||||
font-size: 60px;
|
||||
margin-bottom: 20px;
|
||||
color: var(--primary-red);
|
||||
}
|
||||
|
||||
.next-live-content h2 {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 20px;
|
||||
color: var(--text-color);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.next-live-content p {
|
||||
font-size: 20px;
|
||||
margin: 0 auto 25px;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.5;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.next-live-date {
|
||||
font-size: 22px !important;
|
||||
font-weight: 600;
|
||||
color: white !important;
|
||||
background: var(--primary-red);
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
display: inline-block;
|
||||
margin-bottom: 30px !important;
|
||||
box-shadow: 0 4px 12px rgba(255, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.next-live-date i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.utc-offset {
|
||||
font-size: 16px;
|
||||
opacity: 0.85;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.next-live-datetime {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.next-live-timezones {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 20px;
|
||||
padding: 16px 20px;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.timezone-item {
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
white-space: nowrap;
|
||||
line-height: 1.5;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
flex: 0 1 auto;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.timezone-item strong {
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.day-shift {
|
||||
font-size: 12px;
|
||||
color: var(--primary-red);
|
||||
font-weight: 700;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
display: inline-block;
|
||||
padding: 12px 25px;
|
||||
@@ -2361,6 +2615,32 @@ i.icon-mastodon,
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* Responsive tablette/desktop étroit - 769px à 1024px */
|
||||
@media (max-width: 1024px) and (min-width: 769px) {
|
||||
.hero-mastodon-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hero {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.timeline-wordpress-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
#mt-container {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.wordpress-section {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive pour la page de direct */
|
||||
@media (max-width: 768px) {
|
||||
.live-title {
|
||||
@@ -2399,6 +2679,125 @@ i.icon-mastodon,
|
||||
.no-live-message p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Responsive mobile - Stack vertical pour l'annonce */
|
||||
.next-live-announcement {
|
||||
flex-direction: column;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.next-live-image-container {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
max-height: 400px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.next-live-image {
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
.next-live-content {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
padding: 30px 20px;
|
||||
overflow-y: auto;
|
||||
max-height: 600px;
|
||||
}
|
||||
|
||||
.next-live-content i.fa-calendar-alt {
|
||||
font-size: 45px;
|
||||
}
|
||||
|
||||
.next-live-content h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.next-live-content p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.next-live-date {
|
||||
font-size: 17px !important;
|
||||
padding: 10px 18px;
|
||||
}
|
||||
|
||||
.next-live-timezones {
|
||||
gap: 8px;
|
||||
padding: 14px 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.timezone-item {
|
||||
font-size: 14px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
/* Hero next live responsive */
|
||||
.hero-next-live {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hero-next-live-image-container {
|
||||
flex: 0 0 300px;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.hero-next-live-image {
|
||||
max-height: 270px;
|
||||
}
|
||||
|
||||
.hero-next-live-content {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 5px 15px 25px 15px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.hero-next-live-content i.fa-calendar-alt {
|
||||
font-size: 35px;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.hero-next-live-content h2 {
|
||||
font-size: 20px;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.hero-next-live-content p {
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.hero-next-live-date {
|
||||
font-size: 13px !important;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.hero-next-live-timezones {
|
||||
gap: 5px;
|
||||
padding: 8px 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.hero-timezone-item {
|
||||
font-size: 10px;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
|
||||
.utc-offset {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Catégories */
|
||||
|
||||
+101
-1
@@ -152,7 +152,106 @@ $liveStream = getLiveStream();
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
// Aucun direct en cours
|
||||
// Aucun direct en cours - vérifier s'il y a une annonce configurée
|
||||
$showNextLiveAnnouncement = defined('NEXT_LIVE_ENABLED') && NEXT_LIVE_ENABLED === true;
|
||||
|
||||
if ($showNextLiveAnnouncement) {
|
||||
// Afficher l'annonce du prochain live
|
||||
?>
|
||||
<div class="next-live-announcement">
|
||||
<?php if (!empty(NEXT_LIVE_IMAGE) && file_exists(NEXT_LIVE_IMAGE)): ?>
|
||||
<div class="next-live-image-container">
|
||||
<img src="<?php echo htmlspecialchars(NEXT_LIVE_IMAGE); ?>"
|
||||
alt="<?php echo htmlspecialchars(NEXT_LIVE_TITLE); ?>"
|
||||
class="next-live-image">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="next-live-content">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<?php
|
||||
if (!empty(NEXT_LIVE_DATE)) {
|
||||
$liveDate = new DateTime(NEXT_LIVE_DATE, new DateTimeZone('Indian/Reunion'));
|
||||
$dayFormatter = new IntlDateFormatter(
|
||||
'fr_FR',
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::NONE,
|
||||
'Indian/Reunion',
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
'EEEE d MMMM'
|
||||
);
|
||||
$formattedDay = $dayFormatter->format($liveDate);
|
||||
$formattedDay = ucfirst($formattedDay);
|
||||
$dynamicTitle = NEXT_LIVE_TITLE . ' - ' . $formattedDay;
|
||||
} else {
|
||||
$dynamicTitle = NEXT_LIVE_TITLE;
|
||||
}
|
||||
?>
|
||||
<h2><?php echo htmlspecialchars($dynamicTitle); ?></h2>
|
||||
<?php
|
||||
if (!empty(NEXT_LIVE_DATE)) {
|
||||
$liveHour = $liveDate->format('H\hi');
|
||||
$dynamicDescription = 'Rejoignez-nous à ' . $liveHour . '. ' . NEXT_LIVE_DESCRIPTION;
|
||||
} else {
|
||||
$dynamicDescription = NEXT_LIVE_DESCRIPTION;
|
||||
}
|
||||
?>
|
||||
<p><?php echo nl2br(htmlspecialchars($dynamicDescription)); ?></p>
|
||||
<?php if (!empty(NEXT_LIVE_DATE)): ?>
|
||||
<div class="next-live-datetime">
|
||||
<p class="next-live-date">
|
||||
<i class="fas fa-clock"></i>
|
||||
<?php
|
||||
$formatter = new IntlDateFormatter(
|
||||
'fr_FR',
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::SHORT,
|
||||
'Indian/Reunion'
|
||||
);
|
||||
echo $formatter->format($liveDate);
|
||||
|
||||
$offset = $liveDate->format('P');
|
||||
echo ' <span class="utc-offset">(UTC' . $offset . ')</span>';
|
||||
?>
|
||||
</p>
|
||||
|
||||
<!-- Autres fuseaux horaires -->
|
||||
<div class="next-live-timezones">
|
||||
<?php
|
||||
// Ordre croissant : du plus en retard au plus en avance
|
||||
$timezones = [
|
||||
'Ma\'ohi Nui' => 'Pacific/Tahiti',
|
||||
'Martinique / Guadeloupe' => 'America/Martinique',
|
||||
'Guyane' => 'America/Cayenne',
|
||||
'France' => 'Europe/Paris',
|
||||
'Kanaky' => 'Pacific/Noumea'
|
||||
];
|
||||
|
||||
foreach($timezones as $name => $timezone):
|
||||
$liveDateLocal = clone $liveDate;
|
||||
$liveDateLocal->setTimezone(new DateTimeZone($timezone));
|
||||
|
||||
// Vérifier si c'est un jour différent
|
||||
$dayDiff = $liveDateLocal->format('j') - $liveDate->format('j');
|
||||
|
||||
$dayIndicator = '';
|
||||
if ($dayDiff > 0) {
|
||||
$dayIndicator = ' <span class="day-shift">+1j</span>';
|
||||
} elseif ($dayDiff < 0) {
|
||||
$dayIndicator = ' <span class="day-shift">-1j</span>';
|
||||
}
|
||||
?>
|
||||
<span class="timezone-item">
|
||||
<strong><?php echo $name; ?> :</strong> <?php echo $liveDateLocal->format('H\hi'); ?><?php echo $dayIndicator; ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<a href="index.php" class="btn-primary">Retour à l'accueil</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<div class="no-live-message">
|
||||
<i class="fas fa-tv"></i>
|
||||
@@ -162,6 +261,7 @@ $liveStream = getLiveStream();
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -166,4 +166,24 @@ if (!defined('DONATION_AMOUNTS')) define('DONATION_AMOUNTS', [5, 10, 20, 50]);
|
||||
|
||||
// Devise par défaut
|
||||
if (!defined('DONATION_CURRENCY')) define('DONATION_CURRENCY', 'EUR');
|
||||
|
||||
// =========================================
|
||||
// Annonce du prochain live
|
||||
// =========================================
|
||||
|
||||
// Activer/désactiver l'annonce du prochain live par défaut
|
||||
if (!defined('NEXT_LIVE_ENABLED')) define('NEXT_LIVE_ENABLED', false);
|
||||
|
||||
// Titre de l'annonce du prochain live
|
||||
if (!defined('NEXT_LIVE_TITLE')) define('NEXT_LIVE_TITLE', 'Prochain live');
|
||||
|
||||
// Description de l'annonce du prochain live
|
||||
if (!defined('NEXT_LIVE_DESCRIPTION')) define('NEXT_LIVE_DESCRIPTION', 'Rejoignez-nous pour notre prochain live !');
|
||||
|
||||
// Date du prochain live (format: Y-m-d H:i:s)
|
||||
if (!defined('NEXT_LIVE_DATE')) define('NEXT_LIVE_DATE', '');
|
||||
|
||||
// Chemin vers l'image d'annonce du prochain live (relatif à la racine du site)
|
||||
// Exemple: 'uploads/next-live.jpg'
|
||||
if (!defined('NEXT_LIVE_IMAGE')) define('NEXT_LIVE_IMAGE', 'uploads/next-live.jpg');
|
||||
?>
|
||||
|
||||
@@ -142,7 +142,103 @@ setSecurityHeaders();
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
// Aucun direct en cours
|
||||
// Aucun direct en cours - vérifier s'il y a une annonce configurée
|
||||
$showNextLiveAnnouncement = defined('NEXT_LIVE_ENABLED') && NEXT_LIVE_ENABLED === true;
|
||||
|
||||
if ($showNextLiveAnnouncement) {
|
||||
// Afficher l'annonce du prochain live
|
||||
?>
|
||||
<div class="hero-next-live">
|
||||
<?php if (!empty(NEXT_LIVE_IMAGE) && file_exists(NEXT_LIVE_IMAGE)): ?>
|
||||
<div class="hero-next-live-image-container">
|
||||
<img src="<?php echo htmlspecialchars(NEXT_LIVE_IMAGE); ?>"
|
||||
alt="<?php echo htmlspecialchars(NEXT_LIVE_TITLE); ?>"
|
||||
class="hero-next-live-image">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="hero-next-live-content">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<?php
|
||||
if (!empty(NEXT_LIVE_DATE)) {
|
||||
$liveDate = new DateTime(NEXT_LIVE_DATE, new DateTimeZone('Indian/Reunion'));
|
||||
$dayFormatter = new IntlDateFormatter(
|
||||
'fr_FR',
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::NONE,
|
||||
'Indian/Reunion',
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
'EEEE d MMMM'
|
||||
);
|
||||
$formattedDay = $dayFormatter->format($liveDate);
|
||||
$formattedDay = ucfirst($formattedDay);
|
||||
$dynamicTitle = NEXT_LIVE_TITLE . ' - ' . $formattedDay;
|
||||
} else {
|
||||
$dynamicTitle = NEXT_LIVE_TITLE;
|
||||
}
|
||||
?>
|
||||
<h2><?php echo htmlspecialchars($dynamicTitle); ?></h2>
|
||||
<?php
|
||||
if (!empty(NEXT_LIVE_DATE)) {
|
||||
$liveHour = $liveDate->format('H\hi');
|
||||
$dynamicDescription = 'Rejoignez-nous à ' . $liveHour . '. ' . NEXT_LIVE_DESCRIPTION;
|
||||
} else {
|
||||
$dynamicDescription = NEXT_LIVE_DESCRIPTION;
|
||||
}
|
||||
?>
|
||||
<p><?php echo nl2br(htmlspecialchars($dynamicDescription)); ?></p>
|
||||
<?php if (!empty(NEXT_LIVE_DATE)): ?>
|
||||
<div class="hero-next-live-datetime">
|
||||
<p class="hero-next-live-date">
|
||||
<i class="fas fa-clock"></i>
|
||||
<?php
|
||||
$formatter = new IntlDateFormatter(
|
||||
'fr_FR',
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::SHORT,
|
||||
'Indian/Reunion'
|
||||
);
|
||||
echo $formatter->format($liveDate);
|
||||
|
||||
$offset = $liveDate->format('P');
|
||||
echo ' <span class="utc-offset">(UTC' . $offset . ')</span>';
|
||||
?>
|
||||
</p>
|
||||
|
||||
<!-- Autres fuseaux horaires -->
|
||||
<div class="hero-next-live-timezones">
|
||||
<?php
|
||||
// Ordre croissant : du plus en retard au plus en avance
|
||||
$timezones = [
|
||||
'Ma\'ohi Nui' => 'Pacific/Tahiti',
|
||||
'Martinique / Guadeloupe' => 'America/Martinique',
|
||||
'Guyane' => 'America/Cayenne',
|
||||
'France' => 'Europe/Paris',
|
||||
'Kanaky' => 'Pacific/Noumea'
|
||||
];
|
||||
|
||||
foreach($timezones as $name => $timezone):
|
||||
$liveDateLocal = clone $liveDate;
|
||||
$liveDateLocal->setTimezone(new DateTimeZone($timezone));
|
||||
$dayDiff = $liveDateLocal->format('j') - $liveDate->format('j');
|
||||
|
||||
$dayIndicator = '';
|
||||
if ($dayDiff > 0) {
|
||||
$dayIndicator = ' <span class="day-shift">+1j</span>';
|
||||
} elseif ($dayDiff < 0) {
|
||||
$dayIndicator = ' <span class="day-shift">-1j</span>';
|
||||
}
|
||||
?>
|
||||
<span class="hero-timezone-item">
|
||||
<strong><?php echo $name; ?> :</strong> <?php echo $liveDateLocal->format('H\hi'); ?><?php echo $dayIndicator; ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<div class="hero-no-live">
|
||||
<i class="fas fa-tv"></i>
|
||||
@@ -151,6 +247,7 @@ setSecurityHeaders();
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user