├── README.md ├── src ├── vite-env.d.ts ├── assets │ ├── Logo.png │ ├── Arrow.png │ ├── Circles.png │ ├── image1.png │ ├── image2.png │ ├── image3.png │ ├── image4.png │ ├── image5.png │ ├── image6.png │ ├── Sparkles.png │ ├── EvolveText.png │ ├── HomePageText.png │ ├── AbstractWaves.png │ ├── SponsorForbes.png │ ├── SponsorFortune.png │ ├── SponsorRedBull.png │ ├── HomePageGraphic.png │ ├── BenefitsPageGraphic.png │ └── ContactUsPageGraphic.png ├── main.tsx ├── shared │ ├── HText.tsx │ ├── types.ts │ └── ActionButton.tsx ├── index.css ├── hooks │ └── useMediaQuery.ts ├── scenes │ ├── ourClasses │ │ ├── Class.tsx │ │ └── index.tsx │ ├── navbar │ │ ├── Link.tsx │ │ └── index.tsx │ ├── footer │ │ └── index.tsx │ ├── benefits │ │ ├── Benefit.tsx │ │ └── index.tsx │ ├── home │ │ └── index.tsx │ └── contactUs │ │ └── index.tsx └── App.tsx ├── postcss.config.js ├── prettier.config.cjs ├── tsconfig.node.json ├── vite.config.ts ├── .gitignore ├── index.html ├── .eslintrc.cjs ├── .github └── workflows │ └── deploy.yml ├── tsconfig.json ├── tailwind.config.js ├── package.json └── public └── LOGO.svg /README.md: -------------------------------------------------------------------------------- 1 | # gyn 2 | # gyn 3 | # gyn 4 | # gyn 5 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/assets/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/Logo.png -------------------------------------------------------------------------------- /src/assets/Arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/Arrow.png -------------------------------------------------------------------------------- /src/assets/Circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/Circles.png -------------------------------------------------------------------------------- /src/assets/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/image1.png -------------------------------------------------------------------------------- /src/assets/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/image2.png -------------------------------------------------------------------------------- /src/assets/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/image3.png -------------------------------------------------------------------------------- /src/assets/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/image4.png -------------------------------------------------------------------------------- /src/assets/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/image5.png -------------------------------------------------------------------------------- /src/assets/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/image6.png -------------------------------------------------------------------------------- /src/assets/Sparkles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/Sparkles.png -------------------------------------------------------------------------------- /src/assets/EvolveText.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/EvolveText.png -------------------------------------------------------------------------------- /src/assets/HomePageText.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/HomePageText.png -------------------------------------------------------------------------------- /src/assets/AbstractWaves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/AbstractWaves.png -------------------------------------------------------------------------------- /src/assets/SponsorForbes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/SponsorForbes.png -------------------------------------------------------------------------------- /src/assets/SponsorFortune.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/SponsorFortune.png -------------------------------------------------------------------------------- /src/assets/SponsorRedBull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/SponsorRedBull.png -------------------------------------------------------------------------------- /src/assets/HomePageGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/HomePageGraphic.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/BenefitsPageGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/BenefitsPageGraphic.png -------------------------------------------------------------------------------- /src/assets/ContactUsPageGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanTymoshchuk/gym/HEAD/src/assets/ContactUsPageGraphic.png -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | // prettier.config.js 2 | module.export = { 3 | plugins: [require("prettier-plugin-tailwindcss")], 4 | }; 5 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.tsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /src/shared/HText.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | type Props = { 4 | children: React.ReactNode; 5 | }; 6 | 7 | const HText = ({ children }: Props) => { 8 | return ( 9 |

{children}

10 | ); 11 | }; 12 | 13 | export default HText; 14 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import path from 'path' 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react()], 8 | resolve: { 9 | alias: [{ find: '@', replacement: path.resolve(__dirname, 'src') }] 10 | } 11 | }) 12 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,700&family=Montserrat:wght@700&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | html, body, #root, .app{ 7 | height: 100%; 8 | width: 100%; 9 | font-family: "DM Sans", sans-serif; 10 | @apply text-gray-500; 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gym 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/shared/types.ts: -------------------------------------------------------------------------------- 1 | export enum SelectedPage { 2 | Home = "home", 3 | Benefits = "benefits", 4 | OurClasses = "ourclasses", 5 | ContactUs = "contactus", 6 | } 7 | 8 | export interface BenefitType { 9 | icon: JSX.Element; 10 | title: string; 11 | description: string; 12 | } 13 | 14 | export interface ClassType { 15 | name: string; 16 | description?: string; // знак запитання означає що не обов'язковий 17 | image: string; 18 | } -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 🛎️ 12 | uses: actions/checkout@v2.3.1 13 | 14 | - name: Install and build 🔧 15 | run: | 16 | npm install 17 | npm run build 18 | 19 | - name: Deploy 🚀 20 | uses: JamesIves/github-pages-deploy-action@4.1.0 21 | with: 22 | branch: gh-pages 23 | folder: dist 24 | -------------------------------------------------------------------------------- /src/hooks/useMediaQuery.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | const useMediaQuery = (query: string) => { 4 | const [matches, setMatches] = useState(false); 5 | 6 | useEffect(() => { 7 | const media = window.matchMedia(query); 8 | if (media.matches !== matches) { 9 | setMatches(media.matches); 10 | } 11 | const listener = () => setMatches(media.matches); 12 | window.addEventListener("resize", listener); 13 | return () => window.removeEventListener("resize", listener); 14 | }, [matches, query]); 15 | 16 | return matches; 17 | }; 18 | 19 | export default useMediaQuery; 20 | -------------------------------------------------------------------------------- /src/shared/ActionButton.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import AnchorLink from "react-anchor-link-smooth-scroll"; 3 | import { SelectedPage } from "@/shared/types"; 4 | 5 | type Props = { 6 | children: React.ReactNode; 7 | setSelectedPage: (value: SelectedPage) => void; 8 | }; 9 | 10 | const ActionButton = ({ children, setSelectedPage }: Props) => { 11 | return ( 12 | setSelectedPage(SelectedPage.ContactUs)} 15 | href={`#${SelectedPage.ContactUs}`} 16 | > 17 | {children} 18 | 19 | ); 20 | }; 21 | 22 | export default ActionButton; 23 | -------------------------------------------------------------------------------- /src/scenes/ourClasses/Class.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | name: string; 3 | description?: string; 4 | image: string; 5 | }; 6 | 7 | const Class = ({ name, description, image }: Props) => { 8 | const overlayStyles = `p-5 absolute flex h-[380px] w-[450px] flex-col items-center justify-center whitespace-normal bg-primary-500 text-center text-white opacity-0 transition duration-500 hover:opacity-90`; 9 | 10 | return ( 11 |
  • 12 |
    13 |

    {name}

    14 |

    {description}

    15 |
    16 | {`${image}`} 17 |
  • 18 | ); 19 | }; 20 | 21 | export default Class; 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./src/*"] 5 | }, 6 | "target": "ES2020", 7 | "useDefineForClassFields": true, 8 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 9 | "module": "ESNext", 10 | "skipLibCheck": true, 11 | 12 | /* Bundler mode */ 13 | "moduleResolution": "bundler", 14 | "allowImportingTsExtensions": true, 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "noEmit": true, 18 | "jsx": "react-jsx", 19 | 20 | /* Linting */ 21 | "strict": true, 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | "noFallthroughCasesInSwitch": true 25 | }, 26 | "include": ["src"], 27 | "references": [{ "path": "./tsconfig.node.json" }] 28 | } 29 | -------------------------------------------------------------------------------- /src/scenes/navbar/Link.tsx: -------------------------------------------------------------------------------- 1 | import { SelectedPage } from "@/shared/types"; 2 | import AnchorLink from "react-anchor-link-smooth-scroll"; 3 | 4 | type Props = { 5 | page: string; 6 | selectedPage: SelectedPage; 7 | setSelectedPage: (value: SelectedPage) => void; 8 | }; 9 | 10 | const Link = ({ page, selectedPage, setSelectedPage }: Props) => { 11 | const lowerCasePage = page.toLowerCase().replace(/ /g, "") as SelectedPage; 12 | 13 | return ( 14 | setSelectedPage(lowerCasePage)} 20 | > 21 | {page} 22 | 23 | ); 24 | }; 25 | 26 | export default Link; 27 | -------------------------------------------------------------------------------- /src/scenes/footer/index.tsx: -------------------------------------------------------------------------------- 1 | import Logo from "@/assets/Logo.png"; 2 | 3 | const Footer = () => { 4 | return ( 5 | 29 | ); 30 | }; 31 | 32 | export default Footer; 33 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: { 6 | colors: { 7 | "gray-20": "#F8F4EB", 8 | "gray-50": "#EFE6E6", 9 | "gray-100": "#DFCCCC", 10 | "gray-500": "#5E0000", 11 | "primary-100": "#FFE1E0", 12 | "primary-300": "#FFA6A3", 13 | "primary-500": "#FF6B66", 14 | "secondary-400": "#FFCD5B", 15 | "secondary-500": "#FFC132", 16 | }, 17 | backgroundImage: (theme) => ({ 18 | "gradient-yellowred": 19 | "linear-gradient(90deg, #FF616A 0%, #FFC837 100%)", 20 | "mobile-home": "url('./assets/HomePageGraphic.png')", 21 | }), 22 | fontFamily: { 23 | dmsans: ["DM Sans", "sans-serif"], 24 | montserrat: ["Montserrat", "sans-serif"], 25 | }, 26 | content: { 27 | evolvetext: "url('./assets/EvolveText.png')", 28 | abstractwaves: "url('./assets/AbstractWaves.png')", 29 | sparkles: "url('./assets/Sparkles.png')", 30 | circles: "url('./assets/Circles.png')", 31 | }, 32 | }, 33 | screens: { 34 | xs: "480px", 35 | sm: "768px", 36 | md: "1060px", 37 | }, 38 | }, 39 | plugins: [], 40 | }; 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gym-typescript", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build --base=/gym/", 9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@heroicons/react": "^2.0.18", 14 | "framer-motion": "^10.16.5", 15 | "react": "^18.2.0", 16 | "react-anchor-link-smooth-scroll": "^1.0.12", 17 | "react-dom": "^18.2.0", 18 | "react-hook-form": "^7.48.2" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "^20.9.0", 22 | "@types/react": "^18.2.37", 23 | "@types/react-anchor-link-smooth-scroll": "^1.0.2", 24 | "@types/react-dom": "^18.2.15", 25 | "@typescript-eslint/eslint-plugin": "^6.10.0", 26 | "@typescript-eslint/parser": "^6.10.0", 27 | "@vitejs/plugin-react": "^4.2.0", 28 | "autoprefixer": "^10.4.16", 29 | "eslint": "^8.53.0", 30 | "eslint-plugin-react-hooks": "^4.6.0", 31 | "eslint-plugin-react-refresh": "^0.4.4", 32 | "postcss": "^8.4.31", 33 | "prettier": "^3.1.0", 34 | "prettier-plugin-tailwindcss": "^0.5.7", 35 | "tailwindcss": "^3.3.5", 36 | "typescript": "^5.2.2", 37 | "vite": "^5.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/scenes/benefits/Benefit.tsx: -------------------------------------------------------------------------------- 1 | import { SelectedPage } from "@/shared/types"; 2 | import { motion } from "framer-motion"; 3 | import AnchorLink from "react-anchor-link-smooth-scroll"; 4 | 5 | type Props = { 6 | icon: JSX.Element; 7 | title: string; 8 | description: string; 9 | setSelectedPage: (value: SelectedPage) => void; 10 | }; 11 | 12 | const childVariant = { 13 | hidden: { opacity: 0, scale: 0.9 }, 14 | visible: { opacity: 1, scale: 1 }, 15 | }; 16 | 17 | const Benefit = ({ icon, title, description, setSelectedPage }: Props) => { 18 | return ( 19 | 23 |
    24 |
    25 | {icon} 26 |
    27 |
    28 |

    {title}

    29 |

    {description}

    30 | setSelectedPage(SelectedPage.Benefits)} 33 | href={`#${SelectedPage.Benefits}`} 34 | > 35 | Learn More 36 | 37 |
    38 | ); 39 | }; 40 | 41 | export default Benefit; 42 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { SelectedPage } from "@/shared/types"; 3 | import NavBar from "@/scenes/navbar"; 4 | import Home from "@/scenes/home"; 5 | import Benefits from "@/scenes/benefits"; 6 | import OurClasses from "@/scenes/ourClasses"; 7 | import ContactUs from "@/scenes/contactUs"; 8 | import Footer from "@/scenes/footer"; 9 | 10 | const App = () => { 11 | const [selectedPage, setSelectedPage] = useState( 12 | SelectedPage.Home, 13 | ); 14 | const [isTopOfPage, setIsTopOfPage] = useState(true); 15 | 16 | useEffect(() => { 17 | const handleScroll = () => { 18 | if (window.scrollY === 0) { 19 | setIsTopOfPage(true); // початкове значення де ми є 20 | setSelectedPage(SelectedPage.Home); // це для того, щоб коли ми скролили з відкритою модалкою воно переводило автоматично ховер 21 | } 22 | if (window.scrollY !== 0) setIsTopOfPage(false); 23 | }; 24 | window.addEventListener("scroll", handleScroll); 25 | 26 | return () => removeEventListener("scroll", handleScroll); 27 | }, []); 28 | 29 | return ( 30 |
    31 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | ); 43 | }; 44 | 45 | export default App; 46 | -------------------------------------------------------------------------------- /public/LOGO.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/scenes/ourClasses/index.tsx: -------------------------------------------------------------------------------- 1 | import { motion } from "framer-motion"; 2 | import { SelectedPage, ClassType } from "@/shared/types"; 3 | import HText from "@/shared/HText"; 4 | import Class from "./Class"; 5 | import image1 from "@/assets/image1.png"; 6 | import image2 from "@/assets/image2.png"; 7 | import image3 from "@/assets/image3.png"; 8 | import image4 from "@/assets/image4.png"; 9 | import image5 from "@/assets/image5.png"; 10 | import image6 from "@/assets/image6.png"; 11 | 12 | type Props = { 13 | setSelectedPage: (value: SelectedPage) => void; 14 | }; 15 | 16 | const classes: Array = [ 17 | { 18 | name: "Weight Training Classes", 19 | description: 20 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", 21 | image: image1, 22 | }, 23 | { 24 | name: "Yoga Classes", 25 | image: image2, 26 | }, 27 | { 28 | name: "Ab Core Classes", 29 | description: 30 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", 31 | image: image3, 32 | }, 33 | { 34 | name: "Adventure Classes", 35 | description: 36 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", 37 | image: image4, 38 | }, 39 | { 40 | name: "Fitness Classes", 41 | image: image5, 42 | }, 43 | { 44 | name: "Training Classes", 45 | description: 46 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", 47 | image: image6, 48 | }, 49 | ]; 50 | 51 | const OurClasses = ({ setSelectedPage }: Props) => { 52 | return ( 53 |
    54 | setSelectedPage(SelectedPage.OurClasses)} 56 | > 57 | 68 |
    69 | OUR CLASSES 70 |

    71 | Fringilla a sed at suspendisse ut enim volutpat. Rhoncus vel est 72 | tellus quam porttitor. Mauris velit euismod elementum arcu neque 73 | facilisi. Amet semper tortor facilisis metus nibh. Rhoncus sit 74 | enim mattis odio in risus nunc. 75 |

    76 |
    77 |
    78 |
    79 |
      80 | {classes.map((item, index) => ( 81 | 87 | ))} 88 |
    89 |
    90 |
    91 |
    92 | ); 93 | }; 94 | 95 | export default OurClasses; 96 | -------------------------------------------------------------------------------- /src/scenes/home/index.tsx: -------------------------------------------------------------------------------- 1 | import useMediaQuery from "@/hooks/useMediaQuery"; 2 | import ActionButton from "@/shared/ActionButton"; 3 | import { SelectedPage } from "@/shared/types"; 4 | import HomePageText from "@/assets/HomePageText.png"; 5 | import HomePageGraphic from "@/assets/HomePageGraphic.png"; 6 | import SponsorRedBul from "@/assets/SponsorRedBull.png"; 7 | import SponsorForbes from "@/assets/SponsorForbes.png"; 8 | import SponsorFortune from "@/assets/SponsorFortune.png"; 9 | import AnchorLink from "react-anchor-link-smooth-scroll"; 10 | import { motion } from "framer-motion"; //animation 11 | 12 | type Props = { 13 | setSelectedPage: (value: SelectedPage) => void; 14 | }; 15 | 16 | const Home = ({ setSelectedPage }: Props) => { 17 | const isAboutMediumScreens = useMediaQuery("(min-width:1060px)"); 18 | 19 | return ( 20 |
    21 | {/* IMAGE AND MAIN HEADER */} 22 | setSelectedPage(SelectedPage.Home)} 25 | > 26 | {/* Main header */} 27 |
    28 | {/* Headings */} 29 | 40 |
    41 |
    42 | home-page-text 43 |
    44 |
    45 |

    46 | Unrivaled Gym. Unparalleled Training Fitness Classes. World Class 47 | Studios to get the Body Shapes That you Dream of.. Get Your Dream 48 | Body Now. 49 |

    50 |
    51 | {/* Actions */} 52 | 63 | 64 | Join Now 65 | 66 | setSelectedPage(SelectedPage.ContactUs)} 69 | href={`#${SelectedPage.ContactUs}`} 70 | > 71 | Learn More 72 | 73 | 74 |
    75 | {/* Image */} 76 |
    77 | Home-Page-Graphic 78 |
    79 |
    80 | {/* Sponsors */} 81 | {isAboutMediumScreens && ( 82 |
    83 |
    84 |
    85 | SponsorRedBul 86 | SponsorForbes 87 | SponsorFortune 88 |
    89 |
    90 |
    91 | )} 92 |
    93 | ); 94 | }; 95 | 96 | export default Home; 97 | -------------------------------------------------------------------------------- /src/scenes/navbar/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/solid"; 3 | import { SelectedPage } from "@/shared/types"; 4 | import useMediaQuery from "@/hooks/useMediaQuery"; 5 | import ActionButton from "@/shared/ActionButton"; 6 | import Logo from "@/assets/Logo.png"; 7 | import Link from "./Link"; 8 | 9 | type Props = { 10 | isTopOfPage: boolean; 11 | selectedPage: SelectedPage; 12 | setSelectedPage: (value: SelectedPage) => void; 13 | }; 14 | 15 | 16 | const Navbar = ({ isTopOfPage, selectedPage, setSelectedPage }: Props) => { 17 | const flexBetween = "flex items-center justify-between"; 18 | const [isMenuToggled, setIsMenuToggled] = useState(false); 19 | const isAboveMediumScreens = useMediaQuery("(min-width: 1060px)"); 20 | const navbarBackground = isTopOfPage ? "" : "bg-primary-100 drop-shadow"; 21 | 22 | return ( 23 | 112 | ); 113 | }; 114 | 115 | export default Navbar; 116 | -------------------------------------------------------------------------------- /src/scenes/contactUs/index.tsx: -------------------------------------------------------------------------------- 1 | import { motion } from "framer-motion"; 2 | import { useForm } from "react-hook-form"; 3 | import { SelectedPage } from "@/shared/types"; 4 | import ContactUsPageGraphic from "@/assets/ContactUsPageGraphic.png"; 5 | import HText from "@/shared/HText"; 6 | 7 | type Props = { 8 | setSelectedPage: (value: SelectedPage) => void; 9 | }; 10 | 11 | const ContactUs = ({ setSelectedPage }: Props) => { 12 | const inputStyles = `mb-5 w-full rounded-lg bg-primary-300 px-5 py-3 placeholder-white`; 13 | const { 14 | register, 15 | trigger, 16 | formState: { errors }, 17 | } = useForm(); 18 | 19 | const onSubmit = async (e: any) => { 20 | const isValid = await trigger(); 21 | if (!isValid) { 22 | e.preventDefault(); 23 | } 24 | }; 25 | 26 | return ( 27 |
    28 | setSelectedPage(SelectedPage.ContactUs)} 30 | > 31 | {/* header */} 32 | 43 | 44 | JOIN NOW 45 | TO GET IN SHAPE 46 | 47 |

    48 | Congue adipiscing risus commodo placerat. Tellus et in feugiat nisl 49 | sapien vel rhoncus. Placerat at in enim pellentesque. Nulla 50 | adipiscing leo egestas nisi elit risus sit. Nunc cursus sagittis. 51 |

    52 |
    53 | {/* Form and image */} 54 |
    55 | 66 |
    72 | 78 | {errors.name && ( 79 |

    80 | {errors.name.type === "required" && "Theis field is required"} 81 | {errors.name.type === "maxLength" && 82 | "Max length is 100 char."} 83 |

    84 | )} 85 | 86 | 95 | {errors.email && ( 96 |

    97 | {errors.email.type === "required" && 98 | "Theis field is required"} 99 | {errors.email.type === "pattern" && "Invalid email adresse"} 100 |

    101 | )} 102 |