├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── src
├── App.css
├── App.js
├── App.test.js
├── components
│ ├── ContactForm.js
│ ├── FeaturedProject.js
│ ├── FramerMotion.js
│ ├── NavBar.js
│ ├── Projects.js
│ ├── SocialMedia.js
│ ├── TextAnimation.js
│ ├── detail-project
│ │ ├── DetailProject.css
│ │ └── DetailProject.js
│ └── featured-project
│ │ ├── FeaturedProjectMedium.js
│ │ └── FeaturedProjectSmall.js
├── data
│ └── imgData.js
├── hooks
│ └── CustomHook.js
├── img
│ ├── 0001.png
│ ├── 558669671596975469.gif
│ ├── EF7C8E.jpg
│ ├── Pokemon.jpg
│ ├── avatar.gif
│ ├── barSite.jpg
│ ├── connectFour.jpg
│ ├── disney.jpg
│ ├── hotelProject.jpg
│ ├── planner.jpg
│ ├── random.jpg
│ ├── starWar.jpg
│ └── starWars.jpg
├── index.css
├── index.js
├── logo.svg
├── pages
│ ├── About.js
│ ├── Footer.js
│ ├── Home.js
│ └── Work.js
├── reportWebVitals.js
├── services
│ ├── project-api.js
│ └── quotes-api.js
└── setupTests.js
└── tailwind.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # My Portfolio
2 | > This is my web portfolio to introduce my self
3 |
4 | ## About
5 | [My Porfolio](https://tmp-portfolio.onrender.com/) - This is a deployment link for my portfolio website
6 |
7 | ### Main Features
8 | - Responsive Design
9 | - Fetching Quotes API
10 | - Sticky Nav Bar
11 | - Applying Bootstrap and Tailwind library framework
12 | - Validation for contact form
13 |
14 | ### Build With
15 | - 
16 | - 
17 | - 
18 | - 
19 | - 
20 | - 
21 | - 
22 |
23 | ## Getting Started
24 |
25 | ### Available Scripts
26 |
27 | In the project directory, you can run:
28 |
29 | ### `npm start`
30 |
31 | Runs the app in the development mode.\
32 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
33 |
34 | The page will reload when you make changes.\
35 | You may also see any lint errors in the console.
36 |
37 | ### `npm test`
38 |
39 | Launches the test runner in the interactive watch mode.\
40 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
41 |
42 | ### `npm run build`
43 |
44 | Builds the app for production to the `build` folder.\
45 | It correctly bundles React in production mode and optimizes the build for the best performance.
46 |
47 | The build is minified and the filenames include the hashes.\
48 | Your app is ready to be deployed!
49 |
50 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
51 |
52 | ## Roadmap
53 |
54 | [ ] Local Storage
55 |
56 | ## License
57 | Distributed under the MIT License. See `LICENSE.txt` for more information
58 |
59 | ## Contact
60 | My Phung Tieu - [LinkedIn](https://www.linkedin.com/in/my-phung-tieu-0bba22219/) - [Github](https://github.com/tmp03099):heart_eyes:
61 |
62 |
63 | Project Link - [My Portfolio](https://tmp-portfolio.onrender.com/)
64 |
65 | ## Acknowledgements
66 | - [API Qoute](https://animechan.vercel.app/)
67 | - [Tailwind](https://tailwindcss.com/docs/installation)
68 | - [React BootStrap](https://react-bootstrap.netlify.app/getting-started/introduction)
69 | - [Formik](https://formik.org/docs/tutorial)
70 | - [Netlify](https://app.netlify.com/)
71 |
72 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-portfolio",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@fortawesome/fontawesome-svg-core": "^6.4.0",
7 | "@fortawesome/free-brands-svg-icons": "^6.4.0",
8 | "@fortawesome/free-solid-svg-icons": "^6.4.0",
9 | "@fortawesome/react-fontawesome": "^0.2.0",
10 | "@testing-library/jest-dom": "^5.16.5",
11 | "@testing-library/react": "^13.4.0",
12 | "@testing-library/user-event": "^13.5.0",
13 | "axios": "^1.3.4",
14 | "bootstrap": "^5.2.3",
15 | "deepai": "^1.0.21",
16 | "formik": "^2.2.9",
17 | "framer-motion": "^10.10.0",
18 | "install": "^0.13.0",
19 | "next-gallery": "^1.2.1",
20 | "npm": "^9.6.2",
21 | "react": "^18.2.0",
22 | "react-bootstrap": "^2.7.2",
23 | "react-dom": "^18.2.0",
24 | "react-icons": "^4.8.0",
25 | "react-router-dom": "^6.9.0",
26 | "react-scripts": "5.0.1",
27 | "react-scroll": "^1.8.9",
28 | "web-vitals": "^2.1.4",
29 | "yup": "^1.0.2"
30 | },
31 | "scripts": {
32 | "start": "react-scripts start",
33 | "build": "react-scripts build",
34 | "test": "react-scripts test",
35 | "eject": "react-scripts eject"
36 | },
37 | "eslintConfig": {
38 | "extends": [
39 | "react-app",
40 | "react-app/jest"
41 | ]
42 | },
43 | "browserslist": {
44 | "production": [
45 | ">0.2%",
46 | "not dead",
47 | "not op_mini all"
48 | ],
49 | "development": [
50 | "last 1 chrome version",
51 | "last 1 firefox version",
52 | "last 1 safari version"
53 | ]
54 | },
55 | "devDependencies": {
56 | "tailwindcss": "^3.3.0"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 |
30 |
31 | React App
32 |
33 |
34 | You need to enable JavaScript to run this app.
35 |
36 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 | import NavBar from "./components/NavBar";
3 | import Home from "./pages/Home";
4 | import About from "./pages/About";
5 | import Work from "./pages/Work";
6 | import Footer from "./pages/Footer";
7 |
8 | function App() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
20 | export default App;
21 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render( );
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/src/components/ContactForm.js:
--------------------------------------------------------------------------------
1 | import { useFormik } from "formik";
2 | import * as Yup from "yup";
3 |
4 | function ContactForm() {
5 | const formik = useFormik({
6 | initialValues: {
7 | fullName: "",
8 | email: "",
9 | phone: "",
10 | },
11 |
12 | validationSchema: Yup.object({
13 | fullName: Yup.string().min(2, "Too Short!").required("Required"),
14 | email: Yup.string().email("Invalid email").required("Required"),
15 | phone: Yup.string()
16 | .min(9, "Too Short!")
17 | .max(11, "Too Long!")
18 | .required("Required"),
19 | }),
20 | onSubmit: (values, { resetForm }) => {
21 | resetForm({ values: "" });
22 | alert("Your successfully submit the form ");
23 | },
24 | });
25 |
26 | return (
27 |
141 | );
142 | }
143 | export default ContactForm;
144 |
--------------------------------------------------------------------------------
/src/components/FeaturedProject.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import { getFeatureProjects } from "../services/project-api";
3 | import { useViewport } from "../hooks/CustomHook";
4 | import FeaturedProjectMedium from "./featured-project/FeaturedProjectMedium";
5 | import FeaturedProjectSmall from "./featured-project/FeaturedProjectSmall";
6 |
7 | function FeaturedProject() {
8 | const [fProject, setFProject] = useState([]);
9 |
10 | const { width } = useViewport();
11 | const small = 650;
12 |
13 | useEffect(() => {
14 | const loadProject = () => {
15 | const data = getFeatureProjects();
16 | setFProject(data);
17 | };
18 | loadProject();
19 | }, []);
20 |
21 | return (
22 |
23 | {fProject.map((item, idx) =>
24 | width < small ? (
25 |
26 | ) : (
27 |
28 | )
29 | )}
30 |
31 | );
32 | }
33 | export default FeaturedProject;
34 |
--------------------------------------------------------------------------------
/src/components/FramerMotion.js:
--------------------------------------------------------------------------------
1 | import { motion } from "framer-motion";
2 |
3 | function FramerMotion({ slogan }) {
4 | const words = slogan.split("");
5 |
6 | // Variants for container of words
7 | const container = {
8 | hidden: { opacity: 0 },
9 | visible: (i = 1) => ({
10 | opacity: 1,
11 | transition: { staggerChildren: 0.15, delayChildren: 0.04 * i },
12 | }),
13 | };
14 |
15 | // Variants for each word
16 | const child = {
17 | visible: {
18 | opacity: 1,
19 | x: 0,
20 | transition: {
21 | type: "spring",
22 | damping: 12,
23 | stiffness: 100,
24 | },
25 | },
26 | hidden: {
27 | opacity: 0,
28 | x: 20,
29 | transition: {
30 | type: "spring",
31 | damping: 12,
32 | stiffness: 100,
33 | },
34 | },
35 | };
36 |
37 | return (
38 |
45 | {words.map((word, index) => (
46 |
53 | {word}
54 |
55 | ))}
56 |
57 | );
58 | }
59 | export default FramerMotion;
60 |
--------------------------------------------------------------------------------
/src/components/NavBar.js:
--------------------------------------------------------------------------------
1 | import Navbar from "react-bootstrap/Navbar";
2 | import Nav from "react-bootstrap/Nav";
3 | import Container from "react-bootstrap/Container";
4 | import { Link as LinkScroll } from "react-scroll";
5 | import logoImg from "../img/0001.png";
6 |
7 | function NavBar() {
8 | return (
9 | <>
10 |
11 |
12 |
13 |
18 |
19 |
20 |
25 |
26 |
34 | Home
35 |
36 |
43 | About
44 |
45 |
52 | Work
53 |
54 |
61 | Contact
62 |
63 |
67 | Resume
68 |
69 |
70 |
71 |
72 |
73 | >
74 | );
75 | }
76 |
77 | export default NavBar;
78 |
--------------------------------------------------------------------------------
/src/components/Projects.js:
--------------------------------------------------------------------------------
1 | import DetailProject from "./detail-project/DetailProject";
2 | import { useState, useEffect } from "react";
3 | import { getProjects } from "../services/project-api";
4 |
5 | function Projects() {
6 | const [project, setProject] = useState([]);
7 |
8 | useEffect(() => {
9 | const loadProject = () => {
10 | const data = getProjects();
11 | setProject(data);
12 | };
13 | loadProject();
14 | }, []);
15 |
16 | return (
17 |
18 | OTHER PROJECTS
19 |
20 | {project.map((ele, idx) => (
21 |
22 | ))}
23 |
24 |
25 | );
26 | }
27 | export default Projects;
28 |
--------------------------------------------------------------------------------
/src/components/SocialMedia.js:
--------------------------------------------------------------------------------
1 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2 | import { faGithub } from "@fortawesome/free-brands-svg-icons";
3 | import { faInstagram } from "@fortawesome/free-brands-svg-icons";
4 | import { faLinkedin } from "@fortawesome/free-brands-svg-icons";
5 |
6 | function SocialMedia() {
7 | return (
8 |
36 | );
37 | }
38 | export default SocialMedia;
39 |
--------------------------------------------------------------------------------
/src/components/TextAnimation.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import FramerMotion from "./FramerMotion";
3 |
4 | function TextAnimation() {
5 | useEffect(() => {
6 | const array = ["Simple", "Creative", "Impressive", "Effective"];
7 | let arrayIdx = 0;
8 |
9 | const countinue = () => {
10 | // countinue looping
11 | if (arrayIdx < array.length) {
12 | fadeIn();
13 | arrayIdx++; // loop the next word
14 | } else {
15 | arrayIdx = 0;
16 | fadeIn();
17 | }
18 | };
19 |
20 | const fadeIn = () => {
21 | // get Element by Id
22 | const arrSpan = document.getElementById("text-store");
23 |
24 | //remove the previous word
25 | while (arrSpan.firstElementChild) {
26 | arrSpan.removeChild(arrSpan.firstElementChild);
27 | }
28 |
29 | //create element span for each word
30 | const span = document.createElement("span");
31 | span.id = "text-animation";
32 |
33 | // span.style.animation = "fadeInOut 3s ease-in-out";
34 | span.style.position = "absolute"; //need set up position
35 | //set the text content equal each word
36 | span.textContent = array[arrayIdx];
37 |
38 | //append each word span to the parent arrSpan
39 | arrSpan.appendChild(span);
40 |
41 | setTimeout(() => {
42 | span.remove();
43 | countinue();
44 | }, 3000);
45 | };
46 |
47 | countinue();
48 | }, []);
49 |
50 | return (
51 |
52 |
53 |
54 |
55 |
59 |
60 | );
61 | }
62 | export default TextAnimation;
63 |
--------------------------------------------------------------------------------
/src/components/detail-project/DetailProject.css:
--------------------------------------------------------------------------------
1 | .hide-section {
2 | height: 0;
3 | opacity: 0;
4 |
5 | transition-property: background-color, opacity, height;
6 | transition: 0.5s ease-in-out;
7 | }
8 |
9 | .hover {
10 | height: 50%;
11 | opacity: 1;
12 | background-color: rgb(255, 255, 255);
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/detail-project/DetailProject.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import "./DetailProject.css";
3 |
4 | function DetailProject({ project }) {
5 | const [hover, setHover] = useState(false);
6 |
7 | function mousetEnter() {
8 | setHover(true);
9 | }
10 |
11 | function mouseLeave() {
12 | setHover(false);
13 | }
14 |
15 | return (
16 |
17 |
22 |
27 |
28 |
34 |
35 | {project.title}
36 |
37 |
38 | {project.programs}
39 |
40 |
41 |
58 |
59 |
60 |
61 | );
62 | }
63 | export default DetailProject;
64 |
--------------------------------------------------------------------------------
/src/components/featured-project/FeaturedProjectMedium.js:
--------------------------------------------------------------------------------
1 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2 | import { faGithub } from "@fortawesome/free-brands-svg-icons";
3 | import { faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
4 |
5 | function FeaturedProjectMedium({ project }) {
6 | return (
7 |
11 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
38 |
39 |
44 |
Feature Project
45 |
{project.title}
46 |
47 | {project.description}
48 |
49 |
{project.programs}
50 |
62 |
63 |
64 | );
65 | }
66 |
67 | export default FeaturedProjectMedium;
68 |
--------------------------------------------------------------------------------
/src/components/featured-project/FeaturedProjectSmall.js:
--------------------------------------------------------------------------------
1 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2 | import { faGithub } from "@fortawesome/free-brands-svg-icons";
3 | import { faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
4 |
5 | function FeaturedProjectSmall({ project }) {
6 | return (
7 |
11 |
15 |
16 |
Feature Project
17 |
{project.title}
18 |
{project.description}
19 |
20 | {project.programs}
21 |
22 |
34 |
35 |
36 |
37 | );
38 | }
39 |
40 | export default FeaturedProjectSmall;
41 |
--------------------------------------------------------------------------------
/src/data/imgData.js:
--------------------------------------------------------------------------------
1 | import hotelProject from "../img/hotelProject.jpg";
2 | import connectFour from "../img/connectFour.jpg";
3 | import pokemon from "../img/Pokemon.jpg";
4 | import planner from "../img/planner.jpg";
5 | import foodRandom from "../img/random.jpg";
6 | import disney from "../img/disney.jpg";
7 | import barSite from "../img/barSite.jpg";
8 | import starWars from "../img/starWar.jpg";
9 |
10 | export const imgData = [
11 | {
12 | top: true,
13 | src: planner,
14 | alt: "plannerApp.img",
15 | title: "Travel Planner",
16 | programs: "React Node.js MongoDB JSON Tailwinds ",
17 | description:
18 | "A version website planner for traveller that help them manage and planning their trip is eaiser and faster.",
19 | github: "https://github.com/tmp03099/Travel-Planner",
20 | link: "https://travel-planner-api.onrender.com",
21 | },
22 | {
23 | top: false,
24 | src: hotelProject,
25 | alt: "hotel.img",
26 | title: "Hotel Booking",
27 | programs: "Java RestAPI Spring Boot Angular Typescript PrimeNG ",
28 | description:
29 | "A version web Hotel Booking that allow you fill in the date to search available room, filter out and booking",
30 | github: "https://github.com/tmp03099/BookingApplication",
31 | link: "https://main--laplace-hotel.netlify.app/home",
32 | },
33 | {
34 | top: true,
35 | src: connectFour,
36 | alt: "connect4.img",
37 | title: "Connect Four Game",
38 | programs: "JavaScripts HTML5 CSS3 HTML-DOM ",
39 | description: `A website version connect four game with fully functional,
40 | sounds and animation. Developed responsive design for any devices `,
41 | github: "https://github.com/tmp03099/connect-four-game.github.io",
42 | link: "https://tmp03099.github.io/connect-four-game.github.io/",
43 | },
44 | {
45 | top: false,
46 | src: foodRandom,
47 | alt: "foodRandom.img",
48 | title: "Food Random",
49 | programs: "Angular | Typescript | NgWheel | LocalStorage | JSON | PrimeNG",
50 | github: "https://github.com/tmp03099/FoodRandom",
51 | link: "https://github.com/tmp03099/FoodRandom",
52 | },
53 | {
54 | top: false,
55 | src: disney,
56 | alt: "disney.img",
57 | title: "Disney Character",
58 | programs: "React | Router | API | Axios",
59 | github: "https://github.com/tmp03099/Disney-Characters",
60 | link: "https://main--disneycharactersapp.netlify.app/",
61 | },
62 | {
63 | top: false,
64 | src: pokemon,
65 | alt: "pokemon.img",
66 | title: "Pokemon Card Game",
67 | programs: "HTML5 | CSS3 | Bootstraps | JavaScript | HTML DOM",
68 | github: "https://github.com/tmp03099/memory-card-game",
69 | link: "https://tmp03099.github.io/memory-card-game/",
70 | },
71 | {
72 | top: false,
73 | src: barSite,
74 | alt: "barsite.img",
75 | title: "Bar Website",
76 | programs: "HTML5 | CSS3 | jQuery | JavaScript",
77 | github: "https://github.com/tmp03099/BarWebPage.github.io",
78 | link: "https://main--barswebsite.netlify.app/",
79 | },
80 | {
81 | top: false,
82 | src: starWars,
83 | alt: "starWars.img",
84 | title: "Star Wars Pagination ",
85 | programs: "React | Router | API | Axios | Pagination",
86 | github: "https://github.com/tmp03099/STAR-WARS-API",
87 | link: "https://starwarsapi-app.netlify.app/",
88 | },
89 | ];
90 |
--------------------------------------------------------------------------------
/src/hooks/CustomHook.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | export const useViewport = () => {
4 | const [width, setWidth] = useState(window.innerWidth);
5 | // Add a second state variable "height" and default it to the current window height
6 | const [height, setHeight] = useState(window.innerHeight);
7 |
8 | useEffect(() => {
9 | const handleWindowResize = () => {
10 | setWidth(window.innerWidth);
11 | // Set the height in state as well as the width
12 | setHeight(window.innerHeight);
13 | };
14 |
15 | window.addEventListener("resize", handleWindowResize);
16 | return () => window.removeEventListener("resize", handleWindowResize);
17 | }, []);
18 |
19 | // Return both the height and width
20 | return { width, height };
21 | };
22 |
--------------------------------------------------------------------------------
/src/img/0001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/0001.png
--------------------------------------------------------------------------------
/src/img/558669671596975469.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/558669671596975469.gif
--------------------------------------------------------------------------------
/src/img/EF7C8E.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/EF7C8E.jpg
--------------------------------------------------------------------------------
/src/img/Pokemon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/Pokemon.jpg
--------------------------------------------------------------------------------
/src/img/avatar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/avatar.gif
--------------------------------------------------------------------------------
/src/img/barSite.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/barSite.jpg
--------------------------------------------------------------------------------
/src/img/connectFour.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/connectFour.jpg
--------------------------------------------------------------------------------
/src/img/disney.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/disney.jpg
--------------------------------------------------------------------------------
/src/img/hotelProject.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/hotelProject.jpg
--------------------------------------------------------------------------------
/src/img/planner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/planner.jpg
--------------------------------------------------------------------------------
/src/img/random.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/random.jpg
--------------------------------------------------------------------------------
/src/img/starWar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/starWar.jpg
--------------------------------------------------------------------------------
/src/img/starWars.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmp03099/MyPortfolio/15d0a4f855570a7489b5dde4e7260f31d727c9e5/src/img/starWars.jpg
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | #home {
6 | background-color: #ef7c8e;
7 | }
8 |
9 | #about {
10 | background-image: linear-gradient(
11 | to bottom,
12 | #ef7c8e,
13 | #f59999,
14 | #f8b4aa,
15 | #f9cfc2,
16 | #fae8e0
17 | );
18 | }
19 |
20 | #projects {
21 | background-image: linear-gradient(
22 | to bottom,
23 | #fae8e0,
24 | #f4dcd4,
25 | #efcfca,
26 | #e9c3c1,
27 | #e2b7b9,
28 | #e2b6b2,
29 | #e0b5ab,
30 | #deb4a4,
31 | #d8c0a2,
32 | #cccdab,
33 | #bfd9bc,
34 | #b6e2d3
35 | );
36 | }
37 |
38 | #contact {
39 | background-image: linear-gradient(
40 | to bottom,
41 | #b6e2d3,
42 | #bee9da,
43 | #c6f0e2,
44 | #cff8e9,
45 | #d7fff1
46 | );
47 | }
48 |
49 | .projectBg {
50 | background-color: #220814;
51 | }
52 |
53 | /* Font family */
54 | h5,
55 | .fontSyne {
56 | font-family: "Syne Mono";
57 | }
58 |
59 | h2 {
60 | font-family: "Silkscreen";
61 | }
62 |
63 | h3,
64 | .fontRib {
65 | font-family: "Ribeye";
66 | }
67 |
68 | h1,
69 | .fontCoiny {
70 | font-family: "Coiny";
71 | }
72 |
73 | span,
74 | .fontVT {
75 | font-family: "VT323";
76 | }
77 |
78 | p,
79 | .fontSourceCode {
80 | font-family: "Source Code Pro", monospace;
81 | }
82 |
83 | .fontIncon {
84 | font-family: "Inconsolata";
85 | }
86 |
87 | /* Detail Projects */
88 | .captionImg {
89 | background-color: rgba(255, 255, 255, 0.7);
90 | visibility: none;
91 | opacity: 0;
92 | z-index: 2;
93 | }
94 |
95 | .storeImg:hover .captionImg {
96 | visibility: visible;
97 | opacity: 1;
98 | }
99 |
100 | /* Hover effect */
101 | .hoverEffect {
102 | letter-spacing: 6px;
103 | cursor: pointer;
104 | }
105 |
106 | .hoverEffect span {
107 | transition: 0.8s ease-out;
108 | }
109 | .hoverEffect:hover span:nth-child(1) {
110 | margin-right: 30px;
111 | }
112 |
113 | .hoverEffect:hover span:nth-child(3) {
114 | margin-left: 30px;
115 | }
116 | .hoverEffect:hover span {
117 | color: #fff;
118 | text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 40px #fff;
119 | }
120 |
121 | @keyframes fadeInOut {
122 | 0% {
123 | opacity: 0;
124 | font-size: 150px;
125 | transform: translateX(-100%);
126 | filter: blur(1vmin);
127 | }
128 | 50% {
129 | opacity: 1;
130 | font-size: 60px;
131 | transform: translateX(0%);
132 | filter: blur(0.02vmin);
133 | color: #fff;
134 | text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 40px #fff;
135 | }
136 | 100% {
137 | opacity: 0;
138 | font-size: 150px;
139 | transform: translateX(100%);
140 | filter: blur(1vmin);
141 | }
142 | }
143 |
144 | @keyframes fadeInOutSmall {
145 | 0% {
146 | opacity: 0;
147 | font-size: 100px;
148 | transform: translateX(-100%);
149 | filter: blur(1vmin);
150 | }
151 | 50% {
152 | opacity: 1;
153 | font-size: 30px;
154 | transform: translateX(0%);
155 | filter: blur(0.02vmin);
156 | color: #fff;
157 | text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 40px #fff;
158 | }
159 | 100% {
160 | opacity: 0;
161 | font-size: 100px;
162 | transform: translateX(100%);
163 | filter: blur(1vmin);
164 | }
165 | }
166 |
167 | @media screen and (max-width: 650px) {
168 | .smAnimation {
169 | animation: fadeInOutSmall 3s ease-in-out infinite;
170 | }
171 | }
172 |
173 | @media screen and (min-width: 651px) {
174 | .smAnimation {
175 | animation: fadeInOut 3s ease-in-out infinite;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 | import 'bootstrap/dist/css/bootstrap.min.css';
7 |
8 | const root = ReactDOM.createRoot(document.getElementById('root'));
9 | root.render(
10 |
11 |
12 |
13 | );
14 |
15 | // If you want to start measuring performance in your app, pass a function
16 | // to log results (for example: reportWebVitals(console.log))
17 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
18 | reportWebVitals();
19 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pages/About.js:
--------------------------------------------------------------------------------
1 | import avatarImg from "../img/avatar.gif";
2 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3 | import {
4 | faReact,
5 | faAngular,
6 | faJsSquare,
7 | faJava,
8 | faBootstrap,
9 | } from "@fortawesome/free-brands-svg-icons";
10 | import { SiTypescript } from "react-icons/si";
11 | import { TbApi, TbBrandTailwind, TbDatabase } from "react-icons/tb";
12 | import Carousel from "react-bootstrap/Carousel";
13 |
14 | function About() {
15 | return (
16 |
20 | About Me
21 |
22 |
23 |
24 |
25 | Hi my name is Phung, I’m a frontend developer who enjoys creating
26 | fun and user friendly web applications for everyone. I have always
27 | been interested in computers and related topics such as system
28 | configuration, application design and coding.
29 |
30 |
31 | When it comes to coding, I always have a high standard for my
32 | applications where I spend a lot of time fine tuning and testing
33 | to make sure that the applications are bug free and easy for
34 | everyone to use.
35 |
36 |
37 | To start and advance in my career as a developer, I always try to
38 | improve my existing skills while learning new ones. A recent
39 | example is after completing my college degree, I am participating
40 | in coding bootcamp with Per-Scholars to further improve my front
41 | end development skills along with learning about some of the
42 | latest technologies such as React, Redux, MongoDB, NodeJs. These
43 | skills help me become an even better frontend developer.
44 |
45 |
46 |
47 |
48 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
63 |
64 |
68 |
69 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
85 |
86 |
87 |
88 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | );
100 | }
101 | export default About;
102 |
--------------------------------------------------------------------------------
/src/pages/Footer.js:
--------------------------------------------------------------------------------
1 | import ContactForm from "../components/ContactForm";
2 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3 | import { faPaperPlane } from "@fortawesome/free-solid-svg-icons";
4 | import Accordion from "react-bootstrap/Accordion";
5 | import { useAccordionButton } from "react-bootstrap/AccordionButton";
6 | import Card from "react-bootstrap/Card";
7 | import SocialMedia from "../components/SocialMedia";
8 |
9 | function Footer() {
10 | const CustomToggle = ({ children, eventKey }) => {
11 | const handleClick = useAccordionButton(eventKey, () =>
12 | console.log("totally custom!")
13 | );
14 |
15 | return (
16 |
17 | {children}
18 |
19 | );
20 | };
21 | return (
22 |
75 | );
76 | }
77 | export default Footer;
78 |
--------------------------------------------------------------------------------
/src/pages/Home.js:
--------------------------------------------------------------------------------
1 | import techImg from "../img/EF7C8E.jpg";
2 | import { Link as LinkScroll } from "react-scroll";
3 | import TextAnimation from "../components/TextAnimation";
4 | import { useState, useEffect } from "react";
5 | import { getQuotes } from "../services/quotes-api";
6 |
7 | function Home() {
8 | const [quote, setQuote] = useState([]);
9 |
10 | useEffect(() => {
11 | const quoteData = async () => {
12 | const data = await getQuotes();
13 | setQuote(data);
14 | console.log(data);
15 | };
16 | quoteData();
17 | }, []);
18 |
19 | return (
20 |
24 | Hi, I am
25 |
26 |
27 | My
28 |
29 | Phung
30 |
31 |
32 | Tieu
33 |
34 |
35 |
36 | Frontend Developer | Software Developer
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | {/* {quote.quote} */}
45 |
46 |
47 |
54 | About me
55 |
56 |
57 |
58 |
59 |
60 | );
61 | }
62 | export default Home;
63 |
--------------------------------------------------------------------------------
/src/pages/Work.js:
--------------------------------------------------------------------------------
1 | import FeaturedProject from "../components/FeaturedProject";
2 | import Projects from "../components/Projects";
3 |
4 | function Work() {
5 | return (
6 |
10 | Some Things I've Built
11 |
12 |
13 |
14 | );
15 | }
16 | export default Work;
17 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/services/project-api.js:
--------------------------------------------------------------------------------
1 | import { imgData } from "../data/imgData";
2 |
3 | export const getFeatureProjects = () => {
4 | return imgData.filter((item) => item.top === true);
5 | };
6 |
7 | export const getProjects = () => {
8 | return imgData.filter((item) => item.top === false);
9 | };
10 |
--------------------------------------------------------------------------------
/src/services/quotes-api.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | export const getQuotes = async () => {
3 | try {
4 | const respone = await axios.get("https://animechan.vercel.app/api/random");
5 | console.log(respone);
6 | const data = respone.data;
7 | console.log(data);
8 | return data;
9 | } catch (error) {
10 | console.error(error);
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./src/**/*.{js,jsx,ts,tsx}"],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | };
9 |
--------------------------------------------------------------------------------