From 3b5440565bc2b81f8a7752ae9311b2e929b817f2 Mon Sep 17 00:00:00 2001 From: eksqtr Date: Mon, 26 Aug 2024 17:27:34 +0800 Subject: [PATCH] Fixes regarding responsiveness of the design, Fixes of design utility mousecirclehover, Updates on Tech Sections Experience - Some adjustment over css designs for tech sections\n-Improvement of listing job experience design as well automated calculation of years\n- Added libraries regarding date momentjs and moment-timezone for date time manipulation\n- Bug fixes on design utility mousecirclehover where it doesnt work on tech sections as well conflicting with clickable content\n-\n- Updating my personal job experience\n- Added mitigation for a probability or XSS attacks based on the new implementation of listing job experience responsibilities --- package-lock.json | 48 ++++++++++ package.json | 4 + src/app/components/techsection/jobsList.tsx | 92 +++++++++++++++---- src/app/components/techsection/tech.tsx | 20 ++-- .../components/utilities/mousecirclehover.tsx | 3 +- 5 files changed, 143 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4050c91..dab2a81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "my-personal-website-react", "version": "0.1.0", "dependencies": { + "dompurify": "^3.1.6", + "moment": "^2.30.1", + "moment-timezone": "^0.5.45", "next": "14.2.5", "react": "^18", "react-dom": "^18", @@ -15,6 +18,7 @@ "sharp": "^0.33.5" }, "devDependencies": { + "@types/dompurify": "^3.0.5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -786,6 +790,16 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -826,6 +840,13 @@ "@types/react": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/parser": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", @@ -1765,6 +1786,12 @@ "node": ">=6.0.0" } }, + "node_modules/dompurify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==", + "license": "(MPL-2.0 OR Apache-2.0)" + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3592,6 +3619,27 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/package.json b/package.json index a953524..0bc2adc 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,9 @@ "lint": "next lint" }, "dependencies": { + "dompurify": "^3.1.6", + "moment": "^2.30.1", + "moment-timezone": "^0.5.45", "next": "14.2.5", "react": "^18", "react-dom": "^18", @@ -16,6 +19,7 @@ "sharp": "^0.33.5" }, "devDependencies": { + "@types/dompurify": "^3.0.5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/src/app/components/techsection/jobsList.tsx b/src/app/components/techsection/jobsList.tsx index b2b821d..74e87af 100644 --- a/src/app/components/techsection/jobsList.tsx +++ b/src/app/components/techsection/jobsList.tsx @@ -1,8 +1,11 @@ import { useState} from "react"; +import DOMPurify from 'dompurify'; +import moment from 'moment-timezone'; // props type JobProps = { - year: string; + dateStarted: Date; + dateEnded: Date, company: string; position: string; responsibilities: string; @@ -12,47 +15,104 @@ type JobProps = { // Array jobs info my friend const jobs: JobProps[] = [ { - year: "2022 - 2024", + dateStarted: new Date("2022-03-21"), + dateEnded: new Date("2024-07-31"), company: "PEDDLR PHILIPPINES INC.", - position: "Software Engineer Full Stack", - responsibilities: "Developed and maintained web applications...\nasdasd", - techStacks: ["Node.js", "Vue.js", "React", "Next.js"], + position: "Software Engineer - Full Stack", + responsibilities: ` +
+ Developed and maintained new features of Web Front-End, Back-End and Back-End mobile applications. +
Highlights: + +
+ `, + techStacks: ["NodeJS", "VueJS", "Vuetify", "Vuex", "TypeScript","AWS Cloud Services", "Laravel MIX", "Git", "Jira", "Bitbucket", "Nginx"], }, { - year: "2020 - 2022", + dateStarted: new Date("2020-05-25"), + dateEnded: new Date("2022-02-20"), company: "Equity Gaming", position: "President & Head of Development Team", - responsibilities: "Led a team of developers, managed projects...", - techStacks: ["Laravel", "PHP", "MySQL", "AWS"], + responsibilities: ` +
+ Establish a gaming community for GTA SA-MP Online Roleplay, Led a team and managed developments of the product and organization operation. +
Highlights: + +
+ `, + techStacks: ["Pawn", "VueJS", "OVH Cloud", "Cloudflare", "Trello", "Discord", "Socket.io", "NodeJS", "ExpressJS", "MySQL"], }, ]; - const JobExperience = () => { const [selectedJob, setSelectedJob] = useState(jobs[0]); + // We need to sanitize the possibilies of XSS attack so we use dom prufiy for this shit + const arrTags: Array = ['b', 'i', 'span', 'strong', 'a', 'div', 'ul', 'li', 'em', 'br']; + const arrAttr: Array = ['href', 'class']; + const sanitizedResponsibilities = selectedJob ? DOMPurify.sanitize(selectedJob.responsibilities, { + ALLOWED_TAGS: arrTags, + ALLOWED_ATTR: arrAttr + } + ) : ''; + return (
-
+
    - {jobs.map((job, index) => ( + + {jobs.map((job, index) => { + + // we gonna use the moment timezone on this part + const startDate = moment(job.dateStarted).tz('Asia/Manila'); + const endDate = moment(job.dateEnded).tz('Asia/Manila'); + const duration = moment.duration(endDate.diff(startDate)); + + const years = duration.years(); + const months = duration.months(); + const formattedDuration = `${years} yr${years !== 1 ? 's' : ''} ${months} mo${months !== 1 ? 's' : ''}`; + + return (
  • setSelectedJob(job)} > -

    {job.year}

    +
    + + {`${moment(job.dateStarted).format("YYYY")} - ${moment(job.dateEnded).format("YYYY")}`} + + {formattedDuration}

    {job.company}

    +
  • - ))} + ); + })}
{selectedJob && ( <> -

{selectedJob.position}

-

{selectedJob.responsibilities}

+

{selectedJob.position}

+

Tech Stacks:

diff --git a/src/app/components/techsection/tech.tsx b/src/app/components/techsection/tech.tsx index 4d4328d..dc808c0 100644 --- a/src/app/components/techsection/tech.tsx +++ b/src/app/components/techsection/tech.tsx @@ -1,5 +1,5 @@ import { RefObject, useState} from "react"; - +import { MdOpenInNew } from "react-icons/md"; import JobExperience from "./jobsList" import techIcons from "./techIcons"; @@ -9,23 +9,24 @@ type TechProps = { const TechSection = (props: TechProps) => { const [activeTab, setActiveTab] = useState<'tech' | 'experience'>('tech'); const [iconSize] = useState('30px'); // Increased size for better visibility + const [resume_link, _] = useState("https://drive.google.com/file/d/1CXssqhJuY_-xgjQDOagCLyTckRvozBZr/view"); return (
{/* Tabs */}
) : ( -
-

Experience

- +
+

Experience + + View Full Resume + +

+
+ )} ); diff --git a/src/app/components/utilities/mousecirclehover.tsx b/src/app/components/utilities/mousecirclehover.tsx index 50b5756..d513de3 100644 --- a/src/app/components/utilities/mousecirclehover.tsx +++ b/src/app/components/utilities/mousecirclehover.tsx @@ -23,8 +23,9 @@ export const MouseHoverCircle = () => { top: position.y + 'px', left: position.x + 'px', transform: 'translate(-50%, -50%)', - zIndex: 0, + zIndex: 1, filter: 'blur(100px)', + pointerEvents: 'none' }} >
)