Add FamDone Brand component

This commit is contained in:
JCEEE
2026-09-02 11:50:51 +01:00
parent 1d4d6be20b
commit f288df5b9c
18 changed files with 657 additions and 493 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
--- ---
# FamChore v2 — AI Agent Reference # FamDone v2 — AI Agent Reference
## Stack ## Stack
+1 -1
View File
@@ -1,4 +1,4 @@
# FamChore v2 — Architecture & Developer Reference # FamDone v2 — Architecture & Developer Reference
## Overview ## Overview
+2 -2
View File
@@ -1,4 +1,4 @@
# FamChore v2 — Development Memory # FamDone v2 — Development Memory
## 2026-08-17 — Schema collapse to single source of truth (Option 1) ## 2026-08-17 — Schema collapse to single source of truth (Option 1)
@@ -34,7 +34,7 @@
``` ```
### Sidebar (collapsible to mini-mode) ### Sidebar (collapsible to mini-mode)
- Header: app name (FamChore) - Header: app name (FamDone)
- Admin CTAs: Dashboard, Chores, Rewards (badge count), Bonuses - Admin CTAs: Dashboard, Chores, Rewards (badge count), Bonuses
- Member CTAs: Dashboard, Preferences - Member CTAs: Dashboard, Preferences
- Footer: family name, Settings (admin only), Log out - Footer: family name, Settings (admin only), Log out
+1 -1
View File
@@ -1,4 +1,4 @@
# FamChore v2 — Rules # FamDone v2 — Rules
## Auth ## Auth
- Every collection query includes `famId = @request.auth.famId` filter - Every collection query includes `famId = @request.auth.famId` filter
+1 -1
View File
@@ -1,4 +1,4 @@
# FamChore — TODO # FamDone — TODO
(Completed work is tracked in MEMORY.md / git history.) (Completed work is tracked in MEMORY.md / git history.)
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check-circle"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>

After

Width:  |  Height:  |  Size: 328 B

+15 -4
View File
@@ -1,5 +1,11 @@
<script lang="ts"> <script lang="ts">
let { title, subtitle, children }: { import FamDone from './FamDone.svelte';
let {
title,
subtitle,
children
}: {
title: string; title: string;
subtitle?: string; subtitle?: string;
children?: any; children?: any;
@@ -7,7 +13,7 @@
</script> </script>
<main class="auth"> <main class="auth">
<a class="brand" href="/">FamChore</a> <a class="brand" href="/"><FamDone /></a>
<div class="card"> <div class="card">
<h1>{title}</h1> <h1>{title}</h1>
{#if subtitle} {#if subtitle}
@@ -26,7 +32,10 @@
justify-content: center; justify-content: center;
padding: 2rem 1rem; padding: 2rem 1rem;
background: linear-gradient(135deg, #eef2ff 0%, #ffffff 55%, #eef2ff 100%); background: linear-gradient(135deg, #eef2ff 0%, #ffffff 55%, #eef2ff 100%);
font-family: system-ui, -apple-system, sans-serif; font-family:
system-ui,
-apple-system,
sans-serif;
color: #1f2937; color: #1f2937;
} }
.brand { .brand {
@@ -56,6 +65,8 @@
line-height: 1.5; line-height: 1.5;
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.card { padding: 1.5rem; } .card {
padding: 1.5rem;
}
} }
</style> </style>
@@ -0,0 +1,33 @@
<script lang="ts">
let { tag = 'span' }: { tag?: 'span' | 'h1' | 'h2' | 'h3' | 'a' | 'strong' | 'p' } = $props();
</script>
<svelte:element this={tag} class="fam-done">
FamDone<svg
class="fam-done-check"
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="#10b981"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /><polyline points="22 4 12 14.01 9 11.01" /></svg
></svelte:element
>
<style>
.fam-done {
font-weight: inherit;
color: inherit;
}
.fam-done-check {
vertical-align: super;
position: relative;
top: -0.3em;
margin-left: 1px;
display: inline-block;
}
</style>
+5 -1
View File
@@ -1,5 +1,9 @@
<script lang="ts">
import FamDone from './FamDone.svelte';
</script>
<footer class="app-footer"> <footer class="app-footer">
<span class="footer-text">FamChore</span> <span class="footer-text"><FamDone /></span>
</footer> </footer>
<style> <style>
+2 -1
View File
@@ -10,6 +10,7 @@
logoutIcon, logoutIcon,
prefsIcon prefsIcon
} from './icons'; } from './icons';
import FamDone from './FamDone.svelte';
let { famName = '', session = null, isParent = false, role = 'child' } = $props(); let { famName = '', session = null, isParent = false, role = 'child' } = $props();
@@ -53,7 +54,7 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="sidebar-header"> <div class="sidebar-header">
<span class="app-icon">✦</span> <span class="app-icon">✦</span>
<span class="app-name">FamChore</span> <span class="app-name"><FamDone /></span>
</div> </div>
<nav class="sidebar-nav"> <nav class="sidebar-nav">
+1
View File
@@ -1,4 +1,5 @@
export { default as Sidebar } from './Sidebar.svelte'; export { default as Sidebar } from './Sidebar.svelte';
export { default as FamDone } from './FamDone.svelte';
export { default as TopNav } from './TopNav.svelte'; export { default as TopNav } from './TopNav.svelte';
export { default as Footer } from './Footer.svelte'; export { default as Footer } from './Footer.svelte';
export { default as ViewHeader } from './ViewHeader.svelte'; export { default as ViewHeader } from './ViewHeader.svelte';
+1 -1
View File
@@ -34,7 +34,7 @@ export async function sendParentInviteEmail(opts: {
await resend.emails.send({ await resend.emails.send({
from: 'no-reply@famchamp.ai', from: 'no-reply@famchamp.ai',
to, to,
subject: `You're invited to ${famName} on FamChore`, subject: `You're invited to ${famName} on FamDone`,
html: ` html: `
<p>You've been invited as a parent on <strong>${famName}</strong>.</p> <p>You've been invited as a parent on <strong>${famName}</strong>.</p>
<p><a href="${inviteLink}">Click here to join</a> and set up your password.</p> <p><a href="${inviteLink}">Click here to join</a> and set up your password.</p>
+4 -3
View File
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import Footer from '$lib/components/Footer.svelte'; import Footer from '$lib/components/Footer.svelte';
import FamDone from '$lib/components/FamDone.svelte';
import { homeIcon, checkCircleIcon, chevronRightIcon } from '$lib/components/icons'; import { homeIcon, checkCircleIcon, chevronRightIcon } from '$lib/components/icons';
import { readShortcut, shortcutTarget, type Shortcut } from '$lib/shortcut'; import { readShortcut, shortcutTarget, type Shortcut } from '$lib/shortcut';
@@ -13,7 +14,7 @@
</script> </script>
<svelte:head> <svelte:head>
<title>FamChore — Chores done. Allowance earned.</title> <title>FamDone — Chores done. Allowance earned.</title>
<meta <meta
name="description" name="description"
content="Turn family chores into points and pocket money. Assign chores, kids complete them, allowances are calculated automatically." content="Turn family chores into points and pocket money. Assign chores, kids complete them, allowances are calculated automatically."
@@ -40,8 +41,8 @@
<span class="pill">For busy families</span> <span class="pill">For busy families</span>
<h1>Chores done. <span class="accent">Allowance earned.</span></h1> <h1>Chores done. <span class="accent">Allowance earned.</span></h1>
<p class="lede"> <p class="lede">
FamChore turns everyday household chores into points and pocket money. Assign the chores, <FamDone /> turns everyday household chores into points and pocket money. Assign the chores,
let your kids see their progress live, and FamChore calculates the allowance automatically let your kids see their progress live, and <FamDone /> calculates the allowance automatically
— no spreadsheets, no nagging. — no spreadsheets, no nagging.
</p> </p>
<ul class="hero-ticks"> <ul class="hero-ticks">
+2 -2
View File
@@ -39,7 +39,7 @@
if (returnHandled || page.url.searchParams.get('checkout') !== 'return') return; if (returnHandled || page.url.searchParams.get('checkout') !== 'return') return;
returnHandled = true; returnHandled = true;
if (!disabled) { if (!disabled) {
notices.success('Welcome to FamChore!', 'Your subscription is active.'); notices.success('Welcome to FamDone!', 'Your subscription is active.');
return; return;
} }
startActivating(); startActivating();
@@ -195,7 +195,7 @@
<strong>Access paused</strong> <strong>Access paused</strong>
<span> <span>
{isParent {isParent
? 'Add an access code or resume your subscription to keep using FamChore.' ? 'Add an access code or resume your subscription to keep using FamDone.'
: 'Your family access is paused.'} : 'Your family access is paused.'}
</span> </span>
{/if} {/if}
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -45,9 +45,9 @@ export async function POST({ request, url }) {
await resend.emails.send({ await resend.emails.send({
from: 'no-reply@famchamp.ai', from: 'no-reply@famchamp.ai',
to: email, to: email,
subject: 'Reset your FamChore password', subject: 'Reset your FamDone password',
html: ` html: `
<p>You requested a password reset for your FamChore account.</p> <p>You requested a password reset for your FamDone account.</p>
<p><a href="${resetUrl}">Click here to reset your password</a></p> <p><a href="${resetUrl}">Click here to reset your password</a></p>
<p>This link expires in 1 hour.</p> <p>This link expires in 1 hour.</p>
<p>If you didn't request this, you can ignore this email.</p> <p>If you didn't request this, you can ignore this email.</p>
+1 -1
View File
@@ -27,7 +27,7 @@
} }
</script> </script>
<AuthShell title="Log in" subtitle="Welcome back to FamChore."> <AuthShell title="Log in" subtitle="Welcome back to FamDone.">
{#if showForgot} {#if showForgot}
{#if forgotSuccess} {#if forgotSuccess}
<p class="form-ok"> <p class="form-ok">
+3 -2
View File
@@ -5,6 +5,7 @@
import { PUBLIC_STRIPE_PUBLISHABLE_KEY } from '$app/env/public'; import { PUBLIC_STRIPE_PUBLISHABLE_KEY } from '$app/env/public';
import { loadStripe, type StripeEmbeddedCheckout } from '@stripe/stripe-js'; import { loadStripe, type StripeEmbeddedCheckout } from '@stripe/stripe-js';
import { Button, PricingPlans } from '$lib/components'; import { Button, PricingPlans } from '$lib/components';
import FamDone from '$lib/components/FamDone.svelte';
import Footer from '$lib/components/Footer.svelte'; import Footer from '$lib/components/Footer.svelte';
import { homeIcon, chevronLeftIcon, chevronRightIcon } from '$lib/components/icons'; import { homeIcon, chevronLeftIcon, chevronRightIcon } from '$lib/components/icons';
@@ -56,12 +57,12 @@
} }
</script> </script>
<svelte:head><title>Pricing — FamChore</title></svelte:head> <svelte:head><title>Pricing — FamDone</title></svelte:head>
<div class="shell"> <div class="shell">
<header class="topbar"> <header class="topbar">
<a class="brand" href="/" <a class="brand" href="/"
><span class="brand-icon">{@html homeIcon}</span> <strong>FamChore</strong></a ><span class="brand-icon">{@html homeIcon}</span> <strong><FamDone /></strong></a
> >
<nav> <nav>
<a href="/login" class="nav-link">Log in</a> <a href="/login" class="nav-link">Log in</a>