mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
4843ebc937
Picking a search result fills a column on the left of the add-place dialog - pictures and a description, no extra click. Someone who already knows the place ignores it and saves exactly as before. The column stays mounted with an empty state instead of appearing on the first pick, otherwise the dialog jumps sideways mid-typing. Requests are cached in memory and in sessionStorage and aborted when the selection changes, so clicking back and forth between two results does not pay twice. Every thumbnail carries its author, its licence and a link to the file page. That is not decoration - most of these are CC BY-SA, and reusing one without naming the author does not satisfy the licence. The description is shown but never written into the place on its own; a button copies it across, and it is disabled while the user already has a description of their own. Desktop only. The mobile sheet is untouched.
56 lines
1.6 KiB
TypeScript
56 lines
1.6 KiB
TypeScript
export interface PlaceFormData {
|
|
name: string
|
|
description: string
|
|
address: string
|
|
lat: string
|
|
lng: string
|
|
category_id: string
|
|
place_time: string
|
|
end_time: string
|
|
notes: string
|
|
transport_mode: string
|
|
website: string
|
|
// Populated from a maps-search pick (not part of the initial blank form).
|
|
phone?: string
|
|
google_place_id?: string
|
|
google_ftid?: string
|
|
osm_id?: string
|
|
// Hero image picked from the detail column. Optional and absent from
|
|
// DEFAULT_FORM on purpose: the mobile sheet shares this type and never sets
|
|
// it, and places.service already writes image_url through on create/update.
|
|
image_url?: string
|
|
}
|
|
|
|
export function isGoogleMapsUrl(input: string): boolean {
|
|
try {
|
|
const { hostname, pathname } = new URL(input.trim())
|
|
const h = hostname.toLowerCase()
|
|
// maps.app.goo.gl, goo.gl/maps
|
|
if (h === 'maps.app.goo.gl') return true
|
|
if (h === 'goo.gl' && pathname.startsWith('/maps')) return true
|
|
// maps.google.* (e.g. maps.google.com, maps.google.co.uk)
|
|
// Must be maps.google.<tld> or maps.google.<sld>.<tld> — reject maps.google.evil.com
|
|
if (/^maps\.google\.[a-z]{2,3}(\.[a-z]{2})?$/.test(h)) return true
|
|
// google.*/maps (e.g. google.com/maps, www.google.co.uk/maps)
|
|
const bare = h.startsWith('www.') ? h.slice(4) : h
|
|
if (/^google\.[a-z]{2,3}(\.[a-z]{2})?$/.test(bare) && pathname.startsWith('/maps')) return true
|
|
return false
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export const DEFAULT_FORM: PlaceFormData = {
|
|
name: '',
|
|
description: '',
|
|
address: '',
|
|
lat: '',
|
|
lng: '',
|
|
category_id: '',
|
|
place_time: '',
|
|
end_time: '',
|
|
notes: '',
|
|
transport_mode: 'walking',
|
|
website: '',
|
|
}
|