add
This commit is contained in:
11
superpage/package-lock.json
generated
11
superpage/package-lock.json
generated
@@ -26,6 +26,7 @@
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-hook-form": "^7.56.0",
|
||||
"smartypants": "^0.2.2",
|
||||
"tailwindcss": "^4.0.13",
|
||||
"vanilla-cookieconsent": "^3.1.0",
|
||||
"zod": "^3.24.3"
|
||||
@@ -7120,6 +7121,16 @@
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/smartypants": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/smartypants/-/smartypants-0.2.2.tgz",
|
||||
"integrity": "sha512-TzobUYoEft/xBtb2voRPryAUIvYguG0V7Tt3de79I1WfXgCwelqVsGuZSnu3GFGRZhXR90AeEYIM+icuB/S06Q==",
|
||||
"license": "BSD-3-Clause",
|
||||
"bin": {
|
||||
"smartypants": "bin/smartypants.js",
|
||||
"smartypantsu": "bin/smartypantsu.js"
|
||||
}
|
||||
},
|
||||
"node_modules/smol-toml": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.4.tgz",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-hook-form": "^7.56.0",
|
||||
"smartypants": "^0.2.2",
|
||||
"tailwindcss": "^4.0.13",
|
||||
"vanilla-cookieconsent": "^3.1.0",
|
||||
"zod": "^3.24.3"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<slot name="label" />
|
||||
</summary>
|
||||
<div
|
||||
class="absolute right-0 top-full translate-y-1 bg-stone-900 p-2.5 border border-white/15 min-w-56 rounded-lg shadow drop-shadow"
|
||||
class="absolute right-0 top-full translate-y-1 bg-stone-900 border border-white/15 min-w-74 rounded-lg shadow drop-shadow"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ const courses = await getCollection(
|
||||
({ data }) => data.draft != true,
|
||||
);
|
||||
|
||||
const { title } = Astro.props;
|
||||
const { title, course } = Astro.props;
|
||||
---
|
||||
|
||||
<nav class="sticky top-0 z-10 bg-lime-400 py-3 drop-shadow shadow-sm">
|
||||
@@ -27,8 +27,18 @@ const { title } = Astro.props;
|
||||
|
||||
<BuyDropdown class="ml-auto">
|
||||
<Fragment slot="label">Contratar agora</Fragment>
|
||||
<ul>
|
||||
<li>...</li>
|
||||
<ul class="divide-y divide-white/10">
|
||||
<li class="uppercase py-2.5 px-5">EDUSEG® Flexível</li>
|
||||
<li class="uppercase py-2.5 px-5">EDUSEG® In-Company</li>
|
||||
<li class="uppercase py-2.5 px-5">EDUSEG® Conteúdo</li>
|
||||
<li class="py-2.5 px-5">
|
||||
Contratar {
|
||||
new Intl.NumberFormat("pt-BR", {
|
||||
style: "currency",
|
||||
currency: "BRL",
|
||||
}).format(course.unit_price)
|
||||
} p/ matrícula
|
||||
</li>
|
||||
</ul>
|
||||
</BuyDropdown>
|
||||
</Container>
|
||||
|
||||
@@ -30,7 +30,9 @@ import Modal from "~/components/Modal.astro";
|
||||
<h2 class="text-xl/6 font-semibold">
|
||||
Catálogo completo sempre à sua disposição
|
||||
</h2>
|
||||
<ul class="list-disc max-lg:pl-3.5 space-y-1.5 text-sm/5">
|
||||
<ul
|
||||
class="list-disc max-lg:pl-3.5 space-y-1.5 text-sm/5 marker:text-lime-400"
|
||||
>
|
||||
<li>Acesse todos os cursos imediatamente</li>
|
||||
<li>Pague apenas pelo que usar, mês a mês</li>
|
||||
<li>Gestão e autonomia direto pela plataforma</li>
|
||||
@@ -58,7 +60,9 @@ import Modal from "~/components/Modal.astro";
|
||||
<h2 class="text-xl/6 font-semibold">
|
||||
Treinamento presencial na sua empresa
|
||||
</h2>
|
||||
<ul class="list-disc max-lg:pl-3.5 space-y-1.5 text-sm/5">
|
||||
<ul
|
||||
class="list-disc max-lg:pl-3.5 space-y-1.5 text-sm/5 marker:text-lime-400"
|
||||
>
|
||||
<li>Atendemos nas principais cidades do Brasil</li>
|
||||
<li>Instrutores especialistas com vivência prática</li>
|
||||
<li>Ideal para grandes turmas ou treinamentos práticos</li>
|
||||
@@ -85,7 +89,9 @@ import Modal from "~/components/Modal.astro";
|
||||
<h2 class="text-xl/6 font-semibold">
|
||||
Leve nosso conteúdo para sua plataforma
|
||||
</h2>
|
||||
<ul class="list-disc max-lg:pl-3.5 space-y-1.5 text-sm/5">
|
||||
<ul
|
||||
class="list-disc max-lg:pl-3.5 space-y-1.5 text-sm/5 marker:text-lime-400"
|
||||
>
|
||||
<li>Customização completa com sua identidade visual</li>
|
||||
<li>Entregamos em formato SCORM para qualquer LMS</li>
|
||||
<li>Ideal para empresas com ambiente EAD próprio</li>
|
||||
@@ -104,3 +110,7 @@ import Modal from "~/components/Modal.astro";
|
||||
</div>
|
||||
</section>
|
||||
</Container>
|
||||
|
||||
<script is:inline>
|
||||
console.log(window);
|
||||
</script>
|
||||
|
||||
99
superpage/src/components/SEO.astro
Normal file
99
superpage/src/components/SEO.astro
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
export type Image = {
|
||||
src: string;
|
||||
alt: string;
|
||||
};
|
||||
export type SEOMetadata = {
|
||||
name: string;
|
||||
title: string;
|
||||
description: string;
|
||||
image: Image;
|
||||
canonicalURL?: URL | string | null;
|
||||
locale?: string;
|
||||
};
|
||||
export type OpenGraph = Partial<SEOMetadata> & {
|
||||
type?: string;
|
||||
};
|
||||
export type Twitter = Partial<SEOMetadata> & {
|
||||
handle?: string;
|
||||
card?: "summary" | "summary_large_image";
|
||||
};
|
||||
export type Props = SEOMetadata & {
|
||||
og?: OpenGraph;
|
||||
twitter?: Twitter;
|
||||
};
|
||||
const {
|
||||
name,
|
||||
title,
|
||||
description,
|
||||
image,
|
||||
locale = "en",
|
||||
canonicalURL = new URL(Astro.url.pathname, Astro.site),
|
||||
} = Astro.props;
|
||||
|
||||
const og = {
|
||||
name,
|
||||
title,
|
||||
description,
|
||||
canonicalURL,
|
||||
image,
|
||||
locale,
|
||||
type: "website",
|
||||
...Astro.props.og,
|
||||
} satisfies OpenGraph;
|
||||
|
||||
const twitter = {
|
||||
name,
|
||||
title,
|
||||
description,
|
||||
canonicalURL,
|
||||
image,
|
||||
locale,
|
||||
card: "summary_large_image",
|
||||
...Astro.props.twitter,
|
||||
} satisfies Twitter;
|
||||
|
||||
/**
|
||||
* Enforce some standard canonical URL formatting across the site.
|
||||
*/
|
||||
function formatCanonicalURL(url: string | URL) {
|
||||
const path = url.toString();
|
||||
const hasQueryParams = path.includes("?");
|
||||
// If there are query params, make sure the URL has no trailing slash
|
||||
if (hasQueryParams) {
|
||||
path.replace(/\/?$/, "");
|
||||
}
|
||||
// otherwise, canonical URL always has a trailing slash
|
||||
return path.replace(/\/?$/, hasQueryParams ? "" : "/");
|
||||
}
|
||||
---
|
||||
|
||||
{/* Page Metadata */}
|
||||
{
|
||||
canonicalURL && (
|
||||
<link rel="canonical" href={formatCanonicalURL(canonicalURL)} />
|
||||
)
|
||||
}
|
||||
<meta name="description" content={description} />
|
||||
|
||||
{/* OpenGraph Tags */}
|
||||
<meta property="og:title" content={og.title} />
|
||||
<meta property="og:type" content={og.type} />
|
||||
{
|
||||
og.canonicalURL && (
|
||||
<meta property="og:url" content={formatCanonicalURL(og.canonicalURL)} />
|
||||
)
|
||||
}
|
||||
<meta property="og:locale" content={og.locale} />
|
||||
<meta property="og:description" content={og.description} />
|
||||
<meta property="og:site_name" content={og.name} />
|
||||
{og.image && <meta property="og:image" content={og.image.src} />}
|
||||
{og.image && <meta property="og:image:alt" content={og.image.alt} />}
|
||||
|
||||
{/* Twitter Tags */}
|
||||
{twitter.card && <meta name="twitter:card" content={twitter.card} />}
|
||||
{twitter.handle && <meta name="twitter:site" content={twitter.handle} />}
|
||||
<meta name="twitter:title" content={twitter.title} />
|
||||
<meta name="twitter:description" content={twitter.description} />
|
||||
{twitter.image && <meta name="twitter:image" content={twitter.image.src} />}
|
||||
{twitter.image && <meta name="twitter:image:alt" content={twitter.image.alt} />}
|
||||
37
superpage/src/data/site-info.ts
Normal file
37
superpage/src/data/site-info.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export type SocialLink = {
|
||||
me?: string;
|
||||
/** Longer descriptive label, e.g. `"Join the Astro community on Discord"` */
|
||||
text: string;
|
||||
/** Short label with the name of the platform, e.g. `"Discord"`*/
|
||||
label: string;
|
||||
icon: string;
|
||||
href: string;
|
||||
/** Platform ID, e.g. `"discord"` */
|
||||
platform: string;
|
||||
footerOnly?: boolean;
|
||||
};
|
||||
|
||||
export type SiteInfo = {
|
||||
name: string;
|
||||
title: string;
|
||||
description: string;
|
||||
image: {
|
||||
src: string;
|
||||
alt: string;
|
||||
};
|
||||
socialLinks: SocialLink[];
|
||||
};
|
||||
|
||||
const siteInfo: SiteInfo = {
|
||||
name: "EDUSEG®",
|
||||
title: " Educação que garante sua segurança",
|
||||
description:
|
||||
"Astro builds fast content sites, powerful web applications, dynamic server APIs, and everything in-between.",
|
||||
image: {
|
||||
src: "/og/social.jpg",
|
||||
alt: "Educação que garante sua segurança",
|
||||
},
|
||||
socialLinks: [],
|
||||
};
|
||||
|
||||
export default siteInfo;
|
||||
@@ -1,22 +1,18 @@
|
||||
---
|
||||
import "~/styles/app.css";
|
||||
import BaseHead, {
|
||||
type Props as HeadProps,
|
||||
} from "./_components/BaseHead.astro";
|
||||
import Header from "./_components/Header.astro";
|
||||
import Footer from "./_components/Footer.astro";
|
||||
|
||||
interface Props extends HeadProps {}
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="pt-br">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<slot name="head">
|
||||
<title>
|
||||
Educação que garante sua segurança — EDUSEG®
|
||||
</title>
|
||||
</slot>
|
||||
<BaseHead {...Astro.props} />
|
||||
|
||||
<script
|
||||
is:inline
|
||||
@@ -31,7 +27,6 @@ import Footer from "./_components/Footer.astro";
|
||||
data-type="text/partytown"
|
||||
data-category="analytics"
|
||||
>
|
||||
console.log("a");
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
@@ -47,7 +42,7 @@ import Footer from "./_components/Footer.astro";
|
||||
|
||||
<slot name="nav" />
|
||||
|
||||
<main id="content" data-pagefind-body>
|
||||
<main id="main" data-pagefind-body>
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
|
||||
50
superpage/src/layouts/_components/BaseHead.astro
Normal file
50
superpage/src/layouts/_components/BaseHead.astro
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
import smartypants from "smartypants";
|
||||
import siteInfo from "~/data/site-info";
|
||||
import SEO from "~/components/SEO.astro";
|
||||
|
||||
export type Props = {
|
||||
title?: string;
|
||||
rawTitle?: string;
|
||||
description?: string;
|
||||
image?: { src: string; alt: string };
|
||||
canonicalURL?: URL | null;
|
||||
pageType?: "website" | "article";
|
||||
};
|
||||
|
||||
const twitterHandle = "edusegdotcomdotbr";
|
||||
|
||||
const {
|
||||
rawTitle,
|
||||
description = siteInfo.description,
|
||||
image = siteInfo.image,
|
||||
canonicalURL = new URL(Astro.request.url, Astro.site),
|
||||
pageType = "website",
|
||||
} = Astro.props;
|
||||
|
||||
const title =
|
||||
rawTitle ??
|
||||
[Astro.props.title, siteInfo.name].filter(Boolean).join(" — ");
|
||||
const resolvedImage = {
|
||||
src: new URL(image.src, Astro.site).toString(),
|
||||
alt: image.alt,
|
||||
};
|
||||
---
|
||||
|
||||
{/* High Priority Global Metadata */}
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title set:html={smartypants(title, 1)} />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
|
||||
<SEO
|
||||
name={siteInfo.name}
|
||||
title={title}
|
||||
description={description}
|
||||
image={resolvedImage}
|
||||
twitter={{ handle: twitterHandle }}
|
||||
og={{ type: pageType }}
|
||||
canonicalURL={canonicalURL}
|
||||
/>
|
||||
@@ -28,7 +28,7 @@ const { data } = course;
|
||||
const { Content } = await render(course);
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Layout title={data.title}>
|
||||
<Fragment slot="head">
|
||||
<title>{data.title} — EDUSEG®</title>
|
||||
</Fragment>
|
||||
|
||||
@@ -71,6 +71,7 @@ const currency = new Intl.NumberFormat("pt-BR", {
|
||||
|
||||
const r = await checkout(item);
|
||||
const json = await r.json();
|
||||
target.disabled = true;
|
||||
location.href = `https://checkout.betaeducacao.com.br/${json.id}`;
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user