Skip to content

Commit

Permalink
Create logged-out home page, move logged-in home page to /dashboard
Browse files Browse the repository at this point in the history
… and redirect (#28)

* Add signed-out home page experience

* Add redirect to dashboard if visitng home logged-in

* Linting and fmting

* Stretch sign-in button

* Now center the *contents* of the button 🙄
  • Loading branch information
franknoirot authored Oct 20, 2023
1 parent 3a53489 commit 184bd88
Show file tree
Hide file tree
Showing 7 changed files with 7,946 additions and 53 deletions.
6 changes: 5 additions & 1 deletion src/components/ModelPreviewer.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
<script lang="ts">
import { T } from '@threlte/core'
import { GLTF, OrbitControls, interactivity } from '@threlte/extras'
interactivity()
export let dataUrl: string
export let pausable = true
interactivity()
let shouldAutoRotate = true
const AUTO_ROTATE_PAUSE = 5000
let autorotateTimeout: ReturnType<typeof setTimeout> | undefined
const disableAutoRotate = () => {
if (!pausable) return
shouldAutoRotate = false
clearTimeout(autorotateTimeout)
}
const reenableAutoRotate = () => {
if (!pausable) return
autorotateTimeout = setTimeout(function () {
shouldAutoRotate = true
}, AUTO_ROTATE_PAUSE)
Expand Down
5 changes: 2 additions & 3 deletions src/components/Nav.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<script lang="ts">
import type { Models } from '@kittycad/lib'
import Logo from './Logo.svelte'
import { page } from '$app/stores'
import { paths } from '$lib/paths'
import AccountMenu from './AccountMenu.svelte'
export let user: Models['User_type'] | undefined
</script>

<nav class="nav">
<a href="/">
<a href={user ? paths.DASHBOARD : paths.HOME}>
<Logo className="h-6 md:h-12" />
</a>
{#if user}
Expand All @@ -19,7 +18,7 @@
href={import.meta.env.VITE_SITE_BASE_URL +
paths.SIGN_IN +
'/?callbackUrl=' +
encodeURIComponent($page.url.href)}>Sign in</a
encodeURIComponent(paths.DASHBOARD)}>Sign in</a
>
{/if}
</nav>
Expand Down
1 change: 1 addition & 0 deletions src/lib/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export const SIGN_OUT_PARAM = 'signout'
export const paths = {
SIGN_IN: '/signin',
HOME: '/',
DASHBOARD: '/dashboard',
SIGN_OUT: `/?${SIGN_OUT_PARAM}=true`
} as const
9 changes: 9 additions & 0 deletions src/routes/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { redirect } from '@sveltejs/kit'

export const load = async ({ cookies }) => {
const token = cookies.get('__Secure-next-auth.session-token')

if (token) {
throw redirect(302, '/dashboard')
}
}
115 changes: 66 additions & 49 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,59 +1,76 @@
<script lang="ts">
import { endpoints } from '$lib/endpoints'
import GenerationList from 'components/GenerationList.svelte'
import type { PromptLoadResponse } from './api/submit-prompt/+server'
import type { Models } from '@kittycad/lib'
import type { PageData } from './$types'
export let data: PageData
let promptedGenerations: Models['TextToCad_type'][] = []
import { paths } from '$lib/paths'
import { Canvas } from '@threlte/core'
import ModelPreviewer from 'components/ModelPreviewer.svelte'
const submitPrompt = async (e: Event) => {
e.preventDefault()
const prompt = (e.target as HTMLFormElement).prompt.value
const response = await fetch(endpoints.localPrompt, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ prompt })
})
const data = (await response.json()) as PromptLoadResponse
promptedGenerations = data.body ? [data.body, ...promptedGenerations] : promptedGenerations
const form = e.target as HTMLFormElement
form.reset()
}
const examples = [
{
prompt: 'a spur gear with 13 teeth',
model: '/models/spur-gear.gltf'
}
]
</script>

<section class="mx-auto max-w-3xl my-48">
<h1 class="text-5xl mb-2">
Text to <span class="text-stroke text-stroke-chalkboard-100 dark:text-stroke-chalkboard-20"
>CAD</span
<section class="mx-auto max-w-5xl my-48">
<div class="grid lg:grid-cols-2 gap-0 items-stretch min-h-[33vh]">
<h1 class="text-7xl py-12 self-center pl-4">
Text to <span class="text-stroke text-stroke-chalkboard-100 dark:text-stroke-chalkboard-20"
>CAD</span
>
</h1>
<div class="relative border border-b-0">
<div class="absolute inset-0 -top-full">
<Canvas>
<ModelPreviewer dataUrl={examples[0].model} pausable={false} />
</Canvas>
</div>
</div>
<div
class="w-full flex items-center justify-start col-span-2 text-4xl font-mono border py-4 px-6"
>
</h1>
<form on:submit={submitPrompt} class="flex w-full">
<label class="flex-1">
<span class="sr-only">Enter a text-to-CAD prompt:</span>
<input
autocapitalize="false"
name="prompt"
placeholder="Enter a text-to-CAD prompt:"
required
spellcheck="false"
type="text"
class="w-full px-4 py-1 border"
/>
</label>
<button type="submit" class="submit">Submit</button>
</form>
<div
class="typing-animation block text-chalkboard-70 dark:text-chalkboard-40"
style={`--steps: ${examples[0].prompt.length - 1}`}
>
<div class="block w-fit">{examples[0].prompt}</div>
</div>
</div>
<div class="col-span-2 flex items-center border border-t-0">
<p class="flex-1 pl-4 py-2 text-chalkboard-70 dark:text-chalkboard-40">
Create B-Rep CAD files and meshes from natural language prompts. Powered by KittyCAD.
</p>
<a
href={paths.SIGN_IN}
class="self-stretch flex items-center justify-center text-center bg-energy-10/70 px-4 py-2 dark:bg-energy-40 border-0 border-l font-mono hover:bg-energy-10 dark:hover:bg-energy-20"
>Sign in to get started</a
>
</div>
</div>
</section>
{#if Boolean(data.user)}
<GenerationList additionalGenerations={promptedGenerations} />
{/if}

<style lang="postcss">
.submit {
@apply px-4 py-1 border border-l-0;
@apply border-chalkboard-100 dark:border-chalkboard-20;
@apply bg-energy-10 text-energy-100;
@apply dark:bg-energy-90 dark:text-energy-10;
.typing-animation {
--_cursor-width: 0.15em;
overflow: hidden; /* Ensures the content is not revealed until the animation */
border-right: var(--_cursor-width) solid theme('colors.energy.40'); /* The typwriter cursor */
white-space: nowrap; /* Keeps the content on a single line */
letter-spacing: var(--_cursor-width); /* Adjust as needed */
animation: typing calc(var(--step-timing, 0.1s) * var(--steps, 20)) steps(var(--steps, 20), end),
blink-caret 0.85s step-end infinite;
}
@keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}
@keyframes blink-caret {
50% {
border-color: transparent;
}
}
</style>
59 changes: 59 additions & 0 deletions src/routes/dashboard/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script lang="ts">
import { endpoints } from '$lib/endpoints'
import GenerationList from 'components/GenerationList.svelte'
import type { PromptLoadResponse } from '../api/submit-prompt/+server'
import type { Models } from '@kittycad/lib'
import type { PageData } from './$types'
export let data: PageData
let promptedGenerations: Models['TextToCad_type'][] = []
const submitPrompt = async (e: Event) => {
e.preventDefault()
const prompt = (e.target as HTMLFormElement).prompt.value
const response = await fetch(endpoints.localPrompt, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ prompt })
})
const data = (await response.json()) as PromptLoadResponse
promptedGenerations = data.body ? [data.body, ...promptedGenerations] : promptedGenerations
const form = e.target as HTMLFormElement
form.reset()
}
</script>

<section class="mx-auto max-w-3xl my-48">
<h1 class="text-5xl mb-2">
Text to <span class="text-stroke text-stroke-chalkboard-100 dark:text-stroke-chalkboard-20"
>CAD</span
>
</h1>
<form on:submit={submitPrompt} class="flex w-full">
<label class="flex-1">
<span class="sr-only">Enter a text-to-CAD prompt:</span>
<input
autocapitalize="false"
name="prompt"
placeholder="Enter a text-to-CAD prompt:"
required
spellcheck="false"
type="text"
class="w-full px-4 py-1 border"
/>
</label>
<button type="submit" class="submit">Submit</button>
</form>
</section>
{#if Boolean(data.user)}
<GenerationList additionalGenerations={promptedGenerations} />
{/if}

<style lang="postcss">
.submit {
@apply px-4 py-1 border border-l-0;
@apply border-chalkboard-100 dark:border-chalkboard-20;
@apply bg-energy-10 text-energy-100;
@apply dark:bg-energy-90 dark:text-energy-10;
}
</style>
Loading

0 comments on commit 184bd88

Please sign in to comment.