242 lines
11 KiB
TypeScript
242 lines
11 KiB
TypeScript
import {
|
|
mdiArrowTopRight,
|
|
mdiCalendarCheck,
|
|
mdiCheckDecagram,
|
|
mdiFileDocument,
|
|
mdiHomeCity,
|
|
mdiRoomService,
|
|
} from '@mdi/js';
|
|
import Head from 'next/head';
|
|
import React, { ReactElement } from 'react';
|
|
|
|
import BaseButton from '../components/BaseButton';
|
|
import BaseIcon from '../components/BaseIcon';
|
|
import CardBox from '../components/CardBox';
|
|
import PublicSiteFooter from '../components/PublicSiteFooter';
|
|
import PublicSiteHeader from '../components/PublicSiteHeader';
|
|
import LayoutGuest from '../layouts/Guest';
|
|
import { getPageTitle } from '../config';
|
|
|
|
const productAreas = [
|
|
{
|
|
title: 'Booking intake',
|
|
description: 'Receive requests with the right tenant, dates, approvals, and context before service delivery begins.',
|
|
icon: mdiCalendarCheck,
|
|
},
|
|
{
|
|
title: 'Stay operations',
|
|
description: 'Coordinate readiness, guest service, and internal updates from one controlled operating view.',
|
|
icon: mdiRoomService,
|
|
},
|
|
{
|
|
title: 'Billing follow-through',
|
|
description: 'Keep invoicing and account visibility tied to the same reservation record from start to finish.',
|
|
icon: mdiFileDocument,
|
|
},
|
|
];
|
|
|
|
const servicePillars = [
|
|
'Tenant-aware workspace context for multi-organization teams',
|
|
'Reserved, premium visual tone without turning the page into a template',
|
|
'A direct path from public website to the real operating workspace',
|
|
];
|
|
|
|
const workflowMoments = [
|
|
{
|
|
step: '01',
|
|
title: 'Receive the brief',
|
|
description: 'Capture the request with account context, approvals, dates, and service notes intact.',
|
|
},
|
|
{
|
|
step: '02',
|
|
title: 'Deliver the stay',
|
|
description: 'Move into reservations, readiness, support, and day-to-day guest coordination with clarity.',
|
|
},
|
|
{
|
|
step: '03',
|
|
title: 'Close with confidence',
|
|
description: 'Finish with billing and account follow-through attached to the same operational source of truth.',
|
|
},
|
|
];
|
|
|
|
const highlights = [
|
|
{ label: 'Private operator view', value: 'Multi-tenant workspace' },
|
|
{ label: 'Service posture', value: 'Calm, controlled, premium' },
|
|
{ label: 'Execution model', value: 'Request to reservation to billing' },
|
|
];
|
|
|
|
export default function HomePage() {
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>{getPageTitle('Gracey Corporate Stay Portal')}</title>
|
|
<meta
|
|
name="description"
|
|
content="Manage booking requests, reservations, guest operations, and billing from one refined corporate stay workspace."
|
|
/>
|
|
</Head>
|
|
|
|
<main className="min-h-screen bg-[#f7f4ee] text-slate-950">
|
|
<PublicSiteHeader />
|
|
|
|
<section className="relative overflow-hidden border-b border-[#d9cfbf] bg-[linear-gradient(135deg,rgba(15,23,42,0.96)_0%,rgba(30,41,59,0.92)_42%,rgba(88,65,38,0.88)_100%)] text-white">
|
|
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(255,255,255,0.12),_transparent_28%),radial-gradient(circle_at_bottom_right,_rgba(245,208,140,0.18),_transparent_26%)]" />
|
|
<div className="relative mx-auto grid max-w-6xl gap-14 px-6 py-18 lg:grid-cols-[1.1fr_0.9fr] lg:px-10 lg:py-24">
|
|
<div className="flex flex-col justify-center">
|
|
<div className="inline-flex w-fit items-center gap-2 rounded-full border border-white/15 bg-white/8 px-4 py-1.5 text-[11px] font-medium uppercase tracking-[0.32em] text-[#ead7b0]">
|
|
<BaseIcon path={mdiHomeCity} size={16} className="text-[#f5deb3]" />
|
|
Gracey private operations suite
|
|
</div>
|
|
|
|
<h1 className="mt-7 max-w-4xl text-4xl font-semibold leading-[1.02] text-white md:text-[64px]">
|
|
A more elegant operating layer for premium corporate stays.
|
|
</h1>
|
|
|
|
<p className="mt-6 max-w-2xl text-lg leading-8 text-slate-200">
|
|
Gracey gives booking, service, and billing teams one composed system for high-touch stays—quiet in tone,
|
|
precise in execution, and built for the work behind the guest experience.
|
|
</p>
|
|
|
|
<div className="mt-8 flex flex-wrap gap-3">
|
|
<BaseButton href="/command-center" color="info" label="Open workspace" icon={mdiArrowTopRight} />
|
|
<BaseButton href="/login" color="whiteDark" label="Login" />
|
|
</div>
|
|
|
|
<div className="mt-12 grid gap-4 sm:grid-cols-3">
|
|
{highlights.map((item) => (
|
|
<div key={item.label} className="border-l border-white/20 pl-4">
|
|
<div className="text-[11px] font-medium uppercase tracking-[0.24em] text-[#d7c19a]">{item.label}</div>
|
|
<div className="mt-2 text-sm leading-6 text-slate-100">{item.value}</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<CardBox className="border border-white/10 bg-white/8 text-white shadow-[0_40px_120px_-60px_rgba(15,23,42,0.95)] backdrop-blur-sm">
|
|
<div className="flex items-start justify-between gap-4">
|
|
<div>
|
|
<div className="text-[11px] font-medium uppercase tracking-[0.28em] text-[#d7c19a]">Operator brief</div>
|
|
<h2 className="mt-3 text-2xl font-semibold text-white">What the platform quietly keeps under control</h2>
|
|
</div>
|
|
<div className="rounded-full border border-[#d7c19a]/40 bg-[#d7c19a]/12 px-3 py-1 text-xs font-medium text-[#f2dfba]">
|
|
Refined workflow
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-8 space-y-4">
|
|
{workflowMoments.map((item) => (
|
|
<div key={item.step} className="rounded-[28px] border border-white/10 bg-black/10 p-5">
|
|
<div className="text-xs font-semibold tracking-[0.24em] text-[#d7c19a]">{item.step}</div>
|
|
<h3 className="mt-2 text-lg font-semibold text-white">{item.title}</h3>
|
|
<p className="mt-2 text-sm leading-7 text-slate-200">{item.description}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="mt-8 rounded-[28px] border border-white/10 bg-white/6 p-5">
|
|
<div className="flex items-start gap-3">
|
|
<BaseIcon path={mdiCheckDecagram} size={20} className="mt-0.5 text-[#f0d8ab]" />
|
|
<p className="text-sm leading-7 text-slate-100">
|
|
The public experience stays polished and restrained. The real depth appears only where it belongs:
|
|
inside the authenticated workspace.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</CardBox>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="mx-auto max-w-6xl px-6 py-16 lg:px-10 lg:py-20">
|
|
<div className="grid gap-10 lg:grid-cols-[0.9fr_1.1fr] lg:items-end">
|
|
<div>
|
|
<div className="text-[11px] font-medium uppercase tracking-[0.28em] text-[#8b6b42]">Signature coverage</div>
|
|
<h2 className="mt-3 max-w-2xl text-3xl font-semibold leading-tight text-slate-950 md:text-5xl">
|
|
Designed for teams that want operational polish, not marketing noise.
|
|
</h2>
|
|
</div>
|
|
<p className="max-w-2xl text-base leading-8 text-slate-700 lg:justify-self-end">
|
|
Every section is meant to feel intentional: fewer blocks, better restraint, and a stronger sense that the
|
|
product supports a premium service model behind the scenes.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="mt-10 grid gap-6 md:grid-cols-3">
|
|
{productAreas.map((item) => (
|
|
<div
|
|
key={item.title}
|
|
className="rounded-[32px] border border-[#d9cfbf] bg-[#fcfaf6] p-7 shadow-[0_28px_70px_-60px_rgba(15,23,42,0.45)]"
|
|
>
|
|
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#efe5d4] text-[#5f4526]">
|
|
<BaseIcon path={item.icon} size={22} />
|
|
</div>
|
|
<h3 className="mt-6 text-xl font-semibold text-slate-950">{item.title}</h3>
|
|
<p className="mt-3 text-sm leading-7 text-slate-700">{item.description}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="border-y border-[#d9cfbf] bg-[#efe7db]">
|
|
<div className="mx-auto grid max-w-6xl gap-10 px-6 py-16 lg:grid-cols-[0.95fr_1.05fr] lg:px-10 lg:py-20">
|
|
<div>
|
|
<div className="text-[11px] font-medium uppercase tracking-[0.28em] text-[#8b6b42]">Service standard</div>
|
|
<h2 className="mt-3 text-3xl font-semibold leading-tight text-slate-950 md:text-4xl">
|
|
Luxury online should feel composed, selective, and credible.
|
|
</h2>
|
|
<p className="mt-4 text-base leading-8 text-slate-700">
|
|
So the page leads with restraint: rich tone, quiet confidence, and a product story grounded in actual
|
|
operations rather than inflated feature theater.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid gap-4">
|
|
{servicePillars.map((item) => (
|
|
<div key={item} className="flex items-start gap-4 rounded-[28px] border border-white/60 bg-white/70 p-5 backdrop-blur">
|
|
<BaseIcon path={mdiCheckDecagram} size={20} className="mt-1 text-[#8b6b42]" />
|
|
<p className="text-sm leading-7 text-slate-800">{item}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="px-6 py-16 lg:px-10 lg:py-20">
|
|
<div className="mx-auto max-w-5xl rounded-[36px] border border-[#cfbc9b] bg-[linear-gradient(135deg,#111827_0%,#1f2937_58%,#6b4f2c_100%)] px-6 py-10 text-white shadow-[0_40px_120px_-55px_rgba(15,23,42,0.9)] lg:px-10 lg:py-12">
|
|
<div className="grid gap-8 lg:grid-cols-[1.1fr_0.9fr] lg:items-end">
|
|
<div>
|
|
<div className="text-[11px] font-medium uppercase tracking-[0.28em] text-[#dcc49f]">Private access</div>
|
|
<h2 className="mt-3 max-w-2xl text-3xl font-semibold leading-tight md:text-4xl">
|
|
Enter the workspace when the conversation turns into execution.
|
|
</h2>
|
|
<p className="mt-4 max-w-2xl text-sm leading-7 text-slate-200 md:text-base">
|
|
Review booking flow activity, open the operating workspace, and continue from live data instead of a
|
|
brochure-style homepage.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="rounded-[28px] border border-white/10 bg-black/10 p-5">
|
|
<div className="text-[11px] font-medium uppercase tracking-[0.24em] text-[#d7c19a]">For internal teams</div>
|
|
<p className="mt-3 text-sm leading-7 text-slate-200">
|
|
Reservations, service operations, and billing remain connected—without losing the elevated feel the
|
|
brand should project externally.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-8 flex flex-wrap gap-3">
|
|
<BaseButton href="/command-center" color="info" label="Open workspace" />
|
|
<BaseButton href="/booking_requests/booking_requests-list" color="whiteDark" label="View booking flow" />
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<PublicSiteFooter />
|
|
</main>
|
|
</>
|
|
);
|
|
}
|
|
|
|
HomePage.getLayout = function getLayout(page: ReactElement) {
|
|
return <LayoutGuest>{page}</LayoutGuest>;
|
|
};
|