feat(hints): auto-inject on every main page via URL→key registry
Registry now covers ~50 hints across Service, CRM, Depozit, Finanțe, Admin, Marketing, Analiză, Shop. Every main tenant page has an entry. New Hints::forPath(\$path) does str_starts_with matching against a curated URL prefix map. First match wins so specific paths (e.g. /work-orders/create) beat broader ones (/work-orders). A single render hook on PAGE_HEADER_ACTIONS_BEFORE looks up the current request path and, if it matches, renders a "?" icon next to the page header actions. Blades that already have <x-hint> tags embedded (WO dashboard, Calendar, Pipeline, Excel wizard) keep those on top of the auto-injected header hint. Net effect: users see "?" icons everywhere in the panel now, and adding coverage for a new page is a 2-line change (registry entry + one URL prefix in forPath). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -242,6 +242,309 @@ class Hints
|
||||
'en' => 'Each stat card is clickable and jumps to the relevant page with filters applied. E.g. "Fișe în lucru" → list filtered by status=in_work. Recomputed on every visit.',
|
||||
],
|
||||
],
|
||||
'service.mechanic_board.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Atelierul meu', 'ru' => 'Мой цех', 'en' => 'My workshop'],
|
||||
'body' => [
|
||||
'ro' => 'Vedere mobile-first pentru mecanic: doar fișele lui active (grupate pe status), butoane mari, actualizare status/kilometraj/foto direct din listă, fără să treci prin edit. Ideal pe tabletă în hala service.',
|
||||
'ru' => 'Мобильный интерфейс для механика: только его активные заказы (по статусу), крупные кнопки, обновление статуса/пробега/фото прямо из списка. Удобно на планшете в цехе.',
|
||||
'en' => 'Mobile-first view for a mechanic: only their active WOs (grouped by status), big buttons, update status/mileage/photos inline without opening edit. Made for tablets on the shop floor.',
|
||||
],
|
||||
],
|
||||
'service.kpi.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'KPI mecanici', 'ru' => 'KPI механиков', 'en' => 'Mechanic KPIs'],
|
||||
'body' => [
|
||||
'ro' => 'Pentru fiecare mecanic, pentru perioada aleasă: nr. fișe închise, ore norm-facturate vs. ore reale, venit generat, marja internă. Culorile roșu/verde arată abaterea de la ținta lunară.',
|
||||
'ru' => 'По каждому механику за период: закрытые заказы, нормо-часы vs. фактические, выручка, внутренняя маржа. Красный/зелёный — отклонение от плана.',
|
||||
'en' => 'Per mechanic for the chosen period: closed WOs, billed vs. actual hours, revenue generated, internal margin. Red/green shows deviation from monthly target.',
|
||||
],
|
||||
],
|
||||
'service.labors.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Norme-ore (catalog manopere)', 'ru' => 'Нормо-часы (каталог работ)', 'en' => 'Labor norms (catalog)'],
|
||||
'body' => [
|
||||
'ro' => 'Catalog cu toate manoperele standard: denumire (RO/RU/EN), timp normat, preț recomandat, categoria. Aici se definesc șabloanele. La adăugarea unei manopere într-o fișă, sistemul completează automat timpul și prețul.',
|
||||
'ru' => 'Каталог стандартных работ: название (RO/RU/EN), норматив времени, рекомендованная цена, категория. При добавлении в заказ время и цена подставляются автоматом.',
|
||||
'en' => 'Standard labor catalog: name (RO/RU/EN), normed time, suggested price, category. Adding a labor to a WO auto-fills time + price.',
|
||||
],
|
||||
],
|
||||
'service.masters.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Tehnicieni (maiștri)', 'ru' => 'Мастера', 'en' => 'Technicians'],
|
||||
'body' => [
|
||||
'ro' => 'Aici gestionezi lista de maiștri: nume, culoare (pentru calendar), tarif orar, marja internă, specializare. Sunt utilizatori cu rol „master" — pot vedea doar fișele proprii în „Atelierul meu".',
|
||||
'ru' => 'Список мастеров: имя, цвет (для календаря), почасовая ставка, маржа, специализация. Это пользователи с ролью «master» — видят только свои заказы в «Мой цех».',
|
||||
'en' => 'Manage master mechanics: name, calendar color, hourly rate, internal margin, specialty. These are users with role "master" — they only see their own WOs in "My workshop".',
|
||||
],
|
||||
],
|
||||
'service.templates.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Șabloane servicii', 'ru' => 'Шаблоны услуг', 'en' => 'Service templates'],
|
||||
'body' => [
|
||||
'ro' => 'Pachete predefinite (ex: „Schimb ulei + filtru", „Diagnoză computerizată"). Din edit fișă → „Aplică șablon" adaugi toate manoperele + piesele deodată. Reduce dublă introducere pentru servicii recurente.',
|
||||
'ru' => 'Готовые пакеты («Замена масла + фильтр», «Компьютерная диагностика»). В заказе — «Применить шаблон» добавляет все работы + запчасти сразу. Уменьшает ручной ввод.',
|
||||
'en' => 'Predefined bundles ("Oil + filter change", "OBD diagnostic"). From WO edit → "Apply template" adds all labor + parts at once. Cuts repetitive data entry.',
|
||||
],
|
||||
],
|
||||
'service.injector.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Protocoale forsunki', 'ru' => 'Протоколы форсунок', 'en' => 'Injector protocols'],
|
||||
'body' => [
|
||||
'ro' => 'Formular specializat pentru diagnostic injectoare (debit/pulverizare/retur pentru fiecare injector). Numărul se generează auto: {PREFIX}-{AN}-{SEQ}. Export PDF cu semnătură pentru client.',
|
||||
'ru' => 'Специализированная форма для диагностики форсунок (расход/распыл/возврат по каждой). Номер: {PREFIX}-{ГОД}-{SEQ}. PDF с подписью для клиента.',
|
||||
'en' => 'Specialized form for injector diagnostics (flow/spray/return per injector). Number auto-generated: {PREFIX}-{YEAR}-{SEQ}. Signed PDF for the customer.',
|
||||
],
|
||||
],
|
||||
'service.bodyshop.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Tinichigerie / Detailing', 'ru' => 'Кузовной / Детейлинг', 'en' => 'Bodyshop / Detailing'],
|
||||
'body' => [
|
||||
'ro' => 'Lucrări separate de service mecanic: reparații caroserie, vopsit, polish, detailing. Deviz + foto înainte/după + status separat. Se leagă opțional de o fișă principală.',
|
||||
'ru' => 'Отдельно от механики: кузов, покраска, полировка, детейлинг. Смета + фото до/после + свой статус. Опционально привязка к главному заказу.',
|
||||
'en' => 'Separate from mechanical service: body repairs, paint, polish, detailing. Quote + before/after photos + own status. Optionally links to a parent WO.',
|
||||
],
|
||||
],
|
||||
'service.tires.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Seturi anvelope', 'ru' => 'Комплекты шин', 'en' => 'Tire sets'],
|
||||
'body' => [
|
||||
'ro' => 'Depozitare sezonieră: set anvelope (4 buc) legat de mașină, dimensiuni, DOT, adâncime protector, locație în depozit. Notificare automată la schimb sezonier pentru clienți.',
|
||||
'ru' => 'Сезонное хранение: комплект (4 шт.) на авто, размеры, DOT, глубина протектора, место на складе. Автонапоминания клиентам о сезонной замене.',
|
||||
'en' => 'Seasonal storage: 4-tire set per vehicle, sizes, DOT code, tread depth, warehouse slot. Auto reminders to clients when the seasonal swap is due.',
|
||||
],
|
||||
],
|
||||
'service.subcontract.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Lucrări terți (subcontract)', 'ru' => 'Работы у подрядчика', 'en' => 'Subcontract jobs'],
|
||||
'body' => [
|
||||
'ro' => 'Când o lucrare pleacă la un partener extern (ex: rectificare bloc). Se leagă de o fișă activă, se înregistrează costul plătit terțului + prețul cerut clientului. Diferența = marja pe subcontract.',
|
||||
'ru' => 'Работа уходит к внешнему партнёру (напр. шлифовка блока). Привязка к заказу, стоимость подрядчика + цена клиенту. Разница = маржа.',
|
||||
'en' => 'When work goes out to an external partner (e.g. head resurfacing). Ties to an active WO — logs cost paid to subcontractor + price charged to client. Delta = subcontract margin.',
|
||||
],
|
||||
],
|
||||
'service.subcontractors.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Subcontractori (parteneri)', 'ru' => 'Подрядчики', 'en' => 'Subcontractors'],
|
||||
'body' => [
|
||||
'ro' => 'Lista partenerilor externi: nume, telefon, specializare (rectificări, geometrie roți, tapițerie). Se atașează la Lucrări terți pentru istoric complet + statistici pe partener.',
|
||||
'ru' => 'Список внешних партнёров: имя, телефон, специализация. Подставляются в «Работы у подрядчика» для истории + статистики.',
|
||||
'en' => 'External partner list: name, phone, specialty (machining, wheel alignment, upholstery). Referenced from Subcontract jobs for history + per-partner stats.',
|
||||
],
|
||||
],
|
||||
|
||||
// CRM extras
|
||||
'crm.calls.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Apeluri client', 'ru' => 'Звонки клиентам', 'en' => 'Customer calls'],
|
||||
'body' => [
|
||||
'ro' => 'Jurnal manual + integrare SIP (dacă e configurată): apel intrat/ieșit, durată, notițe, legarea de un client sau lead. Util pentru follow-up și evaluarea echipei.',
|
||||
'ru' => 'Ручной журнал + интеграция SIP (если настроена): входящие/исходящие, длительность, заметки, привязка к клиенту/лиду. Для follow-up и оценки команды.',
|
||||
'en' => 'Manual log + SIP integration (if configured): inbound/outbound, duration, notes, tied to a client or lead. Useful for follow-up and team review.',
|
||||
],
|
||||
],
|
||||
|
||||
// Depozit extras
|
||||
'depozit.purchases.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'Achiziții de la furnizor', 'ru' => 'Закупки у поставщика', 'en' => 'Supplier purchases'],
|
||||
'body' => [
|
||||
'ro' => 'Documentul de intrare (aviz + factură) al pieselor: furnizor, dată, poziții (piesă + cant + preț cost). La salvare, stocul crește automat și prețul de cost al piesei se actualizează.',
|
||||
'ru' => 'Приходный документ (накладная + счёт): поставщик, дата, позиции (запчасть + кол + цена). При сохранении остаток растёт, себестоимость обновляется.',
|
||||
'en' => 'Goods receipt document (waybill + invoice): supplier, date, lines (part + qty + cost). Saving increases stock and updates part cost.',
|
||||
],
|
||||
],
|
||||
'depozit.suppliers.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'Furnizori', 'ru' => 'Поставщики', 'en' => 'Suppliers'],
|
||||
'body' => [
|
||||
'ro' => 'Fișa furnizorului: nume, cod fiscal, contact, condiții plată. Fiecare Achiziție se leagă aici. Maparea coloanelor de la Import Excel se salvează per furnizor pentru viitor.',
|
||||
'ru' => 'Карточка поставщика: имя, реквизиты, контакт, условия оплаты. Каждая закупка привязывается сюда. Соответствие колонок Excel-импорта запоминается по поставщику.',
|
||||
'en' => 'Supplier card: name, tax ID, contact, payment terms. Every purchase links here. Excel import column mapping is remembered per supplier for next time.',
|
||||
],
|
||||
],
|
||||
'depozit.warehouses.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'Depozite (locații)', 'ru' => 'Склады (локации)', 'en' => 'Warehouses (locations)'],
|
||||
'body' => [
|
||||
'ro' => 'Dacă ai mai multe locații de stocare (ex: „Central", „Punct de lucru 2", „Vitrina"), le definești aici. Fiecare piesă are stoc separat pe depozit. Achizițiile pot merge într-un depozit specific.',
|
||||
'ru' => 'Если несколько мест хранения (напр. «Центральный», «Точка 2», «Витрина») — задай их здесь. Остатки ведутся раздельно. Закупки могут идти в конкретный склад.',
|
||||
'en' => 'If you have multiple storage locations (e.g. "Central", "Site 2", "Showroom"), define them here. Each part has per-warehouse stock. Purchases can target a specific warehouse.',
|
||||
],
|
||||
],
|
||||
'depozit.pricing.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'Coeficienți de preț', 'ru' => 'Ценовые коэффициенты', 'en' => 'Pricing coefficients'],
|
||||
'body' => [
|
||||
'ro' => 'Reguli automate: preț manoperă × coeficient pe clasa mașinii (economy/premium/luxury) × coeficient urgență (normal/urgent). Definite o dată — se aplică automat pe toate fișele noi.',
|
||||
'ru' => 'Автоправила: цена работ × коэфф. класса авто × коэфф. срочности. Настроил один раз — применяется на всех новых заказах.',
|
||||
'en' => 'Auto rules: labor price × vehicle-class coeff × urgency coeff. Set once — applies to all new WOs automatically.',
|
||||
],
|
||||
],
|
||||
'depozit.markup.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'Reguli procentaj (markup)', 'ru' => 'Правила наценки', 'en' => 'Markup rules'],
|
||||
'body' => [
|
||||
'ro' => 'Cât adaugi la costul piesei pentru preț client, în funcție de: categoria piesei, prețul cost (praguri), furnizor. Ex: „Piese sub 100 MDL → +40%, peste → +25%". Se aplică automat la achiziții.',
|
||||
'ru' => 'Наценка от закупки к цене клиента по: категории, ценовому диапазону, поставщику. Пример: «до 100 MDL → +40%, свыше → +25%». Применяется автоматом на закупках.',
|
||||
'en' => 'Cost-to-client markup by: part category, cost thresholds, supplier. E.g. "Under 100 MDL → +40%, above → +25%". Applied automatically on purchases.',
|
||||
],
|
||||
],
|
||||
'depozit.units.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'Unități de măsură', 'ru' => 'Единицы измерения', 'en' => 'Units of measure'],
|
||||
'body' => [
|
||||
'ro' => 'Buc / L / kg / m / set etc., cu denumire în 3 limbi. Se folosesc pe piese și pe achiziții pentru claritate în facturi și avize.',
|
||||
'ru' => 'Шт. / Л / кг / м / компл. — с названием на 3-х языках. Используются в запчастях и закупках для ясности в документах.',
|
||||
'en' => 'Pcs / L / kg / m / set — with names in 3 languages. Used on parts and purchases for clarity on invoices.',
|
||||
],
|
||||
],
|
||||
'depozit.vin_search.overview' => [
|
||||
'area' => 'depozit', 'title' => ['ro' => 'VIN-căutare (piese OEM)', 'ru' => 'VIN-поиск (OEM)', 'en' => 'VIN part search'],
|
||||
'body' => [
|
||||
'ro' => 'Introdu VIN-ul mașinii → AI-ul decodează marca/modelul/anul și sugerează codurile OEM ale pieselor necesare pentru operația căutată (ex: „plăcuțe frână față"). Copiază codul, verifică la furnizori.',
|
||||
'ru' => 'Введи VIN → AI декодирует марку/модель/год и подскажет OEM-коды нужных запчастей (напр. «передние тормозные колодки»). Копируй код и проверяй у поставщиков.',
|
||||
'en' => 'Enter a VIN → AI decodes make/model/year and suggests OEM codes for the requested operation (e.g. "front brake pads"). Copy the code and check with suppliers.',
|
||||
],
|
||||
],
|
||||
|
||||
// Finanțe extras
|
||||
'finante.adjustments.overview' => [
|
||||
'area' => 'finante', 'title' => ['ro' => 'Bonusuri & avansuri', 'ru' => 'Бонусы и авансы', 'en' => 'Bonuses & advances'],
|
||||
'body' => [
|
||||
'ro' => 'Ajustări manuale la salariul unui angajat: bonus (adaugă) sau avans (scade la salariu). Cu dată, sumă, motiv. Se aplică automat la următorul „Închide perioadă" din Salarii.',
|
||||
'ru' => 'Ручные корректировки: бонус (плюс) или аванс (минус). Дата, сумма, причина. Применяются на ближайшем «Закрыть период» в Зарплатах.',
|
||||
'en' => 'Manual salary adjustments: bonus (adds) or advance (deducts). Date, amount, reason. Auto-applied on the next Salaries "Close period".',
|
||||
],
|
||||
],
|
||||
'finante.employees.overview' => [
|
||||
'area' => 'finante', 'title' => ['ro' => 'Angajați (profile financiare)', 'ru' => 'Сотрудники (финансовые профили)', 'en' => 'Employees (finance profiles)'],
|
||||
'body' => [
|
||||
'ro' => 'Fiecare angajat are: tarif orar de bază, marja internă (%), tip contract (procent din manoperă sau salariu fix), CNP/CIF pentru facturi. Datele astea alimentează calculul automat din Salarii.',
|
||||
'ru' => 'У каждого сотрудника: базовая ставка, внутренняя маржа, тип договора (% с работы или оклад), налоговый номер. Эти данные питают авторасчёт зарплат.',
|
||||
'en' => 'Each employee: base hourly rate, internal margin, contract type (% of labor or fixed salary), tax ID. These feed the Salaries auto-calculation.',
|
||||
],
|
||||
],
|
||||
'finante.consolidated.overview' => [
|
||||
'area' => 'finante', 'title' => ['ro' => 'Finanțe consolidat', 'ru' => 'Финансы (сводно)', 'en' => 'Finance (consolidated)'],
|
||||
'body' => [
|
||||
'ro' => 'Vedere pe o singură pagină: încasări zi/săptămână/lună, cheltuieli, salariu de plătit, profit net. Comparație cu perioada anterioară. Ideal la începutul zilei sau pentru manager la sfârșit de lună.',
|
||||
'ru' => 'Одна страница: приход день/неделя/месяц, расход, к выплате, чистая прибыль. Сравнение с прошлым периодом. Для утреннего обзора или отчёта месяца.',
|
||||
'en' => 'Single page overview: income day/week/month, expenses, salaries due, net profit. Compared to prior period. Great for a morning check or end-of-month review.',
|
||||
],
|
||||
],
|
||||
|
||||
// Magazin
|
||||
'shop.orders.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Comenzi online (magazin)', 'ru' => 'Онлайн-заказы (магазин)', 'en' => 'Online orders (shop)'],
|
||||
'body' => [
|
||||
'ro' => 'Comenzi primite din magazin-ul public (subdomeniu tenant). Poți accepta/refuza, marca livrat, genera factură. Stocul scade automat la livrare.',
|
||||
'ru' => 'Заказы из публичного магазина (тенант-поддомен). Принять/отклонить, отметить доставку, счёт. Остаток списывается при доставке.',
|
||||
'en' => 'Orders from the public shop (tenant subdomain). Accept/refuse, mark delivered, generate invoice. Stock decrements on delivery.',
|
||||
],
|
||||
],
|
||||
'shop.customers.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Clienți magazin', 'ru' => 'Клиенты магазина', 'en' => 'Shop customers'],
|
||||
'body' => [
|
||||
'ro' => 'Clienți care s-au înregistrat pe magazin-ul online (separați de baza CRM service). Poți converti într-un client CRM cu 1 click atunci când vine în service.',
|
||||
'ru' => 'Клиенты онлайн-магазина (отдельно от CRM-базы). При приезде в сервис — 1 клик → CRM-клиент.',
|
||||
'en' => 'Customers registered in the online shop (separate from service CRM base). One click converts to a CRM client when they show up at the service.',
|
||||
],
|
||||
],
|
||||
|
||||
// Marketing
|
||||
'marketing.channels.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Canale marketing', 'ru' => 'Маркетинговые каналы', 'en' => 'Marketing channels'],
|
||||
'body' => [
|
||||
'ro' => 'Sursele de leaduri: Google Ads, Facebook, recomandare, walk-in, telefon direct. Fiecare cerere se atribuie unui canal → vezi în Rapoarte care canal aduce cel mai bun ROI.',
|
||||
'ru' => 'Источники лидов: Google Ads, Facebook, рекомендация, walk-in, звонок. Каждая заявка привязывается к каналу → в Отчётах видишь ROI по каналу.',
|
||||
'en' => 'Lead sources: Google Ads, Facebook, referral, walk-in, direct call. Each lead ties to a channel → Reports show which channel has best ROI.',
|
||||
],
|
||||
],
|
||||
'marketing.templates.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Template-uri mesaje', 'ru' => 'Шаблоны сообщений', 'en' => 'Message templates'],
|
||||
'body' => [
|
||||
'ro' => 'Mesaje pre-scrise pentru trimitere rapidă către client: „Fișa e gata", „Confirmare programare", „Ofertă piesă". Suportă variabile ({client.name}, {wo.number}, {eta}). Se folosesc din Chat client sau notificări automate.',
|
||||
'ru' => 'Готовые сообщения: «Заказ готов», «Подтверждение записи», «Оферта на запчасть». Поддерживают переменные ({client.name}, {wo.number}, {eta}).',
|
||||
'en' => 'Pre-written messages: "WO ready", "Booking confirmed", "Part quote". Support variables ({client.name}, {wo.number}, {eta}).',
|
||||
],
|
||||
],
|
||||
|
||||
// Analiză
|
||||
'analytics.recommendations.overview' => [
|
||||
'area' => 'finante', 'title' => ['ro' => 'Recomandări automate', 'ru' => 'Автоматические рекомендации', 'en' => 'Auto recommendations'],
|
||||
'body' => [
|
||||
'ro' => 'Sistemul analizează activitatea și îți spune: „Piese cu stoc mort de X luni", „Manopere neprofitabile", „Clienți inactivi > 6 luni". Fiecare are un buton de acțiune (ex: „Trimite ofertă").',
|
||||
'ru' => 'Система анализирует и подсказывает: «Мёртвый сток X месяцев», «Убыточные работы», «Клиенты 6+ мес. без визитов». Кнопка действия рядом (напр. «Отправить оффер»).',
|
||||
'en' => 'The system analyzes activity and suggests: "Dead stock X months", "Unprofitable labor", "Clients inactive 6+ months". Each has an action button (e.g. "Send offer").',
|
||||
],
|
||||
],
|
||||
'analytics.ai.overview' => [
|
||||
'area' => 'finante', 'title' => ['ro' => 'Asistent AI', 'ru' => 'AI-ассистент', 'en' => 'AI assistant'],
|
||||
'body' => [
|
||||
'ro' => 'Întreabă în limbaj natural: „Cât am câștigat luna trecută?", „Care e piesa cea mai vândută la BMW-uri?", „Ce mecanic e cel mai productiv?". AI-ul răspunde din datele tale, cu link-uri către raportul relevant.',
|
||||
'ru' => 'Спрашивай на естественном языке: «Сколько заработал в прошлом месяце?», «Какая запчасть чаще продаётся на BMW?», «Кто самый продуктивный механик?». AI отвечает по твоим данным + ссылки на отчёты.',
|
||||
'en' => 'Ask in plain language: "How much did I earn last month?", "Best-selling part for BMWs?", "Most productive mechanic?". AI answers from your data with links to relevant reports.',
|
||||
],
|
||||
],
|
||||
'analytics.workload.overview' => [
|
||||
'area' => 'finante', 'title' => ['ro' => 'Încărcare STO', 'ru' => 'Загрузка СТО', 'en' => 'Workshop load'],
|
||||
'body' => [
|
||||
'ro' => 'Grafic pe post × zi cu ore rezervate + capacitate. Roșu = supra-încărcat, verde = liber. Ideal pentru planificarea programărilor și evitarea aglomerării unui maistru.',
|
||||
'ru' => 'График по посту × день: занятые часы + мощность. Красный — перегруз, зелёный — свободно. Помогает планировать записи.',
|
||||
'en' => 'Chart per post × day: booked hours + capacity. Red = overloaded, green = free. Helps schedule bookings without overloading a master.',
|
||||
],
|
||||
],
|
||||
|
||||
// Admin
|
||||
'admin.users.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Utilizatori (echipa)', 'ru' => 'Пользователи (команда)', 'en' => 'Users (team)'],
|
||||
'body' => [
|
||||
'ro' => 'Invită oameni pe email — primesc link de acceptare + parolă temporară. Alocare rol (owner/admin/master/accountant/receptionist) → rolul definește ce văd și ce pot modifica. Dezactivarea unui user îl blochează fără să șterge datele.',
|
||||
'ru' => 'Приглашай по email — пользователь получает ссылку + временный пароль. Роль (owner/admin/master/accountant/receptionist) — определяет права. Деактивация блокирует без удаления данных.',
|
||||
'en' => 'Invite people via email — they get an accept link + temp password. Role (owner/admin/master/accountant/receptionist) sets what they can see + change. Deactivating blocks access without deleting data.',
|
||||
],
|
||||
],
|
||||
'admin.roles.overview' => [
|
||||
'area' => 'crm', 'title' => ['ro' => 'Roluri & drepturi', 'ru' => 'Роли и права', 'en' => 'Roles & permissions'],
|
||||
'body' => [
|
||||
'ro' => 'Fiecare rol are un set de permisiuni granulare (poate vedea marja internă? poate șterge fișe? poate exporta rapoarte?). Owner-ul are toate. Poți crea roluri custom pentru cazuri speciale.',
|
||||
'ru' => 'У каждой роли — набор гранулярных прав (видит внутреннюю маржу? может удалять? экспортировать?). У Owner — все. Можно создать кастомные роли.',
|
||||
'en' => 'Each role has granular permissions (can see internal margin? can delete WOs? can export reports?). Owner has all. You can create custom roles for edge cases.',
|
||||
],
|
||||
],
|
||||
'admin.posts.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Posturi de lucru', 'ru' => 'Посты (рабочие места)', 'en' => 'Work posts'],
|
||||
'body' => [
|
||||
'ro' => 'Locurile fizice unde se face lucrarea: „Elevator 1", „Elevator 2", „Zona geometrie", „Vopsitorie". Fiecare post are un maistru default (opțional). Se folosesc în Calendar pentru gruparea programărilor.',
|
||||
'ru' => 'Физические места работ: «Подъёмник 1», «Развал-схождение», «Покраска». У поста может быть мастер по умолчанию. Используются в Календаре для группировки.',
|
||||
'en' => 'Physical work bays: "Lift 1", "Alignment", "Paint booth". Each post can have a default master. Used in Calendar to group appointments.',
|
||||
],
|
||||
],
|
||||
'admin.settings.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Setări service', 'ru' => 'Настройки сервиса', 'en' => 'Service settings'],
|
||||
'body' => [
|
||||
'ro' => 'Config-ul general al service-ului: nume, logo, culoare temă, program de lucru, adresă, telefon public, moneda, contul bancar pentru facturi. Modificările sunt vizibile imediat pentru toți userii.',
|
||||
'ru' => 'Общий конфиг сервиса: имя, лого, цвет темы, график, адрес, телефон, валюта, банк для счетов. Изменения видны всем сразу.',
|
||||
'en' => 'Service-wide config: name, logo, theme color, working hours, address, public phone, currency, bank account for invoices. Changes are visible to everyone immediately.',
|
||||
],
|
||||
],
|
||||
'admin.integrations.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Integrări (Telegram/WhatsApp/Google/Facebook)', 'ru' => 'Интеграции', 'en' => 'Integrations'],
|
||||
'body' => [
|
||||
'ro' => 'Activează canale: Telegram bot (token de la @BotFather), WhatsApp Business (token Facebook), Google Ads, Facebook Lead Ads. După activare, mesajele/lead-urile intră automat în CRM.',
|
||||
'ru' => 'Активируй каналы: Telegram-бот (токен от @BotFather), WhatsApp Business (Facebook), Google Ads, Facebook Lead Ads. После активации всё уходит в CRM автоматом.',
|
||||
'en' => 'Enable channels: Telegram bot (token from @BotFather), WhatsApp Business (Facebook), Google Ads, Facebook Lead Ads. Once enabled, messages/leads flow into CRM automatically.',
|
||||
],
|
||||
],
|
||||
'admin.tokens.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'API Tokens', 'ru' => 'API-токены', 'en' => 'API tokens'],
|
||||
'body' => [
|
||||
'ro' => 'Token-uri pentru integrări externe (aplicații mobile, script-uri, terți). Fiecare token are un nume + drepturi. Tokenul se afișează O SINGURĂ DATĂ la creare — copiază-l imediat.',
|
||||
'ru' => 'Токены для внешних интеграций (мобильные приложения, скрипты). У каждого — имя + права. Токен показывается ОДИН РАЗ при создании — копируй сразу.',
|
||||
'en' => 'Tokens for external integrations (mobile apps, scripts, 3rd parties). Each has a name + permissions. The token is shown ONCE at creation — copy it right away.',
|
||||
],
|
||||
],
|
||||
'admin.backup.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Backup date', 'ru' => 'Резервные копии', 'en' => 'Data backup'],
|
||||
'body' => [
|
||||
'ro' => 'Descarcă un snapshot complet al datelor tenantului (DB + fișiere media) sub formă de arhivă. Recomandat: o dată pe lună. Se poate importa înapoi manual (contactează suport).',
|
||||
'ru' => 'Скачивай снапшот всех данных (БД + медиа) архивом. Рекомендуется раз в месяц. Восстановление — через поддержку.',
|
||||
'en' => 'Download a full snapshot of your tenant data (DB + media files) as an archive. Recommended monthly. Restore is manual via support.',
|
||||
],
|
||||
],
|
||||
'admin.activity.overview' => [
|
||||
'area' => 'service', 'title' => ['ro' => 'Jurnal activitate', 'ru' => 'Журнал активности', 'en' => 'Activity log'],
|
||||
'body' => [
|
||||
'ro' => 'Audit-log complet: cine, ce, când. Utile pentru investigație (ex: „cine a șters fișa X?"). Filtrează pe user, pe entitate, pe interval. Se păstrează 12 luni.',
|
||||
'ru' => 'Полный аудит: кто, что, когда. Полезно для расследований («кто удалил заказ X?»). Фильтры: пользователь, сущность, период. Хранится 12 месяцев.',
|
||||
'en' => 'Full audit log: who, what, when. Great for investigating ("who deleted WO X?"). Filter by user, entity, period. Retained 12 months.',
|
||||
],
|
||||
],
|
||||
|
||||
'finante.expenses.overview' => [
|
||||
'area' => 'finante',
|
||||
'title' => [
|
||||
@@ -411,6 +714,90 @@ class Hints
|
||||
return static::all()[$key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL path → hint key map. Used by the tenant panel render hook to
|
||||
* auto-inject a "?" on top of any page that has a matching entry.
|
||||
* Order matters — first match wins, so put specific paths before
|
||||
* broader ones. Paths are matched with str_starts_with().
|
||||
*/
|
||||
public static function forPath(string $path): ?string
|
||||
{
|
||||
$path = trim($path, '/');
|
||||
$map = [
|
||||
// Service / Work orders
|
||||
'app/work-orders/create' => 'wo.create.overview',
|
||||
'app/work-orders' => 'wo.list.overview',
|
||||
'app/mechanic-board' => 'service.mechanic_board.overview',
|
||||
'app/mechanic-kpi' => 'service.kpi.overview',
|
||||
'app/labors' => 'service.labors.overview',
|
||||
'app/masters' => 'service.masters.overview',
|
||||
'app/service-templates' => 'service.templates.overview',
|
||||
'app/injector-protocols' => 'service.injector.overview',
|
||||
'app/bodyshop-jobs' => 'service.bodyshop.overview',
|
||||
'app/tire-sets' => 'service.tires.overview',
|
||||
'app/subcontract-jobs' => 'service.subcontract.overview',
|
||||
'app/subcontractors' => 'service.subcontractors.overview',
|
||||
|
||||
// CRM
|
||||
'app/clients' => 'crm.clients.overview',
|
||||
'app/vehicles' => 'crm.vehicles.overview',
|
||||
'app/leads' => 'crm.leads.overview',
|
||||
'app/deals' => 'crm.pipeline.overview',
|
||||
'app/pipeline' => 'crm.pipeline.overview',
|
||||
'app/calendar-board' => 'crm.calendar.overview',
|
||||
'app/appointments' => 'crm.calendar.overview',
|
||||
'app/calls' => 'crm.calls.overview',
|
||||
|
||||
// Depozit
|
||||
'app/parts' => 'depozit.parts.overview',
|
||||
'app/purchases' => 'depozit.purchases.overview',
|
||||
'app/suppliers' => 'depozit.suppliers.overview',
|
||||
'app/warehouses' => 'depozit.warehouses.overview',
|
||||
'app/pricing-coefficients' => 'depozit.pricing.overview',
|
||||
'app/markup-rules' => 'depozit.markup.overview',
|
||||
'app/units' => 'depozit.units.overview',
|
||||
'app/scanner' => 'depozit.scanner.usage',
|
||||
'app/vin-search' => 'depozit.vin_search.overview',
|
||||
'app/excel-import-wizard' => 'depozit.excel.import',
|
||||
|
||||
// Finanțe
|
||||
'app/payments' => 'finante.payments.overview',
|
||||
'app/expenses' => 'finante.expenses.overview',
|
||||
'app/payroll-runs' => 'finante.salaries.overview',
|
||||
'app/payroll-adjustments' => 'finante.adjustments.overview',
|
||||
'app/employee-profiles' => 'finante.employees.overview',
|
||||
'app/reports' => 'finante.reports.overview',
|
||||
'app/finance' => 'finante.consolidated.overview',
|
||||
|
||||
// Magazin
|
||||
'app/online-orders' => 'shop.orders.overview',
|
||||
'app/shop-customers' => 'shop.customers.overview',
|
||||
|
||||
// Marketing
|
||||
'app/marketing-channels' => 'marketing.channels.overview',
|
||||
'app/message-templates' => 'marketing.templates.overview',
|
||||
|
||||
// Analiză
|
||||
'app/recommendations' => 'analytics.recommendations.overview',
|
||||
'app/ai-assistant' => 'analytics.ai.overview',
|
||||
'app/workload' => 'analytics.workload.overview',
|
||||
|
||||
// Admin
|
||||
'app/users' => 'admin.users.overview',
|
||||
'app/roles' => 'admin.roles.overview',
|
||||
'app/posts' => 'admin.posts.overview',
|
||||
'app/settings' => 'admin.settings.overview',
|
||||
'app/integrations' => 'admin.integrations.overview',
|
||||
'app/api-tokens' => 'admin.tokens.overview',
|
||||
'app/backup' => 'admin.backup.overview',
|
||||
'app/activities' => 'admin.activity.overview',
|
||||
];
|
||||
foreach ($map as $prefix => $key) {
|
||||
if (str_starts_with($path, $prefix)) return $key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Group all hints by area, preserving insertion order. */
|
||||
public static function byArea(): array
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user