Spot form: enforce required spot type, guard submit during Quick Snap upload, drop debug log (1.2.26)

CreateSpotPage:
- Spot type is marked required (*) and drives the quality meter, but submit
  never validated it — a spot could be published with no type. Now validated
  with a clear toast, matching the title/coordinate checks.
- Submit was allowed while the Quick Snap photo was still uploading in the
  background, which would publish the spot WITHOUT the photo the user just
  took. Submit is now blocked (with an "Uploading photo…" button state and a
  reassuring toast) until the upload settles.
- Removed a leftover console.log of the full event payload.

EditSpotPage:
- Same missing spot-type validation (also marked * in its UI) — added the
  same guard for consistency.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-09-07 21:51:59 +07:00
parent 8affd02bcf
commit 2b50f2b496
3 changed files with 35 additions and 8 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "skate-spots", "name": "skate-spots",
"private": true, "private": true,
"version": "1.2.25", "version": "1.2.26",
"type": "module", "type": "module",
"homepage": "https://skate-spots.com", "homepage": "https://skate-spots.com",
"scripts": { "scripts": {

View file

@ -239,6 +239,25 @@ export default function CreateSpotPage() {
return; return;
} }
if (!selectedCategory) {
toast({
title: 'Spot type required',
description: 'Please pick a spot type so skaters know what they’re rolling up to.',
variant: 'destructive',
});
return;
}
// Don't publish while the Quick Snap photo is still uploading — otherwise the
// spot would go out without the photo the user just took.
if (isUploadingQuickPhoto) {
toast({
title: 'Hang tight',
description: 'Your photo is still uploading. It’ll be attached in a second.',
});
return;
}
try { try {
// Generate geohash from coordinates (7 chars = ~153m precision) // Generate geohash from coordinates (7 chars = ~153m precision)
const geohash = ngeohash.encode(lat, lng, 7); const geohash = ngeohash.encode(lat, lng, 7);
@ -322,12 +341,6 @@ export default function CreateSpotPage() {
// Add alt tag for NIP-31 (human-readable description) // Add alt tag for NIP-31 (human-readable description)
eventTags.push(['alt', `Skate spot: ${title.trim()}`]); eventTags.push(['alt', `Skate spot: ${title.trim()}`]);
console.log('Publishing spot event:', {
kind: SKATE_SPOT_KIND,
tags: eventTags,
content: description.trim()
});
await createEvent({ await createEvent({
kind: SKATE_SPOT_KIND, kind: SKATE_SPOT_KIND,
content: description.trim(), content: description.trim(),
@ -696,13 +709,18 @@ export default function CreateSpotPage() {
<Button <Button
type="submit" type="submit"
className="w-full" className="w-full"
disabled={isPublishing || isUploading} disabled={isPublishing || isUploading || isUploadingQuickPhoto}
> >
{isPublishing ? ( {isPublishing ? (
<> <>
<Loader2 className="h-4 w-4 mr-2 animate-spin" /> <Loader2 className="h-4 w-4 mr-2 animate-spin" />
{t('createSpot.publishing')} {t('createSpot.publishing')}
</> </>
) : isUploadingQuickPhoto ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Uploading photo…
</>
) : ( ) : (
<> <>
<MapPin className="h-4 w-4 mr-2" /> <MapPin className="h-4 w-4 mr-2" />

View file

@ -215,6 +215,15 @@ export default function EditSpotPage() {
return; return;
} }
if (!selectedCategory) {
toast({
title: 'Spot type required',
description: 'Please pick a spot type so skaters know what they’re rolling up to.',
variant: 'destructive',
});
return;
}
try { try {
// Generate geohash from coordinates (7 chars = ~153m precision) // Generate geohash from coordinates (7 chars = ~153m precision)
const geohash = ngeohash.encode(lat, lng, 7); const geohash = ngeohash.encode(lat, lng, 7);