mirror of
https://github.com/openclassify/openclassify.git
synced 2026-04-14 11:12:09 -05:00
Implement oc2 listing improvements
This commit is contained in:
parent
b1293d3960
commit
dbe1dc97ce
@ -59,6 +59,7 @@
|
||||
|
||||
$reportEmail = config('mail.from.address', 'support@example.com');
|
||||
$reportUrl = 'mailto:'.$reportEmail.'?subject='.rawurlencode('Report listing #'.$listing->getKey());
|
||||
$shareUrl = route('listings.show', $listing);
|
||||
|
||||
$overviewItems = collect([
|
||||
['label' => 'Listing ID', 'value' => '#'.$listing->getKey()],
|
||||
@ -108,26 +109,41 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@auth
|
||||
<form method="POST" action="{{ route('favorites.listings.toggle', $listing) }}">
|
||||
@csrf
|
||||
<button
|
||||
type="submit"
|
||||
class="lt-icon-btn {{ $isListingFavorited ? 'is-active' : '' }}"
|
||||
aria-label="{{ $isListingFavorited ? 'Remove from saved listings' : 'Save listing' }}"
|
||||
>
|
||||
<div class="lt-gallery-utility">
|
||||
<button
|
||||
type="button"
|
||||
class="lt-icon-btn"
|
||||
data-listing-share
|
||||
data-share-url="{{ $shareUrl }}"
|
||||
data-share-title="{{ $displayTitle }}"
|
||||
aria-label="Share listing"
|
||||
>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||||
<path d="M15 8a3 3 0 1 0-2.83-4H12a3 3 0 0 0 .17 1L8.91 6.94a3 3 0 0 0-1.91-.69 3 3 0 1 0 1.91 5.31l3.27 1.94A3 3 0 0 0 12 15a3 3 0 1 0 2.82 4H15a3 3 0 0 0-.17-1l-3.26-1.94a3 3 0 0 0 0-3.12L14.83 10A3 3 0 0 0 15 10h0a3 3 0 0 0 0-2Z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@auth
|
||||
<form method="POST" action="{{ route('favorites.listings.toggle', $listing) }}">
|
||||
@csrf
|
||||
<button
|
||||
type="submit"
|
||||
class="lt-icon-btn {{ $isListingFavorited ? 'is-active' : '' }}"
|
||||
aria-label="{{ $isListingFavorited ? 'Remove from saved listings' : 'Save listing' }}"
|
||||
>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||||
<path d="M12 21l-1.45-1.32C5.4 15.03 2 12.01 2 8.31 2 5.3 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08A6.04 6.04 0 0116.5 3C19.58 3 22 5.3 22 8.31c0 3.7-3.4 6.72-8.55 11.39L12 21z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<a href="{{ route('login') }}" class="lt-icon-btn" aria-label="Sign in to save this listing">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||||
<path d="M12 21l-1.45-1.32C5.4 15.03 2 12.01 2 8.31 2 5.3 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08A6.04 6.04 0 0116.5 3C19.58 3 22 5.3 22 8.31c0 3.7-3.4 6.72-8.55 11.39L12 21z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<a href="{{ route('login') }}" class="lt-icon-btn" aria-label="Sign in to save this listing">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||||
<path d="M12 21l-1.45-1.32C5.4 15.03 2 12.01 2 8.31 2 5.3 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08A6.04 6.04 0 0116.5 3C19.58 3 22 5.3 22 8.31c0 3.7-3.4 6.72-8.55 11.39L12 21z"/>
|
||||
</svg>
|
||||
</a>
|
||||
@endauth
|
||||
</a>
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($initialGalleryImage)
|
||||
@ -171,13 +187,13 @@
|
||||
<section class="lt-card lt-summary-card">
|
||||
<div class="lt-summary-copy">
|
||||
<p class="lt-overline">{{ $listing->category?->name ?? 'Marketplace listing' }}</p>
|
||||
<h1 class="lt-title">{{ $displayTitle }}</h1>
|
||||
<div class="lt-price">{{ $priceLabel }}</div>
|
||||
<p class="lt-subtitle">
|
||||
<span>{{ $locationLabel !== '' ? $locationLabel : 'Location not specified' }}</span>
|
||||
<span aria-hidden="true">·</span>
|
||||
<span>{{ $postedAgo }}</span>
|
||||
</p>
|
||||
<h1 class="lt-title">{{ $displayTitle }}</h1>
|
||||
<div class="lt-summary-meta-row">
|
||||
<span class="lt-summary-meta-item">{{ $locationLabel !== '' ? $locationLabel : 'Location not specified' }}</span>
|
||||
<span class="lt-summary-meta-item">{{ $publishedAt }}</span>
|
||||
</div>
|
||||
<p class="lt-subtitle">{{ $postedAgo }}</p>
|
||||
</div>
|
||||
|
||||
<div class="lt-overview-grid">
|
||||
@ -348,6 +364,56 @@
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<div class="lt-mobile-actions">
|
||||
<div class="lt-mobile-actions-shell">
|
||||
<div class="lt-mobile-actions-row">
|
||||
@if(! $listing->user)
|
||||
<button type="button" class="lt-btn" disabled>Unavailable</button>
|
||||
@elseif($canContactSeller)
|
||||
@if($existingConversationId)
|
||||
<a href="{{ route('panel.inbox.index', ['conversation' => $existingConversationId]) }}" class="lt-btn">
|
||||
Message
|
||||
</a>
|
||||
@else
|
||||
<form method="POST" action="{{ route('conversations.start', $listing) }}" class="lt-action-form">
|
||||
@csrf
|
||||
<button type="submit" class="lt-btn">Message</button>
|
||||
</form>
|
||||
@endif
|
||||
@elseif($isOwnListing)
|
||||
<button type="button" class="lt-btn" disabled>Your listing</button>
|
||||
@else
|
||||
<a href="{{ route('login') }}" class="lt-btn">Message</a>
|
||||
@endif
|
||||
|
||||
@if($primaryContactHref)
|
||||
<a href="{{ $primaryContactHref }}" class="lt-btn lt-btn-outline">{{ $primaryContactLabel }}</a>
|
||||
@else
|
||||
<button type="button" class="lt-btn lt-btn-outline" disabled>No contact</button>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if(! $listing->user)
|
||||
<button type="button" class="lt-btn lt-btn-main" disabled>Unavailable</button>
|
||||
@elseif($canContactSeller)
|
||||
@if($existingConversationId)
|
||||
<a href="{{ route('panel.inbox.index', ['conversation' => $existingConversationId]) }}" class="lt-btn lt-btn-main">
|
||||
Make offer
|
||||
</a>
|
||||
@else
|
||||
<form method="POST" action="{{ route('conversations.start', $listing) }}" class="lt-action-form">
|
||||
@csrf
|
||||
<button type="submit" class="lt-btn lt-btn-main">Make offer</button>
|
||||
</form>
|
||||
@endif
|
||||
@elseif($isOwnListing)
|
||||
<button type="button" class="lt-btn lt-btn-main" disabled>Manage listing</button>
|
||||
@else
|
||||
<a href="{{ route('login') }}" class="lt-btn lt-btn-main">Make offer</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(($relatedListings ?? collect())->isNotEmpty() || ($themePillCategories ?? collect())->isNotEmpty())
|
||||
<section class="lt-related">
|
||||
@if(($relatedListings ?? collect())->isNotEmpty())
|
||||
@ -485,6 +551,32 @@
|
||||
track.scrollBy({ left: amount(), behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-listing-share]').forEach((button) => {
|
||||
button.addEventListener('click', async () => {
|
||||
const url = button.dataset.shareUrl || window.location.href;
|
||||
const title = button.dataset.shareTitle || document.title;
|
||||
|
||||
if (navigator.share) {
|
||||
try {
|
||||
await navigator.share({ title, url });
|
||||
return;
|
||||
} catch (error) {
|
||||
if (error?.name === 'AbortError') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
button.classList.add('is-active');
|
||||
window.setTimeout(() => button.classList.remove('is-active'), 1200);
|
||||
} catch (error) {
|
||||
window.prompt('Copy this link', url);
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@endsection
|
||||
|
||||
@ -849,6 +849,12 @@ summary::-webkit-details-marker {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.lt-gallery-utility {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.lt-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@ -997,12 +1003,30 @@ summary::-webkit-details-marker {
|
||||
}
|
||||
|
||||
.lt-subtitle {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 12px;
|
||||
margin-top: 10px;
|
||||
color: var(--oc-muted);
|
||||
font-size: 1rem;
|
||||
font-size: 0.92rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.lt-summary-meta-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 18px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid rgba(29, 29, 31, 0.08);
|
||||
}
|
||||
|
||||
.lt-summary-meta-item {
|
||||
color: #4b5563;
|
||||
font-size: 0.92rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.lt-summary-meta-item:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.lt-overview-grid {
|
||||
@ -1294,6 +1318,10 @@ summary::-webkit-details-marker {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.lt-mobile-actions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lt-related-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -1513,7 +1541,7 @@ summary::-webkit-details-marker {
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.lt-wrap {
|
||||
padding: 18px 12px 40px;
|
||||
padding: 18px 12px calc(130px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
.lt-card {
|
||||
@ -1522,28 +1550,103 @@ summary::-webkit-details-marker {
|
||||
|
||||
.lt-media-card,
|
||||
.lt-summary-card,
|
||||
.lt-detail-card,
|
||||
.lt-side-card {
|
||||
.lt-detail-card {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.lt-media-card {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
.lt-gallery-main,
|
||||
.lt-gallery-main img,
|
||||
.lt-gallery-main-empty {
|
||||
min-height: 360px;
|
||||
min-height: 420px;
|
||||
}
|
||||
|
||||
.lt-gallery-main {
|
||||
border-radius: 0;
|
||||
background: #2b2d31;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.lt-gallery-main::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lt-gallery-main img {
|
||||
padding: 26px;
|
||||
padding: 0;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.lt-title {
|
||||
max-width: none;
|
||||
font-size: 2rem;
|
||||
font-size: 1.18rem;
|
||||
line-height: 1.45;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.lt-price {
|
||||
font-size: 1.8rem;
|
||||
margin-top: 0;
|
||||
font-size: 1.95rem;
|
||||
}
|
||||
|
||||
.lt-overline,
|
||||
.lt-overview-grid,
|
||||
.lt-gallery-pills,
|
||||
.lt-side-card,
|
||||
.lt-contact-strip,
|
||||
.lt-report,
|
||||
.lt-policy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lt-gallery-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.lt-gallery-utility {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.lt-icon-btn,
|
||||
.lt-gallery-nav {
|
||||
border-color: rgba(255, 255, 255, 0.14);
|
||||
background: rgba(29, 29, 31, 0.52);
|
||||
color: #ffffff;
|
||||
box-shadow: none;
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.lt-summary-card {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
margin-top: -22px;
|
||||
border-radius: 22px 22px 0 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
}
|
||||
|
||||
.lt-summary-card + .lt-detail-card {
|
||||
margin-top: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
box-shadow: 0 18px 36px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.lt-summary-meta-row {
|
||||
margin-top: 14px;
|
||||
padding-top: 14px;
|
||||
}
|
||||
|
||||
.lt-summary-meta-item {
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.lt-overview-grid,
|
||||
@ -1566,6 +1669,36 @@ summary::-webkit-details-marker {
|
||||
.lt-rel-photo {
|
||||
height: 156px;
|
||||
}
|
||||
|
||||
.lt-mobile-actions {
|
||||
display: block;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 45;
|
||||
padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px));
|
||||
background: linear-gradient(180deg, rgba(245, 245, 247, 0) 0%, rgba(245, 245, 247, 0.88) 28%, rgba(245, 245, 247, 0.98) 100%);
|
||||
backdrop-filter: blur(14px);
|
||||
}
|
||||
|
||||
.lt-mobile-actions-shell {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
max-width: 28rem;
|
||||
margin: 0 auto;
|
||||
padding: 10px;
|
||||
border: 1px solid rgba(29, 29, 31, 0.08);
|
||||
border-radius: 22px;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
|
||||
.lt-mobile-actions-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
@ -1581,11 +1714,7 @@ summary::-webkit-details-marker {
|
||||
.lt-gallery-main,
|
||||
.lt-gallery-main img,
|
||||
.lt-gallery-main-empty {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.lt-gallery-main img {
|
||||
padding: 18px;
|
||||
min-height: 392px;
|
||||
}
|
||||
|
||||
.lt-gallery-top {
|
||||
@ -1605,6 +1734,10 @@ summary::-webkit-details-marker {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.lt-summary-card {
|
||||
margin-top: -18px;
|
||||
}
|
||||
|
||||
.lt-seller-name {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
@ -1612,6 +1745,15 @@ summary::-webkit-details-marker {
|
||||
.lt-contact-strip {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lt-mobile-actions {
|
||||
padding-inline: 4px;
|
||||
}
|
||||
|
||||
.lt-mobile-actions-shell {
|
||||
border-radius: 18px;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user