chore(brand): update PWA icons, release notes, and About page
This commit is contained in:
parent
abb9f7d443
commit
3a14c50e08
|
|
@ -1,7 +1,7 @@
|
|||
# Bill Tracker
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/images/logo_cut.png" alt="Bill Tracker logo">
|
||||
<img src="client/public/brand/social-preview.svg" alt="Bill Tracker — Calm command for household money">
|
||||
</p>
|
||||
|
||||
Bill Tracker is a private, self-hosted bill planning app for households and
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react';
|
|||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { RELEASE_NOTES } from '@/lib/version';
|
||||
import { Sparkles } from 'lucide-react';
|
||||
import { BrandGlyph } from '@/components/brand/Brand';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { api } from '@/api';
|
||||
|
||||
|
|
@ -28,9 +28,7 @@ export function ReleaseNotesDialog() {
|
|||
<DialogContent className="max-h-[92dvh] max-w-md overflow-y-auto sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10">
|
||||
<Sparkles className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
<BrandGlyph name="tracker" className="h-8 w-8 rounded-lg" />
|
||||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||
v{RELEASE_NOTES.version} · {RELEASE_NOTES.date}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useState } from 'react';
|
|||
import { AlertCircle, ChevronDown, ChevronUp, BellOff, SkipForward, CreditCard, EyeOff } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { api } from '@/api';
|
||||
import { cn, fmt, localDateString } from '@/lib/utils';
|
||||
import { fmt, localDateString } from '@/lib/utils';
|
||||
import { asDollars } from '@/lib/money';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export const RELEASE_NOTES: ReleaseNotes = {
|
|||
},
|
||||
],
|
||||
image: {
|
||||
src: '/img/doingmypart.jpg',
|
||||
alt: 'Doing my part',
|
||||
src: '/brand/social-preview.svg',
|
||||
alt: 'Bill Tracker brand preview',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ import { ArrowLeft, ArrowUpCircle, CheckCircle2, Info, Loader2, Sparkles, AlertC
|
|||
import { api } from '@/api';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { APP_VERSION } from '@/lib/version';
|
||||
import { BRAND } from '@/lib/brand';
|
||||
import { BrandMark } from '@/components/brand/Brand';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { PageHeader } from '@/components/ui/app-primitives';
|
||||
|
||||
const REPOSITORY_URL = 'https://dream.scheller.ltd/null/BillTracker';
|
||||
|
||||
|
|
@ -99,7 +102,7 @@ export default function AboutPage() {
|
|||
const displayVersion = about?.version ?? APP_VERSION;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.06),transparent_34rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.18))] px-4 py-8 text-foreground sm:px-6">
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.10),transparent_32rem),radial-gradient(circle_at_top_right,oklch(var(--accent)/0.08),transparent_24rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.18))] px-4 py-8 text-foreground sm:px-6">
|
||||
<main className="mx-auto w-full max-w-3xl space-y-5">
|
||||
<Button asChild variant="ghost" size="sm" className="-ml-2">
|
||||
<Link to={user ? '/' : '/login'}>
|
||||
|
|
@ -108,14 +111,20 @@ export default function AboutPage() {
|
|||
</Link>
|
||||
</Button>
|
||||
|
||||
<Card className="border-border/70 bg-card shadow-sm" id="about-card">
|
||||
<Card className="overflow-hidden border-border/70 bg-card/95 shadow-sm" id="about-card">
|
||||
<CardHeader>
|
||||
<div className="mb-2 flex h-10 w-10 items-center justify-center rounded-xl border border-border/70 bg-primary/10 text-primary">
|
||||
<Info className="h-5 w-5" />
|
||||
<div className="mb-4 flex justify-center rounded-xl border border-border/70 bg-[radial-gradient(circle_at_top,oklch(var(--primary)/0.14),transparent_70%),oklch(var(--muted)/0.20)] px-5 py-7">
|
||||
<BrandMark className="h-auto w-full max-w-[18rem] drop-shadow-[0_10px_30px_rgba(0,0,0,0.16)]" />
|
||||
</div>
|
||||
<CardTitle className="text-2xl">{about?.name || 'Bill Tracker'}</CardTitle>
|
||||
<PageHeader
|
||||
eyebrow="About"
|
||||
title={about?.name || BRAND.name}
|
||||
description={about?.description || BRAND.tagline}
|
||||
glyph="security"
|
||||
/>
|
||||
<CardTitle className="sr-only">{about?.name || BRAND.name}</CardTitle>
|
||||
<CardDescription>
|
||||
<span className="text-sm">{about?.description || ''}</span>
|
||||
<span className="sr-only">{about?.description || BRAND.tagline}</span>
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-5">
|
||||
|
|
@ -141,12 +150,24 @@ export default function AboutPage() {
|
|||
</div>
|
||||
|
||||
<div className="rounded-xl border border-border/70 bg-muted/35 p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<Info className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
|
||||
<div>
|
||||
<p className="text-sm font-semibold">Private, practical, self-hosted</p>
|
||||
<p className="mt-1 text-sm leading-6 text-muted-foreground">
|
||||
{BRAND.name} is self-hosted software for personal bill planning and history. It is built around local ownership, readable records, and calm monthly review.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-xl border border-primary/20 bg-primary/[0.06] p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<Sparkles className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
|
||||
<div>
|
||||
<p className="text-sm font-semibold">Produced with AI assistance</p>
|
||||
<p className="text-sm font-semibold">{BRAND.tagline}</p>
|
||||
<p className="mt-1 text-sm leading-6 text-muted-foreground">
|
||||
Bill Tracker is self-hosted software for personal bill planning and history. This product was produced with the assistance of AI.
|
||||
The brand direction is premium calm: trustworthy, quiet, and focused on reducing household money stress.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { api } from '@/api';
|
|||
import { cn, errMessage } from '@/lib/utils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { MarkdownText } from '@/components/MarkdownText';
|
||||
import { EmptyState, PageHeader } from '@/components/ui/app-primitives';
|
||||
|
||||
interface ReleaseHistoryData {
|
||||
history?: string;
|
||||
|
|
@ -110,27 +111,32 @@ export default function ReleaseNotesPage() {
|
|||
const history = data?.history || '';
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.06),transparent_34rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.18))] px-4 py-8 text-foreground sm:px-6">
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.10),transparent_32rem),radial-gradient(circle_at_top_right,oklch(var(--accent)/0.08),transparent_24rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.18))] px-4 py-8 text-foreground sm:px-6">
|
||||
<main className="mx-auto w-full max-w-4xl space-y-5">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<Button asChild variant="ghost" size="sm" className="mb-2 -ml-2">
|
||||
<Link to="/about">
|
||||
<ArrowLeft className="h-3.5 w-3.5" />
|
||||
About
|
||||
</Link>
|
||||
</Button>
|
||||
<h1 className="text-2xl font-bold tracking-tight">Release Notes</h1>
|
||||
<p className="text-sm text-muted-foreground mt-0.5">
|
||||
{data?.version ? `Current version v${data.version}` : 'Full project changelog'}
|
||||
{data?.updated_at ? ` · Updated ${formatDateTime(data.updated_at)}` : ''}
|
||||
</p>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" onClick={load} disabled={loading}>
|
||||
<RefreshCw className={cn('h-3.5 w-3.5 mr-1.5', loading && 'animate-spin')} />
|
||||
Refresh
|
||||
<Button asChild variant="ghost" size="sm" className="-ml-2">
|
||||
<Link to="/about">
|
||||
<ArrowLeft className="h-3.5 w-3.5" />
|
||||
About
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<PageHeader
|
||||
eyebrow="Product history"
|
||||
title="Release Notes"
|
||||
description={(
|
||||
<>
|
||||
{data?.version ? `Current version v${data.version}` : 'Full project changelog'}
|
||||
{data?.updated_at ? ` · Updated ${formatDateTime(data.updated_at)}` : ''}
|
||||
</>
|
||||
)}
|
||||
glyph="analytics"
|
||||
actions={(
|
||||
<Button variant="outline" size="sm" onClick={load} disabled={loading}>
|
||||
<RefreshCw className={cn('h-3.5 w-3.5 mr-1.5', loading && 'animate-spin')} />
|
||||
Refresh
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="table-surface">
|
||||
{loading ? (
|
||||
|
|
@ -141,14 +147,17 @@ export default function ReleaseNotesPage() {
|
|||
<div className="h-3 w-3/4 rounded bg-muted" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="p-6">
|
||||
<p className="text-sm font-medium text-destructive">Unable to load release notes.</p>
|
||||
<p className="text-sm text-muted-foreground mt-1">{error}</p>
|
||||
</div>
|
||||
<EmptyState
|
||||
title="Unable to load release notes"
|
||||
description={error}
|
||||
className="border-0 shadow-none"
|
||||
/>
|
||||
) : !history.trim() ? (
|
||||
<div className="p-6">
|
||||
<p className="text-sm text-muted-foreground">No release notes are available.</p>
|
||||
</div>
|
||||
<EmptyState
|
||||
title="No release notes are available"
|
||||
description="Check back after the next release."
|
||||
className="border-0 shadow-none"
|
||||
/>
|
||||
) : (
|
||||
<div className="p-6">
|
||||
{history.split('\n').map((line, index) => (
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 68 KiB |
Loading…
Reference in New Issue