Skip to content
This repository was archived by the owner on Sep 18, 2024. It is now read-only.

chore: implement landing page changes #116

Merged
merged 14 commits into from
May 13, 2024
Merged
12 changes: 6 additions & 6 deletions packages/studio-ts/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import logoPhobiaLight from '@/images/clients/phobia/logo-light.svg'
import logoUnseal from '@/images/clients/unseal/logo-light.svg'
import imageLaptop from '@/images/laptop.jpg'
import { type CaseStudy, type MDXEntry, loadCaseStudies } from '@/lib/mdx'
import { WaitlistForm } from '@/components/WaitlistForm'

const clients = [
['Phobia', logoPhobiaLight],
Expand Down Expand Up @@ -185,13 +186,12 @@ export default async function Home() {
<Container className="mt-24 sm:mt-32 md:mt-56">
<FadeIn className="max-w-3xl">
<h1 className="font-display text-5xl font-medium tracking-tight text-neutral-950 [text-wrap:balance] sm:text-7xl">
Award-winning development studio based in Denmark.
The open source Assistant Platform
</h1>
<p className="mt-6 text-xl text-neutral-600">
We are a development studio working at the intersection of design
and technology. It’s a really busy intersection though — a lot of
our staff have been involved in hit and runs.
</p>
<p className="mt-6 text-xl text-neutral-600">Join the waiting list</p>
<div>
<WaitlistForm />
</div>
</FadeIn>
</Container>

Expand Down
37 changes: 37 additions & 0 deletions packages/studio-ts/src/app/server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use server'

export type FormState = {
message: string
submitted: boolean
}

export const handleWaitlistSubmit = async (
prevState: FormState,
formData: FormData,
) => {
const url = process.env.NEXT_GOOGLE_SHEETS_API!
let rawFormData = { email: formData.get('email') }

try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(rawFormData),
})

if (response.ok) {
return { message: 'Email address sent successfully!', submitted: true }
} else {
console.error(
'Failed to send email address. Status code:',
response.status,
)
}
} catch (error) {
return { message: 'Email address not sent', submitted: false }
}

return { message: 'Email address not sent', submitted: false }
}
46 changes: 0 additions & 46 deletions packages/studio-ts/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,60 +65,14 @@ function Navigation() {
)
}

function ArrowIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
return (
<svg viewBox="0 0 16 6" aria-hidden="true" {...props}>
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M16 3 10 .5v2H0v1h10v2L16 3Z"
/>
</svg>
)
}

function NewsletterForm() {
return (
<form className="max-w-sm">
<h2 className="font-display text-sm font-semibold tracking-wider text-neutral-950">
Sign up for our newsletter
</h2>
<p className="mt-4 text-sm text-neutral-700">
Subscribe to get the latest design news, articles, resources and
inspiration.
</p>
<div className="relative mt-6">
<input
type="email"
placeholder="Email address"
autoComplete="email"
aria-label="Email address"
className="block w-full rounded-2xl border border-neutral-300 bg-transparent py-4 pl-6 pr-20 text-base/6 text-neutral-950 ring-4 ring-transparent transition placeholder:text-neutral-500 focus:border-neutral-950 focus:outline-none focus:ring-neutral-950/5"
/>
<div className="absolute inset-y-1 right-1 flex justify-end">
<button
type="submit"
aria-label="Submit"
className="flex aspect-square h-full items-center justify-center rounded-xl bg-neutral-950 text-white transition hover:bg-neutral-800"
>
<ArrowIcon className="w-4" />
</button>
</div>
</div>
</form>
)
}

export function Footer() {
return (
<Container as="footer" className="mt-24 w-full sm:mt-32 lg:mt-40">
<FadeIn>
<div className="grid grid-cols-1 gap-x-8 gap-y-16 lg:grid-cols-2">
<Navigation />
<div className="flex lg:justify-end">
<NewsletterForm />
</div>
</div>
<div className="mb-20 mt-24 flex flex-wrap items-end justify-between gap-x-6 gap-y-4 border-t border-neutral-950/10 pt-12">
<Link href="/" aria-label="Home">
Expand Down
8 changes: 4 additions & 4 deletions packages/studio-ts/src/components/RootLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ function Header({
/>
</Link>
<div className="flex items-center gap-x-8">
<Button href="/contact" invert={invert}>
Contact us
<Button href="https://github.com/AkeruAI/akeru" invert={invert}>
Star on Github!
</Button>
<button
{/* <button
ref={toggleRef}
type="button"
onClick={onToggle}
Expand All @@ -104,7 +104,7 @@ function Header({
: 'fill-neutral-950 group-hover:fill-neutral-700',
)}
/>
</button>
</button> */}
</div>
</div>
</Container>
Expand Down
79 changes: 79 additions & 0 deletions packages/studio-ts/src/components/WaitlistForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"use client"
import { FormState, handleWaitlistSubmit } from '@/app/server'
import { useFormState, useFormStatus } from 'react-dom'

const initialState: FormState = {
message: '',
submitted: false,
}

function ArrowIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
return (
<svg viewBox="0 0 16 6" aria-hidden="true" {...props}>
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M16 3 10 .5v2H0v1h10v2L16 3Z"
/>
</svg>
)
}

function CheckMarkIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
aria-hidden="true"
{...props}
viewBox="0 0 24 24"
>
<path d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z" />
</svg>
)
}

export function WaitlistForm() {
const [state, formAction] = useFormState(handleWaitlistSubmit, initialState)

return (
<form className="max-w-sm" action={formAction}>
<div className="relative mt-6">
<input
type="email"
placeholder="Email address"
autoComplete="email"
required
name={'email'}
aria-label="Email address"
className="block w-full rounded-2xl border border-neutral-300 bg-transparent py-4 pl-6 pr-20 text-base/6 text-neutral-950 ring-4 ring-transparent transition placeholder:text-neutral-500 focus:border-neutral-950 focus:outline-none focus:ring-neutral-950/5"
/>
<div className="absolute inset-y-1 right-1 flex justify-end">
<FormIconDisplay submitted={state?.submitted} />
</div>
</div>
</form>
)
}

function FormIconDisplay({ submitted }: { submitted: boolean | undefined }) {
const { pending } = useFormStatus()

return (
<button
type="submit"
aria-label="Submit"
disabled={pending}
className="flex aspect-square h-full items-center justify-center rounded-xl bg-neutral-950 text-white transition hover:bg-neutral-800"
>
{submitted ? (
<CheckMarkIcon className="w-4" />
) : (
<ArrowIcon className="w-4" />
)}
</button>
)
}
Loading