@@ -1645,6 +1645,16 @@ export default function MapView({
16451645 ids : string [ ] ;
16461646 overlayTypeKey : string | null ;
16471647 } | null > ( null ) ;
1648+ /** 一覧から詳細へ進んだときの戻り先。詳細を閉じると一覧に戻す ——
1649+ * 重なったピンは地図から開き直せないので、閉じたら選ぶところからやり直しになる */
1650+ const [ stackReturn , setStackReturn ] = useState < {
1651+ ids : string [ ] ;
1652+ overlayTypeKey : string | null ;
1653+ } | null > ( null ) ;
1654+ /** 「この地点のスポット」に出す簡単な住所。座標をキーに覚えておき、
1655+ * 同じ地点を開き直したときにNominatimへ問い合わせ直さない(1秒1回の利用条件があるため) */
1656+ const [ stackAddress , setStackAddress ] = useState < string | null > ( null ) ;
1657+ const stackAddressCacheRef = useRef < Map < string , string > > ( new Map ( ) ) ;
16481658 /** いま地図に出しているスポット(絞り込み後)。ピンのタップ処理は地図の
16491659 * レイヤー生成時に一度だけ束縛されるので、最新の一覧はrefで参照する */
16501660 const displayedSpotsRef = useRef < Spot [ ] > ( [ ] ) ;
@@ -3482,6 +3492,38 @@ export default function MapView({
34823492 ? spotTypes . find ( ( t ) => t . key === returnTypeKey ) ?? null
34833493 : null ;
34843494
3495+ // 「この地点のスポット」を開いたら、その座標の簡単な住所を1回だけ引く。
3496+ // **一覧の1件目の座標**で引く(同じ地点に積まれているのでどれでも同じ)。
3497+ // 失敗しても黙って出さない —— 住所は補助の情報で、無くても一覧は読める
3498+ useEffect ( ( ) => {
3499+ if ( ! stack ) {
3500+ setStackAddress ( null ) ;
3501+ return ;
3502+ }
3503+ const spot = ( stack . overlayTypeKey ? overlaySpotById : spotById ) . get ( stack . ids [ 0 ] ) ;
3504+ if ( ! spot ) return ;
3505+ const key = `${ spot . lat . toFixed ( 6 ) } ,${ spot . lng . toFixed ( 6 ) } ` ;
3506+ const cached = stackAddressCacheRef . current . get ( key ) ;
3507+ if ( cached !== undefined ) {
3508+ setStackAddress ( cached ) ;
3509+ return ;
3510+ }
3511+ let alive = true ;
3512+ api . geocode
3513+ . reverse ( spot . lat , spot . lng , regionScope ?? DEFAULT_REGION_SCOPE )
3514+ . then ( ( { data } ) => {
3515+ const address = data ?. address ?? null ;
3516+ if ( address ) stackAddressCacheRef . current . set ( key , address ) ;
3517+ if ( alive ) setStackAddress ( address ) ;
3518+ } )
3519+ . catch ( ( ) => {
3520+ // 通信に失敗しても一覧は読めるので黙って住所だけ出さない
3521+ } ) ;
3522+ return ( ) => {
3523+ alive = false ;
3524+ } ;
3525+ } , [ stack , spotById , overlaySpotById , regionScope ] ) ;
3526+
34853527 return (
34863528 < div
34873529 className = { `relative ${
@@ -4527,7 +4569,14 @@ export default function MapView({
45274569 readOnly
45284570 allowVisitRecording
45294571 allowPlanList
4530- onClose = { ( ) => setOverlayDetailSpotId ( null ) }
4572+ onClose = { ( ) => {
4573+ setOverlayDetailSpotId ( null ) ;
4574+ // 一覧から開いていたら戻す
4575+ if ( stackReturn ) {
4576+ setStack ( stackReturn ) ;
4577+ setStackReturn ( null ) ;
4578+ }
4579+ } }
45314580 onVisitChange = { loadVisits }
45324581 // 重ね表示スポットを現在の種別のリストへ追加したら、経路表示中のリストの
45334582 // 線にも反映されるようリスト一覧を取り直す
@@ -4558,7 +4607,10 @@ export default function MapView({
45584607 return (
45594608 < div
45604609 className = "fixed inset-0 z-50 flex items-end justify-center bg-black/40 p-4 sm:items-center"
4561- onClick = { ( ) => setStack ( null ) }
4610+ onClick = { ( ) => {
4611+ setStack ( null ) ;
4612+ setStackReturn ( null ) ;
4613+ } }
45624614 >
45634615 { /* 横幅は一覧に必要な分だけ。件数が多いと縦に伸びるので、画面の高さいっぱいまで
45644616 使い、はみ出す分だけ一覧側をスクロールさせる */ }
@@ -4567,14 +4619,24 @@ export default function MapView({
45674619 onClick = { ( e ) => e . stopPropagation ( ) }
45684620 >
45694621 < div className = "flex shrink-0 items-center justify-between border-b px-4 py-3" >
4570- < h2 className = "text-sm font-semibold" >
4571- この地点のスポット({ stack . ids . length } 件)
4572- </ h2 >
4622+ < div className = "min-w-0" >
4623+ < h2 className = "text-sm font-semibold" >
4624+ この地点のスポット({ stack . ids . length } 件)
4625+ </ h2 >
4626+ { /* 簡単な住所。同じ地点に積まれているので1つだけ出す
4627+ (引けなかったときは行ごと出さない) */ }
4628+ { stackAddress && (
4629+ < p className = "truncate text-xs text-slate-500" > { stackAddress } </ p >
4630+ ) }
4631+ </ div >
45734632 < button
45744633 type = "button"
4575- className = "text-slate-400 hover:text-slate-600"
4634+ className = "shrink-0 text-slate-400 hover:text-slate-600"
45764635 aria-label = "閉じる"
4577- onClick = { ( ) => setStack ( null ) }
4636+ onClick = { ( ) => {
4637+ setStack ( null ) ;
4638+ setStackReturn ( null ) ;
4639+ } }
45784640 >
45794641 ✕
45804642 </ button >
@@ -4589,6 +4651,8 @@ export default function MapView({
45894651 type = "button"
45904652 className = "flex w-full items-center gap-2 px-4 py-3 text-left hover:bg-slate-50"
45914653 onClick = { ( ) => {
4654+ // 詳細を閉じたらこの一覧へ戻す(地図からは開き直せない)
4655+ setStackReturn ( stack ) ;
45924656 setStack ( null ) ;
45934657 if ( overlayTypeKey ) openOverlaySpot ( id ) ;
45944658 else handleSpotSelect ( id ) ;
@@ -4635,7 +4699,14 @@ export default function MapView({
46354699 < SpotDetailModal
46364700 spotId = { detailSpotId }
46374701 spots = { spots }
4638- onClose = { ( ) => setDetailSpotId ( null ) }
4702+ onClose = { ( ) => {
4703+ setDetailSpotId ( null ) ;
4704+ // 一覧から開いていたら戻す
4705+ if ( stackReturn ) {
4706+ setStack ( stackReturn ) ;
4707+ setStackReturn ( null ) ;
4708+ }
4709+ } }
46394710 onVisitChange = { loadVisits }
46404711 // 既存の訪問予定リストへの追加をリスト一覧へ反映する(経路表示中の
46414712 // リストに追加した場合、地図の紫の経路も引き直される)
0 commit comments