113 lines
4.8 KiB
JavaScript
113 lines
4.8 KiB
JavaScript
// ------------------------------------------------------------------------
|
||
// components/WeeklyNudge.js - Friendly weekly reminder for free users.
|
||
//
|
||
// Shown at most once every 7 days to non-subscribers (never on the very
|
||
// first visit - the WelcomeModal owns that moment). Leads with a small
|
||
// sun-themed fact so it reads as a bit of sunshine trivia rather than a
|
||
// nag, then offers SunScope Extra.
|
||
//
|
||
// Reuses the .welcome-* overlay/card styling. Purely presentational - the
|
||
// open/close state lives in useAppState (weeklyNudgeOpen).
|
||
//
|
||
// Props:
|
||
// onClose - dismiss and stamp the "shown" date (7-day cooldown)
|
||
// openRestore - opens the "Already subscribed?" restore modal
|
||
// ------------------------------------------------------------------------
|
||
|
||
import { h } from '../../vendor/preact.js';
|
||
import { useEffect, useMemo } from '../../vendor/preact-hooks.js';
|
||
import htm from '../../vendor/htm.js';
|
||
import { Wordmark } from './Wordmark.js';
|
||
import { SUBSCRIBE_URL, SUBSCRIBE_URL_ONEOFF } from './SubscribeModal.js';
|
||
|
||
const html = htm.bind(h);
|
||
|
||
// One of these is picked at random each time the nudge appears, so a
|
||
// regular user gets a different bit of sun trivia week to week.
|
||
const SUN_FACTS = [
|
||
{
|
||
icon: '☀️',
|
||
title: 'Sunlight is eight minutes old',
|
||
body: html`Every ray that warms your face left the Sun eight and a half minutes ago and
|
||
crossed 93 million miles to get here. The least you can do is dress for it.`,
|
||
},
|
||
{
|
||
icon: '🌡️',
|
||
title: 'Shade can feel 15°C cooler',
|
||
body: html`Air temperature barely changes when you step into shade — but what your body
|
||
feels can drop by ten or fifteen degrees. That gap is exactly what SunSoak measures.`,
|
||
},
|
||
{
|
||
icon: '🧴',
|
||
title: 'Clouds are not sunscreen',
|
||
body: html`Up to 80% of UV sails straight through thin cloud, which is why overcast days
|
||
catch people out. SunScope's UV and sunburn-time columns keep score for you.`,
|
||
},
|
||
{
|
||
icon: '🚗',
|
||
title: 'A parked car beats the desert',
|
||
body: html`On a mild 22°C afternoon a car's interior can pass 50°C in under an hour —
|
||
hotter than the Sahara. SunScope can show you that number before you park.`,
|
||
},
|
||
{
|
||
icon: '💨',
|
||
title: 'Wind steals your warmth',
|
||
body: html`A brisk breeze can strip several degrees off how cold you feel without moving
|
||
the thermometer at all. Wind chill is baked into every SunSoak reading.`,
|
||
},
|
||
{
|
||
icon: '🌅',
|
||
title: 'The golden hour is real',
|
||
body: html`Low sun travels through far more atmosphere, so early and late light is gentler
|
||
on skin — a good reason to check the hourly view before heading out.`,
|
||
},
|
||
];
|
||
|
||
export function WeeklyNudge({ onClose, openRestore }) {
|
||
const fact = useMemo(() => SUN_FACTS[Math.floor(Math.random() * SUN_FACTS.length)], []);
|
||
|
||
// Dismiss on Esc.
|
||
useEffect(() => {
|
||
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
|
||
document.addEventListener('keydown', onKey);
|
||
return () => document.removeEventListener('keydown', onKey);
|
||
}, [onClose]);
|
||
|
||
return html`
|
||
<div class="welcome-overlay" onClick=${onClose}>
|
||
<div class="welcome-card" role="dialog" aria-modal="true" aria-labelledby="nudge-title"
|
||
onClick=${(e) => e.stopPropagation()} style=${{ maxWidth: '440px' }}>
|
||
<button class="welcome-close" aria-label="Close" onClick=${onClose}>×</button>
|
||
<div class="welcome-head">
|
||
<${Wordmark} />
|
||
<div class="welcome-kicker" style=${{ marginTop: '10px' }}>Your weekly ray of sun</div>
|
||
</div>
|
||
<div class="nudge-fact">
|
||
<span class="nudge-fact-icon" aria-hidden="true">${fact.icon}</span>
|
||
<h2 class="welcome-title" id="nudge-title">${fact.title}</h2>
|
||
<p class="nudge-fact-body">${fact.body}</p>
|
||
</div>
|
||
<p class="welcome-remember">
|
||
✨ <strong>SunScope Extra</strong> unlocks the 🔒 profiles — hiking, sailing, fishing,
|
||
photography, winter sports and the whole Work set — plus Show All and custom columns,
|
||
so you can build your own view. £2 a month.
|
||
</p>
|
||
<a class="welcome-cta" href=${SUBSCRIBE_URL} target="_blank" rel="noopener noreferrer"
|
||
style=${{ textDecoration: 'none', textAlign: 'center', marginBottom: '10px' }}>
|
||
Subscribe — £2/month
|
||
</a>
|
||
<div class="nudge-links">
|
||
<a href=${SUBSCRIBE_URL_ONEOFF} target="_blank" rel="noopener noreferrer">
|
||
Or make a one-off payment →
|
||
</a>
|
||
<button type="button" onClick=${() => { onClose(); openRestore(); }}>
|
||
Already subscribed? Restore access →
|
||
</button>
|
||
<button type="button" class="nudge-dismiss" onClick=${onClose}>
|
||
Maybe next week
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>`;
|
||
}
|