Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor code and add PropTypes (SonarCloud Issues Fixed) #48

Merged
merged 1 commit into from
Dec 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/favicon.ico
Binary file not shown.
Binary file added public/favicon_io/android-chrome-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon_io/android-chrome-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon_io/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon_io/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon_io/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions public/favicon_io/site.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
5 changes: 5 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <link rel="apple-touch-icon" sizes="180x180" href="./favicon_io/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="./favicon_io/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="./favicon_io/favicon-16x16.png">
<link rel="manifest" href="./favicon_io/site.webmanifest"> -->
<link rel="icon" type="image/x-icon" href="./favicon.ico" />
<title>Personal Portfolio</title>
</head>
<body class="theme4">
Expand Down
5 changes: 5 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import PropTypes from "prop-types";

import Header from "./components/header/Header";
import Nav from "./components/nav/Nav";
Expand Down Expand Up @@ -33,6 +34,10 @@ const App = () => {
</Router>
);

RouterWrapper.propTypes = {
children: PropTypes.node.isRequired,
};

return (
<RouterWrapper>
{screenWidth > 600 ? (
Expand Down
10 changes: 10 additions & 0 deletions src/components/education/educationitem.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import PropTypes from "prop-types";
import { BsFillCalendarEventFill } from "react-icons/bs";

const EducationItem = (props) => {
Expand All @@ -17,3 +18,12 @@ const EducationItem = (props) => {
};

export default EducationItem;

EducationItem.propTypes = {
item: PropTypes.shape({
date: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
cgpa: PropTypes.string.isRequired,
}).isRequired,
};
33 changes: 30 additions & 3 deletions src/components/experience/experienceitem.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import { BsFillCalendarEventFill } from "react-icons/bs";
import { IoLocationSharp } from "react-icons/io5";
import { CiCircleChevDown, CiCircleChevUp } from "react-icons/ci";
Expand All @@ -10,14 +11,27 @@ const ExperienceItem = ({ item }) => {
setShow(!show);
};

// Function to handle keyboard events for accessibility
const handleKeyPress = (e) => {
if (e.key === "Enter" || e.key === " ") {
toggleDropdown();
}
};

return (
<div className="experience__item">
<h3 className="experience__date">
<span className="experience__date__icon">
<BsFillCalendarEventFill />
{item.date}
</span>
<div className="experience__dropdown" onClick={toggleDropdown}>
<div
className="experience__dropdown"
onClick={toggleDropdown}
onKeyPress={handleKeyPress}
role="button"
tabIndex={0}
>
<span className="experience__dropdown__icon">
{show ? <CiCircleChevUp /> : <CiCircleChevDown />}
</span>
Expand Down Expand Up @@ -49,20 +63,33 @@ const ExperienceItem = ({ item }) => {
<h4>What I did?</h4>
<ul>
{Object.values(item.description).map((desc, index) => (
<li key={index}>{desc}</li>
<li key={`desc-${index}-${desc}`}>{desc}</li>
))}
</ul>
</div>
<div className={`experience__item__skills ${show ? "active" : ""}`}>
<h4>Skills I Learned & Used!</h4>
<div className="experience__item__skills__list">
{item.skills.map((skill, index) => (
<span key={index}>{skill}</span>
<span key={`skill-${index}-${skill}`}>{skill}</span>
))}
</div>
</div>
</div>
);
};

ExperienceItem.propTypes = {
item: PropTypes.shape({
date: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
position: PropTypes.string.isRequired,
company: PropTypes.string.isRequired,
location: PropTypes.string.isRequired,
location_type: PropTypes.string.isRequired,
description: PropTypes.objectOf(PropTypes.string).isRequired,
skills: PropTypes.arrayOf(PropTypes.string).isRequired,
}).isRequired,
};

export default ExperienceItem;
9 changes: 5 additions & 4 deletions src/components/header/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react";
import "./header.css";
import CTA from "./CTA";
import CtaComponent from "./CTA"; // Renamed the import to CtaComponent
import ME from "../../assets/me.png";
import HeaderSocials from "./HeaderSocials";
import TW from "./TW";
import TwComponent from "./TW"; // Renamed the import to TwComponent

const Header = () => {
const words = [
Expand All @@ -14,15 +14,16 @@ const Header = () => {
"Open Source Contributor",
"Tech Enthusiast",
];

return (
<section className="header" id="header">
<div className="container header__container">
<h5>Hey Myself</h5>
<h1>Sagar Gupta</h1>
<h5 className="text-light">
I'm a <TW words={words} />
I'm a <TwComponent words={words} />
</h5>
<CTA />
<CtaComponent />
<HeaderSocials />
<div className="me">
<img src={ME} alt="me" />
Expand Down
10 changes: 8 additions & 2 deletions src/components/header/TW.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from "react";
import { Typewriter } from "react-simple-typewriter";
import "react-simple-typewriter/dist/index";
import PropTypes from "prop-types"; // Import PropTypes

const TW = (props) => {
const TW = ({ words }) => {
// Destructure words from props
return (
<Typewriter
words={props.words}
words={words}
loop
cursor
cursorStyle="_"
Expand All @@ -16,4 +18,8 @@ const TW = (props) => {
);
};

TW.propTypes = {
words: PropTypes.arrayOf(PropTypes.string).isRequired, // Define PropTypes for words
};

export default TW;
118 changes: 46 additions & 72 deletions src/components/nav/Nav.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "./nav.css";
import { RiHome3Line, RiServiceLine } from "react-icons/ri";
import { AiOutlineUser, AiOutlineMessage } from "react-icons/ai";
import { GoBriefcase, GoPencil } from "react-icons/go";
import { GiSuitcase, /* GiChatBubble,*/ GiSkills } from "react-icons/gi";
import { GiSuitcase, GiSkills } from "react-icons/gi";

const Nav = () => {
const location = useLocation();
Expand Down Expand Up @@ -32,13 +32,12 @@ const Nav = () => {
"skill",
"services",
"portfolio",
// "testimonial",
"contact",
];

const handleScroll = () => {
const scrollPosition = window.scrollY + 100;
const currentSection = sections.filter((section) => {
const currentSection = sections.find((section) => {
const sectionElement = document.getElementById(section);
if (sectionElement) {
const sectionTop = sectionElement.offsetTop;
Expand All @@ -47,86 +46,61 @@ const Nav = () => {
}
return false;
});
if (currentSection.length > 0) {
setActiveSection(currentSection[0]);
}
setActiveSection(currentSection || "");
};

window.onload = handleScroll;
window.addEventListener("scroll", handleScroll);

return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [screenWidth]);
}, []);

const navItems = [
{ to: "/", icon: <RiHome3Line />, alt: "Home" },
{ to: "/about", icon: <AiOutlineUser />, alt: "About" },
{ to: "/education", icon: <GoPencil />, alt: "Education" },
{ to: "/experience", icon: <GoBriefcase />, alt: "Experience" },
{ to: "/skill", icon: <GiSkills />, alt: "Skills" },
{ to: "/services", icon: <RiServiceLine />, alt: "Services" },
{ to: "/portfolio", icon: <GiSuitcase />, alt: "Portfolio" },
// { to: "/testimonial", icon: <GiChatBubble />, alt: "Testimonial" },
{ to: "/contact", icon: <AiOutlineMessage />, alt: "Contact" },
];

const sections = [
{ id: "header", alt: "Home", icon: <RiHome3Line /> },
{ id: "about", alt: "About", icon: <AiOutlineUser /> },
{ id: "education", alt: "Education", icon: <GoPencil /> },
{ id: "experience", alt: "Experience", icon: <GoBriefcase /> },
{ id: "skill", alt: "Skills", icon: <GiSkills /> },
{ id: "services", alt: "Services", icon: <RiServiceLine /> },
{ id: "portfolio", alt: "Portfolio", icon: <GiSuitcase /> },
// { id: "testimonial", alt: "Testimonial", icon: <GiChatBubble /> },
{ id: "contact", alt: "Contact", icon: <AiOutlineMessage /> },
{ to: "/", icon: <RiHome3Line />, label: "Home" },
{ to: "/about", icon: <AiOutlineUser />, label: "About" },
{ to: "/education", icon: <GoPencil />, label: "Education" },
{ to: "/experience", icon: <GoBriefcase />, label: "Experience" },
{ to: "/skill", icon: <GiSkills />, label: "Skills" },
{ to: "/services", icon: <RiServiceLine />, label: "Services" },
{ to: "/portfolio", icon: <GiSuitcase />, label: "Portfolio" },
{ to: "/contact", icon: <AiOutlineMessage />, label: "Contact" },
];

return (
<>
<nav className="nav">
<div className="nav__logo">
<Link to="/">
<span className="nav__logo--text">SG</span>
</Link>
</div>
<div className="nav__list">
{screenWidth > 600 ? (
<>
{navItems.map((item) => (
<Link
to={item.to}
className={location.pathname === item.to ? "active" : ""}
alt={item.alt}
key={item.to}
>
{item.icon}
</Link>
))}
</>
) : (
<>
{sections.map((section) => (
<button
alt={section.alt}
className={activeSection === section.id ? "active" : ""}
onClick={() =>
document
.getElementById(section.id)
.scrollIntoView({ behavior: "smooth" })
}
key={section.id}
>
{section.icon}
</button>
))}
</>
)}
</div>
</nav>
</>
<nav className="nav">
<div className="nav__logo">
<Link to="/" aria-label="Home">
<span className="nav__logo--text">SG</span>
</Link>
</div>
<div className="nav__list">
{screenWidth > 600
? navItems.map((item) => (
<Link
to={item.to}
className={location.pathname === item.to ? "active" : ""}
aria-label={item.label}
key={item.to}
>
{item.icon}
</Link>
))
: navItems.map((item) => (
<button
aria-label={item.label}
className={activeSection === item.to.substr(1) ? "active" : ""}
onClick={() =>
document
.getElementById(item.to.substr(1))
.scrollIntoView({ behavior: "smooth" })
}
key={item.to}
>
{item.icon}
</button>
))}
</div>
</nav>
);
};

Expand Down
Loading
Loading