mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore: add non authenticated flow (#19243)
* add a new component for input * add textArea * some colors * rename * Update page.tsx * move files * Update ChatInput.tsx * Update Header.tsx * chore:upgrade next14 * Update package-lock.json * update graphql * add graphql dep * Update package.json * Update package-lock.json * added server action in * more actions * getting actions in everywhere * Update ConfirmDeleteThreadModal.tsx * Update Input.tsx * update modal action * Bump nextjs in database-new to v14. * fix build * trying server hooks * more experiemntal stuff * update delete * shimmering * update thread UI * Update actions.ts * Update actions.ts * Update Thread.tsx * Update Input.tsx * updated * delete thread updated * chore: add non authenticated flow * fix build * Update page.tsx * fix builds * Update package-lock.json * Update package.json * Update package-lock.json * Add login message * Cleanup --------- Co-authored-by: Terry Sutton <saltcod@gmail.com>
This commit is contained in:
1 parent
4c39abd88a
commit
d1c65ed77d
7 files changed
+140
-58
No files matched your search
@@ -0,0 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import { useAppStateSnapshot } from '@/lib/state'
|
||||
import { DialogContent_Shadcn_, Dialog_Shadcn_ } from 'ui'
|
||||
|
||||
const LoginDialog = ({ children }: { children: React.ReactNode }) => {
|
||||
const snap = useAppStateSnapshot()
|
||||
|
||||
return (
|
||||
<Dialog_Shadcn_
|
||||
open={snap.loginDialogOpen}
|
||||
onOpenChange={() => snap.setLoginDialogOpen(!snap.loginDialogOpen)}
|
||||
>
|
||||
<DialogContent_Shadcn_ className="max-w-md">{children}</DialogContent_Shadcn_>
|
||||
</Dialog_Shadcn_>
|
||||
)
|
||||
}
|
||||
|
||||
export { LoginDialog }
|
||||
@@ -1,9 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import { ChatInputAtom } from '@/components/Chat/ChatInput'
|
||||
import { CHAT_EXAMPLES } from '@/data/chat-examples'
|
||||
import { useAppStateSnapshot } from '@/lib/state'
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { ExternalLink } from 'lucide-react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { useState } from 'react'
|
||||
import { cn } from 'ui'
|
||||
|
||||
@@ -15,7 +18,21 @@ const suggestions = CHAT_EXAMPLES
|
||||
|
||||
const NewThreadInput = ({ userID }: ChatInputParams) => {
|
||||
const router = useRouter()
|
||||
const [value, setValue] = useState('')
|
||||
|
||||
const [value, setValue] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const localPrompt = localStorage.getItem('prompt')
|
||||
if (localPrompt) {
|
||||
localStorage.removeItem('prompt')
|
||||
return localPrompt
|
||||
}
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
const supabase = createClient()
|
||||
|
||||
const snap = useAppStateSnapshot()
|
||||
|
||||
const { mutate, isPending, isSuccess } = useMutation({
|
||||
mutationFn: async (prompt: string) => {
|
||||
@@ -39,8 +56,19 @@ const NewThreadInput = ({ userID }: ChatInputParams) => {
|
||||
<>
|
||||
<div className="relative w-10/12 xl:w-11/12 max-w-xl">
|
||||
<ChatInputAtom
|
||||
handleSubmit={() => {
|
||||
if (value.length > 0) mutate(value)
|
||||
handleSubmit={async () => {
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
if (!user) {
|
||||
localStorage.setItem('prompt', value)
|
||||
snap.setLoginDialogOpen(true)
|
||||
return
|
||||
}
|
||||
if (value.length > 0) {
|
||||
mutate(value)
|
||||
}
|
||||
}}
|
||||
autoFocus
|
||||
value={value}
|
||||
|
||||
@@ -1,53 +1,5 @@
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { Github } from 'lucide-react'
|
||||
import { cookies, headers } from 'next/headers'
|
||||
import { redirect } from 'next/navigation'
|
||||
import LoginForm from '@/components/Auth/LoginForm'
|
||||
|
||||
export default function Login({ searchParams }: { searchParams: { message: string } }) {
|
||||
const signUp = async (formData: FormData) => {
|
||||
'use server'
|
||||
|
||||
const origin = headers().get('origin')
|
||||
const cookieStore = cookies()
|
||||
const supabase = createClient(cookieStore)
|
||||
|
||||
const { data, error } = await supabase.auth.signInWithOAuth({
|
||||
provider: 'github',
|
||||
options: { redirectTo: `${origin}/auth/callback` },
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.log(error.message)
|
||||
return redirect(`/login?message=${error.message}`)
|
||||
} else {
|
||||
return redirect(data.url)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col justify-center h-full w-full px-8 sm:max-w-sm gap-2 mx-auto">
|
||||
<form
|
||||
className="animate-in flex-1 flex flex-col w-full justify-center gap-2 text-foreground"
|
||||
action={signUp}
|
||||
>
|
||||
<div className="flex items-center gap-x-2 justify-center mb-4">
|
||||
<span className="text-foreground-light">Sign in to</span>{' '}
|
||||
<div className="flex items-center gap-x-1.5 font-mono font-bold">
|
||||
<span>database</span>
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-purple-900"></div>
|
||||
<span>design</span>
|
||||
</div>
|
||||
</div>
|
||||
<button className="border text-sm bg-surface-100 rounded-md px-4 py-2 text-foreground mb-2 flex items-center justify-center gap-x-2">
|
||||
<Github size={18} />
|
||||
Sign in with Github
|
||||
</button>
|
||||
{searchParams?.message && (
|
||||
<p className="mt-4 p-4 bg-foreground/10 text-foreground text-center">
|
||||
{searchParams.message}
|
||||
</p>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
return <LoginForm searchParams={searchParams} />
|
||||
}
|
||||
@@ -2,12 +2,18 @@ import { createClient } from '@/lib/supabase/server'
|
||||
import type { Metadata } from 'next'
|
||||
import { cookies } from 'next/headers'
|
||||
import NewThreadInput from './NewThreadInput'
|
||||
import { LoginDialog } from './LoginDialog'
|
||||
import LoginForm from '@/components/Auth/LoginForm'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'database.design | Create',
|
||||
}
|
||||
|
||||
const NewThread = async () => {
|
||||
const NewThread = async ({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: { prompt: string; message: string }
|
||||
}) => {
|
||||
const cookieStore = cookies()
|
||||
const supabase = createClient(cookieStore)
|
||||
|
||||
@@ -15,10 +21,17 @@ const NewThread = async () => {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
console.log('searchParams on page level', searchParams)
|
||||
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center w-full flex-col gap-y-4">
|
||||
<NewThreadInput userID={user?.id} />
|
||||
</div>
|
||||
<>
|
||||
<div className="h-full flex items-center justify-center w-full flex-col gap-y-4">
|
||||
<NewThreadInput userID={user?.id} />
|
||||
</div>
|
||||
<LoginDialog>
|
||||
<LoginForm searchParams={searchParams} />
|
||||
</LoginDialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { Github } from 'lucide-react'
|
||||
import { cookies, headers } from 'next/headers'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { Button } from 'ui'
|
||||
|
||||
export default function LoginForm({ searchParams }: { searchParams?: { message?: string } }) {
|
||||
const signUp = async (formData: FormData) => {
|
||||
'use server'
|
||||
|
||||
const origin = headers().get('origin')
|
||||
const cookieStore = cookies()
|
||||
const supabase = createClient(cookieStore)
|
||||
|
||||
const { data, error } = await supabase.auth.signInWithOAuth({
|
||||
provider: 'github',
|
||||
options: { redirectTo: `${origin}/auth/callback` },
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.log(error.message)
|
||||
return redirect(`/login?message=${error.message}`)
|
||||
} else {
|
||||
return redirect(data.url)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col justify-center h-full w-full px-8 sm:max-w-sm gap-2 mx-auto">
|
||||
<form
|
||||
className="animate-in flex-1 flex flex-col w-full justify-center gap-2 text-foreground"
|
||||
action={signUp}
|
||||
>
|
||||
<div className="flex items-center gap-x-2 justify-center mb-4">
|
||||
<span className="text-foreground-light">Sign in to</span>{' '}
|
||||
<div className="flex items-center gap-x-1.5 font-mono font-bold">
|
||||
<span>database</span>
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-purple-900"></div>
|
||||
<span>design</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid gap-2 mb-4">
|
||||
<p className="text-center text-sm ">You need to sign in to generate a schema</p>
|
||||
<p className="text-center text-xs">Takes just a few seconds</p>
|
||||
</div>
|
||||
<Button
|
||||
className="border text-sm bg-surface-100 rounded-md px-4 py-2 text-foreground mb-2 flex items-center justify-center gap-x-2"
|
||||
type="default"
|
||||
htmlType="submit"
|
||||
icon={<Github size={18} />}
|
||||
>
|
||||
Sign in with Github
|
||||
</Button>
|
||||
|
||||
{searchParams?.message && (
|
||||
<p className="mt-4 p-4 bg-foreground/10 text-foreground text-center">
|
||||
{searchParams.message}
|
||||
</p>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -10,6 +10,11 @@ export const appState = proxy({
|
||||
setSelectedCode: (value: string) => {
|
||||
appState.selectedCode = value
|
||||
},
|
||||
|
||||
loginDialogOpen: false,
|
||||
setLoginDialogOpen: (value: boolean) => {
|
||||
appState.loginDialogOpen = value
|
||||
},
|
||||
})
|
||||
|
||||
export const getAppStateSnapshot = () => snapshot(appState)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as DialogPrimitive from '@radix-ui/react-dialog'
|
||||
import { X } from 'lucide-react'
|
||||
|
||||
Reference in new issue
Block a user