Adding initial version for react i18n.

master
Tomasz Półgrabia 2021-01-02 12:39:13 +01:00
parent 0cbfd7021a
commit f0813fd849
5 changed files with 127 additions and 76 deletions

View File

@ -5,78 +5,86 @@ import {
Switch,
Route, Link
} from 'react-router-dom';
import {FormattedMessage, IntlProvider} from 'react-intl';
import GlobalContext from './GlobalContext';
import PeopleIndex from "./views/People/PeopleIndex";
import PeopleAdd from "./views/People/PeopleAdd";
import PeopleEdit from "./views/People/PeopleEdit";
import {PeopleService} from "./views/People/PeopleService";
import messages from './locale/messages';
const defaultLocale = 'en';
function App() {
// this should be read from for example local storage and should be changeable. For now it's fixed.
const currentLocale = 'en';
return (
<GlobalContext.Provider value={{peopleService: new PeopleService()}}>
<div>
<Router>
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<a className="navbar-item" href="/">
<h2 id="logo" className="is-uppercase bold" i18n="app-people-management-limited-label">
PeopleIndex management limited
</h2>
</a>
<a href="#logo" role="button" className="navbar-burger" aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarBasicExample" className="navbar-menu">
<div className="navbar-start">
<Link className="navbar-item" to="/">
Home
</Link>
<Link className="navbar-item" to="/people/add">
Add person
</Link>
<IntlProvider locale={currentLocale} defaultLocale={defaultLocale} messages={messages[currentLocale]}>
<GlobalContext.Provider value={{peopleService: new PeopleService()}}>
<div>
<Router>
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<a className="navbar-item" href="/">
<h2 id="logo" className="is-uppercase bold">
<FormattedMessage id='app.navbar.banner'/>
</h2>
</a>
<a href="#logo" role="button" className="navbar-burger" aria-label="menu"
aria-expanded="false"
data-target="mainNavbar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div className="navbar-end">
<div className="navbar-item">
<div className="buttons">
<a href="#logo" className="button is-primary">
<strong>Sign up</strong>
</a>
<a href="#logo" className="button is-light">
<strong>Log in</strong>
</a>
<div id="mainNavbar" className="navbar-menu">
<div className="navbar-start">
<Link className="navbar-item" to="/">
<FormattedMessage id="app.navbar.home"/>
</Link>
<Link className="navbar-item" to="/people/add">
<FormattedMessage id="app.navbar.person.add"/>
</Link>
</div>
<div className="navbar-end">
<div className="navbar-item">
<div className="buttons">
<a href="#logo" className="button is-primary">
<strong><FormattedMessage id="app.navbar.signup"/></strong>
</a>
<a href="#logo" className="button is-light">
<strong><FormattedMessage id="app.navbar.login"/></strong>
</a>
</div>
</div>
</div>
</div>
</div>
</nav>
<Switch>
<Route path="/people/" exact={true}>
<PeopleIndex/>
</Route>
<Route path="/people/add" exact={true}>
<PeopleAdd/>
</Route>
<Route path="/people/edit/:personId" exact={true} children={<PeopleEdit/>}/>
<Route path="/" exact={true}>
<PeopleIndex/>
</Route>
<Route>
404 page
</Route>
</Switch>
</Router>
</div>
</GlobalContext.Provider>
</nav>
<Switch>
<Route path="/people/" exact={true}>
<PeopleIndex/>
</Route>
<Route path="/people/add" exact={true}>
<PeopleAdd/>
</Route>
<Route path="/people/edit/:personId" exact={true} children={<PeopleEdit/>}/>
<Route path="/" exact={true}>
<PeopleIndex/>
</Route>
<Route>
404 page
</Route>
</Switch>
</Router>
</div>
</GlobalContext.Provider>
</IntlProvider>
);
}

View File

@ -0,0 +1,22 @@
{
"app.navbar.banner": "People Management Limited",
"app.navbar.home": "Home",
"app.navbar.person.add": "Add person",
"app.navbar.signup": "Sign up",
"app.navbar.login": "Log in",
"people.index.table.id.header": "Id",
"people.index.table.firstName.header": "First name",
"people.index.table.lastName.header": "Last name",
"people.index.table.email.header": "E-mail",
"people.index.table.status.header": "Status",
"people.index.table.status.value.active": "Active",
"people.index.table.status.value.inactive": "Inactive",
"people.form.person.not.available": "Sorry, the person with id {personId} is not available",
"people.form.firstName.label": "First name",
"people.form.lastName.label": "Last name",
"people.form.email.label": "E-mail",
"people.form.status.label": "Status",
"people.form.status.value.active": "Active",
"people.form.status.value.inactive": "Inactive",
"people.form.submit.label": "Submit"
}

View File

@ -0,0 +1,7 @@
import enMessages from './en.json';
let messages = {
"en": enMessages
};
export default messages;

View File

@ -3,6 +3,7 @@ import {useHistory} from 'react-router-dom';
import {isValidEmail, validateForm} from "../../utils/validators";
import GlobalContext from "../../GlobalContext";
import classNames from 'classnames';
import {useIntl} from "react-intl";
const personValidators = {
email: [isValidEmail]
@ -17,6 +18,7 @@ export function PeopleForm(params) {
status: 0
});
const {formatMessage} = useIntl();
const history = useHistory();
const {peopleService} = useContext(GlobalContext);
let [errors, setErrors] = useState(validateForm(personValidators, formData));
@ -83,11 +85,12 @@ export function PeopleForm(params) {
return (loading
? <div className="loader"/>
: (personNotAvailable && personId)
? <div>Sorry, the person with id {personId} is not available</div>
? <div>{formatMessage({id: 'people.form.person.not.available'}, {personId: personId})}</div>
: <form>
<div className="field is-horizontal">
<div className="field-label is-medium">
<label htmlFor="firstName" className="label">First name</label>
<label htmlFor="firstName"
className="label">{formatMessage({id: 'people.form.firstName.label'})}</label>
</div>
<div className="field-body">
<div className="field">
@ -97,7 +100,7 @@ export function PeopleForm(params) {
name="firstName"
type="text"
className={classNames("input", {'is-danger': errors.firstName})}
placeholder="First name"
placeholder={formatMessage({id: 'people.form.firstName.label'})}
value={formData?.firstName}
onInput={onInputChange}
/>
@ -108,7 +111,8 @@ export function PeopleForm(params) {
<div className="field is-horizontal">
<div className="field-label is-medium">
<label htmlFor="lastName" className="label">Last name</label>
<label htmlFor="lastName"
className="label">{formatMessage({id: 'people.form.lastName.label'})}</label>
</div>
<div className="field-body">
<div className="field">
@ -118,7 +122,7 @@ export function PeopleForm(params) {
name="lastName"
type="text"
className={classNames("input", {'is-danger': errors.lastName})}
placeholder="Last name"
placeholder={formatMessage({id: 'people.form.lastName.label'})}
value={formData?.lastName}
onInput={onInputChange}
/>
@ -129,7 +133,8 @@ export function PeopleForm(params) {
<div className="field is-horizontal">
<div className="field-label is-medium">
<label htmlFor="email" className="label">E-mail</label>
<label htmlFor="email"
className="label">{formatMessage({id: 'people.form.email.label'})}</label>
</div>
<div className="field-body">
<div className="field">
@ -139,7 +144,7 @@ export function PeopleForm(params) {
name="email"
type="text"
className={classNames("input", {'is-danger': errors.email})}
placeholder="E-mail"
placeholder={formatMessage({id: 'people.form.email.label'})}
value={formData?.email}
onInput={onInputChange}
/>
@ -150,7 +155,8 @@ export function PeopleForm(params) {
<div className="field is-horizontal">
<div className="field-label is-medium">
<label htmlFor="status" className="label">Status</label>
<label htmlFor="status"
className="label">{formatMessage({id: 'people.form.status.label'})}</label>
</div>
<div className="field-body">
<div className="field">
@ -162,8 +168,10 @@ export function PeopleForm(params) {
className={classNames("input", {'is-danger': errors.status})}
value={formData?.status}
onInput={onInputChange}>
<option value="0">Active</option>
<option value="1">Inactive</option>
<option
value="0">{formatMessage({id: 'people.form.status.value.active'})}</option>
<option
value="1">{formatMessage({id: 'people.form.status.value.inactive'})}</option>
</select>
</div>
</div>
@ -173,9 +181,10 @@ export function PeopleForm(params) {
<div className="field">
<div className="control">
<button type="button" className="button is-primary" onClick={() => submitPerson()}>Submit
<button type="button" className="button is-primary" onClick={() => submitPerson()}>
{formatMessage({id: 'people.form.submit.label'})}
</button>
</div>
</div>
</form>)
};
}

View File

@ -1,5 +1,6 @@
import "bulma";
import {useContext, useEffect, useState} from "react";
import {FormattedMessage, useIntl} from 'react-intl';
import {useHistory} from 'react-router-dom';
import GlobalContext from "../../GlobalContext";
@ -7,6 +8,8 @@ export default function PeopleIndex() {
const {peopleService} = useContext(GlobalContext);
const [people, setPeople] = useState([]);
const history = useHistory();
const {formatMessage} = useIntl();
useEffect(() => {
peopleService.getAllPeople()
.then(people => {
@ -22,11 +25,11 @@ export default function PeopleIndex() {
<table className="table is-striped is-fullwidth">
<thead>
<tr>
<th>Id</th>
<th>First name</th>
<th>Last name</th>
<th>E-mail</th>
<th>Status</th>
<th><FormattedMessage id='people.index.table.id.header'/></th>
<th><FormattedMessage id='people.index.table.firstName.header'/></th>
<th><FormattedMessage id='people.index.table.lastName.header'/></th>
<th><FormattedMessage id='people.index.table.email.header'/></th>
<th><FormattedMessage id='people.index.table.status.header'/></th>
</tr>
</thead>
<tbody>
@ -36,7 +39,9 @@ export default function PeopleIndex() {
<td>{it.firstName}</td>
<td>{it.lastName}</td>
<td>{it.email}</td>
<td>{it.status === 0 ? 'Active' : 'Inactive'}</td>
<td>{it.status === 0
? formatMessage({id: 'people.index.table.status.value.active'})
: formatMessage({id: 'people.index.table.status.value.inactive'})}</td>
</tr>
)}
</tbody>