diff --git a/app/page.tsx b/app/page.tsx index 05d5a2c..8b70b9a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -14,8 +14,12 @@ export default function Login() { useEffect(() => { const init = async () => { - await axios.get("/api/user/init").then(() => { - router.push("/setup"); + await axios.get("/api/user/init").then((response) => { + if(response.data.message === "No users found") { + router.push("/setup"); + } else { + setLoading(false); + } }).catch((error) => { console.error(error); }); diff --git a/app/setup/SetupPage.tsx b/app/setup/SetupPage.tsx index ea615df..4f13652 100644 --- a/app/setup/SetupPage.tsx +++ b/app/setup/SetupPage.tsx @@ -4,8 +4,10 @@ import { useState } from "react" import { Mail, User, Lock } from "lucide-react" import ErrorToast from "@/components/Error" import { useRouter } from "next/navigation" - +import useSite from "@/hooks/useSite" import axios from "axios" +import useNetworks from "@/hooks/useNetworks" +import { Site } from "@/app/types" export default function SetupPage() { const router = useRouter() @@ -17,14 +19,20 @@ export default function SetupPage() { const [password, setPassword] = useState("") const [passwordConfirm, setPasswordConfirm] = useState("") + const [siteName, setSiteName] = useState("") + const [networkName, setNetworkName] = useState("") + + const { addSite } = useSite() + const { addNetwork } = useNetworks() + const [error, setError] = useState("") const handleNextStep = () => { - setStep(2) + setStep(step + 1) } const handlePreviousStep = () => { - setStep(1) + setStep(step - 1) } const handleComplete = async () => { @@ -33,17 +41,65 @@ export default function SetupPage() { return } try { + // Create user const response = await axios.post("/api/user/create", { email, username, name, password }) - if (response.status === 201) { - router.push("/") + + // Create site using the hook + const siteResult = addSite({ + id: "", + name: siteName, + description: "", + networks: [] + }) + + // Handle validation errors (returned as strings) + if (typeof siteResult === "string") { + setError(siteResult) + return } + + // If not a string, it's a Promise - await it + const site = await siteResult + + if (!site || !site.id) { + setError("Failed to create site") + return + } + + // Create network using the hook + const networkResult = addNetwork({ + id: "", + name: networkName, + siteId: site.id, + ipv4Subnet: "", + ipv6Subnet: "", + gateway: "" + }) + + // Handle validation errors + if (typeof networkResult === "string") { + setError(networkResult) + return + } + + // If not a string, it's a Promise - await it + const network = await networkResult + + if (!network) { + setError("Failed to create network") + return + } + + // Success - navigate to home + router.push("/") } catch (error: any) { - setError(error.response.data.error) + console.error("Error in setup:", error) + setError(typeof error === "string" ? error : error.response?.data?.error || error.message || "An unknown error occurred") } } @@ -55,8 +111,9 @@ export default function SetupPage() {
@@ -131,6 +188,40 @@ export default function SetupPage() { )} {step === 2 && ( +
+
+

Create site & network

+

Please create a site & network to get started. Don't worry, you can always change it later.

+
+ +
+
+ Site Name + +
Enter valid site name
+
+ +
+ Network Name + +
Enter valid network name
+
+
+ +
+ + +
+
+ )} + + {step === 3 && (

Next Steps

diff --git a/app/types.ts b/app/types.ts index 7886752..a2e841b 100644 --- a/app/types.ts +++ b/app/types.ts @@ -1,7 +1,7 @@ export interface Site { id: string; name: string; - description: string; + description?: string; networks: Network[]; } diff --git a/hooks/useNetworks.ts b/hooks/useNetworks.ts index f94d8ad..08599d1 100644 --- a/hooks/useNetworks.ts +++ b/hooks/useNetworks.ts @@ -3,16 +3,17 @@ import { Network } from "@/app/types"; const useNetworks = () => { - const addNetwork = (network: Network) => { + const addNetwork = (network: Network): Promise | string => { if (!network.name) { return 'Network name is required'; } - axios.post('/api/sites/networks/add', network) - .then(() => { - return; + + return axios.post('/api/sites/networks/add', network) + .then((response) => { + return response.data.network; }) .catch(err => { - return err.response?.data?.error || 'An error occurred'; + throw err.response?.data?.error || 'An error occurred'; }); }; diff --git a/hooks/useSite.ts b/hooks/useSite.ts index 3748c00..8f8cb43 100644 --- a/hooks/useSite.ts +++ b/hooks/useSite.ts @@ -44,6 +44,20 @@ const useSite = () => { }); }; + const addSite = (site: Site): Promise | string => { + if(site.name.length < 3) { + return 'Site name must be at least 3 characters long'; + } + + return axios.post('/api/sites/add', site) + .then((response) => { + return response.data.site; + }) + .catch(err => { + throw err.response?.data?.error || 'An error occurred'; + }); + }; + const deleteSite = (siteId: string) => { axios.delete('/api/sites/delete', { params: { siteId } @@ -60,6 +74,7 @@ const useSite = () => { loadSite, setSiteId, editSite, + addSite, deleteSite, loading };