Skip to content

Commit 8753b6f

Browse files
authored
Merge pull request #416 from besscroft/feat/ui-refactor-impeccable
2 parents 9eb8a2c + 7f7ea00 commit 8753b6f

118 files changed

Lines changed: 4003 additions & 2319 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.impeccable.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Design Context
2+
3+
## Target Audience
4+
Mixed user base: photography enthusiasts showcasing personal work, professional photographers needing portfolio sites for clients, and technical self-hosters who value functionality. The interface must serve all three without feeling too casual or too enterprise.
5+
6+
## Use Cases
7+
- Browse and enjoy a photography gallery (visitors)
8+
- Upload, organize, and manage photos with EXIF/geolocation data (owners)
9+
- Configure storage, auth, and site settings (admin)
10+
11+
## Brand Personality / Tone
12+
Warm and textured — like leafing through a beautifully printed photography book. The interface should feel crafted, tactile, and unhurried. Photos are the hero; the UI is the frame that elevates them without competing. Think gallery exhibition, not tech dashboard.
13+
14+
## Pain Points
15+
All areas need attention: typography, color, spacing/layout, motion/interaction. Full audit requested.

app/(default)/layout.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { fetchAlbumsShow } from '~/server/db/query/albums'
2+
import { fetchConfigsByKeys } from '~/server/db/query/configs'
23
import type { AlbumType } from '~/types'
34
import type { AlbumDataProps } from '~/types/props'
4-
import DockMenu from '~/components/layout/dock-menu'
5+
import TopNav from '~/components/layout/top-nav'
6+
import { PageTransition } from '~/components/layout/page-transition'
57

68
export default async function DefaultLayout({
79
children,
@@ -13,16 +15,26 @@ export default async function DefaultLayout({
1315
return await fetchAlbumsShow()
1416
}
1517

18+
const getTitle = async () => {
19+
'use server'
20+
const configs = await fetchConfigsByKeys(['custom_title'])
21+
return configs?.find((item) => item.config_key === 'custom_title')?.config_value || 'PicImpact'
22+
}
23+
1624
const data: AlbumType[] = await getData()
25+
const title = await getTitle()
1726

1827
const props: AlbumDataProps = {
19-
data: data
28+
data: data,
29+
title: title
2030
}
2131

2232
return (
2333
<>
24-
<DockMenu {...props} />
25-
{children}
34+
<TopNav {...props} />
35+
<main id="main-content" className="pt-14">
36+
<PageTransition>{children}</PageTransition>
37+
</main>
2638
</>
2739
)
2840
}

app/(default)/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { fetchClientImagesListByAlbum, fetchClientImagesPageTotalByAlbum } from
33
import SimpleGallery from '~/components/layout/theme/simple/simple-gallery.tsx'
44
import { fetchConfigsByKeys } from '~/server/db/query/configs'
55
import DefaultGallery from '~/components/layout/theme/default/default-gallery.tsx'
6-
import 'react-photo-album/masonry.css'
76
import type { Config } from '~/types'
87
import PolaroidGallery from '~/components/layout/theme/polaroid/polaroid-gallery.tsx'
98

app/(default)/preview/[...id]/page.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,44 @@ import { fetchImageByIdAndAuth } from '~/server/db/query/images'
22
import type { PreviewImageHandleProps } from '~/types/props'
33
import PreviewImage from '~/components/album/preview-image'
44
import { fetchConfigsByKeys } from '~/server/db/query/configs'
5+
import type { Metadata } from 'next/types'
6+
7+
export async function generateMetadata({ params }: { params: any }): Promise<Metadata> {
8+
const { id } = await params
9+
const imageData = await fetchImageByIdAndAuth(String(id))
10+
11+
if (!imageData) {
12+
return { title: 'Photo not found' }
13+
}
14+
15+
const title = imageData.title || 'Photo'
16+
const description = [
17+
imageData.exif?.make,
18+
imageData.exif?.model,
19+
imageData.exif?.focal_length,
20+
imageData.exif?.f_number ?? null,
21+
imageData.exif?.iso_speed_rating ? `ISO ${imageData.exif.iso_speed_rating}` : null,
22+
].filter(Boolean).join(' · ') || imageData.detail || title
23+
24+
const imageUrl = imageData.preview_url || imageData.url
25+
26+
return {
27+
title,
28+
description,
29+
openGraph: {
30+
title,
31+
description,
32+
type: 'article',
33+
images: imageUrl ? [{ url: imageUrl, width: imageData.width, height: imageData.height, alt: title }] : [],
34+
},
35+
twitter: {
36+
card: 'summary_large_image',
37+
title,
38+
description,
39+
images: imageUrl ? [imageUrl] : [],
40+
},
41+
}
42+
}
543

644
export default async function PreView({params}: { params: any }) {
745
const { id } = await params
@@ -30,4 +68,4 @@ export default async function PreView({params}: { params: any }) {
3068
return (
3169
<PreviewImage {...props} />
3270
)
33-
}
71+
}

app/(theme)/[...album]/layout.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { fetchAlbumsShow } from '~/server/db/query/albums'
2+
import { fetchConfigsByKeys } from '~/server/db/query/configs'
23
import type { AlbumType } from '~/types'
34
import type { AlbumDataProps } from '~/types/props'
4-
import DockMenu from '~/components/layout/dock-menu'
5+
import TopNav from '~/components/layout/top-nav'
56

67
export default async function ThemeAlbumLayout({
78
children,
@@ -15,15 +16,23 @@ export default async function ThemeAlbumLayout({
1516
return await fetchAlbumsShow()
1617
}
1718

19+
const getTitle = async () => {
20+
'use server'
21+
const configs = await fetchConfigsByKeys(['custom_title'])
22+
return configs?.find((item) => item.config_key === 'custom_title')?.config_value || 'PicImpact'
23+
}
24+
1825
const dataList: AlbumType[] = await getData()
26+
const title = await getTitle()
1927
const props: AlbumDataProps = {
20-
data: dataList
28+
data: dataList,
29+
title: title
2130
}
2231

2332
return (
2433
<>
25-
<DockMenu {...props} />
26-
{children}
34+
<TopNav {...props} />
35+
<main className="pt-14">{children}</main>
2736
</>
2837
)
2938
}

app/(theme)/[...album]/page.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ export default async function Page({
4747
configHandle: getConfig
4848
}
4949

50+
if (!data) {
51+
return <DefaultGallery {...props} />
52+
}
53+
5054
return (
5155
<>
52-
{data
53-
&& data.theme === '1' ? <SimpleGallery {...props} />
56+
{data.theme === '1' ? <SimpleGallery {...props} />
5457
: data.theme === '2' ? <PolaroidGallery {...props} />
5558
: <DefaultGallery {...props} />
5659
}

app/(theme)/map/layout.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { fetchAlbumsShow } from '~/server/db/query/albums'
2+
import { fetchConfigsByKeys } from '~/server/db/query/configs'
23
import type { AlbumType } from '~/types'
34
import type { AlbumDataProps } from '~/types/props'
4-
import DockMenu from '~/components/layout/dock-menu'
5+
import TopNav from '~/components/layout/top-nav'
56

67
export default async function MapLayout({
78
children,
@@ -13,16 +14,24 @@ export default async function MapLayout({
1314
return await fetchAlbumsShow()
1415
}
1516

17+
const getTitle = async () => {
18+
'use server'
19+
const configs = await fetchConfigsByKeys(['custom_title'])
20+
return configs?.find((item) => item.config_key === 'custom_title')?.config_value || 'PicImpact'
21+
}
22+
1623
const data: AlbumType[] = await getData()
24+
const title = await getTitle()
1725

1826
const props: AlbumDataProps = {
19-
data: data
27+
data: data,
28+
title: title
2029
}
2130

2231
return (
2332
<>
24-
<DockMenu {...props} />
25-
{children}
33+
<TopNav {...props} />
34+
<main className="pt-14">{children}</main>
2635
</>
2736
)
2837
}

app/@modal/(...)preview/[id]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ export default async function Page({params}: { params: any }) {
77
<PreView params={params} />
88
</Modal>
99
)
10-
}
10+
}

app/admin/about/page.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,23 @@ export default async function About() {
2828
return (
2929
<div
3030
key={item.login}
31-
className="select-none border border-black/[0.2] dark:border-white/[0.2] flex flex-col items-start w-full mx-auto p-4 relative"
31+
className="select-none border border-foreground/20 flex flex-col items-start w-full mx-auto p-4 relative"
3232
>
33-
<Icon className="absolute h-6 w-6 -top-3 -left-3 dark:text-white text-black" />
34-
<Icon className="absolute h-6 w-6 -bottom-3 -left-3 dark:text-white text-black" />
35-
<Icon className="absolute h-6 w-6 -top-3 -right-3 dark:text-white text-black" />
36-
<Icon className="absolute h-6 w-6 -bottom-3 -right-3 dark:text-white text-black" />
33+
<Icon className="absolute h-6 w-6 -top-3 -left-3 text-foreground" />
34+
<Icon className="absolute h-6 w-6 -bottom-3 -left-3 text-foreground" />
35+
<Icon className="absolute h-6 w-6 -top-3 -right-3 text-foreground" />
36+
<Icon className="absolute h-6 w-6 -bottom-3 -right-3 text-foreground" />
3737

3838
<EvervaultCard text={item.avatar_url} />
3939

40-
<h2 className="dark:text-white text-black mt-4 text-lg font-light">
40+
<h2 className="text-foreground mt-4 text-lg font-light">
4141
{item.login}
4242
</h2>
4343
<Link
4444
href={item.html_url}
4545
target="_blank"
4646
>
47-
<p className="select-none text-sm border font-light dark:border-white/[0.2] border-black/[0.2] rounded-full mt-4 text-black dark:text-white px-2 py-0.5">
47+
<p className="select-none text-sm border font-light border-foreground/20 rounded-full mt-4 text-foreground px-2 py-0.5">
4848
Follow
4949
</p>
5050
</Link>

app/admin/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ export default function AdminLayout({
77
children: React.ReactNode;
88
}>) {
99
return (
10-
<SidebarProvider>
10+
<SidebarProvider defaultOpen={false}>
1111
<AppSidebar />
12-
<main className="flex w-full h-full flex-1 flex-col p-4">
12+
<main id="main-content" className="flex w-full h-full flex-1 flex-col p-4">
1313
<SidebarTrigger className="cursor-pointer" />
1414
<div className="w-full h-full p-2">
1515
{children}

0 commit comments

Comments
 (0)