m's call 2026-05-19: the /files/hl-patents-style.dotm link on the
anonymous frontpage shouldn't tempt visitors to try downloading. The
/files/{filename} route IS already auth-gated (302 to /login on
anon click), and the macro-update endpoint at /patentstyle/* stays
public for the in-Word update logic per m's note ('with knowledge
of the direct source link it needs to be available').
Authenticated users never see this page anyway — handleRootPage 302s
them to /dashboard. So removing the section costs them nothing and
removes the obvious affordance for anon visitors. ICON_DOWNLOAD
const dropped along with it.
The Downloads page itself (/downloads + Sidebar nav entry) stays —
that's auth-gated and works for logged-in users.
Leftover surface: /patentstyle/HL-Patents-Style.dotm is still anon-
downloadable (necessary for the Word macro's auto-update poll).
That's m's stated requirement — flagged as the known leak path for
anyone who knows the URL.
132 lines
8.9 KiB
TypeScript
132 lines
8.9 KiB
TypeScript
import { h } from "./jsx";
|
|
import { Sidebar } from "./components/Sidebar";
|
|
import { Footer } from "./components/Footer";
|
|
import { PWAHead } from "./components/PWAHead";
|
|
import { FIRM } from "./branding";
|
|
|
|
const ICON_BOOK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/><path d="M8 7h6"/><path d="M8 11h4"/></svg>';
|
|
const ICON_FILE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>';
|
|
const ICON_FOLDER = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
|
|
const ICON_CALC = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="14" x2="8" y2="14.01"/><line x1="12" y1="14" x2="12" y2="14.01"/><line x1="16" y1="14" x2="16" y2="14.01"/><line x1="8" y1="18" x2="16" y2="18"/></svg>';
|
|
const ICON_CLOCK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>';
|
|
const ICON_GLOSSAR = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>';
|
|
const ICON_TABLE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/></svg>';
|
|
const ICON_CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>';
|
|
const ICON_BUILDING = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18"/><path d="M5 21V5a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v16"/><path d="M16 9h3a2 2 0 0 1 2 2v10"/><path d="M9 7h2"/><path d="M9 11h2"/><path d="M9 15h2"/></svg>';
|
|
|
|
export function renderIndex(): string {
|
|
return "<!DOCTYPE html>" + (
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#BFF355" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
|
<PWAHead />
|
|
<title data-i18n="index.title">{`Paliad — Patentwissen für ${FIRM}`}</title>
|
|
<link rel="stylesheet" href="/assets/global.css" />
|
|
</head>
|
|
<body className="has-sidebar">
|
|
<Sidebar currentPath="/" authenticated={false} />
|
|
|
|
<main>
|
|
<section className="hero">
|
|
<div className="container">
|
|
<h1>Patent Litigation<br /><span className="hero-accent" data-i18n="index.hero.accent">{`für ${FIRM}`}</span></h1>
|
|
<p className="hero-sub" data-i18n="index.hero.sub">
|
|
{`Administration, Knowledge und Tools für das ${FIRM} Patent-Team.`}
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="sections">
|
|
<div className="container">
|
|
<div className="grid">
|
|
<div className="card">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_BOOK }} />
|
|
<h2 data-i18n="index.guides.title">Leitfäden</h2>
|
|
<p data-i18n="index.guides.desc">Praxisleitfäden zu Verfahren vor dem EPA, BPatG und UPC. Schritt-für-Schritt-Anleitungen für typische Workflows.</p>
|
|
</div>
|
|
|
|
<div className="card">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_FILE }} />
|
|
<h2 data-i18n="index.templates.title">Vorlagen</h2>
|
|
<p data-i18n="index.templates.desc">{`Standardisierte Vorlagen für Schriftsätze, Korrespondenz und interne Dokumente. ${FIRM} Patents Style Guide.`}</p>
|
|
</div>
|
|
|
|
<div className="card">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_FOLDER }} />
|
|
<h2 data-i18n="index.documents.title">Dokumente</h2>
|
|
<p data-i18n="index.documents.desc">Referenzmaterialien, Checklisten und Arbeitshilfen für den Praxisalltag im Patentrecht.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="sections">
|
|
<div className="container">
|
|
<h3 className="section-heading" data-i18n="index.tools">Werkzeuge</h3>
|
|
<div className="grid grid-2">
|
|
<a href="/tools/kostenrechner" className="card card-link">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_CALC }} />
|
|
<h2 data-i18n="index.cost.title">Kostenrechner</h2>
|
|
<p data-i18n="index.cost.desc">Schätzung der Verfahrenskosten für DE-Gerichte, UPC und EPA-Verfahren. Gerichts- und Anwaltskosten auf einen Blick.</p>
|
|
</a>
|
|
|
|
<a href="/tools/fristenrechner" className="card card-link">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_CLOCK }} />
|
|
<h2 data-i18n="index.deadline.title">Fristenrechner</h2>
|
|
<p data-i18n="index.deadline.desc">Berechnung von Verfahrensfristen für UPC-, deutsche und EPA-Verfahren mit Feiertags-Anpassung.</p>
|
|
</a>
|
|
|
|
<a href="/glossary" className="card card-link">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_GLOSSAR }} />
|
|
<h2 data-i18n="index.glossar.title">Patentglossar</h2>
|
|
<p data-i18n="index.glossar.desc">Zweisprachiges DE/EN-Glossar der wichtigsten Begriffe im Patentrecht. Durchsuchbar nach Kategorien.</p>
|
|
</a>
|
|
|
|
<a href="/tools/gebuehrentabellen" className="card card-link">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_TABLE }} />
|
|
<h2 data-i18n="index.gebuehren.title">Gebührentabellen</h2>
|
|
<p data-i18n="index.gebuehren.desc">Interaktive Gebührentabellen für GKG, RVG, UPC, EPA und PatKostG. Streitwert eingeben, Gebühr ablesen.</p>
|
|
</a>
|
|
|
|
<a href="/checklists" className="card card-link">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_CHECK }} />
|
|
<h2 data-i18n="index.checklisten.title">Checklisten</h2>
|
|
<p data-i18n="index.checklisten.desc">Interaktive Checklisten für UPC-, DE- und EPA-Verfahren. Fortschritt wird lokal gespeichert.</p>
|
|
</a>
|
|
|
|
<a href="/courts" className="card card-link">
|
|
<div className="card-icon" dangerouslySetInnerHTML={{ __html: ICON_BUILDING }} />
|
|
<h2 data-i18n="index.gerichte.title">Gerichtsverzeichnis</h2>
|
|
<p data-i18n="index.gerichte.desc">Gerichte, UPC-Kammern und Patentämter auf einen Blick — mit Adressen, Einreichungshinweisen und Sprachen.</p>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="offices">
|
|
<div className="container">
|
|
<h3 data-i18n="index.offices">Standorte</h3>
|
|
<div className="office-list">
|
|
<span data-i18n="index.office.munich">München</span>
|
|
<span data-i18n="index.office.duesseldorf">Düsseldorf</span>
|
|
<span data-i18n="index.office.hamburg">Hamburg</span>
|
|
<span data-i18n="index.office.amsterdam">Amsterdam</span>
|
|
<span data-i18n="index.office.london">London</span>
|
|
<span data-i18n="index.office.paris">Paris</span>
|
|
<span data-i18n="index.office.milan">Mailand</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<Footer />
|
|
<script src="/assets/index.js"></script>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|