1
0
Fork 0

style: run prettier

This commit is contained in:
Vojtěch Mareš 2022-12-19 10:16:19 +01:00
parent 2193d68895
commit d80c0ec7de
Signed by: vojtech.mares
GPG key ID: C6827B976F17240D
27 changed files with 698 additions and 569 deletions

View file

@ -1,64 +1,60 @@
import Link from 'next/link'
import clsx from 'clsx'
import { ReactNode } from 'react'
import Link from "next/link";
import clsx from "clsx";
import { ReactNode } from "react";
const baseStyles = {
solid:
'group inline-flex items-center justify-center rounded-full py-2 px-4 text-sm font-semibold focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2',
"group inline-flex items-center justify-center rounded-full py-2 px-4 text-sm font-semibold focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2",
outline:
'group inline-flex ring-1 items-center justify-center rounded-full py-2 px-4 text-sm focus:outline-none',
}
"group inline-flex ring-1 items-center justify-center rounded-full py-2 px-4 text-sm focus:outline-none",
};
const variantStyles = {
solid: {
slate:
'bg-slate-900 text-white hover:bg-slate-700 hover:text-slate-100 active:bg-slate-800 active:text-slate-300 focus-visible:outline-slate-900',
blue: 'bg-blue-600 text-white hover:text-slate-100 hover:bg-blue-500 active:bg-blue-800 active:text-blue-100 focus-visible:outline-blue-600',
"bg-slate-900 text-white hover:bg-slate-700 hover:text-slate-100 active:bg-slate-800 active:text-slate-300 focus-visible:outline-slate-900",
blue: "bg-blue-600 text-white hover:text-slate-100 hover:bg-blue-500 active:bg-blue-800 active:text-blue-100 focus-visible:outline-blue-600",
white:
'bg-white text-slate-900 hover:bg-blue-50 active:bg-blue-200 active:text-slate-600 focus-visible:outline-white',
"bg-white text-slate-900 hover:bg-blue-50 active:bg-blue-200 active:text-slate-600 focus-visible:outline-white",
},
outline: {
slate:
'ring-slate-200 text-slate-700 hover:text-slate-900 hover:ring-slate-300 active:bg-slate-100 active:text-slate-600 focus-visible:outline-blue-600 focus-visible:ring-slate-300',
"ring-slate-200 text-slate-700 hover:text-slate-900 hover:ring-slate-300 active:bg-slate-100 active:text-slate-600 focus-visible:outline-blue-600 focus-visible:ring-slate-300",
white:
'ring-slate-700 text-white hover:ring-slate-500 active:ring-slate-700 active:text-slate-400 focus-visible:outline-white',
blue: // Supress TypeScript error
'', // TODO: fix properly
"ring-slate-700 text-white hover:ring-slate-500 active:ring-slate-700 active:text-slate-400 focus-visible:outline-white",
// Supress TypeScript error
blue: "", // TODO: fix properly
},
}
};
type Props = {
variant?: 'solid'|'outline',
color?: 'slate'|'white'|'blue',
className?: string,
href?: string,
children?: ReactNode,
}
variant?: "solid" | "outline";
color?: "slate" | "white" | "blue";
className?: string;
href?: string;
children?: ReactNode;
};
export function Button({
variant = 'solid',
color = 'slate',
variant = "solid",
color = "slate",
className,
href,
children
children,
}: Props) {
className = clsx(
baseStyles[variant],
variantStyles[variant][color],
className
)
);
if (href !== undefined) {
return (
<Link href={href} className={className}>
{children}
</Link>
)
);
} else {
return (
<button className={className}>
{children}
</button>
)
return <button className={className}>{children}</button>;
}
}

View file

@ -1,8 +1,8 @@
import Image from 'next/image'
import Image from "next/image";
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import backgroundImage from '@/images/background-call-to-action.jpg'
import { Button } from "@/components/Button";
import { Container } from "@/components/Container";
import backgroundImage from "@/images/background-call-to-action.jpg";
export function CallToAction() {
return (
@ -24,14 +24,19 @@ export function CallToAction() {
Posuňte svoji aplikaci dnes
</h2>
<p className="mt-4 text-lg tracking-tight text-white">
Je na čase pozvednout vaši infrastrukturu na dnešní standardy.
Vaše infrastruktura by měla nabídnout Vaši aplikaci světu, ne ji držet zpátky.
Je na čase pozvednout vaši infrastrukturu na dnešní standardy. Vaše
infrastruktura by měla nabídnout Vaši aplikaci světu, ne ji držet
zpátky.
</p>
<Button href="https://calendly.com/vojtechmares/30min" color="white" className="mt-10">
<Button
href="https://calendly.com/vojtechmares/30min"
color="white"
className="mt-10"
>
Domluvme si schůzku
</Button>
</div>
</Container>
</section>
)
);
}

View file

@ -1,17 +1,15 @@
import clsx from 'clsx'
import { ReactNode } from 'react'
import clsx from "clsx";
import { ReactNode } from "react";
type Props = {
className?: string,
children?: ReactNode
}
className?: string;
children?: ReactNode;
};
export function Container({ className, children }: Props ) {
export function Container({ className, children }: Props) {
return (
<div
className={clsx('mx-auto max-w-7xl px-4 sm:px-6 lg:px-8', className)}
>
<div className={clsx("mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", className)}>
{children}
</div>
)
);
}

View file

@ -1,49 +1,48 @@
import Image from 'next/image'
import Image from "next/image";
import { Container } from './Container'
import { Container } from "./Container";
import logoKubernetes from '@/images/logos/tools/kubernetes.svg'
import logok3s from '@/images/logos/tools/k3s.svg'
import logoRancher from '@/images/logos/tools/rancher.svg'
import logoAWS from '@/images/logos/tools/amazonaws.svg'
import logoDigitalOcean from '@/images/logos/tools/digitalocean.svg'
import logovmware from '@/images/logos/tools/vmware.svg'
import logoKubernetes from "@/images/logos/tools/kubernetes.svg";
import logok3s from "@/images/logos/tools/k3s.svg";
import logoRancher from "@/images/logos/tools/rancher.svg";
import logoAWS from "@/images/logos/tools/amazonaws.svg";
import logoDigitalOcean from "@/images/logos/tools/digitalocean.svg";
import logovmware from "@/images/logos/tools/vmware.svg";
const features = [
{
name: 'Kubernetes',
summary: 'Open Source systém pro automatizaci deploymentů, škálování a správu kontejnerizovaných aplikací.',
name: "Kubernetes",
summary:
"Open Source systém pro automatizaci deploymentů, škálování a správu kontejnerizovaných aplikací.",
description:
'Kubernetes je na platformě nezávislý systém, díky kterému může běžet vaše aplikace u vás v datacentru, v public cloudu nebo třeba v okrajových lokalitách, a nebo třeba na všech najednou, bez problému.',
"Kubernetes je na platformě nezávislý systém, díky kterému může běžet vaše aplikace u vás v datacentru, v public cloudu nebo třeba v okrajových lokalitách, a nebo třeba na všech najednou, bez problému.",
icon: logoKubernetes,
iconColor: '#326CE5',
iconColor: "#326CE5",
},
{
name: 'k3s & rke2',
name: "k3s & rke2",
summary:
'k3s: lehká distrubuce Kubernetes; rke2: Kubernetes do vašeho datacentra.',
"k3s: lehká distrubuce Kubernetes; rke2: Kubernetes do vašeho datacentra.",
description:
'k3s i rke2 jsou velice snadno instalovatelné distribuce Kubernetes, které můžete nainstalovat úplně všude a přitom mít stále k dispozici celý Kubernetes ekosystém, bez kompromisů.',
"k3s i rke2 jsou velice snadno instalovatelné distribuce Kubernetes, které můžete nainstalovat úplně všude a přitom mít stále k dispozici celý Kubernetes ekosystém, bez kompromisů.",
icon: logok3s,
iconColor: '#FFC61C',
iconColor: "#FFC61C",
},
{
name: 'Rancher',
summary:
'Kubernetes jako služba, ve vašem datacentru.',
name: "Rancher",
summary: "Kubernetes jako služba, ve vašem datacentru.",
description:
'Platforma, pro vaše Kubernetes clustery. Komplexní řešení celého životního cyklu clusteru. Neřešte každodení problémy, nechte je řešit Rancher řešit za vás.',
"Platforma, pro vaše Kubernetes clustery. Komplexní řešení celého životního cyklu clusteru. Neřešte každodení problémy, nechte je řešit Rancher řešit za vás.",
icon: logoRancher,
iconColor: '#0075A8',
iconColor: "#0075A8",
},
{
name: 'AWS',
summary:
'Největší veřejný cloud. Máte problém? AWS má na to službu.',
name: "AWS",
summary: "Největší veřejný cloud. Máte problém? AWS má na to službu.",
description:
'Amazon Web Services (AWS) je cloudový poskytovatel služeb, včetně ukládání obrovských objemů dat, výpočetního výkonu a sítí. To vše aby pomohli firmám i jednotlivcům růst. AWS je nejrozšířenější poskytovatel, který je cenově dostupný, flexibilní cesta, jak stavět a provozovat aplikace a služby.',
"Amazon Web Services (AWS) je cloudový poskytovatel služeb, včetně ukládání obrovských objemů dat, výpočetního výkonu a sítí. To vše aby pomohli firmám i jednotlivcům růst. AWS je nejrozšířenější poskytovatel, který je cenově dostupný, flexibilní cesta, jak stavět a provozovat aplikace a služby.",
icon: logoAWS,
iconColor: '#232F3E',
iconColor: "#232F3E",
},
// {
// name: 'Google Cloud Platform',
@ -55,13 +54,12 @@ const features = [
// iconColor: '#4285F4',
// },
{
name: 'DigitalOcean',
summary:
'Jednoduchý cloudový poskytovatel, ve kterém se neztratíte.',
name: "DigitalOcean",
summary: "Jednoduchý cloudový poskytovatel, ve kterém se neztratíte.",
description:
'DigitalOcean patří k menším cloudovým poskytovatelům, avšak jejich portfolio vám pro vaši aplikaci bohatě stačí a nebudete se ztrácet v komplexitě velkých poskytovatelů se spoustou služeb.',
"DigitalOcean patří k menším cloudovým poskytovatelům, avšak jejich portfolio vám pro vaši aplikaci bohatě stačí a nebudete se ztrácet v komplexitě velkých poskytovatelů se spoustou služeb.",
icon: logoDigitalOcean,
iconColor: '#0080FF',
iconColor: "#0080FF",
},
// {
// name: 'OpenStack',
@ -73,50 +71,48 @@ const features = [
// iconColor: '#ED1944',
// },
{
name: 'VMware',
name: "VMware",
summary:
'Populární řešení pro správu vaše datacentra, od virtuálních serverů až po úložiště.',
"Populární řešení pro správu vaše datacentra, od virtuálních serverů až po úložiště.",
description:
'VMware je virtualizační platforma, která umožňuje vytvářet a spravovat virtuální servery a jejich fyzickém hardwaru. Zároveň umožňuje vytvářet oddělená prostředí například pro vývoj a ostrý provoz, tak i pro zcela různé aplikace.',
"VMware je virtualizační platforma, která umožňuje vytvářet a spravovat virtuální servery a jejich fyzickém hardwaru. Zároveň umožňuje vytvářet oddělená prostředí například pro vývoj a ostrý provoz, tak i pro zcela různé aplikace.",
icon: logovmware,
iconColor: '#607078',
iconColor: "#607078",
},
]
];
type FeatureType = {
name: string,
summary: string,
description: string,
icon: any,
iconColor: string,
}
name: string;
summary: string;
description: string;
icon: any;
iconColor: string;
};
type FeatureProps = {
feature: FeatureType
className?: string,
props?: any[],
}
feature: FeatureType;
className?: string;
props?: any[];
};
function Feature({ feature, className, ...props }: FeatureProps) {
return (
<div
className={className}
{...props}
>
<Image src={feature.icon} className="rounded-lg p-2" width="128" height="128" color={feature.iconColor} alt="" />
<h3
className="mt-6 text-lg font-medium text-blue-600"
>
{feature.name}
</h3>
<p className="mt-2 font-display text-xl text-slate-900">
<div className={className} {...props}>
<Image
src={feature.icon}
className="rounded-lg p-2"
width="128"
height="128"
color={feature.iconColor}
alt=""
/>
<h3 className="mt-6 text-lg font-medium text-blue-600">{feature.name}</h3>
<p className="font-display mt-2 text-xl text-slate-900">
{feature.summary}
</p>
<p className="mt-4 text-sm text-slate-600">
{feature.description}
</p>
<p className="mt-4 text-sm text-slate-600">{feature.description}</p>
</div>
)
);
}
function FeaturesMobile() {
@ -128,7 +124,7 @@ function FeaturesMobile() {
</div>
))}
</div>
)
);
}
function FeaturesDesktop() {
@ -142,7 +138,7 @@ function FeaturesDesktop() {
))}
</div>
</div>
)
);
}
export function Environment() {
@ -155,15 +151,16 @@ export function Environment() {
<Container>
<div className="mx-auto max-w-2xl md:text-center">
<h2 className="font-display text-3xl tracking-tight text-slate-900 sm:text-4xl">
Jakákoliv platforma, kdekoliv
Jakákoliv platforma, kdekoliv
</h2>
<p className="mt-4 text-lg tracking-tight text-slate-700">
Od veřejného cloudu přes on-premise po serverless, se vším vám poradím.
Od veřejného cloudu přes on-premise po serverless, se vším vám
poradím.
</p>
</div>
<FeaturesMobile />
<FeaturesDesktop />
</Container>
</section>
)
);
}

View file

@ -1,61 +1,61 @@
import Image from 'next/image'
import Image from "next/image";
import { Container } from '@/components/Container'
import backgroundImage from '@/images/background-faqs.jpg'
import { Container } from "@/components/Container";
import backgroundImage from "@/images/background-faqs.jpg";
const faqs = [
[
{
question: 'Does TaxPal handle VAT?',
question: "Does TaxPal handle VAT?",
answer:
'Well no, but if you move your company offshore you can probably ignore it.',
"Well no, but if you move your company offshore you can probably ignore it.",
},
{
question: 'Can I pay for my subscription via purchase order?',
answer: 'Absolutely, we are happy to take your money in all forms.',
question: "Can I pay for my subscription via purchase order?",
answer: "Absolutely, we are happy to take your money in all forms.",
},
{
question: 'How do I apply for a job at TaxPal?',
question: "How do I apply for a job at TaxPal?",
answer:
'We only hire our customers, so subscribe for a minimum of 6 months and then lets talk.',
"We only hire our customers, so subscribe for a minimum of 6 months and then lets talk.",
},
],
[
{
question: 'What was that testimonial about tax fraud all about?',
question: "What was that testimonial about tax fraud all about?",
answer:
'TaxPal is just a software application, ultimately your books are your responsibility.',
"TaxPal is just a software application, ultimately your books are your responsibility.",
},
{
question:
'TaxPal sounds horrible but why do I still feel compelled to purchase?',
"TaxPal sounds horrible but why do I still feel compelled to purchase?",
answer:
'This is the power of excellent visual design. You just cant resist it, no matter how poorly it actually functions.',
"This is the power of excellent visual design. You just cant resist it, no matter how poorly it actually functions.",
},
{
question:
'I found other companies called TaxPal, are you sure you can use this name?',
"I found other companies called TaxPal, are you sure you can use this name?",
answer:
'Honestly not sure at all. We havent actually incorporated or anything, we just thought it sounded cool and made this website.',
"Honestly not sure at all. We havent actually incorporated or anything, we just thought it sounded cool and made this website.",
},
],
[
{
question: 'How do you generate reports?',
question: "How do you generate reports?",
answer:
'You just tell us what data you need a report for, and we get our kids to create beautiful charts for you using only the finest crayons.',
"You just tell us what data you need a report for, and we get our kids to create beautiful charts for you using only the finest crayons.",
},
{
question: 'Can we expect more inventory features?',
answer: 'In life its really better to never expect anything at all.',
question: "Can we expect more inventory features?",
answer: "In life its really better to never expect anything at all.",
},
{
question: 'I lost my password, how do I get into my account?',
question: "I lost my password, how do I get into my account?",
answer:
'Send us an email and we will send you a copy of our latest password spreadsheet so you can find your information.',
"Send us an email and we will send you a copy of our latest password spreadsheet so you can find your information.",
},
],
]
];
export function Faqs() {
return (
@ -106,5 +106,5 @@ export function Faqs() {
</ul>
</Container>
</section>
)
);
}

View file

@ -1,9 +1,9 @@
import Link from 'next/link'
import Link from "next/link";
import { Container } from '@/components/Container'
import { Container } from "@/components/Container";
// import { Logo } from '@/components/Logo'
// import { NavLink } from '@/components/NavLink'
import { Button } from '@/components/Button'
import { Button } from "@/components/Button";
export function Footer() {
return (
@ -12,20 +12,29 @@ export function Footer() {
<div className="py-4">
<div className="grid grid-cols-1 gap-y-6 lg:grid-cols-4 lg:gap-4">
<div>
<h4 className="text-lg font-medium" >Vojtěch Mareš</h4>
<ul className="list-none mt-4">
<h4 className="text-lg font-medium">Vojtěch Mareš</h4>
<ul className="mt-4 list-none">
<li>
<Link href="tel:+420732490651" className="underline">+420 732 490 651</Link>
<Link href="tel:+420732490651" className="underline">
+420 732 490 651
</Link>
</li>
<li>
<Link href="mailto:iam@vojtechmares.com" className="underline">iam@vojtechmares.com</Link>
<Link
href="mailto:iam@vojtechmares.com"
className="underline"
>
iam@vojtechmares.com
</Link>
</li>
<li className="mt-4">
Company ID<br />
Company ID
<br />
<code id="company-id">06999280</code>
</li>
<li className="mt-2">
VAT ID<br />
VAT ID
<br />
<code id="vat-id">CZ9709180063</code>
</li>
</ul>
@ -34,13 +43,17 @@ export function Footer() {
<h3 className="text-lg font-medium">Nejblíbenější školení</h3>
<ul className="mt-4 list-disc pl-4">
<li>
<Link href="/skoleni/kubernetes" className="underline">Kubernetes</Link>
<Link href="/skoleni/kubernetes" className="underline">
Kubernetes
</Link>
</li>
{/* <li>
<Link href="/skoleni/gitlab-ci" className="underline">GitLab CI</Link>
</li> */}
<li>
<Link href="/skoleni/terraform" className="underline">Terraform</Link>
<Link href="/skoleni/terraform" className="underline">
Terraform
</Link>
</li>
{/* <li>
<Link href="/skoleni/rancher" className="underline">Rancher</Link>
@ -85,7 +98,10 @@ export function Footer() {
Zaujal jsem vás avšak nevíte, jak přesně bych vám mohl pomoci?
Nebojte se zeptat a společně vymyslíme, jak vám mohu pomoci.
</p>
<Button href="https://calendly.com/vojtechmares/30min" className="mt-5">
<Button
href="https://calendly.com/vojtechmares/30min"
className="mt-5"
>
Domluvme si schůzku
</Button>
</div>
@ -106,7 +122,7 @@ export function Footer() {
aria-hidden="true"
className="h-6 w-6 fill-slate-500 group-hover:fill-slate-700"
>
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
</svg>
</Link>
<Link
@ -137,10 +153,11 @@ export function Footer() {
</Link>
</div>
<p className="mt-6 text-sm text-slate-500 sm:mt-0">
Copyright &copy; {new Date().getFullYear()} Vojtěch Mareš. Všechna práva vyhrazena.
Copyright &copy; {new Date().getFullYear()} Vojtěch Mareš. Všechna
práva vyhrazena.
</p>
</div>
</Container>
</footer>
)
);
}

View file

@ -1,8 +1,8 @@
import Link from "next/link"
import Link from "next/link";
import { NavLink } from "@/components/NavLink";
import { Container } from "@/components/Container"
import { Button } from "@/components/Button"
import { Container } from "@/components/Container";
import { Button } from "@/components/Button";
export function Header() {
return (
@ -19,15 +19,16 @@ export function Header() {
<NavLink href="/skoleni">Školení</NavLink>
{/* <NavLink href="/pripadove-studie">Případové studie</NavLink> */}
<NavLink href="https://vojtechmares.blog/">Blog</NavLink>
</div>
</div>
</div>
<div className="flex items-center gap-x-5 md:gap-x-8">
<Button href="mailto:iam@vojtechmares.com" color="blue">
<span className="text-lg">
Napište mi <span className="hidden lg:inline">ještě dnes</span>
</span>
</Button>
</div>
<Button href="mailto:iam@vojtechmares.com" color="blue">
<span className="text-lg">
Napište mi{" "}
<span className="hidden lg:inline">ještě dnes</span>
</span>
</Button>
</div>
</nav>
</Container>
</header>

View file

@ -1,11 +1,11 @@
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import { Button } from "@/components/Button";
import { Container } from "@/components/Container";
export function Hero() {
return (
<Container className="pt-20 pb-16 text-center lg:pt-32">
<h1 className="mx-auto max-w-4xl font-display text-5xl font-medium tracking-tight text-slate-900 sm:text-7xl">
DevOps{' '}
<h1 className="font-display mx-auto max-w-4xl text-5xl font-medium tracking-tight text-slate-900 sm:text-7xl">
DevOps{" "}
<span className="relative whitespace-nowrap text-blue-600">
<svg
aria-hidden="true"
@ -16,15 +16,17 @@ export function Hero() {
<path d="M203.371.916c-26.013-2.078-76.686 1.963-124.73 9.946L67.3 12.749C35.421 18.062 18.2 21.766 6.004 25.934 1.244 27.561.828 27.778.874 28.61c.07 1.214.828 1.121 9.595-1.176 9.072-2.377 17.15-3.92 39.246-7.496C123.565 7.986 157.869 4.492 195.942 5.046c7.461.108 19.25 1.696 19.17 2.582-.107 1.183-7.874 4.31-25.75 10.366-21.992 7.45-35.43 12.534-36.701 13.884-2.173 2.308-.202 4.407 4.442 4.734 2.654.187 3.263.157 15.593-.78 35.401-2.686 57.944-3.488 88.365-3.143 46.327.526 75.721 2.23 130.788 7.584 19.787 1.924 20.814 1.98 24.557 1.332l.066-.011c1.201-.203 1.53-1.825.399-2.335-2.911-1.31-4.893-1.604-22.048-3.261-57.509-5.556-87.871-7.36-132.059-7.842-23.239-.254-33.617-.116-50.627.674-11.629.54-42.371 2.494-46.696 2.967-2.359.259 8.133-3.625 26.504-9.81 23.239-7.825 27.934-10.149 28.304-14.005.417-4.348-3.529-6-16.878-7.066Z" />
</svg>
<span className="relative">jednoduše</span>
</span>{' '}
</span>{" "}
pro všechny.
</h1>
<p className="mx-auto mt-6 max-w-2xl text-lg tracking-tight text-slate-700">
Společně snížíme vaše náklady na infrasturkuturu,
zbavíme se technického dluhu a připravíme vaší IT infrastrukturu na rapidní růst.
Společně snížíme vaše náklady na infrasturkuturu, zbavíme se technického
dluhu a připravíme vaší IT infrastrukturu na rapidní růst.
</p>
<div className="mt-10 flex justify-center gap-x-6">
<Button href="https://calendly.com/vojtechmares/30min">Domluvme si schůzku</Button>
<Button href="https://calendly.com/vojtechmares/30min">
Domluvme si schůzku
</Button>
{/* <Button
href="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
variant="outline"
@ -74,5 +76,5 @@ export function Hero() {
</ul>
</div> */}
</Container>
)
);
}

View file

@ -1,12 +1,12 @@
import { ReactNode } from 'react';
import Link from 'next/link';
import { ReactNode } from "react";
import Link from "next/link";
type Props = {
href: string,
children: ReactNode,
}
href: string;
children: ReactNode;
};
export function NavLink({href, children}: Props) {
export function NavLink({ href, children }: Props) {
return (
<Link
href={href}

View file

@ -1,9 +1,9 @@
import clsx from 'clsx'
import clsx from "clsx";
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import { Button } from "@/components/Button";
import { Container } from "@/components/Container";
type SwirlyDoodleProps = { className: string }
type SwirlyDoodleProps = { className: string };
function SwirlyDoodle({ className }: SwirlyDoodleProps) {
return (
@ -19,41 +19,48 @@ function SwirlyDoodle({ className }: SwirlyDoodleProps) {
d="M240.172 22.994c-8.007 1.246-15.477 2.23-31.26 4.114-18.506 2.21-26.323 2.977-34.487 3.386-2.971.149-3.727.324-6.566 1.523-15.124 6.388-43.775 9.404-69.425 7.31-26.207-2.14-50.986-7.103-78-15.624C10.912 20.7.988 16.143.734 14.657c-.066-.381.043-.344 1.324.456 10.423 6.506 49.649 16.322 77.8 19.468 23.708 2.65 38.249 2.95 55.821 1.156 9.407-.962 24.451-3.773 25.101-4.692.074-.104.053-.155-.058-.135-1.062.195-13.863-.271-18.848-.687-16.681-1.389-28.722-4.345-38.142-9.364-15.294-8.15-7.298-19.232 14.802-20.514 16.095-.934 32.793 1.517 47.423 6.96 13.524 5.033 17.942 12.326 11.463 18.922l-.859.874.697-.006c2.681-.026 15.304-1.302 29.208-2.953 25.845-3.07 35.659-4.519 54.027-7.978 9.863-1.858 11.021-2.048 13.055-2.145a61.901 61.901 0 0 0 4.506-.417c1.891-.259 2.151-.267 1.543-.047-.402.145-2.33.913-4.285 1.707-4.635 1.882-5.202 2.07-8.736 2.903-3.414.805-19.773 3.797-26.404 4.829Zm40.321-9.93c.1-.066.231-.085.29-.041.059.043-.024.096-.183.119-.177.024-.219-.007-.107-.079ZM172.299 26.22c9.364-6.058 5.161-12.039-12.304-17.51-11.656-3.653-23.145-5.47-35.243-5.576-22.552-.198-33.577 7.462-21.321 14.814 12.012 7.205 32.994 10.557 61.531 9.831 4.563-.116 5.372-.288 7.337-1.559Z"
/>
</svg>
)
);
}
type PlanProps = {
name: string,
price: string,
description: string,
href: string,
featured?: boolean,
buttonText?: string
}
name: string;
price: string;
description: string;
href: string;
featured?: boolean;
buttonText?: string;
};
function Plan({ name, price, description, href, featured = false, buttonText = 'Napište mi' }: PlanProps) {
function Plan({
name,
price,
description,
href,
featured = false,
buttonText = "Napište mi",
}: PlanProps) {
return (
<section
className={clsx(
'flex flex-col rounded-3xl px-6 sm:px-8',
featured ? 'order-first bg-blue-600 py-8 lg:order-none' : 'lg:py-8'
"flex flex-col rounded-3xl px-6 sm:px-8",
featured ? "order-first bg-blue-600 py-8 lg:order-none" : "lg:py-8"
)}
>
<h3 className="mt-5 font-display text-4xl text-white">{name}</h3>
<p className="mt-4 font-display text-lg font-light tracking-tight text-white">
<h3 className="font-display mt-5 text-4xl text-white">{name}</h3>
<p className="font-display mt-4 text-lg font-light tracking-tight text-white">
{price}
</p>
<p
className={clsx(
'mt-2 text-base',
featured ? 'text-white' : 'text-slate-400'
"mt-2 text-base",
featured ? "text-white" : "text-slate-400"
)}
>
{description}
</p>
<Button
href={href}
variant={featured ? 'solid' : 'outline'}
variant={featured ? "solid" : "outline"}
color="white"
className="mt-16"
aria-label={`Get started with the ${name} plan for ${price}`}
@ -61,7 +68,7 @@ function Plan({ name, price, description, href, featured = false, buttonText = '
{buttonText}
</Button>
</section>
)
);
}
export function Pricing() {
@ -77,11 +84,12 @@ export function Pricing() {
<span className="relative whitespace-nowrap">
<SwirlyDoodle className="absolute top-1/2 left-0 h-[1em] w-full fill-blue-400" />
<span className="relative">Co pro Vás,</span>
</span>{' '}
</span>{" "}
můžu udělat.
</h3>
<p className="mt-4 text-lg text-slate-400">
It doesnt matter what size your company is, we will find a way to help you.
It doesnt matter what size your company is, we will find a way to
help you.
</p>
</div>
<div className="-mx-4 mt-16 grid max-w-2xl grid-cols-1 gap-y-10 sm:mx-auto lg:-mx-8 lg:max-w-none lg:grid-cols-3 xl:mx-0 xl:gap-x-8">
@ -109,5 +117,5 @@ export function Pricing() {
</div>
</Container>
</section>
)
);
}

View file

@ -1,27 +1,31 @@
import Image from 'next/image'
import clsx from 'clsx'
import Image from "next/image";
import clsx from "clsx";
import { Container } from '@/components/Container'
import backgroundImage from '@/images/background-features.jpg'
import { Container } from "@/components/Container";
import backgroundImage from "@/images/background-features.jpg";
const steps = [
{
name: 'Analýza současného stavu',
description: 'Zjistíme kde jsou slabá místa vaší infrastruktury nebo aplikace, a nebo obojího.',
name: "Analýza současného stavu",
description:
"Zjistíme kde jsou slabá místa vaší infrastruktury nebo aplikace, a nebo obojího.",
},
{
name: 'Návrh řešení',
description: 'Navrhnu, jak tato slabá místa odstranit, na co si dát pozor a naplánujeme případné další kroky. ',
name: "Návrh řešení",
description:
"Navrhnu, jak tato slabá místa odstranit, na co si dát pozor a naplánujeme případné další kroky. ",
},
{
name: 'Implementace',
description: 'Přesunu vaši aplikaci do Kubernetes, ať na vašem vlastním hardware nebo v public cloudu. Celá infrastruktura bude jasně deklarovaná jako kód pomocí Terraformu.',
name: "Implementace",
description:
"Přesunu vaši aplikaci do Kubernetes, ať na vašem vlastním hardware nebo v public cloudu. Celá infrastruktura bude jasně deklarovaná jako kód pomocí Terraformu.",
},
{
name: 'Proškolení vašeho týmu',
description: 'Naučím váš tým používat moderní technologie, tak abyste mohli rozvíjet vaší aplikaci a byznys a technologie byly nástrojem k rozvoji, ne břemenem, které s sebou táhnete.',
name: "Proškolení vašeho týmu",
description:
"Naučím váš tým používat moderní technologie, tak abyste mohli rozvíjet vaší aplikaci a byznys a technologie byly nástrojem k rozvoji, ne břemenem, které s sebou táhnete.",
},
]
];
export function PrimaryFeatures() {
return (
@ -48,11 +52,23 @@ export function PrimaryFeatures() {
</p>
</div>
<nav aria-label="Progress">
<ol role="list" className="overflow-hidden pt-2 mt-20 max-w-3xl mx-auto">
<ol
role="list"
className="mx-auto mt-20 max-w-3xl overflow-hidden pt-2"
>
{steps.map((step, stepIdx) => (
<li key={step.name} className={clsx(stepIdx !== steps.length - 1 ? 'pb-10' : '', 'relative')}>
<li
key={step.name}
className={clsx(
stepIdx !== steps.length - 1 ? "pb-10" : "",
"relative"
)}
>
{stepIdx !== steps.length - 1 ? (
<div className="absolute top-4 left-6 -ml-px mt-0.5 h-full w-0.5 bg-white" aria-hidden="true" />
<div
className="absolute top-4 left-6 -ml-px mt-0.5 h-full w-0.5 bg-white"
aria-hidden="true"
/>
) : null}
<div className="group relative flex items-start">
<span className="flex h-9 items-center" aria-hidden="true">
@ -61,8 +77,12 @@ export function PrimaryFeatures() {
</span>
</span>
<span className="ml-4 flex min-w-0 flex-col">
<span className="text-2xl text-white font-normal">{step.name}</span>
<span className="text-lg text-blue-200">{step.description}</span>
<span className="text-2xl font-normal text-white">
{step.name}
</span>
<span className="text-lg text-blue-200">
{step.description}
</span>
</span>
</div>
</li>
@ -71,5 +91,5 @@ export function PrimaryFeatures() {
</nav>
</Container>
</section>
)
);
}

View file

@ -1,122 +1,125 @@
import { ReactNode } from 'react'
import Image, { StaticImageData } from 'next/image'
import { Tab } from '@headlessui/react'
import clsx from 'clsx'
import { ReactNode } from "react";
import Image, { StaticImageData } from "next/image";
import { Tab } from "@headlessui/react";
import clsx from "clsx";
import { Container } from '@/components/Container'
import { Container } from "@/components/Container";
import screenshotArgoCD from "@/images/screenshots/argocd.png";
import screenshotGitLab from "@/images/screenshots/gitlab.png";
import screenshotTerraform from "@/images/screenshots/terraform.png";
import screenshotKubernetes from "@/images/screenshots/kubernetes.png";
import screenshotGrafana from "@/images/screenshots/grafana.png";
import screenshotPrometheus from "@/images/screenshots/prometheus.png";
import screenshotArgoCD from '@/images/screenshots/argocd.png'
import screenshotGitLab from '@/images/screenshots/gitlab.png'
import screenshotTerraform from '@/images/screenshots/terraform.png'
import screenshotKubernetes from '@/images/screenshots/kubernetes.png'
import screenshotGrafana from '@/images/screenshots/grafana.png'
import screenshotPrometheus from '@/images/screenshots/prometheus.png'
import logoTerraform from '@/images/logos/tools/terraform.svg'
import logoGit from '@/images/logos/tools/git.svg'
import logoKubernetes from '@/images/logos/tools/kubernetes.svg'
import logoPrometheus from '@/images/logos/tools/prometheus.svg'
import logoArgo from '@/images/logos/tools/argo.svg'
import logoGrafana from '@/images/logos/tools/grafana.svg'
import logoTerraform from "@/images/logos/tools/terraform.svg";
import logoGit from "@/images/logos/tools/git.svg";
import logoKubernetes from "@/images/logos/tools/kubernetes.svg";
import logoPrometheus from "@/images/logos/tools/prometheus.svg";
import logoArgo from "@/images/logos/tools/argo.svg";
import logoGrafana from "@/images/logos/tools/grafana.svg";
const features = [
{
name: 'Verzování',
summary:
'Spravujte svůj kód pomocí verzovacího nástroje Git.',
name: "Verzování",
summary: "Spravujte svůj kód pomocí verzovacího nástroje Git.",
description:
'Mějte historii změn v aplikaci od začátku až do dnes, můžete se kdykoliv vrátit do bodu v čase. Řešte konflikty včas, předtím než je nasadíte do produkce a umožněte vaším programátorům spolupracovat na jednou, aniž by si překáželi.',
"Mějte historii změn v aplikaci od začátku až do dnes, můžete se kdykoliv vrátit do bodu v čase. Řešte konflikty včas, předtím než je nasadíte do produkce a umožněte vaším programátorům spolupracovat na jednou, aniž by si překáželi.",
image: screenshotGitLab,
icon: logoGit,
},
{
name: 'Infastruktura jako kód',
summary: 'Mějte vaši infrastrukturu deklarativně definovanou a verzovanou, díky Terraformu.',
name: "Infastruktura jako kód",
summary:
"Mějte vaši infrastrukturu deklarativně definovanou a verzovanou, díky Terraformu.",
description:
'Vaši infrastrukturu můžete snadno přesunout k jinému poskytovateli, a nebo jen vytvořit nové prostředí pro zákazníka, aby si váš produkt vyzkoušel a to během minut.',
"Vaši infrastrukturu můžete snadno přesunout k jinému poskytovateli, a nebo jen vytvořit nové prostředí pro zákazníka, aby si váš produkt vyzkoušel a to během minut.",
image: screenshotTerraform,
icon: logoTerraform,
},
{
name: 'Orchestrace',
name: "Orchestrace",
summary:
'Nechte vaši aplikaci běžet napříč mnoha servery a škálovat dle potřeb.',
"Nechte vaši aplikaci běžet napříč mnoha servery a škálovat dle potřeb.",
description:
'Kubernetes se stalo nejen standardem, ale i hlavní platformou pro vývoj aplikací ať SaaS nebo dodávaných třetím stranám. Jde o skvělou platformu pro provoz vaší aplikace ať ve veřejném cloudu nebo na vlastním hardwaru popř. on edge blízko koncových uživatelů.',
"Kubernetes se stalo nejen standardem, ale i hlavní platformou pro vývoj aplikací ať SaaS nebo dodávaných třetím stranám. Jde o skvělou platformu pro provoz vaší aplikace ať ve veřejném cloudu nebo na vlastním hardwaru popř. on edge blízko koncových uživatelů.",
image: screenshotKubernetes,
icon: logoKubernetes,
},
{
name: 'Monitoring',
summary:
'Sledujte Vaši aplikaci, jak se chová v čase.',
name: "Monitoring",
summary: "Sledujte Vaši aplikaci, jak se chová v čase.",
description:
'Prometheus je standard pro monitoring aplikací, ať v Kubernetes ale i mimo. Sbírejte telemetrická data v čase o vaši aplikaci. Vyhodnoťte, kde má vaše aplikace slabá místa. Zároveň můžete tvořit pravidla, dle kterých vás AlertManager upozorní, když se něco pokazí.',
"Prometheus je standard pro monitoring aplikací, ať v Kubernetes ale i mimo. Sbírejte telemetrická data v čase o vaši aplikaci. Vyhodnoťte, kde má vaše aplikace slabá místa. Zároveň můžete tvořit pravidla, dle kterých vás AlertManager upozorní, když se něco pokazí.",
image: screenshotPrometheus,
icon: logoPrometheus,
},
{
name: 'Vizualizace',
name: "Vizualizace",
summary:
'Od grafů zatížení procesoru po počet otevřených TCP spojení, vše jasně a přehledně.',
"Od grafů zatížení procesoru po počet otevřených TCP spojení, vše jasně a přehledně.",
description:
'Grafana je skvělý nástroj pro vizualizaci dat z monitoringu, vytvořte si dashboardy pro jednotlivé části vaší aplikace, mějte pohromadě infrastrukturu, provoz na síti, dostupnost a třeba počet neúspěšných pokusů o přihlášení, zda vůči vaší aplikaci neprobíhá hackerský útok.',
"Grafana je skvělý nástroj pro vizualizaci dat z monitoringu, vytvořte si dashboardy pro jednotlivé části vaší aplikace, mějte pohromadě infrastrukturu, provoz na síti, dostupnost a třeba počet neúspěšných pokusů o přihlášení, zda vůči vaší aplikaci neprobíhá hackerský útok.",
image: screenshotGrafana,
icon: logoGrafana,
},
{
name: 'GitOps',
name: "GitOps",
summary:
'Spravujte stav Vašich prostředí deklarativně, ať vždy víte, jaký je aktuální stav.',
"Spravujte stav Vašich prostředí deklarativně, ať vždy víte, jaký je aktuální stav.",
description:
'ArgoCD je spolehlivý nástroj pro práci s Kubernetes a nasazováním změn a přitom si udržovat přehled o právě nasazených aplikacích, verzím a konfiguraci, snadno, soplehlivě, verzovaně.',
"ArgoCD je spolehlivý nástroj pro práci s Kubernetes a nasazováním změn a přitom si udržovat přehled o právě nasazených aplikacích, verzím a konfiguraci, snadno, soplehlivě, verzovaně.",
image: screenshotArgoCD,
icon: logoArgo,
},
]
];
type FeatureType = {
name: string|ReactNode,
summary: string,
description: string,
image: StaticImageData,
icon: any,
}
name: string | ReactNode;
summary: string;
description: string;
image: StaticImageData;
icon: any;
};
type FeatureProps = {
feature: FeatureType,
isActive: boolean,
className?: string,
props?: any,
}
feature: FeatureType;
isActive: boolean;
className?: string;
props?: any;
};
function Feature({ feature, isActive, className, ...props }: FeatureProps ) {
function Feature({ feature, isActive, className, ...props }: FeatureProps) {
return (
<div
className={clsx(className, !isActive && 'opacity-75 hover:opacity-100')}
className={clsx(className, !isActive && "opacity-75 hover:opacity-100")}
{...props}
>
<Image src={feature.icon} width="128" height="128" className={clsx(
<Image
src={feature.icon}
width="128"
height="128"
className={clsx(
// 'w-32',
'rounded-lg p-2 flex justify-center',
"flex justify-center rounded-lg p-2"
// isActive ? 'fill-blue-600' : 'fill-slate-500'
)} alt="" />
)}
alt=""
/>
<h3
className={clsx(
'mt-6 text-lg font-medium',
isActive ? 'text-blue-600' : 'text-slate-600'
"mt-6 text-lg font-medium",
isActive ? "text-blue-600" : "text-slate-600"
)}
>
{feature.name}
</h3>
<p className="mt-2 font-display text-xl text-slate-900">
<p className="font-display mt-2 text-xl text-slate-900">
{feature.summary}
</p>
<p className="mt-4 text-sm text-slate-600">{feature.description}</p>
</div>
)
);
}
function FeaturesMobile() {
@ -141,7 +144,7 @@ function FeaturesMobile() {
</div>
))}
</div>
)
);
}
function FeaturesDesktop() {
@ -167,15 +170,15 @@ function FeaturesDesktop() {
/>
))}
</Tab.List>
<Tab.Panels className="relative mt-20 overflow-hidden rounded-4xl bg-slate-200 px-14 py-16 xl:px-16">
<Tab.Panels className="rounded-4xl relative mt-20 overflow-hidden bg-slate-200 px-14 py-16 xl:px-16">
<div className="-mx-5 flex">
{features.map((feature, featureIndex) => (
<Tab.Panel
static
key={feature.name}
className={clsx(
'px-5 transition duration-500 ease-in-out [&:not(:focus-visible)]:focus:outline-none',
featureIndex !== selectedIndex && 'opacity-60'
"px-5 transition duration-500 ease-in-out [&:not(:focus-visible)]:focus:outline-none",
featureIndex !== selectedIndex && "opacity-60"
)}
style={{ transform: `translateX(-${selectedIndex * 100}%)` }}
aria-hidden={featureIndex !== selectedIndex}
@ -193,12 +196,12 @@ function FeaturesDesktop() {
</Tab.Panel>
))}
</div>
<div className="pointer-events-none absolute inset-0 rounded-4xl ring-1 ring-inset ring-slate-900/10" />
<div className="rounded-4xl pointer-events-none absolute inset-0 ring-1 ring-inset ring-slate-900/10" />
</Tab.Panels>
</>
)}
</Tab.Group>
)
);
}
export function TechStack() {
@ -214,13 +217,13 @@ export function TechStack() {
Open Source DevOps stack
</h2>
<p className="mt-4 text-lg tracking-tight text-slate-700">
Věřím v Open Source technologie, prakticky všichni je denně využíváme
a jsou naší budoucností.
Věřím v Open Source technologie, prakticky všichni je denně
využíváme a jsou naší budoucností.
</p>
</div>
<FeaturesMobile />
<FeaturesDesktop />
</Container>
</section>
)
);
}

View file

@ -1,29 +1,29 @@
import Image from 'next/image'
import Image from "next/image";
import { Container } from '@/components/Container'
import avatarImage1 from '@/images/avatars/avatar-1.png'
import avatarImage2 from '@/images/avatars/avatar-2.png'
import avatarImage3 from '@/images/avatars/avatar-3.png'
import avatarImage4 from '@/images/avatars/avatar-4.png'
import avatarImage5 from '@/images/avatars/avatar-5.png'
import { Container } from "@/components/Container";
import avatarImage1 from "@/images/avatars/avatar-1.png";
import avatarImage2 from "@/images/avatars/avatar-2.png";
import avatarImage3 from "@/images/avatars/avatar-3.png";
import avatarImage4 from "@/images/avatars/avatar-4.png";
import avatarImage5 from "@/images/avatars/avatar-5.png";
const testimonials = [
[
{
content:
'TaxPal is so easy to use I cant help but wonder if its really doing the things the government expects me to do.',
"TaxPal is so easy to use I cant help but wonder if its really doing the things the government expects me to do.",
author: {
name: 'Sheryl Berge',
role: 'CEO at Lynch LLC',
name: "Sheryl Berge",
role: "CEO at Lynch LLC",
image: avatarImage1,
},
},
{
content:
'Im trying to get a hold of someone in support, Im in a lot of trouble right now and they are saying it has something to do with my books. Please get back to me right away.',
"Im trying to get a hold of someone in support, Im in a lot of trouble right now and they are saying it has something to do with my books. Please get back to me right away.",
author: {
name: 'Amy Hahn',
role: 'Director at Velocity Industries',
name: "Amy Hahn",
role: "Director at Velocity Industries",
image: avatarImage4,
},
},
@ -31,19 +31,19 @@ const testimonials = [
[
{
content:
'The best part about TaxPal is every time I pay my employees, my bank balance doesnt go down like it used to. Looking forward to spending this extra cash when I figure out why my card is being declined.',
"The best part about TaxPal is every time I pay my employees, my bank balance doesnt go down like it used to. Looking forward to spending this extra cash when I figure out why my card is being declined.",
author: {
name: 'Leland Kiehn',
role: 'Founder of Kiehn and Sons',
name: "Leland Kiehn",
role: "Founder of Kiehn and Sons",
image: avatarImage5,
},
},
{
content:
'There are so many things I had to do with my old software that I just dont do at all with TaxPal. Suspicious but I cant say I dont love it.',
"There are so many things I had to do with my old software that I just dont do at all with TaxPal. Suspicious but I cant say I dont love it.",
author: {
name: 'Erin Powlowski',
role: 'COO at Armstrong Inc',
name: "Erin Powlowski",
role: "COO at Armstrong Inc",
image: avatarImage2,
},
},
@ -51,31 +51,31 @@ const testimonials = [
[
{
content:
'I used to have to remit tax to the EU and with TaxPal I somehow dont have to do that anymore. Nervous to travel there now though.',
"I used to have to remit tax to the EU and with TaxPal I somehow dont have to do that anymore. Nervous to travel there now though.",
author: {
name: 'Peter Renolds',
role: 'Founder of West Inc',
name: "Peter Renolds",
role: "Founder of West Inc",
image: avatarImage3,
},
},
{
content:
'This is the fourth email Ive sent to your support team. I am literally being held in jail for tax fraud. Please answer your damn emails, this is important.',
"This is the fourth email Ive sent to your support team. I am literally being held in jail for tax fraud. Please answer your damn emails, this is important.",
author: {
name: 'Amy Hahn',
role: 'Director at Velocity Industries',
name: "Amy Hahn",
role: "Director at Velocity Industries",
image: avatarImage4,
},
},
],
]
];
function QuoteIcon(props: any) {
return (
<svg aria-hidden="true" width={105} height={78} {...props}>
<path d="M25.086 77.292c-4.821 0-9.115-1.205-12.882-3.616-3.767-2.561-6.78-6.102-9.04-10.622C1.054 58.534 0 53.411 0 47.686c0-5.273.904-10.396 2.712-15.368 1.959-4.972 4.746-9.567 8.362-13.786a59.042 59.042 0 0 1 12.43-11.3C28.325 3.917 33.599 1.507 39.324 0l11.074 13.786c-6.479 2.561-11.677 5.951-15.594 10.17-3.767 4.219-5.65 7.835-5.65 10.848 0 1.356.377 2.863 1.13 4.52.904 1.507 2.637 3.089 5.198 4.746 3.767 2.41 6.328 4.972 7.684 7.684 1.507 2.561 2.26 5.5 2.26 8.814 0 5.123-1.959 9.19-5.876 12.204-3.767 3.013-8.588 4.52-14.464 4.52Zm54.24 0c-4.821 0-9.115-1.205-12.882-3.616-3.767-2.561-6.78-6.102-9.04-10.622-2.11-4.52-3.164-9.643-3.164-15.368 0-5.273.904-10.396 2.712-15.368 1.959-4.972 4.746-9.567 8.362-13.786a59.042 59.042 0 0 1 12.43-11.3C82.565 3.917 87.839 1.507 93.564 0l11.074 13.786c-6.479 2.561-11.677 5.951-15.594 10.17-3.767 4.219-5.65 7.835-5.65 10.848 0 1.356.377 2.863 1.13 4.52.904 1.507 2.637 3.089 5.198 4.746 3.767 2.41 6.328 4.972 7.684 7.684 1.507 2.561 2.26 5.5 2.26 8.814 0 5.123-1.959 9.19-5.876 12.204-3.767 3.013-8.588 4.52-14.464 4.52Z" />
</svg>
)
);
}
export function Testimonials() {
@ -140,5 +140,5 @@ export function Testimonials() {
</ul>
</Container>
</section>
)
);
}

View file

@ -1,45 +1,66 @@
import Image from "next/image"
import Image from "next/image";
import TrainingType from "@/types/training"
import { Container } from "./Container"
import { Button } from "./Button"
import TrainingType from "@/types/training";
import { Container } from "./Container";
import { Button } from "./Button";
type Props = {
training: TrainingType
}
training: TrainingType;
};
export const Training = ({ training }: Props) => {
const formatter = new Intl.NumberFormat('cs', { style: 'currency', currency: 'CZK', maximumFractionDigits: 0})
const formatter = new Intl.NumberFormat("cs", {
style: "currency",
currency: "CZK",
maximumFractionDigits: 0,
});
return (
<>
<div className="pb-14 sm:pb-20 lg:pb-32">
<div className="bg-slate-900 pt-16 pb-16">
<div className="bg-slate-900 pt-16 pb-16">
<Container className="flex justify-around">
<Image src={training.logo} className="h-40 w-40 rounded-full" width="1500" height="1500" alt="" />
<h2 className="font-display text-4xl tracking-tight text-white sm:text-6xl self-center">
<Image
src={training.logo}
className="h-40 w-40 rounded-full"
width="1500"
height="1500"
alt=""
/>
<h2 className="font-display self-center text-4xl tracking-tight text-white sm:text-6xl">
Školení {training.name}
</h2>
</Container>
</div>
</Container>
</div>
<Container>
<div className="md:grid md:grid-cols-5 md:gap-x-4 md:gap-y-4 mt-12">
<div className="mt-12 md:grid md:grid-cols-5 md:gap-x-4 md:gap-y-4">
<div className="md:col-span-3">
<div className="prose prose-slate prose-h1:text-2xl prose-h2:text-xl prose-h3:text-lg prose-h1:font-medium prose-h2:font-medium prose-h3:font-medium prose-li:my-0" dangerouslySetInnerHTML={{ __html: training.content }} />
<div
className="prose prose-slate prose-h1:text-2xl prose-h1:font-medium prose-h2:text-xl prose-h2:font-medium prose-h3:text-lg prose-h3:font-medium prose-li:my-0"
dangerouslySetInnerHTML={{ __html: training.content }}
/>
</div>
<div className="md:col-span-2 mt-8 md:mt-0">
{ training.days === 2 ? (
<div className=" bg-blue-50 p-4 rounded-lg shadow mb-8">
<div className="mt-8 md:col-span-2 md:mt-0">
{training.days === 2 ? (
<div className=" mb-8 rounded-lg bg-blue-50 p-4 shadow">
<div className="flex">
<div className="flex-shrink-0">
{/* <ExclamationTriangleIcon className="h-5 w-5 text-yellow-400" aria-hidden="true" /> */}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-5 h-5 text-blue-400">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="h-5 w-5 text-blue-400"
>
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
clip-rule="evenodd"
/>
</svg>
</div>
<div className="ml-3">
<p className="text-blue-700">
Toto školení je{' '}
Toto školení je{" "}
<span className="font-medium text-blue-700">
dvoudenní.
</span>
@ -47,20 +68,32 @@ export const Training = ({ training }: Props) => {
</div>
</div>
</div>
) : <></>}
<div className="overflow-hidden bg-slate-50 shadow rounded-lg mt-8 md:mt-0">
) : (
<></>
)}
<div className="mt-8 overflow-hidden rounded-lg bg-slate-50 shadow md:mt-0">
<div className="px-4 py-5 sm:px-6">
<h3 className="text-lg font-medium leading-6 text-slate-900" >Cena za školení</h3>
<h3 className="text-lg font-medium leading-6 text-slate-900">
Cena za školení
</h3>
</div>
<div className="border-t border-gray-200 px-4 py-5">
<dl className="sm:divide-y sm:divide-gray-200">
<div className="py-4 sm:grid sm:grid-cols-2 sm:gap-4 sm:py-5 sm:px-6">
<dt className="font-medium text-gray-500">Veřejný termín</dt>
<dd className="mt-1 text-gray-900 sm:mt-0">{formatter.format(training.priceOpen)} bez DPH</dd>
<dt className="font-medium text-gray-500">
Veřejný termín
</dt>
<dd className="mt-1 text-gray-900 sm:mt-0">
{formatter.format(training.priceOpen)} bez DPH
</dd>
</div>
<div className="py-4 sm:grid sm:grid-cols-2 sm:gap-4 sm:py-5 sm:px-6">
<dt className="font-medium text-gray-500">Firemní školení</dt>
<dd className="mt-1 text-gray-900 sm:mt-0">{formatter.format(training.priceCompany)} bez DPH</dd>
<dt className="font-medium text-gray-500">
Firemní školení
</dt>
<dd className="mt-1 text-gray-900 sm:mt-0">
{formatter.format(training.priceCompany)} bez DPH
</dd>
</div>
</dl>
</div>
@ -80,5 +113,5 @@ export const Training = ({ training }: Props) => {
</Container>
</div>
</>
)
}
);
};

View file

@ -1,117 +1,136 @@
import Image from "next/image"
import clsx from "clsx"
import Image from "next/image";
import clsx from "clsx";
import TrainingType from "@/types/training"
import { Container } from "./Container"
import { Button } from "./Button"
import TrainingType from "@/types/training";
import { Container } from "./Container";
import { Button } from "./Button";
type TrainingDetailProps = {
training: TrainingType,
className?: string,
props?: any[],
}
training: TrainingType;
className?: string;
props?: any[];
};
const TrainingDetail = ({ training, className, ...props }: TrainingDetailProps) => {
const TrainingDetail = ({
training,
className,
...props
}: TrainingDetailProps) => {
return (
<div
className={
clsx(className,
"rounded-3xl shadow py-8 px-6 sm:px-8",
training.featured ? 'bg-blue-600 py-8' : ''
)
}
className={clsx(
className,
"rounded-3xl py-8 px-6 shadow sm:px-8",
training.featured ? "bg-blue-600 py-8" : ""
)}
{...props}
>
<Image src={training.logo} className="h-32 w-32 rounded-full" width="1500" height="1500" alt="" />
<div className="flex justify-between mt-6">
<Image
src={training.logo}
className="h-32 w-32 rounded-full"
width="1500"
height="1500"
alt=""
/>
<div className="mt-6 flex justify-between">
<div className="flex">
<h3
className="text-xl font-display font-medium text-white"
>
<h3 className="font-display text-xl font-medium text-white">
{training.name}
</h3>
{ training.new ? (
{training.new ? (
<>
<span className="ml-2 rounded-full bg-orange-100 px-2 py-1 text-xs font-medium text-orange-800 border border-1 border-orange-800">
<span className="border-1 ml-2 rounded-full border border-orange-800 bg-orange-100 px-2 py-1 text-xs font-medium text-orange-800">
new!
</span>
</>
) : <></> }
) : (
<></>
)}
</div>
<p className="max-w-2xl text-md text-white">{training.days}{' '}{training.days === 1 ? 'den' : 'dny'}</p>
<p className="text-md max-w-2xl text-white">
{training.days} {training.days === 1 ? "den" : "dny"}
</p>
</div>
<p className={
clsx(
"mt-4 text-md",
training.featured ? 'text-white' : 'text-slate-200'
<p
className={clsx(
"text-md mt-4",
training.featured ? "text-white" : "text-slate-200"
)}
>
{training.description.split(" ").splice(0,40).join(" ") + "..."}
{training.description.split(" ").splice(0, 40).join(" ") + "..."}
</p>
<Button
href={"/skoleni/" + training.slug}
variant={training.featured ? 'solid' : 'outline'}
variant={training.featured ? "solid" : "outline"}
color="white"
className="mt-8 w-full"
>
Zjistit více
</Button>
</div>
)
}
);
};
type TrainingListProps = {
trainingList: TrainingType[]
}
trainingList: TrainingType[];
};
const TrainingListMobile = ({ trainingList }: TrainingListProps) => {
return (
<div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden sm:-mx-6 sm:px-6 lg:hidden">
{trainingList.map((training) => (
<div key={training.slug} className={clsx(training.featured ? 'order-first lg:order-none' : '')}>
<div
key={training.slug}
className={clsx(training.featured ? "order-first lg:order-none" : "")}
>
<TrainingDetail training={training} className="mx-auto max-w-2xl" />
</div>
))}
</div>
)
}
);
};
const TrainingListDesktop = ({ trainingList }: TrainingListProps) => {
return (
<div className="hidden lg:mt-20 lg:block">
<div className="grid grid-cols-3 gap-x-8 gap-y-8"
>
<div className="grid grid-cols-3 gap-x-8 gap-y-8">
{trainingList.map((training) => (
<div key={training.slug} className={clsx(training.featured ? 'order-first lg:order-none' : '')}>
<div
key={training.slug}
className={clsx(
training.featured ? "order-first lg:order-none" : ""
)}
>
<TrainingDetail training={training} className="relative" />
</div>
))}
</div>
</div>
)
}
);
};
export const TrainingListGrid = ({ trainingList }: TrainingListProps) => {
return (
<>
<section
id="training-list"
aria-label="Seznam školení"
className="pt-16 pb-14 sm:pb-20 sm:pt-24 lg:pb-32 bg-slate-900"
id="training-list"
aria-label="Seznam školení"
className="bg-slate-900 pt-16 pb-14 sm:pb-20 sm:pt-24 lg:pb-32"
>
<Container>
<div className="mx-auto max-w-2xl md:text-center">
<h2 className="font-display text-3xl tracking-tight text-white sm:text-4xl">
Moje školení
Moje školení
</h2>
<p className="mt-4 text-lg tracking-tight text-slate-400">
Od veřejného cloudu přes on-premise po serverless, se vším vám poradím.
Od veřejného cloudu přes on-premise po serverless, se vším vám
poradím.
</p>
</div>
<TrainingListMobile trainingList={trainingList} />
<TrainingListDesktop trainingList={trainingList} />
<TrainingListDesktop trainingList={trainingList} />
</Container>
</section>
</>
)
}
);
};