diff --git a/apps/landing/package.json b/apps/landing/package.json index 7ba04d9cc..ec58883db 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -25,9 +25,11 @@ "phosphor-react": "^1.4.1", "prismjs": "^1.28.0", "react": "^18.1.0", + "react-canvas-confetti": "^1.3.0", "react-device-detect": "^2.2.2", "react-dom": "^18.1.0", "react-helmet": "^6.1.0", + "react-hook-form": "^7.31.3", "react-router-dom": "6.3.0", "react-tsparticles": "^2.0.6", "simple-icons": "^7.0.0", @@ -36,6 +38,7 @@ "devDependencies": { "@babel/preset-react": "^7.17.12", "@types/lodash": "^4.14.182", + "@types/node": "^17.0.36", "@types/prismjs": "^1.26.0", "@types/react": "^18.0.9", "@types/react-dom": "^18.0.5", diff --git a/apps/landing/src/components/Bubbles.tsx b/apps/landing/src/components/Bubbles.tsx index 1e6ff5030..0aa50f2f4 100644 --- a/apps/landing/src/components/Bubbles.tsx +++ b/apps/landing/src/components/Bubbles.tsx @@ -4,22 +4,15 @@ import { loadFull } from 'tsparticles'; export const Bubbles = () => { const particlesInit = async (main: any) => { - console.log(main); await loadFull(main); }; - const particlesLoaded = (container: any) => { - console.log(container); - }; - return ( //@ts-ignore (); + + const [loading, setLoading] = useState(false); + const [showWaitlistInput, setShowWaitlistInput] = useState(false); + const [waitlistError, setWaitlistError] = useState(''); + const [waitlistSubmitted, setWaitlistSubmitted] = useState(false); + const [fire, setFire] = useState(false); + + const prod = import.meta.env.NODE_ENV === 'production'; + const url = prod ? 'https://waitlist-api.spacedrive.com' : 'http://localhost:3000'; + + async function handleWaitlistSubmit({ email }: WaitlistInputs) { + if (!email.trim().length) return; + + console.log('email', email); + + setLoading(true); + + const req = await fetch(`${url}/api/waitlist`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + email + }) + }); + + if (req.status === 200) { + setWaitlistError(''); + setFire(Math.random()); + setWaitlistSubmitted(true); + setLoading(false); + } else if (req.status >= 400 && req.status < 500) { + const res = await req.json(); + setWaitlistError(res.message); + + // Remove error after a few seconds + setTimeout(() => { + setWaitlistError(''); + }, 5000); + } + + setLoading(false); + } + return ( <> +
- {/* {showWaitlistInput ? ( */} - {/* <> + {!showWaitlistInput ? ( + <> */} - - {/* + + + ) : ( -
{ - e.preventDefault(); - fetch('https://waitlist-api.spacedrive.com/api/expression-of-interest', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - email: waitlistEmail - }) - }); - }} - > -
- setWaitlistEmail(e.target.value)} - placeholder="Enter your email" - className="rounded-r-none" - /> - + +
+ {(waitlistError || waitlistSubmitted) && ( +
+ {waitlistError ? ( + + ) : ( + + )} +

+ {waitlistError || 'You have been added to the waitlist'} +

+
+ )} +
+ + {!waitlistSubmitted && ( + + )} +
)} - */}
-

- {/* {showWaitlistInput ? ( +

+ {showWaitlistInput ? ( <> We'll keep your place in the queue for early access.

+ ) : waitlistSubmitted ? ( + <> + You have been added to the waitlist. +
+
+ ) : ( - <>*/} - Coming soon on macOS, Windows and Linux. -
- Shortly after to iOS & Android. - {/* )} -

*/} + <> + Coming soon on macOS, Windows and Linux. +
+ Shortly after to iOS & Android. + + )}

); diff --git a/apps/landing/src/pages/index.tsx b/apps/landing/src/pages/index.tsx index de26c2974..c60f7a90b 100644 --- a/apps/landing/src/pages/index.tsx +++ b/apps/landing/src/pages/index.tsx @@ -1,15 +1,11 @@ -import { Apple, Github, Linux, Windows } from '@icons-pack/react-simple-icons'; -import { Button, Input } from '@sd/ui'; import clsx from 'clsx'; -import React, { useEffect } from 'react'; -import { useState } from 'react'; +import React, { useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { ReactComponent as Info } from '../../../../packages/interface/src/assets/svg/info.svg'; import AppEmbed from '../components/AppEmbed'; import { Bubbles } from '../components/Bubbles'; -import { Footer } from '../components/Footer'; import HomeCTA from '../components/HomeCTA'; -import NavBar from '../components/NavBar'; -import NewBanner from '../components/NewBanner'; interface SectionProps { orientation: 'left' | 'right'; @@ -44,6 +40,40 @@ function Section(props: SectionProps = { orientation: 'left' }) { } function Page() { + const [searchParams, setSearchParams] = useSearchParams(); + const [unsubscribedFromWaitlist, setUnsubscribedFromWaitlist] = useState(false); + + useEffect(() => { + if (!window) return; + + const cuid = searchParams.get('wunsub'); + if (!cuid) return; + + (async () => { + const prod = import.meta.env.NODE_ENV === 'production'; + const url = prod ? 'https://waitlist-api.spacedrive.com' : 'http://localhost:3000'; + + const req = await fetch(`${url}/api/waitlist?i=${cuid}`, { + method: 'DELETE' + }); + + if (req.status === 200) { + setUnsubscribedFromWaitlist(true); + window.history.replaceState( + {}, + '', + prod ? 'https://spacedrive.com' : 'http://localhost:8003' + ); + + setTimeout(() => { + setUnsubscribedFromWaitlist(false); + }, 5000); + } else if (req.status >= 400 && req.status < 500) { + alert('An error occurred while unsubscribing from waitlist'); + } + })(); + }, []); + return ( <>