feature: integrate Donorbox API for donation management

- Add Donorbox configuration in site/config/config.php with API settings
- Create controller for support page to fetch campaign data from API
- Update support.php template with dynamic donation buttons and gauge
- Transform static buttons into dynamic links with proper URL parameters
- Add JavaScript for tab switching between one-time and monthly donations
- Calculate donation percentage and display real-time campaign stats

The donation buttons now link directly to Donorbox with pre-filled amounts
and intervals. API integration is ready but requires API key configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
isUnknown 2025-11-04 10:06:50 +01:00
parent 81cc9e5919
commit 3bcb51c829
5 changed files with 144 additions and 23 deletions

View file

@ -0,0 +1,59 @@
/**
* Gestion des onglets de donation (ponctuel / mensuel)
*/
document.addEventListener('DOMContentLoaded', function() {
const tabButtons = document.querySelectorAll('.nav--tabs__btn');
const donationLinks = document.querySelectorAll('.btn--donation[data-amount]');
if (tabButtons.length === 0 || donationLinks.length === 0) return;
tabButtons.forEach(button => {
button.addEventListener('click', function() {
// Retirer la classe is-selected de tous les boutons
tabButtons.forEach(btn => btn.classList.remove('is-selected'));
// Ajouter la classe is-selected au bouton cliqué
this.classList.add('is-selected');
// Récupérer l'intervalle (o = ponctuel, m = mensuel)
const interval = this.getAttribute('data-interval');
// Mettre à jour les liens de donation
donationLinks.forEach(link => {
const amount = link.getAttribute('data-amount');
const currentHref = link.getAttribute('href');
// Remplacer l'intervalle dans l'URL
const newHref = currentHref.replace(
/default_interval=[om]/,
`default_interval=${interval}`
);
link.setAttribute('href', newHref);
// Mettre à jour le texte (ajouter /mois pour mensuel)
const amountSpan = link.querySelector('.amount-value');
const boldText = link.querySelector('.bold');
if (amountSpan && boldText) {
if (interval === 'm') {
boldText.innerHTML = `<span class="amount-value">${amount}</span>€/mois`;
} else {
boldText.innerHTML = `<span class="amount-value">${amount}</span>€`;
}
}
});
// Mettre à jour aussi le lien "Montant libre"
const freeAmountLink = document.querySelector('.btn--donation:not([data-amount])');
if (freeAmountLink) {
const currentHref = freeAmountLink.getAttribute('href');
const newHref = currentHref.replace(
/default_interval=[om]/,
`default_interval=${interval}`
);
freeAmountLink.setAttribute('href', newHref);
}
});
});
});

View file

@ -24,5 +24,11 @@ return [
],
'panel' => [
'menu' => require_once __DIR__ . '/menu.php'
],
'donorbox' => [
'api_key' => '', // À remplir avec la clé API Donorbox
'campaign_slug' => 'soutenir-index-en-2024',
'campaign_url' => 'https://donorbox.org/soutenir-index-en-2024',
'api_base_url' => 'https://donorbox.org/api/v1'
]
];

View file

@ -0,0 +1,55 @@
<?php
return function($page) {
$config = kirby()->option('donorbox');
$apiKey = $config['api_key'];
$campaignSlug = $config['campaign_slug'];
// Valeurs par défaut
$data = [
'amount_raised' => 0,
'donor_count' => 0,
'goal_amount' => 20000, // Objectif par défaut
'percentage' => 0,
'campaign_url' => $config['campaign_url']
];
// Si la clé API est configurée, récupérer les données en temps réel
if (!empty($apiKey)) {
try {
$apiUrl = $config['api_base_url'] . '/campaigns/' . $campaignSlug;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$campaignData = json_decode($response, true);
if ($campaignData) {
$data['amount_raised'] = $campaignData['amount_raised'] ?? 0;
$data['donor_count'] = $campaignData['donor_count'] ?? 0;
$data['goal_amount'] = $campaignData['goal_amount'] ?? 20000;
// Calculer le pourcentage
if ($data['goal_amount'] > 0) {
$data['percentage'] = round(($data['amount_raised'] / $data['goal_amount']) * 100, 0);
}
}
}
} catch (Exception $e) {
// En cas d'erreur, on garde les valeurs par défaut
// Optionnel : logger l'erreur
}
}
return $data;
};

View file

@ -1,2 +1,3 @@
<script src="<?= url('assets/js/donation-tabs.js') ?>"></script>
</body>
</html>

View file

@ -22,16 +22,16 @@
<div class="gauge__container">
<!-- calculet le pourcentage avec lAPI?-->
<div id="gauge" style="--pourcent: 70%"></div>
<div id="gauge" style="--pourcent: <?= $percentage ?>%"></div>
<div class="gauge--infos" id="gauge--infos__donnateurs">
<p class="property">Donnateur·ices</p>
<p class="value">288</p>
<p class="value"><?= $donor_count ?></p>
</div>
<div class="gauge--infos" id="gauge--infos__objectif">
<p class="property">Objectif</p>
<p class="value">200</p>
<p class="value"><?= number_format($goal_amount, 0, ',', ' ') ?>€</p>
</div>
</div>
@ -47,32 +47,32 @@
<p class="p__baseline-big">Index est une ONG dinvestigation à but non-lucratif. Vos dons garantissent notre indépendance.</p>
<nav class="nav--tabs">
<button class="nav--tabs__btn is-selected">Je donne une fois</button>
<button class="nav--tabs__btn">Je donne tous les mois</button>
<button class="nav--tabs__btn is-selected" data-interval="o">Je donne une fois</button>
<button class="nav--tabs__btn" data-interval="m">Je donne tous les mois</button>
</nav>
<div class="btn--donation__container">
<button class="btn--donation">
<p class="bold">5/mois</p>
<p class="small">Soit X€ <br>après impôts</p>
</button>
<button class="btn--donation btn--donation__grow-1">
<p class="bold">10/mois</p>
<p class="small">Soit X€ <br>après impôts</p>
</button>
<button class="btn--donation btn--donation__grow-1">
<p class="bold">20/mois</p>
<p class="small">Soit X€ <br>après impôts</p>
</button>
<button class="btn--donation btn--donation__grow-1">
<p class="bold">50/mois</p>
<p class="small">Soit X€ <br>après impôts</p>
</button>
<button class="btn--donation btn--donation__grow-2">
<a href="<?= $campaign_url ?>?amount=5&default_interval=o" class="btn--donation" data-amount="5">
<p class="bold"><span class="amount-value">5</span></p>
<p class="small">Soit <?= round(5 * 0.34) ?>€ <br>après impôts</p>
</a>
<a href="<?= $campaign_url ?>?amount=10&default_interval=o" class="btn--donation btn--donation__grow-1" data-amount="10">
<p class="bold"><span class="amount-value">10</span></p>
<p class="small">Soit <?= round(10 * 0.34) ?>€ <br>après impôts</p>
</a>
<a href="<?= $campaign_url ?>?amount=20&default_interval=o" class="btn--donation btn--donation__grow-1" data-amount="20">
<p class="bold"><span class="amount-value">20</span></p>
<p class="small">Soit <?= round(20 * 0.34) ?>€ <br>après impôts</p>
</a>
<a href="<?= $campaign_url ?>?amount=50&default_interval=o" class="btn--donation btn--donation__grow-1" data-amount="50">
<p class="bold"><span class="amount-value">50</span></p>
<p class="small">Soit <?= round(50 * 0.34) ?>€ <br>après impôts</p>
</a>
<a href="<?= $campaign_url ?>?default_interval=o" class="btn--donation btn--donation__grow-2">
<p class="small">Montant libre</p>
<p class="bold">Choisissez votre montant</p>
<p class="small">Avec déduction fiscale</p>
</button>
</a>
</div>
<p class="p__details">Le don donne droit à une&nbsp;réduction fiscale de 66%<br> Vous pouvez stopper votre don à tout moment</p>