diff --git a/AGENTS.md b/AGENTS.md index 90cbc5e..3f6dc41 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1127,6 +1127,13 @@ session with **no other memory of this project**. So: stall signing (a miss falls back to the stats' read-time region derivation). ⚠️ A geohash-prefix nearby query is still impossible — relays only exact-match `#g` — so the 2000-spot cache remains the mechanism. + **Required set (2026-10-07):** pin + name + description + **address** + + **access type** + photo. Address and access type were **moved OUT of the + "More details (optional)" collapsible** into the required flow (the collapsible + now holds only Shelter + Tags) — required fields must not be hidden under + "optional". Access keeps its **Public default** (so it is always satisfied; the + `*` marks membership in the required set), and Address has real inline + validation (`createSpot.addressRequired`). - **Map pin rendering (perf, 2026-09-29):** the spot/tour/event/crew marker effect in `SpotMap.tsx` used to `clearLayers()` + rebuild **every** marker whenever the parent handed it fresh arrays, and added each marker with a diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 699918f..1265fa0 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -509,6 +509,7 @@ nav: { photoHint: 'a photo is required to publish', nameRequired: 'Please enter a name for this spot.', descriptionRequired: 'Please describe this spot.', + addressRequired: 'Please add an address or area name.', photoRequired: 'Please add at least one photo.', draftTitle: 'You have an unsaved draft', draftBody: 'Pick up where you left off, or discard it.', diff --git a/src/i18n/es.ts b/src/i18n/es.ts index 327cf80..7dc8a12 100644 --- a/src/i18n/es.ts +++ b/src/i18n/es.ts @@ -509,6 +509,7 @@ nav: { photoHint: 'se requiere una foto para publicar', nameRequired: 'Ponle un nombre a este spot.', descriptionRequired: 'Describe este spot.', + addressRequired: 'Añade una dirección o nombre de zona.', photoRequired: 'Añade al menos una foto.', draftTitle: 'Tienes un borrador sin guardar', draftBody: 'Continúa donde lo dejaste o descártalo.', diff --git a/src/i18n/th/batch5.ts b/src/i18n/th/batch5.ts index 4c5f5d7..76fcd34 100644 --- a/src/i18n/th/batch5.ts +++ b/src/i18n/th/batch5.ts @@ -369,6 +369,7 @@ const thBatch5 = { photoHint: 'ต้องมีรูปจึงจะเผยแพร่ได้', nameRequired: 'กรุณาตั้งชื่อสปอตนี้', descriptionRequired: 'กรุณาอธิบายสปอตนี้', + addressRequired: 'กรุณาเพิ่มที่อยู่หรือชื่อพื้นที่', photoRequired: 'กรุณาเพิ่มรูปอย่างน้อยหนึ่งรูป', draftTitle: 'คุณมีฉบับร่างที่ยังไม่ได้บันทึก', draftBody: 'ทำต่อจากที่ค้างไว้ หรือลบทิ้ง', diff --git a/src/pages/CreateSpotPage.tsx b/src/pages/CreateSpotPage.tsx index c2c0d84..c7346a4 100644 --- a/src/pages/CreateSpotPage.tsx +++ b/src/pages/CreateSpotPage.tsx @@ -45,6 +45,7 @@ import { Link } from 'react-router-dom'; type FieldErrors = { title?: string; description?: string; + address?: string; location?: string; type?: string; photo?: string; @@ -342,6 +343,7 @@ export default function CreateSpotPage() { const nextErrors: FieldErrors = {}; if (!title.trim()) nextErrors.title = t('createSpot.nameRequired'); if (!description.trim()) nextErrors.description = t('createSpot.descriptionRequired'); + if (!location.trim()) nextErrors.address = t('createSpot.addressRequired'); if (!hasCoords) nextErrors.location = t('spotUi.locationRequiredDesc'); if (!selectedCategory) nextErrors.type = t('spotUi.spotTypeRequiredDesc'); if (images.length === 0) nextErrors.photo = t('createSpot.photoRequired'); @@ -613,6 +615,19 @@ export default function CreateSpotPage() { + {/* Address (required) — the human-readable place name. */} +
{errors.address}
} +