diff --git a/README.md b/README.md index 4ac906833..8b1378917 100644 --- a/README.md +++ b/README.md @@ -1,211 +1 @@ -# Reactfolio V1.2 👩🏽‍🚀 -Reactfolio is a modern and customizable personal portfolio web template built using the popular React library. It provides an easy way for developers, designers, and creatives to showcase their work, skills, and achievements in a professiona and visually appealing way. With its responsive design and clean code, Reactfolio can be easily tailored to suit individual needs and preferences, making it an ideal choice for anyone looking to create a stunning online portfolio. - -
-Reactfolio -
- -Live demo here: reactfolio.tharindu.dev -
-Readme here: tharindu.dev/portfolio/reactfolio/ - -- [Features](#-features) -- [Getting started](#-getting-started) -- [Installation and Setup Instructions](#-installation-and-setup-instructions) -- [Folder structure](#-folder-structure) -- [Configurations](#-configurations) -- [Google Analytics](#-google-analytics) -- [Building the React App](#-building-the-react-app) -- [FAQ](#-faq) -- [Contribution](#-contribution) - -## 📙 Features - -- 📖 Multi-Page Layout - - Home - - About - - Projects - - Articles - - Contact -- 📱 Fully Responsive -- 🛠 Easy configurations - -## 📚 Getting started - -Clone down this repository. You will need `NodeJS` and `git` installed globally on your machine. - -## 🛠 Installation and Setup Instructions - -1. Installation: `npm install` - -2. Run the project: `npm start` - -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. -The page will reload if you make edits. - -## 📁 Folder structure - -- `/public`: publicly accessible contents (ex: images, media). -- `/src`: all the components used in this project. - - `/src/components/`: each reusable components of each pages. - - `/src/data`: configurations of the web app. - - `/src/pages`: pages that include in the web app. - -## ⚙️ Configurations - -Since this is a public and open source project, you can make any changes to it. If you are a ReactJS developer you can do it easily. But if you are a beginner, I have extracted the configurable data into a single directory, so you can edit the files in that directory to configure the entire web application. - -Directory: `/src/data/` - -- `user.js` - - From this you can change the content of each page of the web application. - -- `articles.js` - - From this you can add your articles to the web application. - - Instructions: - - - Add new article - - 1. Create a new function starts with `article_`. For example you can add new function named `article_3`. - - 2. Then add the data accordingly. - - - Add `` tag and it's closing tags in body. - - In React there has no keyword `class`, so you should use `className` to define html classes. - - ```js - function article_3() { - return { - date: "7 May 2023", - title: "The Benefits of Cloud Computing", - description: "Why businesses are turning to the cloud.", - style: ` - .random-image { - align-self: center; - outline: 2px solid red; - } - `, - body: ( - -
-
- Content of article 1 -
- random -
-
- ), - }; - } - ``` - - 3. In the last lines you will see an array to which you need to add your new `articles` function. - - ```js - const myArticles = [article_1, article_2, article_3]; - ``` - -- `seo.js` - - The SEO.js file is a module that contains an array of objects, with each object representing metadata for a specific page of a React website. The purpose of this file is to centralize and manage the SEO (Search Engine Optimization) information for different pages. - - Each object in the SEO array has the following properties: - - `page`: Represents the page name or identifier. It helps in mapping the SEO data to the appropriate page. - - `title`: Specifies the title of the page. This title is typically displayed in the browser's title bar and is an important element for search engines. - - `description`: Provides a concise and informative description of the page content. This description is often displayed in search engine results and can greatly influence click-through rates. - keywords: Contains an array of keywords relevant to the page's content. Keywords can help search engines understand the topics covered on the page and can impact its visibility in search results. - By storing the SEO information in the SEO.js file, you can easily manage and update the metadata for different pages of your React website. This approach allows you to keep the SEO data separate from the components and reuse it across the application, ensuring consistent and optimized metadata for each page. - - Example: - - ```js - const SEO = [ - { - page: "home", - description: - "I am a backend developer with expertise in Node.js. I have experience in building scalable, secure and reliable web applications using various frameworks and technologies.", - keywords: ["Tharindu", "Tharindu N", "Tharindu Nayanajith"], - }, - ]; - ``` - -- `styles.css` - - From this you can change the font colors and font families of the web application. - - ```css - :root { - /* ------- colors ------- */ - --primary-color: #27272a; - --secondary-color: #65656d; - --tertiary-color: #acacb4; - --quaternary-color: #e4e4e7; - --link-color: #14b8a6; - /* ---------------------- */ - - /* ------- fonts ------- */ - --primary-font: "Heebo", sans-serif; - --secondary-font: "Roboto", sans-serif; - /* --------------------- */ - } - ``` - -## 📈 Google Analytics - -Add your Google Analytics 4 MEASUREMENT ID to `/src/data/tracking.js`. - -How to find the Google Analytics 4 MEASUREMENT ID ? - -[https://support.google.com/analytics/answer/9539598?hl=en](https://support.google.com/analytics/answer/9539598?hl=en) - -## 🚀 Building the React App - -To build the React app, you can use the `npm run build` command. This will create a production-ready build of your app in the `build/` directory. - -Here are the steps to follow: - -1. Open a terminal window and navigate to the root directory of your React app. -2. Run the `npm run build` command to create a production build of your app. This will generate a static bundle of your app in the `build/` directory. -3. Copy the contents of the `build/` directory to your server's public directory. You can do this using an FTP client or by running a command like `scp` to transfer the files to your server. Make sure to replace `example.com` and `/var/www/html` with your server's domain name and public directory, respectively: - - ```bash - scp -r build/* user@example.com:/var/www/html - ``` - -4. Your portfolio app should now be accessible from your server's domain name. You can verify this by opening a web browser and navigating to http://example.com (replace example.com with your server's domain name). - -That's it! Your React portfolio app should now be up and running on your server. Note that you may need to configure your server's web server (e.g., Apache or Nginx) to serve the index.html file in the build/ directory as the default page for your domain. - -## 🤔 FAQ - -**Q1. Subpages can only be accessed through links on the homepage or navigation bar, but those pages are not accessible through direct links.** - -If you are using Apache as your web server, you can insert this into your .htaccess file: - -```c - - RewriteEngine On - RewriteBase / - RewriteRule ^index\.html$ - [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteCond %{REQUEST_FILENAME} !-l - RewriteRule . /index.html [L] - -``` - -## 🌱 Contribution - -If you have any suggestions on what to improve in Reactfolio and would like to share them, feel free to leave an issue or fork project to implement your own ideas diff --git a/package-lock.json b/package-lock.json index e95ac91d4..8358321c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,9 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "caniuse-lite": "^1.0.30001607", + "dotenv": "^16.4.5", + "emailjs-com": "^3.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-ga4": "^2.1.0", @@ -24,6 +27,7 @@ "react-router-dom": "^6.11.1", "react-scripts": "5.0.1", "styled-components": "^5.3.10", + "tailwindcss": "^3.4.1", "web-vitals": "^2.1.4" } }, @@ -5770,9 +5774,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001482", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001482.tgz", - "integrity": "sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ==", + "version": "1.0.30001607", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz", + "integrity": "sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==", "funding": [ { "type": "opencollective", @@ -6918,11 +6922,14 @@ } }, "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { @@ -6959,6 +6966,15 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.382.tgz", "integrity": "sha512-czMavlW52VIPgutbVL9JnZIZuFijzsG1ww/1z2Otu1r1q+9Qe2bTsH3My3sZarlvwyqHM6+mnZfEnt2Vr4dsIg==" }, + "node_modules/emailjs-com": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emailjs-com/-/emailjs-com-3.2.0.tgz", + "integrity": "sha512-Prbz3E1usiAwGjMNYRv6EsJ5c373cX7/AGnZQwOfrpNJrygQJ15+E9OOq4pU8yC977Z5xMetRfc3WmDX6RcjAA==", + "deprecated": "The SDK name changed to @emailjs/browser", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -8034,9 +8050,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -11689,9 +11705,9 @@ } }, "node_modules/jiti": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", "bin": { "jiti": "bin/jiti.js" } @@ -14652,6 +14668,14 @@ } } }, + "node_modules/react-scripts/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, "node_modules/react-side-effect": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz", @@ -16026,19 +16050,19 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "node_modules/tailwindcss": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", - "integrity": "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", + "jiti": "^1.19.1", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -16050,7 +16074,6 @@ "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, diff --git a/package.json b/package.json index c8fcdbdd5..e5ec82872 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,9 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "caniuse-lite": "^1.0.30001607", + "dotenv": "^16.4.5", + "emailjs-com": "^3.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-ga4": "^2.1.0", @@ -25,6 +28,7 @@ "react-router-dom": "^6.11.1", "react-scripts": "5.0.1", "styled-components": "^5.3.10", + "tailwindcss": "^3.4.1", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/public/RavkeeratSinghCV.pdf b/public/RavkeeratSinghCV.pdf new file mode 100644 index 000000000..c38427f58 Binary files /dev/null and b/public/RavkeeratSinghCV.pdf differ diff --git a/public/index.html b/public/index.html index 3fdf6203b..3e7a7178a 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ - Reactfolio + Ravkeerat Singh Portfolio diff --git a/src/App.js b/src/App.js index 0ad30befb..0487b8e9e 100644 --- a/src/App.js +++ b/src/App.js @@ -5,8 +5,7 @@ import ReactGA from "react-ga4"; import Homepage from "./pages/homepage"; import About from "./pages/about"; import Projects from "./pages/projects"; -import Articles from "./pages/articles"; -import ReadArticle from "./pages/readArticle"; + import Contact from "./pages/contact"; import Notfound from "./pages/404"; @@ -26,8 +25,6 @@ function App() { } /> } /> } /> - } /> - } /> } /> } /> diff --git a/src/app.css b/src/app.css index aec0543b7..2fd832f17 100644 --- a/src/app.css +++ b/src/app.css @@ -65,10 +65,6 @@ margin-top: 25px; } -.page-footer { - position: block; -} - .page-footer::before { content: ""; position: absolute; diff --git a/src/components/about/socials.jsx b/src/components/about/socials.jsx index 70f403262..503152127 100644 --- a/src/components/about/socials.jsx +++ b/src/components/about/socials.jsx @@ -1,12 +1,7 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faEnvelope } from "@fortawesome/free-solid-svg-icons"; -import { - faTwitter, - faGithub, - faLinkedin, - faInstagram, -} from "@fortawesome/free-brands-svg-icons"; +import { faGithub, faLinkedin } from "@fortawesome/free-brands-svg-icons"; import INFO from "../../data/user"; @@ -15,17 +10,7 @@ import "./styles/socials.css"; const Socials = () => { return (
- +
- -
{ - const { date, title, description, link } = props; - - return ( - -
-
-
{date}
-
- - -
-
{title}
-
{description}
-
- Read Article{" "} - -
-
- -
-
- ); -}; - -export default Article; diff --git a/src/components/articles/style/article.css b/src/components/articles/style/article.css deleted file mode 100644 index 49ccf37e8..000000000 --- a/src/components/articles/style/article.css +++ /dev/null @@ -1,69 +0,0 @@ -@import "../../../data/styles.css"; - -.article { - display: flex; -} - -.article a { - text-decoration: none; -} - -.article-left-side { - min-width: 20%; - max-width: 20%; -} - -.article-right-side { - flex-basis: 80%; - min-width: 700px; - mix-blend-mode: normal; - border-radius: 20px; - opacity: 0.8; - padding: 30px; -} - -.article-right-side:hover { - background: #fafafa; - opacity: 1; - transition: background-color 0.3s ease-in-out; -} - -.article-date { - padding-top: 30px; - font-size: 15px; - color: var(--tertiary-color); -} - -.article-title { - color: #000000; - font-size: 16px; - font-weight: 600; -} - -.article-description { - padding-top: 10px; - font-size: 12px; - color: var(--secondary-color); - font-weight: 480; - line-height: 25px; -} - -.article-link { - padding-top: 10px; - font-size: 14px; - color: var(--link-color); - font-weight: 700; -} - -@media (max-width: 1024px) { - .article-left-side { - min-width: 10%; - max-width: 10%; - } - - .article-right-side { - flex-basis: 90%; - min-width: 85%; - max-width: 85%; - } -} diff --git a/src/components/common/footer.jsx b/src/components/common/footer.jsx index b79bbf70a..535ec759c 100644 --- a/src/components/common/footer.jsx +++ b/src/components/common/footer.jsx @@ -1,39 +1,50 @@ import React from "react"; import { Link } from "react-router-dom"; -import "./styles/footer.css"; - const Footer = () => { return ( - -
-
-
    -
  • - Home -
  • -
  • - About -
  • -
  • - Projects -
  • -
  • - Articles -
  • -
  • - Contact -
  • -
-
+
+
{" "} + {/* Line before footer on smaller devices */} +
+
+
+
    +
  • + + Home + +
  • +
  • + + About + +
  • +
  • + + Projects + +
  • +
  • + + Contact + +
  • +
+
-
-
- © 2023 Tharindu.dev. All Rights Reserved. +
+ © 2024 Ravkeerat S. All Rights Reserved.
- +
); }; diff --git a/src/components/common/navBar.jsx b/src/components/common/navBar.jsx index 6768cb861..1328df216 100644 --- a/src/components/common/navBar.jsx +++ b/src/components/common/navBar.jsx @@ -39,15 +39,7 @@ const NavBar = (props) => { > Projects -
  • - Articles -
  • +
  • { - const { title, description, date, link } = props; - - return ( - -
    -
    -
    - |   {date} -
    -
    {title}
    -
    - {description} -
    -
    - - Read article{" "} - - -
    -
    -
    -
    - ); -}; - -export default Article; diff --git a/src/components/homepage/styles/article.css b/src/components/homepage/styles/article.css deleted file mode 100644 index e157660d2..000000000 --- a/src/components/homepage/styles/article.css +++ /dev/null @@ -1,58 +0,0 @@ -@import "../../../data/styles.css"; - -.homepage-article { - width: 90%; - mix-blend-mode: normal; - border-radius: 20px; - opacity: 0.8; -} - -.homepage-article:hover { - background: #fafafa; - opacity: 1; - transition: background-color 0.3s ease-in-out; -} - -.homepage-article-content { - padding: 30px; -} - -.homepage-article-date { - opacity: 1; - color: var(--tertiary-color); - font-size: 12px; - margin-bottom: 1em; -} - -.homepage-article-title { - opacity: 1; - color: var(--primary-color); - font-size: 16px; - margin-bottom: 1em; - font-weight: 700; -} - -.homepage-article-description { - opacity: 1; - color: var(--secondary-color); - font-size: 12px; - line-height: 1.5; -} - -.homepage-article-link { - opacity: 1; - padding-top: 20px; - font-size: 15px; - font-weight: 700; -} - -.homepage-article-link a { - color: var(--link-color); - text-decoration: none; -} - -@media (max-width: 600px) { - .homepage-article { - width: 100%; - } -} diff --git a/src/components/homepage/styles/works.css b/src/components/homepage/styles/works.css index 852128572..a0be7370e 100644 --- a/src/components/homepage/styles/works.css +++ b/src/components/homepage/styles/works.css @@ -10,15 +10,8 @@ width: 400px; } -.work-image { - height: 30px; - width: 30px; - border-radius: 50%; - outline: 6px solid white; - box-shadow: 0px 7px 10px rgba(0, 0, 0, 0.25); -} - -.work-title { +.work-title, +.work-location { font-size: 15px; font-weight: 700; padding-left: 20px; diff --git a/src/components/homepage/works.jsx b/src/components/homepage/works.jsx index 7d6124530..b9ae01cb1 100644 --- a/src/components/homepage/works.jsx +++ b/src/components/homepage/works.jsx @@ -1,48 +1,89 @@ import React from "react"; -import { faBriefcase } from "@fortawesome/free-solid-svg-icons"; -import Card from "../common/card"; +const Timeline = () => { + const timelineData = [ + { + date: "August 2023 - Present", + Company: "Kiran Media Inc", + title: "Website Developer", + description: [ + "Expertly develop and maintain websites, combining technical prowess in HTML, CSS, and JavaScript with a keen eye for UI/UX design principles.", + "Apply user-centered design methodologies to create intuitive and visually appealing interfaces, enhancing user satisfaction and driving increased engagement by 20%.", + "Led a team in enhancing an e-commerce platform using TypeScript and React, focusing on improving user experience and performance.", + ], + }, + { + date: "August 2023 - October 2023", + Company: "Arcturus Technologies, Inc.", + title: "Software Intern", + description: [ + "Demonstrated technical leadership both internally and within external communities, contributing valuable insights and solutions to technical challenges.", + "Leveraged Node.js expertise to develop scalable backend services and APIs, resulting in a 30% improvement in server response time.", + "Debugged issues and produced high-quality code fixes, ensuring reliability and stability of software applications.", + ], + }, + { + date: "June 2023 - August 2023", + Company: "Neolytix", + title: "Junior Cyber Security Analyst", + description: [ + "Assisted in developing and refining incident response plans to ensure swift and effective response to security incidents.", + "Conducted regular vulnerability assessments to identify and prioritize potential security risks.", + ], + }, + { + date: "January 2020 - March 2020", + Company: "Exlservice Philippines, Inc", + title: "Intern", + description: [ + "Efficiently handle customer inquiries and concerns, leveraging strong communication skills to ensure a positive caller experience.", + "Collaborate with senior team members to enhance call center software interfaces, applying frontend development skills to streamline navigation and improve usability.", + "Implement interface enhancements resulting in a 75% increase in call ratio, optimizing user interactions and driving greater efficiency in call handling processes.", + ], + }, + ]; -import "./styles/works.css"; + // Sort timelineData based on date + timelineData.sort((a, b) => { + const dateA = new Date(a.date.split(" - ")[0]); + const dateB = new Date(b.date.split(" - ")[0]); + return dateA - dateB; + }); -const Works = () => { return ( -
    - -
    - facebook -
    Facebook
    -
    - Software Engineer -
    -
    2019 - Present
    +
    + {timelineData.map((item, index) => ( +
    +
    +
    {item.title}
    +
      + {item.description.map((desc, index) => ( +
    • {desc}
    • + ))} +
    +
    +
    +
    + {item.date}
    - -
    - twitter -
    Twitter
    -
    - Software Engineer +
    +
    +
    +

    + {item.Company} +

    -
    2019 - Present
    - } - /> +
    + ))}
    ); }; -export default Works; +export default Timeline; diff --git a/src/components/projects/allProjects.jsx b/src/components/projects/allProjects.jsx index 67763f2da..2bba6a4a2 100644 --- a/src/components/projects/allProjects.jsx +++ b/src/components/projects/allProjects.jsx @@ -1,22 +1,18 @@ import React from "react"; - import Project from "./project"; - import INFO from "../../data/user"; -import "./styles/allProjects.css"; - const AllProjects = () => { return ( -
    +
    {INFO.projects.map((project, index) => ( -
    +
    ))} @@ -24,4 +20,18 @@ const AllProjects = () => { ); }; +// Function to format the description as bullet points +const formatDescription = (description) => { + const points = description + .split("\n") + .filter((point) => point.trim() !== ""); + return ( +
      + {points.map((point, index) => ( +
    • {point}
    • + ))} +
    + ); +}; + export default AllProjects; diff --git a/src/components/projects/project.jsx b/src/components/projects/project.jsx index 521c853d9..5cb71a5ad 100644 --- a/src/components/projects/project.jsx +++ b/src/components/projects/project.jsx @@ -2,33 +2,31 @@ import React from "react"; import { Link } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faLink } from "@fortawesome/free-solid-svg-icons"; - -import "./styles/project.css"; +import Footer from "../common/footer"; const Project = (props) => { - const { logo, title, description, linkText, link } = props; + const { title, description, linkText, link, languages } = props; return ( - -
    - -
    -
    - logo -
    -
    {title}
    -
    {description}
    -
    -
    - -
    - -
    {linkText}
    -
    +
    + +
    +
    {title}
    +

    {description}

    +
    + + Languages: {languages} + +
    +
    + + + {linkText} +
    - -
    - +
    + +
    ); }; diff --git a/src/components/projects/styles/project.css b/src/components/projects/styles/project.css index 7030f3eac..c761c5623 100644 --- a/src/components/projects/styles/project.css +++ b/src/components/projects/styles/project.css @@ -42,6 +42,10 @@ margin-bottom: 1em; font-weight: 700; } +.project-languages { + font-size: 12px; + color: var(--tertiary-color); +} .project-description { color: var(--secondary-color); diff --git a/src/data/articles.js b/src/data/articles.js deleted file mode 100644 index c130336da..000000000 --- a/src/data/articles.js +++ /dev/null @@ -1,65 +0,0 @@ -import React from "react"; - -function article_1() { - return { - date: "7 May 2023", - title: "The Benefits of Cloud Computing", - description: - "Cloud computing offers a range of benefits, including cost savings and increased flexibility. Find out why more businesses are turning to the cloud.", - keywords: [ - "The Benefits of Cloud Computing", - "Tharindu", - "Tharindu N", - "Tharindu Nayanajith", - ], - style: ` - .article-content { - display: flex; - flex-direction: column; - align-items: center; - } - - .randImage { - align-self: center; - outline: 2px solid red; - } - `, - body: ( - -
    -
    Content of article 1
    - random -
    -
    - ), - }; -} - -function article_2() { - return { - date: "7 May 2023", - title: "Artificial Intelligence in Healthcare", - description: - "AI is transforming the healthcare industry, from improving patient outcomes to streamlining operations. Discover the latest applications of this game-changing technology.", - style: ``, - keywords: [ - "Artificial Intelligence in Healthcare", - "Tharindu", - "Tharindu N", - "Tharindu Nayanajith", - ], - body: ( - -

    Content of article 2

    -
    - ), - }; -} - -const myArticles = [article_1, article_2]; - -export default myArticles; diff --git a/src/data/seo.js b/src/data/seo.js index 4bee91813..feb9311ca 100644 --- a/src/data/seo.js +++ b/src/data/seo.js @@ -13,13 +13,6 @@ const SEO = [ keywords: ["Tharindu", "Tharindu N", "Tharindu Nayanajith"], }, - { - page: "articles", - description: - "Chronological collection of my long-form thoughts on programming, leadership, product design, and more.", - keywords: ["Tharindu", "Tharindu N", "Tharindu Nayanajith"], - }, - { page: "projects", description: diff --git a/src/data/user.js b/src/data/user.js index 6dcf5bdac..3a00c4d95 100644 --- a/src/data/user.js +++ b/src/data/user.js @@ -1,84 +1,98 @@ const INFO = { main: { - title: "Reactfolio by truethari", - name: "Tharindu N.", - email: "mail@tharindu.dev", - logo: "../logo.png", + title: "Ravkeerat Singh", + name: "Ravkeerat Singh", + email: "ravkeerat_singh@outlook.com", }, socials: { - twitter: "https://twitter.com/", - github: "https://github.com/", - linkedin: "https://linkedin.com/", - instagram: "https://instagram.com/", - stackoverflow: "https://stackoverflow.com/", - facebook: "https://facebook.com/", + github: "https://github.com/Ravkeerat02", + linkedin: "https://www.linkedin.com/in/ravkeeratsingh/", }, homepage: { - title: "Full-stack web and mobile app developer, and amateur astronaut.", + title: "Front End Developer", description: - "I am a backend developer with expertise in Node.js. I have experience in building scalable, secure and reliable web applications using various frameworks and technologies. I enjoy solving complex problems and learning new skills. I am passionate about creating high-quality code that follows best practices and industry standards. I am always looking for new challenges and opportunities to grow as a developer.", + "As a motivated front-end developer proficient in HTML, CSS, and JavaScript, I am dedicated to delivering immersive digital experiences. With a keen eye for detail and a passion for innovation, I strive to contribute creative solutions that elevate user engagement and drive business success. I am eager to collaborate in a professional environment where teamwork and continuous learning are valued, enabling me to further enhance my skills and contribute to impactful projects.", }, about: { - title: "I’m Tharindu N. I live in Sri Lanka, where I design the future.", + title: "Ravkeerat Singh", description: - "I've worked on a variety of projects over the years and I'm proud of the progress I've made. Many of these projects are open-source and available for others to explore and contribute to. If you're interested in any of the projects I've worked on, please feel free to check out the code and suggest any improvements or enhancements you might have in mind. Collaborating with others is a great way to learn and grow, and I'm always open to new ideas and feedback.", - }, - - articles: { - title: "I'm passionate about pushing the boundaries of what's possible and inspiring the next generation of innovators.", - description: - "Chronological collection of my long-form thoughts on programming, leadership, product design, and more.", + "I'm Ravkeerat Singh, a recent graduate passionate about front-end development. Proficient in HTML, CSS, and React.js, I bring a keen eye for design and a drive for creating engaging user experiences. Eager to apply my skills in real-world projects, I thrive in collaborative environments and am committed to delivering polished, innovative solutions. Let's connect and explore how I can contribute to your team!", }, projects: [ { - title: "Project 1", - description: - "Lorem ipsum dolor sit amet. Et incidunt voluptatem ex tempore repellendus qui dicta nemo sit deleniti minima.", - logo: "https://cdn.jsdelivr.net/npm/programming-languages-logos/src/javascript/javascript.png", - linkText: "View Project", - link: "https://github.com", + title: "Time Master Application", + description: ` + Created a user-centric application for employees to manage schedules, clock in/out, and request time off. + Enriched functionality by implementing manager features for efficient employee management.`, + linkText: "Time Master", + languages: "ExpressJS , NodeJs , MongoDb", + link: "https://time-master.herokuapp.com/", }, { - title: "Project 2", - description: - "Lorem ipsum dolor sit amet. Et incidunt voluptatem ex tempore repellendus qui dicta nemo sit deleniti minima.", - logo: "https://cdn.jsdelivr.net/npm/programming-languages-logos/src/python/python.png", - linkText: "View Project", - link: "https://github.com", + title: "CarHub", + description: ` + Developed a web-based application enabling users to sort, filter, and search for specific cars by year and fuel mileage. + Results feature detailed descriptions and images for enhanced user engagement.`, + languages: "NodeJS , Express , ReactJS , NextJS", + linkText: "Car Hub", + link: "https://car-hub-nine-rust.vercel.app/", }, - { - title: "Project 3", - description: - "Lorem ipsum dolor sit amet. Et incidunt voluptatem ex tempore repellendus qui dicta nemo sit deleniti minima.", - logo: "https://cdn.jsdelivr.net/npm/programming-languages-logos/src/html/html.png", - linkText: "View Project", - link: "https://github.com", + title: "Anime Vault", + description: ` + Developed a web-based application that utilizes the Shikimori API to display anime shows. + Implemented smooth animations for seamless scrolling.`, + languages: "TypeScript , JavaScript ", + linkText: "Anime Vault", + link: "https://anime-vault-try.vercel.app/", }, - { - title: "Project 4", - description: - "Lorem ipsum dolor sit amet. Et incidunt voluptatem ex tempore repellendus qui dicta nemo sit deleniti minima.", - logo: "https://cdn.jsdelivr.net/npm/programming-languages-logos/src/javascript/javascript.png", - linkText: "View Project", - link: "https://github.com", + title: "Quote Generator", + description: ` + Randomly Generated Quotes with the help of
    Quotable API. + Ability to share the quote on twitter. + Ability to speak the quote `, + languages: "JavaScript , HTML , CSS", + linkText: "Quote Generator", + link: "https://ravkeerat02.github.io/Quote-generator/", + }, + { + title: "Traveligo - Landing Page Only", + description: ` + Crafted using the power of TypeScript, Next.js, and ReactJS, ensuring robustness and efficiency. + Delivers a contemporary and adaptive interface, elevating the user journey to new heights of convenience and satisfaction. `, + languages: "TypeScript , ReactJS , NextJs ", + linkText: "Traveligo", + link: "https://traveligo-n8bwg4z2h-ravkeerat02.vercel.app/", }, - { - title: "Project 5", - description: - "Lorem ipsum dolor sit amet. Et incidunt voluptatem ex tempore repellendus qui dicta nemo sit deleniti minima.", - logo: "https://cdn.jsdelivr.net/npm/programming-languages-logos/src/javascript/javascript.png", - linkText: "View Project", - link: "https://github.com", + title: "Tic Tac Toe", + description: ` + Developed using HTML, CSS, and JavaScript for a lightweight and browser-compatible gaming experience. + Implements features like automatic game reset upon completion, ensuring continuous enjoyment without interruptions. + Enhances user engagement by dynamically displaying the score and announcing the winner at the conclusion of each game, fostering a competitive and immersive atmosphere.`, + languages: "HTML , CSSS , JS ", + linkText: "Tic Tac Toe", + link: "https://tic-tac-toe-liard-zeta.vercel.app/", }, ], }; +function replaceAPIText(description) { + // Replace both specific HTML tags with the desired text + return description.replace( + /]*href="(?:https:\/\/shikimori\.one\/api\/doc|https:\/\/api\.quotable\.io\/random)"[^>]*>[^<]*<\/a>/gi, + "API" + ); +} + +INFO.projects.forEach((project) => { + project.description = replaceAPIText(project.description); +}); + export default INFO; diff --git a/src/index.css b/src/index.css index a28f84c44..b5c61c956 100644 --- a/src/index.css +++ b/src/index.css @@ -1,14 +1,3 @@ -@import url("https://fonts.googleapis.com/css2?family=Heebo:wght@300&family=Roboto:wght@500&display=swap"); -@import "./data/styles.css"; - -body { - margin: 0; - font-family: var(--primary-font); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; -} +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/src/index.js b/src/index.js index 8759d3e43..fe12d6f87 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,7 @@ import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; -import reportWebVitals from "./reportWebVitals"; + import { BrowserRouter } from "react-router-dom"; const root = ReactDOM.createRoot(document.getElementById("root")); @@ -13,8 +13,3 @@ root.render( ); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/src/pages/.env b/src/pages/.env new file mode 100644 index 000000000..574bfc68e --- /dev/null +++ b/src/pages/.env @@ -0,0 +1,6 @@ + + +REACT_APP_EMAILJS_SERVICE_ID = "service_s4uzwtb", +REACT_APP_EMAILJS_TEMPLATE = "template_v8g6das", +REACT_APP_EMAILJS_USER_ID = "iJ5X1Aaus43y08qUB" + diff --git a/src/pages/FooterLine.jsx b/src/pages/FooterLine.jsx new file mode 100644 index 000000000..0c4d8c88d --- /dev/null +++ b/src/pages/FooterLine.jsx @@ -0,0 +1,7 @@ +import React from "react"; + +const FooterLine = () => { + return
    ; +}; + +export default FooterLine; diff --git a/src/pages/RavkeeratSinghCV.pdf b/src/pages/RavkeeratSinghCV.pdf new file mode 100644 index 000000000..c38427f58 Binary files /dev/null and b/src/pages/RavkeeratSinghCV.pdf differ diff --git a/src/pages/about.jsx b/src/pages/about.jsx index 8f49ef977..316ae0ede 100644 --- a/src/pages/about.jsx +++ b/src/pages/about.jsx @@ -1,16 +1,11 @@ import React, { useEffect } from "react"; import { Helmet } from "react-helmet"; - import NavBar from "../components/common/navBar"; import Footer from "../components/common/footer"; -import Logo from "../components/common/logo"; import Socials from "../components/about/socials"; - import INFO from "../data/user"; import SEO from "../data/seo"; -import "./styles/about.css"; - const About = () => { useEffect(() => { window.scrollTo(0, 0); @@ -29,40 +24,34 @@ const About = () => { /> -
    - -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - {INFO.about.title} -
    + -
    - {INFO.about.description} -
    -
    - -
    -
    -
    - about + diff --git a/src/pages/articles.jsx b/src/pages/articles.jsx deleted file mode 100644 index a66ad5940..000000000 --- a/src/pages/articles.jsx +++ /dev/null @@ -1,79 +0,0 @@ -import React, { useEffect } from "react"; -import { Helmet } from "react-helmet"; - -import NavBar from "../components/common/navBar"; -import Footer from "../components/common/footer"; -import Logo from "../components/common/logo"; -import Article from "../components/articles/article"; - -import INFO from "../data/user"; -import SEO from "../data/seo"; -import myArticles from "../data/articles"; - -import "./styles/articles.css"; - -const Articles = () => { - useEffect(() => { - window.scrollTo(0, 0); - }, []); - - const currentSEO = SEO.find((item) => item.page === "articles"); - - return ( - - - {`Articles | ${INFO.main.title}`} - - - - -
    - -
    -
    -
    - -
    -
    - -
    -
    - {INFO.articles.title} -
    - -
    - {INFO.articles.description} -
    - -
    -
    - {myArticles.map((article, index) => ( -
    -
    -
    - ))} -
    -
    -
    -
    -
    -
    -
    -
    -
    - ); -}; - -export default Articles; diff --git a/src/pages/contact.jsx b/src/pages/contact.jsx index 7b73ae4bd..e63428ab6 100644 --- a/src/pages/contact.jsx +++ b/src/pages/contact.jsx @@ -1,91 +1,106 @@ -import React, { useEffect } from "react"; -import { Helmet } from "react-helmet"; - +import React, { useState } from "react"; +import emailjs from "emailjs-com"; import NavBar from "../components/common/navBar"; import Footer from "../components/common/footer"; -import Logo from "../components/common/logo"; -import Socials from "../components/about/socials"; - -import INFO from "../data/user"; -import SEO from "../data/seo"; -import "./styles/contact.css"; +const ContactForm = () => { + const [formData, setFormData] = useState({ + name: "", + email: "", + message: "", + }); -const Contact = () => { - useEffect(() => { - window.scrollTo(0, 0); - }, []); + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; - const currentSEO = SEO.find((item) => item.page === "contact"); + const handleSubmit = (e) => { + e.preventDefault(); - return ( - - - {`Contact | ${INFO.main.title}`} - - - + // Send email using EmailJS + emailjs + .sendForm( + "service_s4uzwtb", + "template_v8g6das", + e.target, + "iJ5X1Aaus43y08qUB" + ) + .then( + (result) => { + console.log("Email sent successfully:", result.text); + alert("Your message has been sent successfully!"); + }, + (error) => { + console.error("Error sending email:", error.text); + alert( + "Oops! Something went wrong. Please try again later." + ); + } + ); -
    - -
    -
    -
    - -
    -
    + setFormData({ + name: "", + email: "", + message: "", + }); + }; -
    -
    - Let's Get in Touch: Ways to Connect with Me -
    + return ( +
    + +
    +

    Contact Me

    -
    - Thank you for your interest in getting in touch with - me. I welcome your feedback, questions, and - suggestions. If you have a specific question or - comment, please feel free to email me directly at -  {" "} - - {INFO.main.email} - - . I make an effort to respond to all messages within - 24 hours, although it may take me longer during busy - periods. Alternatively, you can use the contact form - on my website to get in touch. Simply fill out the - required fields and I'll get back to you as soon as - possible. Finally, if you prefer to connect on - social media, you can find me on{" "} - - {INFO.socials.instagram} - - . I post regular updates and engage with my - followers there, so don't hesitate to reach out. - Thanks again for your interest, and I look forward - to hearing from you! -
    +
    +
    + +
    - -
    -
    - -
    +
    + +
    - -
    -
    +
    + +
    -
    + +
    - +
    +
    ); }; -export default Contact; +export default ContactForm; diff --git a/src/pages/homepage.jsx b/src/pages/homepage.jsx index 3ee3de60e..5f8c0159e 100644 --- a/src/pages/homepage.jsx +++ b/src/pages/homepage.jsx @@ -1,205 +1,93 @@ -import React, { useState, useEffect } from "react"; +import React, { useEffect } from "react"; import { Helmet } from "react-helmet"; - import { faMailBulk } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faTwitter, - faGithub, - faStackOverflow, - faInstagram, -} from "@fortawesome/free-brands-svg-icons"; - -import Logo from "../components/common/logo"; +import { faGithub, faLinkedin } from "@fortawesome/free-brands-svg-icons"; import Footer from "../components/common/footer"; import NavBar from "../components/common/navBar"; -import Article from "../components/homepage/article"; import Works from "../components/homepage/works"; -import AllProjects from "../components/projects/allProjects"; - import INFO from "../data/user"; -import SEO from "../data/seo"; -import myArticles from "../data/articles"; - -import "./styles/homepage.css"; const Homepage = () => { - const [stayLogo, setStayLogo] = useState(false); - const [logoSize, setLogoSize] = useState(80); - const [oldLogoSize, setOldLogoSize] = useState(80); - useEffect(() => { window.scrollTo(0, 0); }, []); - useEffect(() => { - const handleScroll = () => { - let scroll = Math.round(window.pageYOffset, 2); - - let newLogoSize = 80 - (scroll * 4) / 10; - - if (newLogoSize < oldLogoSize) { - if (newLogoSize > 40) { - setLogoSize(newLogoSize); - setOldLogoSize(newLogoSize); - setStayLogo(false); - } else { - setStayLogo(true); - } - } else { - setLogoSize(newLogoSize); - setStayLogo(false); - } - }; - - window.addEventListener("scroll", handleScroll); - return () => window.removeEventListener("scroll", handleScroll); - }, [logoSize, oldLogoSize]); - - const currentSEO = SEO.find((item) => item.page === "home"); - - const logoStyle = { - display: "flex", - position: stayLogo ? "fixed" : "relative", - top: stayLogo ? "3vh" : "auto", - zIndex: 999, - border: stayLogo ? "1px solid white" : "none", - borderRadius: stayLogo ? "50%" : "none", - boxShadow: stayLogo ? "0px 4px 10px rgba(0, 0, 0, 0.25)" : "none", - }; - return ( - + <> {INFO.main.title} - - + -
    +
    -
    -
    -
    - +
    +
    +
    + {INFO.homepage.title}
    -
    - -
    -
    -
    -
    - {INFO.homepage.title} -
    -
    - {INFO.homepage.description} +
    +
    +
    +

    + {INFO.homepage.description} +

    -
    - - -
    - - - -
    - -
    - -
    -
    - {myArticles.map((article, index) => ( - - ))} -
    - -
    -
    -
    + {/* Work */} +
    +
    +
    {" "} + {/* Line before footer */} +
    - + ); }; diff --git a/src/pages/projects.jsx b/src/pages/projects.jsx index 9c423b230..b3df1f154 100644 --- a/src/pages/projects.jsx +++ b/src/pages/projects.jsx @@ -1,9 +1,11 @@ import React, { useEffect } from "react"; import { Helmet } from "react-helmet"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faGithub } from "@fortawesome/free-brands-svg-icons"; +import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; import NavBar from "../components/common/navBar"; import Footer from "../components/common/footer"; -import Logo from "../components/common/logo"; import AllProjects from "../components/projects/allProjects"; import INFO from "../data/user"; @@ -28,43 +30,37 @@ const Projects = () => { content={currentSEO.keywords.join(", ")} /> + +
    +
    +
    Projects
    -
    - -
    -
    -
    - -
    +
    + Here, you'll find a curated list of projects I've + developed using the{" "} + + MERN (MongoDB, Express.js, React.js, Node.js) stack + + . These projects showcase my proficiency in building + full-stack web applications, employing modern + technologies and best practices. One of the notable + projects is my{" "} + Capstone project, "Time Master", which + demonstrates my skills in creating user-centric + applications for efficient time management.
    -
    -
    - Things I’ve made trying to put my dent in the - universe. -
    -
    - I've worked on a variety of projects over the years - and I'm proud of the progress I've made. Many of - these projects are open-source and available for - others to explore and contribute to. If you're - interested in any of the projects I've worked on, - please feel free to check out the code and suggest - any improvements or enhancements you might have in - mind. Collaborating with others is a great way to - learn and grow, and I'm always open to new ideas and - feedback. -
    - -
    - -
    -
    -
    -
    +