This repository has been archived by the owner on Jun 27, 2024. It is now read-only.
generated from sanity-io/sanity-template-vercel-visual-editing
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* styling setup * button component * newsletter form * feat: setup react query for subscription mutation
- Loading branch information
1 parent
88136ad
commit 1a9a8eb
Showing
36 changed files
with
1,723 additions
and
746 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
20.11.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"plugins": [ | ||
"prettier-plugin-organize-imports", | ||
"prettier-plugin-tailwindcss" | ||
], | ||
"tailwindConfig": "./tailwind.config.js", | ||
"tailwindFunctions": ["tv"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,19 @@ | ||
import 'tailwindcss/tailwind.css' | ||
|
||
import { IBM_Plex_Mono, Inter, PT_Serif } from 'next/font/google' | ||
import { karelia } from '@/fonts/fonts' | ||
|
||
const serif = PT_Serif({ | ||
variable: '--font-serif', | ||
style: ['normal', 'italic'], | ||
subsets: ['latin'], | ||
weight: ['400', '700'], | ||
}) | ||
const sans = Inter({ | ||
variable: '--font-sans', | ||
subsets: ['latin'], | ||
// @todo: understand why extrabold (800) isn't being respected when explicitly specified in this weight array | ||
// weight: ['500', '700', '800'], | ||
}) | ||
const mono = IBM_Plex_Mono({ | ||
variable: '--font-mono', | ||
subsets: ['latin'], | ||
weight: ['500', '700'], | ||
}) | ||
import { Providers } from './providers' | ||
|
||
export default async function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode | ||
}) { | ||
return ( | ||
<html | ||
lang="en" | ||
className={`${mono.variable} ${sans.variable} ${serif.variable}`} | ||
> | ||
<body>{children}</body> | ||
<html lang="en" className={`${karelia.variable}`}> | ||
<body className="overscroll-none"> | ||
<Providers>{children}</Providers> | ||
</body> | ||
</html> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import type { Metadata } from 'next/types' | ||
|
||
import { HomePage } from '@/components/pages/home/HomePage' | ||
|
||
export const metadata: Metadata = { | ||
title: 'Datum', | ||
} | ||
|
||
export default async function Homepage() { | ||
return <HomePage /> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use client' | ||
|
||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' | ||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools' | ||
|
||
const queryClient = new QueryClient() | ||
|
||
export function Providers({ children }: { children: React.ReactNode }) { | ||
return ( | ||
<QueryClientProvider client={queryClient}> | ||
{children} | ||
<ReactQueryDevtools initialIsOpen={false} /> | ||
</QueryClientProvider> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"$schema": "https://ui.shadcn.com/schema.json", | ||
"style": "default", | ||
"rsc": true, | ||
"tsx": true, | ||
"tailwind": { | ||
"config": "tailwind.config.ts", | ||
"css": "styles/index.css", | ||
"baseColor": "slate", | ||
"cssVariables": false, | ||
"prefix": "" | ||
}, | ||
"aliases": { | ||
"components": "@/components", | ||
"utils": "@/lib/utils" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
type LogoProps = { | ||
w?: number | ||
h?: number | ||
} | ||
|
||
export const Logo = ({ w = 145, h = 39 }: LogoProps) => { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
width={`${w}px`} | ||
height={`${h}px`} | ||
fill="none" | ||
viewBox="0 0 145 39" | ||
> | ||
<path | ||
fill="#F27A67" | ||
d="M14.254 0a.996.996 0 0 0-.995.995v9.725c0 .548.445.995.995.995h4.778c1.951 0 3.81.762 5.233 2.144 1.433 1.392 2.233 3.229 2.255 5.176a7.35 7.35 0 0 1-2.14 5.29 7.352 7.352 0 0 1-5.264 2.197h-.084c-1.947-.023-3.784-.823-5.176-2.255a7.485 7.485 0 0 1-2.144-5.234v-4.778a.996.996 0 0 0-.995-.995H.995a.996.996 0 0 0-.995.995v9.725c0 .548.446.995.995.995H8.67c1.032 0 1.697.014 2.245.089.728.098 1.216.306 1.584.673.368.367.575.856.674 1.584.074.55.088 1.213.088 2.247v7.672c0 .548.446.995.995.995h4.863a19.08 19.08 0 0 0 6.372-1.09c7.623-2.694 12.745-9.939 12.745-18.027 0-8.089-5.122-15.334-12.745-18.029A19.08 19.08 0 0 0 19.118 0H14.254Z" | ||
/> | ||
<path | ||
fill="#fff" | ||
d="M139.479 13.68c1.607 0 2.831.503 3.671 1.51.851.995 1.276 2.359 1.276 4.091v10.968h-3.858V20.183c0-2.105-.82-3.158-2.459-3.158-.943 0-1.726.436-2.349 1.307-.622.871-.933 1.996-.933 3.376v8.541h-3.843V20.183c0-1.026-.208-1.81-.622-2.349-.415-.54-1.027-.809-1.836-.809-.944 0-1.727.436-2.35 1.307-.622.871-.933 1.986-.933 3.345v8.572h-3.889V14.007h3.827v2.956h.093c.291-.902.835-1.675 1.634-2.318.809-.643 1.815-.965 3.018-.965 1.224 0 2.22.296 2.987.887.778.591 1.312 1.431 1.603 2.52h.093a5.092 5.092 0 0 1 1.742-2.427c.83-.653 1.873-.98 3.128-.98ZM105.001 25.022V14.007h3.858v10.129c0 2.074.845 3.111 2.536 3.111.996 0 1.82-.446 2.474-1.338.653-.892.98-2.038.98-3.438v-8.464h3.874V30.25h-3.812v-3.034h-.093c-.374.975-.939 1.779-1.696 2.412-.757.622-1.711.933-2.863.933-3.505 0-5.258-1.846-5.258-5.539ZM94.828 25.567V17.18h-2.132v-3.018h.794c.643 0 1.068-.14 1.276-.42.218-.28.326-.85.326-1.712V8.904h3.594v5.103h4.045v3.174h-4.045v7.717c0 .902.156 1.535.467 1.898.311.352.825.529 1.54.529.695 0 1.375-.161 2.038-.482v3.189c-.912.384-1.918.576-3.018.576-1.732 0-2.982-.39-3.75-1.167-.756-.789-1.135-2.08-1.135-3.874ZM75.112 22.253c0-2.635.643-4.72 1.93-6.255 1.286-1.545 2.992-2.318 5.118-2.318 1.234 0 2.23.275 2.987.825.757.539 1.265 1.156 1.525 1.851h.109v-2.35h3.78V30.25h-3.78v-2.925h-.11c-.217.872-.746 1.629-1.586 2.272-.84.643-1.934.965-3.283.965-.944 0-1.82-.182-2.63-.545a6.292 6.292 0 0 1-2.13-1.571c-.602-.685-1.074-1.556-1.416-2.614-.343-1.068-.514-2.261-.514-3.578Zm11.59.093v-.794c0-1.472-.352-2.634-1.057-3.485-.695-.86-1.571-1.29-2.63-1.29-1.213 0-2.183.481-2.909 1.446-.715.965-1.073 2.266-1.073 3.905 0 1.68.352 2.987 1.058 3.92.705.934 1.628 1.4 2.77 1.4 1.12 0 2.037-.45 2.753-1.353.726-.902 1.089-2.152 1.089-3.75ZM55.258 8.904h7.872c1.307 0 2.51.177 3.61.53 1.11.352 2.063.845 2.862 1.477a9.063 9.063 0 0 1 2.054 2.256c.57.871.995 1.83 1.275 2.878.28 1.048.42 2.163.42 3.345 0 1.535-.233 2.961-.7 4.279a10.355 10.355 0 0 1-1.975 3.438c-.861.975-1.956 1.742-3.283 2.303-1.328.56-2.816.84-4.465.84h-7.67V8.904ZM62.71 26.78c1.1 0 2.069-.181 2.91-.544.85-.363 1.54-.872 2.068-1.525a6.717 6.717 0 0 0 1.183-2.318c.27-.882.404-1.862.404-2.94 0-1.017-.13-1.945-.389-2.785a6.588 6.588 0 0 0-1.166-2.24c-.52-.654-1.204-1.157-2.054-1.51-.85-.363-1.836-.544-2.956-.544h-3.47V26.78h3.47Z" | ||
/> | ||
</svg> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
'use client' | ||
import Matter from 'matter-js' | ||
import React, { useEffect, useRef } from 'react' | ||
|
||
export const HomePageAnimation = () => { | ||
const sceneRef = useRef(null) | ||
|
||
useEffect(() => { | ||
const { | ||
Engine, | ||
Render, | ||
Runner, | ||
Bodies, | ||
Composite, | ||
Composites, | ||
Constraint, | ||
Mouse, | ||
MouseConstraint, | ||
Common, | ||
Events, | ||
Body, | ||
} = Matter | ||
|
||
const currentRef = sceneRef.current | ||
if (!currentRef) return | ||
|
||
const engine = Engine.create() | ||
const world = engine.world | ||
const render = Render.create({ | ||
element: currentRef, | ||
engine: engine, | ||
options: { | ||
width: 1000, | ||
height: 1100, | ||
wireframes: true, | ||
background: 'white', | ||
}, | ||
}) | ||
|
||
Render.run(render) | ||
const runner = Runner.create() | ||
Runner.run(runner, engine) | ||
|
||
// create obstacles | ||
const obstacles = Composites.stack(10, 0, 15, 3, 10, 10, function (x, y) { | ||
let sides = Math.round(Common.random(1, 8)), | ||
options = { | ||
render: { | ||
fillStyle: Common.choose([ | ||
'#48f164', | ||
'#f5d259', | ||
'#f55a3c', | ||
'#063e7b', | ||
'#ececd1', | ||
]), | ||
}, | ||
} | ||
|
||
switch (Math.round(Common.random(0, 1))) { | ||
case 0: | ||
if (Common.random() < 0.8) { | ||
return Bodies.rectangle( | ||
x, | ||
y, | ||
Common.random(25, 50), | ||
Common.random(25, 50), | ||
options, | ||
) | ||
} else { | ||
return Bodies.rectangle( | ||
x, | ||
y, | ||
Common.random(80, 120), | ||
Common.random(25, 30), | ||
options, | ||
) | ||
} | ||
case 1: | ||
return Bodies.polygon(x, y, sides, Common.random(25, 50), options) | ||
} | ||
}) | ||
|
||
Composite.add(world, [obstacles]) | ||
|
||
let timeScaleTarget = 1, | ||
lastTime = Common.now() | ||
|
||
Events.on(engine, 'afterUpdate', function (event) { | ||
var timeScale = (event.delta || 1000 / 60) / 1000 | ||
|
||
// tween the timescale for slow-mo | ||
if (mouse.button === -1) { | ||
engine.timing.timeScale += | ||
(timeScaleTarget - engine.timing.timeScale) * 3 * timeScale | ||
} else { | ||
engine.timing.timeScale = 1 | ||
} | ||
|
||
// every 2 sec (real time) | ||
if (Common.now() - lastTime >= 2000) { | ||
// flip the timescale | ||
if (timeScaleTarget < 1) { | ||
timeScaleTarget = 1 | ||
} else { | ||
timeScaleTarget = 0.05 | ||
} | ||
|
||
// update last time | ||
lastTime = Common.now() | ||
} | ||
|
||
for (let i = 0; i < obstacles.bodies.length; i += 1) { | ||
var body = obstacles.bodies[i], | ||
bounds = body.bounds | ||
|
||
// move obstacles back to the top of the screen | ||
if (bounds.min.y > render.bounds.max.y + 100) { | ||
Body.translate(body, { | ||
x: -bounds.min.x, | ||
y: -render.bounds.max.y - 300, | ||
}) | ||
} | ||
} | ||
}) | ||
|
||
// add mouse control and make the mouse revolute | ||
var mouse = Mouse.create(render.canvas), | ||
mouseConstraint = MouseConstraint.create(engine, { | ||
mouse: mouse, | ||
constraint: { | ||
stiffness: 0.6, | ||
length: 0, | ||
angularStiffness: 0, | ||
render: { | ||
visible: false, | ||
}, | ||
}, | ||
}) | ||
|
||
Composite.add(world, mouseConstraint) | ||
|
||
// keep the mouse in sync with rendering | ||
render.mouse = mouse | ||
|
||
// fit the render viewport to the scene | ||
Render.lookAt(render, { | ||
min: { x: 0, y: 0 }, | ||
max: { x: 800, y: 600 }, | ||
}) | ||
|
||
return () => { | ||
Render.stop(render) | ||
Runner.stop(runner) | ||
while (currentRef.firstChild) { | ||
currentRef.removeChild(currentRef.firstChild) | ||
} | ||
} | ||
}, []) | ||
|
||
return <div ref={sceneRef} className="w-full h-full overflow-hidden"></div> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
'use client' | ||
|
||
import { zodResolver } from '@hookform/resolvers/zod' | ||
import { LoaderCircle, MailCheck } from 'lucide-react' | ||
import { useForm } from 'react-hook-form' | ||
import { z } from 'zod' | ||
|
||
import { | ||
Button, | ||
Form, | ||
FormControl, | ||
FormField, | ||
FormMessage, | ||
Input, | ||
} from '@/components/ui' | ||
import { useSubscribeMutation } from '@/hooks/mutations/useSubscribeMutation' | ||
|
||
import { newsletterStyles } from './HomePage.styles' | ||
|
||
const formSchema = z.object({ | ||
email: z.string().email(), | ||
}) | ||
|
||
export const HomePageNewsletter = () => { | ||
const { | ||
wrapper, | ||
input, | ||
button, | ||
errorMessage, | ||
success, | ||
successMessage, | ||
successIcon, | ||
} = newsletterStyles() | ||
const { mutate, status, isError, error, data } = useSubscribeMutation() | ||
const isLoading = status === 'pending' | ||
|
||
const form = useForm<z.infer<typeof formSchema>>({ | ||
resolver: zodResolver(formSchema), | ||
defaultValues: { | ||
email: '', | ||
}, | ||
}) | ||
|
||
const onSubmit = ({ email }: z.infer<typeof formSchema>) => { | ||
mutate(email) | ||
} | ||
|
||
return ( | ||
<> | ||
{status === 'success' ? ( | ||
<div className={success()}> | ||
<MailCheck size={24} className={successIcon()} /> | ||
<span className={successMessage()}>{data.message}</span> | ||
</div> | ||
) : ( | ||
<Form {...form}> | ||
<form onSubmit={form.handleSubmit(onSubmit)} className={wrapper()}> | ||
<FormField | ||
control={form.control} | ||
name="email" | ||
render={({ field }) => ( | ||
<> | ||
<FormControl> | ||
<Input | ||
type="email" | ||
placeholder="Your email" | ||
variant="outline" | ||
className={input()} | ||
{...field} | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
</> | ||
)} | ||
/> | ||
<Button type="submit" variant="white" className={button()}> | ||
{isLoading && <LoaderCircle className="animate-spin" size={20} />} | ||
{isLoading ? 'Loading' : 'Stay in the loop'} | ||
</Button> | ||
</form> | ||
{isError && <div className={errorMessage()}>{error.message}</div>} | ||
</Form> | ||
)} | ||
</> | ||
) | ||
} |
Oops, something went wrong.