diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 7ddae9c..15b1464 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,5 +1,6 @@ import { createClient } from '@/lib/supabase/server' import Link from 'next/link' +import NewProjectButton from '@/components/NewProjectButton' interface Project { id: string @@ -47,13 +48,16 @@ export default async function DashboardPage() { return (
-
-

- Your Projects -

-

- Select a project to open the flowchart editor -

+
+
+

+ Your Projects +

+

+ Select a project to open the flowchart editor +

+
+
{projects && projects.length > 0 ? ( diff --git a/src/app/signup/page.tsx b/src/app/signup/page.tsx index da9c15b..fb1a733 100644 --- a/src/app/signup/page.tsx +++ b/src/app/signup/page.tsx @@ -8,19 +8,14 @@ import { createClient } from '@/lib/supabase/client' export default function SignupPage() { const router = useRouter() const searchParams = useSearchParams() - const [email, setEmail] = useState('') + // Pre-fill email if provided in URL (from invite link) + const [email, setEmail] = useState(searchParams.get('email') ?? '') const [password, setPassword] = useState('') const [confirmPassword, setConfirmPassword] = useState('') const [error, setError] = useState(null) const [loading, setLoading] = useState(false) useEffect(() => { - // Pre-fill email if provided in URL (from invite link) - const emailParam = searchParams.get('email') - if (emailParam) { - setEmail(emailParam) - } - // Handle invite/signup token from URL hash // Supabase adds tokens to the URL hash after redirect const handleTokenFromUrl = async () => { diff --git a/src/components/NewProjectButton.tsx b/src/components/NewProjectButton.tsx new file mode 100644 index 0000000..ea6df58 --- /dev/null +++ b/src/components/NewProjectButton.tsx @@ -0,0 +1,156 @@ +'use client' + +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import { createClient } from '@/lib/supabase/client' + +export default function NewProjectButton() { + const [isOpen, setIsOpen] = useState(false) + const [projectName, setProjectName] = useState('') + const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState(null) + const router = useRouter() + + const handleOpen = () => { + setIsOpen(true) + setProjectName('') + setError(null) + } + + const handleClose = () => { + if (!isLoading) { + setIsOpen(false) + setProjectName('') + setError(null) + } + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + + if (!projectName.trim()) { + setError('Project name is required') + return + } + + setIsLoading(true) + setError(null) + + const supabase = createClient() + + const { + data: { user }, + } = await supabase.auth.getUser() + + if (!user) { + setError('You must be logged in to create a project') + setIsLoading(false) + return + } + + const { data, error: insertError } = await supabase + .from('projects') + .insert({ + user_id: user.id, + name: projectName.trim(), + flowchart_data: { nodes: [], edges: [] }, + }) + .select('id') + .single() + + if (insertError) { + setError(insertError.message || 'Failed to create project') + setIsLoading(false) + return + } + + if (data) { + router.push(`/editor/${data.id}`) + } + } + + return ( + <> + + + {isOpen && ( +
+ + )} + + ) +}