feat: add persona landing pages for IT department, IT support, and MSPs
Adds three "who it's for" pages reachable via a new nav dropdown, each built around a distinct day-to-day workflow rather than a reworded homepage pitch: - /for/it-department — the core admin/engineer audience: drift-fix, Ansible automation, VM provisioning, dashboards - /for/it-support — day-to-day operators: status at a glance, one-click Ack, Wake-on-LAN, scheduled reboots, filterable audit log - /for/msp — managed service providers: Satellite deployments for unreachable client sites, audit trail as client-facing evidence, self-hosted with no per-seat SaaS The MSP page deliberately avoids claiming per-site/per-customer RBAC — verified against netork/models/role.py that permissions are global role-based sets, not site-scoped, and phrased the copy accordingly. Nav.tsx's Docs dropdown logic is extracted into a reusable NavDropdown component (open state, outside-click, route-change-close) instead of being duplicated for the new "Für wen" dropdown, which also links to the existing /nis2 page rather than rebuilding that persona. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d57734767d
commit
2d85aa2e47
@@ -0,0 +1,106 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { LifebuoyIcon } from '@heroicons/react/24/outline'
|
||||
import { useLang } from '../context/LangContext'
|
||||
import { linkify } from '../lib/glossary'
|
||||
|
||||
type Item = { title: string; body: string }
|
||||
|
||||
const SECTION_LABELS: Record<'en' | 'de', { pain: string; features: string }> = {
|
||||
en: { pain: 'Your day today', features: 'Where netOrk helps' },
|
||||
de: { pain: 'Euer Alltag heute', features: 'Wo netOrk hilft' },
|
||||
}
|
||||
|
||||
const PAIN_POINTS: Record<'en' | 'de', Item[]> = {
|
||||
en: [
|
||||
{ title: 'Is this device actually up right now?', body: 'Checking status means opening the vendor UI for that one device — or pinging it yourself and hoping.' },
|
||||
{ title: 'The same manual reboot, over and over', body: 'A flaky AP needs a power cycle every few weeks, and someone has to remember to do it and be there for it.' },
|
||||
{ title: '"Who changed this?" — with no record', body: 'A setting is different than it was yesterday. Nobody can say who touched it, when, or why.' },
|
||||
{ title: 'Full admin access just to fix one ticket', body: 'Resolving a single warning shouldn\'t require the keys to the whole network configuration.' },
|
||||
],
|
||||
de: [
|
||||
{ title: 'Läuft das Gerät gerade wirklich?', body: 'Status prüfen heißt: die Hersteller-UI für genau dieses Gerät öffnen — oder selbst pingen und hoffen.' },
|
||||
{ title: 'Derselbe manuelle Reboot, immer wieder', body: 'Ein zickiger AP braucht alle paar Wochen einen Power-Cycle — und jemand muss daran denken und dafür vor Ort sein.' },
|
||||
{ title: '„Wer hat das geändert?" — ohne Protokoll', body: 'Eine Einstellung ist anders als gestern. Niemand kann sagen, wer sie wann und warum geändert hat.' },
|
||||
{ title: 'Voller Admin-Zugriff nur für ein Ticket', body: 'Eine einzelne Warnung zu beheben sollte nicht den Schlüssel zur gesamten Netzwerkkonfiguration erfordern.' },
|
||||
],
|
||||
}
|
||||
|
||||
const FEATURES: Record<'en' | 'de', Item[]> = {
|
||||
en: [
|
||||
{ title: 'Status at a glance', body: 'Per-device warning system with severity levels (error / warning / info); a dashboard warnings widget surfaces every open issue across sites without hunting per device.' },
|
||||
{ title: 'One-click Ack', body: 'Clears a warning immediately and writes an audit log entry. Config-change warnings accept the current state as the new baseline in the same click.' },
|
||||
{ title: 'Wake-on-LAN', body: 'Saved WOL targets per device, sent via the firewall\'s driver. On-demand "Wake now" or a recurring schedule; save a seen host as a target directly from the DHCP/ARP tabs.' },
|
||||
{ title: 'Scheduled reboots & updates', body: 'Scheduled reboots for OpenWRT APs with per-site concurrency locking, and package updates scheduled or applied with one click.' },
|
||||
{ title: 'Full audit log, filterable', body: 'Every action — who, when, what — filterable by date range, user, action, or resource, exportable to CSV or PDF.' },
|
||||
{ title: 'Roles scoped to the job', body: 'Viewer/operator roles, or a custom permission set, hand out exactly the access support work needs — without granting engineer-level config rights.' },
|
||||
],
|
||||
de: [
|
||||
{ title: 'Status auf einen Blick', body: 'Gerätespezifisches Warnsystem mit Schweregraden (Fehler / Warnung / Info); ein Dashboard-Warnungs-Widget zeigt jedes offene Problem standortübergreifend, ohne pro Gerät zu suchen.' },
|
||||
{ title: 'Ein-Klick-Ack', body: 'Löscht eine Warnung sofort und protokolliert die Aktion im Audit-Log. Config-Change-Warnungen akzeptieren im selben Klick den aktuellen Zustand als neue Baseline.' },
|
||||
{ title: 'Wake-on-LAN', body: 'Gespeicherte WOL-Ziele pro Gerät, gesendet über den Treiber der Firewall. Ein-Klick-„Jetzt wecken" oder wiederkehrender Zeitplan; ein gesehener Host lässt sich direkt aus den DHCP-/ARP-Tabs als Ziel speichern.' },
|
||||
{ title: 'Geplante Reboots & Updates', body: 'Geplante Neustarts für OpenWRT-APs mit standortbezogener Concurrency-Sperre, Paket-Updates geplant oder per Ein-Klick angewendet.' },
|
||||
{ title: 'Vollständiges, filterbares Audit-Log', body: 'Jede Aktion — wer, wann, was — filterbar nach Datumsbereich, Benutzer, Aktion oder Ressource, exportierbar als CSV oder PDF.' },
|
||||
{ title: 'Rollen passend zur Aufgabe', body: 'Betrachter-/Operator-Rollen oder ein eigener Berechtigungssatz geben genau den Zugriff, den Support-Arbeit braucht — ohne Engineer-Rechte für die Konfiguration.' },
|
||||
],
|
||||
}
|
||||
|
||||
export default function ForItSupport() {
|
||||
const { lang, t } = useLang()
|
||||
const labels = SECTION_LABELS[lang]
|
||||
const painPoints = PAIN_POINTS[lang]
|
||||
const features = FEATURES[lang]
|
||||
|
||||
return (
|
||||
<div className="py-16 md:py-24">
|
||||
<div className="max-w-4xl mx-auto px-6">
|
||||
|
||||
<div className="mb-16">
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg bg-sky-600/10">
|
||||
<LifebuoyIcon className="h-5 w-5 text-sky-400" />
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">{t.forItSupport.heading}</h1>
|
||||
<p className="text-base text-slate-400 leading-relaxed max-w-2xl">{linkify(t.forItSupport.sub)}</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-20">
|
||||
<h2 className="text-xl font-semibold text-slate-200 mb-6 pb-2 border-b border-slate-800">
|
||||
{labels.pain}
|
||||
</h2>
|
||||
<div className="grid sm:grid-cols-2 gap-6">
|
||||
{painPoints.map((p) => (
|
||||
<div key={p.title} className="rounded-xl border border-slate-800 bg-slate-900 p-5">
|
||||
<p className="text-sm font-semibold text-slate-200 mb-1.5">{p.title}</p>
|
||||
<p className="text-sm text-slate-500 leading-relaxed">{linkify(p.body)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-20">
|
||||
<h2 className="text-xl font-semibold text-slate-200 mb-6 pb-2 border-b border-slate-800">
|
||||
{labels.features}
|
||||
</h2>
|
||||
<div className="grid sm:grid-cols-2 gap-6">
|
||||
{features.map((f) => (
|
||||
<div key={f.title} className="rounded-xl border border-slate-800 bg-slate-900 p-5">
|
||||
<p className="text-sm font-semibold text-slate-200 mb-1.5">{f.title}</p>
|
||||
<p className="text-sm text-slate-500 leading-relaxed">{linkify(f.body)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-xl border border-slate-800 bg-slate-900 p-8 text-center">
|
||||
<h2 className="text-xl font-semibold text-slate-100 mb-3">{t.forItSupport.cta.heading}</h2>
|
||||
<p className="text-sm text-slate-400 leading-relaxed mb-6 max-w-md mx-auto">{t.forItSupport.cta.body}</p>
|
||||
<Link
|
||||
to="/docs/getting-started"
|
||||
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg bg-sky-600 hover:bg-sky-500 text-white text-sm font-medium transition-colors"
|
||||
>
|
||||
{t.forItSupport.cta.button}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user