RTSDA-Website/astro-church-website/src/components/Footer.astro
Benjamin Slingo 756a755ba6 Fix PO BOX display and security vulnerability
- Add getChurchPhysicalAddress and getChurchPoBox functions to church-core
- Update UniFFI interface to expose new functions
- Add NAPI wrappers in astro-church-website for new functions
- Update Footer and contact page to use separate address fields
- Rebuild native bindings with new functions
- Display physical address and PO BOX on separate lines properly
- Fix Astro security vulnerability (GHSA-xf8x-j4p2-f749)

Resolves the missing PO BOX issue that was caused by newline character
handling problems between Rust and JavaScript in production environments.
2025-08-26 17:22:25 -04:00

357 lines
14 KiB
Plaintext

---
import { SERVICE_TIMES } from '../lib/constants.js';
import {
getChurchName,
getChurchPhysicalAddress,
getChurchPoBox,
getContactPhone,
getContactEmail,
getFacebookUrl,
getYoutubeUrl,
getInstagramUrl,
getMissionStatement
} from '../lib/bindings.js';
let churchName = 'Church';
let physicalAddress = '';
let poBox = '';
let phone = '';
let email = '';
let facebookUrl = '';
let youtubeUrl = '';
let instagramUrl = '';
let missionStatement = '';
try {
churchName = getChurchName();
physicalAddress = getChurchPhysicalAddress();
poBox = getChurchPoBox();
phone = getContactPhone();
// Get the base email from church-core and make it dynamic based on current domain
const baseEmail = getContactEmail();
const currentUrl = Astro.url.hostname;
// Extract the domain part and create dynamic email
if (currentUrl && currentUrl !== 'localhost') {
email = `admin@${currentUrl}`;
} else {
// Fallback to the original email from church-core
email = baseEmail;
}
facebookUrl = getFacebookUrl();
youtubeUrl = getYoutubeUrl();
instagramUrl = getInstagramUrl();
missionStatement = getMissionStatement();
} catch (e) {
console.error('Failed to get church config:', e);
}
const currentYear = new Date().getFullYear();
---
<footer class="bg-gradient-to-r from-earth-900 via-earth-800 to-earth-900 text-white relative overflow-hidden">
<!-- Background Pattern -->
<div class="absolute inset-0 bg-[url('data:image/svg+xml,%3Csvg width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"%3E%3Cg fill="none" fill-rule="evenodd"%3E%3Cg fill="%236366f1" fill-opacity="0.05"%3E%3Cpath d="M20 20c0 11.046-8.954 20-20 20s-20-8.954-20-20 8.954-20 20-20 20 8.954 20 20z"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E')] opacity-30"></div>
<div class="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<!-- Three Angels' Message Section -->
<div class="text-center mb-16">
<h2 class="text-4xl lg:text-5xl font-bold text-golden-gradient mb-6">The Three Angels' Message</h2>
<div class="grid md:grid-cols-3 gap-8 max-w-4xl mx-auto">
<!-- First Angel -->
<div class="bg-white/5 backdrop-blur-sm rounded-2xl p-6 border border-white/10 hover:bg-white/10 transition-all duration-300 group" data-animate>
<div class="w-16 h-16 bg-gradient-to-br from-primary-500 to-primary-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
<span class="text-2xl font-bold text-white">1</span>
</div>
<h3 class="text-xl font-semibold text-primary-300 mb-3">Fear God</h3>
<p class="text-gray-300 text-sm leading-relaxed">
"Fear God and give glory to Him, for the hour of His judgment has come"
</p>
</div>
<!-- Second Angel -->
<div class="bg-white/5 backdrop-blur-sm rounded-2xl p-6 border border-white/10 hover:bg-white/10 transition-all duration-300 group" data-animate>
<div class="w-16 h-16 bg-gradient-to-br from-primary-500 to-primary-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
<span class="text-2xl font-bold text-white">2</span>
</div>
<h3 class="text-xl font-semibold text-primary-300 mb-3">Babylon Fallen</h3>
<p class="text-gray-300 text-sm leading-relaxed">
"Babylon is fallen, is fallen, that great city"
</p>
</div>
<!-- Third Angel -->
<div class="bg-white/5 backdrop-blur-sm rounded-2xl p-6 border border-white/10 hover:bg-white/10 transition-all duration-300 group" data-animate>
<div class="w-16 h-16 bg-gradient-to-br from-primary-500 to-primary-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
<span class="text-2xl font-bold text-white">3</span>
</div>
<h3 class="text-xl font-semibold text-primary-300 mb-3">Mark of Beast</h3>
<p class="text-gray-300 text-sm leading-relaxed">
"If anyone worships the beast and his image..."
</p>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-12">
<!-- Church Info -->
<div class="lg:col-span-2">
<div class="flex items-center space-x-3 mb-6">
<div class="w-12 h-12 bg-gradient-to-br from-primary-500 to-primary-600 rounded-xl flex items-center justify-center shadow-lg">
<i data-lucide="sparkles" class="w-7 h-7 text-white"></i>
</div>
<div>
<h3 class="text-2xl font-bold text-golden-gradient">{churchName}</h3>
<p class="text-gray-300 text-sm">Seventh-day Adventist Church</p>
</div>
</div>
{missionStatement ? (
<p class="text-gray-300 mb-6 leading-relaxed">
{missionStatement}
</p>
) : (
<p class="text-gray-300 mb-6 leading-relaxed">
Join us as we study God's Word and prepare for His second coming. We are committed to sharing the everlasting gospel and the Three Angels' Message of Revelation 14.
</p>
)}
<!-- Scripture Verse -->
<div class="bg-white/5 backdrop-blur-sm rounded-xl p-4 border border-white/10">
<p class="text-sm text-gray-200 italic leading-relaxed">
"Then I saw another angel flying in midheaven, having the everlasting gospel to preach to those who dwell on the earth..."
</p>
<p class="text-xs text-primary-300 mt-2 font-medium">— Revelation 14:6</p>
</div>
</div>
<!-- Quick Links -->
<div>
<h4 class="text-lg font-semibold mb-6 text-white">Quick Links</h4>
<ul class="space-y-3">
<li><a href="/about" class="footer-link"><i data-lucide="info" class="w-4 h-4"></i><span>About Us</span></a></li>
<li><a href="/sermons" class="footer-link"><i data-lucide="book-open" class="w-4 h-4"></i><span>Sermons</span></a></li>
<li><a href="/events" class="footer-link"><i data-lucide="calendar" class="w-4 h-4"></i><span>Events</span></a></li>
<li><a href="/three-angels" class="footer-link"><i data-lucide="users" class="w-4 h-4"></i><span>Three Angels</span></a></li>
<li><a href="/contact" class="footer-link"><i data-lucide="mail" class="w-4 h-4"></i><span>Contact</span></a></li>
<li><a href="/live" class="footer-link text-gold-400"><i data-lucide="video" class="w-4 h-4"></i><span>Watch Live</span></a></li>
</ul>
</div>
<!-- Contact & Connect -->
<div>
<h4 class="text-lg font-semibold mb-6 text-white">Connect With Us</h4>
<!-- Contact Info -->
<div class="space-y-3 mb-6">
{(physicalAddress || poBox) && (
<div class="flex items-start space-x-2 text-sm text-gray-300">
<i data-lucide="map-pin" class="w-4 h-4 text-gold-400 mt-0.5 flex-shrink-0"></i>
<div class="leading-relaxed">
{physicalAddress && (
<div class="mb-1">{physicalAddress}</div>
)}
{poBox && (
<div class="mb-0">{poBox}</div>
)}
</div>
</div>
)}
{phone && (
<div class="flex items-center space-x-2 text-sm text-gray-300">
<i data-lucide="phone" class="w-4 h-4 text-gold-400"></i>
<a href={`tel:${phone}`} class="hover:text-white transition-colors">{phone}</a>
</div>
)}
{email && (
<div class="flex items-center space-x-2 text-sm text-gray-300">
<i data-lucide="mail" class="w-4 h-4 text-gold-400"></i>
<a href={`mailto:${email}`} class="hover:text-white transition-colors">{email}</a>
</div>
)}
</div>
<!-- Sabbath Service Times -->
<div class="mb-6">
<h5 class="text-sm font-medium text-primary-300 mb-2">Sabbath Services</h5>
<div class="space-y-1 text-sm text-gray-300">
<div class="flex items-center space-x-2">
<i data-lucide="sun" class="w-4 h-4 text-gold-400"></i>
<span>Sabbath School: {SERVICE_TIMES.SABBATH_SCHOOL}</span>
</div>
<div class="flex items-center space-x-2">
<i data-lucide="church" class="w-4 h-4 text-gold-400"></i>
<span>Divine Service: {SERVICE_TIMES.DIVINE_SERVICE}</span>
</div>
</div>
</div>
<!-- Social Links -->
{(facebookUrl || youtubeUrl || instagramUrl) && (
<div class="mb-6">
<h5 class="text-sm font-medium text-primary-300 mb-3">Follow Us</h5>
<div class="flex space-x-3">
{facebookUrl && (
<a href={facebookUrl} target="_blank" rel="noopener" class="social-link">
<i data-lucide="facebook" class="w-5 h-5"></i>
</a>
)}
{youtubeUrl && (
<a href={youtubeUrl} target="_blank" rel="noopener" class="social-link">
<i data-lucide="youtube" class="w-5 h-5"></i>
</a>
)}
{instagramUrl && (
<a href={instagramUrl} target="_blank" rel="noopener" class="social-link">
<i data-lucide="instagram" class="w-5 h-5"></i>
</a>
)}
</div>
</div>
)}
<!-- Mobile App Downloads -->
<div>
<h5 class="text-sm font-medium text-primary-300 mb-3">Get Our App</h5>
<div class="space-y-3">
<!-- iOS App Store -->
<a href="https://apps.apple.com/us/app/rtsda/id6738595657" target="_blank" rel="noopener" class="app-download-btn">
<div class="flex items-center space-x-3">
<div class="w-8 h-8 bg-gradient-to-br from-gray-700 to-black rounded-lg flex items-center justify-center">
<i data-lucide="smartphone" class="w-4 h-4 text-white"></i>
</div>
<div class="text-left">
<div class="text-xs text-gray-400">Download on the</div>
<div class="text-sm font-medium text-white">App Store</div>
</div>
</div>
</a>
<!-- PWA Installation -->
<button onclick="installPWA()" class="app-download-btn w-full text-left">
<div class="flex items-center space-x-3">
<div class="w-8 h-8 bg-gradient-to-br from-primary-600 to-primary-700 rounded-lg flex items-center justify-center">
<i data-lucide="smartphone" class="w-4 h-4 text-gold-400"></i>
</div>
<div class="text-left">
<div class="text-xs text-gray-400">Install as App</div>
<div class="text-sm font-medium text-white">Mobile & Desktop</div>
</div>
</div>
</button>
</div>
</div>
</div>
</div>
<!-- Bottom Bar -->
<div class="border-t border-white/10 mt-12 pt-8">
<div class="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
<div class="text-sm text-gray-400">
<p>&copy; {currentYear} {churchName}. All rights reserved.</p>
</div>
<div class="flex items-center space-x-6 text-sm text-gray-400">
<a href="/privacy" class="hover:text-white transition-colors">Privacy Policy</a>
<a href="/terms" class="hover:text-white transition-colors">Terms of Service</a>
<div class="flex items-center space-x-2">
<span>Built with love for God's glory</span>
</div>
</div>
</div>
</div>
</div>
</footer>
<style>
.footer-link {
@apply flex items-center space-x-2 text-gray-300 hover:text-white transition-colors duration-200;
}
.footer-link:hover i {
@apply text-primary-400 transform scale-110;
}
.social-link {
@apply w-10 h-10 bg-white/10 hover:bg-primary-500 rounded-lg flex items-center justify-center text-gray-300 hover:text-white transition-all duration-300 hover:scale-110 hover:shadow-lg;
}
.app-download-btn {
@apply block w-full p-3 bg-white/5 hover:bg-white/10 rounded-xl border border-white/10 hover:border-white/20 transition-all duration-300 hover:transform hover:scale-105 hover:shadow-lg;
}
</style>
<script is:inline>
let deferredPrompt = null;
// Listen for the beforeinstallprompt event
window.addEventListener('beforeinstallprompt', (e) => {
console.log('beforeinstallprompt event fired');
e.preventDefault();
deferredPrompt = e;
});
// PWA installation handler
window.installPWA = function() {
if (deferredPrompt) {
// Show the install prompt
deferredPrompt.prompt();
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the install prompt');
} else {
console.log('User dismissed the install prompt');
}
deferredPrompt = null;
});
} else {
// Show manual instructions for different platforms
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
let instructions = '';
if (isIOS) {
instructions = `To install this app on iOS:
1. Tap the Share button (□↗) in Safari
2. Scroll down and tap "Add to Home Screen"
3. Tap "Add" to confirm
4. The app will appear on your home screen
This creates a full-screen app experience!`;
} else if (isMobile) {
instructions = `To install this app on Android:
1. Open this website in Chrome browser
2. Tap the menu (⋮) in the top right
3. Select "Add to Home screen" or "Install app"
4. Follow the prompts to install
5. The app will appear on your home screen
This creates a full-screen app experience!`;
} else {
instructions = `To install this app on Desktop:
Chrome/Edge:
1. Look for the install icon (⊕) in the address bar
2. Click it and select "Install"
3. The app will open in its own window
Firefox/Safari:
1. Click the menu button
2. Look for "Install" or "Add to Home Screen" option
3. Follow the prompts to install
This creates a dedicated app window without browser tabs!`;
}
alert(instructions);
}
};
</script>