Skip to content

Remove public upload links, sort photos by capture time, cut stale marketing - #36

Merged
TomProkop merged 2 commits into
mainfrom
users/tomas.prokop/turbo-potato
Jul 24, 2026
Merged

TomProkop merged 2 commits into
mainfrom
users/tomas.prokop/turbo-potato

Conversation

@TomProkop

Copy link
Copy Markdown
Member

Why

Three follow-up issues after the map/media polish PR (#35) merged:

  1. Security/abuse: three public buttons still linked to /photos, the unauthenticated crew upload page (shared token embedded server-side, no real auth) — FollowSection's "Share a photo from your phone" button, and PhotoStreamTile's "View all" and "Share a photo" links.
  2. Wrong photo order: photos/videos were displayed in upload order (Table Storage rowKey/id), not capture order. Crews upload with a lag, so followers weren't seeing photos in the trip's actual timeline.
  3. Stale content: pre-trip recruiting copy ("Join the Rallye" CTA, "The Idea" pitch, "What to bring") no longer makes sense with the trip almost over, and it was pushing the live map/photo stream (what people actually check multiple times a day) further down the page.

What changed

  • Removed all three /photos links. PhotoStreamTile's "View all" now points to #follow (the fuller in-page grid) instead of leaking the crew upload page; the bottom "Share a photo" link is gone with no replacement. /photos itself and its rewrite rule are untouched — crews still have their direct link.
  • useMediaPosts now sorts by capturedAt descending once at the source; MediaMarkers' sortNewestFirst() and mediaClusterRenderer's pickThumbnailPost() updated to match (previously sorted by id/rowKey, i.e. upload order). Every post already has a capturedAt value, so this reorders everything already uploaded — no backend change or backfill needed.
  • Deleted ConceptSection.tsx and SignupSection.tsx entirely, dropped Hero's "Join the Rallye" CTA, removed #concept/#join from Nav.tsx and Footer.tsx. Stripped the "sign up" copy/link from CrewsSection (kept the crew list itself). Reordered App.tsx: Hero → RouteSection (map) → FollowSection (stream) → Itinerary → Crews → LastYear.

Verification

  • npm run build and npm run lint clean.
  • Playwright pass (desktop + mobile 390×844) with mocked /api/media: confirmed nav/hero have no dangling #join/#concept links, no remaining /photos hrefs anywhere in the rendered DOM, "View all" correctly points to #follow, and the photo grid renders newest-captured-first (verified against a fixture where capture order differs from upload order).

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

…rketing

Three fixes:

1. Remove the last 3 public buttons that linked to /photos (the
   unauthenticated crew upload page): FollowSection's "Share a photo"
   button, and PhotoStreamTile's "View all" (now points to #follow
   instead) and "Share a photo" link. /photos itself is untouched -
   crews still reach it via their direct link.

2. Sort photos/videos by capturedAt (when taken) instead of upload
   order everywhere: useMediaPosts sorts once at the source,
   MediaMarkers' sortNewestFirst() and mediaClusterRenderer's
   pickThumbnailPost() updated to match. Crews upload with a lag;
   followers should see trip-timeline order. Every post already has a
   capturedAt value, so this reorders all previously-uploaded photos
   too with no backend change or migration.

3. Remove stale pre-trip recruiting content now that the trip is
   almost over: delete ConceptSection and SignupSection entirely, drop
   Hero's "Join the Rallye" CTA, remove #concept/#join from Nav and
   Footer. Strip the "sign up" copy/link from CrewsSection, keep the
   crew list. Reorder App.tsx so the live map and photo stream lead
   (Hero -> Route -> Follow -> Itinerary -> Crews -> Last Year).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the public-facing rallye site to remove links to the unauthenticated crew upload page, reorder media consistently by capture time (trip timeline), and remove/reorder “join/concept” marketing sections to prioritize live-follow content.

Changes:

  • Removed remaining public UI links to /photos (upload page), replacing “View all” with an in-page #follow anchor.
  • Changed media ordering logic to sort newest-captured-first at the useMediaPosts source and aligned map marker/cluster ordering accordingly.
  • Deleted ConceptSection/SignupSection and simplified navigation/hero/footer to remove #join/#concept, plus reordered the main page sections.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/sections/SignupSection.tsx Deleted legacy signup CTA section.
src/sections/ConceptSection.tsx Deleted legacy “The Idea / What to bring” marketing section.
src/sections/Hero.tsx Removed “Join” CTA, kept route CTA styling consistent.
src/components/Nav.tsx Removed join/concept items; updated nav order to include Follow.
src/sections/Footer.tsx Removed join/concept links; added Follow link.
src/sections/CrewsSection.tsx Removed signup prompt copy; updated headings.
src/sections/FollowSection.tsx Removed public “Share a photo” button linking to /photos.
src/App.tsx Reordered sections to surface Route + Follow earlier; removed deleted sections.
src/hooks/useMediaPosts.ts Re-sorted posts by capturedAt descending at the hook source.
src/components/RouteMap/MediaMarkers.tsx Updated map lightbox ordering to match captured-time ordering.
src/components/RouteMap/mediaClusterRenderer.ts Updated cluster thumbnail selection ordering to match captured-time ordering.
src/components/RouteMap/PhotoStreamTile.tsx Repointed “View all” to #follow; removed “Share a photo” link.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +25
/**
* Sorts posts newest-*captured*-first (not newest-uploaded). Crews upload
* with a time lag, but followers should see photos in the trip's actual
* timeline order regardless of when they landed in Blob/Table Storage.
* `capturedAt` is an ISO date string, so lexicographic comparison sorts
* correctly without parsing.
*/
function sortByCapturedAtDesc(posts: MediaPost[]): MediaPost[] {
return [...posts].sort((a, b) => (a.capturedAt < b.capturedAt ? 1 : a.capturedAt > b.capturedAt ? -1 : 0));
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa1615: extracted a shared compareCapturedAtDesc() that parses capturedAt via Date.parse (epoch ms) instead of comparing raw strings, with an id tie-breaker for equal/unparseable timestamps.

Comment on lines +14 to +18
* `useMediaPosts` sorts. Crews upload with a time lag, so sorting by
* `capturedAt` (an ISO string, sorts correctly lexicographically) keeps
* lightbox ordering on trip-timeline order everywhere it's opened from. */
function sortNewestFirst(posts: readonly MediaPost[]): MediaPost[] {
return [...posts].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
return [...posts].sort((a, b) => (a.capturedAt < b.capturedAt ? 1 : a.capturedAt > b.capturedAt ? -1 : 0));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa1615: now imports and uses the shared compareCapturedAtDesc() from useMediaPosts.ts instead of the local string-based sort.

Comment on lines 18 to 22
// no photos at all. Pick deterministically (newest *captured* first, by
// `capturedAt` - an ISO string, sorts correctly lexicographically)
// rather than randomly, so the same cluster doesn't flicker between
// different thumbnails on every pan/zoom re-render.
const photos = posts.filter((p) => p.mediaType === 'photo');

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa1615: pickThumbnailPost() now imports and uses the shared compareCapturedAtDesc() instead of comparing capturedAt as raw strings.

Comment on lines +7 to +10
* Compact preview of the live photo stream, shown next to the map so
* visitors don't have to scroll all the way down to `/photos` / the
* `FollowSection` grid to see what's just been uploaded. Shows the most
* recent thumbnails; tapping one opens the same shared `MediaLightbox`
* used everywhere else, seeded with the *full* posts list (not just this
* visitors don't have to scroll all the way down to the `FollowSection`
* grid to see what's just been uploaded. Shows the most recent
* thumbnails; tapping one opens the same shared `MediaLightbox` used

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa1615: reworded the doc comment to describe capture-time ordering instead of the stale "just been uploaded" phrasing.

- Extract shared compareCapturedAtDesc() in useMediaPosts.ts: parses
  capturedAt to epoch ms (Date.parse) instead of comparing raw strings,
  and falls back to an id tie-breaker when timestamps are equal or
  unparseable. Fixes fragile lexicographic comparison flagged across
  three call sites.
- MediaMarkers.tsx and mediaClusterRenderer.ts now import and reuse the
  shared comparator instead of duplicating string-based sort logic.
- PhotoStreamTile.tsx: reworded stale doc comment that referenced
  upload-time ordering ("just been uploaded") to reflect the
  capturedAt-based capture-time ordering shipped in this PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@TomProkop
TomProkop merged commit c7c1327 into main Jul 24, 2026
TomProkop added a commit that referenced this pull request Jul 27, 2026
main had independently added multi-photo browsing/navigation and a
download button to MediaLightbox (#35), plus client-side capturedAt
sorting in useMediaPosts (#36), overlapping with this branch's own
displayUrl-fetching and download-button work.

Resolved by keeping main's posts/initialIndex-based MediaLightbox (portal
rendering, prev/next nav, single download button) and layering this
branch's displayUrl fetch-on-open logic on top, keyed to the currently
navigated post - so browsing between photos in the lightbox still uses
the compressed display copy per-post, not just on initial open.

PhotoStream.tsx: kept main's selectedIndex-based version, re-applied the
12-post preview cap on top.

useMediaPosts.ts: both branches sort by capturedAt (main client-side,
this branch server-side in media.ts) - harmless redundancy, kept both and
corrected a comment that had gone stale.

Verified with npm run build (frontend) and cd api && npm run build - both
clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants