chore: bootstrap module from working instance and add install guide
This commit is contained in:
341
views/donations/index.php
Normal file
341
views/donations/index.php
Normal 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
146
views/settings/history.php
Normal 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
635
views/settings/index.php
Normal 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
|
||||
);
|
||||
Reference in New Issue
Block a user