diff --git a/frontend/package.json b/frontend/package.json index 44c8813..f262933 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "test": "vitest" }, "dependencies": { + "@clerk/clerk-react": "^4.29.0", "@codemirror/lang-html": "^6.4.6", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.0.5", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 550eb20..74ff7c1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -3,7 +3,7 @@ import ImageUpload from "./components/ImageUpload"; import CodePreview from "./components/CodePreview"; import Preview from "./components/Preview"; import { generateCode } from "./generateCode"; -import Spinner from "./components/Spinner"; +import Spinner from "./components/custom-ui/Spinner"; import classNames from "classnames"; import { FaCode, @@ -44,7 +44,11 @@ import ImportCodeSection from "./components/ImportCodeSection"; const IS_OPENAI_DOWN = false; -function App() { +interface Props { + navbarComponent?: JSX.Element; +} + +function App({ navbarComponent }: Props) { const [appState, setAppState] = useState(AppState.INITIAL); const [generatedCode, setGeneratedCode] = useState(""); @@ -475,6 +479,8 @@ function App() {
+ {!!navbarComponent && navbarComponent} + {appState === AppState.INITIAL && (
diff --git a/frontend/src/components/custom-ui/FullPageSpinner.tsx b/frontend/src/components/custom-ui/FullPageSpinner.tsx new file mode 100644 index 0000000..dd39ead --- /dev/null +++ b/frontend/src/components/custom-ui/FullPageSpinner.tsx @@ -0,0 +1,11 @@ +import Spinner from "./Spinner"; + +function FullPageSpinner() { + return ( +
+ +
+ ); +} + +export default FullPageSpinner; diff --git a/frontend/src/components/Spinner.tsx b/frontend/src/components/custom-ui/Spinner.tsx similarity index 100% rename from frontend/src/components/Spinner.tsx rename to frontend/src/components/custom-ui/Spinner.tsx diff --git a/frontend/src/components/hosted/AppContainer.tsx b/frontend/src/components/hosted/AppContainer.tsx new file mode 100644 index 0000000..f081d29 --- /dev/null +++ b/frontend/src/components/hosted/AppContainer.tsx @@ -0,0 +1,51 @@ +import { SignUp, UserButton, useUser } from "@clerk/clerk-react"; +import App from "../../App"; +import { useEffect, useState } from "react"; +import { AlertDialog } from "@radix-ui/react-alert-dialog"; +import { AlertDialogContent } from "../ui/alert-dialog"; +import FullPageSpinner from "../custom-ui/FullPageSpinner"; + +function AppContainer() { + const [showPopup, setShowPopup] = useState(false); + const { isSignedIn, isLoaded } = useUser(); + + // If Clerk is loaded and the user is not signed in, show the sign up popup + useEffect(() => { + if (isLoaded && !isSignedIn) { + setShowPopup(true); + } + }, [isSignedIn, isLoaded]); + + // If Clerk is still loading, show a spinner + if (!isLoaded) return ; + + return ( + <> + + +
+ } + /> + + + + + + + ); +} + +export default AppContainer; diff --git a/frontend/src/config.ts b/frontend/src/config.ts index 4f0de2f..e4ddaf2 100644 --- a/frontend/src/config.ts +++ b/frontend/src/config.ts @@ -8,5 +8,10 @@ export const WS_BACKEND_URL = export const HTTP_BACKEND_URL = import.meta.env.VITE_HTTP_BACKEND_URL || "http://127.0.0.1:7001"; +// Hosted version only + export const PICO_BACKEND_FORM_SECRET = import.meta.env.VITE_PICO_BACKEND_FORM_SECRET || null; + +export const CLERK_PUBLISHABLE_KEY = + import.meta.env.VITE_CLERK_PUBLISHABLE_KEY || null; diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 2e771a7..740829f 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,12 +1,18 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import App from "./App.tsx"; -import "./index.css"; import { Toaster } from "react-hot-toast"; +import AppContainer from "./components/hosted/AppContainer.tsx"; +import { ClerkProvider } from "@clerk/clerk-react"; +import { CLERK_PUBLISHABLE_KEY } from "./config.ts"; +import "./index.css"; ReactDOM.createRoot(document.getElementById("root")!).render( - - + + + + ); diff --git a/frontend/yarn.lock b/frontend/yarn.lock index da1a8e8..f35b9bb 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -225,6 +225,31 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@clerk/clerk-react@^4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@clerk/clerk-react/-/clerk-react-4.29.0.tgz#42d677265689fcdf20fbbb56fc112578c8a16ded" + integrity sha512-mNFjUiKd40bc1+PVbUS/PWbzU/w2pSo/5mvQYU9rpyE/0jRFdhx/q58ouuI9LYmBS1IGjP8sY/tKXe69snZDWA== + dependencies: + "@clerk/shared" "1.1.1" + "@clerk/types" "3.59.0" + tslib "2.4.1" + +"@clerk/shared@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@clerk/shared/-/shared-1.1.1.tgz#7844edcaad285a98528e754b82909015065002d0" + integrity sha512-pEzhalD1Yo/gGsOE2BQugVQTjlIl2aYmoeRld3BDXHRDV1jnk+yUE2CFOw6bojgFWN9sbeN/ph/47UWvvoCSOg== + dependencies: + glob-to-regexp "0.4.1" + js-cookie "3.0.1" + swr "2.2.0" + +"@clerk/types@3.59.0": + version "3.59.0" + resolved "https://registry.yarnpkg.com/@clerk/types/-/types-3.59.0.tgz#13d8a12b660ac0922f2ecbdbb1546d407c0e9391" + integrity sha512-OchGdY3mf+hXql7CPQsuCv1HicPvvz6NdMeo6r0M5FY11INcXGaF4pexido9IThrd31rIum+giWVLaFTwlhzfg== + dependencies: + csstype "3.1.1" + "@codemirror/autocomplete@^6.0.0": version "6.11.0" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.11.0.tgz#406dee8bf5342dfb48920ad75454d3406ddf9963" @@ -1882,6 +1907,11 @@ cssesc@^3.0.0: resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +csstype@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + csstype@^3.0.2: version "3.1.2" resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz" @@ -2351,6 +2381,11 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob-to-regexp@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + glob@7.1.6: version "7.1.6" resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" @@ -2561,6 +2596,11 @@ jiti@^1.19.1: resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz" integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== +js-cookie@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414" + integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -3378,6 +3418,13 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swr@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.0.tgz#575c6ac1bec087847f4c86a39ccbc0043c834d6a" + integrity sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ== + dependencies: + use-sync-external-store "^1.2.0" + tailwind-merge@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.0.0.tgz#a0f3a8c874ebae5feec5595614d08245a5f88a39" @@ -3506,6 +3553,11 @@ ts-interface-checker@^0.1.9: resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== +tslib@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== + tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: version "2.6.2" resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" @@ -3583,6 +3635,11 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" +use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"