feat(faq): visual redesign — hero, chip toggles, 2-col colored cards

Replaced the flat vertical list with:
- Hero strip (gradient blue) with title, subtitle, and 2 stat pills
  showing total topics + section count
- Controls bar in a card: search input with inline icon, pill-shaped
  toggle button (green when hints ON), reset button with icon
- 2-column responsive grid of area cards. Each card has a colored
  header (service=blue, crm=purple, depozit=amber, finante=green)
  with icon + name + count badge
- Details/summary items use +/− indicators, tinted background when
  open, hover state; body has pill-styled links and green next-step
- Full dark-mode support
- Empty state with search icon

Same content, much easier to scan and looks like a proper help center.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 10:43:33 +00:00
parent dbac930523
commit cae2904c76
3 changed files with 259 additions and 54 deletions
+5
View File
@@ -151,6 +151,7 @@
"Adresă IP": "IP address",
"Adresă email": "Email address",
"Adresă livrare:": "Delivery address:",
"Aduce înapoi hint-urile ascunse": "Bring back dismissed hints",
"Advance": "Advance",
"Aer condiționat": "Air conditioning",
"Afișează detalii marjă la procesele calculate": "Show margin details in calculations",
@@ -936,6 +937,7 @@
"Generez ZIP...": "Generating ZIP...",
"Gestionează tokene API": "Manage API tokens",
"Gestionează utilizatori (creează/blochează)": "Manage users (create/block)",
"Ghid rapid AutoCRM": "AutoCRM quick guide",
"Global": "Global",
"Gol — trage un card aici": "Empty — drop a card here",
"Google Maps": "Google Maps",
@@ -2057,6 +2059,7 @@
"Toate plățile": "All payments",
"Toate produsele": "All products",
"Toate rolurile": "All roles",
"Toate răspunsurile la un click distanță. Fiecare pagină are propriile hint-uri „?\" — sau caută mai jos.": "All answers a click away. Every page has its own \"?\" hints — or search below.",
"Toate statusurile": "All statuses",
"Toate timpurile": "All time",
"Token generat!": "Token generated!",
@@ -2512,11 +2515,13 @@
"salarii": "salaries",
"salariu": "salary",
"sau": "or",
"secțiuni": "sections",
"set anvelope": "tire set",
"seturi anvelope": "tire sets",
"site": "Website",
"subcontractor": "subcontractor",
"subcontractori": "subcontractors",
"subiecte": "topics",
"săptămâna curentă": "current week",
"tehnician": "technician",
"tehnicieni": "technicians",
+5
View File
@@ -151,6 +151,7 @@
"Adresă IP": "IP-адрес",
"Adresă email": "Email",
"Adresă livrare:": "Адрес доставки:",
"Aduce înapoi hint-urile ascunse": "Вернуть скрытые подсказки",
"Advance": "Аванс",
"Aer condiționat": "Кондиционер",
"Afișează detalii marjă la procesele calculate": "Показать детали маржи в расчётах",
@@ -936,6 +937,7 @@
"Generez ZIP...": "Создаю ZIP...",
"Gestionează tokene API": "Управление API-токенами",
"Gestionează utilizatori (creează/blochează)": "Управление пользователями (создание/блокировка)",
"Ghid rapid AutoCRM": "Быстрый гид AutoCRM",
"Global": "Глобально",
"Gol — trage un card aici": "Пусто — перетащите карточку сюда",
"Google Maps": "Google Maps",
@@ -2057,6 +2059,7 @@
"Toate plățile": "Все платежи",
"Toate produsele": "Все товары",
"Toate rolurile": "Все роли",
"Toate răspunsurile la un click distanță. Fiecare pagină are propriile hint-uri „?\" — sau caută mai jos.": "Все ответы в одном клике. У каждой страницы свои подсказки «?» — или ищи ниже.",
"Toate statusurile": "Все статусы",
"Toate timpurile": "За всё время",
"Token generat!": "Токен создан!",
@@ -2512,11 +2515,13 @@
"salarii": "зарплаты",
"salariu": "зарплата",
"sau": "или",
"secțiuni": "разделов",
"set anvelope": "комплект шин",
"seturi anvelope": "комплекты шин",
"site": "Сайт",
"subcontractor": "субподрядчик",
"subcontractori": "субподрядчики",
"subiecte": "тем",
"săptămâna curentă": "текущая неделя",
"tehnician": "техник",
"tehnicieni": "техники",
@@ -4,73 +4,266 @@
$areas = $this->getAreas();
$grouped = $this->getGrouped();
$user = auth()->user();
$totalHints = collect($grouped)->sum(fn ($g) => count($g));
// Distinct accent color per area for card headers
$areaColors = [
'service' => '#0ea5e9',
'crm' => '#8b5cf6',
'depozit' => '#f59e0b',
'finante' => '#10b981',
];
@endphp
<style>
.faq-shell { max-width: 960px; margin: 0 auto; }
.faq-top { display: flex; gap: 12px; align-items: center; margin-bottom: 20px; flex-wrap: wrap; }
.faq-search { flex: 1; min-width: 260px; padding: 10px 14px; border: 1px solid #e5e7eb; border-radius: 8px; font-size: 14px; }
.faq-shell { max-width: 1200px; margin: 0 auto; }
/* ── 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-section { margin-bottom: 32px; }
.faq-section-hd { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; font-size: 15px; font-weight: 600; color: #111; }
.faq-section-hd .faq-icon { font-size: 20px; }
.faq-item { border: 1px solid #e5e7eb; border-radius: 8px; margin-bottom: 8px; overflow: hidden; }
.faq-item summary { padding: 12px 16px; cursor: pointer; font-weight: 500; font-size: 14px; list-style: none; display: flex; justify-content: space-between; align-items: center; background: #fafafa; user-select: none; }
.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(2, 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: 12px; }
.faq-item[open] summary { background: #eff6ff; }
.faq-item[open] summary::after { content: '▴'; }
.faq-body { padding: 14px 16px; font-size: 13px; line-height: 1.5; color: #374151; }
.faq-next { color: #059669; font-size: 12px; margin-top: 8px; }
.faq-links { margin-top: 10px; display: flex; gap: 12px; flex-wrap: wrap; }
.faq-links a { font-size: 12px; color: #2563eb; text-decoration: none; }
.faq-empty { color: #9ca3af; text-align: center; padding: 40px 20px; font-size: 14px; }
.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">
<div class="faq-top">
{{-- 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>
{{-- 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>{{ __('Sugestii pe pagini:') }}</span>
<span class="faq-toggle-lbl">{{ __('Sugestii pe pagini:') }}</span>
<form method="POST" action="{{ route('hints.toggle') }}" style="display:inline;">
@csrf
<button type="submit" style="padding:6px 12px;border-radius:6px;border:1px solid #d1d5db;background:{{ $user?->hints_enabled ? '#10b981' : '#f3f4f6' }};color:{{ $user?->hints_enabled ? '#fff' : '#374151' }};cursor:pointer;font-size:12px;font-weight:500;">
{{ $user?->hints_enabled ? __('ACTIVE') : __('INACTIVE') }}
<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" style="padding:6px 12px;border-radius:6px;border:1px solid #d1d5db;background:#fff;color:#374151;cursor:pointer;font-size:12px;">
{{ __('Resetează') }}
<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">{{ __('Nicio potrivire pentru „:q".', ['q' => $search]) }}</div>
<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; @endphp
<div class="faq-section">
<div class="faq-section-hd">
<span class="faq-icon">{{ $area['icon'] ?? '📖' }}</span>
<span>{{ $area['label'][$lc] ?? $areaKey }}</span>
<span style="color:#9ca3af;font-weight:400;font-size:12px;">({{ count($hints) }})</span>
@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">
<div class="faq-body-txt">
{{ $h['body'][$lc] ?? $h['body']['ro'] }}
@if (! empty($h['next'][$lc]))
<div class="faq-next"> {{ $h['next'][$lc] }}</div>
<div class="faq-next">{{ $h['next'][$lc] }}</div>
@endif
@if (! empty($h['links']))
<div class="faq-links">
@foreach ($h['links'] as $ln)
<a href="{{ url($ln['url']) }}">{{ $ln['label_' . $lc] ?? $ln['label_ro'] }} </a>
<a class="faq-link" href="{{ url($ln['url']) }}">{{ $ln['label_' . $lc] ?? $ln['label_ro'] }}</a>
@endforeach
</div>
@endif
@@ -78,6 +271,8 @@
</details>
@endforeach
</div>
</div>
@endforeach
</div>
</div>
</x-filament-panels::page>