-
-
Save anonymous/f63476535216edfca981c9f0968e4437 to your computer and use it in GitHub Desktop.
My small react application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
const AdminPanel = ({onShowBooksClick, onShowMembersClick, onAddBookEntryClick, onAddMemberEntryClick, onRentBookClick}) =>{ | |
return ( | |
<div className="container"> | |
<div className="buttonBar row"> | |
<button type="button" id="btnShowBookList" className="btn btn-info col-sm-2 sm-margin" onClick={onShowBooksClick}>Show a list of books</button> | |
<button type="button" id="btnShowMembers" className="btn btn-info col-sm-2 sm-margin" onClick={onShowMembersClick}>Show a list of members</button> | |
<button type="button" id="btnAddBook" className="btn btn-info col-sm-2 sm-margin" onClick={onAddBookEntryClick}>Add a new book</button> | |
<button type="button" id="btnAddMember" className="btn btn-info col-sm-2 sm-margin" onClick={onAddMemberEntryClick}>Add a new member</button> | |
<button type="button" id="btnRentBook" className="btn btn-info col-sm-2 sm-margin" onClick={onRentBookClick}>Rent a book</button> | |
</div> | |
</div> | |
); | |
}; | |
AdminPanel.propTypes = { | |
onShowBooksClick: PropTypes.func.isRequired, | |
onShowMembersClick: PropTypes.func.isRequired, | |
onAddBookEntryClick: PropTypes.func.isRequired, | |
onAddMemberEntryClick: PropTypes.func.isRequired, | |
onRentBookClick: PropTypes.func.isRequired | |
} | |
export default AdminPanel; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import Header from './Header'; | |
import AdminPanel from './AdminPanel'; | |
import BookList from './BookList'; | |
import MemberList from './MemberList'; | |
import AddBookEntry from './AddBookEntry'; | |
import AddMemberEntry from './AddMemberEntry'; | |
import BookRent from './BookRent'; | |
import * as api from '../api'; | |
class App extends React.Component { | |
//Since we configured stage-2 in our .babelrc we can just use the class properties directly | |
state = { | |
books: null, | |
members: null, | |
checkoutInformation: null, | |
renderAddBookEntryForm: false, | |
renderAddMemberEntryForm: false | |
}; | |
//Computing the header name depending on the current state | |
pageHeader = () => { | |
if (this.state.books != null) { | |
return 'Book list'; | |
} else if (this.state.members != null) { | |
return 'Member list'; | |
} else if (this.state.checkoutInformation != null){ | |
return 'Rent a book' | |
}else if (this.state.renderAddBookEntryForm) { | |
return 'Add a new book'; | |
} else if (this.state.renderAddMemberEntryForm) { | |
return 'Add a new member'; | |
} else { | |
return 'Welcome to the library'; | |
} | |
}; | |
getBookList = () => { | |
api.getBookList().then(books => { | |
this.setState({ | |
books: books, | |
members: null, | |
checkoutInformation: null, | |
renderAddBookEntryForm: false, | |
renderAddMemberEntryForm: false, | |
}); | |
}).catch(console.error); | |
}; | |
getMemberList = () => { | |
api.getMemberList().then(members => { | |
this.setState({ | |
members: members, | |
books: null, | |
checkoutInformation: null, | |
renderAddBookEntryForm: false, | |
renderAddMemberEntryForm: false, | |
}); | |
}).catch(console.error); | |
}; | |
addNewBookEntry = (newName, newAuthor, newDescription) => { | |
api.addNewBookEntry(newName, newAuthor, newDescription) | |
.then(books => { | |
this.setState({ | |
books: books, | |
renderAddBookEntryForm: false, | |
}); | |
}).catch(console.error); | |
}; | |
addNewMemberEntry = (newFirstName, newLastName, newRole) => { | |
api.addNewMemberEntry(newFirstName, newLastName, newRole) | |
.then(members => { | |
this.setState({ | |
members: members, | |
renderAddMemberEntryForm: false | |
}); | |
}).catch(console.error); | |
}; | |
saveRentInformation = (bookId, memberId) => { | |
api.rentABook(bookId, memberId) | |
.then(rentedBook => { | |
//TODO: Find a way to do this cleaner, i don't want to call the same functions twice when it's probably possible to do it in one call | |
this.setState((prevState, rentedBook) => ({ | |
books: prevState.checkoutInformation.books, | |
checkoutInformation: null | |
})); | |
this.setState({ | |
books: { | |
...this.state.books, | |
[rentedBook._id]: rentedBook | |
}, | |
}); | |
}).catch(console.error); | |
}; | |
showAddBookEntryForm = () => { | |
this.setState({ | |
books: null, | |
members: null, | |
checkoutInformation: null, | |
renderAddBookEntryForm: true, | |
renderAddMemberEntryForm: false | |
}); | |
}; | |
showAddMemberEntryForm = () => { | |
this.setState({ | |
books: null, | |
members: null, | |
checkoutInformation: null, | |
renderAddBookEntryForm: false, | |
renderAddMemberEntryForm: true | |
}); | |
}; | |
getCheckoutInformation = () => { | |
api.getCheckoutInformation().then(checkoutInformation => { | |
this.setState({ | |
books: null, | |
members: null, | |
checkoutInformation: checkoutInformation, | |
renderAddBookEntryForm: false, | |
renderAddMemberEntryForm: false | |
}); | |
}).catch(console.error); | |
}; | |
//Handling content rendering depending on the state | |
currentBookListContent = () => { | |
if (this.state.books == null) { | |
return; | |
} | |
return <BookList books={this.state.books} />; | |
}; | |
currentMemberListContent = () => { | |
if (this.state.members == null) { | |
return; | |
} | |
return <MemberList members={this.state.members} />; | |
}; | |
currentAddBookEntryContent = () => { | |
if(this.state.renderAddBookEntryForm){ | |
return <AddBookEntry addNewBookEntry = {this.addNewBookEntry} />; | |
} | |
return; | |
}; | |
currentAddMemberEntryContent = () => { | |
if (this.state.renderAddMemberEntryForm) { | |
return <AddMemberEntry addNewMemberEntry = {this.addNewMemberEntry} />; | |
} | |
return; | |
}; | |
currentRentBookContent = () => { | |
if(this.state.checkoutInformation != null){ | |
return <BookRent bookInformation = {this.state.checkoutInformation.books} | |
memberInformation = {this.state.checkoutInformation.members} | |
saveRentInformation = {this.saveRentInformation}/> | |
} | |
return; | |
}; | |
render() { | |
return ( | |
<div className="App "> | |
<Header message={this.pageHeader()} /> | |
<AdminPanel onShowBooksClick = {this.getBookList} | |
onShowMembersClick = {this.getMemberList} | |
onAddBookEntryClick= {this.showAddBookEntryForm} | |
onAddMemberEntryClick = {this.showAddMemberEntryForm} | |
onRentBookClick = {this.getCheckoutInformation} /> | |
{this.currentBookListContent()} | |
{this.currentMemberListContent()} | |
{this.currentAddBookEntryContent()} | |
{this.currentAddMemberEntryContent()} | |
{this.currentRentBookContent()} | |
</div> | |
); | |
}; | |
}; | |
App.propTypes = { | |
books: PropTypes.object, | |
members: PropTypes.object | |
}; | |
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%- include('header') -%> | |
<div id="root"><%- initialMarkup -%></div> | |
<%- include('footer') -%> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import App from './components/App'; | |
ReactDOM.render( | |
<App />, | |
document.getElementById('root') | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import config from './config'; | |
import apiRouter from './api'; | |
import sassMiddleware from 'node-sass-middleware'; | |
import path from 'path'; | |
import bodyParser from 'body-parser'; | |
import mongoose from 'mongoose'; | |
mongoose.Promise = global.Promise; | |
mongoose.connect(config.mongodbUri, { useMongoClient: true }) | |
.then(()=> { | |
console.log('Successfully connected to database at: ' + config.mongodbUri); | |
}, | |
err => { | |
throw new Error('Unable to connect to database at: ' + config.mongodbUri); | |
} | |
); | |
import express from 'express'; | |
const server = express(); | |
server.use(bodyParser.json()); | |
server.use(sassMiddleware({ | |
src: path.join(__dirname, 'sass'), | |
dest: path.join(__dirname, 'public') | |
})); | |
//Set view engine for templating | |
server.set('view engine', 'ejs'); | |
import serverRender from './serverRender'; | |
//Rendering the app component on an ejs template on the root level | |
server.get('/', (req, res) => { | |
res.render('index', serverRender()); | |
}); | |
server.use('/api', apiRouter); | |
//Express static middleware used to serve static assets | |
server.use(express.static('public')); | |
server.listen(config.port, config.host, ()=>{ | |
console.info('Express listening on port', config.port); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import ReactDomServer from 'react-dom/server'; | |
import App from './src/components/App'; | |
import config from './config'; | |
const serverRender = () => { | |
return { | |
initialMarkup: ReactDomServer.renderToString( | |
<App /> | |
) | |
} | |
} | |
export default serverRender; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment