feat: add visibility toggles for content showcase items on public and PDF views
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user