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');
|
$reportEmail = config('mail.from.address', 'support@example.com');
|
||||||
$reportUrl = 'mailto:'.$reportEmail.'?subject='.rawurlencode('Report listing #'.$listing->getKey());
|
$reportUrl = 'mailto:'.$reportEmail.'?subject='.rawurlencode('Report listing #'.$listing->getKey());
|
||||||
|
$shareUrl = route('listings.show', $listing);
|
||||||
|
|
||||||
$overviewItems = collect([
|
$overviewItems = collect([
|
||||||
['label' => 'Listing ID', 'value' => '#'.$listing->getKey()],
|
['label' => 'Listing ID', 'value' => '#'.$listing->getKey()],
|
||||||
@ -108,26 +109,41 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@auth
|
<div class="lt-gallery-utility">
|
||||||
<form method="POST" action="{{ route('favorites.listings.toggle', $listing) }}">
|
<button
|
||||||
@csrf
|
type="button"
|
||||||
<button
|
class="lt-icon-btn"
|
||||||
type="submit"
|
data-listing-share
|
||||||
class="lt-icon-btn {{ $isListingFavorited ? 'is-active' : '' }}"
|
data-share-url="{{ $shareUrl }}"
|
||||||
aria-label="{{ $isListingFavorited ? 'Remove from saved listings' : 'Save listing' }}"
|
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">
|
<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"/>
|
<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>
|
</svg>
|
||||||
</button>
|
</a>
|
||||||
</form>
|
@endauth
|
||||||
@else
|
</div>
|
||||||
<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
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($initialGalleryImage)
|
@if($initialGalleryImage)
|
||||||
@ -171,13 +187,13 @@
|
|||||||
<section class="lt-card lt-summary-card">
|
<section class="lt-card lt-summary-card">
|
||||||
<div class="lt-summary-copy">
|
<div class="lt-summary-copy">
|
||||||
<p class="lt-overline">{{ $listing->category?->name ?? 'Marketplace listing' }}</p>
|
<p class="lt-overline">{{ $listing->category?->name ?? 'Marketplace listing' }}</p>
|
||||||
<h1 class="lt-title">{{ $displayTitle }}</h1>
|
|
||||||
<div class="lt-price">{{ $priceLabel }}</div>
|
<div class="lt-price">{{ $priceLabel }}</div>
|
||||||
<p class="lt-subtitle">
|
<h1 class="lt-title">{{ $displayTitle }}</h1>
|
||||||
<span>{{ $locationLabel !== '' ? $locationLabel : 'Location not specified' }}</span>
|
<div class="lt-summary-meta-row">
|
||||||
<span aria-hidden="true">·</span>
|
<span class="lt-summary-meta-item">{{ $locationLabel !== '' ? $locationLabel : 'Location not specified' }}</span>
|
||||||
<span>{{ $postedAgo }}</span>
|
<span class="lt-summary-meta-item">{{ $publishedAt }}</span>
|
||||||
</p>
|
</div>
|
||||||
|
<p class="lt-subtitle">{{ $postedAgo }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lt-overview-grid">
|
<div class="lt-overview-grid">
|
||||||
@ -348,6 +364,56 @@
|
|||||||
</aside>
|
</aside>
|
||||||
</div>
|
</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())
|
@if(($relatedListings ?? collect())->isNotEmpty() || ($themePillCategories ?? collect())->isNotEmpty())
|
||||||
<section class="lt-related">
|
<section class="lt-related">
|
||||||
@if(($relatedListings ?? collect())->isNotEmpty())
|
@if(($relatedListings ?? collect())->isNotEmpty())
|
||||||
@ -485,6 +551,32 @@
|
|||||||
track.scrollBy({ left: amount(), behavior: 'smooth' });
|
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>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
@ -849,6 +849,12 @@ summary::-webkit-details-marker {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lt-gallery-utility {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.lt-badge {
|
.lt-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -997,12 +1003,30 @@ summary::-webkit-details-marker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.lt-subtitle {
|
.lt-subtitle {
|
||||||
display: flex;
|
margin-top: 10px;
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 10px;
|
|
||||||
margin-top: 12px;
|
|
||||||
color: var(--oc-muted);
|
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 {
|
.lt-overview-grid {
|
||||||
@ -1294,6 +1318,10 @@ summary::-webkit-details-marker {
|
|||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lt-mobile-actions {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.lt-related-head {
|
.lt-related-head {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -1513,7 +1541,7 @@ summary::-webkit-details-marker {
|
|||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
.lt-wrap {
|
.lt-wrap {
|
||||||
padding: 18px 12px 40px;
|
padding: 18px 12px calc(130px + env(safe-area-inset-bottom, 0px));
|
||||||
}
|
}
|
||||||
|
|
||||||
.lt-card {
|
.lt-card {
|
||||||
@ -1522,28 +1550,103 @@ summary::-webkit-details-marker {
|
|||||||
|
|
||||||
.lt-media-card,
|
.lt-media-card,
|
||||||
.lt-summary-card,
|
.lt-summary-card,
|
||||||
.lt-detail-card,
|
.lt-detail-card {
|
||||||
.lt-side-card {
|
|
||||||
padding: 14px;
|
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,
|
||||||
.lt-gallery-main img,
|
.lt-gallery-main img,
|
||||||
.lt-gallery-main-empty {
|
.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 {
|
.lt-gallery-main img {
|
||||||
padding: 26px;
|
padding: 0;
|
||||||
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lt-title {
|
.lt-title {
|
||||||
max-width: none;
|
max-width: none;
|
||||||
font-size: 2rem;
|
font-size: 1.18rem;
|
||||||
|
line-height: 1.45;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lt-price {
|
.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,
|
.lt-overview-grid,
|
||||||
@ -1566,6 +1669,36 @@ summary::-webkit-details-marker {
|
|||||||
.lt-rel-photo {
|
.lt-rel-photo {
|
||||||
height: 156px;
|
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) {
|
@media (max-width: 480px) {
|
||||||
@ -1581,11 +1714,7 @@ summary::-webkit-details-marker {
|
|||||||
.lt-gallery-main,
|
.lt-gallery-main,
|
||||||
.lt-gallery-main img,
|
.lt-gallery-main img,
|
||||||
.lt-gallery-main-empty {
|
.lt-gallery-main-empty {
|
||||||
min-height: 300px;
|
min-height: 392px;
|
||||||
}
|
|
||||||
|
|
||||||
.lt-gallery-main img {
|
|
||||||
padding: 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.lt-gallery-top {
|
.lt-gallery-top {
|
||||||
@ -1605,6 +1734,10 @@ summary::-webkit-details-marker {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lt-summary-card {
|
||||||
|
margin-top: -18px;
|
||||||
|
}
|
||||||
|
|
||||||
.lt-seller-name {
|
.lt-seller-name {
|
||||||
font-size: 1.35rem;
|
font-size: 1.35rem;
|
||||||
}
|
}
|
||||||
@ -1612,6 +1745,15 @@ summary::-webkit-details-marker {
|
|||||||
.lt-contact-strip {
|
.lt-contact-strip {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lt-mobile-actions {
|
||||||
|
padding-inline: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lt-mobile-actions-shell {
|
||||||
|
border-radius: 18px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user