diff --git a/.env b/.env index 1c9e060..0f202ec 100644 --- a/.env +++ b/.env @@ -1,2 +1,5 @@ -VITE_API_URL=https://api.thehideoutltd.com -VITE_TURNSTILE_KEY=0x4AAAAAAB2uebWFPXaK8spB +VITE_API_URL=https://api2026.tombutcher.work +VITE_TURNSTILE_KEY=0x4AAAAAAA_bc3QTrE68whtg +VITE_KEYCLOAK_URL=https://auth.tombutcher.work +VITE_KEYCLOAK_REALM=master +VITE_KEYCLOAK_CLIENT_ID=2026-web-client \ No newline at end of file diff --git a/.env.development b/.env.development index 419f505..387954d 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,5 @@ -VITE_API_URL=https://thehideout.tombutcher.work/api -VITE_TURNSTILE_KEY=0x4AAAAAAB2dBq6i8m4kYzDm +VITE_API_URL=https://dev.tombutcher.work/api +VITE_TURNSTILE_KEY=0x4AAAAAAA_bc3QTrE68whtg +VITE_KEYCLOAK_URL=https://auth.tombutcher.work +VITE_KEYCLOAK_REALM=master +VITE_KEYCLOAK_CLIENT_ID=dev-web-client \ No newline at end of file diff --git a/assets/errorcloudicon.svg b/assets/errorcloudicon.svg new file mode 100644 index 0000000..8abda40 --- /dev/null +++ b/assets/errorcloudicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/lefticon.svg b/assets/lefticon.svg index 697f1cb..4abbf19 100644 --- a/assets/lefticon.svg +++ b/assets/lefticon.svg @@ -1,6 +1,6 @@ - + diff --git a/assets/reloadicon.svg b/assets/reloadicon.svg new file mode 100644 index 0000000..3ced06e --- /dev/null +++ b/assets/reloadicon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/righticon.svg b/assets/righticon.svg index 4121ecc..f82b0e8 100644 --- a/assets/righticon.svg +++ b/assets/righticon.svg @@ -1,6 +1,6 @@ - + diff --git a/index.html b/index.html index 5a10e78..b10bcb0 100644 --- a/index.html +++ b/index.html @@ -21,7 +21,7 @@ name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> - + Tom Butcher diff --git a/src/App.jsx b/src/App.jsx index a970633..76ae06b 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,11 +1,7 @@ -import PropTypes from "prop-types"; import { useState, useEffect, useRef, useMemo, useCallback } from "react"; -import { Alert } from "antd"; import { useMediaQuery } from "react-responsive"; import { useNavigate, useLocation } from "react-router-dom"; import { Element, scroller } from "react-scroll"; -import axios from "axios"; -import { useQuery } from "@tanstack/react-query"; import Page from "./components/Page"; import { ImageProvider, useImageContext } from "./contexts/ImageContext"; import LoadingModal from "./components/LoadingModal"; @@ -16,23 +12,22 @@ import ProjectPage from "./components/Projects/ProjectPage"; import ExperiencePage from "./components/Experience/ExperiencePage"; import { MenuProvider, useMenu } from "./contexts/MenuContext"; import { ThemeProvider } from "./contexts/ThemeContext"; -import { - SettingsProvider, - useSettingsContext, -} from "./contexts/SettingsContext"; -import { BlogsProvider } from "./contexts/BlogsContext"; -import { ProjectsProvider } from "./contexts/ProjectsContext"; -import { CompaniesProvider } from "./contexts/CompaniesContext"; import { KeycloakProvider } from "./contexts/KeycloakContext"; import { VideoProvider } from "./contexts/VideoContext"; import { FileProvider } from "./contexts/FileContext"; +import { MessageProvider } from "./contexts/MessageContext"; +import { DeveloperProvider, useDeveloper } from "./contexts/DeveloperContext"; +import { DeveloperMenuProvider } from "./contexts/DeveloperMenuContext"; +import { ContentProvider, useContent } from "./contexts/ContentContext"; import Header from "./components/Header"; import Footer from "./components/Footer"; import { AccountProvider, useAccount } from "./contexts/AccountContext"; -const apiUrl = import.meta.env.VITE_API_URL; +import AppError from "./components/AppError"; // Component that handles image loading after API data is fetched -const AppContent = ({ pages, blogs, images, projects, companies, loading }) => { +const AppContent = () => { + const { pages, blogs, images, projects, companies, settings, isLoading } = + useContent(); const { loadImages } = useImageContext(); const [loadedOnce, setLoadedOnce] = useState(false); const [currentPage, setCurrentPage] = useState({ pageType: "landingPage" }); @@ -48,6 +43,7 @@ const AppContent = ({ pages, blogs, images, projects, companies, loading }) => { const [currentBlog, setCurrentBlog] = useState(null); const [currentProject, setCurrentProject] = useState(null); const [currentCompany, setCurrentCompany] = useState(null); + const { developerMode } = useDeveloper(); const [currentPageIdx, setCurrentPageIdx] = useState(0); const [nextPageIdx, setNextPageIdx] = useState(0); const [blogVisible, setBlogVisible] = useState(false); @@ -72,7 +68,6 @@ const AppContent = ({ pages, blogs, images, projects, companies, loading }) => { const navigate = useNavigate(); const location = useLocation(); - const settings = useSettingsContext(); const isMobile = useMediaQuery({ maxWidth: 800 }); const [skipAnimation, setSkipAnimation] = useState(true); @@ -87,13 +82,13 @@ const AppContent = ({ pages, blogs, images, projects, companies, loading }) => { }, [settings?.themes]); useEffect(() => { - if (loading == false) { + if (isLoading == false) { setTimeout(() => { setSkipAnimation(false); - console.log("skipAnimation", loading); + console.log("skipAnimation", isLoading); }, 500); // Reduced from 2000ms to 500ms } - }, [loading]); + }, [isLoading]); // Check for iOS webclip and set body className useEffect(() => { @@ -620,164 +615,195 @@ const AppContent = ({ pages, blogs, images, projects, companies, loading }) => { return ( -
-
0 && - skipAnimation == false - ? "tb-visible" - : "tb-hidden" - } + +
+
0 && + skipAnimation == false + ? "tb-visible" + : "tb-hidden" + } ${skipAnimation ? "tb-skip-animation" : ""} `} - id="app-container" - > - {landingPages.map((pageData, index) => ( - - + {landingPages.map((pageData, index) => ( + - - ))} -
+ data-name={pageData.slug} + > + + + ))} +
- - + + + + + + + + + + + + + + + +