diff --git a/src/App.jsx b/src/App.jsx index 047fd42..43ae695 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -5,11 +5,18 @@ import Footer from './components/Footer/Footer.jsx' import Toast from "./components/Toast/Toast.jsx" import BackGround from './components/BackGround/BackGround.jsx' import ScrollToTop from './components/ScrollToTop/ScrollToTop.jsx' +import PreLoader from './components/PreLoader/PreLoader.jsx' +import { useState } from 'react' + function App() { + + const [isPreLoading, setIsPreLoading] = useState(true) + return ( <> - + {isPreLoading && } + diff --git a/src/assets/method.svg b/src/assets/method.svg new file mode 100644 index 0000000..bb7b251 --- /dev/null +++ b/src/assets/method.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/preloader.svg b/src/assets/preloader.svg new file mode 100644 index 0000000..16aae33 --- /dev/null +++ b/src/assets/preloader.svg @@ -0,0 +1,5 @@ + + + diff --git a/src/assets/vision.svg b/src/assets/vision.svg new file mode 100644 index 0000000..b050796 --- /dev/null +++ b/src/assets/vision.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Apod/Apod.jsx b/src/components/Apod/Apod.jsx index fb87068..4c07c85 100644 --- a/src/components/Apod/Apod.jsx +++ b/src/components/Apod/Apod.jsx @@ -22,14 +22,10 @@ function Apod() { response = await response.json(); - console.log(response); - setApodInfo((prev) => { return { ...prev, url: response.url, explanation: response.explanation, title: response.title, date: response.date, copyright: response.copyright, media_type: response.media_type } }) - console.log(apodInfo); - } catch (error) { console.log(error.message); } diff --git a/src/components/BackGround/BackGround.jsx b/src/components/BackGround/BackGround.jsx index 3fab2ba..bbdb673 100644 --- a/src/components/BackGround/BackGround.jsx +++ b/src/components/BackGround/BackGround.jsx @@ -13,7 +13,7 @@ function Star({ position }) { ); }; -function StarField({ numberOfStars = 100 }) { +function StarField({ numberOfStars = 100, setIsPreLoading }) { const starFieldRef = useRef(); @@ -25,6 +25,7 @@ function StarField({ numberOfStars = 100 }) { const [positions, setPositions] = useState([]) const addStars = useCallback(() => { + setIsPreLoading(true); const starsPosition = []; for (let i = 0; i < numberOfStars; i++) { let x = (Math.random() * 2 - 1) * 10; // Ensure x is within -5 to 5 range @@ -33,10 +34,12 @@ function StarField({ numberOfStars = 100 }) { starsPosition.push([x, y, z]); } setPositions((prev) => [...starsPosition]); + setTimeout(() => setIsPreLoading(false), 2000) }, [numberOfStars]) useEffect(addStars, []); return ( + { positions.map((position, index) => ( @@ -48,13 +51,13 @@ function StarField({ numberOfStars = 100 }) { } -function Background() { +function Background({ setIsPreLoading }) { return (
- + - +
); diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index 860ded9..623fde4 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -50,6 +50,7 @@ function Navbar() {
  • APOD
  • MartianImagery
  • NASA's Projects
  • +
  • About us
  • @@ -73,6 +74,9 @@ function Navbar() {
  • NASA's Projects
  • +
  • + About us +
  • diff --git a/src/components/PreLoader/PreLoader.jsx b/src/components/PreLoader/PreLoader.jsx new file mode 100644 index 0000000..360c23b --- /dev/null +++ b/src/components/PreLoader/PreLoader.jsx @@ -0,0 +1,14 @@ +import React, { useEffect } from 'react' +import Styles from "./PreLoader.module.css" +import preloader from "../../assets/preloader.svg" + +function PreLoader() { + + return ( +
    + + + ) +} + +export default PreLoader \ No newline at end of file diff --git a/src/components/PreLoader/PreLoader.module.css b/src/components/PreLoader/PreLoader.module.css new file mode 100644 index 0000000..8e5c9ea --- /dev/null +++ b/src/components/PreLoader/PreLoader.module.css @@ -0,0 +1,12 @@ +#container { + position: fixed; + z-index: 11000; + height: 100%; + width: 100%; + top: 0; + left: 0; + display: flex; + justify-content: center; + align-items: center; + background: #000000; +} \ No newline at end of file diff --git a/src/components/Toast/Toast.jsx b/src/components/Toast/Toast.jsx index 9a5a8a3..9a67e86 100644 --- a/src/components/Toast/Toast.jsx +++ b/src/components/Toast/Toast.jsx @@ -14,7 +14,6 @@ function Toast() { const [isSuccess, setIsSuccess] = useState(false); toastify = (message = "", isSuccess = true) => { - console.log(timeOut); if (timeOut) { setMessage(message); setIsSuccess(isSuccess); diff --git a/src/main.jsx b/src/main.jsx index bde04b1..c6030f9 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,10 +1,11 @@ import React from 'react' import ReactDOM from 'react-dom/client' +import { createBrowserRouter, createRoutesFromElements, RouterProvider, Route } from "react-router-dom" +import './index.css' import App from './App.jsx' import Home from "./pages/Home/Home.jsx" import NasaProjects from "./pages/NasaProjects/NasaProjects.jsx" -import './index.css' -import { createBrowserRouter, createRoutesFromElements, RouterProvider, Route } from "react-router-dom" +import About from "./pages/About/About.jsx" import MarsRover from './pages/MarsRover/MarsRover.jsx' const router = createBrowserRouter( @@ -12,6 +13,7 @@ const router = createBrowserRouter( }> } /> } /> + } /> }/> ) diff --git a/src/pages/About/About.jsx b/src/pages/About/About.jsx new file mode 100644 index 0000000..525e045 --- /dev/null +++ b/src/pages/About/About.jsx @@ -0,0 +1,126 @@ +import React, { useEffect, useState } from 'react' +import Styles from "./About.module.css" +import vision from "../../assets/vision.svg" +import method from "../../assets/method.svg" +import { FaAnglesRight, FaAnglesLeft, FaAngleLeft, FaAngleRight, FaGithub, FaLinkedin } from "react-icons/fa6"; +import Pagination from "../../utils/Pagination.js" + + + + +function About() { + + const FOUNDER_NAME = "PranavBarthwal" + const FOUNDER_LINKEDIN_URL = "https://www.linkedin.com/in/pranavbarthwal03/" + const CARDS_PER_PAGE = 8; + const repoName = "cosmoXplore"; + + const [contributors, setContributors] = useState([]); + const [founder, setFounder] = useState({}); + const [currentPage, setCurrentPage] = useState(1); // to store pagination number. + const [pageinatedContributors, setPageinatedContributors] = useState([]); + + + useEffect(() => { + fetchContributors() + }, []) + + useEffect(() => { + setPageinatedContributors(Pagination.Paginate(contributors, currentPage, CARDS_PER_PAGE)); + }, [contributors, currentPage]) + + async function fetchContributors() { + try { + + const response = await fetch(`https://api.github.com/repos/${FOUNDER_NAME}/${repoName}/contributors`) + + const data = await response.json(); + + setContributors((prev) => { + return data.filter((user, idx) => user.login != FOUNDER_NAME); + }) + + setFounder(data.find((user) => user.login == FOUNDER_NAME)); + + } catch (error) { + console.log(error.message); + } + } + + + return ( +
    + +
    +

    About CosmoXplore

    +

    + “CosmoXplore is your portal to the universe's wonders, Making space exploration accessible and exciting for everyone.” +

    +
    + +
    +

    Our Vision

    +
    +

    Explore the cosmos with CosmoXplore and stay informed about the innovations driving humanity's journey into the final frontier. Join us in discovering the beauty and mysteries of space, one photo and breakthrough at a time.As an open source organization, we are committed to transparency, collaboration, and community-driven development.

    + +
    +
    + +
    +

    Our Methods

    +
    + +

    Our platform brings you stunning Astronomy Picture of the Day (APOD) images, fascinating photos of Mars, and updates on the latest technological breakthroughs at NASA. Utilizing NASA's open API, we deliver a seamless and engaging experience for space enthusiasts and curious minds alike.

    +
    +
    + +
    + +
    +

    Our Founder

    +
    + +

    {founder.login}

    +
    + + +
    +
    +
    + +
    +

    Our Contributors

    + +
    + { + pageinatedContributors.map((user, idx) => ( +
    + +

    {user.login}

    +
    + +
    +
    + )) + } +
    + +
    + setCurrentPage(Pagination.StartPage(contributors, currentPage, CARDS_PER_PAGE))} /> + setCurrentPage(Pagination.PrevPage(contributors, currentPage, CARDS_PER_PAGE))} /> + + {currentPage} + + setCurrentPage(Pagination.NextPage(contributors, currentPage, CARDS_PER_PAGE))} /> + setCurrentPage(Pagination.LastPage(contributors, currentPage, CARDS_PER_PAGE))} /> +
    +
    + +
    + + +
    + ) +} + +export default About \ No newline at end of file diff --git a/src/pages/About/About.module.css b/src/pages/About/About.module.css new file mode 100644 index 0000000..b1629da --- /dev/null +++ b/src/pages/About/About.module.css @@ -0,0 +1,227 @@ +#container { + min-height: 100dvh; + border-top: solid 30dvh transparent; + padding-bottom: 20dvh; + background-color: transparent; +} + +/* section 1 */ +#section_1 { + display: flex; + flex-direction: column; + align-items: center; + animation: leviate 2s ease-in-out infinite; +} + +#section_1 h1 { + color: rgb(140, 0, 255); +} + +#section_1 p { + font-size: 3rem; + width: 70%; + color: rgb(255, 255, 255); + text-align: center; + text-shadow: 3px 3px 20px rgb(174, 0, 255); +} + +#section_2 img, +#section_3 img { + animation: leviate 2s ease-in-out infinite; + filter: drop-shadow(0px 0px 5px rgb(255, 255, 255)); +} + +/* section 2 */ +#section_2 { + margin-top: 25%; + padding-left: 10%; +} + +#section_2 h1, +#section_3 h1 { + text-shadow: 3px 3px 20px rgb(174, 0, 255); +} + +#section_2 div { + display: flex; + align-items: center; +} + +#section_2 p { + width: 60%; + font-size: 1.5rem; + margin-top: 10px; +} + +/* section 3 */ +#section_3 { + margin-top: 25%; + padding-left: 10%; +} + +#section_3 h1 { + text-align: right; + padding-right: 10%; +} + +#section_3 div { + display: flex; + align-items: center; +} + +#section_3 p { + width: 60%; + font-size: 1.5rem; + text-align: left; +} + +/* open source section */ + +#section_4 { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + margin-top: 25%; +} + +/* founder */ +#founder { + text-align: center; + margin-bottom: 20%; +} + +#founder>div { + border: 1px solid white; + padding: 20px 40px; + background: #00000059; + border-radius: 20px; + margin-top: 30px; + box-shadow: 0 0 20px rgb(174, 0, 255); + animation: leviate 2s ease-in-out infinite; +} + +#founder img { + border-radius: 50%; + aspect-ratio: 1 / 1; + width: 300px; + margin-bottom: 20px; + box-shadow: 0 0 20px white; +} + +#social { + display: flex; + justify-content: space-evenly; +} + +#social a { + color: white; + +} + + +/* contributors */ +#contributors { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +#cards { + display: grid; + grid-template-rows: 1fr 1fr; + grid-template-columns: repeat(4, 1fr); + column-gap: 20px; +} + +.card { + height: 250px; + width: 250px; + border: 1px solid white; + padding: 20px 20px; + background: #00000059; + border-radius: 20px; + margin-top: 30px; + text-align: center; + word-wrap: break-word; +} + +.card h3 { + font-size: 1.2rem; +} + +.card img { + aspect-ratio: 1 / 1; + width: 150px; + border-radius: 50%; + margin-bottom: 5px; + box-shadow: 0 0 20px rgb(255, 255, 255); +} + +.card:hover { + animation: leviate 2s ease-in-out infinite; + box-shadow: 0 0 40px rgb(174, 0, 255); +} + +@keyframes leviate { + + 50% { + transform: translateY(-10px); + } +} + +#page-btns { + margin-top: 5%; + display: flex; + justify-content: space-between; + align-items: center; + width: 200px; +} + +.page-icons { + cursor: pointer; +} + +#page-num { + font-size: 2rem; +} + +@media (max-width:1000px) { + #cards { + grid-template-columns: repeat(3, 1fr); + } +} + +@media (max-width:800px) { + #cards { + grid-template-columns: repeat(2, 1fr); + margin-bottom: 20%; + } +} + +@media (max-width:600px) { + #section_1 p { + font-size: 1.5rem; + } + + #section_2 p, + #section_3 p { + font-size: 1rem; + } + + #section_2 img, + #section_3 img { + width: 200px; + } + + #section_3 { + margin-right: 20px; + } + + .card { + width: 170px; + padding: 10px 0; + } + +} \ No newline at end of file diff --git a/src/pages/NasaProjects/NasaProjects.jsx b/src/pages/NasaProjects/NasaProjects.jsx index 9127ca1..286838c 100644 --- a/src/pages/NasaProjects/NasaProjects.jsx +++ b/src/pages/NasaProjects/NasaProjects.jsx @@ -2,14 +2,11 @@ import React, { useEffect, useState } from 'react'; import logo from "../../assets/NASA_logo.svg"; import Styles from "./NasaProjects.module.css"; import { FaSearch } from "react-icons/fa"; -import { FaAnglesRight } from "react-icons/fa6"; +import { FaAnglesRight, FaAnglesLeft, FaAngleLeft, FaAngleRight } from "react-icons/fa6"; import ProjectCard from '../../components/ProjectCard/ProjectCard'; import { IoReloadOutline } from "react-icons/io5"; -import { FaAnglesLeft } from "react-icons/fa6"; -import { FaAngleLeft } from "react-icons/fa6"; -import { FaAngleRight } from "react-icons/fa6"; import ReadableStreamDecoder from "../../utils/ReadableStreamDecoder.js" - +import Pagination from "../../utils/Pagination.js"; function TechNews() { @@ -18,10 +15,11 @@ function TechNews() { const [isLoading, setIsLoading] = useState(true); // to show loading state. const [search, setSearch] = useState(""); // to store search query. const [projects, setProjects] = useState([]); // to store projects. - const [tempProject, setTempProjects] = useState(JSON.parse(localStorage.getItem("projects")) || []); // to stote temporary projects. - const [paginationProjects, setPaginationProjects] = useState([]); // to store projects for pagination. - const [page, setPage] = useState(1); // to store pagination number. + const [tempProject, setTempProjects] = useState([]); // to stote temporary projects. + // const [paginationProjects, setPaginationProjects] = useState([]); // to store projects for pagination. + const [currentPage, setCurrentPage] = useState(1); // to store pagination number. const [week, setWeek] = useState(1); // to set weeks for fetching data. + const itemsPerPage = 10; // Adding on scroll event listener for auto closing search bar. useEffect(() => { @@ -39,10 +37,10 @@ function TechNews() { }, [week]) - // to paginate when new projects are fetched or page is changed + // to paginate when new projects are fetched or currentPage is changed useEffect(() => { - Pagination(); - }, [page, projects, paginationProjects]) + setTempProjects(Pagination.Paginate(projects, currentPage, itemsPerPage)); + }, [currentPage, projects]) // debouncing the search query @@ -160,12 +158,13 @@ function TechNews() { // search for projects function handleSearch() { try { - setPaginationProjects( + setTempProjects( projects.filter((item) => ( item.title.toLowerCase().search(search.toLowerCase()) > -1 )) ); - setPage(1) + setCurrentPage(1) + Pagination.Paginate(tempProject, currentPage, itemsPerPage) } catch (error) { console.log(error.message); } @@ -176,49 +175,6 @@ function TechNews() { setSearch(e.target.value); } - - // next page - function handleNextPage(e) { - setPage((prev) => { - if (prev < (Math.ceil(paginationProjects.length / 10))) - return prev + 1; - return prev; - }) - } - - - // go to last page - function handleLastPage(e) { - setPage(Math.ceil(paginationProjects.length / 10)); - } - - - // previous page - function handlePrevPage(e) { - setPage((prev) => { - if (prev > 1) - return prev - 1; - return prev; - }) - } - - - // go to first page - function handleStartPage(e) { - setPage(1); - } - - - // to make pages - function Pagination() { - setTempProjects((prev) => { - const last_index = page * 10; - const start_index = last_index - 10; - return paginationProjects.slice(start_index, last_index); - }) - } - - return (
    @@ -254,15 +210,15 @@ function TechNews() { { projects.length ?
    - - - {page} - - + setCurrentPage(Pagination.StartPage(projects, currentPage, itemsPerPage))} /> + setCurrentPage(Pagination.PrevPage(projects, currentPage, itemsPerPage))} /> + {currentPage} + setCurrentPage(Pagination.NextPage(projects, currentPage, itemsPerPage))} /> + setCurrentPage(Pagination.LastPage(projects, currentPage, itemsPerPage))} />
    : "" } - +
    ) diff --git a/src/utils/Pagination.js b/src/utils/Pagination.js new file mode 100644 index 0000000..a8aa1a5 --- /dev/null +++ b/src/utils/Pagination.js @@ -0,0 +1,36 @@ +// next page +function NextPage(array = [], currentPage = 1, itemsPerPage = 10) { + if (currentPage < (Math.ceil(array.length / itemsPerPage))) + return currentPage + 1; + return currentPage; +} + + +// go to last page +function LastPage(array = [], currentPage = 1, itemsPerPage = 10) { + return Math.ceil(array.length / itemsPerPage); +} + + +// previous page +function PrevPage(array = [], currentPage = 1, itemsPerPage = 10) { + if (currentPage > 1) + return currentPage - 1; + return currentPage; +} + + +// go to first page +function StartPage(array = [], currentPage = 1, itemsPerPage = 10) { + return 1; +} + + +// to make pages +function Paginate(array = [], currentPage = 1, itemsPerPage = 10) { + const last_index = currentPage * itemsPerPage; + const start_index = last_index - itemsPerPage; + return array.slice(start_index, last_index); +} + +export default { Paginate, NextPage, PrevPage, LastPage, StartPage }; \ No newline at end of file