feat: add legal pages and improve site navigation

Introduce polished legal/support/contact/careers/about pages with production-ready content and update header/footer links to point to real routes and external resources.
This commit is contained in:
Gekon Dev
2026-05-09 20:11:26 +03:00
parent 80f98282e7
commit a16f6a5c58
13 changed files with 1148 additions and 24 deletions
+37 -13
View File
@@ -1,22 +1,38 @@
import { useI18n } from "@/i18n/context"; import { useI18n } from "@/i18n/context";
import type { TranslationKeys } from "@/i18n/translations"; import type { TranslationKeys } from "@/i18n/translations";
const columns: { titleKey: TranslationKeys; linkKeys: TranslationKeys[] }[] = [ const columns: { titleKey: TranslationKeys; links: { key: TranslationKeys; href: string }[] }[] = [
{ {
titleKey: "footer_product", titleKey: "footer_product",
linkKeys: ["footer_technology", "footer_performance", "footer_pricing"], links: [
{ key: "footer_technology", href: "/#technology" },
{ key: "footer_performance", href: "https://uptime.pvenode.ru/" },
{ key: "footer_pricing", href: "/#pricing" },
],
}, },
{ {
titleKey: "footer_company", titleKey: "footer_company",
linkKeys: ["footer_about", "footer_blog", "footer_careers"], links: [
{ key: "footer_about", href: "/about" },
{ key: "footer_blog", href: "/about" },
{ key: "footer_careers", href: "/careers" },
],
}, },
{ {
titleKey: "footer_support", titleKey: "footer_support",
linkKeys: ["footer_help", "footer_contact", "footer_faq"], links: [
{ key: "footer_help", href: "/support" },
{ key: "footer_contact", href: "/contacts" },
{ key: "footer_faq", href: "/#faq" },
],
}, },
{ {
titleKey: "footer_legal", titleKey: "footer_legal",
linkKeys: ["footer_privacy", "footer_terms"], links: [
{ key: "footer_privacy", href: "/privacy-policy" },
{ key: "footer_user_agreement", href: "/user-agreement" },
{ key: "footer_terms", href: "/terms-of-use" },
],
}, },
]; ];
@@ -46,13 +62,15 @@ export function Footer() {
<div key={col.titleKey}> <div key={col.titleKey}>
<h4 className="mb-3 text-sm font-semibold">{t(col.titleKey)}</h4> <h4 className="mb-3 text-sm font-semibold">{t(col.titleKey)}</h4>
<ul className="space-y-2"> <ul className="space-y-2">
{col.linkKeys.map((lk) => ( {col.links.map((link) => (
<li key={lk}> <li key={link.key}>
<a <a
href="#" href={link.href}
target={link.href.startsWith("http") ? "_blank" : undefined}
rel={link.href.startsWith("http") ? "noopener noreferrer" : undefined}
className="text-sm text-muted-foreground transition-colors hover:text-foreground" className="text-sm text-muted-foreground transition-colors hover:text-foreground"
> >
{t(lk)} {t(link.key)}
</a> </a>
</li> </li>
))} ))}
@@ -66,13 +84,19 @@ export function Footer() {
{t("footer_rights")} {t("footer_rights")}
</p> </p>
<div className="flex gap-4"> <div className="flex gap-4">
{["Twitter", "Telegram", "GitHub"].map((s) => ( {[
{ label: "Twitter", href: "https://uptime.pvenode.ru/" },
{ label: "Telegram", href: "https://helpdesk.pvenode.ru/" },
{ label: "GitHub", href: "https://gitlab.pvenode.ru/1nt/GEKON-SUITE-VPN" },
].map((s) => (
<a <a
key={s} key={s.label}
href="#" href={s.href}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-muted-foreground transition-colors hover:text-foreground" className="text-xs text-muted-foreground transition-colors hover:text-foreground"
> >
{s} {s.label}
</a> </a>
))} ))}
</div> </div>
+92
View File
@@ -0,0 +1,92 @@
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { ParticlesBackground } from "@/components/ParticlesBackground";
import { FileText, ScrollText } from "lucide-react";
type LegalSection = {
heading: string;
paragraphs: string[];
};
type LegalDocumentPageProps = {
title: string;
subtitle: string;
sections: LegalSection[];
};
function makeSectionId(heading: string, index: number) {
const normalized = heading
.toLowerCase()
.replace(/[^a-zа-я0-9]+/gi, "-")
.replace(/^-+|-+$/g, "");
return normalized ? `${normalized}-${index + 1}` : `section-${index + 1}`;
}
export function LegalDocumentPage({ title, subtitle, sections }: LegalDocumentPageProps) {
return (
<div className="relative min-h-screen">
<ParticlesBackground />
<Navbar />
<main className="relative z-10 px-4 pb-16 pt-28 sm:pb-20">
<div className="mx-auto max-w-7xl">
<section className="mb-5 rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/95 via-background/85 to-background/95 p-6 shadow-[0_0_0_1px_rgba(16,185,129,0.06)] sm:p-8">
<div className="mb-3 inline-flex items-center gap-2 rounded-full border border-gekon-green/30 bg-gekon-green/10 px-3 py-1 text-xs font-medium text-gekon-green">
<FileText size={14} />
Юридический документ
</div>
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">{title}</h1>
<p className="mt-3 max-w-4xl text-sm leading-relaxed text-muted-foreground sm:text-base">{subtitle}</p>
</section>
<div className="grid gap-5 lg:grid-cols-[280px_minmax(0,1fr)]">
<aside className="h-fit rounded-2xl border border-border bg-background/75 p-4 lg:sticky lg:top-24">
<h2 className="mb-3 inline-flex items-center gap-2 text-sm font-semibold text-foreground">
<ScrollText size={16} />
Содержание
</h2>
<nav className="space-y-1.5">
{sections.map((section, index) => {
const id = makeSectionId(section.heading, index);
return (
<a
key={id}
href={`#${id}`}
className="block rounded-lg px-2.5 py-2 text-sm text-muted-foreground transition-colors hover:bg-gekon-green/10 hover:text-foreground"
>
{section.heading}
</a>
);
})}
</nav>
</aside>
<section className="space-y-4">
{sections.map((section, index) => {
const id = makeSectionId(section.heading, index);
return (
<article
id={id}
key={id}
className="scroll-mt-24 rounded-2xl border border-gekon-green/15 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5 shadow-[0_0_0_1px_rgba(16,185,129,0.05)] transition-all hover:border-gekon-green/30 hover:shadow-[0_10px_28px_rgba(16,185,129,0.12)] sm:p-6"
>
<h3 className="text-lg font-semibold text-foreground sm:text-xl">{section.heading}</h3>
<div className="mt-3 space-y-3">
{section.paragraphs.map((paragraph) => (
<p key={paragraph} className="text-sm leading-relaxed text-muted-foreground sm:text-[15px]">
{paragraph}
</p>
))}
</div>
</article>
);
})}
</section>
</div>
</div>
</main>
<Footer />
</div>
);
}
+9 -5
View File
@@ -6,10 +6,10 @@ import { localeLabels, type Locale } from "@/i18n/translations";
import type { TranslationKeys } from "@/i18n/translations"; import type { TranslationKeys } from "@/i18n/translations";
const navLinks: { key: TranslationKeys; href: string }[] = [ const navLinks: { key: TranslationKeys; href: string }[] = [
{ key: "nav_technology", href: "#technology" }, { key: "nav_technology", href: "/#technology" },
{ key: "nav_performance", href: "#performance" }, { key: "nav_performance", href: "https://uptime.pvenode.ru/" },
{ key: "nav_pricing", href: "#pricing" }, { key: "nav_pricing", href: "/#pricing" },
{ key: "nav_faq", href: "#faq" }, { key: "nav_faq", href: "/#faq" },
]; ];
const locales: Locale[] = ["en", "ru", "zh"]; const locales: Locale[] = ["en", "ru", "zh"];
@@ -34,7 +34,7 @@ export function Navbar() {
> >
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8"> <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between"> <div className="flex h-16 items-center justify-between">
<a href="#" className="flex items-center gap-3"> <a href="/" className="flex items-center gap-3">
<img <img
src="/gekon-logo.png" src="/gekon-logo.png"
alt="Gekon Fast logo" alt="Gekon Fast logo"
@@ -51,6 +51,8 @@ export function Navbar() {
<a <a
key={link.href} key={link.href}
href={link.href} href={link.href}
target={link.href.startsWith("http") ? "_blank" : undefined}
rel={link.href.startsWith("http") ? "noopener noreferrer" : undefined}
className="text-sm text-muted-foreground transition-colors hover:text-foreground" className="text-sm text-muted-foreground transition-colors hover:text-foreground"
> >
{t(link.key)} {t(link.key)}
@@ -131,6 +133,8 @@ export function Navbar() {
<a <a
key={link.href} key={link.href}
href={link.href} href={link.href}
target={link.href.startsWith("http") ? "_blank" : undefined}
rel={link.href.startsWith("http") ? "noopener noreferrer" : undefined}
className="text-sm text-muted-foreground transition-colors hover:text-foreground" className="text-sm text-muted-foreground transition-colors hover:text-foreground"
onClick={() => setMobileOpen(false)} onClick={() => setMobileOpen(false)}
> >
+62
View File
@@ -0,0 +1,62 @@
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { ParticlesBackground } from "@/components/ParticlesBackground";
import { Button } from "@/components/ui/button";
type StaticInfoSection = {
heading: string;
paragraphs: string[];
};
type StaticInfoPageProps = {
title: string;
subtitle: string;
sections: StaticInfoSection[];
ctaLabel?: string;
ctaHref?: string;
};
export function StaticInfoPage({ title, subtitle, sections, ctaLabel, ctaHref }: StaticInfoPageProps) {
return (
<div className="relative min-h-screen">
<ParticlesBackground />
<Navbar />
<main className="relative z-10 px-4 pb-16 pt-28 sm:pb-20">
<div className="mx-auto max-w-4xl">
<section className="glass-card rounded-2xl p-6 sm:p-8">
<h1 className="text-3xl font-bold text-foreground sm:text-4xl">{title}</h1>
<p className="mt-3 text-sm leading-relaxed text-muted-foreground sm:text-base">{subtitle}</p>
<div className="mt-8 space-y-7">
{sections.map((section) => (
<article key={section.heading}>
<h2 className="text-xl font-semibold text-foreground">{section.heading}</h2>
<div className="mt-2 space-y-3">
{section.paragraphs.map((paragraph) => (
<p key={paragraph} className="text-sm leading-relaxed text-muted-foreground sm:text-base">
{paragraph}
</p>
))}
</div>
</article>
))}
</div>
{ctaLabel && ctaHref ? (
<div className="mt-8 border-t border-border pt-6">
<Button asChild variant="glow" size="lg">
<a href={ctaHref} target="_blank" rel="noopener noreferrer">
{ctaLabel}
</a>
</Button>
</div>
) : null}
</section>
</div>
</main>
<Footer />
</div>
);
}
+6 -3
View File
@@ -160,10 +160,11 @@ const en = {
footer_about: "About", footer_about: "About",
footer_blog: "Blog", footer_blog: "Blog",
footer_careers: "Careers", footer_careers: "Careers",
footer_help: "Help Center", footer_help: "User Technical Support",
footer_contact: "Contact", footer_contact: "Contact",
footer_faq: "FAQ", footer_faq: "FAQ",
footer_privacy: "Privacy Policy", footer_privacy: "Privacy Policy",
footer_user_agreement: "User Agreement",
footer_terms: "Terms of Service", footer_terms: "Terms of Service",
footer_rights: "© 2026 Gekon. All rights reserved.", footer_rights: "© 2026 Gekon. All rights reserved.",
}; };
@@ -310,10 +311,11 @@ const ru: typeof en = {
footer_about: "О нас", footer_about: "О нас",
footer_blog: "Блог", footer_blog: "Блог",
footer_careers: "Карьера", footer_careers: "Карьера",
footer_help: "Центр помощи", footer_help: "Техническая поддержка пользователей",
footer_contact: "Контакты", footer_contact: "Контакты",
footer_faq: "FAQ", footer_faq: "FAQ",
footer_privacy: "Политика конфиденциальности", footer_privacy: "Политика конфиденциальности",
footer_user_agreement: "Пользовательское соглашение",
footer_terms: "Условия использования", footer_terms: "Условия использования",
footer_rights: "© 2026 Gekon. Все права защищены.", footer_rights: "© 2026 Gekon. Все права защищены.",
}; };
@@ -460,10 +462,11 @@ const zh: typeof en = {
footer_about: "关于", footer_about: "关于",
footer_blog: "博客", footer_blog: "博客",
footer_careers: "招聘", footer_careers: "招聘",
footer_help: "帮助中心", footer_help: "用户技术支持",
footer_contact: "联系我们", footer_contact: "联系我们",
footer_faq: "常见问题", footer_faq: "常见问题",
footer_privacy: "隐私政策", footer_privacy: "隐私政策",
footer_user_agreement: "用户协议",
footer_terms: "服务条款", footer_terms: "服务条款",
footer_rights: "© 2026 Gekon. 保留所有权利。", footer_rights: "© 2026 Gekon. 保留所有权利。",
}; };
+154 -3
View File
@@ -9,8 +9,50 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root' import { Route as rootRouteImport } from './routes/__root'
import { Route as UserAgreementRouteImport } from './routes/user-agreement'
import { Route as TermsOfUseRouteImport } from './routes/terms-of-use'
import { Route as SupportRouteImport } from './routes/support'
import { Route as PrivacyPolicyRouteImport } from './routes/privacy-policy'
import { Route as ContactsRouteImport } from './routes/contacts'
import { Route as CareersRouteImport } from './routes/careers'
import { Route as AboutRouteImport } from './routes/about'
import { Route as IndexRouteImport } from './routes/index' import { Route as IndexRouteImport } from './routes/index'
const UserAgreementRoute = UserAgreementRouteImport.update({
id: '/user-agreement',
path: '/user-agreement',
getParentRoute: () => rootRouteImport,
} as any)
const TermsOfUseRoute = TermsOfUseRouteImport.update({
id: '/terms-of-use',
path: '/terms-of-use',
getParentRoute: () => rootRouteImport,
} as any)
const SupportRoute = SupportRouteImport.update({
id: '/support',
path: '/support',
getParentRoute: () => rootRouteImport,
} as any)
const PrivacyPolicyRoute = PrivacyPolicyRouteImport.update({
id: '/privacy-policy',
path: '/privacy-policy',
getParentRoute: () => rootRouteImport,
} as any)
const ContactsRoute = ContactsRouteImport.update({
id: '/contacts',
path: '/contacts',
getParentRoute: () => rootRouteImport,
} as any)
const CareersRoute = CareersRouteImport.update({
id: '/careers',
path: '/careers',
getParentRoute: () => rootRouteImport,
} as any)
const AboutRoute = AboutRouteImport.update({
id: '/about',
path: '/about',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({ const IndexRoute = IndexRouteImport.update({
id: '/', id: '/',
path: '/', path: '/',
@@ -19,28 +61,130 @@ const IndexRoute = IndexRouteImport.update({
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
'/about': typeof AboutRoute
'/careers': typeof CareersRoute
'/contacts': typeof ContactsRoute
'/privacy-policy': typeof PrivacyPolicyRoute
'/support': typeof SupportRoute
'/terms-of-use': typeof TermsOfUseRoute
'/user-agreement': typeof UserAgreementRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
'/about': typeof AboutRoute
'/careers': typeof CareersRoute
'/contacts': typeof ContactsRoute
'/privacy-policy': typeof PrivacyPolicyRoute
'/support': typeof SupportRoute
'/terms-of-use': typeof TermsOfUseRoute
'/user-agreement': typeof UserAgreementRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
'/': typeof IndexRoute '/': typeof IndexRoute
'/about': typeof AboutRoute
'/careers': typeof CareersRoute
'/contacts': typeof ContactsRoute
'/privacy-policy': typeof PrivacyPolicyRoute
'/support': typeof SupportRoute
'/terms-of-use': typeof TermsOfUseRoute
'/user-agreement': typeof UserAgreementRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' fullPaths:
| '/'
| '/about'
| '/careers'
| '/contacts'
| '/privacy-policy'
| '/support'
| '/terms-of-use'
| '/user-agreement'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: '/' to:
id: '__root__' | '/' | '/'
| '/about'
| '/careers'
| '/contacts'
| '/privacy-policy'
| '/support'
| '/terms-of-use'
| '/user-agreement'
id:
| '__root__'
| '/'
| '/about'
| '/careers'
| '/contacts'
| '/privacy-policy'
| '/support'
| '/terms-of-use'
| '/user-agreement'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute
AboutRoute: typeof AboutRoute
CareersRoute: typeof CareersRoute
ContactsRoute: typeof ContactsRoute
PrivacyPolicyRoute: typeof PrivacyPolicyRoute
SupportRoute: typeof SupportRoute
TermsOfUseRoute: typeof TermsOfUseRoute
UserAgreementRoute: typeof UserAgreementRoute
} }
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
interface FileRoutesByPath { interface FileRoutesByPath {
'/user-agreement': {
id: '/user-agreement'
path: '/user-agreement'
fullPath: '/user-agreement'
preLoaderRoute: typeof UserAgreementRouteImport
parentRoute: typeof rootRouteImport
}
'/terms-of-use': {
id: '/terms-of-use'
path: '/terms-of-use'
fullPath: '/terms-of-use'
preLoaderRoute: typeof TermsOfUseRouteImport
parentRoute: typeof rootRouteImport
}
'/support': {
id: '/support'
path: '/support'
fullPath: '/support'
preLoaderRoute: typeof SupportRouteImport
parentRoute: typeof rootRouteImport
}
'/privacy-policy': {
id: '/privacy-policy'
path: '/privacy-policy'
fullPath: '/privacy-policy'
preLoaderRoute: typeof PrivacyPolicyRouteImport
parentRoute: typeof rootRouteImport
}
'/contacts': {
id: '/contacts'
path: '/contacts'
fullPath: '/contacts'
preLoaderRoute: typeof ContactsRouteImport
parentRoute: typeof rootRouteImport
}
'/careers': {
id: '/careers'
path: '/careers'
fullPath: '/careers'
preLoaderRoute: typeof CareersRouteImport
parentRoute: typeof rootRouteImport
}
'/about': {
id: '/about'
path: '/about'
fullPath: '/about'
preLoaderRoute: typeof AboutRouteImport
parentRoute: typeof rootRouteImport
}
'/': { '/': {
id: '/' id: '/'
path: '/' path: '/'
@@ -53,6 +197,13 @@ declare module '@tanstack/react-router' {
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
AboutRoute: AboutRoute,
CareersRoute: CareersRoute,
ContactsRoute: ContactsRoute,
PrivacyPolicyRoute: PrivacyPolicyRoute,
SupportRoute: SupportRoute,
TermsOfUseRoute: TermsOfUseRoute,
UserAgreementRoute: UserAgreementRoute,
} }
export const routeTree = rootRouteImport export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren) ._addFileChildren(rootRouteChildren)
+145
View File
@@ -0,0 +1,145 @@
import { createFileRoute } from "@tanstack/react-router";
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { ParticlesBackground } from "@/components/ParticlesBackground";
import { Button } from "@/components/ui/button";
import { Activity, Globe2, ShieldCheck, Sparkles, Users, Zap } from "lucide-react";
export const Route = createFileRoute("/about")({
component: AboutPage,
});
function AboutPage() {
const principles = [
{
title: "Прозрачная технология",
desc: "Объясняем, как работает ускорение: понятные метрики, открытая логика и контроль качества соединения.",
icon: Sparkles,
},
{
title: "Инфраструктура и надежность",
desc: "Распределенная сеть узлов, резервирование критичных компонентов и постоянный мониторинг состояния.",
icon: Globe2,
},
{
title: "Безопасность по умолчанию",
desc: "Разумная минимизация данных, технические меры защиты и строгие процессы доступа.",
icon: ShieldCheck,
},
];
const roadmap = [
"Улучшение алгоритмов выбора маршрута с учетом перегрузки каналов в реальном времени.",
"Новые профили ускорения для стриминга, игр и рабочих видеоконференций.",
"Расширение инфраструктуры и качества поддержки пользователей в регионах.",
];
return (
<div className="relative min-h-screen">
<ParticlesBackground />
<Navbar />
<main className="relative z-10 px-4 pb-16 pt-28 sm:pb-20">
<div className="mx-auto max-w-7xl">
<section className="mb-5 rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/95 via-background/85 to-background/95 p-6 shadow-[0_0_0_1px_rgba(16,185,129,0.06)] sm:p-8">
<div className="mb-3 inline-flex items-center gap-2 rounded-full border border-gekon-green/30 bg-gekon-green/10 px-3 py-1 text-xs font-medium text-gekon-green">
<Activity size={14} />
О проекте Gekon
</div>
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
Сервис ускорения интернета для стабильной и быстрой работы каждый день
</h1>
<p className="mt-3 max-w-4xl text-sm leading-relaxed text-muted-foreground sm:text-base">
Gekon развивает технологию интеллектуальной оптимизации сетевых маршрутов. Наша задача сделать
интернет-соединение предсказуемым, быстрым и удобным для людей, которым важны скорость, надежность и
комфорт без сложной ручной настройки.
</p>
<div className="mt-6 grid gap-3 sm:grid-cols-3">
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="text-2xl font-bold text-gekon-green">24/7</div>
<p className="mt-1 text-sm text-muted-foreground">Мониторинг и контроль доступности инфраструктуры.</p>
</div>
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="text-2xl font-bold text-gekon-green">50+</div>
<p className="mt-1 text-sm text-muted-foreground">Узлов в глобальной сети оптимизации маршрутов.</p>
</div>
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="text-2xl font-bold text-gekon-green">3x</div>
<p className="mt-1 text-sm text-muted-foreground">Потенциальное ускорение в типичных сценариях нагрузки.</p>
</div>
</div>
</section>
<section className="mb-5 grid gap-4 md:grid-cols-2">
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<h2 className="text-xl font-semibold text-foreground">Наша миссия</h2>
<p className="mt-3 text-sm leading-relaxed text-muted-foreground">
Мы делаем высокую скорость сети и стабильный доступ к онлайн-сервисам доступными для всех: от
пользователей домашних устройств до небольших команд, которым нужен устойчивый интернет для работы.
</p>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Вместо сложных технических настроек понятный интерфейс, автоматический подбор оптимального маршрута
и поддержка на каждом этапе.
</p>
</article>
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<h2 className="text-xl font-semibold text-foreground">Как это работает</h2>
<ul className="mt-3 space-y-2 text-sm leading-relaxed text-muted-foreground">
<li> Анализируем состояние сети и выбираем более эффективный путь передачи трафика.</li>
<li> Снижаем потери на маршруте и улучшаем стабильность в перегруженных сегментах.</li>
<li> Поддерживаем разные сценарии: стриминг, игры, видеосвязь, загрузки и ежедневный серфинг.</li>
</ul>
</article>
</section>
<section className="mb-5">
<h2 className="mb-3 text-2xl font-semibold text-foreground">Принципы, на которых строится сервис</h2>
<div className="grid gap-4 md:grid-cols-3">
{principles.map((item) => (
<article
key={item.title}
className="group rounded-2xl border border-border bg-background/75 p-5 transition-all hover:-translate-y-0.5 hover:border-gekon-green/40 hover:shadow-[0_10px_28px_rgba(16,185,129,0.16)]"
>
<div className="mb-3 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green transition-all group-hover:bg-gekon-green/20">
<item.icon size={18} />
</div>
<h3 className="text-lg font-semibold text-foreground">{item.title}</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">{item.desc}</p>
</article>
))}
</div>
</section>
<section className="mb-5 rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<h2 className="text-2xl font-semibold text-foreground">Что дальше</h2>
<div className="mt-3 grid gap-3">
{roadmap.map((point) => (
<div key={point} className="rounded-xl border border-border bg-background/60 px-4 py-3 text-sm text-muted-foreground">
{point}
</div>
))}
</div>
<div className="mt-5 flex flex-wrap gap-3">
<Button asChild variant="glow" size="lg">
<a href="/#pricing">
<Zap size={18} />
Выбрать тариф
</a>
</Button>
<Button asChild variant="glow-outline" size="lg">
<a href="/support">
<Users size={18} />
Связаться с поддержкой
</a>
</Button>
</div>
</section>
</div>
</main>
<Footer />
</div>
);
}
+125
View File
@@ -0,0 +1,125 @@
import { createFileRoute } from "@tanstack/react-router";
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { ParticlesBackground } from "@/components/ParticlesBackground";
import { Button } from "@/components/ui/button";
import { Briefcase, Clock3, ShieldCheck, Users } from "lucide-react";
export const Route = createFileRoute("/careers")({
component: CareersPage,
});
function CareersPage() {
const vacancies = [
{
title: "Инженер технической поддержки первой линии",
format: "Полная занятость / сменный график",
tasks: [
"Первичная диагностика обращений пользователей и маршрутизация заявок.",
"Контроль SLA, коммуникация с клиентами и подготовка инструкций.",
],
},
{
title: "Дежурный инженер",
format: "24/7 дежурства / ротационный график",
tasks: [
"Мониторинг инфраструктуры сервиса ускорения интернета и реакция на инциденты.",
"Эскалация критических инцидентов и пост-инцидентный анализ.",
],
},
{
title: "Маркетолог/СЕО",
format: "Удаленно / гибкий формат",
tasks: [
"Развитие SEO-стратегии и органического трафика.",
"Планирование контент-кампаний, работа с аналитикой и воронками конверсии.",
],
},
];
return (
<div className="relative min-h-screen">
<ParticlesBackground />
<Navbar />
<main className="relative z-10 px-4 pb-16 pt-28 sm:pb-20">
<div className="mx-auto max-w-6xl">
<section className="glass-card rounded-2xl p-6 sm:p-8">
<div className="flex flex-wrap items-start justify-between gap-4">
<div>
<h1 className="text-3xl font-bold text-foreground sm:text-4xl">Карьера в Gekon</h1>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-muted-foreground sm:text-base">
Мы развиваем сервис ускорения интернета и ищем специалистов, которые хотят строить надежную
инфраструктуру, сильную поддержку и рост продукта.
</p>
</div>
<div className="rounded-full border border-gekon-green/30 bg-gekon-green/10 px-4 py-1.5 text-xs font-medium text-gekon-green">
Актуальные вакансии
</div>
</div>
<div className="mt-8 grid gap-4 md:grid-cols-3">
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="mb-2 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green">
<Briefcase size={18} />
</div>
<h2 className="text-base font-semibold text-foreground">Продукт международного уровня</h2>
<p className="mt-1.5 text-sm text-muted-foreground">Работаем на стыке сетей, UX и надежности.</p>
</div>
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="mb-2 inline-flex rounded-lg border border-gekon-cyan/25 bg-gekon-cyan/10 text-gekon-cyan p-2">
<Users size={18} />
</div>
<h2 className="text-base font-semibold text-foreground">Сильная команда</h2>
<p className="mt-1.5 text-sm text-muted-foreground">Инженерная культура, прозрачные процессы, взаимопомощь.</p>
</div>
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="mb-2 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green">
<ShieldCheck size={18} />
</div>
<h2 className="text-base font-semibold text-foreground">Влияние на результат</h2>
<p className="mt-1.5 text-sm text-muted-foreground">Каждая роль напрямую влияет на опыт пользователей.</p>
</div>
</div>
<div className="mt-8 grid gap-4">
{vacancies.map((vacancy) => (
<article
key={vacancy.title}
className="group rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5 transition-all hover:-translate-y-0.5 hover:border-gekon-green/40 hover:shadow-[0_10px_28px_rgba(16,185,129,0.16)]"
>
<div className="flex flex-wrap items-start justify-between gap-3">
<h3 className="text-lg font-semibold text-foreground transition-colors group-hover:text-gekon-green">
{vacancy.title}
</h3>
<span className="inline-flex items-center gap-1 rounded-full border border-border bg-background/75 px-3 py-1 text-xs text-muted-foreground">
<Clock3 size={12} />
{vacancy.format}
</span>
</div>
<ul className="mt-3 space-y-2 text-sm leading-relaxed text-muted-foreground">
{vacancy.tasks.map((task) => (
<li key={task}> {task}</li>
))}
</ul>
</article>
))}
</div>
<div className="mt-8 border-t border-border pt-6">
<p className="mb-3 text-sm text-muted-foreground">
Отклик: отправьте резюме и короткое письмо на <span className="font-medium text-foreground">careers@gekon.example</span>
</p>
<Button asChild variant="glow" size="lg">
<a href="mailto:careers@gekon.example">Отправить резюме</a>
</Button>
</div>
</section>
</div>
</main>
<Footer />
</div>
);
}
+99
View File
@@ -0,0 +1,99 @@
import { createFileRoute } from "@tanstack/react-router";
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { ParticlesBackground } from "@/components/ParticlesBackground";
import { Button } from "@/components/ui/button";
import { Clock3, LifeBuoy, Mail, MessageCircleMore, ShieldCheck } from "lucide-react";
export const Route = createFileRoute("/contacts")({
component: ContactsPage,
});
function ContactsPage() {
return (
<div className="relative min-h-screen">
<ParticlesBackground />
<Navbar />
<main className="relative z-10 px-4 pb-16 pt-28 sm:pb-20">
<div className="mx-auto max-w-6xl">
<section className="mb-5 rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/95 via-background/85 to-background/95 p-6 shadow-[0_0_0_1px_rgba(16,185,129,0.06)] sm:p-8">
<div className="mb-3 inline-flex items-center gap-2 rounded-full border border-gekon-green/30 bg-gekon-green/10 px-3 py-1 text-xs font-medium text-gekon-green">
<MessageCircleMore size={14} />
Контактный центр Gekon
</div>
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">Контакты</h1>
<p className="mt-3 max-w-4xl text-sm leading-relaxed text-muted-foreground sm:text-base">
Если у вас вопросы по сервису ускорения интернета Gekon, тарифам, интеграциям или технической части
выберите подходящий канал связи ниже.
</p>
</section>
<section className="grid gap-4 md:grid-cols-3">
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<div className="mb-2 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green">
<LifeBuoy size={18} />
</div>
<h2 className="text-lg font-semibold text-foreground">Техническая поддержка</h2>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Для проблем с доступом, скоростью, настройкой и стабильностью соединения.
</p>
<div className="mt-4">
<Button asChild variant="glow" size="sm">
<a href="https://helpdesk.pvenode.ru/" target="_blank" rel="noopener noreferrer">
Открыть Helpdesk
</a>
</Button>
</div>
</article>
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<div className="mb-2 inline-flex rounded-lg border border-gekon-cyan/25 bg-gekon-cyan/10 p-2 text-gekon-cyan">
<Mail size={18} />
</div>
<h2 className="text-lg font-semibold text-foreground">Общие запросы</h2>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Для вопросов по партнерству, публикациям и общим организационным обращениям.
</p>
<div className="mt-4">
<Button asChild variant="glow-outline" size="sm">
<a href="mailto:hello@gekon.example">Написать на email</a>
</Button>
</div>
</article>
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<div className="mb-2 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green">
<ShieldCheck size={18} />
</div>
<h2 className="text-lg font-semibold text-foreground">Статус платформы</h2>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Отслеживайте актуальное состояние инфраструктуры и статус доступности сервисов.
</p>
<div className="mt-4">
<Button asChild variant="glow-outline" size="sm">
<a href="https://uptime.pvenode.ru/" target="_blank" rel="noopener noreferrer">
Открыть Uptime
</a>
</Button>
</div>
</article>
</section>
<section className="mt-5 rounded-2xl border border-border bg-background/75 p-5">
<h3 className="inline-flex items-center gap-2 text-lg font-semibold text-foreground">
<Clock3 size={18} />
Время обработки обращений
</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Первичный ответ по большинству заявок приходит в течение рабочего дня. Критичные обращения по
недоступности сервиса обрабатываются приоритетно.
</p>
</section>
</div>
</main>
<Footer />
</div>
);
}
+106
View File
@@ -0,0 +1,106 @@
import { createFileRoute } from "@tanstack/react-router";
import { LegalDocumentPage } from "@/components/LegalDocumentPage";
export const Route = createFileRoute("/privacy-policy")({
component: PrivacyPolicyPage,
});
function PrivacyPolicyPage() {
return (
<LegalDocumentPage
title="Политика конфиденциальности"
subtitle="Настоящая Политика регулирует сбор, использование и защиту пользовательских данных при использовании сервиса ускорения интернета Gekon."
sections={[
{
heading: "1. Общие положения",
paragraphs: [
"1.1. Настоящая Политика конфиденциальности (далее — «Политика») регулирует порядок обработки и защиты информации, которую Пользователь передает при использовании сервиса ускорения интернета Gekon (далее — «Сервис»).",
"1.2. Используя Сервис, Пользователь подтверждает согласие с условиями настоящей Политики.",
"1.3. Если Пользователь не согласен с условиями Политики, он обязан прекратить использование Сервиса.",
],
},
{
heading: "2. Какие данные мы собираем",
paragraphs: [
"2.1. Идентификаторы аккаунта: логин, ID, никнейм, контактный email и иные данные, которые Пользователь добровольно предоставляет при регистрации и обращениях в поддержку.",
"2.2. Технические данные: IP-адрес, тип и версия браузера, данные устройства и операционной системы, часовой пояс, диагностические сведения о работе приложения.",
"2.3. История взаимодействий: действия в интерфейсе, данные о сессиях и запросах, обращения в службу поддержки.",
"2.4. Сервис не требует паспортные данные и иную избыточную персональную информацию, не необходимую для предоставления функционала.",
],
},
{
heading: "3. Цели обработки данных",
paragraphs: [
"3.1. Обеспечение работы Сервиса и предоставление доступа к функциям ускорения интернет-соединения.",
"3.2. Улучшение стабильности, скорости и качества обслуживания, включая техническую диагностику и аналитику.",
"3.3. Связь с Пользователем по вопросам поддержки, безопасности, оплаты и сервисных уведомлений.",
],
},
{
heading: "4. Правовые основания обработки",
paragraphs: [
"4.1. Обработка данных осуществляется на основании согласия Пользователя, необходимости исполнения пользовательского договора и соблюдения требований законодательства.",
"4.2. При необходимости Администрация может обрабатывать данные для защиты законных интересов Сервиса, Пользователей и третьих лиц.",
],
},
{
heading: "5. Передача данных третьим лицам",
paragraphs: [
"5.1. Администрация не продает и не передает персональные данные третьим лицам, кроме случаев, предусмотренных законом.",
"5.2. Передача данных допускается при интеграции с платежными и техническими провайдерами, если это необходимо для предоставления услуг.",
"5.3. Передача данных возможна по запросу уполномоченных государственных органов в случаях, предусмотренных законодательством.",
],
},
{
heading: "6. Хранение, безопасность и срок обработки",
paragraphs: [
"6.1. Данные хранятся в течение срока, необходимого для достижения целей обработки, исполнения обязательств и соблюдения требований законодательства.",
"6.2. Администрация применяет разумные организационные и технические меры защиты информации: контроль доступа, журналирование и защиту каналов передачи данных.",
"6.3. Абсолютная безопасность передачи данных через интернет не может быть гарантирована.",
],
},
{
heading: "7. Cookies и аналитика",
paragraphs: [
"7.1. Сервис может использовать cookies и схожие технологии для авторизации, сохранения настроек и улучшения пользовательского опыта.",
"7.2. Пользователь может ограничить использование cookies в настройках браузера, однако это может повлиять на доступность отдельных функций Сервиса.",
],
},
{
heading: "8. Права пользователя",
paragraphs: [
"8.1. Пользователь вправе запросить уточнение, обновление или удаление своих данных в пределах, допускаемых законодательством и техническими возможностями Сервиса.",
"8.2. Для реализации прав Пользователь может обратиться в службу технической поддержки пользователей через доступные каналы связи.",
],
},
{
heading: "9. Ограничение ответственности",
paragraphs: [
"9.1. Пользователь понимает и соглашается, что передача информации через интернет связана с рисками, не зависящими полностью от Администрации.",
"9.2. Администрация не несет ответственности за утрату данных вследствие действий третьих лиц, форс-мажора или нарушения Пользователем правил информационной безопасности.",
],
},
{
heading: "10. Изменение Политики",
paragraphs: [
"10.1. Администрация вправе вносить изменения в настоящую Политику без предварительного уведомления, если иное не требуется законом.",
"10.2. Актуальная редакция Политики публикуется в Сервисе. Продолжение использования Сервиса означает согласие Пользователя с новой редакцией.",
],
},
{
heading: "11. Применимое право и разрешение споров",
paragraphs: [
"11.1. К отношениям, связанным с обработкой данных в рамках Сервиса, применяется право Российской Федерации, если иное не установлено императивными нормами применимого права.",
"11.2. До обращения в суд стороны стремятся урегулировать спор в претензионном порядке через службу технической поддержки пользователей.",
],
},
{
heading: "12. Контакты по персональным данным",
paragraphs: [
"12.1. По вопросам обработки персональных данных, реализации прав субъекта данных и отзыва согласия Пользователь может обратиться через официальный канал технической поддержки пользователей.",
],
},
]}
/>
);
}
+103
View File
@@ -0,0 +1,103 @@
import { createFileRoute } from "@tanstack/react-router";
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { ParticlesBackground } from "@/components/ParticlesBackground";
import { Button } from "@/components/ui/button";
import { AlarmClock, CircleHelp, Headphones, ShieldCheck, Wrench } from "lucide-react";
export const Route = createFileRoute("/support")({
component: SupportPage,
});
function SupportPage() {
return (
<div className="relative min-h-screen">
<ParticlesBackground />
<Navbar />
<main className="relative z-10 px-4 pb-16 pt-28 sm:pb-20">
<div className="mx-auto max-w-6xl">
<section className="glass-card rounded-2xl p-6 sm:p-8">
<div className="flex flex-wrap items-start justify-between gap-4">
<div>
<h1 className="text-3xl font-bold text-foreground sm:text-4xl">Техническая поддержка пользователей</h1>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-muted-foreground sm:text-base">
Помогаем с подключением, скоростью и стабильностью сервиса ускорения интернета. Чем точнее данные в заявке,
тем быстрее решим вопрос.
</p>
</div>
<div className="inline-flex items-center gap-2 rounded-full border border-gekon-green/30 bg-gekon-green/10 px-4 py-1.5 text-xs font-medium text-gekon-green">
<Headphones size={14} />
Support Desk
</div>
</div>
<div className="mt-8 grid gap-4 md:grid-cols-3">
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="mb-2 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green">
<AlarmClock size={18} />
</div>
<h2 className="text-base font-semibold text-foreground">Быстрый первичный ответ</h2>
<p className="mt-1.5 text-sm text-muted-foreground">Обычно в течение рабочего дня, по критичным обращениям приоритетно.</p>
</div>
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="mb-2 inline-flex rounded-lg border border-gekon-cyan/25 bg-gekon-cyan/10 p-2 text-gekon-cyan">
<Wrench size={18} />
</div>
<h2 className="text-base font-semibold text-foreground">Техдиагностика</h2>
<p className="mt-1.5 text-sm text-muted-foreground">Проверяем маршрут, устройство, клиент и сетевые ограничения.</p>
</div>
<div className="rounded-xl border border-border bg-background/60 p-4">
<div className="mb-2 inline-flex rounded-lg border border-gekon-green/25 bg-gekon-green/10 p-2 text-gekon-green">
<ShieldCheck size={18} />
</div>
<h2 className="text-base font-semibold text-foreground">Контроль SLA</h2>
<p className="mt-1.5 text-sm text-muted-foreground">Инциденты отслеживаются до полного восстановления сервиса.</p>
</div>
</div>
<div className="mt-8 grid gap-4 lg:grid-cols-2">
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<h3 className="text-lg font-semibold text-foreground">Как оформить обращение</h3>
<ul className="mt-3 space-y-2 text-sm text-muted-foreground">
<li> Нажмите кнопку «Написать» и создайте заявку в helpdesk.</li>
<li> Укажите устройство, ОС, регион и тип подключения.</li>
<li> Добавьте время проблемы и шаги воспроизведения.</li>
</ul>
</article>
<article className="rounded-2xl border border-gekon-green/20 bg-gradient-to-br from-background/90 via-background/75 to-background/90 p-5">
<h3 className="text-lg font-semibold text-foreground">Что ускорит решение</h3>
<ul className="mt-3 space-y-2 text-sm text-muted-foreground">
<li> Скриншоты ошибки или нестабильной работы.</li>
<li> Логи клиента (если доступны) и время сбоя.</li>
<li> Краткое описание ожидаемого результата.</li>
</ul>
</article>
</div>
<div className="mt-8 rounded-2xl border border-border bg-background/60 p-5">
<h3 className="inline-flex items-center gap-2 text-lg font-semibold text-foreground">
<CircleHelp size={18} />
Важно
</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Поддержка помогает по вопросам использования сервиса ускорения интернета, стабильности соединения,
доступа к аккаунту и оплате. Не передавайте третьим лицам пароли и коды подтверждения.
</p>
</div>
<div className="mt-8 border-t border-border pt-6">
<Button asChild variant="glow" size="lg">
<a href="https://helpdesk.pvenode.ru/" target="_blank" rel="noopener noreferrer">
Написать
</a>
</Button>
</div>
</section>
</div>
</main>
<Footer />
</div>
);
}
+94
View File
@@ -0,0 +1,94 @@
import { createFileRoute } from "@tanstack/react-router";
import { LegalDocumentPage } from "@/components/LegalDocumentPage";
export const Route = createFileRoute("/terms-of-use")({
component: TermsOfUsePage,
});
function TermsOfUsePage() {
return (
<LegalDocumentPage
title="Условия использования"
subtitle="Настоящие Условия использования определяют правила доступа к сервису ускорения интернета Gekon, его функциям и тарифным планам."
sections={[
{
heading: "1. Область применения",
paragraphs: [
"1.1. Условия распространяются на всех пользователей Сервиса, включая бесплатный тестовый доступ, платные тарифы и дополнительные функции.",
"1.2. Использование Сервиса означает согласие Пользователя с настоящими Условиями, Пользовательским соглашением и Политикой конфиденциальности.",
],
},
{
heading: "2. Регистрация и аккаунт",
paragraphs: [
"2.1. Для доступа к части функционала Пользователь создает аккаунт и предоставляет актуальные данные, необходимые для работы Сервиса.",
"2.2. Пользователь обязан обеспечивать конфиденциальность учетных данных и несет ответственность за действия, совершенные под его аккаунтом.",
"2.3. Администрация вправе ограничить или приостановить доступ при подозрении на компрометацию аккаунта или нарушение правил использования.",
],
},
{
heading: "3. Условия предоставления сервиса",
paragraphs: [
"3.1. Сервис ускорения интернета предоставляется в формате best effort с учетом технических ограничений сети, провайдера и оборудования Пользователя.",
"3.2. Доступность отдельных функций может зависеть от региона, тарифного плана, конфигурации устройства и внешних сетевых факторов.",
"3.3. Администрация вправе выполнять технические работы, обновления и профилактику, что может временно влиять на доступность Сервиса.",
],
},
{
heading: "4. Тарифы, оплата и тестовый доступ",
paragraphs: [
"4.1. Актуальные тарифы, условия оплаты и срок действия доступа публикуются в интерфейсе Сервиса и/или на официальных страницах проекта.",
"4.2. Тестовые периоды, промоусловия и бонусные предложения действуют в пределах объявленных сроков и могут быть изменены или прекращены без сохранения на будущие периоды.",
"4.3. Вопросы возврата средств регулируются Пользовательским соглашением и применимым законодательством.",
],
},
{
heading: "5. Правила допустимого использования",
paragraphs: [
"5.1. Пользователь обязуется использовать Сервис только в законных целях и не предпринимать действий, нарушающих работу инфраструктуры, приложений и сетей.",
"5.2. Запрещены: сетевые атаки, распространение вредоносного ПО, спам-активность, обход ограничений, нарушающих закон, и любые формы злоупотребления функционалом.",
"5.3. При выявлении нарушений Администрация вправе ограничить доступ без предварительного уведомления.",
],
},
{
heading: "6. Интеллектуальная собственность",
paragraphs: [
"6.1. Контент, дизайн, программное обеспечение и документация Сервиса охраняются законодательством об интеллектуальной собственности.",
"6.2. Любое копирование, переработка, распространение, декомпиляция или коммерческое использование материалов Сервиса без разрешения правообладателя запрещены.",
],
},
{
heading: "7. Ограничение ответственности",
paragraphs: [
"7.1. Администрация не гарантирует постоянный уровень ускорения интернет-соединения в каждом конкретном сценарии использования.",
"7.2. Администрация не несет ответственности за убытки, вызванные действиями третьих лиц, работой провайдеров, региональными ограничениями сети или неверной настройкой со стороны Пользователя.",
],
},
{
heading: "8. Поддержка пользователей",
paragraphs: [
"8.1. Пользователь может обращаться в службу технической поддержки пользователей по официальным каналам, указанным в Сервисе.",
"8.2. Для ускорения обработки обращения рекомендуется прикладывать описание проблемы, конфигурацию устройства и шаги воспроизведения.",
],
},
{
heading: "9. Изменение условий",
paragraphs: [
"9.1. Администрация вправе изменять настоящие Условия использования в одностороннем порядке.",
"9.2. Обновленная редакция вступает в силу с момента публикации, если иное прямо не указано в тексте обновления.",
"9.3. Продолжение использования Сервиса после обновления означает согласие Пользователя с новой редакцией Условий.",
],
},
{
heading: "10. Заключительные положения",
paragraphs: [
"10.1. Все споры и разногласия по возможности решаются путем переговоров и обращения в поддержку.",
"10.2. Если отдельные положения Условий будут признаны недействительными, остальные положения сохраняют юридическую силу.",
"10.3. К настоящим Условиям применяется право Российской Федерации, если иное не требуется обязательными нормами применимого права.",
"10.4. Настоящие Условия не подтверждают и не декларируют принадлежность Сервиса к какой-либо лицензируемой категории услуг, если такое прямо не указано в обязательной правовой информации, размещенной Администрацией.",
],
},
]}
/>
);
}
+116
View File
@@ -0,0 +1,116 @@
import { createFileRoute } from "@tanstack/react-router";
import { LegalDocumentPage } from "@/components/LegalDocumentPage";
export const Route = createFileRoute("/user-agreement")({
component: UserAgreementPage,
});
function UserAgreementPage() {
return (
<LegalDocumentPage
title="Пользовательское соглашение"
subtitle="Настоящее Соглашение регулирует порядок использования сервиса ускорения интернета Gekon и сопутствующих цифровых услуг."
sections={[
{
heading: "1. Общие положения",
paragraphs: [
"1.1. Настоящее Пользовательское соглашение (далее — «Соглашение») регулирует отношения между Администрацией и Пользователем при использовании сервиса ускорения интернета Gekon (далее — «Сервис»).",
"1.2. Регистрация, вход в аккаунт, оплата услуг или фактическое использование Сервиса означает полное и безоговорочное принятие условий настоящего Соглашения.",
"1.3. При несогласии с условиями Соглашения Пользователь обязан прекратить использование Сервиса.",
],
},
{
heading: "2. Предмет и формат услуг",
paragraphs: [
"2.1. Сервис предоставляет цифровые услуги нематериального характера, направленные на оптимизацию сетевого маршрута, повышение стабильности соединения и улучшение пользовательского интернет-опыта.",
"2.2. Функциональность Сервиса может включать клиентские приложения, веб-интерфейс, аналитические инструменты, техническую поддержку и сопутствующие цифровые материалы.",
"2.3. Администрация вправе изменять состав и объем функциональности для развития продукта и обеспечения безопасности.",
],
},
{
heading: "3. Отказ от гарантий и ответственности",
paragraphs: [
"3.1. Сервис предоставляется на условиях «AS IS» («как есть»).",
"3.2. Администрация не гарантирует полного соответствия Сервиса индивидуальным ожиданиям Пользователя и непрерывной работы без технических перерывов.",
"3.3. Администрация не несет ответственности за прямые и косвенные убытки, включая упущенную выгоду, возникшие в результате использования или невозможности использования Сервиса, за исключением случаев, прямо предусмотренных законом.",
"3.4. Пользователь самостоятельно принимает решения о применении функций Сервиса и несет связанные с этим риски.",
],
},
{
heading: "4. Законность использования",
paragraphs: [
"4.1. Пользователь обязуется использовать Сервис исключительно в рамках применимого законодательства страны использования и международных норм.",
"4.2. Запрещено использовать Сервис для противоправной деятельности, распространения вредоносного ПО, сетевых атак, мошенничества, спама и иных злоупотреблений.",
"4.3. Ответственность за законность сценариев использования Сервиса полностью возлагается на Пользователя.",
],
},
{
heading: "5. Интеллектуальная собственность",
paragraphs: [
"5.1. Все объекты, размещенные в Сервисе, включая программный код, дизайн, тексты, базы данных и иные материалы, являются объектами интеллектуальной собственности и защищаются законом.",
"5.2. Пользователю запрещается копирование, модификация, декомпиляция, распространение и коммерческое использование материалов Сервиса без письменного согласия правообладателя.",
"5.3. Нарушение прав интеллектуальной собственности может привести к ограничению доступа и иным мерам правовой защиты.",
],
},
{
heading: "6. Ограничение доступа",
paragraphs: [
"6.1. Администрация вправе временно приостановить или полностью ограничить доступ к Сервису при нарушении Соглашения, выявлении подозрительной активности или поступлении обязательных требований закона.",
"6.2. Ограничение доступа не освобождает Пользователя от обязательств, возникших до даты ограничения.",
"6.3. Администрация вправе отказать в обслуживании, если действия Пользователя создают риски для инфраструктуры, других пользователей или партнерских систем.",
],
},
{
heading: "7. Платежи и возвраты",
paragraphs: [
"7.1. Оплата услуг осуществляется на условиях и по тарифам, указанным в Сервисе на момент оплаты.",
"7.2. Учитывая цифровой и нематериальный характер предоставляемых услуг, возврат средств после предоставления доступа, как правило, не производится, если иное не указано в условиях тарифа.",
"7.3. Запрос на возврат может быть рассмотрен индивидуально в случаях технической невозможности оказания услуги по вине Сервиса.",
"7.4. Для рассмотрения запроса Пользователь обязан обратиться в техническую поддержку в разумный срок после оплаты.",
],
},
{
heading: "8. Конфиденциальность",
paragraphs: [
"8.1. Обработка персональных и технических данных осуществляется в соответствии с Политикой конфиденциальности Сервиса.",
"8.2. Используя Сервис, Пользователь подтверждает ознакомление с Политикой конфиденциальности и согласие с ее условиями.",
],
},
{
heading: "9. Изменение условий",
paragraphs: [
"9.1. Администрация вправе изменять настоящее Соглашение в одностороннем порядке.",
"9.2. Актуальная редакция публикуется в Сервисе и вступает в силу с момента публикации, если иное не указано дополнительно.",
"9.3. Продолжение использования Сервиса после обновления условий означает согласие Пользователя с новой редакцией.",
],
},
{
heading: "10. Контактная информация",
paragraphs: [
"10.1. По вопросам использования Сервиса и условий настоящего Соглашения Пользователь может обратиться в службу технической поддержки пользователей.",
],
},
{
heading: "11. Правоспособность пользователя",
paragraphs: [
"11.1. Пользователь подтверждает, что обладает необходимой правоспособностью и дееспособностью для принятия настоящего Соглашения.",
"11.2. Если доступ к Сервису осуществляется от имени организации, лицо, принимающее условия, подтверждает наличие соответствующих полномочий.",
],
},
{
heading: "12. Применимое право и порядок разрешения споров",
paragraphs: [
"12.1. Настоящее Соглашение регулируется правом Российской Федерации, если иное не установлено обязательными нормами применимого права.",
"12.2. Споры подлежат досудебному урегулированию путем направления обращения в техническую поддержку пользователей; при недостижении соглашения спор рассматривается в суде по правилам действующего законодательства.",
],
},
{
heading: "Подтверждение согласия",
paragraphs: [
"Используя Сервис, Пользователь подтверждает, что ознакомлен с настоящим Соглашением и принимает его условия в полном объеме.",
],
},
]}
/>
);
}