chore: bootstrap module from working instance and add install guide

This commit is contained in:
Kelin Rescue Hub
2026-04-09 14:18:10 -04:00
parent 97ad7da6f4
commit 6cda47760e
35 changed files with 6267 additions and 4 deletions

341
views/donations/index.php Normal file
View File

@@ -0,0 +1,341 @@
<?php
use humhub\modules\donations\models\DonationGoal;
use humhub\modules\donations\models\DonationProviderConfig;
use humhub\modules\space\models\Space;
use yii\helpers\Html;
/* @var DonationGoal[] $goals */
/* @var DonationProviderConfig|null $providerConfig */
/* @var bool $canDonate */
/* @var array $providerOptions */
/* @var array $recurringOptions */
/* @var Space $space */
/* @var bool $schemaReady */
/* @var array $dashboardData */
$dashboardData = is_array($dashboardData ?? null) ? $dashboardData : [];
$isManager = (bool)($dashboardData['isManager'] ?? false);
$months = is_array($dashboardData['months'] ?? null) ? $dashboardData['months'] : [];
$selectedMonth = (string)($dashboardData['selectedMonth'] ?? '');
$userRows = is_array($dashboardData['userRows'] ?? null) ? $dashboardData['userRows'] : [];
$userMonthlyHeaders = is_array($dashboardData['userMonthlyHeaders'] ?? null) ? $dashboardData['userMonthlyHeaders'] : [];
$userGrandTotal = (float)($dashboardData['userGrandTotal'] ?? 0);
$adminRows = is_array($dashboardData['adminRows'] ?? null) ? $dashboardData['adminRows'] : [];
$adminTotals = is_array($dashboardData['adminTotals'] ?? null) ? $dashboardData['adminTotals'] : ['target' => 0.0, 'donated' => 0.0, 'percent' => 0.0];
$ytd = is_array($dashboardData['ytd'] ?? null) ? $dashboardData['ytd'] : ['year' => (int)date('Y'), 'donated' => 0.0, 'target' => 0.0, 'percent' => 0.0];
$previousYear = is_array($dashboardData['previousYear'] ?? null) ? $dashboardData['previousYear'] : null;
$layout = trim((string)Yii::$app->request->get('layout', 'tiles'));
if (in_array($layout, ['cols2', 'cols3'], true)) {
$layout = 'tiles';
}
if (!in_array($layout, ['tiles', 'table'], true)) {
$layout = 'tiles';
}
$modeOptions = [
'one_time' => Yii::t('DonationsModule.base', 'One-time'),
];
if (!empty($recurringOptions)) {
$modeOptions['recurring'] = Yii::t('DonationsModule.base', 'Recurring');
}
$buildPageUrl = static function (array $overrides) use ($space, $selectedMonth, $layout): string {
$params = array_merge([
'month' => $selectedMonth,
'layout' => $layout,
], $overrides);
return $space->createUrl('/donations/donations/index', $params);
};
$selectedMonthIndex = array_search($selectedMonth, $months, true);
$prevMonth = ($selectedMonthIndex !== false && isset($months[$selectedMonthIndex + 1])) ? (string)$months[$selectedMonthIndex + 1] : '';
$nextMonth = ($selectedMonthIndex !== false && $selectedMonthIndex > 0 && isset($months[$selectedMonthIndex - 1])) ? (string)$months[$selectedMonthIndex - 1] : '';
$userGridClass = 'col-md-6 col-sm-6 col-xs-12';
$hasUserDashboard = $schemaReady && !Yii::$app->user->isGuest;
?>
<style>
.donations-view-toggle {
width: 32px;
height: 30px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
}
.donations-total-amount {
font-size: 28px;
font-weight: 800;
color: #1c7c45;
line-height: 1;
margin-left: 10px;
}
.donations-summary-table thead th {
text-align: center;
padding-left: 14px;
}
.donations-summary-table td {
padding-left: 14px;
}
.donations-summary-table .donation-subtotals-row {
background: #f8fafc;
}
.donation-breakdown-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
border-top: 1px solid #eef2f6;
padding: 4px 0;
}
.donation-breakdown-row .donation-breakdown-date {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.donation-breakdown-row .donation-breakdown-amount {
min-width: 110px;
text-align: right;
font-weight: 700;
}
@media (prefers-color-scheme: dark) {
.donations-summary-table .donation-subtotals-row {
background: #1f2937;
color: #e5e7eb;
}
}
</style>
<div class="panel panel-default">
<div class="panel-heading" style="display:flex;justify-content:space-between;align-items:center;gap:8px;">
<span><?= Yii::t('DonationsModule.base', '<strong>My Donations</strong>') ?></span>
<span style="display:flex;gap:6px;align-items:center;">
<?= Html::a('<i class="fa fa-th-large"></i>', $buildPageUrl(['layout' => 'tiles']), ['class' => 'btn btn-default btn-xs donations-view-toggle' . ($layout === 'tiles' ? ' active' : ''), 'title' => Yii::t('DonationsModule.base', 'Tile View'), 'aria-label' => Yii::t('DonationsModule.base', 'Tile View')]) ?>
<?= Html::a('<i class="fa fa-table"></i>', $buildPageUrl(['layout' => 'table']), ['class' => 'btn btn-default btn-xs donations-view-toggle' . ($layout === 'table' ? ' active' : ''), 'title' => Yii::t('DonationsModule.base', 'Table View'), 'aria-label' => Yii::t('DonationsModule.base', 'Table View')]) ?>
</span>
</div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-warning" style="margin-bottom:14px;">
<?= Yii::t('DonationsModule.base', 'Donations setup has not been run yet. Please ask a space admin to run module setup.') ?>
</div>
<?php endif; ?>
<?php if ($schemaReady && Yii::$app->user->isGuest): ?>
<div class="alert alert-info" style="margin-bottom:14px;">
<?= Yii::t('DonationsModule.base', 'Sign in to see your personal donation history dashboard.') ?>
</div>
<?php endif; ?>
<?php if ($schemaReady): ?>
<div class="row" style="margin-top:2px;">
<?php if ($hasUserDashboard): ?>
<div class="col-md-8 col-sm-12" style="min-width:0;">
<div style="margin-bottom:14px;display:flex;align-items:flex-end;flex-wrap:wrap;gap:8px;">
<span style="font-size:14px;font-weight:700;"><?= Yii::t('DonationsModule.base', 'Your Total Contributions') ?>:</span>
<span class="donations-total-amount">$<?= Html::encode(number_format($userGrandTotal, 2)) ?></span>
</div>
<?php if (empty($userRows)): ?>
<div class="alert alert-info" style="margin-bottom:14px;">
<?= Yii::t('DonationsModule.base', 'No successful donations from your account were found in this space yet.') ?>
</div>
<?php elseif ($layout === 'table'): ?>
<div class="table-responsive" style="margin-bottom:14px;">
<table class="table table-bordered table-hover donations-summary-table" style="margin-bottom:0;">
<thead>
<tr>
<th><?= Yii::t('DonationsModule.base', 'Animal') ?></th>
<?php foreach ($userMonthlyHeaders as $monthKey): ?>
<th><?= Html::encode(date('M Y', strtotime($monthKey . '-01'))) ?></th>
<?php endforeach; ?>
<th><?= Yii::t('DonationsModule.base', 'Annual Total') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Lifetime Total') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($userRows as $row): ?>
<?php
$annualTotal = 0.0;
foreach ((array)($row['annual'] ?? []) as $yearAmount) {
$annualTotal += (float)$yearAmount;
}
?>
<tr>
<td>
<?php if (!empty($row['animalUrl'])): ?>
<?= Html::a(Html::encode((string)$row['animalName']), (string)$row['animalUrl']) ?>
<?php else: ?>
<?= Html::encode((string)$row['animalName']) ?>
<?php endif; ?>
</td>
<?php foreach ($userMonthlyHeaders as $monthKey): ?>
<td>$<?= Html::encode(number_format((float)($row['monthly'][$monthKey] ?? 0), 2)) ?></td>
<?php endforeach; ?>
<td>$<?= Html::encode(number_format($annualTotal, 2)) ?></td>
<td><strong>$<?= Html::encode(number_format((float)($row['total'] ?? 0), 2)) ?></strong></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="row" style="margin-bottom:6px;">
<?php foreach ($userRows as $row): ?>
<?php
$goalTarget = max(0.0, (float)($row['goalTarget'] ?? 0));
$goalCurrent = max(0.0, (float)($row['goalCurrent'] ?? 0));
$goalPercent = $goalTarget > 0 ? min(100.0, ($goalCurrent / $goalTarget) * 100.0) : 0.0;
$annualTotals = (array)($row['annual'] ?? []);
krsort($annualTotals, SORT_NUMERIC);
?>
<div class="<?= Html::encode($userGridClass) ?>" style="margin-bottom:12px;">
<div class="panel panel-default" style="margin-bottom:0;overflow:hidden;">
<?php if (!empty($row['imageUrl'])): ?>
<img src="<?= Html::encode((string)$row['imageUrl']) ?>" alt="<?= Html::encode((string)$row['animalName']) ?>" style="width:100%;height:165px;object-fit:cover;display:block;">
<?php else: ?>
<div style="height:165px;background:#eef2f6;display:flex;align-items:center;justify-content:center;color:#98a2b3;">
<i class="fa fa-heart fa-2x"></i>
</div>
<?php endif; ?>
<div class="panel-body" style="padding:10px;">
<div style="font-size:16px;font-weight:700;line-height:1.2;margin-bottom:4px;">
<?php if (!empty($row['animalUrl'])): ?>
<?= Html::a(Html::encode((string)$row['animalName']), (string)$row['animalUrl']) ?>
<?php else: ?>
<?= Html::encode((string)$row['animalName']) ?>
<?php endif; ?>
</div>
<div style="font-size:13px;margin-bottom:8px;color:#344054;">
<?= Yii::t('DonationsModule.base', 'Your Contribution') ?>:
<strong>$<?= Html::encode(number_format((float)($row['total'] ?? 0), 2)) ?></strong>
</div>
<div class="progress" style="height:9px;margin-bottom:6px;">
<div class="progress-bar progress-bar-success" role="progressbar" style="width:<?= Html::encode((string)round($goalPercent, 2)) ?>%;"></div>
</div>
<div style="font-size:12px;color:#667085;margin-bottom:8px;">
<?= Yii::t('DonationsModule.base', 'Goal') ?>:
$<?= Html::encode(number_format($goalCurrent, 2)) ?> / $<?= Html::encode(number_format($goalTarget, 2)) ?>
(<?= Html::encode(number_format($goalPercent, 1)) ?>%)
</div>
<div style="font-size:12px;font-weight:700;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Monthly Breakdown') ?></div>
<div style="max-height:120px;overflow:auto;">
<?php foreach ($userMonthlyHeaders as $monthKey): ?>
<div class="donation-breakdown-row">
<span class="donation-breakdown-date"><?= Html::encode(date('M Y', strtotime($monthKey . '-01'))) ?></span>
<span class="donation-breakdown-amount">$<?= Html::encode(number_format((float)($row['monthly'][$monthKey] ?? 0), 2)) ?></span>
</div>
<?php endforeach; ?>
</div>
<div style="font-size:12px;font-weight:700;margin-top:8px;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Annual Totals') ?></div>
<?php foreach ($annualTotals as $year => $amount): ?>
<div class="donation-breakdown-row">
<span class="donation-breakdown-date"><?= Html::encode((string)$year) ?></span>
<span class="donation-breakdown-amount">$<?= Html::encode(number_format((float)$amount, 2)) ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="<?= $hasUserDashboard ? 'col-md-4 col-sm-12' : 'col-md-12 col-sm-12' ?>" style="min-width:0;">
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading" style="display:flex;align-items:center;justify-content:space-between;gap:8px;">
<span><?= Yii::t('DonationsModule.base', 'All Donation Progress by Month') ?></span>
<span style="display:flex;align-items:center;gap:6px;">
<?php if ($prevMonth !== ''): ?>
<?= Html::a('<i class="fa fa-chevron-left"></i>', $buildPageUrl(['month' => $prevMonth]), ['class' => 'btn btn-default btn-xs', 'title' => Yii::t('DonationsModule.base', 'Previous Month')]) ?>
<?php endif; ?>
<span style="font-size:12px;font-weight:700;"><?= Html::encode($selectedMonth !== '' ? date('F Y', strtotime($selectedMonth . '-01')) : Yii::t('DonationsModule.base', 'Current Month')) ?></span>
<?php if ($nextMonth !== ''): ?>
<?= Html::a('<i class="fa fa-chevron-right"></i>', $buildPageUrl(['month' => $nextMonth]), ['class' => 'btn btn-default btn-xs', 'title' => Yii::t('DonationsModule.base', 'Next Month')]) ?>
<?php endif; ?>
</span>
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped donations-summary-table" style="margin-bottom:0;">
<thead>
<tr>
<th><?= Yii::t('DonationsModule.base', 'Animal') ?></th>
<th><?= Yii::t('DonationsModule.base', '$ Target') ?></th>
<th><?= Yii::t('DonationsModule.base', '$ Donated') ?></th>
<th><?= Yii::t('DonationsModule.base', '% of Goal') ?></th>
</tr>
<tr class="donation-subtotals-row">
<th><?= Yii::t('DonationsModule.base', 'Subtotals') ?></th>
<th>$<?= Html::encode(number_format((float)($adminTotals['target'] ?? 0), 2)) ?></th>
<th>$<?= Html::encode(number_format((float)($adminTotals['donated'] ?? 0), 2)) ?></th>
<th><?= Html::encode(number_format((float)($adminTotals['percent'] ?? 0), 1)) ?>%</th>
</tr>
</thead>
<tbody>
<?php if (empty($adminRows)): ?>
<tr>
<td colspan="4" class="text-muted"><?= Yii::t('DonationsModule.base', 'No donation data for this month.') ?></td>
</tr>
<?php else: ?>
<?php foreach ($adminRows as $row): ?>
<tr>
<td>
<?php if (!empty($row['animalUrl'])): ?>
<?= Html::a(Html::encode((string)$row['animalName']), (string)$row['animalUrl']) ?>
<?php else: ?>
<?= Html::encode((string)$row['animalName']) ?>
<?php endif; ?>
</td>
<td>$<?= Html::encode(number_format((float)($row['target'] ?? 0), 2)) ?></td>
<td>$<?= Html::encode(number_format((float)($row['donated'] ?? 0), 2)) ?></td>
<td><?= Html::encode(number_format((float)($row['percent'] ?? 0), 1)) ?>%</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading"><?= Yii::t('DonationsModule.base', 'Year to Date Overview') ?></div>
<div class="panel-body">
<div style="font-size:13px;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Year') ?>: <strong><?= Html::encode((string)($ytd['year'] ?? date('Y'))) ?></strong></div>
<div style="font-size:13px;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Donated') ?>: <strong>$<?= Html::encode(number_format((float)($ytd['donated'] ?? 0), 2)) ?></strong></div>
<div style="font-size:13px;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Target') ?>: <strong>$<?= Html::encode(number_format((float)($ytd['target'] ?? 0), 2)) ?></strong></div>
<div style="font-size:13px;"><?= Yii::t('DonationsModule.base', 'Progress') ?>: <strong><?= Html::encode(number_format((float)($ytd['percent'] ?? 0), 1)) ?>%</strong></div>
</div>
</div>
<?php if (is_array($previousYear)): ?>
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading"><?= Yii::t('DonationsModule.base', 'Annual Overview') ?> (<?= Html::encode((string)($previousYear['year'] ?? '')) ?>)</div>
<div class="panel-body">
<div style="font-size:13px;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Donated') ?>: <strong>$<?= Html::encode(number_format((float)($previousYear['donated'] ?? 0), 2)) ?></strong></div>
<div style="font-size:13px;margin-bottom:4px;"><?= Yii::t('DonationsModule.base', 'Target') ?>: <strong>$<?= Html::encode(number_format((float)($previousYear['target'] ?? 0), 2)) ?></strong></div>
<div style="font-size:13px;"><?= Yii::t('DonationsModule.base', 'Progress') ?>: <strong><?= Html::encode(number_format((float)($previousYear['percent'] ?? 0), 1)) ?>%</strong></div>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
</div>

146
views/settings/history.php Normal file
View File

@@ -0,0 +1,146 @@
<?php
use humhub\modules\donations\models\DonationSubscription;
use humhub\modules\donations\models\DonationTransaction;
use humhub\modules\donations\models\DonationWebhookEvent;
use humhub\modules\space\models\Space;
use yii\helpers\Html;
/* @var string|null $subNav */
/* @var DonationTransaction[] $transactions */
/* @var DonationSubscription[] $subscriptions */
/* @var DonationWebhookEvent[] $webhookEvents */
/* @var Space $space */
?>
<div class="panel panel-default">
<div class="panel-heading"><?= Yii::t('DonationsModule.base', '<strong>Donations</strong> History') ?></div>
<?php if (!empty($subNav)): ?>
<?= $subNav ?>
<?php endif; ?>
<div class="panel-body">
<div style="margin-bottom:12px;">
<?= Html::a(
Yii::t('DonationsModule.base', 'Back to Donations Settings'),
$space->createUrl('/donations/settings'),
['class' => 'btn btn-default btn-sm']
) ?>
<?= Html::beginForm($space->createUrl('/donations/settings/reconcile-pending'), 'post', ['style' => 'display:inline-block;margin-left:8px;']) ?>
<?= Html::submitButton(
Yii::t('DonationsModule.base', 'Reconcile Pending Transactions'),
[
'class' => 'btn btn-primary btn-sm',
'data-confirm' => Yii::t('DonationsModule.base', 'Attempt reconciliation for pending transactions in this space now?'),
]
) ?>
<?= Html::endForm() ?>
</div>
<h4 style="margin-top:0;"><?= Yii::t('DonationsModule.base', 'Transactions') ?></h4>
<?php if (empty($transactions)): ?>
<div class="alert alert-info"><?= Yii::t('DonationsModule.base', 'No transactions found.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:14px;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>ID</th>
<th><?= Yii::t('DonationsModule.base', 'Provider') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Mode') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Status') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Amount') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Goal') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Checkout ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Payment ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Created') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($transactions as $transaction): ?>
<tr>
<td><?= (int)$transaction->id ?></td>
<td><?= Html::encode($transaction->provider) ?></td>
<td><?= Html::encode($transaction->mode) ?></td>
<td><?= Html::encode($transaction->status) ?></td>
<td><?= number_format((float)$transaction->amount, 2) ?> <?= Html::encode($transaction->currency) ?></td>
<td>#<?= (int)$transaction->goal_id ?></td>
<td style="max-width:180px;word-break:break-all;"><?= Html::encode((string)$transaction->provider_checkout_id) ?></td>
<td style="max-width:180px;word-break:break-all;"><?= Html::encode((string)$transaction->provider_payment_id) ?></td>
<td><?= Html::encode((string)$transaction->created_at) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<h4><?= Yii::t('DonationsModule.base', 'Subscriptions') ?></h4>
<?php if (empty($subscriptions)): ?>
<div class="alert alert-info"><?= Yii::t('DonationsModule.base', 'No subscriptions found.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:14px;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>ID</th>
<th><?= Yii::t('DonationsModule.base', 'Provider') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Status') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Amount') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Interval') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Subscription ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Created') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($subscriptions as $subscription): ?>
<tr>
<td><?= (int)$subscription->id ?></td>
<td><?= Html::encode($subscription->provider) ?></td>
<td><?= Html::encode($subscription->status) ?></td>
<td><?= number_format((float)$subscription->amount, 2) ?> <?= Html::encode($subscription->currency) ?></td>
<td><?= Html::encode((string)$subscription->interval_count) ?> <?= Html::encode((string)$subscription->interval_unit) ?></td>
<td style="max-width:220px;word-break:break-all;"><?= Html::encode((string)$subscription->provider_subscription_id) ?></td>
<td><?= Html::encode((string)$subscription->created_at) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<h4><?= Yii::t('DonationsModule.base', 'Recent Webhook Events (Global)') ?></h4>
<?php if (empty($webhookEvents)): ?>
<div class="alert alert-info" style="margin-bottom:0;"><?= Yii::t('DonationsModule.base', 'No webhook events found.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:0;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>ID</th>
<th><?= Yii::t('DonationsModule.base', 'Provider') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Event Type') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Event ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Processed') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Created') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($webhookEvents as $event): ?>
<tr>
<td><?= (int)$event->id ?></td>
<td><?= Html::encode($event->provider) ?></td>
<td><?= Html::encode((string)$event->event_type) ?></td>
<td style="max-width:220px;word-break:break-all;"><?= Html::encode((string)$event->provider_event_id) ?></td>
<td><?= (int)$event->is_processed === 1 ? Yii::t('DonationsModule.base', 'Yes') : Yii::t('DonationsModule.base', 'No') ?></td>
<td><?= Html::encode((string)$event->created_at) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>

635
views/settings/index.php Normal file
View File

@@ -0,0 +1,635 @@
<?php
use humhub\modules\donations\models\DonationGoal;
use humhub\modules\donations\models\DonationSubscription;
use humhub\modules\donations\models\DonationTransaction;
use humhub\modules\donations\models\DonationWebhookEvent;
use humhub\modules\donations\models\forms\DonationGoalForm;
use humhub\modules\donations\models\forms\ProviderSettingsForm;
use yii\bootstrap\ActiveForm;
use yii\helpers\Html;
use yii\helpers\Json;
/* @var string|null $subNav */
/* @var ProviderSettingsForm $providerForm */
/* @var DonationGoalForm $goalForm */
/* @var DonationGoal[] $goals */
/* @var DonationTransaction[] $transactions */
/* @var DonationSubscription[] $subscriptions */
/* @var DonationWebhookEvent[] $webhookEvents */
/* @var array $animalOptions */
/* @var array $animalGalleryImageMap */
/* @var string $activeTab */
/* @var bool $schemaReady */
$goalTypeOptions = DonationGoal::goalTypeOptions();
$isEditingGoal = !empty($goalForm->id);
$showAnimalTargetField = $goalForm->goal_type === DonationGoal::TYPE_ANIMAL;
$hostInfo = Yii::$app->request->hostInfo;
$stripeWebhookUrl = $hostInfo . $providerForm->contentContainer->createUrl('/donations/donations/stripe-webhook');
$paypalWebhookUrl = $hostInfo . $providerForm->contentContainer->createUrl('/donations/donations/paypal-webhook');
$tabs = [
'general' => Yii::t('DonationsModule.base', 'General'),
'goals' => Yii::t('DonationsModule.base', 'Goals'),
'payment-providers' => Yii::t('DonationsModule.base', 'Payment Providers'),
'donation-history' => Yii::t('DonationsModule.base', 'Donation History'),
'advanced' => Yii::t('DonationsModule.base', 'Advanced'),
];
if (!array_key_exists($activeTab, $tabs)) {
$activeTab = 'general';
}
$tabUrl = static function (string $tab) use ($providerForm): string {
return $providerForm->contentContainer->createUrl('/donations/settings', ['tab' => $tab]);
};
?>
<div class="panel panel-default">
<div class="panel-heading"><?= Yii::t('DonationsModule.base', '<strong>Donations</strong> Settings') ?></div>
<?php if (!empty($subNav)): ?>
<?= $subNav ?>
<?php endif; ?>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-warning" style="margin-bottom:14px;">
<?= Yii::t('DonationsModule.base', 'Donations schema is not initialized for this environment yet. Use the Advanced tab to run setup before configuring providers, goals, or history.') ?>
</div>
<?php endif; ?>
<ul class="nav nav-tabs" style="margin-bottom:14px;">
<?php foreach ($tabs as $tabKey => $tabLabel): ?>
<li class="<?= $activeTab === $tabKey ? 'active' : '' ?>">
<?= Html::a(Html::encode($tabLabel), $tabUrl($tabKey)) ?>
</li>
<?php endforeach; ?>
</ul>
<?php if ($activeTab === 'general'): ?>
<div class="panel panel-default" style="margin-bottom:0;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Default Currency') ?></div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-info" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Run Donations setup from the Advanced tab to enable General settings.') ?>
</div>
<?php else: ?>
<?php $generalForm = ActiveForm::begin(); ?>
<?= Html::hiddenInput('active_tab', 'general') ?>
<?= $generalForm->errorSummary($providerForm, ['class' => 'alert alert-danger']) ?>
<div class="row">
<div class="col-md-4">
<?= $generalForm->field($providerForm, 'default_currency')->textInput(['maxlength' => 8]) ?>
</div>
<div class="col-md-4">
<?= $generalForm->field($providerForm, 'animal_tile_extra_height_px')->input('number', [
'min' => 0,
'max' => 600,
'step' => 1,
])->hint(Yii::t('DonationsModule.base', 'Adds extra height to animal cards in pixels to accommodate donation overlays.')) ?>
</div>
<div class="col-md-8">
<?= $generalForm->field($providerForm, 'animal_donation_form_header')->textInput(['maxlength' => 255])
->hint(Yii::t('DonationsModule.base', 'Use [animal-name] to insert the animal name, e.g. "Your Donation directly supports [animal-name]".')) ?>
</div>
</div>
<?= Html::submitButton(Yii::t('DonationsModule.base', 'Save General Settings'), ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if ($activeTab === 'goals'): ?>
<div class="panel panel-default" style="margin-bottom:14px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Donation Goals') ?></div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-info" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Run Donations setup from the Advanced tab to manage goals.') ?>
</div>
<?php else: ?>
<?php if ($isEditingGoal): ?>
<div class="alert alert-info" style="margin-bottom:12px;">
<?= Yii::t('DonationsModule.base', 'You are editing an existing goal.') ?>
<?= Html::a(
Yii::t('DonationsModule.base', 'Cancel'),
$tabUrl('goals'),
['class' => 'btn btn-xs btn-default', 'style' => 'margin-left:8px;']
) ?>
</div>
<?php endif; ?>
<?php $goalActiveForm = ActiveForm::begin([
'options' => ['enctype' => 'multipart/form-data'],
]); ?>
<?= $goalActiveForm->errorSummary($goalForm, ['class' => 'alert alert-danger']) ?>
<?= $goalActiveForm->field($goalForm, 'id')->hiddenInput()->label(false) ?>
<div class="row">
<div class="col-md-3"><?= $goalActiveForm->field($goalForm, 'goal_type')->dropDownList($goalTypeOptions) ?></div>
<div class="col-md-3" id="donation-goal-animal-field" style="display:<?= $showAnimalTargetField ? 'block' : 'none' ?>;">
<?= $goalActiveForm->field($goalForm, 'target_animal_id')->dropDownList($animalOptions, ['prompt' => Yii::t('DonationsModule.base', 'Select animal')]) ?>
</div>
<div class="col-md-4"><?= $goalActiveForm->field($goalForm, 'title') ?></div>
<div class="col-md-2"><?= $goalActiveForm->field($goalForm, 'target_amount')->input('number', ['step' => '0.01', 'min' => '0']) ?></div>
</div>
<?= $goalActiveForm->field($goalForm, 'description')->textarea(['rows' => 3]) ?>
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Goal Image') ?></div>
<div class="panel-body">
<?= $goalActiveForm->field($goalForm, 'imageGalleryPath')->hiddenInput()->label(false) ?>
<div id="donation-goal-current-preview" style="margin-bottom:10px;"></div>
<div id="donation-goal-gallery-wrapper" style="margin-bottom:12px;">
<div id="donation-goal-gallery-options" style="display:flex;flex-wrap:wrap;"></div>
<div id="donation-goal-gallery-empty" class="text-muted" style="display:none;">
<?= Yii::t('DonationsModule.base', 'No gallery images found for this animal. You can upload a new image below.') ?>
</div>
</div>
<?= $goalActiveForm->field($goalForm, 'imageFile')->fileInput(['accept' => 'image/*']) ?>
</div>
</div>
<?= $goalActiveForm->field($goalForm, 'is_active')->checkbox() ?>
<?= Html::submitButton(
$isEditingGoal ? Yii::t('DonationsModule.base', 'Update Goal') : Yii::t('DonationsModule.base', 'Create Goal'),
['class' => 'btn btn-primary']
) ?>
<?php ActiveForm::end(); ?>
<?php endif; ?>
</div>
</div>
<div class="panel panel-default" style="margin-bottom:0;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Existing Goals') ?></div>
<div class="panel-body">
<?php if (empty($goals)): ?>
<div class="alert alert-info" style="margin-bottom:0;"><?= Yii::t('DonationsModule.base', 'No donation goals configured yet.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:0;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th><?= Yii::t('DonationsModule.base', 'Title') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Type') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Progress') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Status') ?></th>
<th style="width:180px;"><?= Yii::t('DonationsModule.base', 'Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($goals as $goal): ?>
<tr>
<td><?= Html::encode($goal->title) ?></td>
<td><?= Html::encode($goalTypeOptions[$goal->goal_type] ?? $goal->goal_type) ?></td>
<td><?= number_format((float)$goal->current_amount, 2) ?> / <?= number_format((float)$goal->target_amount, 2) ?> <?= Html::encode($goal->currency) ?></td>
<td>
<?php if ((int)$goal->is_active === 1): ?>
<span class="label label-success"><?= Yii::t('DonationsModule.base', 'Active') ?></span>
<?php else: ?>
<span class="label label-default"><?= Yii::t('DonationsModule.base', 'Inactive') ?></span>
<?php endif; ?>
</td>
<td>
<?= Html::a(
Yii::t('DonationsModule.base', 'Edit'),
$providerForm->contentContainer->createUrl('/donations/settings', [
'tab' => 'goals',
'goalId' => (int)$goal->id,
]),
['class' => 'btn btn-xs btn-primary']
) ?>
<?= Html::a(
Yii::t('DonationsModule.base', 'Delete'),
$providerForm->contentContainer->createUrl('/donations/settings/delete-goal', ['id' => (int)$goal->id]),
[
'class' => 'btn btn-xs btn-danger',
'data-method' => 'post',
'data-confirm' => Yii::t('DonationsModule.base', 'Delete this donation goal?'),
]
) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if ($activeTab === 'payment-providers'): ?>
<div class="panel panel-default" style="margin-bottom:0;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Payment Providers') ?></div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-info" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Run Donations setup from the Advanced tab to manage payment providers.') ?>
</div>
<?php else: ?>
<?php $providerActiveForm = ActiveForm::begin(); ?>
<?= Html::hiddenInput('active_tab', 'payment-providers') ?>
<?= $providerActiveForm->errorSummary($providerForm, ['class' => 'alert alert-danger']) ?>
<div class="alert alert-info" style="margin-bottom:12px;">
<?= Yii::t('DonationsModule.base', 'Sandbox mode automatically uses sandbox credentials. Disable sandbox mode to use live credentials.') ?>
</div>
<div class="row" style="margin-bottom:8px;">
<div class="col-md-4" style="padding-top:6px;"><?= $providerActiveForm->field($providerForm, 'sandbox_mode')->checkbox() ?></div>
</div>
<div class="row">
<div class="col-md-6">
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'PayPal') ?></div>
<div class="panel-body" style="padding-bottom:4px;">
<div class="row">
<div class="col-md-6"><?= $providerActiveForm->field($providerForm, 'paypal_enabled')->checkbox() ?></div>
<div class="col-md-6"><?= $providerActiveForm->field($providerForm, 'paypal_recurring_enabled')->checkbox() ?></div>
</div>
<div class="panel panel-default" style="margin-bottom:8px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Sandbox Credentials') ?></div>
<div class="panel-body" style="padding-bottom:4px;">
<?= $providerActiveForm->field($providerForm, 'paypal_sandbox_client_id') ?>
<?= $providerActiveForm->field($providerForm, 'paypal_sandbox_client_secret') ?>
<?= $providerActiveForm->field($providerForm, 'paypal_sandbox_webhook_id') ?>
</div>
</div>
<div class="panel panel-default" style="margin-bottom:0;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Live Credentials') ?></div>
<div class="panel-body" style="padding-bottom:4px;">
<?= $providerActiveForm->field($providerForm, 'paypal_live_client_id') ?>
<?= $providerActiveForm->field($providerForm, 'paypal_live_client_secret') ?>
<?= $providerActiveForm->field($providerForm, 'paypal_live_webhook_id') ?>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Stripe') ?></div>
<div class="panel-body" style="padding-bottom:4px;">
<div class="row">
<div class="col-md-6"><?= $providerActiveForm->field($providerForm, 'stripe_enabled')->checkbox() ?></div>
<div class="col-md-6"><?= $providerActiveForm->field($providerForm, 'stripe_recurring_enabled')->checkbox() ?></div>
</div>
<div class="panel panel-default" style="margin-bottom:8px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Sandbox Credentials') ?></div>
<div class="panel-body" style="padding-bottom:4px;">
<?= $providerActiveForm->field($providerForm, 'stripe_sandbox_publishable_key') ?>
<?= $providerActiveForm->field($providerForm, 'stripe_sandbox_secret_key') ?>
<?= $providerActiveForm->field($providerForm, 'stripe_sandbox_webhook_secret') ?>
</div>
</div>
<div class="panel panel-default" style="margin-bottom:0;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Live Credentials') ?></div>
<div class="panel-body" style="padding-bottom:4px;">
<?= $providerActiveForm->field($providerForm, 'stripe_live_publishable_key') ?>
<?= $providerActiveForm->field($providerForm, 'stripe_live_secret_key') ?>
<?= $providerActiveForm->field($providerForm, 'stripe_live_webhook_secret') ?>
</div>
</div>
</div>
</div>
</div>
</div>
<?= Html::submitButton(Yii::t('DonationsModule.base', 'Save Provider Settings'), ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if ($activeTab === 'donation-history'): ?>
<div class="panel panel-default" style="margin-bottom:14px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Transactions') ?></div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-info" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Run Donations setup from the Advanced tab to view transaction history.') ?>
</div>
<?php elseif (empty($transactions)): ?>
<div class="alert alert-info" style="margin-bottom:0;"><?= Yii::t('DonationsModule.base', 'No transactions found.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:0;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>ID</th>
<th><?= Yii::t('DonationsModule.base', 'Provider') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Mode') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Status') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Amount') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Goal') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Checkout ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Payment ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Created') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($transactions as $transaction): ?>
<tr>
<td><?= (int)$transaction->id ?></td>
<td><?= Html::encode($transaction->provider) ?></td>
<td><?= Html::encode($transaction->mode) ?></td>
<td><?= Html::encode($transaction->status) ?></td>
<td><?= number_format((float)$transaction->amount, 2) ?> <?= Html::encode($transaction->currency) ?></td>
<td>#<?= (int)$transaction->goal_id ?></td>
<td style="max-width:180px;word-break:break-all;"><?= Html::encode((string)$transaction->provider_checkout_id) ?></td>
<td style="max-width:180px;word-break:break-all;"><?= Html::encode((string)$transaction->provider_payment_id) ?></td>
<td><?= Html::encode((string)$transaction->created_at) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<div class="panel panel-default" style="margin-bottom:14px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Subscriptions') ?></div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-info" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Run Donations setup from the Advanced tab to view subscription history.') ?>
</div>
<?php elseif (empty($subscriptions)): ?>
<div class="alert alert-info" style="margin-bottom:0;"><?= Yii::t('DonationsModule.base', 'No subscriptions found.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:0;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>ID</th>
<th><?= Yii::t('DonationsModule.base', 'Provider') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Status') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Amount') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Interval') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Subscription ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Created') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($subscriptions as $subscription): ?>
<tr>
<td><?= (int)$subscription->id ?></td>
<td><?= Html::encode($subscription->provider) ?></td>
<td><?= Html::encode($subscription->status) ?></td>
<td><?= number_format((float)$subscription->amount, 2) ?> <?= Html::encode($subscription->currency) ?></td>
<td><?= Html::encode((string)$subscription->interval_count) ?> <?= Html::encode((string)$subscription->interval_unit) ?></td>
<td style="max-width:220px;word-break:break-all;"><?= Html::encode((string)$subscription->provider_subscription_id) ?></td>
<td><?= Html::encode((string)$subscription->created_at) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<div class="panel panel-default" style="margin-bottom:0;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Recent Webhook Events (Global)') ?></div>
<div class="panel-body">
<?php if (!$schemaReady): ?>
<div class="alert alert-info" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Run Donations setup from the Advanced tab to view webhook event history.') ?>
</div>
<?php elseif (empty($webhookEvents)): ?>
<div class="alert alert-info" style="margin-bottom:0;"><?= Yii::t('DonationsModule.base', 'No webhook events found.') ?></div>
<?php else: ?>
<div class="table-responsive" style="margin-bottom:0;">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>ID</th>
<th><?= Yii::t('DonationsModule.base', 'Provider') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Event Type') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Event ID') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Processed') ?></th>
<th><?= Yii::t('DonationsModule.base', 'Created') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($webhookEvents as $event): ?>
<tr>
<td><?= (int)$event->id ?></td>
<td><?= Html::encode($event->provider) ?></td>
<td><?= Html::encode((string)$event->event_type) ?></td>
<td style="max-width:220px;word-break:break-all;"><?= Html::encode((string)$event->provider_event_id) ?></td>
<td><?= (int)$event->is_processed === 1 ? Yii::t('DonationsModule.base', 'Yes') : Yii::t('DonationsModule.base', 'No') ?></td>
<td><?= Html::encode((string)$event->created_at) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if ($activeTab === 'advanced'): ?>
<div class="well well-sm" style="margin-bottom:14px;">
<div style="font-weight:700;margin-bottom:6px;"><?= Yii::t('DonationsModule.base', 'Module Setup') ?></div>
<div style="margin-bottom:8px;">
<?= Yii::t('DonationsModule.base', 'Donations supports one-time and recurring contributions using PayPal and Stripe.') ?>
</div>
<div style="margin-bottom:10px;">
<?= Yii::t('DonationsModule.base', 'Run setup to apply pending Donations migrations and initialize defaults for this space.') ?>
</div>
<?= Html::a(
Yii::t('DonationsModule.base', 'Run Donations Setup'),
$providerForm->contentContainer->createUrl('/donations/settings/setup'),
[
'class' => 'btn btn-primary btn-sm',
'data-method' => 'post',
'data-confirm' => Yii::t('DonationsModule.base', 'Run Donations setup now for this space?'),
]
) ?>
</div>
<?php if (!$schemaReady): ?>
<div class="alert alert-warning" style="margin-bottom:0;">
<?= Yii::t('DonationsModule.base', 'Donations schema is not initialized for this environment yet. Run setup above to continue.') ?>
</div>
<?php else: ?>
<div class="alert alert-info" style="margin-bottom:12px;">
<div><strong><?= Yii::t('DonationsModule.base', 'Stripe Webhook URL') ?>:</strong> <?= Html::encode($stripeWebhookUrl) ?></div>
<div><strong><?= Yii::t('DonationsModule.base', 'PayPal Webhook URL') ?>:</strong> <?= Html::encode($paypalWebhookUrl) ?></div>
</div>
<div class="panel panel-default" style="margin-bottom:12px;">
<div class="panel-heading" style="font-weight:600;"><?= Yii::t('DonationsModule.base', 'Webhook Simulation Tools') ?></div>
<div class="panel-body" style="padding-bottom:8px;">
<p style="margin-bottom:10px;">
<?= Yii::t('DonationsModule.base', 'Use these tools to test webhook processing locally after creating donation intents. Latest matching transaction in this space is used automatically.') ?>
</p>
<div style="display:flex;gap:8px;flex-wrap:wrap;">
<?= Html::beginForm($providerForm->contentContainer->createUrl('/donations/settings/simulate-stripe-webhook'), 'post', ['style' => 'display:inline-block;']) ?>
<?= Html::submitButton(Yii::t('DonationsModule.base', 'Simulate Stripe Checkout Completed'), ['class' => 'btn btn-default btn-sm']) ?>
<?= Html::endForm() ?>
<?= Html::beginForm($providerForm->contentContainer->createUrl('/donations/settings/simulate-paypal-webhook'), 'post', ['style' => 'display:inline-block;']) ?>
<?= Html::submitButton(Yii::t('DonationsModule.base', 'Simulate PayPal Capture Completed'), ['class' => 'btn btn-default btn-sm']) ?>
<?= Html::endForm() ?>
</div>
</div>
</div>
<div>
<?= Html::beginForm($providerForm->contentContainer->createUrl('/donations/settings/reconcile-pending'), 'post', ['style' => 'display:inline-block;margin-bottom:0;']) ?>
<?= Html::submitButton(
Yii::t('DonationsModule.base', 'Reconcile Pending Transactions'),
[
'class' => 'btn btn-primary btn-sm',
'data-confirm' => Yii::t('DonationsModule.base', 'Attempt reconciliation for pending transactions in this space now?'),
]
) ?>
<?= Html::endForm() ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<?php
$animalGalleryMapJson = Json::htmlEncode($animalGalleryImageMap);
$selectedImageUrl = trim((string)$goalForm->imageGalleryPath) !== ''
? trim((string)$goalForm->imageGalleryPath)
: trim((string)$goalForm->image_path);
$selectedImageUrlJson = Json::htmlEncode($selectedImageUrl);
$this->registerCss(<<<CSS
.donation-gallery-item {
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
}
.donation-gallery-item.is-active {
border-color: #337ab7;
box-shadow: 0 0 0 1px rgba(51, 122, 183, 0.25);
}
#donation-goal-current-preview img {
width: 120px;
height: 120px;
object-fit: cover;
border: 1px solid #ddd;
border-radius: 4px;
}
CSS
);
$this->registerJs(<<<JS
(function() {
var galleryMap = $animalGalleryMapJson;
var selectedImageUrl = $selectedImageUrlJson;
function setSelectedImage(url) {
$('#donationgoalform-imagegallerypath').val(url || '');
selectedImageUrl = url || '';
renderCurrentPreview();
renderGalleryOptions();
}
function renderCurrentPreview() {
var wrapper = $('#donation-goal-current-preview');
wrapper.empty();
if (!selectedImageUrl) {
wrapper.append('<span class="text-muted">No image selected.</span>');
return;
}
var image = $('<img>').attr('src', selectedImageUrl);
wrapper.append(image);
}
function renderGalleryOptions() {
var goalType = $('#donationgoalform-goal_type').val();
var animalId = $('#donationgoalform-target_animal_id').val();
var wrapper = $('#donation-goal-gallery-options');
var emptyState = $('#donation-goal-gallery-empty');
wrapper.empty();
if (goalType !== 'animal' || !animalId || !galleryMap[animalId] || !galleryMap[animalId].length) {
emptyState.show();
return;
}
emptyState.hide();
galleryMap[animalId].forEach(function(url) {
var button = $('<button type="button" class="donation-gallery-item" style="margin:0 8px 8px 0;padding:4px;"></button>');
button.attr('data-url', url);
if (selectedImageUrl === url) {
button.addClass('is-active');
}
button.append($('<img>').attr('src', url).css({
width: '72px',
height: '72px',
objectFit: 'cover'
}));
wrapper.append(button);
});
}
function toggleAnimalField() {
var goalType = $('#donationgoalform-goal_type').val();
var wrapper = $('#donation-goal-animal-field');
if (goalType === 'animal') {
wrapper.show();
} else {
wrapper.hide();
$('#donationgoalform-target_animal_id').val('');
}
renderGalleryOptions();
}
$(document).on('change', '#donationgoalform-goal_type', toggleAnimalField);
$(document).on('change', '#donationgoalform-target_animal_id', renderGalleryOptions);
$(document).on('click', '.donation-gallery-item', function() {
var url = $(this).data('url') || '';
setSelectedImage(url);
});
$(document).on('change', '#donationgoalform-imagefile', function() {
if (this.files && this.files.length > 0) {
setSelectedImage('');
}
});
toggleAnimalField();
renderCurrentPreview();
})();
JS
);