Files
autocrm/resources/views/filament/tenant/pages/faq.blade.php
T
Vasyka 0716b70bfa feat(faq): video tutorial + full-width layout + wider grid
- New tenant setting: settings.faq_video_url. TextInput on Settings
  page → Liste configurabile (accepts YouTube watch URL, youtu.be
  short URL, YouTube shorts/embed URL, or Vimeo URL).
- Faq page has getVideoEmbedUrl() that converts recognized URLs to
  their /embed/ variant. Unknown URLs fall back to a "?" card with
  a direct link. Admins see a "configure in Settings" nudge when no
  URL is set.
- Video renders as a 16:9 iframe capped at 480px height, above the
  hero.
- .faq-shell is now width:100% (was max-width:1200px) so FAQ uses
  all available horizontal space.
- .faq-grid switched from strict 2 columns to
  repeat(auto-fit, minmax(420px, 1fr)) so wide screens get 3 columns
  and narrow screens stack.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-09-01 10:50:40 +00:00

348 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<x-filament-panels::page>
@php
$lc = \App\Support\Hints::locale();
$areas = $this->getAreas();
$grouped = $this->getGrouped();
$user = auth()->user();
$totalHints = collect($grouped)->sum(fn ($g) => count($g));
$videoEmbed = $this->getVideoEmbedUrl();
$videoRaw = $this->getVideoRawUrl();
// Distinct accent color per area for card headers
$areaColors = [
'service' => '#0ea5e9',
'crm' => '#8b5cf6',
'depozit' => '#f59e0b',
'finante' => '#10b981',
];
@endphp
<style>
.faq-shell { width: 100%; }
/* ── VIDEO ── */
.faq-video-card {
background: #000;
border-radius: 12px;
overflow: hidden;
margin-bottom: 20px;
position: relative;
aspect-ratio: 16 / 9;
max-height: 480px;
}
.faq-video-card iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
}
.faq-video-fallback {
background: linear-gradient(135deg, #374151 0%, #111827 100%);
border-radius: 12px;
padding: 40px 28px;
color: #fff;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 20px;
flex-wrap: wrap;
}
.faq-video-fallback-icon { font-size: 40px; }
.faq-video-fallback-txt { flex: 1; min-width: 200px; }
.faq-video-fallback-title { font-size: 16px; font-weight: 600; margin: 0 0 4px; }
.faq-video-fallback-sub { font-size: 13px; opacity: .8; margin: 0; }
.faq-video-fallback a { color: #60a5fa; text-decoration: none; font-weight: 500; }
.faq-video-fallback a:hover { text-decoration: underline; }
/* ── HERO STRIP ── */
.faq-hero {
background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
border-radius: 12px;
padding: 24px 28px;
color: #fff;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 24px;
flex-wrap: wrap;
}
.dark .faq-hero { background: linear-gradient(135deg, #1e3a8a 0%, #0f172a 100%); }
.faq-hero-icon { font-size: 48px; line-height: 1; }
.faq-hero-txt { flex: 1; min-width: 200px; }
.faq-hero-title { font-size: 22px; font-weight: 700; margin: 0 0 4px; letter-spacing: -.3px; }
.faq-hero-sub { font-size: 13px; opacity: .85; margin: 0; }
.faq-hero-stats { display: flex; gap: 16px; }
.faq-hero-stat { text-align: center; }
.faq-hero-stat-n { font-size: 24px; font-weight: 700; line-height: 1; }
.faq-hero-stat-l { font-size: 11px; opacity: .8; text-transform: uppercase; letter-spacing: .5px; }
/* ── CONTROLS BAR ── */
.faq-controls {
display: grid;
grid-template-columns: 1fr auto;
gap: 12px;
align-items: center;
margin-bottom: 24px;
padding: 12px 16px;
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 10px;
}
.dark .faq-controls { background: #1f2937; border-color: #374151; }
.faq-search {
width: 100%;
padding: 10px 14px 10px 40px;
border: 1px solid #d1d5db;
border-radius: 8px;
font-size: 14px;
background: #fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2'><circle cx='11' cy='11' r='8'/><path d='m21 21-4.35-4.35'/></svg>") no-repeat 12px center;
}
.dark .faq-search { background-color: #111827; border-color: #4b5563; color: #f3f4f6; }
.faq-search:focus { outline: 2px solid #3b82f6; outline-offset: -1px; border-color: #3b82f6; }
.faq-toggle { display: flex; gap: 8px; align-items: center; font-size: 13px; }
.faq-toggle-lbl { color: #6b7280; font-size: 12px; }
.faq-btn-toggle {
display: inline-flex; align-items: center; gap: 6px;
padding: 7px 14px; border-radius: 20px; border: 0;
font-size: 12px; font-weight: 600; cursor: pointer;
transition: all .15s;
}
.faq-btn-toggle.on { background: #10b981; color: #fff; }
.faq-btn-toggle.off { background: #e5e7eb; color: #374151; }
.faq-btn-toggle:hover { transform: translateY(-1px); box-shadow: 0 2px 6px rgba(0,0,0,.15); }
.faq-btn-reset {
padding: 7px 14px; border-radius: 20px;
border: 1px solid #d1d5db; background: #fff; color: #6b7280;
font-size: 12px; cursor: pointer;
}
.dark .faq-btn-reset { background: #374151; border-color: #4b5563; color: #d1d5db; }
.faq-btn-reset:hover { background: #f9fafb; color: #111; }
.dark .faq-btn-reset:hover { background: #4b5563; color: #f3f4f6; }
/* ── GRID OF AREA CARDS ── */
.faq-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 20px; }
@media (max-width: 900px) { .faq-grid { grid-template-columns: 1fr; } }
.faq-card {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0,0,0,.05);
}
.dark .faq-card { background: #1f2937; border-color: #374151; }
.faq-card-hd {
padding: 16px 18px;
border-bottom: 1px solid #e5e7eb;
display: flex; align-items: center; gap: 12px;
color: #fff;
}
.dark .faq-card-hd { border-bottom-color: #374151; }
.faq-card-icon { font-size: 26px; line-height: 1; }
.faq-card-title { font-size: 15px; font-weight: 700; letter-spacing: -.2px; flex: 1; }
.faq-card-badge {
background: rgba(255,255,255,.25);
padding: 2px 10px; border-radius: 10px;
font-size: 11px; font-weight: 700;
}
.faq-card-body { padding: 8px; }
.faq-item {
border-radius: 8px;
margin-bottom: 4px;
overflow: hidden;
transition: background .15s;
}
.faq-item summary {
padding: 10px 14px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
color: #111;
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
user-select: none;
border-radius: 8px;
}
.dark .faq-item summary { color: #f3f4f6; }
.faq-item summary:hover { background: #f9fafb; }
.dark .faq-item summary:hover { background: #374151; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: '+'; color: #9ca3af; font-size: 18px; font-weight: 400; line-height: 1; }
.faq-item[open] { background: #f0f9ff; }
.dark .faq-item[open] { background: #1e3a5f; }
.faq-item[open] summary::after { content: ''; }
.faq-body-txt {
padding: 0 14px 14px;
font-size: 12.5px;
line-height: 1.55;
color: #374151;
}
.dark .faq-body-txt { color: #d1d5db; }
.faq-next {
margin-top: 10px;
padding: 8px 12px;
background: #d1fae5;
color: #065f46;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
}
.dark .faq-next { background: #064e3b; color: #a7f3d0; }
.faq-next::before { content: '→ '; font-weight: 700; }
.faq-links {
margin-top: 10px;
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.faq-link {
padding: 4px 10px;
background: #eff6ff;
color: #1d4ed8;
border-radius: 6px;
font-size: 11.5px;
text-decoration: none;
font-weight: 500;
}
.dark .faq-link { background: #1e3a8a; color: #93c5fd; }
.faq-link:hover { background: #dbeafe; }
.dark .faq-link:hover { background: #1e40af; }
/* ── EMPTY STATE ── */
.faq-empty {
grid-column: 1 / -1;
text-align: center;
padding: 60px 20px;
color: #9ca3af;
font-size: 14px;
background: #fff;
border: 1px dashed #e5e7eb;
border-radius: 12px;
}
.dark .faq-empty { background: #1f2937; border-color: #374151; }
.faq-empty-icon { font-size: 40px; margin-bottom: 12px; }
</style>
<div class="faq-shell">
{{-- HERO --}}
<div class="faq-hero">
<div class="faq-hero-icon">📖</div>
<div class="faq-hero-txt">
<h1 class="faq-hero-title">{{ __('Ghid rapid AutoCRM') }}</h1>
<p class="faq-hero-sub">{{ __('Toate răspunsurile la un click distanță. Fiecare pagină are propriile hint-uri „?" — sau caută mai jos.') }}</p>
</div>
<div class="faq-hero-stats">
<div class="faq-hero-stat">
<div class="faq-hero-stat-n">{{ $totalHints }}</div>
<div class="faq-hero-stat-l">{{ __('subiecte') }}</div>
</div>
<div class="faq-hero-stat">
<div class="faq-hero-stat-n">{{ count($areas) }}</div>
<div class="faq-hero-stat-l">{{ __('secțiuni') }}</div>
</div>
</div>
</div>
{{-- VIDEO TUTORIAL (dacă e configurat) --}}
@if ($videoEmbed)
<div class="faq-video-card">
<iframe src="{{ $videoEmbed }}"
title="{{ __('Video tutorial') }}"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen></iframe>
</div>
@elseif ($videoRaw)
<div class="faq-video-fallback">
<div class="faq-video-fallback-icon">🎥</div>
<div class="faq-video-fallback-txt">
<h3 class="faq-video-fallback-title">{{ __('Video tutorial') }}</h3>
<p class="faq-video-fallback-sub">
{{ __('URL nerecunoscut — deschide-l direct:') }}
<a href="{{ $videoRaw }}" target="_blank">{{ $videoRaw }}</a>
</p>
</div>
</div>
@elseif ($user?->isAdmin())
<div class="faq-video-fallback">
<div class="faq-video-fallback-icon">🎥</div>
<div class="faq-video-fallback-txt">
<h3 class="faq-video-fallback-title">{{ __('Video tutorial') }}</h3>
<p class="faq-video-fallback-sub">
{{ __('Adaugă un link YouTube/Vimeo în') }}
<a href="{{ url('/app/settings') }}">{{ __('Setări → Liste configurabile') }} </a>
</p>
</div>
</div>
@endif
{{-- CONTROLS --}}
<div class="faq-controls">
<input type="text" class="faq-search" placeholder="{{ __('Caută în ghid...') }}" wire:model.live.debounce.300ms="search">
<div class="faq-toggle">
<span class="faq-toggle-lbl">{{ __('Sugestii pe pagini:') }}</span>
<form method="POST" action="{{ route('hints.toggle') }}" style="display:inline;">
@csrf
<button type="submit" class="faq-btn-toggle {{ $user?->hints_enabled ? 'on' : 'off' }}">
{{ $user?->hints_enabled ? '● ' . __('ACTIVE') : '○ ' . __('INACTIVE') }}
</button>
</form>
<form method="POST" action="{{ route('hints.reset') }}" style="display:inline;">
@csrf
<button type="submit" class="faq-btn-reset" title="{{ __('Aduce înapoi hint-urile ascunse') }}">
{{ __('Resetează') }}
</button>
</form>
</div>
</div>
{{-- GRID --}}
<div class="faq-grid">
@if (empty($grouped))
<div class="faq-empty">
<div class="faq-empty-icon">🔍</div>
{{ __('Nicio potrivire pentru „:q".', ['q' => $search]) }}
</div>
@endif
@foreach ($grouped as $areaKey => $hints)
@php
$area = $areas[$areaKey] ?? null;
$accent = $areaColors[$areaKey] ?? '#6b7280';
@endphp
<div class="faq-card">
<div class="faq-card-hd" style="background:{{ $accent }};">
<span class="faq-card-icon">{{ $area['icon'] ?? '📖' }}</span>
<span class="faq-card-title">{{ $area['label'][$lc] ?? $areaKey }}</span>
<span class="faq-card-badge">{{ count($hints) }}</span>
</div>
<div class="faq-card-body">
@foreach ($hints as $key => $h)
<details class="faq-item">
<summary>{{ $h['title'][$lc] ?? $h['title']['ro'] }}</summary>
<div class="faq-body-txt">
{{ $h['body'][$lc] ?? $h['body']['ro'] }}
@if (! empty($h['next'][$lc]))
<div class="faq-next">{{ $h['next'][$lc] }}</div>
@endif
@if (! empty($h['links']))
<div class="faq-links">
@foreach ($h['links'] as $ln)
<a class="faq-link" href="{{ url($ln['url']) }}">{{ $ln['label_' . $lc] ?? $ln['label_ro'] }}</a>
@endforeach
</div>
@endif
</div>
</details>
@endforeach
</div>
</div>
@endforeach
</div>
</div>
</x-filament-panels::page>