diff --git a/.github/workflows/autocomment-issue-close.yml b/.github/workflows/autocomment-issue-close.yml new file mode 100644 index 00000000..33201003 --- /dev/null +++ b/.github/workflows/autocomment-issue-close.yml @@ -0,0 +1,27 @@ +name: Comment on Issue Close + +on: + issues: + types: [closed] + +jobs: + greet-on-close: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Greet User + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issue = context.payload.issue; + const issueCreator = issue.user.login; + const issueNumber = issue.number; + const greetingMessage = `Hello @${issueCreator}! Your issue #${issueNumber} has been closed. Thank you for your contribution!`; + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: greetingMessage + }); \ No newline at end of file diff --git a/.github/workflows/autocomment-pr-merge.yml b/.github/workflows/autocomment-pr-merge.yml new file mode 100644 index 00000000..c4a075c5 --- /dev/null +++ b/.github/workflows/autocomment-pr-merge.yml @@ -0,0 +1,36 @@ +name: Auto Comment on PR Merge + +on: + pull_request: + types: [closed] + +permissions: + issues: write + pull-requests: write + +jobs: + comment: + runs-on: ubuntu-latest + permissions: + pull-requests: write + if: github.event.pull_request.merged == true + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Add Comment to Issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + COMMENT=$(cat < + + + Counsellor Portal diff --git a/package-lock.json b/package-lock.json index 1cb78680..f1e9a77c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "uid": "^2.0.2" }, "devDependencies": { - "@types/react": "^18.3.2", + "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.0", "vite": "^5.2.11" @@ -1674,9 +1674,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", - "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -4062,9 +4062,9 @@ "dev": true }, "@types/react": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", - "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dev": true, "requires": { "@types/prop-types": "*", diff --git a/package.json b/package.json index 2cdb17a4..43afce71 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "uid": "^2.0.2" }, "devDependencies": { - "@types/react": "^18.3.2", + "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.0", "vite": "^5.2.11" diff --git a/src/App.jsx b/src/App.jsx index a822035f..4bbcfd52 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -8,7 +8,7 @@ const App = () => { return (
- +
); }; diff --git a/src/Pages/Profile/Profile.css b/src/Pages/Profile/Profile.css new file mode 100644 index 00000000..850a30f2 --- /dev/null +++ b/src/Pages/Profile/Profile.css @@ -0,0 +1,259 @@ +@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap"); + +:root { + --light: #f6f6f9; + --primary: #1976d2; + --light-primary: #cfe8ff; + --grey: #eee; + --dark-grey: #aaaaaa; + --dark: #363949; + --danger: #d32f2f; + --light-danger: #fecdd3; + --warning: #fbc02d; + --light-warning: #fff2c6; + --success: #388e3c; + --light-success: #bbf7d0; +} +.profile-body { + overflow-x: hidden; +} +.profile-body * { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "Poppins", sans-serif; +} + +.profile-body .bx { + font-size: 1.7rem; +} + +.profile-body a { + text-decoration: none; +} +.profile-body html { + overflow-x: hidden; +} + +.profile-body body { + background: var(--grey); + overflow-x: hidden; +} + +.profile-body .sidebar { + position: fixed; + top: 0; + left: 0; + background: var(--light); + width: 230px; + height: 100%; + z-index: 2000; + overflow-x: hidden; + scrollbar-width: none; + transition: all 0.3s ease; +} + +.profile-body .sidebar::-webkit-scrollbar { + display: none; +} + +.profile-body .sidebar.close { + width: 60px; +} + +.profile-body .sidebar .logo { + font-size: 24px; + font-weight: 700; + height: 56px; + display: flex; + align-items: center; + color: var(--primary); + z-index: 500; + padding-bottom: 20px; + box-sizing: content-box; +} +.profile-body .logo .logo-img { + width: 60px; +} + +.profile-body .sidebar .logo .logo-name span { + color: var(--dark); +} + +.profile-body .sidebar .logo .bx { + min-width: 60px; + display: flex; + justify-content: center; + font-size: 2.2rem; +} + +.profile-body .sidebar .side-menu { + width: 100%; +} + +.profile-body .sidebar .side-menu li { + height: 48px; + background: transparent; + margin-left: 6px; + border-radius: 48px 0 0 48px; + padding: 4px; +} +/* +.sidebar .side-menu li.active { + background: var(--grey); + position: relative; +} + +.sidebar .side-menu li.active::before { + content: ""; + position: absolute; + width: 40px; + height: 40px; + border-radius: 50%; + top: -40px; + right: 0; + box-shadow: 20px 20px 0 var(--grey); + z-index: -1; +} */ + +/* .sidebar .side-menu li.active::after { + content: ""; + position: absolute; + width: 40px; + height: 40px; + border-radius: 50%; + bottom: -40px; + right: 0; + box-shadow: 20px -20px 0 var(--grey); + z-index: -1; +} */ + +.profile-body .sidebar .side-menu li a { + width: 100%; + height: 100%; + background: var(--light); + display: flex; + align-items: center; + border-radius: 48px; + font-size: 16px; + color: var(--dark); + white-space: nowrap; + overflow-x: hidden; + transition: all 0.3s ease; +} + +.profile-body .sidebar .side-menu li.active a { + color: var(--success); +} + +.profile-body .sidebar.close .side-menu li a { + width: calc(48px - (4px * 2)); + transition: all 0.3s ease; +} + +.profile-body .sidebar .side-menu li a .bx { + min-width: calc(60px - ((4px + 6px) * 2)); + display: flex; + font-size: 1.6rem; + justify-content: center; +} + +.profile-body .sidebar .side-menu li a.logout { + color: var(--danger); +} + +.profile-body .content { + position: relative; + background: var(--grey); + width: calc(100% - 230px); + left: 230px; + transition: all 0.3s ease; +} + +.profile-body .sidebar.close ~ .content { + width: calc(100% - 60px); + left: 60px; +} + +.profile-body .content nav { + height: 56px; + background: var(--light); + padding: 0 24px 0 0; + display: flex; + align-items: center; + justify-content: space-between; + grid-gap: 24px; + top: 0; + left: 0; + z-index: 1000; + width: 100%; +} + +.profile-body .content nav a { + color: var(--dark); +} + +.profile-body .content nav .bx.bx-menu { + cursor: pointer; + color: var(--dark); + font-size: 25px; + margin: 0 5px; +} +.profile-body .content nav .logoName { + font-size: 24px; + font-weight: 700; + color: var(--primary); + z-index: 500; +} + +.profile-body .content nav .logoName span { + color: var(--dark); +} + +.profile-body .content nav .notif { + font-size: 20px; + position: relative; + margin: 0 9px; +} + +.profile-body .content nav .notif .count { + position: absolute; + top: -6px; + right: -6px; + width: 20px; + height: 20px; + background: var(--danger); + border-radius: 50%; + color: var(--light); + border: 2px solid var(--light); + font-weight: 700; + font-size: 12px; + display: flex; + align-items: center; + justify-content: center; +} + +.profile-body .content nav .profile .img { + font-size: 30px; + object-fit: cover; + border-radius: 50%; +} + +@media screen and (max-width: 768px) { + .profile-body .sidebar { + width: 200px; + } + + .profile-body .content { + width: calc(100% - 60px); + left: 200px; + } + + .profile-body .content nav .logoName { + font-size: 17px; + } + + .profile-body .content nav .profile .img { + font-size: 20px; + } +} diff --git a/src/Pages/Profile/ProfileHeader.jsx b/src/Pages/Profile/ProfileHeader.jsx new file mode 100644 index 00000000..4552f6ef --- /dev/null +++ b/src/Pages/Profile/ProfileHeader.jsx @@ -0,0 +1,113 @@ +import React, { useEffect, useState } from "react"; +import "./Profile.css"; +import { Link, useNavigate } from "react-router-dom"; +import { signOut } from "firebase/auth"; +import { auth } from "../../firebase/auth"; +export default function ProfileHeader({ children }) { + const navigate = useNavigate(); + const [sidebarClosed, setSidebarClosed] = useState(window.innerWidth < 768); + + useEffect(() => { + const handleResize = () => { + setSidebarClosed(window.innerWidth < 768); + }; + + window.addEventListener("resize", handleResize); + + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + useEffect(() => { + const sideLinks = document.querySelectorAll( + ".sidebar .side-menu li a:not(.logout)" + ); + const handleLinkClick = (item) => { + sideLinks.forEach((i) => i.parentElement.classList.remove("active")); + item.parentElement.classList.add("active"); + }; + + sideLinks.forEach((item) => { + item.addEventListener("click", () => handleLinkClick(item)); + }); + + return () => { + sideLinks.forEach((item) => { + item.removeEventListener("click", () => handleLinkClick(item)); + }); + }; + }, []); + + const toggleSidebar = () => { + setSidebarClosed(!sidebarClosed); + }; + + const handleSignOut = () => { + signOut(auth) + .then(() => { + navigate("/"); + }) + .catch((err) => { + alert(err.message); + }); + }; + + return ( + <> +
+ + {/* logo */} + +
+ CounSellor +
+ + + +
+
+ + +
{children}
+
+ + ); +} diff --git a/src/Pages/Profile/index.jsx b/src/Pages/Profile/index.jsx new file mode 100644 index 00000000..741b46ee --- /dev/null +++ b/src/Pages/Profile/index.jsx @@ -0,0 +1,25 @@ +import React, { useEffect } from "react"; +import "./Profile.css"; +import SocialProfile from "../../components/ProfileComponent/SocialProfile"; +import ProfileCard from "../../components/ProfileComponent/ProfileCard"; +import ProfileHeader from "./ProfileHeader"; +import { auth } from "../../firebase/auth"; +export default function ProfilePage() { + useEffect(() => { + auth.onAuthStateChanged((user) => { + if (user) { + console.log(""); + } else if (!user) { + navigate("/"); + } + }); + }, []); + return ( +
+ + + + +
+ ); +} diff --git a/src/assets/college.png b/src/assets/college.png new file mode 100644 index 00000000..11be85da Binary files /dev/null and b/src/assets/college.png differ diff --git a/src/assets/collegehover.png b/src/assets/collegehover.png new file mode 100644 index 00000000..0879cf0c Binary files /dev/null and b/src/assets/collegehover.png differ diff --git a/src/assets/explore.png b/src/assets/explore.png new file mode 100644 index 00000000..e2bdccd5 Binary files /dev/null and b/src/assets/explore.png differ diff --git a/src/assets/explorehover.png b/src/assets/explorehover.png new file mode 100644 index 00000000..6ab653ad Binary files /dev/null and b/src/assets/explorehover.png differ diff --git a/src/assets/life.png b/src/assets/life.png new file mode 100644 index 00000000..84c6d741 Binary files /dev/null and b/src/assets/life.png differ diff --git a/src/assets/lifehover.png b/src/assets/lifehover.png new file mode 100644 index 00000000..bcea52cb Binary files /dev/null and b/src/assets/lifehover.png differ diff --git a/src/assets/stream.png b/src/assets/stream.png new file mode 100644 index 00000000..dc6ef1f4 Binary files /dev/null and b/src/assets/stream.png differ diff --git a/src/assets/streamhover.png b/src/assets/streamhover.png new file mode 100644 index 00000000..87a48d21 Binary files /dev/null and b/src/assets/streamhover.png differ diff --git a/src/components/About/About.css b/src/components/About/About.css index 8af4c3fc..6888c0bb 100644 --- a/src/components/About/About.css +++ b/src/components/About/About.css @@ -1,3 +1,9 @@ +@import url('https://fonts.googleapis.com/css2?family=ABeeZee:ital@0;1&display=swap'); + +* { + font-family: "ABeeZee", sans-serif; +} + @keyframes moveInLeft { 0% { opacity: 0; @@ -399,7 +405,7 @@ body { .composition { position: relative; } -.composition__photo { +.composition__grp { width: 55%; box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.4); border-radius: 2px; @@ -408,25 +414,25 @@ body { transition: all 0.2s; outline-offset: 2rem; } -.composition__photo--p1 { +.composition__grp--p1 { left: 0; top: -2rem; } -.composition__photo--p2 { +.composition__grp--p2 { right: 0; top: 2rem; } -.composition__photo--p3 { +.composition__grp--p3 { left: 20%; top: 10rem; } -.composition__photo:hover { +.composition__grp:hover { outline: 1.5rem solid #3b4bb1; transform: scale(1.05) translateY(-0.5rem); box-shadow: 0 2.5rem 4rem rgba(0, 0, 0, 0.5); z-index: 20; } -.composition:hover .composition__photo:not(:hover) { +.composition:hover .composition__grp:not(:hover) { transform: scale(0.95); } @@ -994,3 +1000,113 @@ body { width: 50%; padding: 6rem; } /*# sourceMappingURL=main.css.map */ + + +/* About us Section Features */ + +.about-us-block { + display: flex; + justify-content: space-evenly; +} + +.about-us-community, .about-us-product, .about-us-event, .about-us-location { + display: flex; + flex-direction: column; + gap: 1rem; + width: 38%; + background: transparent; + height: 17rem; + border: 1px solid rgba(206, 212, 218, 1); + border-radius: 8px; + margin-bottom: 21px; +} + +.about-us-community { + border: 2px solid rgb(26, 99, 245); +} + +.about-us-community:hover { + background: rgb(26, 99, 245); + color: white; +} + +.about-us-location { + border: 2px solid rgb(26, 99, 245); +} + +.about-us-location:hover { + background: rgb(26, 99, 245); + color: white; +} + +.about-us-product { + border: 2px solid rgb(26, 99, 245); +} + +.about-us-product:hover { + background: rgb(26, 99, 245); + color: white; +} + +.about-us-event { + border: 2px solid rgb(26, 99, 245); +} + +.about-us-event:hover { + background: rgb(26, 99, 245); + color: white; +} + +.about-us-blk-text { + font-size: 20px; + font-weight: 600; + line-height: 30px; + letter-spacing: 0em; + text-align: left; + margin-top: 1rem; +} + +.about-us-blk-para { + font-size: 16px; + font-weight: 400; + font-weight: 400; + line-height: 25px; + letter-spacing: 0em; + text-align: left; + margin-left: 1rem; + margin-right: 1rem; +} + +@media only screen and (max-width: 768px) { + .about-us-block { + flex-direction: column; + justify-content: center; + align-items: center; + } + + .about-us-community, .about-us-event, .about-us-location, .about-us-product { + width: 90%; + height: 100%; + padding: 0.5rem; + } +} + +@media only screen and (max-width: 1020px) { + .about-us-block { + flex-direction: column; + justify-content: center; + align-items: center; + } + + .about-us-community, .about-us-event, .about-us-location, .about-us-product { + width: 90% !important; + height: 100%; + padding: 0.5rem; + } +} + +@media only screen and (max-width: 1250px) { + .about-us-community, .about-us-event, .about-us-location, .about-us-product { + width: 45%; + } +} diff --git a/src/components/About/About.jsx b/src/components/About/About.jsx index 8121e51c..24d88991 100644 --- a/src/components/About/About.jsx +++ b/src/components/About/About.jsx @@ -1,409 +1,24 @@ -import Logo from "../../assets/logo.webp"; -import React, { useEffect, useState } from "react"; -import { signOut, onAuthStateChanged } from "firebase/auth"; -import { auth } from "../../firebase/auth"; -import { useNavigate } from "react-router-dom"; import Footer from "../Footer/Footer"; import "./About.css"; - +import Navbar from "./Navbar"; +import Banner from "./Banner"; +import SectionAbout from "./SectionAbout"; +import SectionFeatures from "./SectionFeatures"; +import SectionStories from "./SectionStories"; +import SectionTours from "./SectionTours"; + +//About Us const About = () => { - const navigate = useNavigate(); - const [user, setUser] = useState(null); - - useEffect(() => { - auth.onAuthStateChanged((user) => { - if (user) { - setUser(user); - } - }); - }, []); - - const handleSignOut = () => { - signOut(auth) - .then(() => { - navigate("/"); - }) - .catch((err) => { - alert(err.message); - }); - }; - - const [menuOpen, setMenuOpen] = useState(false); - - const toggleMenu = () => { - setMenuOpen(!menuOpen); - }; return ( - <> -
- - -
-
-
-

- ABOUT US -

- - - Discover Who We Are? - -
-
- -
-
-
-

- Behold For What We Present You -

-
- -
-
-

- Our mission? To bestow upon students the gift of wisdom, - aiding them in their quest for undergraduate enlightenment. - Prepare to witness the extraordinary! -

-

- Within these virtual walls, students will uncover a treasure - trove of streams and branches, carefully curated to match - their very souls, their passions, and their wildest career - aspirations. No stone shall be left unturned, no path left - unexplored! But wait, dear traveler, there's more! We bring - forth the whispers of the present, the tales of those who - have embarked on this hallowed journey before you. Hear the - unfiltered truths, the real-life sagas, as they guide you - towards the perfect college. For in the realm of education, - one size does not fit all. Let your desires and preferences - reign supreme! -

-
- -
-
- photo 1 - photo 2 - photo 3 -
-
-
-
- -
-
-
-
- -

- Explore the World -

-

- We let you know the worldwide college options which fits - for you -

-
-
- -
-
- -

- Right Stream -

-

- Choosing Right stream is necessary for your career growth -

-
-
- -
-
- -

- Right College -

-

- Choosing Right College is necessary for your career growth -

-
-
- -
-
- -

- Live Your Life -

-

- Choose the college which you dreamt all your life. - Kudos!!!! -

-
-
-
-
- -
-
-

Happy Statistics

-
- -
-
-
-
-
 
-

- - Indian Colleges - -

-
-
    -
  • 3000+
  • -
  • Up to 500 Students
  • -
  • 5 Guides
  • -
  • Choose Top Notch
  • -
  • Feedback: 5+ Stars
  • -
-
-
-
-
-
-

Explore Colleges

-

3000+

-
- - Explore Now! - -
-
-
-
-
-
-
-
 
-

- - American Colleges - -

-
-
    -
  • 300+
  • -
  • Up to 40 Students
  • -
  • 6 Guides
  • -
  • Fits Best For You
  • -
  • Feedback: 4+ Stars
  • -
-
-
-
-
-
-

Explore Colleges

-

300+

-
- - Explore Now! - -
-
-
-
-
-
-
-
 
-

- - Austrian Colleges - -

-
-
    -
  • 100+
  • -
  • Up to 15 Students
  • -
  • 3 Guides
  • -
  • Go Worldwide
  • -
  • Feedback: 4+ Stars
  • -
-
-
-
-
-
-

Explore Colleges

-

100+

-
- - Explore Now! - -
-
-
-
-
- - -
- -
-
- -
-
-

- We Make People Genuinely Happy -

-
- -
-
-
- Person on a Tour -
Mary Smith
-
- -
-

- I got the best college with their guidance -

-

- Lorem ipsum dolor sit amet consectetur adipisicing elit. - Vitae voluptatibus accusantium esse quibusdam repellat - molestiae a modi non, incidunt nisi minus labore quas - blanditiis mollitia autem sapiente sint laboriosam fugiat? -

-
-
-
- -
-
-
- Person on a Tour -
Jack Wilson
-
- -
-

- Wow! My life is completely different now -

-

- Lorem ipsum dolor sit amet consectetur adipisicing elit. - Vitae voluptatibus accusantium esse quibusdam repellat - molestiae a modi non, incidunt nisi minus labore quas - blanditiis mollitia autem sapiente sint laboriosam fugiat? -

-
-
-
-
-
-
- - {/*
-

About Us

-

For the Students, By the Students

-

- Behold, for we present to you our awe-inspiring web application, crafted with the mystical powers of ReactJS. Our mission? To bestow upon students the gift of wisdom, aiding them in their quest for undergraduate enlightenment. Prepare to witness the extraordinary! -

-

- -Within these virtual walls, students will uncover a treasure trove of streams and branches, carefully curated to match their very souls, their passions, and their wildest career aspirations. No stone shall be left unturned, no path left unexplored! - -But wait, dear traveler, there's more! We bring forth the whispers of the present, the tales of those who have embarked on this hallowed journey before you. Hear the unfiltered truths, the real-life sagas, as they guide you towards the perfect college. For in the realm of education, one size does not fit all. Let your desires and preferences reign supreme!

-

- -With our divine knowledge at your fingertips, you shall seize the undergraduate throne and forge a destiny unlike any other. Unleash the power within, embrace the possibilities, and embark on the path to triumph. -

-

-Enter our realm, intrepid adventurer, and let us be your guiding light in the boundless universe of higher education. Together, we shall illuminate your future with brilliance and triumph! -

-
*/} - -
-
- +
+ + + + + + +
+
); }; diff --git a/src/components/About/Banner.jsx b/src/components/About/Banner.jsx new file mode 100644 index 00000000..f21017fb --- /dev/null +++ b/src/components/About/Banner.jsx @@ -0,0 +1,20 @@ +import "./About.css"; + +// Banner Component +const Banner = () => { + return ( +
+
+

+ ABOUT US +

+ + +
+
+ ); +}; + +export default Banner; diff --git a/src/components/About/Navbar.jsx b/src/components/About/Navbar.jsx new file mode 100644 index 00000000..4a26c68c --- /dev/null +++ b/src/components/About/Navbar.jsx @@ -0,0 +1,138 @@ +import { useEffect, useState, useCallback } from 'react'; +import { signOut } from "firebase/auth"; +import Logo from "../../assets/logo.webp"; +import "./About.css"; +import { auth } from "../../firebase/auth"; +import { useNavigate } from "react-router-dom"; + +// Signout function +const signOutUser = (navigate, setError) => { + signOut(auth) + .then(() => { + navigate("/"); + }) + .catch((err) => { + setError(err.message); + }); +}; + +// Toggle menu function +const toggleNavMenu = (setMenuOpen, menuOpen) => { + setMenuOpen(!menuOpen); +}; + +// Navbar Component +const Navbar = () => { + const navigate = useNavigate(); + const [user, setUser] = useState(null); + const [menuOpen, setMenuOpen] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + auth.onAuthStateChanged((authuser) => { + if (authuser) { + setUser(authuser); + } + }); + }, []); + + // Define callbacks using useCallback + const handleSignOutCallback = useCallback(() => { + signOutUser(navigate, setError); + }, [navigate, setError]); + + // Toggle menu callback + const toggleMenuCallback = useCallback(() => { + toggleNavMenu(setMenuOpen, menuOpen); + }, [setMenuOpen, menuOpen]); + + // Define handleKeyPress outside of JSX + const handleKeyPress = useCallback((event) => { + if (event.key === 'Enter' || event.key === ' ') { + toggleMenuCallback(); + } + }, [toggleMenuCallback]); + + return ( + + ); +}; + +// Logo Component +const LogoSection = () => ( +
+ Logo +
+); + +// Menu Section Component +const MenuSection = ({ user, handleSignOut, menuOpen }) => ( +
+ +
+); + +// MenuItem Component +const MenuItem = ({ href, dot, children }) => ( +
  • + {children} +
  • +); + +// Hamburger Section Component +const HamburgerSection = ({ toggleMenu, menuOpen, handleKeyPress }) => ( +
    + {[1, 2, 3].map((index) => ( +
    + ))} +
    +); + +// Error Section Component +const ErrorSection = ({ error }) =>
    {error}
    ; + +export default Navbar; diff --git a/src/components/About/SectionAbout.jsx b/src/components/About/SectionAbout.jsx new file mode 100644 index 00000000..47a3ec4f --- /dev/null +++ b/src/components/About/SectionAbout.jsx @@ -0,0 +1,59 @@ +import "./About.css"; + +//Section About +const SectionAbout = () => { + return ( +
    +
    +

    + Behold For What We Present You +

    +
    + +
    +
    +

    + Our mission? To bestow upon students the gift of wisdom, + aiding them in their quest for undergraduate enlightenment. + Prepare to witness the extraordinary! +

    +

    + Within these virtual walls, students will uncover a treasure + trove of streams and branches, carefully curated to match + their very souls, their passions, and their wildest career + aspirations. No stone shall be left unturned, no path left + unexplored! But wait, dear traveler, there's more! We bring + forth the whispers of the present, the tales of those who + have embarked on this hallowed journey before you. Hear the + unfiltered truths, the real-life sagas, as they guide you + towards the perfect college. For in the realm of education, + one size does not fit all. Let your desires and preferences + reign supreme! +

    +
    + +
    +
    + Group 1 + Group 2 + Group 3 +
    +
    +
    +
    + ) +} + +export default SectionAbout \ No newline at end of file diff --git a/src/components/About/SectionFeatures.jsx b/src/components/About/SectionFeatures.jsx new file mode 100644 index 00000000..f0cec64c --- /dev/null +++ b/src/components/About/SectionFeatures.jsx @@ -0,0 +1,98 @@ +import { useState, useCallback } from 'react'; +import explore from '../../assets/explore.png'; +import explorehover from '../../assets/explorehover.png'; +import college from '../../assets/college.png'; +import collegehover from '../../assets/collegehover.png'; +import stream from '../../assets/stream.png'; +import streamhover from '../../assets/streamhover.png'; +import life from '../../assets/life.png'; +import lifehover from '../../assets/lifehover.png'; + +// Feature Button Component +const FeatureButton = ({ className, image, hoverImage, altText, title, description }) => { + const [hover, setHover] = useState(false); + + //mouseover + const handleMouseOver = useCallback(() => { + setHover(true); + }, []); + + //mouseleave + const handleMouseLeave = useCallback(() => { + setHover(false); + }, []); + + //handle focus + const handleFocus = useCallback(() => { + setHover(true); + }, []); + + //handle blur + const handleBlur = useCallback(() => { + setHover(false); + }, []); + + return ( + + ); +}; + +// Section Features Component +const SectionFeatures = () => { + return ( +
    +
    +
    + + +
    +
    + + +
    +
    +
    + ); +}; + +export default SectionFeatures; diff --git a/src/components/About/SectionStories.jsx b/src/components/About/SectionStories.jsx new file mode 100644 index 00000000..5bf97841 --- /dev/null +++ b/src/components/About/SectionStories.jsx @@ -0,0 +1,55 @@ +import "./About.css"; + +// Individual Story Component +const Story = ({ imgSrc, altText, caption, heading, text }) => ( +
    +
    + {altText} +
    {caption}
    +
    +
    +

    {heading}

    +

    {text}

    +
    +
    +); + +// Section Stories Component +const SectionStories = () => ( +
    +
    + +
    +
    +

    + We Make People Genuinely Happy +

    +
    + +
    + +
    + +
    + +
    +
    +); + +export default SectionStories; diff --git a/src/components/About/SectionTours.jsx b/src/components/About/SectionTours.jsx new file mode 100644 index 00000000..b8244e8a --- /dev/null +++ b/src/components/About/SectionTours.jsx @@ -0,0 +1,110 @@ +import "./About.css"; + +// Card Front Component +const CardFront = ({ pictureClass, heading, headingSpan, details }) => ( +
    +
     
    +

    + + {heading} + +

    +
    +
      + {details.map((detail) => ( +
    • {detail}
    • + ))} +
    +
    +
    +); + +// Card Back Component +const CardBack = ({ className, priceValue }) => ( +
    +
    +
    +

    Explore Colleges

    +

    {priceValue}

    +
    + + Explore Now! + +
    +
    +); + +// Card Component +const Card = ({ className, heading, headingSpan, pictureClass, details, priceValue }) => ( +
    +
    + + +
    +
    +); + +// Section Tours Component +const SectionTours = () => ( +
    +
    +

    Happy Statistics

    +
    + +
    + + + +
    + +
    + + Discover All + +
    +
    +); + +export default SectionTours; diff --git a/src/components/Contact/Contact.css b/src/components/Contact/Contact.css index 56302296..2689cd73 100644 --- a/src/components/Contact/Contact.css +++ b/src/components/Contact/Contact.css @@ -54,6 +54,7 @@ border-radius: 10px 0 0 10px; } + .contact-form-wrapper { background-color: #ffffff8f; border-radius: 0 10px 10px 0; @@ -124,6 +125,7 @@ } .cform-item { + margin-top: 15px; position: relative; } @@ -152,25 +154,30 @@ } #m-textarea { width: 100%; + height: 90px; outline: 0; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 20px; padding: 12px; font-size: clamp(15px, 1.5vw, 18px); + resize: none; } - - -.cinput:focus+.clabel, -.cinput:valid+.clabel, -.ctextarea:focus+.clabel, -.ctextarea:valid+.clabel { - font-size: clamp(13px, 1.3vw, 16px); - color: #777; - top: -20px; - transition: all .225s ease; + #m-textarea.focused::label { + color: #f7f1f1; + background: #1f2e43; } +.cinput:focus + .clabel, +.cinput:valid + .clabel, +.ctextarea:focus + .clabel, +.ctextarea:valid + .clabel { + font-size: clamp(13px, 1.3vw, 16px); + color: #777; + top: -20px; + transition: all .225s ease; +} + .csubmit-btn { background-color: #fd917e; diff --git a/src/components/Contact/Contact.jsx b/src/components/Contact/Contact.jsx index 37fbd6b1..aadb9c8d 100644 --- a/src/components/Contact/Contact.jsx +++ b/src/components/Contact/Contact.jsx @@ -88,10 +88,10 @@ const Contact = () => {
    - - + +
    - + diff --git a/src/components/Dashboard/Dashboard.css b/src/components/Dashboard/Dashboard.css index a592b818..bc10ad49 100644 --- a/src/components/Dashboard/Dashboard.css +++ b/src/components/Dashboard/Dashboard.css @@ -291,7 +291,7 @@ .search { width: 70vw; - background-color: #5CB6F9; + background-color: #76c6f5; padding: 10px; border-radius: 15px; margin: 0 auto; @@ -305,34 +305,35 @@ top: 1px; right: -25px; border-left: 2px solid #306094; - height: 70px; + height: 72px; } .search img { - width: 30px; - height: 36px; + width: 35px; + height: 39px; position: relative; top: 18px; - right: -10px; + right: -6px; color: #306094; } .search input { width: 78%; height: 70px; - background-color: #5CB6F9; + background-color: #e4f1fe; appearance: none; border: none; + border-radius: 15px; font-size: 25px; font-family: 'ABeeZee'; - color: #F4F6FC; + color: #25376e; padding-left: 35px; margin-left: 40px; margin-right: 15px; } .search input::placeholder { - color: white; + color: rgb(198, 190, 190); } .search button { diff --git a/src/components/Dashboard/Dashboard.jsx b/src/components/Dashboard/Dashboard.jsx index fa34627a..8cda7551 100644 --- a/src/components/Dashboard/Dashboard.jsx +++ b/src/components/Dashboard/Dashboard.jsx @@ -1,19 +1,19 @@ -import React, { useEffect, useState, useCallback } from 'react'; -import './Dashboard.css' -import { useNavigate, NavLink } from 'react-router-dom' -import Logo from '../../assets/logo.webp' +import React, { useEffect, useState, useCallback } from "react"; +import "./Dashboard.css"; +import { useNavigate, NavLink, Link } from "react-router-dom"; +import Logo from "../../assets/logo.webp"; import { signOut, onAuthStateChanged } from "firebase/auth"; import { auth } from "../../firebase/auth"; import Footer from "../Footer/Footer"; -import collegesData from './colleges.json'; +import collegesData from "./colleges.json"; import ScrollToTop from "react-scroll-to-top"; -import CollegeCard from './CollegeCard'; +import CollegeCard from "./CollegeCard"; const Dashboard = () => { const navigate = useNavigate(); const [menuOpen, setMenuOpen] = useState(false); - const [searchTerm, setSearchTerm] = useState(''); + const [searchTerm, setSearchTerm] = useState(""); const [filteredColleges, setFilteredColleges] = useState(collegesData); useEffect(() => { auth.onAuthStateChanged((user) => { @@ -25,9 +25,10 @@ const Dashboard = () => { }); }, []); useEffect(() => { - const results = collegesData.filter(college => - college.name.toLowerCase().includes(searchTerm.toLowerCase()) || - college.location.toLowerCase().includes(searchTerm.toLowerCase()) + const results = collegesData.filter( + (college) => + college.name.toLowerCase().includes(searchTerm.toLowerCase()) || + college.location.toLowerCase().includes(searchTerm.toLowerCase()) ); setFilteredColleges(results); }, [searchTerm]); @@ -42,17 +43,16 @@ const Dashboard = () => { }); }; - - - const handleCollegeClick = useCallback((college) => { - navigate(`/college/${college.id}`); - }, [filteredColleges]); - + const handleCollegeClick = useCallback( + (college) => { + navigate(`/college/${college.id}`); + }, + [filteredColleges] + ); const toggleMenu = useCallback(() => { setMenuOpen(!menuOpen); - } - ) + }); const handleSearchChange = useCallback((e) => { setSearchTerm(e.target.value); @@ -82,30 +82,52 @@ window.addEventListener("scroll", setFixed) return ( <>
    - -
    ); - }; export default Dashboard; diff --git a/src/components/ProfileComponent/ProfileCard.css b/src/components/ProfileComponent/ProfileCard.css new file mode 100644 index 00000000..a8c01152 --- /dev/null +++ b/src/components/ProfileComponent/ProfileCard.css @@ -0,0 +1,234 @@ +.profile-card-container { + max-width: 100%; + margin: 0 auto; + padding: 20px; + border-radius: 10px; + position: relative; + min-height: 60vh; +} + +.greeting { + background-color: #28a745; + border-radius: 10px; + padding: 20px; + margin-bottom: 20px; + color: white; + display: flex; + text-align: left; + justify-content: space-between; +} + +.greeting h1 { + font-size: 25px; +} + +.greeting p { + margin: 0; + margin-top: 5px; + font-size: 14px; +} + +.profile-card-content { + width: calc(100% - 320px); + text-align: left; + padding-left: 10px; +} + +.profile-card img { + width: 100px; + border-radius: 100%; +} + +.upcoming-events { + text-align: left; + width: 100%; + height: 100%; +} + +.upcoming-events h2 { + margin-top: 0; + font-size: 19px; + margin-bottom: 5px; +} + +.calendar { + display: flex; + align-items: center; + justify-content: flex-start; + flex-wrap: wrap; + margin-bottom: 10px; +} + +.calendar-date { + position: relative; + padding: 10px; + background-color: #f5f5f5; + border-radius: 5px; + margin: 5px; + text-align: center; + width: 50px; + font-weight: 700; +} +.calendar-date span { + display: block; +} +.calendar-date.active { + position: relative; + background-color: #000000; + color: white; +} +.calendar-date.active::after { + content: ""; + position: absolute; + top: 10%; + right: 10%; + width: 5px; + height: 5px; + background: rgb(64, 255, 64); + border-radius: 50%; +} +.next-event { + margin: 0; + font-size: 14px; +} + +.profile-card-content .profile-details { + margin: 20px 0; +} +.profile-card-content .profile-details h2 { + font-size: 20px; +} +.profile-card-content .profile-details p { + font-size: 14px; + margin: 5px 0; +} + +.profile-card-content .profile-details .about-info { + display: flex; + gap: 5px; + align-items: center; +} + +.profile-card-content .profile-details .about-info h3 { + font-size: 13px; +} +.profile-card-content .profile-details .about-info p { + font-size: 14px; +} + +.profile-summary { + display: flex; + justify-content: center; + align-items: center; + width: 250px; + position: absolute; + top: 50px; + right: 5%; +} + +.profile-card { + background-color: #ffffff; + padding: 10px; + border-radius: 15px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + text-align: center; + width: 300px; +} + +.profile-card .bxs-edit { + position: absolute; + font-size: 25px; + right: 7%; + cursor: pointer; +} + +.profile-image { + width: 100px; + height: 100px; + border-radius: 50%; + object-fit: cover; + border: 0.5px solid lightblue; +} + +.profile-card h3 { + margin: 10px 0 5px 0; + font-size: 22px; + color: #333; +} + +.profile-card .title { + margin: 5px 0; + font-size: 16px; + color: #666; +} + +.profile-card .role { + margin: 5px 0 15px 0; + font-size: 16px; + color: #007bff; +} + +.skills-section { + border-top: 0.5px solid rgba(21, 21, 21, 0.555); + text-align: left; + margin-top: 10px; +} + +.skills-section h2 { + margin-top: 5px; + font-size: 18px; + color: #333; + margin-bottom: 10px; +} + +.skills-section ul { + list-style-type: none; + padding: 0; + display: flex; + flex-wrap: wrap; + gap: 5px; +} + +.skills-section li { + background-color: #f0f0f0; + border-radius: 5px; + padding: 2px 5px; + font-size: 10px; + color: #333; +} + +@media screen and (max-width: 650px) { + .profile-summary { + width: 60%; + position: absolute; + top: 150px; + right: 50%; + transform: translateX(50%); + } + .profile-card { + width: 100%; + } + + .profile-card-content { + width: 100%; + margin-top: 350px; + } +} + +@media screen and (max-width: 450px) { + .profile-summary { + width: 80%; + position: absolute; + top: 170px; + right: 50%; + transform: translateX(50%); + } + .profile-card { + width: 100%; + } + + .profile-card-content { + width: 100%; + margin-top: 350px; + } +} diff --git a/src/components/ProfileComponent/ProfileCard.jsx b/src/components/ProfileComponent/ProfileCard.jsx new file mode 100644 index 00000000..97c08055 --- /dev/null +++ b/src/components/ProfileComponent/ProfileCard.jsx @@ -0,0 +1,110 @@ +import React, { useState, useEffect } from "react"; +import "./ProfileCard.css"; + +const ProfileCard = () => { + const [dates, setDates] = useState([]); + + useEffect(() => { + const generateDates = () => { + const result = []; + const currentDate = new Date(); + + for (let i = 0; i < 23; i++) { + const date = new Date(); + date.setDate(currentDate.getDate() + i); + result.push({ + day: date.getDate(), + weekDay: date.toLocaleString("default", { weekday: "short" }), + isActive: i === 9, // set 10th date as active for demonstration + }); + } + + setDates(result); + }; + + generateDates(); + }, []); + + return ( +
    +
    +
    +

    Hello, Alex!

    +

    + Your Profile is updated here. Dates, counselling and your Skills are + all in one tap. +

    +
    +
    +
    +
    +

    Upcoming Events

    +
    + {dates.map((date, index) => ( +
    + {date.day} {date.weekDay} +
    + ))} +
    +

    + Next counselling: 22.04.2021 - Stay Connected +

    +
    +
    +
    +

    About

    +

    + Lorem ipsum dolor sit amet consectetur adipisicing elit. Aperiam + labore distinctio optio nobis aut. Voluptatum laborum dolor fugit + necessitatibus corrupti aspernatur, perferendis obcaecati eaque + dolorem. Sint iusto animi minima delectus. +

    +
    +
    +

    Email :

    counsellor@gmail.com

    +
    +
    +

    Phone :

    +918795768574

    +
    +
    +

    Gender :

    Male

    +
    +
    +

    BirthDate :

    21-1-2000

    +
    +
    +

    College :

    IIT Bombay

    +
    +
    +
    +
    +
    + + Profile +

    Alex Foam

    +

    IIT Bombay

    +

    Student

    +
    +

    Skills

    +
      +
    • #JavaScript
    • +
    • #MongoDB
    • +
    • #Node.js
    • +
    • #HTML5
    • +
    • #CSS3
    • +
    +
    +
    +
    +
    + ); +}; + +export default ProfileCard; diff --git a/src/components/ProfileComponent/SocialProfile.css b/src/components/ProfileComponent/SocialProfile.css new file mode 100644 index 00000000..d4eccf21 --- /dev/null +++ b/src/components/ProfileComponent/SocialProfile.css @@ -0,0 +1,173 @@ +.social-profile-container { + max-width: 90%; + margin: 0 auto; + padding: 20px 30px; + background: rgba(173, 216, 230, 0.13); + border-radius: 10px; +} + +.social-profile-container .social-profile-header { + display: flex; + align-items: center; + margin-bottom: 40px; + justify-content: space-between; +} +.social-profile-header .heading h2 { + font-size: 20px; + text-align: left; +} +.social-profile-header.heading p { + font-size: 14px; + text-align: left; +} +.social-profile-header button { + padding: 5px 6px; + background: rgb(0, 183, 255); + border: 1px solid #ffff; + border-radius: 5px; + font-weight: 400; + color: #fff; + font-size: 15px; + text-transform: capitalize; +} + +.profile-list { + margin-bottom: 20px; +} + +.profile-item { + display: flex; + align-items: center; + margin-bottom: 10px; +} +.profile-item .icon-details { + margin-right: 10px; + display: flex; + justify-content: stretch; + gap: 5px; + align-items: center; + min-width: 150px; +} +.profile-item .icon-details h4 { + font-size: 16px; + font-weight: 500; + text-align: left; + flex: 1; +} + +.profile-item .icon-details span { + font-size: 19px; + font-weight: 900; +} +.profile-item .icon-details i { + font-size: 25px; + width: 29px; + margin-right: 5px; +} +.add-profile { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; +} + +.profile-item input, +select { + width: 100%; + padding: 8px; + outline: none; +} + +.profile-item button { + background-color: #f44336; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + width: 40px !important; + + padding: 5px; + padding-left: 12px; + margin: 0 8px; +} + +.profile-item button .btn-icon { + font-size: 18px; +} + +.profile-item button:hover { + background-color: #d32f2f; +} +.profile-item button.Edit { + background: rgb(0, 128, 255); +} +.profile-item button.Edit:hover { + background: rgb(0, 76, 255); +} +.profile-item button.Save { + background: #4caf50; +} +.profile-item button.Save:hover { + background: rgb(0, 91, 0); +} +.add-profile input { + display: block; + width: 100%; + padding: 8px; + margin-bottom: 10px; +} + +.add-btn { + padding: 10px 15px; + background-color: #4caf50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.add-btn:hover { + background-color: #45a049; +} +.btns { + display: flex; +} + +@media (max-width: 550px) { + .social-profile-container { + padding: 10px 15px; + } + .social-profile-container .social-profile-header { + flex-direction: column; + align-items: flex-start; + } + .social-profile-header .heading h2 { + font-size: 18px; + } + .social-profile-header .heading p { + font-size: 12px; + } + .social-profile-header button { + margin-top: 10px; + } + .profile-item { + flex-direction: column; + align-items: flex-start; + } + .profile-item .icon-details { + margin-right: 0; + margin-bottom: 5px; + min-width: auto; + } + .profile-item button { + width: 100%; + margin: 5px 0; + } + .btns { + gap: 10px; + } +} diff --git a/src/components/ProfileComponent/SocialProfile.jsx b/src/components/ProfileComponent/SocialProfile.jsx new file mode 100644 index 00000000..d7632f22 --- /dev/null +++ b/src/components/ProfileComponent/SocialProfile.jsx @@ -0,0 +1,173 @@ +import React, { useState } from "react"; +import "./SocialProfile.css"; + +const initialProfiles = [ + { + id: 1, + name: "Twitter", + url: "https://twitter.com/arafatnayeem94", + }, + { + id: 2, + name: "LinkedIn", + url: "https://www.linkedin.com/in/arafatnayeem/", + }, + { + id: 3, + name: "Behance", + url: "https://www.behance.net/arafatnayeem", + }, +]; + +const socialMediaOptions = [ + "Twitter", + "LinkedIn", + "Behance", + "Facebook", + "Instagram", + "Github", + "LeetCode", + "CodeForces", + "HackerEarth", + "HackerRank", +]; + +const SocialProfile = () => { + const [profiles, setProfiles] = useState(initialProfiles); + const [newProfile, setNewProfile] = useState({ name: "", url: "" }); + const [isEditing, setIsEditing] = useState(false); + const [editingId, setEditingId] = useState(null); + const [showNewProfileForm, setShowNewProfileForm] = useState(false); + + const handleInputChange = (e) => { + const { name, value } = e.target; + setNewProfile({ ...newProfile, [name]: value }); + }; + + const handleAddProfile = () => { + if (!newProfile.name || !isValidUrl(newProfile.url)) { + alert("Please enter a valid profile name and URL starting with http"); + return; + } + setProfiles([...profiles, { ...newProfile, id: profiles.length + 1 }]); + setNewProfile({ name: "", url: "" }); + setShowNewProfileForm(false); + }; + + const handleProfileChange = (id, url) => { + setProfiles( + profiles.map((profile) => + profile.id === id ? { ...profile, url } : profile + ) + ); + }; + + const handleDeleteProfile = (id) => { + setProfiles(profiles.filter((profile) => profile.id !== id)); + }; + + const handleEditProfile = (id) => { + setEditingId(id); + setIsEditing(true); + }; + + const handleSaveProfile = () => { + setEditingId(null); + setIsEditing(false); + }; + + const handleUpdate = () => { + setIsEditing(!isEditing); + }; + + const isValidUrl = (url) => { + const regex = /^(http|https):\/\/[^ "]+$/; + return regex.test(url); + }; + + return ( +
    +
    +
    +

    Social Profile

    +

    You can update your social profile here

    +
    + +
    + +
    + {profiles.map((profile) => ( +
    +
    + +

    {profile.name.slice(0, 12)}

    + > +
    + handleProfileChange(profile.id, e.target.value)} + /> +
    + {isEditing && editingId === profile.id ? ( + + ) : ( + + )} + {isEditing && ( + + )} +
    +
    + ))} +
    + + {showNewProfileForm ? ( +
    + + + +
    + ) : ( + + )} +
    + ); +}; + +export default SocialProfile; diff --git a/src/index.jsx b/src/index.jsx index 4a68a0e3..15d13edf 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -2,7 +2,7 @@ import React, { Suspense } from "react"; import ReactDOM from "react-dom/client"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import App from "./App"; -import CollegePage from './components/CollegePage/CollegePage'; +import CollegePage from "./components/CollegePage/CollegePage"; import { About, Dashboard, @@ -14,6 +14,7 @@ import Loading from "./components/Loading/Loading"; import Login from "./components/Login/Login"; import "./index.css"; import Contact from "./components/Contact/Contact"; +import ProfilePage from "./Pages/Profile"; const router = createBrowserRouter([ { @@ -41,9 +42,9 @@ const router = createBrowserRouter([ element: , }, { - path: '/contact', - errorElement: , - element: + path: "/contact", + errorElement: , + element: , }, // { // path: '/login', @@ -61,12 +62,15 @@ const router = createBrowserRouter([ element: , }, { - path:"/college/:id" , + path: "/college/:id", errorElement: , - element: - - } - + element: , + }, + { + path: "/profile", + errorElement: , + element: , + }, ], }, ]);