feat: estimates on the homepage, monthly booking on the freelance page
The homepage showed a price list per case, including a day rate. Buyers of a result need a way to a price, not rates: each case now shows three steps to an estimate, one line for orientation and a button that opens the contact message with that topic chosen. The developer case is booked by the month, not by the day. The day rate is gone; the freelance page has the booking terms: 100 EUR per hour, fixed days of the week agreed for one month at a time, an example month, monthly invoice, two weeks notice to the end of a month. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
|
||||
import { DecodeText } from "@/src/components/bits/DecodeText";
|
||||
import { Block } from "@/src/components/home/Block";
|
||||
import { ClosingCta } from "@/src/components/home/ClosingCta";
|
||||
import { TopicButton } from "@/src/components/home/TopicButton";
|
||||
import { PipelineRun } from "@/src/components/illustrations/PipelineRun";
|
||||
import { Reveal } from "@/src/components/Reveal";
|
||||
import { SwipeRow } from "@/src/components/SwipeRow";
|
||||
@@ -36,6 +37,7 @@ export default async function FreelancePage({ params }: Props) {
|
||||
const locale = parseLocale((await params).locale) ?? DEFAULT_LOCALE;
|
||||
const content = contentFor(locale);
|
||||
const { freelance, technology } = content;
|
||||
const { booking } = freelance;
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-col bg-white">
|
||||
@@ -135,6 +137,57 @@ export default async function FreelancePage({ params }: Props) {
|
||||
</Reveal>
|
||||
</Block>
|
||||
|
||||
<Block
|
||||
index="03"
|
||||
label={booking.label}
|
||||
title={
|
||||
<>
|
||||
{booking.title.lead}{" "}
|
||||
<span className={MUTED}>{booking.title.rest}</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Reveal>
|
||||
<div className="grid grid-cols-1 gap-12 md:grid-cols-12 md:gap-12">
|
||||
<div className="md:col-span-6">
|
||||
<p className={BODY}>{booking.text}</p>
|
||||
<ul className="m-0 mt-8 list-none p-0">
|
||||
{booking.terms.map((term) => (
|
||||
<li
|
||||
key={term}
|
||||
className="border-t border-slate-200 py-4 font-sans text-lg text-slate-900 md:text-xl"
|
||||
>
|
||||
{term}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="md:col-span-6">
|
||||
<div className="rounded-3xl bg-slate-50 p-6 md:p-10">
|
||||
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2">
|
||||
{[booking.rate, booking.example].map((price) => (
|
||||
<div key={price.label}>
|
||||
<p className="m-0 font-sans text-base text-slate-500 md:text-lg">
|
||||
{price.label}
|
||||
</p>
|
||||
<p className="m-0 mt-2 font-sans text-3xl font-black tracking-tighter text-slate-900 md:text-5xl">
|
||||
{price.amount}
|
||||
</p>
|
||||
<p className="m-0 mt-2 font-mono text-[11px] uppercase tracking-[0.2em] text-slate-500">
|
||||
{price.note}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-10 border-t border-slate-200 pt-8">
|
||||
<TopicButton topic="developer">{booking.cta}</TopicButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
</Block>
|
||||
|
||||
<ClosingCta contact={content.contact} />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user