diff --git a/src/frontend/src/assets/css/index.css b/src/frontend/src/assets/css/index.css index 93280f0b..45c2f10e 100644 --- a/src/frontend/src/assets/css/index.css +++ b/src/frontend/src/assets/css/index.css @@ -12,6 +12,10 @@ body { font-family: 'Barlow Condensed', sans-serif; } +.landing-page p { + font-family: 'Manrope', sans-serif !important; +} + @keyframes slideInFromLeft { from { opacity: 0; diff --git a/src/frontend/src/components/LandingPage/AboutTM/index.tsx b/src/frontend/src/components/LandingPage/AboutTM/index.tsx new file mode 100644 index 00000000..62449601 --- /dev/null +++ b/src/frontend/src/components/LandingPage/AboutTM/index.tsx @@ -0,0 +1,67 @@ +import { Grid } from '@Components/common/Layouts'; +import Image from '@Components/RadixComponents/Image'; +import { motion } from 'framer-motion'; +import droneImage from '@Assets/images/LandingPage/DroneImage.png'; +import { aboutData } from '@Constants/landingPage'; +import { + containerAnimationVariant, + fadeUpVariant, +} from '@Constants/animations'; + +export default function AboutTM() { + return ( +
+
+ + +

+ About Drone Tasking Manager (Drone TM) +

+

+ Drone TM is an integrated digital public good solution that aims + to harness the power of the crowd to help generate high-resolution + aerial maps of any location. Its innovative platform allows drone + pilots in developing countries to access job opportunities and + contribute to creating high-resolution datasets for disaster + response and community resilience. +

+
+ + + +
+ + {aboutData.map(data => ( + + +

+ {data.title} +

+

+ {data.description} +

+
+ ))} +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/CaseStudies/index.tsx b/src/frontend/src/components/LandingPage/CaseStudies/index.tsx new file mode 100644 index 00000000..bd559b75 --- /dev/null +++ b/src/frontend/src/components/LandingPage/CaseStudies/index.tsx @@ -0,0 +1,88 @@ +import { FlexRow } from '@Components/common/Layouts'; +import Icon from '@Components/common/Icon'; +import Image from '@Components/RadixComponents/Image'; +import { motion } from 'framer-motion'; +import { + containerAnimationVariant, + fadeUpVariant, +} from '@Constants/animations'; +import { caseStudiesData } from '@Constants/landingPage'; +import caseStudyImage from '@Assets/images/LandingPage/CaseStudyImage.png'; +import { useEffect, useState } from 'react'; + +export default function CaseStudies() { + const [itemsToShow, setItemsToShow] = useState(1); + + useEffect(() => { + function handleResize() { + if (window.innerWidth < 768) { + setItemsToShow(1); + } else { + setItemsToShow(2); + } + } + + window.addEventListener('resize', handleResize); + handleResize(); + return () => window.removeEventListener('resize', handleResize); + }, []); + return ( +
+
+ + + Case Studies + + + + + + + + {caseStudiesData.slice(0, itemsToShow).map(data => ( + +
+

+ {data.title} +

+

+ {data.description} +

+
+
+ +
+
+ ))} +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/ClientsAndPartners/index.tsx b/src/frontend/src/components/LandingPage/ClientsAndPartners/index.tsx new file mode 100644 index 00000000..8e05d2a1 --- /dev/null +++ b/src/frontend/src/components/LandingPage/ClientsAndPartners/index.tsx @@ -0,0 +1,34 @@ +import Image from '@Components/RadixComponents/Image'; +import { motion } from 'framer-motion'; +import worldBankLogo from '@Assets/images/LandingPage/WorldbankLogo.png'; +import { fadeUpVariant } from '@Constants/animations'; + +export default function ClientAndPartners() { + return ( +
+
+
+ + Client & Partners + + + world bank logo + +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/Features/index.tsx b/src/frontend/src/components/LandingPage/Features/index.tsx new file mode 100644 index 00000000..077827b6 --- /dev/null +++ b/src/frontend/src/components/LandingPage/Features/index.tsx @@ -0,0 +1,65 @@ +import { FlexColumn } from '@Components/common/Layouts'; +import { motion } from 'framer-motion'; +import { featuresData } from '@Constants/landingPage'; + +export default function Features() { + const container = { + hidden: { opacity: 1, scale: 0 }, + visible: { + opacity: 1, + scale: 1, + transition: { + delayChildren: 0.3, + staggerChildren: 0.2, + }, + }, + }; + + const item = { + hidden: { y: 20, opacity: 0 }, + visible: { + y: 0, + opacity: 1, + }, + }; + return ( +
+
+
+
+

+ Features of Drone Tasking Manager +

+
+ + {featuresData.map(data => ( + + + {data.id} + +
+

+ {data.title} +

+
+

+ {data.description} +

+
+ ))} +
+
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/Footer/index.tsx b/src/frontend/src/components/LandingPage/Footer/index.tsx new file mode 100644 index 00000000..eb5a488e --- /dev/null +++ b/src/frontend/src/components/LandingPage/Footer/index.tsx @@ -0,0 +1,66 @@ +import { Flex, FlexRow } from '@Components/common/Layouts'; +import Icon from '@Components/common/Icon'; +import Image from '@Components/RadixComponents/Image'; +import naxaLogo from '@Assets/images/LandingPage/Naxa-logo.png'; +import hotLogo from '@Assets/images/LandingPage/HOT-logo.png'; +import { Button } from '@Components/RadixComponents/Button'; +import { motion } from 'framer-motion'; +import { fadeUpVariant } from '@Constants/animations'; + +export default function Footer() { + return ( + + ); +} diff --git a/src/frontend/src/components/LandingPage/Home/index.tsx b/src/frontend/src/components/LandingPage/Home/index.tsx new file mode 100644 index 00000000..bcd40eee --- /dev/null +++ b/src/frontend/src/components/LandingPage/Home/index.tsx @@ -0,0 +1,99 @@ +import { useTypedDispatch } from '@Store/hooks'; +import { FlexColumn } from '@Components/common/Layouts'; +import Image from '@Components/RadixComponents/Image'; +import { Button } from '@Components/RadixComponents/Button'; +import { motion } from 'framer-motion'; +import droneTaskingManagerLogo from '@Assets/images/LandingPage/DTM-logo-red.svg'; +import droneBackgroundImage from '@Assets/images/LandingPage/DroneTM-bg.png'; +import arrowSouth from '@Assets/images/LandingPage/arrow_south.svg'; +import { setCommonState } from '@Store/actions/common'; + +export default function Home() { + const dispatch = useTypedDispatch(); + + const bounceTransition: { + y: { + repeat: number; + repeatType: 'reverse' | 'loop' | 'mirror'; + duration: number; + ease: string; + }; + } = { + y: { + repeat: Infinity, + repeatType: 'mirror', + duration: 0.8, + ease: 'easeOut', + }, + }; + + const container = { + visible: { + transition: { + staggerChildren: 0.025, + }, + }, + }; + + return ( +
+
+
+ + +
+ + +

+ Drone Tasking +

+

+ Manager (Drone TM) +

+

+ Together, WeMap - Open.Accurate. Accessible +

+
+ {/*
+ + +
*/} + + + +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/MajorImpacts/index.tsx b/src/frontend/src/components/LandingPage/MajorImpacts/index.tsx new file mode 100644 index 00000000..78f4bf0a --- /dev/null +++ b/src/frontend/src/components/LandingPage/MajorImpacts/index.tsx @@ -0,0 +1,57 @@ +import { Grid } from '@Components/common/Layouts'; +import Image from '@Components/RadixComponents/Image'; +import { motion } from 'framer-motion'; +import Accordion from '@Components/common/Accordion'; +import majorImpactsImage from '@Assets/images/LandingPage/MajorImpactImage.png'; +import { accordionData } from '@Constants/landingPage'; +import { + containerAnimationVariant, + fadeUpVariant, +} from '@Constants/animations'; + +export default function MajorImpacts() { + return ( +
+
+ + {/* */} + + {/* */} + +

+ Anticipated Major Impacts +

+
+ {accordionData.map((data: Record) => ( + + + + ))} +
+
+
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/Navbar/index.tsx b/src/frontend/src/components/LandingPage/Navbar/index.tsx new file mode 100644 index 00000000..b1595577 --- /dev/null +++ b/src/frontend/src/components/LandingPage/Navbar/index.tsx @@ -0,0 +1,21 @@ +import { FlexRow } from '@Components/common/Layouts'; + +export default function Navbar() { + return ( +
+ + +

About

+

FAQs

+

Documentations

+
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/OpenSource/index.tsx b/src/frontend/src/components/LandingPage/OpenSource/index.tsx new file mode 100644 index 00000000..eb854134 --- /dev/null +++ b/src/frontend/src/components/LandingPage/OpenSource/index.tsx @@ -0,0 +1,38 @@ +import { FlexColumn } from '@Components/common/Layouts'; +import Image from '@Components/RadixComponents/Image'; +import { motion } from 'framer-motion'; +import forestImage from '@Assets/images/LandingPage/ForestImage.png'; + +export default function OpenSource() { + return ( +
+
+ +
+

+ Open Source +

+

+ Drone Tasking Manager +

+
+

+ An open-source drone tasking platform to coordinate aerial survey + activities for target project areas among multiple pilots, + incorporating tools and processes to ensure coordinated flight plans + for imagery acquisition, and a seamless pipeline for processing and + dissemination. +

+ + + +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/OurRationale/index.tsx b/src/frontend/src/components/LandingPage/OurRationale/index.tsx new file mode 100644 index 00000000..f9a1e8f5 --- /dev/null +++ b/src/frontend/src/components/LandingPage/OurRationale/index.tsx @@ -0,0 +1,52 @@ +import { FlexColumn } from '@Components/common/Layouts'; +import { motion } from 'framer-motion'; +import { ourRationaleData } from '@Constants/landingPage'; +import { + containerAnimationVariant, + fadeUpVariant, +} from '@Constants/animations'; + +export default function OurRationale() { + return ( +
+
+
+
+

+ Our Rationale +

+
+ + {ourRationaleData.map(data => ( + + + + {data.id} + + +
+

+ {data.title} +

+
+

+ {data.description} +

+
+ ))} +
+
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx b/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx new file mode 100644 index 00000000..ed991228 --- /dev/null +++ b/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx @@ -0,0 +1,58 @@ +import { useTypedDispatch } from '@Store/hooks'; +import { FlexColumn, FlexRow } from '@Components/common/Layouts'; +import { Button } from '@Components/RadixComponents/Button'; +import Image from '@Components/RadixComponents/Image'; +import droneTMLogo from '@Assets/images/LandingPage/dtm-logo-red.svg'; +import projectCreator from '@Assets/images/LandingPage/project-creator.svg'; +import droneOperator from '@Assets/images/LandingPage/drone-operator.svg'; +import Icon from '@Components/common/Icon'; +import { setCommonState } from '@Store/actions/common'; +import { motion } from 'framer-motion'; +import { slideVariants } from '@Constants/animations'; + +export default function SignInOverlay() { + const dispatch = useTypedDispatch(); + + return ( + + + + { + dispatch(setCommonState({ openSignInMenu: false })); + }} + /> + + + +
Project Creator
+ + +
+ +
Drone Operator
+ + +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/UserAndRoles/index.tsx b/src/frontend/src/components/LandingPage/UserAndRoles/index.tsx new file mode 100644 index 00000000..a79b5cb4 --- /dev/null +++ b/src/frontend/src/components/LandingPage/UserAndRoles/index.tsx @@ -0,0 +1,87 @@ +import { useState, useEffect } from 'react'; +import { FlexRow } from '@Components/common/Layouts'; +// import Icon from '@Components/common/Icon'; +import { motion } from 'framer-motion'; +import { userAndRolesData } from '@Constants/landingPage'; +import { + containerAnimationVariant, + fadeUpVariant, +} from '@Constants/animations'; + +export default function UserAndRoles() { + const [itemsToShow, setItemsToShow] = useState(1); + + useEffect(() => { + function handleResize() { + if (window.innerWidth < 768) { + setItemsToShow(1); + } else if (window.innerWidth < 1024) { + setItemsToShow(2); + } else { + setItemsToShow(3); + } + } + + window.addEventListener('resize', handleResize); + handleResize(); + return () => window.removeEventListener('resize', handleResize); + }, []); + + return ( +
+
+ + Drone TM: Users & Roles + + + {/* */} + + {userAndRolesData.slice(0, itemsToShow).map(singleItem => ( + +

+ {singleItem.title} +

+
    + {singleItem.listItems.map(item => ( +
  • {item.text}
  • + ))} +
+
+ ))} +
+ {/* */} +
+
+
+ ); +} diff --git a/src/frontend/src/components/LandingPage/index.tsx b/src/frontend/src/components/LandingPage/index.tsx new file mode 100644 index 00000000..0ef48aeb --- /dev/null +++ b/src/frontend/src/components/LandingPage/index.tsx @@ -0,0 +1,27 @@ +import Navbar from './Navbar'; +import Home from './Home'; +import AboutTM from './AboutTM'; +import OurRationale from './OurRationale'; +import OpenSource from './OpenSource'; +import Features from './Features'; +import UserAndRoles from './UserAndRoles'; +import MajorImpacts from './MajorImpacts'; +import CaseStudies from './CaseStudies'; +import ClientAndPartners from './ClientsAndPartners'; +import Footer from './Footer'; +import SignInOverlay from './SignInOverlay'; + +export { + Navbar, + Home, + AboutTM, + OurRationale, + OpenSource, + Features, + UserAndRoles, + MajorImpacts, + CaseStudies, + ClientAndPartners, + Footer, + SignInOverlay, +}; diff --git a/src/frontend/src/views/LandingPage/index.tsx b/src/frontend/src/views/LandingPage/index.tsx new file mode 100644 index 00000000..6e157a6e --- /dev/null +++ b/src/frontend/src/views/LandingPage/index.tsx @@ -0,0 +1,36 @@ +import { useTypedSelector } from '@Store/hooks'; +import { + Navbar, + Home, + AboutTM, + OurRationale, + OpenSource, + Features, + UserAndRoles, + MajorImpacts, + CaseStudies, + ClientAndPartners, + Footer, + SignInOverlay, +} from '@Components/LandingPage'; +import { AnimatePresence } from 'framer-motion'; + +export default function LandingPage() { + const openSignInMenu = useTypedSelector(state => state.common.openSignInMenu); + return ( +
+ + {openSignInMenu && } + + + + + + + + + +
+ ); +}