@ -0,0 +1,8 @@ | |||
node_modules | |||
build | |||
.dockerignore | |||
Dockerfile | |||
.git | |||
.gitignore | |||
README.md | |||
npm-debug.log |
@ -0,0 +1,29 @@ | |||
# Step 1: Use a base image with Node.js | |||
FROM node:16 AS build | |||
# Step 2: Set the working directory inside the container | |||
WORKDIR /app | |||
# Step 3: Copy package.json and package-lock.json (or yarn.lock) | |||
COPY package*.json ./ | |||
# Step 4: Install dependencies | |||
RUN npm install | |||
# Step 5: Copy the rest of your application code | |||
COPY . . | |||
# Step 6: Build the React application | |||
RUN npm run build | |||
# Step 7: Use a base image to serve the application | |||
FROM nginx:alpine | |||
# Step 8: Copy the build output from the previous stage to the Nginx public directory | |||
COPY --from=build /app/build /usr/share/nginx/html | |||
# Step 9: Expose port 80 to the outside | |||
EXPOSE 80 | |||
# Step 10: Start the Nginx server | |||
CMD ["nginx", "-g", "daemon off;"] |
@ -1,5 +1,63 @@ | |||
# My Portfolio | |||
### `npm start` | |||
This is a personal portfolio web application built using React. It showcases various projects and skills and includes a contact form for users to get in touch. | |||
Runs the app in the development mode.\ | |||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser. | |||
## Table of Contents | |||
- [Getting Started](#getting-started) | |||
- [Features](#features) | |||
- [Installation](#installation) | |||
- [Usage](#usage) | |||
- [EmailJS Setup](#emailjs-setup) | |||
- [Contributing](#contributing) | |||
- [License](#license) | |||
## Getting Started | |||
To get a local copy of the project up and running, follow these simple steps. | |||
### Prerequisites | |||
Make sure you have the following installed: | |||
- [Node.js](https://nodejs.org/) (v14 or later) | |||
- [npm](https://www.npmjs.com/) (comes with Node.js) | |||
- [EmailJS](https://www.emailjs.com) | |||
Create an account on EmailJS, then create a new email service and template. Copy the Service ID, Template ID, and User ID. | |||
### EmailJS Configuration | |||
1. **Create a configuration file:** | |||
Create a file named `emailConfig.js` in the `src/components` directory with the following content: | |||
```javascript | |||
// src/components/emailConfig.js | |||
const emailConfig = { | |||
serviceId: 'yourserviceid', // Replace with your EmailJS Service ID | |||
templateId: 'yourtemplateid', // Replace with your EmailJS Template ID | |||
userId: 'youruserid' // Replace with your EmailJS User ID | |||
}; | |||
export default emailConfig; | |||
you then import it to the ContactForm.js | |||
### Installation | |||
1. **Install the dependencies:** | |||
bash | |||
npm install | |||
## Usage | |||
### Running the App | |||
To start the app in development mode: | |||
bash | |||
npm start |
@ -0,0 +1,4 @@ | |||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> | |||
<title>GitHub</title> | |||
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.302 3.438 9.8 8.207 11.387.6.11.82-.26.82-.577v-2.022c-3.338.725-4.033-1.41-4.033-1.41-.546-1.385-1.333-1.756-1.333-1.756-1.09-.745.083-.73.083-.73 1.204.084 1.837 1.236 1.837 1.236 1.07 1.835 2.807 1.305 3.492.997.108-.774.42-1.305.763-1.605-2.665-.304-5.466-1.333-5.466-5.93 0-1.31.47-2.38 1.236-3.22-.124-.303-.536-1.52.117-3.168 0 0 1.008-.322 3.3 1.23.957-.266 1.98-.398 3-.403 1.02.005 2.043.137 3 .403 2.29-1.552 3.297-1.23 3.297-1.23.653 1.648.242 2.865.118 3.168.77.84 1.235 1.91 1.235 3.22 0 4.61-2.803 5.624-5.475 5.92.43.372.814 1.102.814 2.222v3.293c0 .32.218.694.825.576C20.565 21.795 24 17.298 24 12c0-6.63-5.373-12-12-12z"/> | |||
</svg> |
@ -0,0 +1,4 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img"> | |||
<title>LinkedIn</title> | |||
<path d="M22.23 0H1.77C.79 0 0 .8 0 1.78v20.45C0 23.2.79 24 1.77 24h20.45c.98 0 1.78-.8 1.78-1.77V1.78C24 .8 23.21 0 22.23 0zM7.12 20.45H3.56V9h3.56v11.45zM5.34 7.48c-1.14 0-2.06-.93-2.06-2.08 0-1.15.92-2.08 2.06-2.08 1.14 0 2.07.93 2.07 2.08 0 1.15-.93 2.08-2.07 2.08zM20.45 20.45h-3.56v-5.58c0-1.33-.03-3.04-1.85-3.04-1.85 0-2.13 1.45-2.13 2.94v5.68h-3.56V9h3.42v1.56h.05c.48-.9 1.66-1.85 3.42-1.85 3.65 0 4.32 2.4 4.32 5.51v6.23z"/> | |||
</svg> |
@ -0,0 +1,104 @@ | |||
// src/components/ContactForm.js | |||
import React, { useState } from 'react'; | |||
import { Modal, Button, Form } from 'react-bootstrap'; | |||
import emailjs from 'emailjs-com'; | |||
import emailConfig from './apikey'; | |||
const ContactForm = ({ show, handleClose }) => { | |||
const [formData, setFormData] = useState({ | |||
firstName: '', | |||
lastName: '', | |||
email: '', | |||
message: '' | |||
}); | |||
const handleChange = (e) => { | |||
const { name, value } = e.target; | |||
setFormData({ | |||
...formData, | |||
[name]: value | |||
}); | |||
}; | |||
const handleSubmit = (e) => { | |||
e.preventDefault(); | |||
emailjs.send( | |||
emailConfig.serviceId, // EmailJS service ID | |||
emailConfig.templateId, // EmailJS template ID | |||
formData, | |||
emailConfig.userId // EmailJS user ID | |||
) | |||
.then((result) => { | |||
alert('Message sent successfully!'); | |||
handleClose(); | |||
}, (error) => { | |||
alert('Failed to send message, please try again.'); | |||
}); | |||
}; | |||
return ( | |||
<Modal show={show} onHide={handleClose}> | |||
<Modal.Header closeButton> | |||
<Modal.Title>Contact Me</Modal.Title> | |||
</Modal.Header> | |||
<Modal.Body> | |||
<Form onSubmit={handleSubmit}> | |||
<Form.Group controlId="formFirstName"> | |||
<Form.Label>First Name</Form.Label> | |||
<Form.Control | |||
type="text" | |||
placeholder="Enter your first name" | |||
name="firstName" | |||
value={formData.firstName} | |||
onChange={handleChange} | |||
required | |||
/> | |||
</Form.Group> | |||
<Form.Group controlId="formLastName"> | |||
<Form.Label>Last Name</Form.Label> | |||
<Form.Control | |||
type="text" | |||
placeholder="Enter your last name" | |||
name="lastName" | |||
value={formData.lastName} | |||
onChange={handleChange} | |||
required | |||
/> | |||
</Form.Group> | |||
<Form.Group controlId="formEmail"> | |||
<Form.Label>Email</Form.Label> | |||
<Form.Control | |||
type="email" | |||
placeholder="Enter your email" | |||
name="email" | |||
value={formData.email} | |||
onChange={handleChange} | |||
required | |||
/> | |||
</Form.Group> | |||
<Form.Group controlId="formMessage"> | |||
<Form.Label>Message</Form.Label> | |||
<Form.Control | |||
as="textarea" | |||
rows={3} | |||
placeholder="Enter your message" | |||
name="message" | |||
value={formData.message} | |||
onChange={handleChange} | |||
required | |||
/> | |||
</Form.Group> | |||
<Button variant="primary" type="submit"> | |||
Send Message | |||
</Button> | |||
</Form> | |||
</Modal.Body> | |||
</Modal> | |||
); | |||
}; | |||
export default ContactForm; |
@ -0,0 +1,67 @@ | |||
import React from 'react'; | |||
import Carousel from 'react-multi-carousel'; | |||
import 'react-multi-carousel/lib/styles.css'; | |||
const projects = [ | |||
{ | |||
title: 'Project One', | |||
description: 'This is a brief description of project one.', | |||
imageUrl: 'https://via.placeholder.com/150', | |||
link: 'https://github.com/yourusername/project-one' | |||
}, | |||
{ | |||
title: 'Project Two', | |||
description: 'This is a brief description of project two.', | |||
imageUrl: 'https://via.placeholder.com/150', | |||
link: 'https://github.com/yourusername/project-two' | |||
}, | |||
{ | |||
title: 'Project Three', | |||
description: 'This is a brief description of project three.', | |||
imageUrl: 'https://via.placeholder.com/150', | |||
link: 'https://github.com/yourusername/project-three' | |||
} | |||
]; | |||
const Projects = () => { | |||
const handleCardClick = (link) => { | |||
window.open(link, '_blank'); | |||
}; | |||
const responsive = { | |||
superLargeDesktop: { | |||
breakpoint: { max: 4000, min: 3000 }, | |||
items: 5 | |||
}, | |||
desktop: { | |||
breakpoint: { max: 3000, min: 1024 }, | |||
items: 3 | |||
}, | |||
tablet: { | |||
breakpoint: { max: 1024, min: 464 }, | |||
items: 2 | |||
}, | |||
mobile: { | |||
breakpoint: { max: 464, min: 0 }, | |||
items: 1 | |||
} | |||
}; | |||
return ( | |||
<section className="projects-section" id="projects"> | |||
<Carousel responsive={responsive} infinite={true} className="skill-slider"> | |||
{projects.map((project, index) => ( | |||
<div key={index} className="card-custom" onClick={() => handleCardClick(project.link)}> | |||
<img src={project.imageUrl} alt={project.title} /> | |||
<div className="card-custom-body"> | |||
<h5>{project.title}</h5> | |||
<p>{project.description}</p> | |||
</div> | |||
</div> | |||
))} | |||
</Carousel> | |||
</section> | |||
); | |||
}; | |||
export default Projects; |