Files
filament-short-url/resources/views/sidebar/social-preview.blade.php

132 lines
8.3 KiB
PHP

@php
$ogTitle = $ogTitle ?? ($get('og_title') ?: null);
$ogDescription = $ogDescription ?? ($get('og_description') ?: null);
$ogImageUrl = $ogImageUrl ?? null;
$isScraping = $isScraping ?? ($get('is_scraping') ?: false);
@endphp
<div
class="sidebar-social-container"
wire:key="fsu-social-preview-{{ md5(json_encode([$ogTitle, $ogDescription, $ogImageUrl, (bool) $isScraping])) }}"
x-data="{ scraping: @js((bool) $isScraping), passwordProtected: @js((bool) $isPasswordProtected) }"
x-on:fsu-scraping-start.window="scraping = true"
x-on:fsu-scraping-end.window="scraping = false"
x-on:fsu-password-protection-changed.window="passwordProtected = !!$event.detail.protected"
x-on:fsu-og-image-updated.window="scraping = false"
>
{{-- Header: Title only (no "i" icon) --}}
<span class="fi-fo-field-wrp-label flex items-center gap-x-3 mb-1.5">
<label class="fi-label text-sm font-semibold leading-6 text-gray-950 dark:text-white">
{{ __('filament-short-url::default.live_social_preview') }}
</label>
</span>
<div x-show="scraping" x-cloak>
{{-- ===== LOADING / SCRAPING STATE ===== --}}
<div class="relative w-full rounded-xl overflow-hidden border border-neutral-200 dark:border-neutral-700 qr-preview-dots-bg aspect-[16/10] flex items-center justify-center">
<div class="absolute inset-0 bg-neutral-100 dark:bg-neutral-800/20 flex items-center justify-center">
<svg class="w-8 h-8 text-indigo-600 dark:text-indigo-400 animate-spin" fill="none" viewBox="0 0 24 24" style="width: 32px !important; height: 32px !important;">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</div>
</div>
<div class="mt-2.5 space-y-2">
<div class="h-4 bg-neutral-200 dark:bg-neutral-800 rounded animate-pulse w-3/4"></div>
<div class="h-3.5 bg-neutral-200 dark:bg-neutral-800 rounded animate-pulse w-5/6"></div>
<div class="h-3 bg-neutral-200 dark:bg-neutral-800/60 rounded animate-pulse w-1/2"></div>
</div>
</div>
<div x-show="!scraping && passwordProtected" x-cloak>
{{-- ===== PASSWORD STATE ===== --}}
<div class="relative w-full rounded-xl overflow-hidden bg-black aspect-[16/10]">
{{-- Edit button --}}
<button
type="button"
onclick="
const tabs = document.querySelectorAll('[role=tab]');
tabs.forEach(t => { if (t.textContent.trim().includes('SEO') || t.textContent.trim().includes('Social') || t.getAttribute('aria-label')?.includes('seo')) { t.click(); } });
"
class="absolute top-2 right-2 z-10 w-8 h-8 rounded-lg bg-white/90 dark:bg-neutral-900/90 border border-neutral-200 dark:border-neutral-700 shadow-sm flex items-center justify-center hover:bg-white dark:hover:bg-neutral-800 transition cursor-pointer"
style="width: 32px !important; height: 32px !important;"
title="{{ __('filament-short-url::default.action_edit') }}"
>
<svg class="w-4 h-4 text-neutral-500 dark:text-neutral-400" style="width: 20px !important; height: 20px !important;" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"/>
</svg>
</button>
{{-- Lock icon centered --}}
<div class="absolute inset-0 flex items-center justify-center">
<div class="w-14 h-14 rounded-full bg-neutral-800/80 flex items-center justify-center">
<svg class="w-7 h-7 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"/>
</svg>
</div>
</div>
</div>
{{-- Password caption --}}
<div class="mt-2.5">
<p class="text-sm font-bold text-neutral-800 dark:text-neutral-100">
{{ __('filament-short-url::default.password_status_active') }}
</p>
<p class="text-[12px] text-neutral-500 dark:text-neutral-400 mt-0.5 leading-snug">
{{ __('filament-short-url::default.password_prompt_preview_desc') }}
</p>
</div>
</div>
<div x-show="!scraping && !passwordProtected" x-cloak>
{{-- ===== DEFAULT / IMAGE STATE ===== --}}
<div class="relative w-full rounded-xl overflow-hidden border border-neutral-200 dark:border-neutral-700 qr-preview-dots-bg aspect-[16/10] flex items-center justify-center">
{{-- Edit button (same style as QR preview: small, top-right) --}}
<button
type="button"
onclick="
const tabs = document.querySelectorAll('[role=tab]');
tabs.forEach(t => { if (t.textContent.trim().includes('SEO') || t.textContent.trim().includes('Social') || t.getAttribute('aria-label')?.includes('seo')) { t.click(); } });
"
class="absolute top-2 right-2 z-10 w-8 h-8 rounded-lg bg-white/90 dark:bg-neutral-900/90 border border-neutral-200 dark:border-neutral-700 shadow-sm flex items-center justify-center hover:bg-white dark:hover:bg-neutral-800 transition cursor-pointer"
style="width: 32px !important; height: 32px !important;"
title="{{ __('filament-short-url::default.action_edit') }}"
>
<svg class="w-4 h-4 text-neutral-500 dark:text-neutral-400" style="width: 20px !important; height: 20px !important;" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"/>
</svg>
</button>
@if ($ogImageUrl)
{{-- OG Image preview --}}
<img src="{{ $ogImageUrl }}" alt="OG Preview" class="absolute inset-0 w-full h-full object-cover">
@else
{{-- Empty state: photo icon + text --}}
<div class="flex flex-col items-center gap-2 text-neutral-400 dark:text-neutral-500 select-none pointer-events-none">
<svg class="w-7 h-7" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.3">
<rect x="3" y="3" width="18" height="18" rx="3" stroke-width="1.3" stroke="currentColor" fill="none"/>
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16l5-5a2 2 0 012.8 0L16 16m-2-2l1.5-1.5a2 2 0 012.8 0L20 14"/>
<circle cx="8.5" cy="8.5" r="1.5" fill="currentColor" stroke="none"/>
</svg>
<span class="text-[11px] font-medium text-center leading-snug">
{{ __('filament-short-url::default.og_empty_state_hint') }}
</span>
</div>
@endif
</div>
{{-- Title / Description caption --}}
<div class="mt-2.5 space-y-0.5">
<p class="text-sm font-bold {{ $ogTitle ? 'text-neutral-800 dark:text-neutral-100' : 'text-neutral-400 dark:text-neutral-600' }}">
{{ $ogTitle ?: __('filament-short-url::default.og_title_placeholder') }}
</p>
<p class="text-[12px] {{ $ogDescription ? 'text-neutral-500 dark:text-neutral-400' : 'text-neutral-300 dark:text-neutral-600' }} leading-snug">
{{ $ogDescription ?: __('filament-short-url::default.og_description_placeholder') }}
</p>
</div>
</div>
</div>