@@ -0,0 +1,91 @@
|
||||
import ConsultationForm from '@/components/site/consultation-form';
|
||||
import Glow from '@/components/site/glow';
|
||||
import Icon from '@/components/site/icon';
|
||||
import Pill from '@/components/site/pill';
|
||||
import Section from '@/components/site/section';
|
||||
import { company, offices } from '@/data/site';
|
||||
|
||||
type ConsultationSectionProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
/** Closing call-to-action with contact details and the quick form. */
|
||||
export default function ConsultationSection({
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
}: ConsultationSectionProps) {
|
||||
const contacts = offices.map((office) => ({
|
||||
icon: office.icon,
|
||||
title: office.name,
|
||||
lines: [
|
||||
office.building,
|
||||
`${office.street}, ${office.area}`,
|
||||
office.city,
|
||||
`Telp: ${office.phone.label}`,
|
||||
],
|
||||
}));
|
||||
|
||||
return (
|
||||
<Section
|
||||
id={id}
|
||||
background={
|
||||
<Glow className="top-1/2 left-1/2 h-[520px] w-[850px] -translate-x-1/2 -translate-y-1/2" />
|
||||
}
|
||||
>
|
||||
<div className="border-outline-variant/60 bg-surface-container rounded-3xl border p-6 shadow-2xl sm:p-8 lg:p-12">
|
||||
<div className="grid grid-cols-1 items-center gap-10 lg:grid-cols-12">
|
||||
<div className="flex flex-col gap-6 lg:col-span-7">
|
||||
<Pill tone="brand" icon="verified_user">
|
||||
KONSULTASI TEKNIS & AUDIT INFRASTRUKTUR
|
||||
</Pill>
|
||||
<div className="flex flex-col gap-3">
|
||||
<h2 className="font-display text-on-surface lg:text-headline-xl text-3xl leading-tight font-extrabold tracking-tight">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-on-surface-variant text-sm leading-relaxed lg:text-base">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-on-surface-variant grid grid-cols-1 gap-4 pt-2 text-xs sm:grid-cols-2">
|
||||
{contacts.map((contact) => (
|
||||
<div
|
||||
key={contact.title}
|
||||
className="border-outline-variant/40 bg-surface-container-high/60 flex items-start gap-2.5 rounded-xl border p-3"
|
||||
>
|
||||
<Icon
|
||||
name={contact.icon}
|
||||
className="text-primary mt-0.5 text-xl"
|
||||
/>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-on-surface font-bold">
|
||||
{contact.title}
|
||||
</span>
|
||||
{contact.lines.map((line) => (
|
||||
<span key={line}>{line}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<a
|
||||
href={`mailto:${company.email.busdev}`}
|
||||
className="text-on-surface-variant hover:text-primary flex items-center gap-2 text-xs"
|
||||
>
|
||||
<Icon
|
||||
name="mail"
|
||||
className="text-primary text-base"
|
||||
/>
|
||||
{company.email.busdev}
|
||||
</a>
|
||||
</div>
|
||||
<div className="w-full lg:col-span-5">
|
||||
<ConsultationForm idPrefix={id} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import Glow from '@/components/site/glow';
|
||||
import Icon from '@/components/site/icon';
|
||||
import Pill from '@/components/site/pill';
|
||||
import Section from '@/components/site/section';
|
||||
import { company } from '@/data/site';
|
||||
|
||||
type CtaBannerProps = {
|
||||
badge: string;
|
||||
title: string;
|
||||
description: string;
|
||||
/** Usually one primary and one secondary <ButtonLink />. */
|
||||
actions: ReactNode;
|
||||
showContacts?: boolean;
|
||||
};
|
||||
|
||||
/** Centered call-to-action card used to close informational pages. */
|
||||
export default function CtaBanner({
|
||||
badge,
|
||||
title,
|
||||
description,
|
||||
actions,
|
||||
showContacts = true,
|
||||
}: CtaBannerProps) {
|
||||
const contacts = [
|
||||
{ icon: 'call', label: company.phone.label },
|
||||
{ icon: 'mail', label: company.email.busdev },
|
||||
{ icon: 'location_on', label: 'Bintaro & Plaza Simatupang, Jakarta' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Section
|
||||
size="narrow"
|
||||
background={
|
||||
<Glow className="-top-32 left-1/2 h-64 w-[48rem] -translate-x-1/2" />
|
||||
}
|
||||
>
|
||||
<div className="border-outline-variant/50 from-surface-container to-surface-container-low flex flex-col items-center gap-6 rounded-3xl border bg-gradient-to-b p-8 text-center shadow-xl md:p-14">
|
||||
<Pill tone="brand" icon="verified_user" className="self-center">
|
||||
{badge}
|
||||
</Pill>
|
||||
<div className="flex max-w-2xl flex-col gap-3">
|
||||
<h2 className="font-display text-on-surface lg:text-headline-xl text-3xl font-extrabold tracking-tight">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-on-surface-variant text-base leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex w-full flex-col items-center gap-4 sm:w-auto sm:flex-row">
|
||||
{actions}
|
||||
</div>
|
||||
{showContacts && (
|
||||
<div className="text-on-surface-variant flex flex-wrap items-center justify-center gap-x-6 gap-y-2 pt-2 text-sm">
|
||||
{contacts.map((contact) => (
|
||||
<span
|
||||
key={contact.icon}
|
||||
className="flex items-center gap-1.5"
|
||||
>
|
||||
<Icon
|
||||
name={contact.icon}
|
||||
className="text-primary text-base"
|
||||
/>
|
||||
{contact.label}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import FeatureCard from '@/components/site/feature-card';
|
||||
import { officialServices } from '@/data/site';
|
||||
|
||||
type ServiceGridProps = {
|
||||
/** `summary` for overviews, `description` for the official wording. */
|
||||
detail?: 'summary' | 'description';
|
||||
};
|
||||
|
||||
/** The eight official PAJ services as a 4-column card grid. */
|
||||
export default function ServiceGrid({ detail = 'summary' }: ServiceGridProps) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-4">
|
||||
{officialServices.map((service, index) => {
|
||||
const number = String(index + 1).padStart(2, '0');
|
||||
|
||||
return (
|
||||
<FeatureCard
|
||||
key={service.title}
|
||||
icon={service.icon}
|
||||
tag={`${number} / JASA RESMI`}
|
||||
title={`${index + 1}. ${service.title}`}
|
||||
description={
|
||||
<>
|
||||
{service.expansion && (
|
||||
<span className="text-on-surface font-semibold">
|
||||
{service.expansion}:{' '}
|
||||
</span>
|
||||
)}
|
||||
{service[detail]}
|
||||
</>
|
||||
}
|
||||
footer={service.outcome}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user