merge with the master branch
|
@ -1,8 +1,10 @@
|
||||||
# SEG3125-LAB8
|
# SEG3125-LAB8
|
||||||
|
|
||||||
The Real Estate Website using React made by Ruchira Perrera, Sam Oyediran, Batuhan Basoglu, and Kene Ojukwu
|
The Real Estate Website using React made by Ruchira Perrera, Sam Oyediran, Batuhan Basoglu, and Kene Ojukwu.
|
||||||
|
|
||||||
|
|
||||||
|
After npm start execute the command "node src/shared-components/contact-us/index.js" in order to set up the backend of the contact form.
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
- Batuhan Basoglu, 300001274 - ArcticHawk1
|
- Batuhan Basoglu, 300001274 - ArcticHawk1
|
||||||
|
|
20791
package-lock.json
generated
28
package.json
|
@ -6,14 +6,27 @@
|
||||||
"@testing-library/jest-dom": "^5.11.10",
|
"@testing-library/jest-dom": "^5.11.10",
|
||||||
"@testing-library/react": "^11.2.5",
|
"@testing-library/react": "^11.2.5",
|
||||||
"@testing-library/user-event": "^12.8.3",
|
"@testing-library/user-event": "^12.8.3",
|
||||||
|
"axios": "^0.21.1",
|
||||||
"bootstrap": "^4.6.0",
|
"bootstrap": "^4.6.0",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"joi-browser": "^13.4.0",
|
||||||
|
"nodemailer": "^6.5.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-alert": "^7.0.2",
|
||||||
|
"react-alert-template-basic": "^1.0.0",
|
||||||
"react-bootstrap": "^1.5.2",
|
"react-bootstrap": "^1.5.2",
|
||||||
"react-bootstrap-carousel": "^4.1.1",
|
"react-bootstrap-carousel": "^4.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-fa": "^5.0.0",
|
||||||
|
"react-form-with-constraints": "^0.16.0",
|
||||||
|
"react-form-with-constraints-bootstrap4": "^0.16.0",
|
||||||
"react-google-maps": "^9.4.5",
|
"react-google-maps": "^9.4.5",
|
||||||
|
"react-hook-form": "^7.0.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
|
"react-select": "^4.3.0",
|
||||||
|
"reactstrap": "^8.9.0",
|
||||||
"spectre.css": "^0.5.9",
|
"spectre.css": "^0.5.9",
|
||||||
"web-vitals": "^1.1.1"
|
"web-vitals": "^1.1.1"
|
||||||
},
|
},
|
||||||
|
@ -43,5 +56,18 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"create-react-component-folder": "^0.3.7"
|
"create-react-component-folder": "^0.3.7"
|
||||||
}
|
},
|
||||||
|
"description": "The Real Estate Website using React made by Ruchira Perrera, Sam Oyediran, Batuhan Basoglu, and Kene Ojukwu.",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/ArcticHawk1/SEG3125-LAB8.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/ArcticHawk1/SEG3125-LAB8/issues"
|
||||||
|
},
|
||||||
|
"homepage": ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,10 @@ import HomePage from "./homePage/Homepage";
|
||||||
import ListingsPage from "./listings-page/ListingsPage";
|
import ListingsPage from "./listings-page/ListingsPage";
|
||||||
import AgentPage from "./agent-page/AgentPage";
|
import AgentPage from "./agent-page/AgentPage";
|
||||||
import ListingPage from "./listings-page/single-listing/listing-page";
|
import ListingPage from "./listings-page/single-listing/listing-page";
|
||||||
// import Login from "./login-page/Login";
|
import Login from "./login-page/Login";
|
||||||
import Account from "./login-page/account/Account";
|
// import Account from "./login-page/account/Account";
|
||||||
// import ContactUs from "./shared-components/Contact-us/Contact-us";
|
// import ContactUs from "./shared-components/Contact-us/Contact-us";
|
||||||
|
import ContactUs from "./shared-components/contact-us/contact-us";
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -20,7 +21,8 @@ class App extends Component {
|
||||||
<Route path="/listings" component={ListingsPage}></Route>
|
<Route path="/listings" component={ListingsPage}></Route>
|
||||||
<Route path="/agents" component={AgentPage}></Route>
|
<Route path="/agents" component={AgentPage}></Route>
|
||||||
<Route path="/listing-page" component={ListingPage}></Route>
|
<Route path="/listing-page" component={ListingPage}></Route>
|
||||||
<Route path="/login" component={Account}></Route>
|
<Route path="/login" component={Login}></Route>
|
||||||
|
<Route path="/contact-us" component={ContactUs}></Route>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
<Footer></Footer>
|
<Footer></Footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,25 +4,30 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.white-section {
|
.white-section {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
padding-top: 10rem;
|
||||||
|
padding-bottom: 5rem;
|
||||||
|
padding-left: 18%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#title .container-fluid {
|
#title .container-fluid {
|
||||||
padding: 4% 34% 6%;
|
padding: 5% 34% 6%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-family: "Georgia";
|
font-family: "Georgia";
|
||||||
}
|
}
|
||||||
|
|
||||||
#features .container-fluid {
|
#features .container-fluid {
|
||||||
padding: 2% 48% 2%;
|
padding: 2% 14% 4%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-family: "Georgia";
|
font-family: "Georgia";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.housesIntro{
|
.housesIntro{
|
||||||
padding: 4% 5%;
|
width: 1200px;
|
||||||
|
height: 800px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contactIntro{
|
.contactIntro{
|
||||||
|
@ -31,23 +36,9 @@
|
||||||
padding-bottom: 80px;
|
padding-bottom: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carouselSection {
|
|
||||||
margin: 2% 8%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerImg{
|
.headerImg{
|
||||||
width: 2000px;
|
width: 1200px;
|
||||||
height: 600px;
|
height: 800px;
|
||||||
}
|
|
||||||
|
|
||||||
.heading-1{
|
|
||||||
padding-left: 40%;
|
|
||||||
padding-top: 10%;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formhelper{
|
|
||||||
padding-bottom: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-1 {
|
.button-1 {
|
||||||
|
@ -67,3 +58,69 @@
|
||||||
padding-left: 45%;
|
padding-left: 45%;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.buttonka{
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev-icon,
|
||||||
|
.next-icon {
|
||||||
|
height: 210px;
|
||||||
|
width: 100px;
|
||||||
|
outline: black;
|
||||||
|
background-size: 100%, 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-image: none;
|
||||||
|
text-shadow: 2px 2px 5px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.next-icon:after
|
||||||
|
{
|
||||||
|
content: '>';
|
||||||
|
font-size: 140px;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
text-shadow: 2px 2px 5px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev-icon:after {
|
||||||
|
content: '<';
|
||||||
|
font-size: 140px;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
text-shadow: 2px 2px 5px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.carousel-indicators {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
margin: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.carousel-indicators li,
|
||||||
|
ol.carousel-indicators li.active {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: 0 0 1px 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.carousel-indicators li {
|
||||||
|
background: rgb(255, 255, 255);
|
||||||
|
margin-left: .5rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
box-shadow: 0 0 1px 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.carousel-indicators li.active {
|
||||||
|
background: #17a2b8;
|
||||||
|
box-shadow: 0 0 1px 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.homePage{
|
||||||
|
padding-bottom: 15%;
|
||||||
|
}
|
|
@ -3,20 +3,23 @@ import "./Homepage.css";
|
||||||
import house1 from "../images/house1.jpg";
|
import house1 from "../images/house1.jpg";
|
||||||
import house2 from "../images/house2.jpg";
|
import house2 from "../images/house2.jpg";
|
||||||
import house3 from "../images/house3.jpg";
|
import house3 from "../images/house3.jpg";
|
||||||
|
import house4 from "../images/house4.jpg";
|
||||||
import Carousel from "react-bootstrap/Carousel";
|
import Carousel from "react-bootstrap/Carousel";
|
||||||
|
import Button from "react-bootstrap/Button";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Homepage extends Component {
|
class Homepage extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
firstname: "",
|
nextIcon: <span className="next-icon"></span>,
|
||||||
lastname: "",
|
prevIcon: <span className="prev-icon"></span>,
|
||||||
email: "",
|
|
||||||
message: "",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { nextIcon, prevIcon } = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="homePage">
|
<div className="homePage">
|
||||||
<section className="colored-section" id="title">
|
<section className="colored-section" id="title">
|
||||||
|
@ -29,98 +32,70 @@ class Homepage extends Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="white-section" id="white-section">
|
<section className="white-section">
|
||||||
<div className="housesIntro">
|
<div className="housesIntro">
|
||||||
<Carousel>
|
<Carousel nextIcon={nextIcon} prevIcon={prevIcon}>
|
||||||
<Carousel.Item>
|
<Carousel.Item>
|
||||||
<img className="headerImg" src={house1} alt="First House" />
|
<img className="headerImg" src={house1} alt="First House" />
|
||||||
|
<Carousel.Caption>
|
||||||
|
<h3 style={{ fontSize: "250%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>100 Charlie Rogers, Kanata, ON K2V 1A7</h3>
|
||||||
|
<h2 style={{ fontSize: "150%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>1 Bedroom, 2 Bathroom</h2>
|
||||||
|
<div className="buttonka">
|
||||||
|
<Button href="/listings" variant="info">Click for Details</Button>
|
||||||
|
</div>
|
||||||
|
</Carousel.Caption>
|
||||||
</Carousel.Item>
|
</Carousel.Item>
|
||||||
<Carousel.Item>
|
<Carousel.Item>
|
||||||
<img className="headerImg" src={house2} alt="Second House" />
|
<img className="headerImg" src={house2} alt="Second House" />
|
||||||
|
<Carousel.Caption>
|
||||||
|
<h3 style={{ fontSize: "250%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>1490 Youville Drive, Orléans, ON K1C 2X8</h3>
|
||||||
|
<h2 style={{ fontSize: "150%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>1 Bedroom, 2 Bathroom</h2>
|
||||||
|
<div className="buttonka">
|
||||||
|
<Button href="/listings" variant="info">Click for Details</Button>
|
||||||
|
</div>
|
||||||
|
</Carousel.Caption>
|
||||||
</Carousel.Item>
|
</Carousel.Item>
|
||||||
<Carousel.Item>
|
<Carousel.Item>
|
||||||
<img className="headerImg" src={house3} alt="Third House" />
|
<img className="headerImg" src={house3} alt="Third House" />
|
||||||
|
<Carousel.Caption>
|
||||||
|
<h3 style={{ fontSize: "250%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>8720 Russell Road, Navan, ON K4B 1J1</h3>
|
||||||
|
<h2 style={{ fontSize: "150%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>1 Bedroom, 2 Bathroom</h2>
|
||||||
|
<div className="buttonka">
|
||||||
|
<Button href="/listings" variant="info">Click for Details</Button>
|
||||||
|
</div>
|
||||||
|
</Carousel.Caption>
|
||||||
|
</Carousel.Item>
|
||||||
|
<Carousel.Item>
|
||||||
|
<img className="headerImg" src={house4} alt="Fourth House" />
|
||||||
|
<Carousel.Caption>
|
||||||
|
<h3 style={{ fontSize: "250%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>2785 8th Line Road, Metcalfe, ON K0A 2P0</h3>
|
||||||
|
<h2 style={{ fontSize: "150%", textShadow: "-2px 0 black, 0 2px black, 2px 0 black, 0 -2px black" }}>1 Bedroom, 2 Bathroom</h2>
|
||||||
|
<div className="buttonka">
|
||||||
|
<Button href="/listings" variant="info">Click for Details</Button>
|
||||||
|
</div>
|
||||||
|
</Carousel.Caption>
|
||||||
</Carousel.Item>
|
</Carousel.Item>
|
||||||
</Carousel>
|
</Carousel>
|
||||||
|
<section className="colored-section" id="features">
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<h2 style={{ paddingLeft: "22rem", paddingBottom: "1rem", fontFamily: "Trebuchet MS" }}>Description </h2>
|
||||||
|
<p style={{ fontSize: "110%" }}> Welcome to Kene's Cribs. Kene's Cribs is a real estator company which provides the clients with the houses. <br></br>
|
||||||
|
The houses limited to the clients are only limited to the clients' dreams. In order to further navigate the<br></br>
|
||||||
|
website, use the navigation bar to switch between pages. Listings page is for browsing houses, Agents page<br></br>
|
||||||
|
is for browsing the estators, the Contact Us page is for the contacting us and the login page is for our<br></br>
|
||||||
|
members who want to benefit from our deals. Above are some houses which can interest you. Feel free to<br></br>
|
||||||
|
click the buttons above to explore the houses you want. </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="colored-section" id="contact">
|
|
||||||
<div className="container-fluid">
|
|
||||||
<div className="contactIntro">
|
|
||||||
<h2 className="heading-1">Contact Us</h2>
|
|
||||||
<form
|
|
||||||
id="contact-form"
|
|
||||||
onSubmit={this.handleSubmit.bind(this)}
|
|
||||||
method="POST"
|
|
||||||
>
|
|
||||||
<div className="formhelper row">
|
|
||||||
<div className="col-6">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
placeholder="First Name"
|
|
||||||
value={this.state.firstname}
|
|
||||||
onChange={this.onFirstNameChange.bind(this)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="col-6">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
placeholder="Last Name"
|
|
||||||
value={this.state.lastname}
|
|
||||||
onChange={this.onLastNameChange.bind(this)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
className="form-control"
|
|
||||||
placeholder="Email Address"
|
|
||||||
aria-describedby="emailHelp"
|
|
||||||
value={this.state.email}
|
|
||||||
onChange={this.onEmailChange.bind(this)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
|
||||||
<textarea
|
|
||||||
className="form-control"
|
|
||||||
placeholder="Message"
|
|
||||||
rows="5"
|
|
||||||
value={this.state.message}
|
|
||||||
onChange={this.onMessageChange.bind(this)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="buttonhelper">
|
|
||||||
<button type="submit" className="button-1">
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onFirstNameChange(event) {
|
|
||||||
this.setState({ firstname: event.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
onLastNameChange(event) {
|
|
||||||
this.setState({ lastname: event.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
onEmailChange(event) {
|
|
||||||
this.setState({ email: event.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessageChange(event) {
|
|
||||||
this.setState({ message: event.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmit(event) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Homepage;
|
export default Homepage;
|
||||||
|
|
1
src/homePage/index.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { default } from "./homePage";
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 253 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 245 KiB |
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 288 KiB |
BIN
src/images/house4.jpg
Normal file
After Width: | Height: | Size: 114 KiB |
|
@ -0,0 +1,48 @@
|
||||||
|
.colored-section {
|
||||||
|
background-color: #e7dec8;
|
||||||
|
color: #000000;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#contact .container-fluid {
|
||||||
|
padding-top: 50px;
|
||||||
|
text-align: left;
|
||||||
|
font-family: "Georgia";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.contactIntro{
|
||||||
|
padding-left: 10%;
|
||||||
|
padding-right: 10%;
|
||||||
|
padding-bottom: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-1{
|
||||||
|
padding-left: 38%;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 20%;
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formhelper{
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown{
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, textarea {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-feedback] {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-feedback].error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
4
src/shared-components/contact-us/config.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
USER: 'a0f17fd29c4ac0',
|
||||||
|
PASS: '671f8cbe2bd5e2'
|
||||||
|
}
|
|
@ -1,9 +1,220 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
import "./Contact-us.css";
|
||||||
|
import axios from 'axios'
|
||||||
|
import {
|
||||||
|
FieldFeedback,
|
||||||
|
FieldFeedbacks,
|
||||||
|
FormWithConstraints
|
||||||
|
} from 'react-form-with-constraints';
|
||||||
|
import Alert from 'react-bootstrap/Alert';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ContactUs extends Component {
|
class ContactUs extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
firstname: "",
|
||||||
|
lastname: "",
|
||||||
|
email: "",
|
||||||
|
message: "",
|
||||||
|
agent: "",
|
||||||
|
house: "",
|
||||||
|
alertBad: false,
|
||||||
|
alertSucess: false,
|
||||||
|
time: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div>ContactUs</div>;
|
return (
|
||||||
|
<div className="contact-us">
|
||||||
|
<Alert variant="danger" style={{ display: this.state.alertBad ? "block" : "none" }} onClose={() => this.setState({ alertBad: false })} dismissible>
|
||||||
|
<Alert.Heading>Message could not send.</Alert.Heading>
|
||||||
|
<p>
|
||||||
|
There are some errors in your contact form.
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
|
<Alert variant="success" style={{ display: this.state.alertSucess ? "block" : "none" }} onClose={() => this.setState({ alertSucess: false })} dismissible>
|
||||||
|
<Alert.Heading>The message is successfully sent.</Alert.Heading>
|
||||||
|
<p>
|
||||||
|
You contact form will be delivered to our support team.
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
|
<div className="container">
|
||||||
|
<section class="colored-section" id="contact">
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="contactIntro">
|
||||||
|
<h2 className="heading-1">Contact Us</h2>
|
||||||
|
<FormWithConstraints ref={form => this.form = form}
|
||||||
|
id="contact-form"
|
||||||
|
onSubmit={this.handleSubmit.bind(this)}
|
||||||
|
method="POST"
|
||||||
|
noValidate
|
||||||
|
>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-6">
|
||||||
|
<select className="form-group" name="agent" id="dropdown" required onChange={this.onAgentChange.bind(this)} value={this.state.agent}>
|
||||||
|
<option value="">Select an Agent</option>
|
||||||
|
<option value="Michael">Michael</option>
|
||||||
|
<option value="Jin">Jin </option>
|
||||||
|
<option value="Anita">Anita</option>
|
||||||
|
<option value="Alex">Alex</option>
|
||||||
|
<option value="Xuan">Xuan</option>
|
||||||
|
<option value="Walter">Walter</option>
|
||||||
|
<option value="No preference">No preference</option>
|
||||||
|
</select>
|
||||||
|
<FieldFeedbacks for="agent">
|
||||||
|
<FieldFeedback when="*" />
|
||||||
|
</FieldFeedbacks>
|
||||||
|
</div>
|
||||||
|
<div className="col-6">
|
||||||
|
<select className="form-group" name="house" id="dropdown" required onChange={this.onHouseChange.bind(this)} value={this.state.house}>
|
||||||
|
<option value="">Select a House</option>
|
||||||
|
<option value="100 Charlie Rogers">100 Charlie Rogers</option>
|
||||||
|
<option value="1490 Youville Drive">1490 Youville Drive </option>
|
||||||
|
<option value="8720 Russell Road">8720 Russell Road</option>
|
||||||
|
<option value="2785 8th Line Road">2785 8th Line Road</option>
|
||||||
|
<option value="No preference">No preference</option>
|
||||||
|
</select>
|
||||||
|
<FieldFeedbacks for="house">
|
||||||
|
<FieldFeedback when="*" />
|
||||||
|
</FieldFeedbacks>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="formhelper row">
|
||||||
|
<div className="col-6">
|
||||||
|
<input name="firstname"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="First Name"
|
||||||
|
value={this.state.firstname}
|
||||||
|
required onChange={this.onFirstNameChange.bind(this)}
|
||||||
|
/>
|
||||||
|
<FieldFeedbacks for="firstname">
|
||||||
|
<FieldFeedback when="*" />
|
||||||
|
</FieldFeedbacks>
|
||||||
|
</div>
|
||||||
|
<div className="col-6">
|
||||||
|
<input name="lastname"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Last Name"
|
||||||
|
value={this.state.lastname}
|
||||||
|
required onChange={this.onLastNameChange.bind(this)}
|
||||||
|
/>
|
||||||
|
<FieldFeedbacks for="lastname">
|
||||||
|
<FieldFeedback when="*" />
|
||||||
|
</FieldFeedbacks>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<input name="email"
|
||||||
|
type="email"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Email Address"
|
||||||
|
aria-describedby="emailHelp"
|
||||||
|
value={this.state.email}
|
||||||
|
required onChange={this.onEmailChange.bind(this)}
|
||||||
|
/>
|
||||||
|
<FieldFeedbacks for="email">
|
||||||
|
<FieldFeedback when="*" />
|
||||||
|
</FieldFeedbacks>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<textarea name="message"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Message"
|
||||||
|
rows="5"
|
||||||
|
value={this.state.message}
|
||||||
|
required onChange={this.onMessageChange.bind(this)}
|
||||||
|
/>
|
||||||
|
<FieldFeedbacks for="message">
|
||||||
|
<FieldFeedback when="*" />
|
||||||
|
</FieldFeedbacks>
|
||||||
|
</div>
|
||||||
|
<div className="buttonhelper">
|
||||||
|
<button type="submit" className="button-1">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</FormWithConstraints>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
onAgentChange(event) {
|
||||||
|
this.setState({ agent: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
onHouseChange(event) {
|
||||||
|
this.setState({ house: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
onFirstNameChange(event) {
|
||||||
|
this.setState({ firstname: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
onLastNameChange(event) {
|
||||||
|
this.setState({ lastname: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
onEmailChange(event) {
|
||||||
|
this.setState({ email: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessageChange(event) {
|
||||||
|
this.setState({ message: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange = e => {
|
||||||
|
this.form.validateFields(e.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.form.validateFields();
|
||||||
|
|
||||||
|
if (!this.form.isValid()) {
|
||||||
|
this.alertBad();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.alertSuccess();
|
||||||
|
axios({
|
||||||
|
method: "POST",
|
||||||
|
url: "http://localhost:3002/send",
|
||||||
|
data: this.state
|
||||||
|
}).then((response) => {
|
||||||
|
if (response.data.status === 'success') {
|
||||||
|
this.resetForm();
|
||||||
|
} else if (response.data.status === 'fail') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
alertSuccess(){
|
||||||
|
this.setState({ alertBad: false, alertSucess: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
alertBad(){
|
||||||
|
this.setState({ alertSucess: false, alertBad: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
resetForm() {
|
||||||
|
this.setState({ firstname: '', lastname: '', email: '', message: '', agent: '', house: '' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default ContactUs;
|
export default ContactUs;
|
||||||
|
|
|
@ -1 +1,60 @@
|
||||||
export { default } from "./Contact-us";
|
var express = require('express');
|
||||||
|
var router = express.Router();
|
||||||
|
var nodemailer = require('nodemailer');
|
||||||
|
var cors = require('cors');
|
||||||
|
const creds = require('./config');
|
||||||
|
|
||||||
|
var transport = {
|
||||||
|
host: 'smtp.mailtrap.io', // Don’t forget to replace with the SMTP host of your provider
|
||||||
|
port: 2525,
|
||||||
|
auth: {
|
||||||
|
user: creds.USER,
|
||||||
|
pass: creds.PASS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var transporter = nodemailer.createTransport(transport)
|
||||||
|
|
||||||
|
transporter.verify((error, success) => {
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
} else {
|
||||||
|
console.log('Server is ready to take messages');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/send', (req, res, next) => {
|
||||||
|
var firstname = req.body.firstname
|
||||||
|
var lastname = req.body.lastname
|
||||||
|
var email = req.body.email
|
||||||
|
var agent = req.body.agent
|
||||||
|
var house = req.body.house
|
||||||
|
var message = req.body.message
|
||||||
|
var content = `First Name: ${firstname} \n Last Name: ${lastname} \n E-mail: ${email} \n Agent: ${agent} \n House: ${house} \n Message: ${message} `
|
||||||
|
|
||||||
|
var mail = {
|
||||||
|
from: email,
|
||||||
|
to: 'kenes@cribs.com', // Change to email address that you want to receive messages on
|
||||||
|
subject: 'New Message from Contact Form',
|
||||||
|
text: content
|
||||||
|
}
|
||||||
|
|
||||||
|
transporter.sendMail(mail, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
res.json({
|
||||||
|
status: 'fail'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.json({
|
||||||
|
status: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = express()
|
||||||
|
app.use(cors())
|
||||||
|
app.use(express.json())
|
||||||
|
app.use('/', router)
|
||||||
|
app.listen(3002)
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ const Navbar = () => {
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<Link className="nav-link" to="/">
|
<Link className="nav-link" to="/contact-us">
|
||||||
Contact Us
|
Contact Us
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
|