Merge pull request 'dev' (#35) from dev into master

Reviewed-on: #35
This commit is contained in:
2026-07-02 09:41:16 +00:00
6 changed files with 219 additions and 27 deletions

View File

@@ -0,0 +1,41 @@
<?php
namespace App\View\Components;
use App\Models\Entry;
use App\Models\News;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class ShareRhpzUrl extends Component
{
/**
* Create a new component instance.
*/
public function __construct(
public Entry|News $entry,
)
{
//
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
if( ( $this->entry->type ?? "news" ) === 'news' ){
$letter = 'n';
} else {
$letter = $this->entry->type[0];
}
$id = $this->entry->id;
$shareUrl = config('app.share_url');
$url = rtrim($shareUrl, '/') . '/' . $letter . '/' . $id;
return view('components.share-rhpz-url', compact('url') );
}
}

View File

@@ -126,4 +126,5 @@ return [
'store' => env('APP_MAINTENANCE_STORE', 'database'), 'store' => env('APP_MAINTENANCE_STORE', 'database'),
], ],
'share_url' => env('RHPZ_SHARE_URL', ''),
]; ];

View File

@@ -178,7 +178,6 @@
max-width: 90%; max-width: 90%;
max-height: 90%; max-height: 90%;
position: relative; position: relative;
img { img {
max-width: 100%; max-width: 100%;
max-height: 90vh; max-height: 90vh;
@@ -198,12 +197,40 @@
font-weight: bold; font-weight: bold;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
&:hover { &:hover {
color: var(--rhpz-orange); color: var(--rhpz-orange);
} }
} }
.gallery-modal-arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: #fff;
cursor: pointer;
user-select: none;
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
&:hover {
color: var(--rhpz-orange);
}
i {
width: 28px;
height: 28px;
}
}
.gallery-modal-arrow-prev {
left: 20px;
}
.gallery-modal-arrow-next {
right: 20px;
}
.gallery-modal-video { .gallery-modal-video {
width: 90%; width: 90%;
max-width: 960px; max-width: 960px;
@@ -211,7 +238,6 @@
box-shadow: 0 10px 30px rgba(0,0,0,0.6); box-shadow: 0 10px 30px rgba(0,0,0,0.6);
border: 1px solid var(--border); border: 1px solid var(--border);
background-color: #000; background-color: #000;
iframe { iframe {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@@ -0,0 +1,50 @@
<div x-data="{
shareModal: false,
copied: false,
copyClipboard: function(){
let share = document.getElementById('share-link');
share.select();
share.setSelectionRange(0, 99999);
navigator.clipboard.writeText(share.value);
this.copied = true;
}
}">
<button type="button" class="btn" @click="shareModal = true">
<i data-lucide="link"></i> Share
</button>
<div
class="modal-overlay"
x-show="shareModal"
x-effect="shareModal && $nextTick(() => window.refreshIcons($el))"
x-cloak
x-transition.opacity.duration.300ms
@keydown.escape.window="shareModal = false; copied = false;"
@focus="window.refreshIcons($el)"
>
<div @click.outside="shareModal = false; copied = false;" class="modal-window">
<div class="modal-header">
<span class="modal-title">Share this page</span>
<button type="button" @click="shareModal = false; copied = false;" class="modal-close">
<i data-lucide="x" size="18"></i>
</button>
</div>
<div class="modal-content">
<div class="form-group">
<label class="form-label">URL</label>
<input type="text" id="share-link" disabled class="form-input" value="{{ $url }}">
</div>
<button type="button" class="btn" @click="copyClipboard()">
<i data-lucide="link" size="14"></i> Copy
</button>
<span class="whisper" x-show="copied">Copied !</span>
</div>
</div>
</div>
</div>

View File

@@ -7,9 +7,16 @@
{{ \Diglactic\Breadcrumbs\Breadcrumbs::render() }} {{ \Diglactic\Breadcrumbs\Breadcrumbs::render() }}
<article id="entry-container"> <article id="entry-container">
<div class="entry-header"> <div class="entry-header">
<div class="entry-cover"> <div class="entry-cover" x-data="{open: false}">
@if( $entry->main_image ) @if( $entry->main_image )
<img src="{{ Storage::url($entry->main_image) }}"> <img src="{{ Storage::url($entry->main_image) }}" @click="open = true;">
<div class="gallery-modal" x-show="open" x-transition.opacity.duration.300ms @click="open = false"
@keydown.escape.window="open = false" x-cloak>
<span class="gallery-modal-close" @click="open = false;"><i data-lucide="x"></i></span>
<div class="gallery-modal-content" @click.stop>
<img src="{{ Storage::url($entry->main_image) }}">
</div>
</div>
@else @else
<div class="entry-cover-placeholder"> <div class="entry-cover-placeholder">
<i data-lucide="image" size="48"></i> <i data-lucide="image" size="48"></i>
@@ -208,6 +215,7 @@
<i data-lucide="flag"></i> Report / Claim Ownership <i data-lucide="flag"></i> Report / Claim Ownership
</a> </a>
@endauth @endauth
<x-share-rhpz-url :entry="$entry" />
</div> </div>
</div> </div>
</div> </div>
@@ -240,25 +248,57 @@
</ul> </ul>
</div> </div>
@endif @endif
{{-- Gallery --}}
@if( $entry->gallery->isNotEmpty() ) @if( $entry->gallery->isNotEmpty() )
<div x-data="{ open: false, currentImage: ''}" x-cloak> <div x-data="{
images: [
@foreach( $entry->gallery as $galleryItem )
'{{ Storage::url($galleryItem->image) }}',
@endforeach
],
currentIndex: 0,
open: false,
get currentImage() { return this.images[this.currentIndex]; },
get hasPrev() { return this.currentIndex > 0; },
get hasNext() { return this.currentIndex < this.images.length - 1; },
openAt(index) { this.currentIndex = index; this.open = true; },
prev() { if (this.hasPrev) this.currentIndex--; },
next() { if (this.hasNext) this.currentIndex++; }
}" x-cloak>
<x-entry-section-title label="Gallery" icon="images"/> <x-entry-section-title label="Gallery" icon="images"/>
<div class="entry-gallery"> <div class="entry-gallery">
@foreach( $entry->gallery as $galleryItem ) @foreach( $entry->gallery as $galleryItem )
<div class="entry-gallery-item" <div class="entry-gallery-item" @click="openAt({{ $loop->index }})">
@click="currentImage = '{{ Storage::url($galleryItem->image) }}'; open = true; "><img <img src="{{ Storage::url($galleryItem->image) }}">
src="{{ Storage::url($galleryItem->image) }}"></div> </div>
@endforeach @endforeach
</div> </div>
<div class="gallery-modal" x-show="open" x-transition.opacity.duration.300ms @click="open = false" <div class="gallery-modal" x-show="open" x-transition.opacity.duration.300ms @click="open = false"
@keydown.escape.window="open = false"> @keydown.escape.window="open = false"
@keydown.arrow-left.window="prev()"
@keydown.arrow-right.window="next()"
x-cloak>
<span class="gallery-modal-close" @click="open = false;"><i data-lucide="x"></i></span> <span class="gallery-modal-close" @click="open = false;"><i data-lucide="x"></i></span>
<span class="gallery-modal-arrow gallery-modal-arrow-prev" x-show="hasPrev" @click.stop="prev()">
<i data-lucide="chevron-left"></i>
</span>
<div class="gallery-modal-content" @click.stop> <div class="gallery-modal-content" @click.stop>
<img :src="currentImage"> <img :src="currentImage">
</div> </div>
<span class="gallery-modal-arrow gallery-modal-arrow-next" x-show="hasNext" @click.stop="next()">
<i data-lucide="chevron-right"></i>
</span>
</div> </div>
</div> </div>
@endif @endif
{{-- End gallery --}}
@if( $entry->relevant_link ) @if( $entry->relevant_link )
<x-entry-section-title label="Relevant Link" icon="link"/> <x-entry-section-title label="Relevant Link" icon="link"/>
<div class="entry-description"> <div class="entry-description">

View File

@@ -123,6 +123,8 @@
</a> </a>
@endauth @endauth
<x-share-rhpz-url :entry="$news" />
</div> </div>
</div> </div>
</div> </div>
@@ -134,25 +136,57 @@
{!! $news->description_html !!} {!! $news->description_html !!}
</div> </div>
@endif @endif
@if( $news->gallery->isNotEmpty() )
<div x-data="{ open: false, currentImage: ''}" x-cloak> {{-- Gallery --}}
<x-entry-section-title label="Gallery" icon="images"/>
<div class="entry-gallery"> @if( $news->gallery->isNotEmpty() )
@foreach( $news->gallery as $galleryItem ) <div x-data="{
<div class="entry-gallery-item" images: [
@click="currentImage = '{{ Storage::url($galleryItem->image) }}'; open = true; "><img @foreach( $news->gallery as $galleryItem )
src="{{ Storage::url($galleryItem->image) }}"></div> '{{ Storage::url($galleryItem->image) }}',
@endforeach @endforeach
</div> ],
<div class="gallery-modal" x-show="open" x-transition.opacity.duration.300ms @click="open = false" currentIndex: 0,
@keydown.escape.window="open = false"> open: false,
<span class="gallery-modal-close" @click="open = false;"><i data-lucide="x"></i></span> get currentImage() { return this.images[this.currentIndex]; },
<div class="gallery-modal-content" @click.stop> get hasPrev() { return this.currentIndex > 0; },
<img :src="currentImage"> get hasNext() { return this.currentIndex < this.images.length - 1; },
openAt(index) { this.currentIndex = index; this.open = true; },
prev() { if (this.hasPrev) this.currentIndex--; },
next() { if (this.hasNext) this.currentIndex++; }
}" x-cloak>
<x-entry-section-title label="Gallery" icon="images"/>
<div class="entry-gallery">
@foreach( $news->gallery as $galleryItem )
<div class="entry-gallery-item" @click="openAt({{ $loop->index }})">
<img src="{{ Storage::url($galleryItem->image) }}">
</div>
@endforeach
</div>
<div class="gallery-modal" x-show="open" x-transition.opacity.duration.300ms @click="open = false"
@keydown.escape.window="open = false"
@keydown.arrow-left.window="prev()"
@keydown.arrow-right.window="next()"
x-cloak>
<span class="gallery-modal-close" @click="open = false;"><i data-lucide="x"></i></span>
<span class="gallery-modal-arrow gallery-modal-arrow-prev" x-show="hasPrev" @click.stop="prev()">
<i data-lucide="chevron-left"></i>
</span>
<div class="gallery-modal-content" @click.stop>
<img :src="currentImage">
</div>
<span class="gallery-modal-arrow gallery-modal-arrow-next" x-show="hasNext" @click.stop="next()">
<i data-lucide="chevron-right"></i>
</span>
</div> </div>
</div> </div>
</div> @endif
@endif
{{-- End gallery --}}
</div> </div>
@if( $news->entry()->exists() || $news->relevant_link || $news->youtube_link ) @if( $news->entry()->exists() || $news->relevant_link || $news->youtube_link )
<aside class="news-sidebar"> <aside class="news-sidebar">