mirror of
https://github.com/PeterMaquiran/tvone.git
synced 2026-04-18 07:17:52 +00:00
inicila commit
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
const destaques = [
|
||||
{
|
||||
cat: "FAMOSOS",
|
||||
catColor: "text-pink-600",
|
||||
title: "Cerimónia reúne estrelas nacionais e internacionais em Lisboa.",
|
||||
date: "24 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=600&q=80",
|
||||
},
|
||||
{
|
||||
cat: "NEGÓCIOS",
|
||||
catColor: "text-[#0066cc]",
|
||||
title: "Mercados reagem às novas projeções de crescimento para a região.",
|
||||
date: "24 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1486406146926-c627a92ad4ab?w=600&q=80",
|
||||
},
|
||||
{
|
||||
cat: "DESPORTO",
|
||||
catColor: "text-emerald-600",
|
||||
title: "Taça: equipa da casa garante lugar nas meias com exibição sólida.",
|
||||
date: "23 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1574629810360-7efbbe195018?w=600&q=80",
|
||||
},
|
||||
{
|
||||
cat: "TECNOLOGIA",
|
||||
catColor: "text-violet-600",
|
||||
title: "Novos dispositivos chegam às lojas com foco em sustentabilidade.",
|
||||
date: "23 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1518770660439-4636190af475?w=600&q=80",
|
||||
},
|
||||
];
|
||||
|
||||
const recentes = [
|
||||
{
|
||||
cat: "EM FOCO",
|
||||
catBg: "bg-pink-100 text-pink-700",
|
||||
title: "Governo anuncia medidas para apoiar famílias e pequenas empresas.",
|
||||
excerpt: "Pacote inclui linhas de crédito e simplificação de procedimentos.",
|
||||
byline: "Por Redação",
|
||||
date: "24 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1507679799987-c73779587ccf?w=200&q=80",
|
||||
},
|
||||
{
|
||||
cat: "ECONOMIA",
|
||||
catBg: "bg-amber-100 text-amber-800",
|
||||
title: "Inflação desce pelo terceiro mês consecutivo, segundo dados preliminares.",
|
||||
excerpt: "Analistas mantêm cautela face ao cenário internacional.",
|
||||
byline: "Por Economia",
|
||||
date: "24 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?w=200&q=80",
|
||||
},
|
||||
{
|
||||
cat: "CULTURA",
|
||||
catBg: "bg-violet-100 text-violet-800",
|
||||
title: "Museu inaugura exposição com obras inéditas de artistas locais.",
|
||||
excerpt: "Visitas guiadas e programa educativo arrancam no próximo fim de semana.",
|
||||
byline: "Por Cultura",
|
||||
date: "23 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1549887534-1541e9326642?w=200&q=80",
|
||||
},
|
||||
{
|
||||
cat: "SAÚDE",
|
||||
catBg: "bg-emerald-100 text-emerald-800",
|
||||
title: "Campanha de vacinação alarga faixas etárias em todo o país.",
|
||||
excerpt: "Autoridades de saúde reforçam importância da adesão às janelas recomendadas.",
|
||||
byline: "Por Saúde",
|
||||
date: "23 Mar 2025",
|
||||
img: "https://images.unsplash.com/photo-1576091160399-112ba8d25d1d?w=200&q=80",
|
||||
},
|
||||
];
|
||||
|
||||
const aSeguir = [
|
||||
{
|
||||
title: "Mercado imobiliário: especialistas explicam tendências para 2025.",
|
||||
date: "23 Mar",
|
||||
img: "https://images.unsplash.com/photo-1560518883-ce09059eeffa?w=120&q=80",
|
||||
},
|
||||
{
|
||||
title: "Cinema: estreia nacional bate recordes de bilheteira no primeiro fim de semana.",
|
||||
date: "22 Mar",
|
||||
img: "https://images.unsplash.com/photo-1489599849927-2ee91cede3ba?w=120&q=80",
|
||||
},
|
||||
{
|
||||
title: "Ambiente: projeto de reflorestação ultrapassa meta anual em três meses.",
|
||||
date: "22 Mar",
|
||||
img: "https://images.unsplash.com/photo-1448375240586-882707db888d?w=120&q=80",
|
||||
},
|
||||
];
|
||||
|
||||
export function TvoneDestaques() {
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-[1200px] px-4 pb-10">
|
||||
<h2 className="mb-5 text-xl font-bold tracking-tight text-neutral-900">Destaques</h2>
|
||||
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{destaques.map((item) => (
|
||||
<article
|
||||
key={item.title}
|
||||
className="group overflow-hidden rounded-xl border border-neutral-200/80 bg-white shadow-sm transition hover:shadow-md"
|
||||
>
|
||||
<Link href="#" className="block">
|
||||
<div className="relative aspect-[4/3] w-full overflow-hidden">
|
||||
<Image
|
||||
src={item.img}
|
||||
alt=""
|
||||
fill
|
||||
className="object-cover transition duration-300 group-hover:scale-[1.03]"
|
||||
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw"
|
||||
/>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<p className={`mb-2 text-[11px] font-bold uppercase tracking-wide ${item.catColor}`}>{item.cat}</p>
|
||||
<h3 className="text-[15px] font-semibold leading-snug text-neutral-900">{item.title}</h3>
|
||||
<p className="mt-3 text-xs text-neutral-500">{item.date}</p>
|
||||
</div>
|
||||
</Link>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export function TvoneMainColumns() {
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-[1200px] gap-10 px-4 pb-12 lg:grid-cols-[1fr_340px]">
|
||||
<section>
|
||||
<h2 className="mb-6 text-xl font-bold tracking-tight text-neutral-900">Mais Recentes</h2>
|
||||
<ul className="flex flex-col gap-6">
|
||||
{recentes.map((item) => (
|
||||
<li key={item.title}>
|
||||
<Link href="#" className="group flex gap-4 rounded-xl border border-transparent p-1 transition hover:border-neutral-200 hover:bg-neutral-50">
|
||||
<div className="relative h-24 w-28 shrink-0 overflow-hidden rounded-lg sm:h-28 sm:w-36">
|
||||
<Image src={item.img} alt="" fill className="object-cover" sizes="144px" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<span className={`inline-block rounded px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide ${item.catBg}`}>
|
||||
{item.cat}
|
||||
</span>
|
||||
<h3 className="mt-2 text-base font-semibold leading-snug text-neutral-900 group-hover:text-[#0066cc]">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="mt-1 line-clamp-2 text-sm text-neutral-600">{item.excerpt}</p>
|
||||
<p className="mt-2 text-xs text-neutral-500">
|
||||
{item.byline} · {item.date}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Link
|
||||
href="#"
|
||||
className="mt-8 flex w-full items-center justify-center rounded-xl bg-[#f5f5f7] py-3 text-sm font-medium text-neutral-800 transition hover:bg-neutral-200/80"
|
||||
>
|
||||
Ver todas as notícias
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
<aside className="flex flex-col gap-8">
|
||||
<div className="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm">
|
||||
<div className="flex items-center gap-2 border-b border-neutral-100 px-4 py-3">
|
||||
<svg className="h-5 w-5 text-neutral-800" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
|
||||
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" />
|
||||
</svg>
|
||||
<span className="text-sm font-semibold text-neutral-800">Apple Line</span>
|
||||
</div>
|
||||
<div className="relative aspect-[16/10] w-full">
|
||||
<Image
|
||||
src="https://images.unsplash.com/photo-1486406146926-c627a92ad4ab?w=680&q=80"
|
||||
alt=""
|
||||
fill
|
||||
className="object-cover"
|
||||
sizes="340px"
|
||||
/>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<span className="text-[11px] font-bold uppercase tracking-wide text-[#0066cc]">Bancos</span>
|
||||
<h3 className="mt-2 text-lg font-bold leading-snug text-neutral-900">
|
||||
BAI regista lucros acima das expectativas no último trimestre.
|
||||
</h3>
|
||||
<p className="mt-2 text-xs text-neutral-500">24 Mar 2025</p>
|
||||
<Link
|
||||
href="#"
|
||||
className="mt-4 flex w-full items-center justify-center rounded-lg bg-neutral-900 py-2.5 text-sm font-medium text-white transition hover:bg-neutral-800"
|
||||
>
|
||||
Ver Página Apple Line
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="mb-4 text-lg font-bold text-neutral-900">A seguir</h3>
|
||||
<ul className="flex flex-col gap-4">
|
||||
{aSeguir.map((item) => (
|
||||
<li key={item.title}>
|
||||
<Link href="#" className="group flex gap-3">
|
||||
<div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-lg">
|
||||
<Image src={item.img} alt="" fill className="object-cover" sizes="64px" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="text-sm font-medium leading-snug text-neutral-900 group-hover:text-[#0066cc]">{item.title}</p>
|
||||
<p className="mt-1 text-xs text-neutral-500">{item.date}</p>
|
||||
</div>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TvoneAdBanner() {
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-[1200px] px-4 pb-10">
|
||||
<div className="relative overflow-hidden rounded-xl bg-gradient-to-r from-[#0a4d8c] via-[#1e6fb8] to-[#e85c2a] px-6 py-8 text-white md:flex md:items-center md:justify-between md:py-10">
|
||||
<div className="max-w-lg">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-widest text-white/90">BAI Directo</p>
|
||||
<h2 className="mt-2 text-2xl font-bold md:text-3xl">Actualização do BAI Directo</h2>
|
||||
<p className="mt-2 text-sm text-white/90">Faça as suas operações com mais rapidez e segurança em qualquer dispositivo.</p>
|
||||
</div>
|
||||
<div className="relative mt-6 h-32 w-full max-w-xs shrink-0 md:mt-0 md:h-36">
|
||||
<Image
|
||||
src="https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=400&q=80"
|
||||
alt=""
|
||||
fill
|
||||
className="object-contain object-right"
|
||||
sizes="320px"
|
||||
/>
|
||||
</div>
|
||||
<span className="absolute right-6 top-1/2 hidden -translate-y-1/2 text-2xl font-black tracking-tight opacity-90 md:block">
|
||||
BAI
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
const services = [
|
||||
{ icon: "truck", label: "Entrega gratuita" },
|
||||
{ icon: "return", label: "Devoluções fáceis" },
|
||||
{ icon: "shield", label: "Pagamento seguro" },
|
||||
{ icon: "headset", label: "Apoio 24/7" },
|
||||
];
|
||||
|
||||
function ServiceIcon({ name }: { name: string }) {
|
||||
const common = "h-6 w-6 text-neutral-600";
|
||||
switch (name) {
|
||||
case "truck":
|
||||
return (
|
||||
<svg className={common} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
<path d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m-4 0a2 2 0 114 0m6 0a2 2 0 104 0m-4 0a2 2 0 114 0" />
|
||||
</svg>
|
||||
);
|
||||
case "return":
|
||||
return (
|
||||
<svg className={common} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.5">
|
||||
<path d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
);
|
||||
case "shield":
|
||||
return (
|
||||
<svg className={common} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.5">
|
||||
<path d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||
</svg>
|
||||
);
|
||||
case "headset":
|
||||
return (
|
||||
<svg className={common} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.5">
|
||||
<path d="M19 14v3a2 2 0 01-2 2h-2v-6h2a2 2 0 012 2zm-8 5H7a2 2 0 01-2-2v-3a2 2 0 012-2h2v7z" />
|
||||
<path d="M5 14v-1a7 7 0 0114 0v1" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function TvoneServiceStrip() {
|
||||
return (
|
||||
<div className="border-y border-neutral-200 bg-[#f5f5f7] py-6">
|
||||
<div className="mx-auto flex max-w-[1200px] flex-wrap items-center justify-center gap-8 px-4 md:justify-between md:gap-4">
|
||||
{services.map((s) => (
|
||||
<div key={s.label} className="flex items-center gap-3 text-sm text-neutral-700">
|
||||
<ServiceIcon name={s.icon} />
|
||||
<span className="font-medium">{s.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TvoneFooter() {
|
||||
return (
|
||||
<footer className="border-t border-neutral-200 bg-white py-10">
|
||||
<div className="mx-auto flex max-w-[1200px] flex-col gap-8 px-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<p className="text-lg font-bold tracking-tight text-neutral-900">PLATINALINE</p>
|
||||
<p className="mt-1 text-sm text-neutral-500">© 2025 PlatinaLine. Todos os direitos reservados.</p>
|
||||
</div>
|
||||
<nav className="flex flex-wrap gap-x-6 gap-y-2 text-sm text-neutral-600">
|
||||
<Link href="#" className="hover:text-neutral-900">
|
||||
Privacidade
|
||||
</Link>
|
||||
<Link href="#" className="hover:text-neutral-900">
|
||||
Termos de Uso
|
||||
</Link>
|
||||
<Link href="#" className="hover:text-neutral-900">
|
||||
Publicidade
|
||||
</Link>
|
||||
<Link href="#" className="hover:text-neutral-900">
|
||||
Contactos
|
||||
</Link>
|
||||
</nav>
|
||||
<div className="flex items-center gap-4 text-neutral-500">
|
||||
<Link href="#" aria-label="Facebook" className="hover:text-neutral-800">
|
||||
f
|
||||
</Link>
|
||||
<Link href="#" aria-label="Instagram" className="hover:text-neutral-800">
|
||||
in
|
||||
</Link>
|
||||
<Link href="#" aria-label="YouTube" className="hover:text-neutral-800">
|
||||
▶
|
||||
</Link>
|
||||
<Link href="#" aria-label="X" className="hover:text-neutral-800">
|
||||
𝕏
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
const PROMO_IMG_LEFT =
|
||||
"https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=800&q=80&auto=format&fit=crop";
|
||||
const PROMO_IMG_RIGHT =
|
||||
"https://images.unsplash.com/photo-1544367567-0f2fcb009e0b?w=800&q=80&auto=format&fit=crop";
|
||||
|
||||
const appleNav = [
|
||||
"Loja",
|
||||
"Mac",
|
||||
"iPad",
|
||||
"iPhone",
|
||||
"Watch",
|
||||
"AirPods",
|
||||
"TV e Casa",
|
||||
"Entretenimento",
|
||||
"Acessórios",
|
||||
"Suporte",
|
||||
];
|
||||
|
||||
function AppleLogo({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg aria-hidden className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function SearchIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 15 15" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.2">
|
||||
<circle cx="6.5" cy="6.5" r="5" />
|
||||
<path d="M10 10l3.5 3.5" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function BagIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="1.5">
|
||||
<path d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" strokeLinejoin="round" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function TvoneHeader() {
|
||||
return (
|
||||
<header className="w-full">
|
||||
<nav
|
||||
className="flex h-11 items-center justify-center gap-1 bg-[#1d1d1f] px-4 text-[12px] font-normal text-[#f5f5f7] md:gap-2 md:text-[13px]"
|
||||
aria-label="Navegação principal"
|
||||
>
|
||||
<div className="flex w-full max-w-[980px] items-center justify-between gap-2">
|
||||
<Link href="/" className="opacity-90 hover:opacity-100" aria-label="Apple">
|
||||
<AppleLogo className="h-5 w-5 text-white md:h-[22px] md:w-[22px]" />
|
||||
</Link>
|
||||
<ul className="hidden flex-1 items-center justify-center gap-4 lg:flex xl:gap-6">
|
||||
{appleNav.map((item) => (
|
||||
<li key={item}>
|
||||
<Link href="#" className="whitespace-nowrap opacity-90 hover:opacity-100">
|
||||
{item}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="flex items-center gap-5">
|
||||
<button type="button" className="opacity-90 hover:opacity-100" aria-label="Pesquisar">
|
||||
<SearchIcon className="text-white" />
|
||||
</button>
|
||||
<button type="button" className="opacity-90 hover:opacity-100" aria-label="Sacola">
|
||||
<BagIcon className="text-white" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div className="relative flex min-h-[148px] w-full overflow-hidden bg-[#9d1f55] text-white sm:min-h-[180px] md:min-h-[204px] lg:min-h-[228px]">
|
||||
<div className="relative w-[22%] min-w-[80px] max-w-[300px] shrink-0 sm:w-[24%] md:w-[26%]">
|
||||
<Image
|
||||
src={PROMO_IMG_LEFT}
|
||||
alt="Mulher em atividade ao ar livre"
|
||||
fill
|
||||
className="object-cover object-[center_28%]"
|
||||
sizes="(max-width: 640px) 28vw, 300px"
|
||||
priority
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0 bg-gradient-to-r from-black/35 from-[8%] via-[#b8326a]/88 via-[55%] to-[#b8326a]"
|
||||
aria-hidden
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="relative z-[1] flex min-w-0 flex-1 flex-col justify-center gap-3 bg-gradient-to-r from-[#b8326a] via-[#d9468f] to-[#b8326a] px-4 py-6 sm:flex-row sm:items-center sm:justify-between sm:gap-6 sm:px-7 sm:py-7 md:gap-10 md:px-9 md:py-8 lg:px-10">
|
||||
<div className="flex min-w-0 flex-col gap-2 sm:flex-row sm:items-center sm:gap-5 md:gap-9">
|
||||
<span className="shrink-0 text-[11px] font-semibold uppercase tracking-[0.2em] text-white/95 sm:text-xs">
|
||||
Nossa Seguros
|
||||
</span>
|
||||
<p className="text-pretty text-sm font-medium leading-relaxed text-white sm:text-base md:text-lg lg:max-w-[40rem] lg:leading-relaxed">
|
||||
Seguro Saúde Mulher — cuidado que acompanha o seu ritmo.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-4 text-white/95 sm:pl-2">
|
||||
<span className="sr-only">Redes sociais</span>
|
||||
<Link href="#" className="text-sm hover:opacity-80" aria-label="Facebook">
|
||||
f
|
||||
</Link>
|
||||
<Link href="#" className="text-sm hover:opacity-80" aria-label="LinkedIn">
|
||||
in
|
||||
</Link>
|
||||
<Link href="#" className="text-sm hover:opacity-80" aria-label="Instagram">
|
||||
◎
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative w-[22%] min-w-[80px] max-w-[300px] shrink-0 sm:w-[24%] md:w-[26%]">
|
||||
<Image
|
||||
src={PROMO_IMG_RIGHT}
|
||||
alt="Bem-estar e cuidados de saúde"
|
||||
fill
|
||||
className="object-cover object-[center_38%]"
|
||||
sizes="(max-width: 640px) 28vw, 300px"
|
||||
priority
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0 bg-gradient-to-l from-black/35 from-[8%] via-[#b8326a]/88 via-[55%] to-[#b8326a]"
|
||||
aria-hidden
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-b border-[#0066cc]/20 bg-[#0066cc] py-2">
|
||||
<div className="mx-auto flex max-w-[1200px] items-center gap-3 px-4">
|
||||
<div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-white text-sm font-bold tracking-tight text-[#0066cc]">
|
||||
tv
|
||||
</div>
|
||||
<span className="text-lg font-semibold tracking-tight text-white">tvone</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
|
||||
const slides = [
|
||||
{
|
||||
id: 1,
|
||||
tag: "MÚSICA",
|
||||
title:
|
||||
"Diddy na XB Label? Gerilson Israel responde após anúncio de lançamento de nova música em conjunto.",
|
||||
byline: "Por Redação — 24 de Março, 2025",
|
||||
image:
|
||||
"https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=1400&q=80",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
tag: "CULTURA",
|
||||
title: "Festivais de verão: calendário completo e bilhetes à venda esta semana.",
|
||||
byline: "Por Equipa tvone — 23 de Março, 2025",
|
||||
image:
|
||||
"https://images.unsplash.com/photo-1459749411175-04bf5292ceea?w=1400&q=80",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
tag: "TV",
|
||||
title: "Novas séries internacionais chegam às plataformas — o que não pode perder.",
|
||||
byline: "Por Redação — 22 de Março, 2025",
|
||||
image:
|
||||
"https://images.unsplash.com/photo-1522869635100-9f4c5e86aa37?w=1400&q=80",
|
||||
},
|
||||
];
|
||||
|
||||
export function TvoneHero() {
|
||||
const [active, setActive] = useState(0);
|
||||
const slide = slides[active]!;
|
||||
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-[1200px] px-4 py-6">
|
||||
<div className="relative overflow-hidden rounded-xl shadow-[0_12px_40px_rgba(0,0,0,0.12)]">
|
||||
<div className="relative aspect-[21/9] min-h-[280px] w-full md:aspect-[2.4/1]">
|
||||
<Image
|
||||
src={slide.image}
|
||||
alt=""
|
||||
fill
|
||||
className="object-cover"
|
||||
sizes="(max-width: 1200px) 100vw, 1200px"
|
||||
priority
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/75 via-black/25 to-transparent" />
|
||||
<div className="absolute inset-0 flex flex-col justify-end p-6 md:p-10">
|
||||
<span className="mb-2 inline-flex w-fit rounded bg-[#7c3aed] px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-white">
|
||||
{slide.tag}
|
||||
</span>
|
||||
<h1 className="max-w-3xl text-balance text-2xl font-bold leading-tight text-white md:text-3xl lg:text-4xl">
|
||||
{slide.title}
|
||||
</h1>
|
||||
<p className="mt-3 text-sm text-white/85">{slide.byline}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute bottom-4 left-0 right-0 z-10 flex justify-center gap-2 md:bottom-6">
|
||||
{slides.map((s, i) => (
|
||||
<button
|
||||
key={s.id}
|
||||
type="button"
|
||||
onClick={() => setActive(i)}
|
||||
className={`h-2 w-2 rounded-full transition ${i === active ? "bg-white" : "bg-white/45 hover:bg-white/70"}`}
|
||||
aria-label={`Slide ${i + 1}`}
|
||||
aria-current={i === active}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
export type TvonePublicationBannerProps = {
|
||||
/** When set, the whole slot links here (campaign URL). */
|
||||
href?: string;
|
||||
/** Optional creative — leaderboard-style wide image (e.g. 970×90 or similar). */
|
||||
imageSrc?: string;
|
||||
imageAlt?: string;
|
||||
/** Short line shown when no image (placeholder for unsold inventory). */
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
/** Small label above the slot (legal / transparency). */
|
||||
slotLabel?: string;
|
||||
};
|
||||
|
||||
export function TvonePublicationBanner({
|
||||
href = "#publicidade",
|
||||
imageSrc,
|
||||
imageAlt = "Publicidade",
|
||||
title = "Espaço publicitário",
|
||||
subtitle = "Reserve este espaço para a sua marca. Contacte a nossa equipa comercial.",
|
||||
slotLabel = "Publicidade",
|
||||
}: TvonePublicationBannerProps) {
|
||||
const inner = imageSrc ? (
|
||||
<Image
|
||||
src={imageSrc}
|
||||
alt={imageAlt}
|
||||
width={1200}
|
||||
height={120}
|
||||
className="h-auto w-full max-h-[120px] object-cover object-center md:max-h-[140px]"
|
||||
sizes="100vw"
|
||||
priority
|
||||
/>
|
||||
) : (
|
||||
<div className="flex min-h-[88px] w-full flex-col items-center justify-center gap-1 bg-[#f0f0f3] px-4 py-5 text-center md:min-h-[100px] md:flex-row md:justify-between md:text-left">
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-neutral-800">{title}</p>
|
||||
<p className="mt-0.5 max-w-xl text-xs text-neutral-600 md:text-sm">{subtitle}</p>
|
||||
</div>
|
||||
<span className="mt-2 shrink-0 rounded-full border border-neutral-300 bg-white px-3 py-1 text-[11px] font-medium text-neutral-700 md:mt-0">
|
||||
Espaço disponível
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<aside
|
||||
className="w-full border-y border-neutral-200/90 bg-white"
|
||||
aria-label={slotLabel}
|
||||
>
|
||||
<div className="mx-auto w-full max-w-[1200px] px-0">
|
||||
<div className="flex items-center gap-2 px-4 pt-2 pb-1">
|
||||
<span className="text-[10px] font-semibold uppercase tracking-wider text-neutral-400">{slotLabel}</span>
|
||||
</div>
|
||||
<div className="overflow-hidden">
|
||||
{href ? (
|
||||
<Link
|
||||
href={href}
|
||||
className="block w-full outline-none transition-opacity hover:opacity-95 focus-visible:ring-2 focus-visible:ring-[#0066cc] focus-visible:ring-offset-2"
|
||||
target={href.startsWith("http") ? "_blank" : undefined}
|
||||
rel={href.startsWith("http") ? "noopener noreferrer" : undefined}
|
||||
>
|
||||
{inner}
|
||||
</Link>
|
||||
) : (
|
||||
inner
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
+5
-10
@@ -3,24 +3,19 @@
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
--tvone-blue: #0066cc;
|
||||
--tvone-magenta: #d9468f;
|
||||
--tvone-muted: #f5f5f7;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
--font-sans: var(--font-inter), ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-family: var(--font-inter), ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
|
||||
+11
-15
@@ -1,20 +1,15 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
const inter = Inter({
|
||||
variable: "--font-inter",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
title: "tvone — Notícias e entretenimento",
|
||||
description: "O seu portal de notícias, música e cultura.",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -23,11 +18,12 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
||||
>
|
||||
<body className="min-h-full flex flex-col">{children}</body>
|
||||
<html lang="pt" className={`${inter.variable} h-full antialiased`}>
|
||||
<body
|
||||
className={`min-h-full flex flex-col bg-white text-neutral-900 ${inter.className}`}
|
||||
>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
+17
-59
@@ -1,65 +1,23 @@
|
||||
import Image from "next/image";
|
||||
import { TvoneHeader } from "./components/tvone-header";
|
||||
import { TvoneHero } from "./components/tvone-hero";
|
||||
import {
|
||||
TvoneAdBanner,
|
||||
TvoneDestaques,
|
||||
TvoneFooter,
|
||||
TvoneMainColumns,
|
||||
TvoneServiceStrip,
|
||||
} from "./components/tvone-content";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
||||
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={100}
|
||||
height={20}
|
||||
priority
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
||||
To get started, edit the page.tsx file.
|
||||
</h1>
|
||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
||||
Looking for a starting point or more instructions? Head over to{" "}
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Templates
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Learning
|
||||
</a>{" "}
|
||||
center.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Deploy Now
|
||||
</a>
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<div className="flex min-h-full flex-col bg-white">
|
||||
<TvoneHeader />
|
||||
<TvoneHero />
|
||||
<TvoneDestaques />
|
||||
<TvoneMainColumns />
|
||||
<TvoneAdBanner />
|
||||
<TvoneServiceStrip />
|
||||
<TvoneFooter />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+9
-1
@@ -1,7 +1,15 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "images.unsplash.com",
|
||||
pathname: "/**",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
Reference in New Issue
Block a user