
- 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.
357 lines
14 KiB
Plaintext
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>© {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> |