add platform pages
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { Button, CardGrid, Card } from '$lib/components';
|
||||
|
||||
interface Tier {
|
||||
id: 'trial' | 'monthly' | 'yearly';
|
||||
name: string;
|
||||
price: string;
|
||||
period: string;
|
||||
desc: string;
|
||||
blurb: string;
|
||||
features: string[];
|
||||
cta: string;
|
||||
featured?: boolean;
|
||||
}
|
||||
@@ -17,16 +17,18 @@
|
||||
id: 'trial',
|
||||
name: 'Trial',
|
||||
price: 'Free',
|
||||
period: 'for a set period',
|
||||
desc: 'Try FamChore free for a period (e.g. 3 months) with a code.',
|
||||
cta: 'Start trial'
|
||||
period: 'for the trial period',
|
||||
blurb: 'Kick the tires on us.',
|
||||
features: ['Full family access', 'No card required', 'Code from us or a partner'],
|
||||
cta: 'Start free trial'
|
||||
},
|
||||
{
|
||||
id: 'monthly',
|
||||
name: 'Monthly',
|
||||
price: '£3',
|
||||
period: '/month',
|
||||
desc: 'Full access for one family. Cancel anytime.',
|
||||
blurb: 'Everything, month to month.',
|
||||
features: ['Unlimited kids & chores', 'Allowances calculated automatically', 'Bonuses & seasons', 'Cancel anytime'],
|
||||
cta: 'Choose monthly',
|
||||
featured: true
|
||||
},
|
||||
@@ -35,7 +37,8 @@
|
||||
name: 'Yearly',
|
||||
price: '£30',
|
||||
period: '/year',
|
||||
desc: 'Two months free vs monthly. Best value for committed families.',
|
||||
blurb: 'Two months free vs monthly.',
|
||||
features: ['Everything in Monthly', 'Two months free', 'Best for committed families'],
|
||||
cta: 'Choose yearly'
|
||||
}
|
||||
];
|
||||
@@ -49,104 +52,157 @@
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<CardGrid>
|
||||
<div class="tiers">
|
||||
{#each tiers.filter((t) => !(hideTrial && t.id === 'trial')) as tier}
|
||||
<Card title={tier.name} accent={tier.featured ? '#6366f1' : undefined} selected={selected === tier.id}>
|
||||
<article
|
||||
class="tier"
|
||||
class:featured={tier.featured}
|
||||
class:picked={selected === tier.id}
|
||||
aria-label="{tier.name} plan"
|
||||
>
|
||||
{#if tier.featured}
|
||||
<span class="pop">Most popular</span>
|
||||
{/if}
|
||||
<h3>{tier.name}</h3>
|
||||
<p class="price">
|
||||
<span class="amount">{tier.price}</span>
|
||||
<span class="period">{tier.period}</span>
|
||||
</p>
|
||||
<p class="hint">{tier.desc}</p>
|
||||
<p class="blurb">{tier.blurb}</p>
|
||||
|
||||
{#if tier.id === 'trial'}
|
||||
<form
|
||||
method="POST"
|
||||
action={action}
|
||||
use:enhance={onsubmit ?? undefined}
|
||||
>
|
||||
<input type="hidden" name="plan" value="trial" />
|
||||
<label class="field-label" for="trial-code">Trial code</label>
|
||||
<input
|
||||
id="trial-code"
|
||||
name="code"
|
||||
placeholder="e.g. FAM3MONTHS"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<Button type="submit" size="md" variant="secondary">Start trial</Button>
|
||||
</form>
|
||||
{:else}
|
||||
<form
|
||||
method="POST"
|
||||
action={action}
|
||||
use:enhance={onsubmit ?? undefined}
|
||||
>
|
||||
<input type="hidden" name="plan" value={tier.id} />
|
||||
<Button type="submit" size="md" variant={tier.featured ? 'primary' : 'secondary'}>
|
||||
{tier.cta}
|
||||
</Button>
|
||||
</form>
|
||||
{/if}
|
||||
<form method="POST" action={action} use:enhance={onsubmit ?? undefined}>
|
||||
<input type="hidden" name="plan" value={tier.id} />
|
||||
{#if tier.id === 'trial'}
|
||||
<input name="code" placeholder="Trial code" autocomplete="off" />
|
||||
{/if}
|
||||
<button type="submit" class="cta" class:primary={tier.featured}>{tier.cta}</button>
|
||||
</form>
|
||||
|
||||
{#if error}
|
||||
<p class="error">{error}</p>
|
||||
{/if}
|
||||
</Card>
|
||||
<ul>
|
||||
{#each tier.features as f}
|
||||
<li><span class="tick">✓</span>{f}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</article>
|
||||
{/each}
|
||||
</CardGrid>
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<p class="form-error">{error}</p>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.hint {
|
||||
font-size: 0.85rem;
|
||||
color: #9ca3af;
|
||||
line-height: 1.4;
|
||||
.tiers {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
|
||||
gap: 1.25rem;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
}
|
||||
.price {
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
.amount {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
.period {
|
||||
color: #9ca3af;
|
||||
font-size: 0.9rem;
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
form {
|
||||
.tier {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.6rem;
|
||||
margin-top: 0.75rem;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem 1.4rem 1.4rem;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.field-label {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
.tier.featured {
|
||||
border: 2px solid #6366f1;
|
||||
box-shadow: 0 10px 28px rgba(99, 102, 241, 0.18);
|
||||
}
|
||||
.tier.picked {
|
||||
outline: 2px solid #a5b4fc;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.pop {
|
||||
position: absolute;
|
||||
top: -0.7rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||
color: #fff;
|
||||
font-size: 0.68rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
padding: 0.22rem 0.7rem;
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: #6b7280;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
.price { margin: 0.55rem 0 0.15rem; line-height: 1; }
|
||||
.amount { font-size: 2.4rem; font-weight: 800; color: #111827; }
|
||||
.period { font-size: 0.85rem; color: #9ca3af; margin-left: 0.3rem; }
|
||||
.blurb { margin: 0 0 0.9rem; font-size: 0.85rem; color: #6b7280; }
|
||||
|
||||
form { display: flex; flex-direction: column; gap: 0.55rem; margin-top: auto; }
|
||||
input {
|
||||
padding: 0.55rem 0.75rem;
|
||||
padding: 0.5rem 0.65rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
font-size: 0.85rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
input:focus {
|
||||
outline: 2px solid #6366f1;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
form :global(.btn) {
|
||||
.cta {
|
||||
width: 100%;
|
||||
padding: 0.65rem 1rem;
|
||||
border-radius: 10px;
|
||||
font-size: 0.92rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
border: 1.5px solid #6366f1;
|
||||
background: #fff;
|
||||
color: #4338ca;
|
||||
transition: background 0.15s ease, transform 0.05s ease;
|
||||
}
|
||||
.error {
|
||||
.cta:hover { background: #eef2ff; }
|
||||
.cta:active { transform: scale(0.98); }
|
||||
.cta.primary {
|
||||
background: linear-gradient(135deg, #4338ca, #6366f1);
|
||||
color: #fff;
|
||||
border-color: transparent;
|
||||
}
|
||||
.cta.primary:hover { background: linear-gradient(135deg, #3730a3, #4f46e5); }
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 1.1rem 0 0;
|
||||
padding: 0.9rem 0 0;
|
||||
border-top: 1px solid #f3f4f6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
li {
|
||||
font-size: 0.84rem;
|
||||
color: #4b5563;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
.tick { color: #059669; font-weight: 700; flex-shrink: 0; }
|
||||
|
||||
.form-error {
|
||||
grid-column: 1 / -1;
|
||||
color: #dc2626;
|
||||
background: #fef2f2;
|
||||
padding: 0.5rem;
|
||||
border-radius: 6px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 8px;
|
||||
font-size: 0.85rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
:global(.selected) {
|
||||
border: 2px solid #6366f1;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user