diff --git a/tracknow/web/package-lock.json b/tracknow/web/package-lock.json index 3d792db..939a8ab 100644 --- a/tracknow/web/package-lock.json +++ b/tracknow/web/package-lock.json @@ -28,6 +28,7 @@ "react-dom": "^18.3.1", "react-icons": "^3.11.0", "react-infinite-scroll-component": "^6.1.0", + "react-lite-youtube-embed": "^2.4.0", "react-router-dom": "^6.23.1", "react-scripts": "5.0.1", "react-slick": "^0.30.2", @@ -18752,6 +18753,15 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-lite-youtube-embed": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/react-lite-youtube-embed/-/react-lite-youtube-embed-2.4.0.tgz", + "integrity": "sha512-Xo6cM1zPlROvvM97JkqQIoXstlQDaC4+DawmM7BB7Hh1cXrkBHEGq1iJlQxBTUWAUklmpcC7ph7qg7CztXtABQ==", + "peerDependencies": { + "react": ">=18.2.0", + "react-dom": ">=18.2.0" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", diff --git a/tracknow/web/package.json b/tracknow/web/package.json index ece843c..acafc0b 100644 --- a/tracknow/web/package.json +++ b/tracknow/web/package.json @@ -23,6 +23,7 @@ "react-dom": "^18.3.1", "react-icons": "^3.11.0", "react-infinite-scroll-component": "^6.1.0", + "react-lite-youtube-embed": "^2.4.0", "react-router-dom": "^6.23.1", "react-scripts": "5.0.1", "react-slick": "^0.30.2", diff --git a/tracknow/web/src/App.tsx b/tracknow/web/src/App.tsx index 134b481..39eec91 100644 --- a/tracknow/web/src/App.tsx +++ b/tracknow/web/src/App.tsx @@ -1,7 +1,9 @@ import React from "react"; -import { ChakraProvider } from "@chakra-ui/react"; +import { ChakraProvider, Flex, useDisclosure } from "@chakra-ui/react"; import { theme } from "./tracknowTheme"; import { BrowserRouter, Routes, Route, useParams } from "react-router-dom"; +import { NavbarLayout, NavbarLoggedInLayout, NavbarWelcomeLayout } from "./components/Navbar/Navbar"; +import MainLayout from "./components/MainLayout"; import { UserLogin } from "./components/User/UserLogin"; import { UserSignUp } from "./components/User/UserSignUp"; @@ -17,66 +19,98 @@ import ErrorPage from "./components/404/ErrorPage"; import { UserProvider } from "./hooks/useUsers"; -export const App = () => ( - - - - } /> - } /> - } /> - } /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - { + + const UserProfileWrapper = () => { + const { user_id } = useParams(); + // fetch user data based on user_id + const id = Number(user_id); + + return ; + }; + const { isOpen, onOpen, onClose } = useDisclosure(); + + return ( + + + + + } /> + + {/*welcome page*/} + + }> + } /> + + + {/*user is about to login/signup */} + + }> + } /> + } /> + + + {/*user is logged in */} + - + + }> + + + + }> - } - > - - - - - -); -const UserProfileWrapper = () => { - const { user_id } = useParams(); - // fetch user data based on user_id - const id = Number(user_id); + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + + + ) +}; - return ; -}; \ No newline at end of file diff --git a/tracknow/web/src/components/Home/Home.tsx b/tracknow/web/src/components/Home/Home.tsx index 6fa2749..c28572c 100644 --- a/tracknow/web/src/components/Home/Home.tsx +++ b/tracknow/web/src/components/Home/Home.tsx @@ -1,79 +1,27 @@ -import { NavbarLoggedIn } from "../Navbar/Navbar"; import { HomePost } from "../Post/Post"; import { useLaptimes } from "../../hooks/useLaptimes"; import { useUsers } from "../../hooks/useUsers"; import { LoadingSpinner } from "../Loading/LoadingSpinner"; -import { - Box, - Flex, - useBreakpointValue, - useDisclosure, -} from "@chakra-ui/react"; -import MobileDrawer from "../../misc/MobileDrawer"; -import LeftSideBar from "../SideBar/LeftSideBar"; -import RightSideBar from "../SideBar/RightSideBar"; + export const Home = () => { const { laptime, fetchMoreData, hasMore, laptime_loading } = useLaptimes(); - const { username, profilePic, loading } = useUsers(); - - const { isOpen, onOpen, onClose } = useDisclosure(); - const isMobile = useBreakpointValue({ base: true, md: false }); + const { loading } = useUsers(); return ( <> - - - {/* Adjust height to fit the viewport */} - {/* Left section */} - {isMobile ? ( - - - - ) : ( - - - - )} - - {/* Middle section */} - - {loading && laptime_loading ? ( - - ) : ( - - )} - + {/* Middle section */} + {loading && laptime_loading ? ( + + ) : ( + + )} - {/* Right section */} - - {/* right sidebar content*/} - - ); }; diff --git a/tracknow/web/src/components/MainLayout.tsx b/tracknow/web/src/components/MainLayout.tsx new file mode 100644 index 0000000..8f0d6eb --- /dev/null +++ b/tracknow/web/src/components/MainLayout.tsx @@ -0,0 +1,57 @@ +import * as React from "react"; +import { Flex, Box, useBreakpointValue } from '@chakra-ui/react'; +import LeftSideBar from './SideBar/LeftSideBar'; +import RightSideBar from './SideBar/RightSideBar'; +import MobileDrawer from "../misc/MobileDrawer"; +import { Outlet } from 'react-router-dom'; + +type MainLayoutProps = { + isOpen: boolean; + onOpen: () => void; + onClose: () => void; +}; + +const MainLayout: React.FC = ({ isOpen, onOpen, onClose }) => { + + + const isMobile = useBreakpointValue({ base: true, md: false }); + + return ( + + {/* Left section */} + + {isMobile ? ( + + + + ) : ( + + + + )} + + {/* Middle section */} + + + + + {/* Right section */} + + {/* right sidebar content*/} + + + + ); +}; + +export default MainLayout; diff --git a/tracknow/web/src/components/Navbar/Navbar.tsx b/tracknow/web/src/components/Navbar/Navbar.tsx index 398744b..7b26657 100644 --- a/tracknow/web/src/components/Navbar/Navbar.tsx +++ b/tracknow/web/src/components/Navbar/Navbar.tsx @@ -13,17 +13,18 @@ import { MenuDivider, MenuItem, MenuList, - IconButton + IconButton, } from "@chakra-ui/react"; import { AddIcon } from '@chakra-ui/icons'; import { FiMenu } from "react-icons/fi"; import { Link as ReactRouterLink } from 'react-router-dom'; import { identityProfile } from "../../Types"; import useMiscFunctions from "../../misc/miscFunctions"; +import { Outlet } from 'react-router-dom'; +import { useUsers } from "../../hooks/useUsers"; - -export const NavbarWelcome = () => ( +const NavbarWelcome = () => ( @@ -46,7 +47,7 @@ export const NavbarWelcome = () => ( ); -export const Navbar = () => ( +const Navbar = () => ( @@ -68,7 +69,7 @@ export const Navbar = () => ( ); -export const NavbarLoggedIn = ({ name, pp, onOpen }: identityProfile) => { +const NavbarLoggedIn = ({ name, pp, onOpen }: identityProfile) => { const { handleLogout } = useMiscFunctions(); return ( { ); +}; + + +// Layout to prevent duplicating navbar across components +export const NavbarLayout = () => { + return ( + <> + + + + ) +}; +export const NavbarWelcomeLayout = () => { + return ( + <> + + + + ) +}; + +type NavbarLoggedInLayout = { + onOpen: () => void; +}; + +export const NavbarLoggedInLayout: React.FC = ({ onOpen }) => { + const { username, profilePic } = useUsers(); + + return ( + <> + + + + ) }; \ No newline at end of file diff --git a/tracknow/web/src/components/Post/Post.tsx b/tracknow/web/src/components/Post/Post.tsx index 6ce9a03..55ef526 100644 --- a/tracknow/web/src/components/Post/Post.tsx +++ b/tracknow/web/src/components/Post/Post.tsx @@ -1,13 +1,10 @@ import * as React from "react"; -import { Box, Flex, Text, Stack, Icon, HStack, Center, Link } from "@chakra-ui/react"; +import { Box, Flex, Text, Stack, Icon, HStack, Link } from "@chakra-ui/react"; import { GetUserLaptimesResponse } from "../../Types"; import { RiComputerLine, RiMapPinLine, RiTimerFlashLine } from "react-icons/ri"; import { FaCar } from "react-icons/fa"; import miscFunctions from "../../misc/miscFunctions"; -import InfiniteScroll from "react-infinite-scroll-component"; -import { BeatLoader } from "react-spinners"; import { Link as ReactRouterLink } from 'react-router-dom'; -import { useLaptimes } from "../../hooks/useLaptimes"; import { LoadingSpinner } from "../Loading/LoadingSpinner"; type PostProps = { @@ -20,7 +17,24 @@ type PostProps = { // homepage posts( recent) posts of users export const HomePost: React.FC = ({ laptimes, fetchMoreData, hasMore }) => { - const { laptime_loading } = useLaptimes(); + // intersection observation api instead of the bad infinite scroll component + // when the user reach the end of the page, its going to fetch more data + const observer = React.useRef(null); + const lastLaptimeRef = React.useCallback((node: HTMLDivElement | null) => { + if (observer.current) observer.current.disconnect(); + if (hasMore) { + observer.current = new IntersectionObserver(entries => { + if (entries[0].isIntersecting) fetchMoreData(); + }); + if (node) observer.current.observe(node); + } + }, [hasMore, fetchMoreData]); + + React.useEffect(() => { + return () => { + if (observer.current) observer.current.disconnect(); + }; + }, []); //const [liked, setLiked] = React.useState(false); const [showFullText, setShowFullText] = React.useState(false); @@ -35,14 +49,9 @@ export const HomePost: React.FC = ({ laptimes, fetchMoreData, hasMore }; return ( - } - > - {laptimes.map((laptime) => ( - + <> + {laptimes.map((laptime, index) => ( + {laptime.title} @@ -183,8 +192,8 @@ export const HomePost: React.FC = ({ laptimes, fetchMoreData, hasMore */} ))} - + ); }; diff --git a/tracknow/web/src/components/SideBar/LeftSideBar.tsx b/tracknow/web/src/components/SideBar/LeftSideBar.tsx index fedcf05..4f8b262 100644 --- a/tracknow/web/src/components/SideBar/LeftSideBar.tsx +++ b/tracknow/web/src/components/SideBar/LeftSideBar.tsx @@ -1,4 +1,4 @@ -import { Box, Center, Divider, Flex, FlexProps, Icon, Link, Stack, Text } from '@chakra-ui/react'; +import { Box, Center, Flex, FlexProps, Icon, Link, Stack } from '@chakra-ui/react'; import { FiHome, FiAward, FiGlobe, FiInfo, FiSettings, FiDollarSign, FiCalendar } from 'react-icons/fi'; import { IconType } from 'react-icons'; import { Link as ReactRouterLink } from 'react-router-dom'; diff --git a/tracknow/web/src/components/SideBar/RightSideBar.tsx b/tracknow/web/src/components/SideBar/RightSideBar.tsx index e860489..ecbf77e 100644 --- a/tracknow/web/src/components/SideBar/RightSideBar.tsx +++ b/tracknow/web/src/components/SideBar/RightSideBar.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import { - Box, Heading, List, ListItem, - Text, Divider, Image, Stack, Flex, Center, + Box, Heading, Text, Divider, Image, Flex, Center, Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, diff --git a/tracknow/web/src/components/User/UserAccountSettings.tsx b/tracknow/web/src/components/User/UserAccountSettings.tsx index be65df5..aad6042 100644 --- a/tracknow/web/src/components/User/UserAccountSettings.tsx +++ b/tracknow/web/src/components/User/UserAccountSettings.tsx @@ -1,8 +1,6 @@ import * as React from "react"; - -import { Box, Button, Card, CardBody, CardHeader, useToast, Flex, FormControl, Heading, Stack, Avatar, FormErrorMessage, InputRightElement, InputGroup, Center, Input, useDisclosure, useBreakpointValue } from "@chakra-ui/react"; +import { Box, Button, Card, CardBody, CardHeader, useToast, Flex, FormControl, Heading, Stack, Avatar, FormErrorMessage, InputRightElement, InputGroup, Center, Input, } from "@chakra-ui/react"; import { CountryDropdown } from "../../misc/dropDown"; -import { NavbarLoggedIn } from "../Navbar/Navbar"; import { useNavigate, Link as ReactRouterLink } from "react-router-dom"; import { useUsers } from "../../hooks/useUsers"; import { EditUser, EditUserPic } from "../../Types"; @@ -11,9 +9,6 @@ import { BeatLoader } from "react-spinners"; import { ViewIcon, ViewOffIcon } from "@chakra-ui/icons"; import useMiscFunctions from "../../misc/miscFunctions"; -import MobileDrawer from "../../misc/MobileDrawer"; -import LeftSideBar from "../SideBar/LeftSideBar"; -import RightSideBar from "../SideBar/RightSideBar"; const UserAccountSettings = () => { @@ -39,9 +34,6 @@ const UserAccountSettings = () => { const { editProfilePic, editProfile } = useUsers(); const fileInputRef = React.useRef(null); - const { isOpen, onOpen, onClose } = useDisclosure(); - const isMobile = useBreakpointValue({ base: true, md: false }); - // sidebar @@ -168,168 +160,133 @@ const UserAccountSettings = () => { return ( <> + {/* Main Section */} + + + Settings + + + + + +
+ + + + + + handleProfilePic()} + /> + + - - - - {/* Left section */} - {isMobile ? ( - - - - ) : ( - - - - )} - - {/* Main Section */} - - - - - Settings - - - - - -
- - - - - - handleProfilePic()} +
+ + + + + + Username + + + { + setNewUsername(e.target.value); + setUsernameValid(e.target.value.length >= 5 && e.target.value.length <= 10); + }} + /> + + Username must be between 5 and 10 characters long. + + + + + + Password + + + + { + setPassword(e.target.value); + setPasswordValid(e.target.value.length >= 8); + }} /> - - - -
- - - - - - Username - - - { - setNewUsername(e.target.value); - setUsernameValid(e.target.value.length >= 5 && e.target.value.length <= 10); - }} - /> - - Username must be between 5 and 10 characters long. - - - - - - Password - - - - { - setPassword(e.target.value); - setPasswordValid(e.target.value.length >= 8); - }} - /> - - - - - - Password must be at least 8 characters long. - - - - - - - - Nationality - - setNationality(e.target.value)} /> - - - + + + + + + Password must be at least 8 characters long. + + + +
+ + + + Nationality + + setNationality(e.target.value)} /> - - - - - - - - - - - - + + + + + + + + + + ) diff --git a/tracknow/web/src/components/User/UserAddLaptimes.tsx b/tracknow/web/src/components/User/UserAddLaptimes.tsx index f48534c..5a61537 100644 --- a/tracknow/web/src/components/User/UserAddLaptimes.tsx +++ b/tracknow/web/src/components/User/UserAddLaptimes.tsx @@ -5,25 +5,17 @@ import { Textarea, FormHelperText, Input, Select, HStack, useToast, FormErrorMessage, - useDisclosure, - useBreakpointValue } from "@chakra-ui/react"; import { SimracingTitles } from "../../misc/dropDown"; import { useLaptimes } from "../../hooks/useLaptimes"; import { Laptime } from "../../Types"; import { BeatLoader } from "react-spinners"; -import { NavbarLoggedIn } from "../Navbar/Navbar"; //import { LoadingSpinner } from "../Loading/LoadingSpinner"; import { useUsers } from "../../hooks/useUsers"; -import MobileDrawer from "../../misc/MobileDrawer"; -import LeftSideBar from "../SideBar/LeftSideBar"; -import RightSideBar from "../SideBar/RightSideBar"; - const UserAddLaptimes = () => { const { addLaptime } = useLaptimes(); - const { username, profilePic } = useUsers(); const [title, setTitle] = React.useState(""); const [car, setCar] = React.useState(""); @@ -37,9 +29,6 @@ const UserAddLaptimes = () => { const [isLoading, setIsLoading] = React.useState(false); // for moments - const { isOpen, onOpen, onClose } = useDisclosure(); - const isMobile = useBreakpointValue({ base: true, md: false }); - const toast = useToast(); /*if (loading) { @@ -91,174 +80,144 @@ const UserAddLaptimes = () => { return ( <> - - - {/* Left section*/} - {isMobile ? ( - - - - ) : ( - + + Add Racing Moment + + + + Sim racing + + + {/* if simracing is selected show simracing titles*/} + {simracing && ( + setPlatform(e.target.value)} /> + )} + + + + + + + + setTitle(e.target.value)} + /> + {!title && ( + Required + )} + + + + + +