108108 <?php endif ; ?>
109109 </td>
110110 <td style="padding-right:20px;text-align:center;white-space:nowrap;">
111+ <?php if (filter_var ($ row ['mail ' ] ?? '' , FILTER_VALIDATE_EMAIL ) && $ row ['payment_status ' ]==1 ): ?>
112+ <button type="button" class="btn btn-gradient-success btn-xs me-1 js-resend-receipt"
113+ data-rid="<?= (int )$ row ['id ' ] ?> "
114+ data-mail="<?= htmlspecialchars ($ row ['mail ' ]) ?> "
115+ title="Resend receipt email to <?= htmlspecialchars ($ row ['mail ' ]) ?> ">
116+ <i class="mdi mdi-email-outline"></i>
117+ </button>
118+ <?php endif ; ?>
111119 <a href="manage_donations?rid=<?= $ row ['id ' ] ?> " class="btn btn-gradient-info btn-xs me-1">
112120 <i class="mdi mdi-pencil"></i>
113121 </a>
145153
146154</div>
147155<?php include 'includes/footer.php ' ; ?>
148- </div>
156+ </div>
157+
158+ <!-- ── Resend receipt (inline, no page reload) ─────────────────────────── -->
159+ <script>
160+ (function () {
161+ "use strict";
162+ const API_BASE = "<?= rtrim ($ api_url , '/ ' ) ?> ";
163+
164+ function toast(message, ok) {
165+ const t = document.createElement('div');
166+ t.textContent = message;
167+ t.style.cssText =
168+ 'position:fixed;z-index:3000;right:20px;bottom:20px;max-width:340px;' +
169+ 'padding:12px 16px;border-radius:10px;color:#fff;font-size:.86rem;' +
170+ 'box-shadow:0 6px 20px rgba(0,0,0,.18);' +
171+ (ok ? 'background:#2a7d4f;' : 'background:#c0392b;');
172+ document.body.appendChild(t);
173+ setTimeout(function () {
174+ t.style.transition = 'opacity .4s';
175+ t.style.opacity = '0';
176+ setTimeout(function () { t.remove(); }, 400);
177+ }, 3400);
178+ }
179+
180+ document.querySelectorAll('.js-resend-receipt').forEach(function (btn) {
181+ btn.addEventListener('click', function () {
182+ const rid = btn.getAttribute('data-rid');
183+ const mail = btn.getAttribute('data-mail') || 'this donor';
184+ if (!rid) return;
185+ if (!confirm('Resend the donation receipt to ' + mail + '?')) return;
186+
187+ const icon = btn.querySelector('i');
188+ const prev = icon ? icon.className : '';
189+ if (icon) icon.className = 'mdi mdi-loading mdi-spin';
190+ btn.disabled = true;
191+
192+ fetch(API_BASE + '/logs/resend_receipt?rid=' + encodeURIComponent(rid))
193+ .then(function (r) { return r.json(); })
194+ .then(function (j) {
195+ toast(j.message || (j.status === 'success' ? 'Receipt sent.' : 'Could not send receipt.'),
196+ j.status === 'success');
197+ })
198+ .catch(function () { toast('Network error. Please try again.', false); })
199+ .finally(function () {
200+ if (icon) icon.className = prev;
201+ btn.disabled = false;
202+ });
203+ });
204+ });
205+ })();
206+ </script>
0 commit comments