Skip to content

Commit bf6de1c

Browse files
committed
Apply best practices
1 parent 0f11f41 commit bf6de1c

File tree

9 files changed

+28
-50
lines changed

9 files changed

+28
-50
lines changed

src/components/AdminAlbum/AdminAlbumClient.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ export default function AdminAlbumClient(
3131
const [currentIndex, setCurrentIndex] = useState<number>(-1)
3232
const [selectedIndices, setSelectedIndices] = useState<Set<number>>(new Set())
3333
const [searchQuery, setSearchQuery] = useState<string>('')
34-
const [searchResults, setSearchResults] = useState<SearchResult[]>([])
3534
const [isSearching, setIsSearching] = useState(false)
3635
const {
3736
EditCountPill,
@@ -198,19 +197,14 @@ export default function AdminAlbumClient(
198197
const data: { results: SearchResult[] } = await response.json()
199198

200199
if (data.results && data.results.length > 0) {
201-
setSearchResults(data.results)
202200
// Load the first result automatically
203201
const firstResult = data.results[0]
204202
setCurrentGallery(firstResult.gallery)
205203

206204
const selectedAlbum = galleryAlbum[firstResult.gallery].albums.find(a => a.name === firstResult.album)
207205
if (selectedAlbum) {
208206
setAlbum(selectedAlbum)
209-
// Wait for the album to load, then select the item
210-
setTimeout(async () => {
211-
await mutate()
212-
setCurrentIndex(firstResult.index)
213-
}, 100)
207+
setCurrentIndex(firstResult.index)
214208
}
215209
} else {
216210
alert('No matching files found')

src/components/AdminAlbum/Fields.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ export default function Fields(
319319
}}
320320
disabled={!editedItem?.ref?.source || !editedItem?.ref?.name}
321321
title="Copy reference URL to clipboard"
322+
aria-label="Copy reference URL to clipboard"
322323
sx={{ minWidth: 'auto', px: 1 }}
323324
>
324325
📋

src/components/AdminAlbum/useGeoCopy.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export function useGeoCopy(editedItem: RawXmlItem | null) {
3030
onClick={copyGeoCoordinates}
3131
disabled={disabled}
3232
title={title}
33+
aria-label={title}
3334
sx={{ minWidth: 'auto', px: 1 }}
3435
>
3536
📋

src/components/SplitViewer/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function SplitViewer({
128128
coordinates: clearCoordinates,
129129
} as Item)
130130
}
131-
}, [isClearing, clearCoordinates])
131+
}, [isClearing, clearCoordinates, dynamicCentroid])
132132

133133
// Update locked centroid during normal navigation only
134134
useEffect(() => {

src/hooks/useMemory.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const useMemory = (
6161
{Array.isArray(details.filename) ? details.filename.join(', ') : String(details.filename)}
6262
</h5>
6363
{details.reference && details.reference.length >= 2 && (
64-
<Link href={details.reference[0]} target='_blank'>
64+
<Link href={details.reference[0]} target='_blank' rel="noopener noreferrer">
6565
{decodeURI(details.reference[1]).replaceAll('_', ' ')}
6666
</Link>
6767
)}

src/hooks/useSearch.tsx

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,10 @@ export default function useSearch<ItemType extends ServerSideItem>({
6363
setVisibleCount((prev) => (prev === count ? prev : count))
6464
}, [])
6565

66-
// Adjust visibleCount when filtered items change during render
67-
// This avoids a double render caused by useEffect synchronization
68-
const [prevFiltered, setPrevFiltered] = useState(filtered)
69-
if (filtered !== prevFiltered) {
70-
setPrevFiltered(filtered)
71-
setVisibleCount(filtered.length)
72-
}
66+
// Sync visibleCount when filtered items change (avoids state-update-during-render)
67+
useEffect(() => {
68+
setVisibleCount((prev) => (prev === filtered.length ? prev : filtered.length))
69+
}, [filtered.length])
7370

7471
const handleSubmit = useCallback((event: React.FormEvent<HTMLFormElement>) => {
7572
event.preventDefault()
@@ -84,19 +81,14 @@ export default function useSearch<ItemType extends ServerSideItem>({
8481
const currentIndex = refImageGallery?.current?.getCurrentIndex?.() ?? 0
8582
const itemsToUse = displayedItems || filtered
8683
const currentItem = itemsToUse[currentIndex]
87-
if (!currentItem) return
88-
89-
// Use filename as unique identifier (works across all albums)
90-
const identifier = Array.isArray((currentItem as any).filename)
91-
? (currentItem as any).filename[0]
92-
: (currentItem as any).filename
93-
if (!identifier) return
94-
95-
// Extract coordinates from current item
96-
const coordinates = (currentItem as any).coordinates as [number, number] | null
97-
98-
// Set selectedId with clear flag for immediate processing
99-
if (selectById) {
84+
const identifier = currentItem
85+
? (Array.isArray((currentItem as any).filename)
86+
? (currentItem as any).filename[0]
87+
: (currentItem as any).filename)
88+
: null
89+
const coordinates = (currentItem as any)?.coordinates as [number, number] | null
90+
91+
if (selectById && identifier) {
10092
selectById(identifier, true)
10193
}
10294

@@ -111,7 +103,7 @@ export default function useSearch<ItemType extends ServerSideItem>({
111103
}
112104

113105
// Update URL to reflect the selection (use filename for global uniqueness)
114-
router.replace(`${pathname}?select=${identifier}`)
106+
router.replace(identifier ? `${pathname}?select=${identifier}` : pathname)
115107
}, [refImageGallery, displayedItems, filtered, selectById, mapFilterEnabled, onClearMapFilter, router, pathname])
116108

117109
const { BookmarkButton } = useBookmark({

src/lib/paths.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
import type { Gallery, Item, XmlItem } from '../types/common'
22

3-
const type = (filepath: string): string => {
4-
const lastDot = filepath.lastIndexOf('.')
5-
if (lastDot === 0) {
6-
return filepath.substring(1)
7-
}
8-
if (lastDot === -1) {
9-
return ''
10-
}
11-
return filepath.substring(lastDot + 1)
12-
}
13-
143
const filenameAsJpg = (filename: Item['filename'][0]) => {
15-
const currentExt = type(filename)
4+
const lastDot = filename.lastIndexOf('.')
5+
if (lastDot === -1) return `${filename}.jpg`
6+
const base = filename.slice(0, lastDot)
7+
const currentExt = filename.slice(lastDot + 1)
168
const futureExt = (currentExt.toLowerCase() === 'jpg' || currentExt.toLowerCase() === 'jpeg') ? currentExt : 'jpg'
17-
const imageFilename = filename.replace(currentExt, futureExt)
18-
return imageFilename
9+
return `${base}.${futureExt}`
1910
}
2011

2112
/**
@@ -27,7 +18,7 @@ const filenameAsJpg = (filename: Item['filename'][0]) => {
2718
*/
2819
export const rasterPath = (filename: XmlItem['filename'], gallery: Gallery, rasterType: 'photo' | 'thumb') => {
2920
const imageFilename = filenameAsJpg(Array.isArray(filename) ? filename[0] : filename)
30-
const year = imageFilename.indexOf('-') >= 0 && imageFilename.split('-')[0]
21+
const year = imageFilename.indexOf('-') >= 0 ? imageFilename.split('-')[0] : ''
3122

3223
return `/galleries/${gallery}/media/${rasterType}s/${year}/${imageFilename}`
3324
}
@@ -52,7 +43,7 @@ export const getVideoPaths = (filename: XmlItem['filename'], gallery: Gallery) =
5243
const filenames = Array.isArray(filename) ? filename : [filename]
5344

5445
return filenames.map(fn => {
55-
const year = fn.indexOf('-') >= 0 && fn.split('-')[0]
46+
const year = fn.indexOf('-') >= 0 ? fn.split('-')[0] : ''
5647
return `/galleries/${gallery}/media/videos/${year}/${fn}`
5748
})
5849
}

src/lib/xml.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ async function readAlbum(gallery: NonNullable<AlbumMeta['gallery']>, album: stri
1616
async function readAlbum(gallery: NonNullable<AlbumMeta['gallery']>, album: string, options: ParserOptions): Promise<RawXmlAlbum>
1717
async function readAlbum(gallery: NonNullable<AlbumMeta['gallery']>, album: string, options?: ParserOptions): Promise<XmlAlbum | RawXmlAlbum> {
1818
const fileBuffer = await fs.readFile(`public/galleries/${gallery}/${album}.xml`)
19-
const selectedParser = options ? new xml2js.Parser(options) : parser
19+
const selectedParser = options === rawParseOptions ? rawParser : (options ? new xml2js.Parser(options) : parser)
2020
return selectedParser.parseStringPromise(fileBuffer)
2121
}
2222

src/utils/reference.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ItemReferenceSource, XmlItem } from '../types/common'
22

3-
export function buildReferenceUrl(source: ItemReferenceSource, name: string): string | null {
3+
export function buildReferenceUrl(source: ItemReferenceSource, name: string): string {
44
const baseUrls: Record<ItemReferenceSource, string> = {
55
facebook: 'https://www.facebook.com/',
66
google: 'https://www.google.com/search?q=',
@@ -9,7 +9,7 @@ export function buildReferenceUrl(source: ItemReferenceSource, name: string): st
99
youtube: 'https://www.youtube.com/watch?v=',
1010
}
1111

12-
return baseUrls[source] + name
12+
return baseUrls[source] + encodeURIComponent(name)
1313
}
1414

1515
export function transformReference(ref: XmlItem['ref']): [string, string] | null {
@@ -18,7 +18,6 @@ export function transformReference(ref: XmlItem['ref']): [string, string] | null
1818
}
1919
if ('name' in ref && 'source' in ref) {
2020
const url = buildReferenceUrl(ref.source, ref.name)
21-
if (!url) return null
2221
return [url, ref.name]
2322
}
2423
return null

0 commit comments

Comments
 (0)