feat: add visibility toggles for content showcase items on public and PDF views

This commit is contained in:
I-Fun
2026-04-06 08:29:47 +07:00
parent 1c73279e52
commit a72eec3ead
4 changed files with 76 additions and 45 deletions

View File

@@ -131,6 +131,8 @@ class RateCardController extends Controller
'content_showcase.*.name' => 'required_with:content_showcase|string|max:255', 'content_showcase.*.name' => 'required_with:content_showcase|string|max:255',
'content_showcase.*.url' => 'nullable|url', 'content_showcase.*.url' => 'nullable|url',
'content_showcase.*.thumbnail_path' => 'nullable|string', 'content_showcase.*.thumbnail_path' => 'nullable|string',
'content_showcase.*.show_on_public' => 'nullable',
'content_showcase.*.show_on_pdf' => 'nullable',
]); ]);
$profile = RateCardProfile::getSingleton(); $profile = RateCardProfile::getSingleton();
@@ -141,7 +143,12 @@ class RateCardController extends Controller
} }
$validated['show_prices'] = $request->has('show_prices'); $validated['show_prices'] = $request->has('show_prices');
$validated['content_showcase'] = $request->input('content_showcase', []); $contentShowcase = $request->input('content_showcase', []);
foreach ($contentShowcase as &$item) {
$item['show_on_public'] = filter_var($item['show_on_public'] ?? true, FILTER_VALIDATE_BOOLEAN);
$item['show_on_pdf'] = filter_var($item['show_on_pdf'] ?? true, FILTER_VALIDATE_BOOLEAN);
}
$validated['content_showcase'] = $contentShowcase;
unset($validated['logo']); unset($validated['logo']);
$profile->update($validated); $profile->update($validated);

View File

@@ -299,12 +299,17 @@
</div> </div>
@endif @endif
@if(!empty($profile->content_showcase)) @php
$pdfShowcase = array_filter($profile->content_showcase ?? [], function($item) {
return !isset($item['show_on_pdf']) || $item['show_on_pdf'];
});
@endphp
@if(!empty($pdfShowcase))
<div style="page-break-before: always;"></div> <div style="page-break-before: always;"></div>
<div class="platform-section" style="margin-top:20px; page-break-inside:avoid;"> <div class="platform-section" style="margin-top:20px; page-break-inside:avoid;">
<div class="platform-title" style="text-align:center;">Content Showcase</div> <div class="platform-title" style="text-align:center;">Content Showcase</div>
<div style="text-align:center; padding-top:10px;"> <div style="text-align:center; padding-top:10px;">
@foreach($profile->content_showcase as $item) @foreach($pdfShowcase as $item)
@php @php
$isUrl = ($item['file_id'] === 'url'); $isUrl = ($item['file_id'] === 'url');
$file = !$isUrl ? \App\Models\MediaFile::find($item['file_id']) : null; $file = !$isUrl ? \App\Models\MediaFile::find($item['file_id']) : null;

View File

@@ -361,9 +361,9 @@
<h2 class="font-bold text-gray-700">Content Showcase</h2> <h2 class="font-bold text-gray-700">Content Showcase</h2>
</div> </div>
<div class="p-5" x-data="{ <div class="p-5" x-data="{
items: {{ Illuminate\Support\Js::from(old('content_showcase', $profile->content_showcase ?? [])) }}.map(i => ({ file_id: i.file_id || '', name: i.name || '', url: i.url || '', thumbnail_path: i.thumbnail_path || '', uploading: false })), items: {{ Illuminate\Support\Js::from(old('content_showcase', $profile->content_showcase ?? [])) }}.map(i => ({ file_id: i.file_id || '', name: i.name || '', url: i.url || '', thumbnail_path: i.thumbnail_path || '', show_on_public: i.show_on_public ?? true, show_on_pdf: i.show_on_pdf ?? true, uploading: false })),
addItem() { addItem() {
this.items.push({ file_id: '', name: '', url: '', thumbnail_path: '', uploading: false }); this.items.push({ file_id: '', name: '', url: '', thumbnail_path: '', show_on_public: true, show_on_pdf: true, uploading: false });
}, },
removeItem(index) { removeItem(index) {
this.items.splice(index, 1); this.items.splice(index, 1);
@@ -421,48 +421,62 @@
</div> </div>
<template x-if="item.file_id"> <template x-if="item.file_id">
<div class="w-full border-t border-pink-100 pt-3 flex flex-wrap gap-3 items-center"> <div class="w-full">
<div class="shrink-0 flex items-center justify-center"> <div class="w-full border-t border-pink-100 pt-3 flex flex-wrap gap-3 items-center">
<input type="hidden" :name="'content_showcase['+index+'][thumbnail_path]'" <div class="shrink-0 flex items-center justify-center">
x-model="item.thumbnail_path"> <input type="hidden" :name="'content_showcase['+index+'][thumbnail_path]'"
x-model="item.thumbnail_path">
<template x-if="item.thumbnail_path">
<div class="relative rounded-xl border border-pink-100 p-1 flex items-center justify-center bg-white group shrink-0" <template x-if="item.thumbnail_path">
style="width: 54px; height: 54px;"> <div class="relative rounded-xl border border-pink-100 p-1 flex items-center justify-center bg-white group shrink-0"
<img :src="'/storage/' + item.thumbnail_path" style="width: 54px; height: 54px;">
class="max-w-full max-h-full object-contain rounded"> <img :src="'/storage/' + item.thumbnail_path"
<button type="button" @click="item.thumbnail_path = ''" class="max-w-full max-h-full object-contain rounded">
class="absolute -top-2 -right-2 bg-red-100 text-red-500 rounded-full w-5 h-5 flex items-center justify-center hover:bg-red-200 shadow text-[9px] z-10 transition-colors">🗑️</button> <button type="button" @click="item.thumbnail_path = ''"
class="absolute -top-2 -right-2 bg-red-100 text-red-500 rounded-full w-5 h-5 flex items-center justify-center hover:bg-red-200 shadow text-[9px] z-10 transition-colors">🗑️</button>
</div>
</template>
<template x-if="!item.thumbnail_path">
<label
class="rounded-xl border-2 border-dashed border-pink-200 flex items-center justify-center text-pink-300 hover:bg-pink-50 hover:text-pink-400 cursor-pointer transition-colors shrink-0"
style="width: 54px; height: 54px;"
:class="{'opacity-50 pointer-events-none': item.uploading}"
title="Upload Thumbnail (Optional)">
<span x-show="!item.uploading"
class="text-xl font-light leading-none mb-1">+</span>
<span x-show="item.uploading" class="text-[10px]">...</span>
<input type="file" accept="image/*" class="hidden"
@change="uploadThumb($event.target, item)">
</label>
</template>
</div>
<template x-if="item.file_id === 'url'">
<div class="flex-1 min-w-[200px]">
<input type="url" :name="'content_showcase['+index+'][url]'" x-model="item.url"
class="input-soft w-full py-2 px-3 text-xs"
placeholder="URL (https://instagram.com/p/...)" required>
</div> </div>
</template> </template>
<template x-if="!item.thumbnail_path">
<label <template x-if="item.file_id !== 'url'">
class="rounded-xl border-2 border-dashed border-pink-200 flex items-center justify-center text-pink-300 hover:bg-pink-50 hover:text-pink-400 cursor-pointer transition-colors shrink-0" <div class="flex-1 text-xs text-gray-400">
style="width: 54px; height: 54px;" Uploaded Thumbnail: Use this to override the default display icon for videos and documents.
:class="{'opacity-50 pointer-events-none': item.uploading}" </div>
title="Upload Thumbnail (Optional)">
<span x-show="!item.uploading"
class="text-xl font-light leading-none mb-1">+</span>
<span x-show="item.uploading" class="text-[10px]">...</span>
<input type="file" accept="image/*" class="hidden"
@change="uploadThumb($event.target, item)">
</label>
</template> </template>
</div> </div>
<div class="w-full border-t border-pink-100 pt-3 flex flex-wrap gap-4 items-center mt-2">
<template x-if="item.file_id === 'url'"> <label class="flex items-center gap-2 cursor-pointer text-[11px] font-semibold text-gray-600">
<div class="flex-1 min-w-[200px]"> <input type="hidden" :name="'content_showcase['+index+'][show_on_public]'" value="0">
<input type="url" :name="'content_showcase['+index+'][url]'" x-model="item.url" <input type="checkbox" :name="'content_showcase['+index+'][show_on_public]'" value="1" x-model="item.show_on_public" class="w-4 h-4 accent-pink-400 rounded cursor-pointer shrink-0">
class="input-soft w-full py-2 px-3 text-xs" Show on Public Page
placeholder="URL (https://instagram.com/p/...)" required> </label>
</div> <label class="flex items-center gap-2 cursor-pointer text-[11px] font-semibold text-gray-600">
</template> <input type="hidden" :name="'content_showcase['+index+'][show_on_pdf]'" value="0">
<input type="checkbox" :name="'content_showcase['+index+'][show_on_pdf]'" value="1" x-model="item.show_on_pdf" class="w-4 h-4 accent-pink-400 rounded cursor-pointer shrink-0">
<template x-if="item.file_id !== 'url'"> Show on PDF
<div class="flex-1 text-xs text-gray-400"> </label>
Uploaded Thumbnail: Use this to override the default display icon for videos and documents. </div>
</div>
</template>
</div> </div>
</template> </template>
</div> </div>

View File

@@ -329,11 +329,16 @@
</div> </div>
@endif @endif
@if(!empty($profile->content_showcase)) @php
$publicShowcase = array_filter($profile->content_showcase ?? [], function($item) {
return !isset($item['show_on_public']) || $item['show_on_public'];
});
@endphp
@if(!empty($publicShowcase))
<div class="platform-section" style="margin-top:40px;"> <div class="platform-section" style="margin-top:40px;">
<div class="platform-title" style="justify-content:center;">Content Showcase</div> <div class="platform-title" style="justify-content:center;">Content Showcase</div>
<div class="cards"> <div class="cards">
@foreach($profile->content_showcase as $item) @foreach($publicShowcase as $item)
@php @php
$isUrl = ($item['file_id'] === 'url'); $isUrl = ($item['file_id'] === 'url');
$file = !$isUrl ? \App\Models\MediaFile::find($item['file_id']) : null; $file = !$isUrl ? \App\Models\MediaFile::find($item['file_id']) : null;