translations, listing-page and login and accout page
This commit is contained in:
parent
4b2a08a36f
commit
bc29f27d2d
13 changed files with 21452 additions and 197 deletions
21110
package-lock.json
generated
21110
package-lock.json
generated
File diff suppressed because it is too large
Load diff
10
package.json
10
package.json
|
@ -9,8 +9,14 @@
|
|||
"axios": "^0.21.1",
|
||||
"bootstrap": "^4.6.0",
|
||||
"cors": "^2.8.5",
|
||||
"email-validator": "^2.0.4",
|
||||
"express": "^4.17.1",
|
||||
"flag-icon-css": "^3.5.0",
|
||||
"formik": "^2.2.6",
|
||||
"i18next-browser-languagedetector": "^6.1.0",
|
||||
"i18next-http-backend": "^1.2.1",
|
||||
"joi-browser": "^13.4.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"nodemailer": "^6.5.0",
|
||||
"react": "^17.0.2",
|
||||
"react-alert": "^7.0.2",
|
||||
|
@ -23,12 +29,14 @@
|
|||
"react-form-with-constraints-bootstrap4": "^0.16.0",
|
||||
"react-google-maps": "^9.4.5",
|
||||
"react-hook-form": "^7.0.0",
|
||||
"react-i18next": "^11.8.12",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "4.0.3",
|
||||
"react-select": "^4.3.0",
|
||||
"reactstrap": "^8.9.0",
|
||||
"spectre.css": "^0.5.9",
|
||||
"web-vitals": "^1.1.1"
|
||||
"web-vitals": "^1.1.1",
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
|
27
public/assets/locales/en/translations.json
Normal file
27
public/assets/locales/en/translations.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"Welcome_to_React": "Welcome to React and react-i18next",
|
||||
"Login_header": "Kene's Cribs",
|
||||
"Login_message": "Welcome please back, please sign in!",
|
||||
"Login_email": "Email address",
|
||||
"Login_password": "Password",
|
||||
"Login_remember_me": "remember me",
|
||||
"Login_submit_button": "Submit",
|
||||
"Account_header": "Personal Information",
|
||||
"Account_message": "You can update/edit your account information here",
|
||||
"Account_first_name": "First Name",
|
||||
"Account_last_name": "Last Name",
|
||||
"Account_email": "Email",
|
||||
"Account_phone_number": "Phone Number",
|
||||
"Account_current_password": "Current Password",
|
||||
"Account_new_password": "New password",
|
||||
"Account_update_button": "Update",
|
||||
"Footer_message": "Copyright SEG3125 - Group 3",
|
||||
"Nav_brand": "Kene's Cribs",
|
||||
"Nav_Home": "Home",
|
||||
"Nav_Listings": "Listings",
|
||||
"Nav_Agents": "Agents",
|
||||
"Nav_Contact_Us": "Contact Us",
|
||||
"Nav_listing_page": "listing-page",
|
||||
"Nav_Login": "Login"
|
||||
|
||||
}
|
26
public/assets/locales/fr/translations.json
Normal file
26
public/assets/locales/fr/translations.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"Welcome_to_React": "Bienvenue a react et react-i18next",
|
||||
"Login_header": "Berceaux de Kene",
|
||||
"Login_message": "Bienvenue, merci de vous connecter!",
|
||||
"Login_email": "Adresse e-mail",
|
||||
"Login_password": "Mot de passe",
|
||||
"Login_remember_me": "souviens-toi de moi",
|
||||
"Login_submit_button": "Nous faire parvenir",
|
||||
"Account_header": "Informations personnelles",
|
||||
"Account_message": "Vous pouvez mettre à jour / modifier les informations de votre compte ici",
|
||||
"Account_first_name": "Prénom",
|
||||
"Account_last_name": "Nom de famille",
|
||||
"Account_email": "E-mail",
|
||||
"Account_phone_number": "Numéro de téléphone",
|
||||
"Account_current_password": "Mot de passe actuel",
|
||||
"Account_new_password": "Nouveau mot de passe",
|
||||
"Account_update_button": "Mettre à jour",
|
||||
"Footer_message": "Copyright SEG3125 - Groupe 3",
|
||||
"Nav_brand": "Berceaux de Kene",
|
||||
"Nav_Home": "Accueil",
|
||||
"Nav_Listings": "Annonces",
|
||||
"Nav_Agents": "Agents",
|
||||
"Nav_Contact_Us": "Nous contacter",
|
||||
"Nav_listing_page": "page de liste",
|
||||
"Nav_Login": "Connexion"
|
||||
}
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
<title>Kene's Cribs</title>
|
||||
</head>
|
||||
<body>
|
||||
<body dir="ltr">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
|
|
74
src/App.js
74
src/App.js
|
@ -1,33 +1,93 @@
|
|||
import { Component } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import Footer from "./shared-components/footer-component/Footer";
|
||||
import Navbar from "./shared-components/navbar-component/Navbar";
|
||||
import { BrowserRouter, Route } from "react-router-dom";
|
||||
import { BrowserRouter, Route, Switch } from "react-router-dom";
|
||||
import i18next from "i18next";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Cookies from "js-cookie";
|
||||
import HomePage from "./homePage/Homepage";
|
||||
import ListingsPage from "./listings-page/ListingsPage";
|
||||
import AgentPage from "./agent-page/AgentPage";
|
||||
import ListingPage from "./listings-page/single-listing/listing-page";
|
||||
import Login from "./login-page/Login";
|
||||
// import Account from "./login-page/account/Account";
|
||||
// import ContactUs from "./shared-components/Contact-us/Contact-us";
|
||||
import Account from "./login-page/account/Account";
|
||||
import ContactUs from "./shared-components/contact-us/contact-us";
|
||||
|
||||
class App extends Component {
|
||||
render() {
|
||||
const langauges = [
|
||||
{
|
||||
code: "fr",
|
||||
name: "Français",
|
||||
country_code: "fr",
|
||||
},
|
||||
{
|
||||
code: "en",
|
||||
name: "English",
|
||||
country_code: "gb",
|
||||
},
|
||||
];
|
||||
|
||||
function App() {
|
||||
const currentLanguageCode = Cookies.get("i18next") || "en";
|
||||
const currentLanguage = langauges.find(
|
||||
(lang) => lang.code === currentLanguageCode
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
document.body.dir = currentLanguage.dir || "ltr";
|
||||
}, [currentLanguage]);
|
||||
return (
|
||||
<div className="App">
|
||||
{/* create the translations button */}
|
||||
<div className="container">
|
||||
<div className="d-flex justify-content-end">
|
||||
{/* <!-- Example single danger button --> */}
|
||||
<div class="btn-group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-link dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i class="fas fa-globe"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
{langauges.map(({ code, name, country_code }) => (
|
||||
<button
|
||||
class="dropdown-item"
|
||||
key={code}
|
||||
onClick={() => i18next.changeLanguage(code)}
|
||||
disabled={code === currentLanguageCode}
|
||||
>
|
||||
<span
|
||||
className={`flag-icon flag-icon-${country_code} mx-2`}
|
||||
></span>
|
||||
{name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex flex-column align-items-start">
|
||||
{t("Welcome_to_React")}
|
||||
</div>
|
||||
</div>
|
||||
<BrowserRouter>
|
||||
<Navbar></Navbar>
|
||||
<Switch>
|
||||
<Route exact path="/" component={HomePage}></Route>
|
||||
<Route path="/listings" component={ListingsPage}></Route>
|
||||
<Route path="/agents" component={AgentPage}></Route>
|
||||
<Route path="/listing-page" component={ListingPage}></Route>
|
||||
<Route path="/login" component={Login}></Route>
|
||||
<Route path="/contact-us" component={ContactUs}></Route>
|
||||
<Route path="/account" component={Account}></Route>
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
<Footer></Footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
43
src/index.js
43
src/index.js
|
@ -1,14 +1,49 @@
|
|||
import React from "react";
|
||||
import React, { Suspense } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import "flag-icon-css/css/flag-icon.min.css";
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import HttpApi from "i18next-http-backend";
|
||||
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
|
||||
i18n
|
||||
.use(initReactI18next) // passes i18n down to react-i18next
|
||||
.use(LanguageDetector)
|
||||
.use(HttpApi)
|
||||
.init({
|
||||
// lng: "en",
|
||||
supportedLngs: ["en", "fr"],
|
||||
fallbackLng: "en",
|
||||
detection: {
|
||||
// "querystring",
|
||||
order: ["cookie", "htmlTag", "localStorage", "path", "subdomain"],
|
||||
caches: ["cookie"],
|
||||
},
|
||||
backend: {
|
||||
loadPath: "/assets/locales/{{lng}}/translations.json",
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
});
|
||||
|
||||
const loadingMsg = (
|
||||
<div className="py-4 text-center">
|
||||
<h2>Loading......</h2>
|
||||
</div>
|
||||
);
|
||||
ReactDOM.render(
|
||||
<Suspense fallback={loadingMsg}>
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
</React.StrictMode>
|
||||
</Suspense>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import "./listing-page.css";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
// import house images
|
||||
import house_img1 from "../../images/house1-2.jpg";
|
||||
|
@ -102,9 +103,11 @@ const ListingPage = () => {
|
|||
West facing backyard!
|
||||
</p>
|
||||
<div className="booking-btn">
|
||||
<button type="button" class="btn btn-outline-success">
|
||||
<Link to="/contact-us">
|
||||
<button type="button" class="btn btn-lg btn-info">
|
||||
Book Showing
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,35 +1,52 @@
|
|||
import React, { Component } from "react";
|
||||
import Logo from "../images/logo1.png";
|
||||
import "./Login.css";
|
||||
import { Link } from "react-router-dom";
|
||||
// import { useTranslation } from "react-i18next";
|
||||
import { withTranslation } from "react-i18next";
|
||||
class Login extends Component {
|
||||
state = {
|
||||
Accounts: [],
|
||||
Account: {
|
||||
firstName: "Kevon",
|
||||
lastName: "Green",
|
||||
email: "kevon.green@kcribs.com",
|
||||
password: "Kcribs123",
|
||||
},
|
||||
};
|
||||
|
||||
handleLogin = (e) => {
|
||||
console.log(e);
|
||||
};
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<div className="login-page">
|
||||
<form action="" className="signin-Form">
|
||||
<form action="" className="signin-Form" onClick={this.handleLogin}>
|
||||
<img className="app-logo" src={Logo} alt="app-logo" />
|
||||
<h1 className="form-title">Kene's Cribs</h1>
|
||||
<p>Welcome please back, please sign in!</p>
|
||||
<h1 className="form-title">{t("Login_header")} </h1>
|
||||
<p>{t("Login_message")}</p>
|
||||
<hr className="hr" />
|
||||
<div className="login-box">
|
||||
<div class="form-group">
|
||||
<label for="email">Email address</label>
|
||||
<label for="email">{t("Login_email")}</label>
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
id="login-email"
|
||||
// value={email}
|
||||
aria-describedby="emailHelp"
|
||||
placeholder="Enter your email"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<label for="password">{t("Login_password")}</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
id="login-password"
|
||||
// value={password}
|
||||
placeholder="Enter your password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
@ -40,13 +57,15 @@ class Login extends Component {
|
|||
id="exampleCheck1"
|
||||
/>
|
||||
<label class="form-check-label" for="exampleCheck1">
|
||||
remember me
|
||||
{t("Login_remember_me")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="login-btn">
|
||||
<Link to="/account">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
Submit
|
||||
{t("Login_submit_button")}
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -55,4 +74,4 @@ class Login extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default Login;
|
||||
export default withTranslation()(Login);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.account-info{
|
||||
padding: 7%;
|
||||
text-align: center;
|
||||
background-color: #e7dec8;
|
||||
}
|
||||
|
||||
.account-header{
|
||||
|
|
|
@ -1,15 +1,26 @@
|
|||
import React from "react";
|
||||
import React, { Component } from "react";
|
||||
import "./Account.css";
|
||||
import Profile from "../../images/profile-picture.png";
|
||||
import { withTranslation } from "react-i18next";
|
||||
// import { useTranslation } from "react-i18next";
|
||||
|
||||
const Account = () => {
|
||||
class Account extends Component {
|
||||
state = {
|
||||
Account: {
|
||||
firstName: "Kevon",
|
||||
lastName: "Green",
|
||||
email: "kevon.green@kcribs.com",
|
||||
password: "Kcribs123",
|
||||
},
|
||||
};
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<div className="account-info">
|
||||
{/* // send information to my login component */}
|
||||
<div className="account-header">
|
||||
<h2 className="account-title">Personal Information</h2>
|
||||
<p className="account-text">
|
||||
You can update/edit your account information here
|
||||
</p>
|
||||
<h2 className="account-title">{t("Account_header")}</h2>
|
||||
<p className="account-text">{t("Account_message")}</p>
|
||||
</div>
|
||||
|
||||
<div className="row account-box">
|
||||
|
@ -21,7 +32,7 @@ const Account = () => {
|
|||
<div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
First Name
|
||||
{t("Account_first_name")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
|
@ -29,14 +40,16 @@ const Account = () => {
|
|||
type="text"
|
||||
class="form-control"
|
||||
id="account-fname"
|
||||
placeholder={this.state.Account.firstName}
|
||||
required
|
||||
disabled={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
Last Name
|
||||
{t("Account_last_name")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
|
@ -44,7 +57,9 @@ const Account = () => {
|
|||
type="text"
|
||||
class="form-control"
|
||||
id="account-lname"
|
||||
placeholder={this.state.Account.lastName}
|
||||
required
|
||||
disabled={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,7 +67,7 @@ const Account = () => {
|
|||
<div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
Email
|
||||
{t("Account_email")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
|
@ -61,14 +76,16 @@ const Account = () => {
|
|||
class="form-control"
|
||||
id="account-email"
|
||||
aria-describedby="emailHelp"
|
||||
placeholder={this.state.Account.email}
|
||||
required
|
||||
disabled={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
Phone Number
|
||||
{t("Account_phone_number")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
|
@ -76,14 +93,16 @@ const Account = () => {
|
|||
type="text"
|
||||
class="form-control"
|
||||
id="account-phoneNumber"
|
||||
placeholder={this.state.Account.email}
|
||||
required
|
||||
disabled={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
Existing Password
|
||||
{t("Account_current_password")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
|
@ -91,14 +110,16 @@ const Account = () => {
|
|||
type="text"
|
||||
class="form-control"
|
||||
id="account-existPassword"
|
||||
placeholder={"**************"}
|
||||
required
|
||||
disabled={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group info-group">
|
||||
{/* <div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
New password
|
||||
{t("Account_new_password")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
|
@ -109,37 +130,25 @@ const Account = () => {
|
|||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group info-group">
|
||||
<div className="col-4">
|
||||
<label class="label-text" for="email">
|
||||
Confirm New Password
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-8 update-input">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="account-confirmPassword"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div> */}
|
||||
<div className="update-btn">
|
||||
<button type="button" class="btn btn-lg btn-danger">
|
||||
Update
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-lg btn-danger"
|
||||
disabled={true}
|
||||
>
|
||||
{t("Account_update_button")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="account-title">Booked Appointments</h2>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//links
|
||||
// https://www.pngitem.com/pimgs/m/146-1468479_my-profile-icon-blank-profile-picture-circle-hd.png
|
||||
|
||||
export default Account;
|
||||
export default withTranslation()(Account);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import React from "react";
|
||||
import "./Footer.css";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const Footer = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<footer>
|
||||
<section id="footer">
|
||||
|
@ -9,7 +12,7 @@ const Footer = () => {
|
|||
<i class="fab fa-facebook social-icon"></i>
|
||||
<i class="fab fa-instagram social-icon"></i>
|
||||
<i class="fas fa-envelope social-icon"></i>
|
||||
<p class="">© Copyright SEG3125 - Group 3</p>
|
||||
<p class="">© {t("Footer_message")}</p>
|
||||
</div>
|
||||
</section>
|
||||
</footer>
|
||||
|
|
|
@ -3,14 +3,16 @@ import { Link, withRouter } from "react-router-dom";
|
|||
import "./Navbar.css";
|
||||
import logo from "./logo2.png";
|
||||
/* eslint-disable jsx-a11y/anchor-is-valid */
|
||||
import { useTranslation } from "react-i18next";
|
||||
const Navbar = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
/* Nav Bar */
|
||||
<div className="Navbar">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark">
|
||||
<img src={logo} alt="" width="40" height="40"></img>
|
||||
<a href="/" class="navbar-brand">
|
||||
Kene's Cribs
|
||||
{t("Nav_brand")}
|
||||
</a>
|
||||
<button
|
||||
className="navbar-toggler"
|
||||
|
@ -27,36 +29,36 @@ const Navbar = () => {
|
|||
<ul className="navbar-nav ml-auto">
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" exact to="/">
|
||||
Home
|
||||
{t("Nav_Home")}
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/listings">
|
||||
Listings
|
||||
{t("Nav_Listings")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/agents">
|
||||
Agents
|
||||
{t("Nav_Agents")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/contact-us">
|
||||
Contact Us
|
||||
{t("Nav_Contact_Us")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/listing-page">
|
||||
listing-page
|
||||
{t("Nav_listing_page")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/login">
|
||||
Login
|
||||
{t("Nav_Login")}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in a new issue