From 39e90f4f09d4c7b6984a40a64870f4691d67a2c0 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sun, 8 Feb 2026 15:09:17 +0100 Subject: [PATCH] feat: implement site creation confirmation with integration options and script copying functionality --- app/sites/new/page.tsx | 124 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/app/sites/new/page.tsx b/app/sites/new/page.tsx index 0350d07..b4f0522 100644 --- a/app/sites/new/page.tsx +++ b/app/sites/new/page.tsx @@ -1,12 +1,18 @@ 'use client' -import { useState, useEffect } from 'react' +import { useState, useEffect, useCallback } from 'react' import { useRouter } from 'next/navigation' -import { createSite, listSites } from '@/lib/api/sites' +import Link from 'next/link' +import { createSite, listSites, type Site } from '@/lib/api/sites' import { getSubscription } from '@/lib/api/billing' +import { API_URL, APP_URL } from '@/lib/api/client' +import { integrations, getIntegration } from '@/lib/integrations' import { toast } from '@ciphera-net/ui' import { getAuthErrorMessage } from '@/lib/utils/authErrors' import { Button, Input } from '@ciphera-net/ui' +import { CheckCircleIcon, CheckIcon } from '@ciphera-net/ui' + +const popularIntegrations = integrations.filter((i) => i.category === 'framework').slice(0, 10) export default function NewSitePage() { const router = useRouter() @@ -15,6 +21,9 @@ export default function NewSitePage() { name: '', domain: '', }) + const [createdSite, setCreatedSite] = useState(null) + const [selectedIntegrationSlug, setSelectedIntegrationSlug] = useState(null) + const [scriptCopied, setScriptCopied] = useState(false) // * Check for plan limits on mount useEffect(() => { @@ -38,6 +47,15 @@ export default function NewSitePage() { checkLimits() }, [router]) + const copyScript = useCallback(() => { + if (!createdSite) return + const script = `` + navigator.clipboard.writeText(script) + setScriptCopied(true) + toast.success('Script copied to clipboard') + setTimeout(() => setScriptCopied(false), 2000) + }, [createdSite]) + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setLoading(true) @@ -45,14 +63,112 @@ export default function NewSitePage() { try { const site = await createSite(formData) toast.success('Site created successfully') - router.push(`/sites/${site.id}`) - } catch (error: any) { + setCreatedSite(site) + } catch (error: unknown) { toast.error(getAuthErrorMessage(error) || 'Failed to create site: ' + ((error as Error)?.message || 'Unknown error')) } finally { setLoading(false) } } + // * Step 2: Show framework picker + script (same as /welcome after adding first site) + if (createdSite) { + return ( +
+
+
+
+ +
+

+ Site created +

+

+ Add the script to your site to start collecting data. +

+
+ +
+

+ Add the script to your site +

+

+ Choose your framework for setup instructions. +

+
+ {popularIntegrations.map((int) => ( + + ))} +
+

+ + View all integrations → + +

+ +
+ + {``} + + +
+ {selectedIntegrationSlug && getIntegration(selectedIntegrationSlug) && ( +

+ + See full {getIntegration(selectedIntegrationSlug)!.name} guide → + +

+ )} +
+ +
+ + +
+
+
+ ) + } + + // * Step 1: Name & domain form return (