This commit is contained in:
@@ -6,6 +6,7 @@ import Glow from '@/components/site/glow';
|
||||
import Icon from '@/components/site/icon';
|
||||
import IconTile from '@/components/site/icon-tile';
|
||||
import ImageCard from '@/components/site/image-card';
|
||||
import OdooPartnerBadge from '@/components/site/odoo-partner-badge';
|
||||
import PageHero from '@/components/site/page-hero';
|
||||
import RichText from '@/components/site/rich-text';
|
||||
import Section from '@/components/site/section';
|
||||
@@ -40,16 +41,8 @@ export default function About() {
|
||||
{t.hero.stats.map((stat) => (
|
||||
<StatCard key={stat.label} {...stat} />
|
||||
))}
|
||||
<Card className="col-span-2 flex items-center justify-between lg:col-span-1">
|
||||
<div className="flex flex-col">
|
||||
<span className="font-display text-on-surface text-3xl font-bold">
|
||||
Official
|
||||
</span>
|
||||
<span className="text-primary font-mono text-xs font-semibold tracking-wider uppercase">
|
||||
Odoo Partner
|
||||
</span>
|
||||
</div>
|
||||
<IconTile icon="verified_user" size="md" />
|
||||
<Card className="col-span-2 flex items-center justify-center lg:col-span-1">
|
||||
<OdooPartnerBadge className="h-16" />
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -118,51 +118,7 @@ export default function Clients() {
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section>
|
||||
<div className="flex flex-col gap-12">
|
||||
<SectionHeader
|
||||
align="split"
|
||||
eyebrow={t.testimonials.eyebrow}
|
||||
title={t.testimonials.title}
|
||||
description={t.testimonials.description}
|
||||
/>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
{t.testimonials.items.map((testimonial) => (
|
||||
<Card
|
||||
key={testimonial.initials}
|
||||
className="flex flex-col justify-between gap-6"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div
|
||||
className="text-primary flex"
|
||||
aria-label={t.testimonials.rating}
|
||||
>
|
||||
{Array.from({ length: 5 }, (_, i) => (
|
||||
<Icon key={i} name="star" filled />
|
||||
))}
|
||||
</div>
|
||||
<blockquote className="text-on-surface text-base italic">
|
||||
“{testimonial.quote}”
|
||||
</blockquote>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-surface-container text-primary flex h-10 w-10 items-center justify-center rounded-full font-mono font-bold">
|
||||
{testimonial.initials}
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-on-surface text-sm font-bold">
|
||||
{testimonial.role}
|
||||
</div>
|
||||
<span className="text-on-surface-variant text-sm">
|
||||
{testimonial.organization}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
<Testimonials t={t} />
|
||||
|
||||
<Section tone="muted">
|
||||
<Card
|
||||
@@ -358,6 +314,11 @@ function SectorPortfolio({ t }: { t: Content }) {
|
||||
<span className="text-on-surface font-semibold">
|
||||
{project.title}
|
||||
</span>
|
||||
{project.scope && (
|
||||
<span className="text-on-surface-variant text-sm">
|
||||
{project.scope}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-on-surface-variant flex items-center gap-1.5 text-sm">
|
||||
<Icon
|
||||
name="apartment"
|
||||
@@ -495,6 +456,61 @@ function FeaturedPrograms({ t }: { t: Content }) {
|
||||
);
|
||||
}
|
||||
|
||||
/** Hidden until real client testimonials are added to the content file. */
|
||||
function Testimonials({ t }: { t: Content }) {
|
||||
if (t.testimonials.items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<div className="flex flex-col gap-12">
|
||||
<SectionHeader
|
||||
align="split"
|
||||
eyebrow={t.testimonials.eyebrow}
|
||||
title={t.testimonials.title}
|
||||
description={t.testimonials.description}
|
||||
/>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
{t.testimonials.items.map((testimonial) => (
|
||||
<Card
|
||||
key={testimonial.initials}
|
||||
className="flex flex-col justify-between gap-6"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div
|
||||
className="text-primary flex"
|
||||
aria-label={t.testimonials.rating}
|
||||
>
|
||||
{Array.from({ length: 5 }, (_, i) => (
|
||||
<Icon key={i} name="star" filled />
|
||||
))}
|
||||
</div>
|
||||
<blockquote className="text-on-surface text-base italic">
|
||||
“{testimonial.quote}”
|
||||
</blockquote>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-surface-container text-primary flex h-10 w-10 items-center justify-center rounded-full font-mono font-bold">
|
||||
{testimonial.initials}
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-on-surface text-sm font-bold">
|
||||
{testimonial.role}
|
||||
</div>
|
||||
<span className="text-on-surface-variant text-sm">
|
||||
{testimonial.organization}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function RetentionGauge({ t }: { t: Content }) {
|
||||
return (
|
||||
<div className="bg-surface-container flex w-full flex-col items-center justify-center rounded-xl p-6 lg:w-96">
|
||||
|
||||
@@ -5,6 +5,7 @@ import Eyebrow from '@/components/site/eyebrow';
|
||||
import Glow, { GridPattern } from '@/components/site/glow';
|
||||
import Icon from '@/components/site/icon';
|
||||
import IconTile from '@/components/site/icon-tile';
|
||||
import OdooPartnerBadge from '@/components/site/odoo-partner-badge';
|
||||
import Pill from '@/components/site/pill';
|
||||
import RichText from '@/components/site/rich-text';
|
||||
import Section from '@/components/site/section';
|
||||
@@ -13,6 +14,7 @@ import ConsultationSection from '@/components/site/sections/consultation-section
|
||||
import ServiceGrid from '@/components/site/sections/service-grid';
|
||||
import StatCard from '@/components/site/stat-card';
|
||||
import { homeContent } from '@/content/home';
|
||||
import { topClients } from '@/data/projects';
|
||||
import { useContent } from '@/hooks/use-locale';
|
||||
import { about, clients, services } from '@/routes';
|
||||
|
||||
@@ -46,15 +48,24 @@ export default function Home() {
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-5">
|
||||
{t.sectors.items.map((sector) => (
|
||||
{topClients(10).map((client) => (
|
||||
<div
|
||||
key={sector}
|
||||
className="border-outline-variant/40 bg-surface-container text-on-surface hover:border-primary/50 hover:bg-surface-container-high flex h-16 items-center justify-center rounded-xl border px-4 text-center font-mono text-xs font-medium transition-all"
|
||||
key={client}
|
||||
className="border-outline-variant/40 bg-surface-container text-on-surface hover:border-primary/50 hover:bg-surface-container-high flex min-h-16 items-center justify-center rounded-xl border px-4 py-3 text-center font-mono text-xs font-medium transition-all"
|
||||
>
|
||||
{sector}
|
||||
{client}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<ButtonLink
|
||||
href={clients()}
|
||||
variant="ghost"
|
||||
size="inline"
|
||||
trailingIcon="arrow_forward"
|
||||
className="self-start"
|
||||
>
|
||||
{t.sectors.more}
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
@@ -328,9 +339,7 @@ function OdooSpotlight({ t }: { t: Content }) {
|
||||
<Glow className="-top-24 -right-24 h-80 w-80 blur-3xl" />
|
||||
<div className="relative grid grid-cols-1 items-center gap-8 lg:grid-cols-12">
|
||||
<div className="flex flex-col gap-4 lg:col-span-8">
|
||||
<Pill tone="brand" icon="verified">
|
||||
{t.odoo.badge}
|
||||
</Pill>
|
||||
<OdooPartnerBadge className="self-start" />
|
||||
<h3 className="font-display text-on-surface text-2xl font-extrabold lg:text-3xl">
|
||||
{t.odoo.title}
|
||||
<span className="text-on-surface-variant mt-1 block font-sans text-xl font-normal lg:text-2xl">
|
||||
|
||||
@@ -4,6 +4,7 @@ import Card from '@/components/site/card';
|
||||
import FeatureCard from '@/components/site/feature-card';
|
||||
import Glow from '@/components/site/glow';
|
||||
import IconTile from '@/components/site/icon-tile';
|
||||
import OdooPartnerBadge from '@/components/site/odoo-partner-badge';
|
||||
import PageHero from '@/components/site/page-hero';
|
||||
import Pill from '@/components/site/pill';
|
||||
import RichText from '@/components/site/rich-text';
|
||||
@@ -83,9 +84,7 @@ export default function Services() {
|
||||
>
|
||||
<div className="grid grid-cols-1 items-center gap-10 lg:grid-cols-12">
|
||||
<div className="flex flex-col gap-5 lg:col-span-5">
|
||||
<Pill tone="brand" icon="verified">
|
||||
{t.odoo.badge}
|
||||
</Pill>
|
||||
<OdooPartnerBadge className="self-start" />
|
||||
<h2 className="font-display text-on-surface lg:text-headline-xl text-3xl font-extrabold tracking-tight">
|
||||
{t.odoo.title}
|
||||
</h2>
|
||||
|
||||
Reference in New Issue
Block a user