// DEPLOY_CONFIG: {"cron": [{"name": "monthly_family_milestone_summary", "schedule": "0 9 1 * *", "action": "event", "config": {"event_type": "generate_monthly_family_milestone_summary"}}], "triggers": [{"name": "send_monthly_family_milestone_summary_email", "on": "event.generate_monthly_family_milestone_summary", "actions": [{"type": "email", "to": "{{family_member_emails}}", "subject": "Monthly Milestone Summary", "body": "Hello family member,\n\nHere is your monthly milestone summary for the family.\n\n{{milestone_summary}}\n\nBest,\nDeplixo"}]}]} import { useMemo, useRef, useState } from 'react'; import { useAuth, useCollection, generatePDF } from '@deplixo/sdk'; import { Timeline } from './components/Timeline.jsx'; import { Suggestions } from './components/Suggestions.jsx'; function App() { const { user, loading, login, logout } = useAuth(); const { items: shareLinks, add: addShareLink, loading: shareLinksLoading } = useCollection('share_links', { personal: true }); const { items: milestones = [], loading: milestonesLoading } = useCollection('milestones', { personal: true }); const [activeTab, setActiveTab] = useState('timeline'); const [shareLinkCopied, setShareLinkCopied] = useState(false); const [shareError, setShareError] = useState(''); const [linkMode, setLinkMode] = useState(false); const [accessCode, setAccessCode] = useState(''); const [shareTitle, setShareTitle] = useState('Grandparent Viewer'); const [pdfExporting, setPdfExporting] = useState(false); const pdfRef = useRef(null); const tabs = [ { id: 'timeline', label: '๐Ÿ“… Timeline', icon: '๐Ÿ“…' }, { id: 'suggestions', label: '๐Ÿ’ก Suggestions', icon: '๐Ÿ’ก' } ]; const currentShareLink = useMemo(() => { if (!shareLinks?.length) return null; return [...shareLinks] .filter(link => link && link.token) .sort((a, b) => new Date(b.createdAt || 0) - new Date(a.createdAt || 0))[0] || null; }, [shareLinks]); const printableMilestones = useMemo(() => { return [...(milestones || [])].sort((a, b) => new Date(b.date || b.createdAt || 0) - new Date(a.date || a.createdAt || 0)); }, [milestones]); const readQueryParam = (key) => { try { return new URLSearchParams(window.location.search).get(key) || ''; } catch { return ''; } }; const normalizeToken = (value) => (value || '').trim(); const hasTimelineAccess = () => { const linkToken = normalizeToken(readQueryParam('share')); if (!linkToken) return true; return shareLinks?.some(link => normalizeToken(link.token) === linkToken && link.active !== false) || false; }; const canCreateShareLink = () => !!user && !linkMode && !shareLinksLoading; const generateShareLink = async () => { setShareError(''); setShareLinkCopied(false); try { const token = `${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`; const baseUrl = window.location.origin + window.location.pathname; const url = `${baseUrl}?share=${encodeURIComponent(token)}`; await addShareLink({ token, url, title: shareTitle.trim() || 'Grandparent Viewer', familyName: user?.name || 'Family', active: true, createdAt: new Date().toISOString(), createdBy: user?.email || user?.name || 'unknown' }); try { await navigator.clipboard.writeText(url); setShareLinkCopied(true); } catch { setShareLinkCopied(false); } } catch (error) { setShareError('Could not generate a share link right now. Please try again.'); } }; const handlePdfExport = async () => { if (!pdfRef.current || pdfExporting) return; setPdfExporting(true); try { await generatePDF(pdfRef.current, { filename: 'milestone-book.pdf', margin: 10 }); } finally { setPdfExporting(false); } }; const renderShareAccessBanner = () => { const shareToken = normalizeToken(readQueryParam('share')); if (!shareToken) return null; const valid = shareLinks?.some(link => normalizeToken(link.token) === shareToken && link.active !== false); return (
{valid ? 'Shared family timeline' : 'Invalid or expired share link'}

{valid ? 'You are viewing a timeline shared by this family. You can browse the shared milestones without signing in.' : 'This link is not active anymore. Please ask the family for a new shared link.'}

{valid ? ( ) : null}
); }; if (loading) { return (
๐Ÿ‘ถ

Baby Milestones

Loading your family account...

); } const queryShareToken = normalizeToken(readQueryParam('share')); const sharedAccess = queryShareToken ? hasTimelineAccess() : false; if (!user && !sharedAccess && queryShareToken) { return (
๐Ÿ‘ถ

Baby Milestones

Shared timeline access

๐Ÿ”’

This shared link is unavailable

Ask the family to generate a new share link so you can view the timeline again.

); } if (!user && !sharedAccess) { return (
๐Ÿ‘ถ

Baby Milestones

Cherish every first moment

โœจ

Sign in with Google

Create or join a shared family account so parents and caregivers can record milestones together.

  • Shared family timeline
  • Multiple caregivers on one account
  • Safe Google sign-in for every family member

By continuing, your Google account becomes part of this family workspace.

); } return (
๐Ÿ‘ถ

Baby Milestones

Cherish every first moment

{user ? `Signed in as ${user.name} ยท ${user.email}` : 'Viewing shared family timeline'}

{user?.avatar ? {user.name} : '๐Ÿ‘ค'}
{user ? user.name : 'Grandparent viewer'} {sharedAccess && !user ? 'Shared link access' : 'Family member account'}
{user ? : null} {user ? ( ) : null}
{renderShareAccessBanner()} {user ? (

Share the timeline with grandparents

Create a view-only link that lets grandparents open the shared family timeline.

setShareTitle(e.target.value)} placeholder="Grandparent Viewer" aria-label="Share link title" />
{currentShareLink ? (
{shareLinkCopied ?

Link copied to clipboard.

: null}
) : null} {shareError ?

{shareError}

: null}
) : null}
{activeTab === 'timeline' && } {activeTab === 'suggestions' && user && } {activeTab === 'suggestions' && !user ? (
๐Ÿ‘ช

Shared view is timeline-only

Sign in to access milestone suggestions and manage your family workspace.

) : null}
); } ReactDOM.createRoot(document.getElementById('root')).render();