chore: initialize project
Deploy monie-landing (kaniko) / build-and-deploy (push) Successful in 14m15s

This commit is contained in:
2026-04-04 23:14:39 +03:00
commit e406c55c89
84 changed files with 13590 additions and 0 deletions
@@ -0,0 +1,31 @@
import { Card, SectionHeader } from "denjs-ui";
import { getBenefits } from "#/entities/landing";
import { useMessages } from "#/shared/lib/i18n";
export function BenefitsSection() {
const m = useMessages();
return (
<section id="benefits" className="mt-10 sm:mt-14">
<SectionHeader
eyebrow={m.benefits_eyebrow()}
title={m.benefits_title()}
align="left"
className="max-w-3xl"
/>
<div className="mt-5 grid gap-4 md:grid-cols-2">
{getBenefits(m).map((item, index) => (
<Card
key={item.title}
title={item.title}
description={item.text}
padding="lg"
className="feature-card rise-in rounded-2xl"
style={{ animationDelay: `${index * 90 + 100}ms` }}
/>
))}
</div>
</section>
);
}
@@ -0,0 +1,37 @@
import { Accordion, SectionHeader, Text } from "denjs-ui";
import { getFaqItems } from "#/entities/landing";
import { useMessages } from "#/shared/lib/i18n";
export function FaqSection() {
const m = useMessages();
return (
<section id="faq" className="mt-10 sm:mt-14">
<SectionHeader
eyebrow={m.faq_eyebrow()}
title={m.faq_title()}
align="left"
className="max-w-3xl"
/>
<Accordion
className="mt-5 rounded-2xl border border-[var(--line)] bg-[var(--glass-surface)]"
items={getFaqItems(m).map((item) => ({
value: item.value,
title: item.title,
content: (
<Text
as="p"
tone="muted"
className="m-0 text-sm leading-6 text-[var(--sea-ink-soft)]"
>
{item.content}
</Text>
),
}))}
type="single"
collapsible
/>
</section>
);
}
@@ -0,0 +1,32 @@
import { Card, SectionHeader } from "denjs-ui";
import { RequestDemoForm } from "#/features/request-demo";
import { useMessages } from "#/shared/lib/i18n";
export function FinalCtaSection() {
const m = useMessages();
return (
<section id="demo" className="mt-10 sm:mt-14">
<Card
padding="lg"
className="island-shell rounded-[2rem] border-[rgba(31,96,99,0.3)] bg-[linear-gradient(160deg,rgba(255,255,255,0.95),rgba(220,245,241,0.8))] sm:p-10"
>
<div className="grid gap-6 lg:grid-cols-[1fr_1.08fr]">
<div className="rise-in" style={{ animationDelay: "120ms" }}>
<SectionHeader
eyebrow={m.final_eyebrow()}
title={m.final_title()}
subtitle={m.final_subtitle()}
align="left"
/>
<div className="mt-4 inline-flex rounded-full border border-[var(--chip-line)] bg-[var(--chip-bg)] px-3 py-1 text-xs font-semibold text-[var(--sea-ink-soft)]">
{m.final_hint()}
</div>
</div>
<RequestDemoForm />
</div>
</Card>
</section>
);
}
@@ -0,0 +1,84 @@
import { Badge, Button, Card, Heading, Text } from "denjs-ui";
import { getHeroMetrics } from "#/entities/landing";
import { scrollToSection } from "#/shared/lib/dom";
import { useMessages } from "#/shared/lib/i18n";
export function HeroSection() {
const m = useMessages();
return (
<section className="island-shell rise-in relative overflow-hidden rounded-[2.2rem] px-6 py-10 sm:px-10 sm:py-14">
<div className="pointer-events-none absolute -left-20 -top-24 h-56 w-56 rounded-full bg-[radial-gradient(circle,rgba(79,184,178,0.32),transparent_66%)]" />
<div className="pointer-events-none absolute -bottom-24 -right-16 h-56 w-56 rounded-full bg-[radial-gradient(circle,rgba(230,128,97,0.2),transparent_66%)]" />
<Badge
color="teal"
rounded="full"
bordered
className="w-fit px-3 py-1 text-[11px] tracking-[0.12em] uppercase"
>
{m.hero_badge()}
</Badge>
<Heading
level={1}
className="mt-4 max-w-4xl text-4xl leading-[0.98] font-bold tracking-tight text-[var(--sea-ink)] sm:text-6xl"
>
{m.hero_title()}
</Heading>
<Text
size="lg"
tone="muted"
className="mt-5 max-w-3xl text-base leading-7 text-[var(--sea-ink-soft)] sm:text-lg"
>
{m.hero_subtitle()}
</Text>
<div className="mt-8 flex flex-wrap gap-3">
<Button
size="large"
className="rounded-full"
onClick={() => scrollToSection("demo")}
>
{m.hero_cta_primary()}
</Button>
<Button
tone="secondary"
size="large"
className="rounded-full"
onClick={() => scrollToSection("how")}
>
{m.hero_cta_secondary()}
</Button>
</div>
<div className="mt-8 grid gap-3 sm:grid-cols-3">
{getHeroMetrics(m).map((item, index) => (
<Card
key={item.label}
padding="md"
className="metric-card rise-in rounded-2xl"
style={{ animationDelay: `${index * 100 + 80}ms` }}
>
<Text
as="p"
weight="semibold"
className="m-0 text-2xl font-extrabold text-[var(--sea-ink)]"
>
{item.value}
</Text>
<Text
as="p"
size="sm"
tone="muted"
className="mt-1 text-[var(--sea-ink-soft)]"
>
{item.label}
</Text>
</Card>
))}
</div>
</section>
);
}
@@ -0,0 +1,49 @@
import { Badge, Card, Heading, SectionHeader, Text } from "denjs-ui";
import { getSteps } from "#/entities/landing";
import { useMessages } from "#/shared/lib/i18n";
export function HowItWorksSection() {
const m = useMessages();
return (
<section id="how" className="mt-10 sm:mt-14">
<SectionHeader
eyebrow={m.how_eyebrow()}
title={m.how_title()}
align="left"
className="max-w-3xl"
/>
<div className="mt-5 grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{getSteps(m).map((step, index) => (
<Card
key={step.title}
padding="lg"
className="island-shell rise-in rounded-2xl"
style={{ animationDelay: `${index * 80 + 120}ms` }}
>
<Badge
color="teal"
rounded="full"
className="mb-3 w-fit px-2.5 py-1 text-[11px] font-semibold"
>
{m.how_step_label()} {index + 1}
</Badge>
<Heading
level={4}
className="text-base font-semibold text-[var(--sea-ink)]"
>
{step.title}
</Heading>
<Text
tone="muted"
className="mt-2 text-sm leading-6 text-[var(--sea-ink-soft)]"
>
{step.text}
</Text>
</Card>
))}
</div>
</section>
);
}
+10
View File
@@ -0,0 +1,10 @@
export { BenefitsSection } from "./benefits-section/ui/benefits-section";
export { FaqSection } from "./faq-section/ui/faq-section";
export { FinalCtaSection } from "./final-cta-section/ui/final-cta-section";
export { HeroSection } from "./hero-section/ui/hero-section";
export { HowItWorksSection } from "./how-it-works-section/ui/how-it-works-section";
export { PersonalPageSection } from "./personal-page-section/ui/personal-page-section";
export { ProblemSection } from "./problem-section/ui/problem-section";
export { ProductPreviewSection } from "./product-preview-section/ui/product-preview-section";
export { SolutionSection } from "./solution-section/ui/solution-section";
export { TrustSection } from "./trust-section/ui/trust-section";
@@ -0,0 +1,56 @@
import { Button, Card, SectionHeader, Text } from "denjs-ui";
import { scrollToSection } from "#/shared/lib/dom";
import { useMessages } from "#/shared/lib/i18n";
export function PersonalPageSection() {
const m = useMessages();
return (
<section id="personal" className="mt-10 sm:mt-14">
<Card
padding="lg"
className="island-shell rounded-[2rem] border-[rgba(31,96,99,0.28)] bg-[linear-gradient(155deg,rgba(255,255,255,0.95),rgba(220,245,241,0.74))] sm:p-10"
>
<div className="grid gap-6 lg:grid-cols-[1.1fr_1fr] lg:items-center">
<div>
<SectionHeader
eyebrow={m.personal_eyebrow()}
title={m.personal_title()}
subtitle={m.personal_subtitle()}
align="left"
/>
<div className="mt-4 inline-flex rounded-full border border-[var(--chip-line)] bg-[var(--chip-bg)] px-3 py-1 text-xs font-semibold text-[var(--sea-ink-soft)]">
{m.personal_example()}
</div>
</div>
<Card
padding="lg"
className="rounded-2xl border border-[var(--line)] bg-white/82"
>
<Text
as="p"
size="sm"
tone="muted"
className="m-0 text-[var(--sea-ink-soft)]"
>
{m.personal_card_title()}
</Text>
<ul className="m-0 mt-3 space-y-2 pl-5 text-sm leading-6 text-[var(--sea-ink-soft)]">
<li>{m.personal_point_1()}</li>
<li>{m.personal_point_2()}</li>
<li>{m.personal_point_3()}</li>
</ul>
<Button
size="large"
className="mt-5 w-full rounded-full"
onClick={() => scrollToSection("demo")}
>
{m.personal_cta()}
</Button>
</Card>
</div>
</Card>
</section>
);
}
@@ -0,0 +1,32 @@
import { Card, SectionHeader } from "denjs-ui";
import { getProblems } from "#/entities/landing";
import { useMessages } from "#/shared/lib/i18n";
export function ProblemSection() {
const m = useMessages();
return (
<section id="problem" className="mt-10 sm:mt-14">
<SectionHeader
eyebrow={m.problem_eyebrow()}
title={m.problem_title()}
subtitle={m.problem_subtitle()}
align="left"
className="max-w-3xl"
/>
<div className="mt-5 grid gap-4 md:grid-cols-3">
{getProblems(m).map((item, index) => (
<Card
key={item.title}
title={item.title}
description={item.text}
padding="lg"
className="feature-card rise-in rounded-2xl"
style={{ animationDelay: `${index * 90 + 110}ms` }}
/>
))}
</div>
</section>
);
}
@@ -0,0 +1,96 @@
import { Badge, Card, Heading, SectionHeader, Text } from "denjs-ui";
import { useMessages } from "#/shared/lib/i18n";
export function ProductPreviewSection() {
const m = useMessages();
return (
<section id="preview" className="mt-10 sm:mt-14">
<SectionHeader
eyebrow={m.preview_eyebrow()}
title={m.preview_title()}
subtitle={m.preview_subtitle()}
align="left"
className="max-w-3xl"
/>
<div className="mt-5 grid gap-4 lg:grid-cols-[1.1fr_1fr]">
<Card padding="lg" className="island-shell rounded-2xl">
<Text as="p" size="sm" tone="muted" className="island-kicker mb-2">
{m.preview_profile_title()}
</Text>
<Heading
level={3}
className="text-2xl font-semibold text-[var(--sea-ink)] sm:text-3xl"
>
monie.app/anna-nails
</Heading>
<Text
tone="muted"
className="mt-3 text-sm leading-6 text-[var(--sea-ink-soft)]"
>
{m.preview_profile_description()}
</Text>
<div className="mt-4 grid gap-3 sm:grid-cols-2">
<Card
padding="sm"
title={m.preview_service_1_title()}
description={m.preview_service_1_description()}
className="rounded-xl border border-[var(--line)] bg-white/76"
/>
<Card
padding="sm"
title={m.preview_service_2_title()}
description={m.preview_service_2_description()}
className="rounded-xl border border-[var(--line)] bg-white/76"
/>
</div>
</Card>
<Card padding="lg" className="island-shell rounded-2xl">
<Text as="p" size="sm" tone="muted" className="island-kicker mb-2">
{m.preview_schedule_title()}
</Text>
<div className="space-y-3">
<Card
padding="sm"
title={m.preview_appt_1_title()}
description={m.preview_appt_1_description()}
className="rounded-xl border border-[var(--line)] bg-white/80"
footer={
<Badge
color="emerald"
rounded="full"
className="w-fit px-2 py-0.5 text-[11px]"
>
{m.preview_appt_1_badge()}
</Badge>
}
/>
<Card
padding="sm"
title={m.preview_appt_2_title()}
description={m.preview_appt_2_description()}
className="rounded-xl border border-[var(--line)] bg-white/80"
footer={
<Badge
color="sky"
rounded="full"
className="w-fit px-2 py-0.5 text-[11px]"
>
{m.preview_appt_2_badge()}
</Badge>
}
/>
<Card
padding="sm"
title={m.preview_income_title()}
description={m.preview_income_description()}
className="rounded-xl border border-[var(--line)] bg-white/80"
/>
</div>
</Card>
</div>
</section>
);
}
@@ -0,0 +1,32 @@
import { Card, SectionHeader } from "denjs-ui";
import { getSolutionItems } from "#/entities/landing";
import { useMessages } from "#/shared/lib/i18n";
export function SolutionSection() {
const m = useMessages();
return (
<section
id="solution"
className="mt-10 grid gap-6 lg:grid-cols-[1.05fr_1fr] sm:mt-14"
>
<Card padding="lg" className="island-shell rounded-2xl">
<SectionHeader
eyebrow={m.solution_eyebrow()}
title={m.solution_title()}
subtitle={m.solution_subtitle()}
align="left"
className="max-w-2xl"
/>
</Card>
<Card padding="lg" className="island-shell rounded-2xl">
<ul className="m-0 space-y-3 pl-5 text-sm leading-6 text-[var(--sea-ink-soft)]">
{getSolutionItems(m).map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</Card>
</section>
);
}
@@ -0,0 +1,31 @@
import { Card, SectionHeader } from "denjs-ui";
import { getTrustItems } from "#/entities/landing";
import { useMessages } from "#/shared/lib/i18n";
export function TrustSection() {
const m = useMessages();
return (
<section id="trust" className="mt-10 sm:mt-14">
<SectionHeader
eyebrow={m.trust_eyebrow()}
title={m.trust_title()}
align="left"
className="max-w-3xl"
/>
<div className="mt-5 grid gap-4 md:grid-cols-3">
{getTrustItems(m).map((item, index) => (
<Card
key={item.title}
title={item.title}
description={item.text}
padding="lg"
className="feature-card rise-in rounded-2xl"
style={{ animationDelay: `${index * 90 + 100}ms` }}
/>
))}
</div>
</section>
);
}