diff --git a/src/App.js b/src/App.js index a99f38c84..7b4eda5a7 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React, { useState, useEffect } from "react"; import $ from "jquery"; import "./App.scss"; import Header from "./components/Header"; @@ -8,135 +8,109 @@ import Experience from "./components/Experience"; import Projects from "./components/Projects"; import Skills from "./components/Skills"; -class App extends Component { +function App(props) { + const [resumeData, setResumeData] = useState({}); + const [sharedData, setSharedData] = useState({}); + const [selectedLanguage, setSelectedLanguage] = useState( + window.$primaryLanguage + ); + document.title = sharedData.basic_info?.name; - constructor(props) { - super(); - this.state = { - foo: "bar", - resumeData: {}, - sharedData: {}, - }; - } - - applyPickedLanguage(pickedLanguage, oppositeLangIconId) { - this.swapCurrentlyActiveLanguage(oppositeLangIconId); + function applyPickedLanguage(pickedLanguage) { + setSelectedLanguage(pickedLanguage); document.documentElement.lang = pickedLanguage; var resumePath = document.documentElement.lang === window.$primaryLanguage ? `res_primaryLanguage.json` : `res_secondaryLanguage.json`; - this.loadResumeFromPath(resumePath); + loadResumeFromPath(resumePath); } - swapCurrentlyActiveLanguage(oppositeLangIconId) { - var pickedLangIconId = - oppositeLangIconId === window.$primaryLanguageIconId - ? window.$secondaryLanguageIconId - : window.$primaryLanguageIconId; - document - .getElementById(oppositeLangIconId) - .removeAttribute("filter", "brightness(40%)"); - document - .getElementById(pickedLangIconId) - .setAttribute("filter", "brightness(40%)"); - } - - componentDidMount() { - this.loadSharedData(); - this.applyPickedLanguage( - window.$primaryLanguage, - window.$secondaryLanguageIconId - ); - } + useEffect(() => { + loadSharedData(); + applyPickedLanguage(window.$primaryLanguage); + }, []); - loadResumeFromPath(path) { + function loadResumeFromPath(path) { $.ajax({ url: path, dataType: "json", cache: false, success: function (data) { - this.setState({ resumeData: data }); - }.bind(this), + setResumeData(data); + }, error: function (xhr, status, err) { alert(err); }, }); } - loadSharedData() { + function loadSharedData() { $.ajax({ url: `portfolio_shared_data.json`, dataType: "json", cache: false, success: function (data) { - this.setState({ sharedData: data }); - document.title = `${this.state.sharedData.basic_info.name}`; - }.bind(this), + setSharedData(data); + }, error: function (xhr, status, err) { alert(err); }, }); } - render() { - return ( -
-
-
-
- this.applyPickedLanguage( - window.$primaryLanguage, - window.$secondaryLanguageIconId - ) - } - style={{ display: "inline" }} - > - -
-
- this.applyPickedLanguage( - window.$secondaryLanguage, - window.$primaryLanguageIconId - ) - } - style={{ display: "inline" }} - > - -
+ return ( +
+
+
+
applyPickedLanguage(window.$primaryLanguage)} + style={ + selectedLanguage === window.$primaryLanguage + ? { display: "inline", filter: "brightness(40%)" } + : { display: "inline" } + } + > + +
+
applyPickedLanguage(window.$secondaryLanguage)} + style={ + selectedLanguage === window.$secondaryLanguage + ? { display: "inline", filter: "brightness(40%)" } + : { display: "inline" } + } + > +
- - - - -
- ); - } + + + + +
+
+ ); } export default App; diff --git a/src/components/About.js b/src/components/About.js index c7ff9bbad..9e7d79d03 100644 --- a/src/components/About.js +++ b/src/components/About.js @@ -1,95 +1,85 @@ -import React, { Component } from "react"; +import React from "react"; import { Icon } from "@iconify/react"; import angularIcon from "@iconify/icons-logos/angular-icon"; import reactIcon from "@iconify/icons-logos/react"; import vueIcon from "@iconify/icons-logos/vue"; -class About extends Component { - render() { - if (this.props.sharedBasicInfo) { - var profilepic = "images/" + this.props.sharedBasicInfo.image; - } - if (this.props.resumeBasicInfo) { - var sectionName = this.props.resumeBasicInfo.section_name.about; - var hello = this.props.resumeBasicInfo.description_header; - var about = this.props.resumeBasicInfo.description; - } +function About(props) { + const profilepic = "images/" + props?.sharedBasicInfo?.image; + const sectionName = props?.resumeBasicInfo?.section_name.about; + const hello = props?.resumeBasicInfo?.description_header; + const about = props?.resumeBasicInfo?.description; - return ( -
-
-

- {sectionName} -

-
-
-
- - Avatar placeholder - - - - -
+ return ( +
+
+

+ {sectionName} +

+
+
+
+ + Avatar placeholder + + + +
+
-
-
-
-
- {" "} -  {" "} - {" "} -  {" "} - -
-
-
- {hello} :) -
-
- {about} -
+
+
+
+
+ {" "} +  {" "} + {" "} +  {" "} + +
+
+
+ {hello} :) +
+
+ {about}
-
- ); - } +
+
+ ); } export default About; diff --git a/src/components/Experience.js b/src/components/Experience.js index 6e40f620d..67786b6ec 100644 --- a/src/components/Experience.js +++ b/src/components/Experience.js @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React from "react"; import { VerticalTimeline, VerticalTimelineElement, @@ -6,91 +6,89 @@ import { import "react-vertical-timeline-component/style.min.css"; import Badge from "react-bootstrap/Badge"; -class Experience extends Component { - render() { - if (this.props.resumeExperience && this.props.resumeBasicInfo) { - var sectionName = this.props.resumeBasicInfo.section_name.experience; - var work = this.props.resumeExperience.map(function (work, i) { - const technologies = work.technologies; - const mainTechnologies = work.mainTech; +function Experience(props) { + if (props.resumeExperience && props.resumeBasicInfo) { + var sectionName = props.resumeBasicInfo.section_name.experience; + var work = props.resumeExperience.map(function (work, i) { + const technologies = work.technologies; + const mainTechnologies = work.mainTech; - var mainTech = mainTechnologies.map((technology, i) => { - return ( - - {technology} - - ); - }); - var tech = technologies.map((technology, i) => { - return ( - - {technology} - - ); - }); + var mainTech = mainTechnologies.map((technology, i) => { return ( + + {technology} + + ); + }); + var tech = technologies.map((technology, i) => { + return ( + + {technology} + + ); + }); + return ( + } + key={i} + > +
+ {mainTech} +
+ +

+ {work.title} +

+

+ {work.company} +

+
{tech}
+
+ ); + }); + } + + return ( +
+
+
+

+ + {sectionName} + +

+
+
+
+ + {work} } - key={i} - > -
- {mainTech} -
- -

- {work.title} -

-

- {work.company} -

-
{tech}
-
- ); - }); - } - - return ( -
-
-
-

- - {sectionName} - -

-
-
-
- - {work} - - } - /> - -
-
- ); - } + icon={ + + } + /> +
+
+
+ ); } export default Experience; diff --git a/src/components/Footer.js b/src/components/Footer.js index 00b28970f..c2b36dd68 100644 --- a/src/components/Footer.js +++ b/src/components/Footer.js @@ -1,38 +1,34 @@ -import React, { Component } from "react"; +import React from "react"; -class Footer extends Component { - render() { - if (this.props.sharedBasicInfo) { - var networks = this.props.sharedBasicInfo.social.map(function (network) { - return ( - - - - - - ); - }); - } +function Footer(props) { + if (props.sharedBasicInfo) { + var networks = props.sharedBasicInfo.social.map(function (network) { + return ( + + + + + + ); + }); + } - return ( -
-
-
{networks}
+ return ( +
+
+
{networks}
-
-
- - Copyright ©{" "} - {this.props.sharedBasicInfo - ? this.props.sharedBasicInfo.name - : "???"} - -
+
+
+ + Copyright ©{" "} + {props.sharedBasicInfo ? props.sharedBasicInfo.name : "???"} +
-
- ); - } +
+
+ ); } export default Footer; diff --git a/src/components/Header.js b/src/components/Header.js index b94973a9f..105ddf66e 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -1,98 +1,94 @@ -import React, { Component } from "react"; +import React, { useState, useMemo } from "react"; import Typical from "react-typical"; import Switch from "react-switch"; -class Header extends Component { - titles = []; +function Header(props) { + const name = props.sharedData?.name ? props.sharedData.name : ""; + const [isChecked, setIsChecked] = useState(false); - constructor() { - super(); - this.state = { checked: false }; - this.onThemeSwitchChange = this.onThemeSwitchChange.bind(this); + function onThemeSwitchChange(checked) { + setIsChecked(checked); + setTheme(); } - onThemeSwitchChange(checked) { - this.setState({ checked }); - this.setTheme(); - } - - setTheme() { - var dataThemeAttribute = "data-theme"; - var body = document.body; - var newTheme = + function setTheme() { + const dataThemeAttribute = "data-theme"; + const body = document.body; + const newTheme = body.getAttribute(dataThemeAttribute) === "dark" ? "light" : "dark"; body.setAttribute(dataThemeAttribute, newTheme); } - render() { - if (this.props.sharedData) { - var name = this.props.sharedData.name; - this.titles = this.props.sharedData.titles.map(x => [ x.toUpperCase(), 1500 ] ).flat(); - } + const HeaderTitleTypeAnimation = useMemo(() => { + const titles = props.sharedData?.titles + ? props.sharedData.titles.map((x) => [x.toUpperCase(), 1500]).flat() + : []; + return ; + }, [props.sharedData?.titles]); - const HeaderTitleTypeAnimation = React.memo( () => { - return - }, (props, prevProp) => true); - - return ( -
-
-
-
- -
-

- -

-
- -
- - } - checkedIcon={ - - } - id="icon-switch" - /> -
+ return ( +
+
+
+
+ +
+

+ +

+
{HeaderTitleTypeAnimation}
+ + } + checkedIcon={ + + } + id="icon-switch" + />
-
- ); - } +
+
+ ); } export default Header; diff --git a/src/components/ProjectDetailsModal.js b/src/components/ProjectDetailsModal.js index a3f27fc64..4801779fd 100644 --- a/src/components/ProjectDetailsModal.js +++ b/src/components/ProjectDetailsModal.js @@ -1,107 +1,105 @@ -import React, { Component } from "react"; +import React from "react"; import { Modal } from "react-bootstrap"; import AwesomeSlider from "react-awesome-slider"; import AwesomeSliderStyles from "../scss/light-slider.scss"; import AwesomeSliderStyles2 from "../scss/dark-slider.scss"; import "react-awesome-slider/dist/custom-animations/scale-out-animation.css"; -class ProjectDetailsModal extends Component { - render() { - if (this.props.data) { - const technologies = this.props.data.technologies; - const images = this.props.data.images; - var title = this.props.data.title; - var description = this.props.data.description; - var url = this.props.data.url; - if (this.props.data.technologies) { - var tech = technologies.map((icons, i) => { - return ( -
  • - -
    - -

    - {icons.name} -

    -
    -
    -
    -
  • - ); +function ProjectDetailsModal(props) { + if (props.data) { + const technologies = props.data.technologies; + const images = props.data.images; + var title = props.data.title; + var description = props.data.description; + var url = props.data.url; + if (props.data.technologies) { + var tech = technologies.map((icons, i) => { + return ( +
  • + +
    + +

    + {icons.name} +

    +
    +
    +
    +
  • + ); + }); + if (props.data.images) { + var img = images.map((elem, i) => { + return
    ; }); - if (this.props.data.images) { - var img = images.map((elem, i) => { - return
    ; - }); - } } } - return ( - - - - -
    -
    -
    - {" "} -  {" "} - {" "} -  {" "} - -
    - - {img} - + } + return ( + + + + +
    +
    +
    + {" "} +  {" "} + {" "} +  {" "} +
    -
    -

    - {title} - {url ? ( - - - - ) : null} -

    -

    {description}

    -
    -
      {tech}
    -
    + + {img} + +
    +
    +

    + {title} + {url ? ( + + + + ) : null} +

    +

    {description}

    +
    +
      {tech}
    - - ); - } +
    + + ); } export default ProjectDetailsModal; diff --git a/src/components/Projects.js b/src/components/Projects.js index 4eb73a83b..1c78f784b 100644 --- a/src/components/Projects.js +++ b/src/components/Projects.js @@ -1,70 +1,69 @@ -import React, { Component } from "react"; +import React, { useState } from "react"; import ProjectDetailsModal from "./ProjectDetailsModal"; -class Projects extends Component { - constructor(props) { - super(props); - this.state = { - deps: {}, - detailsModalShow: false, - }; - } +function Projects(props) { + const [deps, setDeps] = useState({}); + const [detailsModalShow, setDetailsModalShow] = useState(false); - render() { - let detailsModalShow = (data) => { - this.setState({ detailsModalShow: true, deps: data }); - }; + const handleDetailsModalShowClick = (data) => { + setDeps(data); + setDetailsModalShow(true); + }; - let detailsModalClose = () => this.setState({ detailsModalShow: false }); - if (this.props.resumeProjects && this.props.resumeBasicInfo) { - var sectionName = this.props.resumeBasicInfo.section_name.projects; - var projects = this.props.resumeProjects.map(function (projects) { - return ( -
    - -
    detailsModalShow(projects)}> -
    - projectImages - {projects.startDate} -
    -

    - {projects.title} -

    -
    + const detailsModalClose = () => setDetailsModalShow(false); + if (props.resumeProjects && props.resumeBasicInfo) { + var sectionName = props.resumeBasicInfo.section_name.projects; + var projects = props.resumeProjects.map(function (projects) { + return ( +
    + +
    handleDetailsModalShowClick(projects)} + > +
    + projectImages + {projects.startDate} +
    +

    {projects.title}

    - -
    - ); - }); - } - - return ( -
    -
    -

    - {sectionName} -

    -
    -
    {projects}
    -
    - +
    +
    - - ); + ); + }); } + + return ( +
    +
    +

    + {sectionName} +

    +
    +
    {projects}
    +
    + +
    +
    + ); } export default Projects; diff --git a/src/components/Skills.js b/src/components/Skills.js index ddd6c14d7..4906a6646 100644 --- a/src/components/Skills.js +++ b/src/components/Skills.js @@ -1,44 +1,42 @@ -import React, { Component } from "react"; +import React from "react"; -class Skills extends Component { - render() { - if (this.props.sharedSkills && this.props.resumeBasicInfo) { - var sectionName = this.props.resumeBasicInfo.section_name.skills; - var skills = this.props.sharedSkills.icons.map(function (skills, i) { - return ( -
  • - -
    - -

    - {skills.name} -

    -
    -
    -
    -
  • - ); - }); - } +function Skills(props) { + if (props.sharedSkills && props.resumeBasicInfo) { + var sectionName = props.resumeBasicInfo.section_name.skills; + var skills = props.sharedSkills.icons.map(function (skills, i) { + return ( +
  • + +
    + +

    + {skills.name} +

    +
    +
    +
    +
  • + ); + }); + } - return ( -
    + return ( +
    +
    -
    -

    - {sectionName} -

    -
    -
    -
      {skills}
    -
    +

    + {sectionName} +

    -
    - ); - } +
    +
      {skills}
    +
    +
    + + ); } export default Skills;