Repository navigation
Fix friend place-count bug + Recently Deleted relocation + chunked My Places rendering - #9
Conversation
…y Places
Real bug found & fixed: friends.js used Prisma's bare _count.places to
show 'N places' on friend cards / requests — that count had NO
deletedAt filter, unlike every other places query, so it silently
included soft-deleted places and over-reported a friend's real place
count. Fixed by filtering the relation count (_count.places.where);
verified end-to-end: badge correctly drops 3 -> 2 after a soft-delete
(would have stayed 3 with the bug).
Recently Deleted UX: moved from a section at the very bottom of a
541-card list (had to scroll past everything to reach it) to a
dedicated icon button in the header, right next to Select, with a
badge for pending count. Opens a floating panel (same pattern as the
map's legend card) instead of pushing the list down.
Dynamic (chunked) rendering for My Places: mounting all 541 cards at
once (icons, stars, tag lists, thumbnails, and a sortedPlaces computed
that re-filters/sorts on every GPS update) was the actual render-lag
source. Now only a window of 60 cards is in the DOM, grown by 60 via
an IntersectionObserver sentinel as the user scrolls — verified 60
initial -> 420 after scrolling. Search, header count and category
chips are untouched (always computed over the FULL in-memory array,
never the render window): verified 'All (541)' stays correct and a
search for a place NOT among the initial 60 rendered cards is found
instantly ('Grizzly' -> found, full-dataset Fuse search unaffected).
.pv-count ('541 saved') had no padding/line-height at all — a bare
text pill hugging its own glyphs — stacked 3px below a bold 26px
title. Gave it proper padding (matching .fv-count's convention) and
widened the view-hero-text gap 3px -> 7px so the badge has visible
breathing room under the title.
|
Fixed: cramped header spacing on My Places — the |
Address row is now a button with a subtle copy-icon affordance; tapping copies the exact address text + haptic tap + 'Address copied!' toast (same pattern as copyHandle elsewhere in the app). Verified end-to-end: clipboard contents match the displayed address.
|
Added: tap the address to copy it — the ADDRESS row in the place detail sheet is now tappable (subtle copy icon on the right), copies the exact address text to the clipboard with a haptic tap + 'Address copied!' toast. Verified end-to-end: clipboard content matches the displayed address exactly. |
Converting the address row from <div> to <button class="info-row info-row--copy"> added a scoped 'background: none' reset (meant to kill the browser's default button-face gray). That selector (.info-row.info-row--copy[data-v-hash], 2 classes + 1 attr) had slightly higher specificity than cartoon.scss's 'html[data-skin] .info-row' (1 class + 1 attr + 1 element), so it won and made the Address card fall through to transparent -> the page's cream backdrop instead of staying white like Coordinates/Notes/Added. - Removed the scoped background reset (not needed / was the bug) - cartoon.scss now explicitly owns .info-row--copy's background too, so future scoped tweaks in the component can't out-specify it again Verified: all four info rows report identical backgroundColor: rgb(255,255,255) via computed styles.
|
Fixed: Address card background regression — the copy-to-clipboard change turned the address row into a |
…ader/body Navigation (App.vue) - Switching tabs (click OR swipe) now does a smooth directional slide+fade (18px translateX + opacity, 320ms cubic-bezier) instead of an instant cut. Map (v-show, permanently mounted for MapLibre) and the other 4 views (v-if chain) share the same transition name/ direction so the motion reads as one continuous animation across the mount-vs-show boundary. prefers-reduced-motion gets a fast plain crossfade instead. - Swipe left/right ON the bottom tab bar moves to the next/previous view (in tab order: Map -> Search -> Places -> Friends -> Profile), clamped at the ends; a plain tap still switches tabs normally (the swipe handler only engages past a 12px/horizontal-dominant threshold and swallows the trailing synthetic click so it doesn't also fire a random button's onClick). - Verified with real TouchEvent dispatch: swipe left -> next tab, swipe right -> previous tab, plain tap unaffected; verified the transition is a real animation by sampling computed opacity/ transform mid-flight (0 -> 1, -18px -> 0px), not an instant swap. Place detail redesign (PlaceDetail.vue) - New header hierarchy: name -> 'Added <date>' (small meta line, moved out of the info list) -> rating/cuisine -> tags (moved up from the bottom of the sheet) -> friend-matches. One cohesive header instead of scattered metadata. - Address + Coordinates merged into a single rounded pill: address row (tap to copy, unchanged) on top, a collapsed 'Coordinates' toggle below that expands to reveal the lat/lng plus its own copy button. - Notes redone as a bigger, distinct card (soft yellow tint, bigger icon badge, 15.5px/1.55 line-height text) instead of a cramped generic info-row. - Fixed two real bugs found before shipping: the new address/coords buttons had no background set, so the browser's default button-face gray (rgb(239,239,239)) covered the white card underneath; and no font-family reset, risking a system-font fallback instead of the app's webfont. Both fixed with explicit background:transparent + font:inherit on the button elements (verified via computed styles, not just a screenshot, after the earlier background-specificity incident).
|
Added: smooth tab transitions + navbar swipe, and a full place-detail header/body redesign Navigation
Place detail redesign
|
…nline toggle Spacing bug: removing the old .info-sections wrapper in the earlier header redesign dropped its 22px side padding, leaving .addr-card and .notes-card bleeding edge-to-edge while quick-actions/tags kept their own self-padding — the two cards visibly touched the sheet border. Fixed by giving both their own margin: 0 22px 12px (verified via bounding boxes: both now x=22 width=346, matching quick-actions' content inset exactly). Notes card also got more generous padding (16px 18px -> 18px 20px). Coordinates: replaced the accordion (tap -> chevron rotates -> a new row expands below with the value+copy button, changing the card's height) with a single-line inline toggle — tapping the row REPLACES the 'Coordinates' label in place with the value + a Copy button, same row, same height (verified: 58px before and after). Tapping again (anywhere but Copy) reverts to the label. The outer toggle is now a div[role=button] (keyboard accessible: Enter/Space) instead of a <button>, since a real Copy <button> now lives inside it and a button cannot legally nest inside another button. Removed the now-dead .coords-panel/.coords-expand-* CSS. Verified end-to-end: clipboard content matches the displayed value.
|
Fixed: card margins + coordinates redesigned as a single-line inline toggle SpacingThe earlier header redesign accidentally dropped the wrapper that gave the address/coordinates card and the notes card their side margins — both were bleeding edge-to-edge while the buttons/tags above kept theirs. Fixed: both now sit at the same 22px inset as everything else (verified via bounding boxes). Notes card also got more generous internal padding. Coordinates — much better UX nowReplaced the old accordion (tap → chevron rotates → a new row expands below, card grows taller) with a single-line inline toggle: tapping the row now replaces the 'Coordinates' label in place with the value + a Copy button — same row, same height (verified: 58px before and after, no layout jump). Tap again to revert to the label. Verified end-to-end: margins match exactly, row height constant through the toggle, clipboard content matches the displayed value. |
Content: - New hook/tagline, badges, a 'Why Pinna' section that leads with benefits (delightful, organized, shareable, accessible, open, fast) instead of a dry feature dump - Fixed the Live Demo link: maps.osyna.com doesn't even resolve anymore (DNS dead) — the real live app is maps.osyna.sh - Fixed the demo login: test@test.com was wiped in the Feb incident and never recreated, so the README was advertising a broken credential to every first-time visitor. Recreated it as a public shared demo account with a curated dataset (24 real-world places across 15+ cities, 2 demo friends, a custom list, favorites) — same account doubles as the source for every screenshot below - New hero: a 10s, 2.5MB optimized GIF (ffmpeg two-pass palette, recorded via Playwright) showing the swipe-driven tab transitions across all 5 identity colors and the inline coordinates-copy interaction — sells the motion work that static PNGs can't - All 7 static screenshots re-captured against the CURRENT UI (per- tab hero colors, icon+color markers/legend, redesigned place detail header/notes/coordinates) — the previous images were from before most of this session's work and no longer represented the app - Reorganized screenshot gallery, tech stack (Frontend/Backend/Infra columns), streamlined Docker one-liner framing, Contributing + star-the-repo close
|
README rewrite + all-new screenshots — ready to actually sell the app Found and fixed two things that were quietly sabotaging every first impression:
What's new
Verified: every local image path exists, every shields.io badge resolves, live login + domain both return 200. |
1 · Real bug fixed: inflated friend place counts
friends.jsused Prisma's bare_count.placesfor the 'N places' badge on friend cards and incoming/sent requests — that count had nodeletedAtfilter, unlike every other places query in the app, so it silently included soft-deleted places. Fixed with a filtered relation count. Verified end-to-end: badge correctly drops 3 → 2 immediately after a soft-delete (stayed at 3 with the bug).2 · Recently Deleted → icon button next to Select
Was a section at the very bottom of a (now) 541-card list — unreachable without scrolling past everything. Moved to a dedicated trash-icon button in the header, right beside Select, with a pending-count badge. Opens a floating panel near the top (same pattern as the map's Pin-types legend) instead of pushing the list down.
3 · My Places: dynamic (chunked) rendering — the actual lag source
Confirmed 541
.pv-cardelements were mounting in the DOM at once, andsortedPlacesre-filters/re-sorts on every GPS update (continuouswatchPositionsince the locate work). That's what caused visible lag, not the data size itself (541 places is ~250 KB, no network problem).Now only a 60-card window renders, grown by 60 via an
IntersectionObserversentinel as the user scrolls — verified: 60 initial → 420 after scrolling, silent and instant (pure client-side slicing, no network wait).Search stays instant and full-dataset, exactly as requested: Fuse indexes the complete in-memory
store.placesregardless of the render window. Verified by searching for a place confirmed not among the initial 60 rendered cards ('Grizzly') — found instantly. Header count ('541 saved') and category chip counts ('All (541)', 'Restaurant (327)'...) are also untouched — they read the full array, never the DOM window.