Files
website/src/pages/ForItSupport.tsx
T
Christian ManivongandClaude Opus 5.5 8a1cf7b2b6
CI / TypeScript — type-check (push) Successful in 19s
CI / Publish — build & push image (push) Skipped
CI / TypeScript — type-check (pull_request) Successful in 17s
CI / Publish — build & push image (pull_request) Skipped
fix: usable on phones — menu, no sideways scrolling, whole roadmap intro
- The navigation had no mobile layout: every page was 413px wider than a
  phone. Below lg the links now sit behind a menu button, grouped like the
  desktop dropdowns; the menu closes on navigation.
- Glossary tooltips were invisible but still laid out, so a term near the
  right edge widened the page. Hidden tooltips no longer take up space;
  they show on hover and on keyboard focus as before.
- Long German words in page headings ("produktionstauglich",
  "Konfigurationstiefe") overflowed at 360px; headings start a size smaller
  on phones.
- The roadmap intro dropped everything after its second "NIS2" ("…the
  baseline requirements of"); it is split at the first one only now.

Checked at 360, 390 and 768px on every page: no horizontal overflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:52:13 +02:00

111 lines
7.8 KiB
TypeScript

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.' },
{ title: 'Problems reach you on Signal', body: 'Failed devices, dead tunnels, expiring certificates — one message per outage instead of one per device, quiet hours per person, and any kind of message muted with one click.' },
{ title: 'Service checks every minute', body: 'DNS, time servers, VPN tunnels, core daemons and gateways are checked about once a minute, derived from what netOrk already knows — a dead resolver shows up in minutes, not at the next ticket.' },
],
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.' },
{ title: 'Probleme kommen per Signal', body: 'Ausgefallene Geräte, tote Tunnel, ablaufende Zertifikate — eine Nachricht pro Ausfall statt einer pro Gerät, Ruhezeiten pro Person, und jede Nachrichtenart mit einem Klick stumm.' },
{ title: 'Service-Checks jede Minute', body: 'DNS, Zeitserver, VPN-Tunnel, Kerndienste und Gateways werden etwa einmal pro Minute geprüft, abgeleitet aus dem, was netOrk ohnehin weiß — ein toter Resolver fällt in Minuten auf, nicht erst beim nächsten Ticket.' },
],
}
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-3xl sm: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>
)
}