Files
dynamic-sites-simple/src/pages/sms-onboarding.astro
Khalid A 250b0d4aa3 Add legal and onboarding pages
- Add /sms-onboarding page for text message consent signup
  with FAQ, consent checkbox, and feature grid
- Add /privacy-policy page with comprehensive sections
  covering data collection, SMS communications, and user rights
- Add /terms page with full terms of use including
  SMS service terms, intellectual property, and disclaimers

All pages use BaseLayout and site-context for dynamic branding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 03:48:01 -05:00

422 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
import BaseLayout from '../layouts/BaseLayout.astro';
import { loadSiteData } from '../lib/site-data.ts';
const { siteContext } = loadSiteData();
// In a real implementation, this would connect to an API endpoint
// that stores the phone number and sends a confirmation SMS
---
<BaseLayout title={`Text Message Updates — ${siteContext.businessName}`} primaryColor={siteContext.primaryColor}>
<Fragment slot="logo">{siteContext.businessName}</Fragment>
<Fragment slot="tagline">Stay Connected</Fragment>
<section class="onboarding-hero">
<div class="container">
<h1>Get Website Updates by Text</h1>
<p class="lead">
Sign up to receive text message notifications whenever we update our website
with new events, menu items, or announcements.
</p>
</div>
</section>
<section class="onboarding-form">
<div class="container">
<div class="form-card">
<h2>Sign Up for Text Notifications</h2>
<form id="sms-signup-form" method="POST" action="/api/sms/subscribe">
<div class="form-group">
<label for="phone">Phone Number</label>
<input
type="tel"
id="phone"
name="phone"
placeholder="(503) 555-0142"
required
pattern="[\d\s\-\+\(\)]{10,}"
/>
<span class="hint">We'll send a confirmation text to verify your number.</span>
</div>
<div class="form-group">
<label for="name">Your Name (optional)</label>
<input
type="text"
id="name"
name="name"
placeholder="First name"
/>
</div>
<div class="consent-box">
<label class="checkbox-label">
<input type="checkbox" name="consent" required />
<span class="checkmark"></span>
<span class="label-text">
I consent to receive text messages from <strong>{siteContext.businessName}</strong>
about website updates, events, and announcements.
Message frequency varies. Message and data rates may apply.
Reply STOP to opt out at any time.
</span>
</label>
</div>
<button type="submit" class="submit-btn">Subscribe</button>
</form>
<div id="form-success" class="form-message success" style="display: none;">
<h3>You're all set!</h3>
<p>Check your phone for a confirmation message. Reply YES to complete your signup.</p>
</div>
<div id="form-error" class="form-message error" style="display: none;">
<h3>Something went wrong</h3>
<p>Please try again or contact us directly.</p>
</div>
</div>
</div>
</section>
<section class="what-to-expect">
<div class="container">
<h2>What You'll Receive</h2>
<div class="feature-grid">
<div class="feature">
<span class="feature-icon">📅</span>
<h3>New Events</h3>
<p>Be the first to know about upcoming community events, tastings, and workshops.</p>
</div>
<div class="feature">
<span class="feature-icon">☕</span>
<h3>Menu Updates</h3>
<p>Get notified when we add new seasonal drinks or specialty items to the menu.</p>
</div>
<div class="feature">
<span class="feature-icon">🏷️</span>
<h3>Special Offers</h3>
<p>Receive exclusive promotions and limited-time offers for subscribers.</p>
</div>
<div class="feature">
<span class="feature-icon">🔔</span>
<h3>Website Changes</h3>
<p>Stay informed when we update our hours, location details, or services.</p>
</div>
</div>
</div>
</section>
<section class="faq-section">
<div class="container">
<h2>Common Questions</h2>
<div class="faq-list">
<details class="faq-item">
<summary>How often will I receive messages?</summary>
<p>
Message frequency varies based on website updates and events — typically 2-4 messages per month.
We respect your time and only send messages that matter.
</p>
</details>
<details class="faq-item">
<summary>Is there a cost?</summary>
<p>
Message and data rates may apply depending on your wireless carrier plan.
Standard text messaging rates from your provider will apply.
</p>
</details>
<details class="faq-item">
<summary>How do I stop receiving messages?</summary>
<p>
Reply <strong>STOP</strong> to any message at any time to opt out.
You'll receive a confirmation, and no further messages will be sent.
Reply <strong>START</strong> to resubscribe.
</p>
</details>
<details class="faq-item">
<summary>Is my phone number shared?</summary>
<p>
No. Your phone number is used solely by {siteContext.businessName} for the purposes
you consented to. We do not sell or share your information with third parties.
See our <a href="/privacy-policy">Privacy Policy</a> for full details.
</p>
</details>
</div>
</div>
</section>
<Fragment slot="footer">
&copy; {new Date().getFullYear()} {siteContext.businessName} &middot;
<a href="/privacy-policy">Privacy Policy</a> &middot;
<a href="/terms">Terms of Use</a>
</Fragment>
</BaseLayout>
<style>
.onboarding-hero {
text-align: center;
padding: 4rem 1.5rem 2.5rem;
background: linear-gradient(180deg, color-mix(in srgb, var(--color-primary), white 92%) 0%, var(--color-bg) 100%);
}
.onboarding-hero h1 {
font-family: var(--font-display);
font-size: 2.25rem;
color: var(--color-primary-dark);
margin-bottom: 0.75rem;
}
.onboarding-hero .lead {
font-size: 1.1rem;
color: var(--color-text-muted);
max-width: 560px;
margin: 0 auto;
line-height: 1.6;
}
.onboarding-form {
padding: 1.5rem 1.5rem 3rem;
}
.form-card {
max-width: 520px;
margin: 0 auto;
background: white;
border: 1px solid var(--color-border);
border-radius: 10px;
padding: 2rem;
}
.form-card h2 {
font-family: var(--font-display);
font-size: 1.3rem;
color: var(--color-primary-dark);
margin-bottom: 1.25rem;
text-align: center;
}
.form-group {
margin-bottom: 1.25rem;
}
.form-group label {
display: block;
font-size: 0.85rem;
font-weight: 500;
color: var(--color-text);
margin-bottom: 0.35rem;
}
.form-group input {
display: block;
width: 100%;
padding: 0.65rem 0.85rem;
border: 1px solid var(--color-border);
border-radius: 6px;
font-size: 1rem;
font-family: var(--font-body);
transition: border-color 0.2s;
}
.form-group input:focus {
outline: none;
border-color: var(--color-primary);
}
.form-group .hint {
display: block;
font-size: 0.8rem;
color: var(--color-text-muted);
margin-top: 0.3rem;
}
.consent-box {
margin-bottom: 1.5rem;
}
.checkbox-label {
display: flex;
align-items: flex-start;
gap: 0.6rem;
cursor: pointer;
font-size: 0.9rem;
line-height: 1.5;
color: var(--color-text);
}
.checkbox-label input[type="checkbox"] {
width: 18px;
height: 18px;
margin-top: 0.15rem;
accent-color: var(--color-primary);
flex-shrink: 0;
}
.label-text strong {
color: var(--color-primary-dark);
}
.submit-btn {
width: 100%;
padding: 0.8rem;
background: var(--color-primary);
color: white;
border: none;
border-radius: 6px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
font-family: var(--font-body);
transition: background 0.2s;
}
.submit-btn:hover {
background: var(--color-primary-dark);
}
.form-message {
text-align: center;
padding: 1.5rem;
border-radius: 8px;
margin-top: 1rem;
}
.form-message h3 {
font-family: var(--font-display);
font-size: 1.15rem;
margin-bottom: 0.5rem;
}
.form-message.success {
background: color-mix(in srgb, #22c55e, white 88%);
color: #166534;
}
.form-message.error {
background: color-mix(in srgb, #ef4444, white 88%);
color: #991b1b;
}
.what-to-expect {
padding: 3rem 1.5rem;
background: color-mix(in srgb, var(--color-primary), white 96%);
border-top: 1px solid var(--color-border);
}
.what-to-expect h2 {
font-family: var(--font-display);
font-size: 1.6rem;
color: var(--color-primary-dark);
text-align: center;
margin-bottom: 2rem;
}
.feature-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
max-width: 720px;
margin: 0 auto;
}
@media (max-width: 600px) {
.feature-grid {
grid-template-columns: 1fr;
}
}
.feature {
text-align: center;
padding: 1.25rem;
background: white;
border: 1px solid var(--color-border);
border-radius: 8px;
}
.feature-icon {
font-size: 1.75rem;
display: block;
margin-bottom: 0.5rem;
}
.feature h3 {
font-family: var(--font-display);
font-size: 1.1rem;
color: var(--color-primary-dark);
margin-bottom: 0.4rem;
}
.feature p {
font-size: 0.9rem;
color: var(--color-text-muted);
line-height: 1.5;
}
.faq-section {
padding: 3rem 1.5rem;
}
.faq-section h2 {
font-family: var(--font-display);
font-size: 1.6rem;
color: var(--color-primary-dark);
text-align: center;
margin-bottom: 2rem;
}
.faq-list {
max-width: 680px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.faq-item {
background: white;
border: 1px solid var(--color-border);
border-radius: 8px;
overflow: hidden;
}
.faq-item summary {
padding: 1rem 1.25rem;
font-weight: 500;
color: var(--color-text);
cursor: pointer;
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
}
.faq-item summary::-webkit-details-marker {
display: none;
}
.faq-item summary::after {
content: '+';
font-size: 1.25rem;
color: var(--color-primary);
font-weight: 300;
}
.faq-item[open] summary::after {
content: '';
}
.faq-item p {
padding: 0 1.25rem 1rem;
font-size: 0.9rem;
color: var(--color-text-muted);
line-height: 1.6;
}
.faq-item p a {
color: var(--color-primary);
text-decoration: underline;
}
</style>
<script>
const form = document.getElementById('sms-signup-form');
const successMsg = document.getElementById('form-success');
const errorMsg = document.getElementById('form-error');
if (form) {
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
try {
const response = await fetch('/api/sms/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
phone: formData.get('phone'),
name: formData.get('name'),
consent: formData.get('consent') === 'on',
}),
});
if (response.ok) {
form.style.display = 'none';
successMsg.style.display = 'block';
} else {
throw new Error('Subscription failed');
}
} catch {
errorMsg.style.display = 'block';
}
});
}
</script>