ENH - deep link Local Pages listings

This commit is contained in:
smx.pusha
2026-08-06 14:16:38 +02:00
parent fac418050f
commit ecfc00a758
4 changed files with 24 additions and 3 deletions
+6 -1
View File
@@ -30,6 +30,7 @@ import {
X,
} from 'lucide-vue-next'
import { computed, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import CityMarktSelect from '@/components/citymarkt/CityMarktSelect.vue'
import CityMarktGallery from '@/components/citymarkt/CityMarktGallery.vue'
@@ -58,6 +59,7 @@ type ChatTimelineItem =
| { createdAt: string; isCounter: boolean; key: string; kind: 'offer'; value: MarketplaceOffer }
const phone = usePhoneStore()
const route = useRoute()
const account = useAccountStore()
const marketplace = useMarketplaceStore()
const media = useMediaStore()
@@ -328,7 +330,7 @@ async function selectTab(next: Tab): Promise<void> {
}
}
async function openListing(item: MarketplaceListingSummary): Promise<void> {
async function openListing(item: Pick<MarketplaceListingSummary, 'id'>): Promise<void> {
const response = await marketplace.get(item.id)
if (!response.success || !response.data) {
setFeedback('Apps.citymarkt.errors.listing_not_found')
@@ -565,6 +567,9 @@ async function blockSeller(): Promise<void> {
onMounted(async () => {
await loadFeed()
if (isAuthenticated.value) await marketplace.loadCounts()
if (typeof route.query.listingId === 'string') {
await openListing({ id: route.query.listingId })
}
})
</script>
+9 -1
View File
@@ -185,6 +185,14 @@ function moveGallery(direction: number): void {
galleryIndex.value = (galleryIndex.value + direction + selected.value.images.length) % selected.value.images.length
}
function openCityMarktListing(): void {
if (!selected.value?.citymarkt_listing_id) return
void router.push({
path: '/apps/citymarkt',
query: { listingId: selected.value.citymarkt_listing_id },
})
}
onMounted(() => void loadFeed())
</script>
@@ -231,7 +239,7 @@ onMounted(() => void loadFeed())
<header><button @click="screen = 'main'"><ArrowLeft :size="20" /></button><strong>{{ phone.t('Apps.localPages.post') }}</strong><button v-if="selected.is_owner" class="danger" @click="removePost"><Trash2 :size="18" /></button><button v-else @click="react('save')"><Bookmark :size="18" :fill="selected.is_saved ? 'currentColor' : 'none'" /></button></header>
<div class="pages__detail-scroll">
<div v-if="selected.images.length" class="pages__gallery" :style="{ background: selected.images[galleryIndex]?.gradient }"><button v-if="selected.images.length > 1" @click="moveGallery(-1)"><ChevronLeft /></button><button v-if="selected.images.length > 1" @click="moveGallery(1)"><ChevronRight /></button><span>{{ galleryIndex + 1 }} / {{ selected.images.length }}</span></div>
<article><div class="pages__author"><span>{{ selected.author_name.charAt(0).toUpperCase() }}</span><div><strong>@{{ selected.author_name }}</strong><small>{{ relativeDate(selected.created_at) }}</small></div><i>{{ label('categories', selected.category) }}</i></div><h1>{{ selected.title }}</h1><p>{{ selected.body }}</p><div class="pages__location"><MapPin :size="17" /><div><small>{{ phone.t('Apps.localPages.location') }}</small><strong>{{ selected.district ? phone.t(`Apps.citymarkt.districts.${selected.district}`) : phone.t('Apps.localPages.allLosSantos') }}</strong></div></div><button v-if="selected.source_type === 'citymarkt'" class="pages__market-link" @click="router.push('/apps/citymarkt')"><Store :size="18" /><span><small>{{ phone.t('Apps.localPages.sharedFrom') }}</small><strong>{{ phone.t('Apps.localPages.openCityMarkt') }}</strong></span><b v-if="selected.citymarkt_price">${{ Number(selected.citymarkt_price).toLocaleString() }}</b></button></article>
<article><div class="pages__author"><span>{{ selected.author_name.charAt(0).toUpperCase() }}</span><div><strong>@{{ selected.author_name }}</strong><small>{{ relativeDate(selected.created_at) }}</small></div><i>{{ label('categories', selected.category) }}</i></div><h1>{{ selected.title }}</h1><p>{{ selected.body }}</p><div class="pages__location"><MapPin :size="17" /><div><small>{{ phone.t('Apps.localPages.location') }}</small><strong>{{ selected.district ? phone.t(`Apps.citymarkt.districts.${selected.district}`) : phone.t('Apps.localPages.allLosSantos') }}</strong></div></div><button v-if="selected.source_type === 'citymarkt'" class="pages__market-link" @click="openCityMarktListing"><Store :size="18" /><span><small>{{ phone.t('Apps.localPages.sharedFrom') }}</small><strong>{{ phone.t('Apps.localPages.openCityMarkt') }}</strong></span><b v-if="selected.citymarkt_price">${{ Number(selected.citymarkt_price).toLocaleString() }}</b></button></article>
</div>
<div class="pages__detail-actions"><button :class="{ active: selected.is_liked }" @click="react('like')"><Heart :size="19" :fill="selected.is_liked ? 'currentColor' : 'none'" />{{ selected.like_count }} {{ phone.t('Apps.localPages.likes') }}</button><button @click="react('save')"><Bookmark :size="19" :fill="selected.is_saved ? 'currentColor' : 'none'" />{{ phone.t('Apps.localPages.save') }}</button></div>
</section>
+8
View File
@@ -259,6 +259,14 @@ const marketplaceOffers = [
},
]
const pagesPosts = [
{
id: 'pages-citymarkt-1', account_id: 2, author_name: 'morgan', source_type: 'citymarkt',
citymarkt_listing_id: '81bc9d37-20e1-4d8a-82f8-f4b85f77cf01',
title: 'Sultan RS in excellent condition',
body: 'Clean Sultan RS with fresh service, tidy interior and no known damage. Viewing and test drive available in Vinewood.',
category: 'citymarkt', district: 'vinewood', created_at: '2026-08-06 12:50:00', like_count: 24,
images: [{ media_id: 'capture-car', gradient: 'linear-gradient(145deg, #ff6b6b, #845ec2 52%, #0f2027)', sort_order: 1 }],
},
{
id: 'pages-1', account_id: 2, author_name: 'morgan', source_type: 'personal', citymarkt_listing_id: null,
title: 'Best sunset view above Vinewood', body: 'Take the small trail behind the observatory shortly before sunset. The view across Los Santos is incredible and there is enough space to park two cars.',
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sky Phone</title>
<script type="module" crossorigin src="./assets/sky-index-CAnPmU58.js"></script>
<script type="module" crossorigin src="./assets/sky-index-DaOvmEKc.js"></script>
<link rel="stylesheet" crossorigin href="./assets/sky-index-D9eWeoNZ.css">
</head>
<body>