06081159b6
Infrastructure for a portal-wide in-app help system:
* Users have hints_enabled (default true) and dismissed_hints (JSON
array) columns. User::shouldSeeHint(key) checks both.
* app/Support/Hints.php — single-source-of-truth registry with 14
pilot hints across Service (5), CRM (3), Depozit (3), Finanțe (3).
Each entry has RO/RU/EN title + body + optional next-step + links.
* <x-hint key="wo.dashboard.overview" /> Blade component renders a
small "?" icon with Alpine.js popover; the popover shows title,
body, next-step, related links and an "X" button that POSTs to
/app/hints/{key}/dismiss.
* HintController handles dismiss (per key), toggle (global on/off)
and reset (clear dismissed + re-enable). Routes are auth:web.
* /app/faq page (Filament Page under Admin group) renders the whole
registry grouped by area with a live search box and buttons to
toggle global hints or reset dismissed ones.
* Wired 3 pilot hints into the WO dashboard: title (overview), Docs
tab PDF preview, and the Chat client card.
Follow-ups: extend registry to cover more pages and add <x-hint>
tags where useful. Filament resource fields can also reuse the same
copy via ->hint()/->helperText().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
65 lines
1.6 KiB
PHP
65 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Tenant\Pages;
|
|
|
|
use App\Support\Hints;
|
|
use Filament\Pages\Page;
|
|
|
|
/**
|
|
* FAQ / help page — renders the entire hints registry grouped by area
|
|
* with a client-side search box. Same content that surfaces contextually
|
|
* in "?" popovers around the app.
|
|
*/
|
|
class Faq extends Page
|
|
{
|
|
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-question-mark-circle';
|
|
|
|
protected string $view = 'filament.tenant.pages.faq';
|
|
|
|
public string $search = '';
|
|
|
|
public static function getNavigationLabel(): string
|
|
{
|
|
return __('nav.label.FAQ & Ghid');
|
|
}
|
|
|
|
public static function getNavigationGroup(): ?string
|
|
{
|
|
return __('nav.group.Admin');
|
|
}
|
|
|
|
protected static ?int $navigationSort = 1;
|
|
|
|
public function getTitle(): string
|
|
{
|
|
return __('FAQ & Ghid utilizator');
|
|
}
|
|
|
|
public function getHeading(): string
|
|
{
|
|
return '';
|
|
}
|
|
|
|
public function getAreas(): array
|
|
{
|
|
return Hints::AREAS;
|
|
}
|
|
|
|
public function getGrouped(): array
|
|
{
|
|
$q = mb_strtolower(trim($this->search));
|
|
$lc = Hints::locale();
|
|
$grouped = Hints::byArea();
|
|
if ($q === '') return $grouped;
|
|
$out = [];
|
|
foreach ($grouped as $area => $hints) {
|
|
$matched = array_filter($hints, function ($h) use ($q, $lc) {
|
|
$t = mb_strtolower(($h['title'][$lc] ?? '') . ' ' . ($h['body'][$lc] ?? ''));
|
|
return str_contains($t, $q);
|
|
});
|
|
if (! empty($matched)) $out[$area] = $matched;
|
|
}
|
|
return $out;
|
|
}
|
|
}
|