Redesign components in frontend (DRY)
This commit is contained in:
parent
91c530bcd5
commit
cfb3290194
|
@ -2,6 +2,8 @@ from django.urls import path
|
|||
from .views import *
|
||||
|
||||
urlpatterns = [
|
||||
path('books', getAllBooks),
|
||||
path('books/challenge', getChallengeOfYear),
|
||||
path('books/years', getYears),
|
||||
path('books/stats', getStats),
|
||||
|
||||
|
|
|
@ -17,6 +17,15 @@ def getBooksData():
|
|||
|
||||
return df
|
||||
|
||||
def getBookChallenge(year = None):
|
||||
engine = create_engine('mysql+mysqldb://' + ras.settings.DATABASES['default']['USER'] + ':' + ras.settings.DATABASES['default']['PASSWORD'] + '@' + ras.settings.DATABASES['default']['HOST'] + ':3306/' + ras.settings.DATABASES['default']['NAME'])
|
||||
if(year):
|
||||
df = pd.read_sql('SELECT * FROM book_challenge where year = ' + year, engine)
|
||||
else:
|
||||
df = pd.read_sql('SELECT * FROM book_challenge', engine)
|
||||
|
||||
return df
|
||||
|
||||
def filterData(df, datayear = None):
|
||||
df['readed'] = pd.to_datetime(df['readed'], format='%Y-%m-%d')
|
||||
df['readed'] = df['readed'].dt.strftime('%m-%Y')
|
||||
|
@ -27,6 +36,43 @@ def filterData(df, datayear = None):
|
|||
|
||||
return df
|
||||
|
||||
@api_view(['GET'])
|
||||
def getAllBooks(request):
|
||||
|
||||
data = []
|
||||
books = getBooksData()
|
||||
|
||||
for index, row in books.iterrows():
|
||||
data.append({
|
||||
"id": row['id'],
|
||||
"name": row['name'],
|
||||
"author": row['author'],
|
||||
"genre": row['genre'],
|
||||
"author": row['author'],
|
||||
"country": row['country'],
|
||||
"country_code": row['country_code'],
|
||||
"pages": row['pages'],
|
||||
"readed": row['readed'],
|
||||
"rating": row['rating'],
|
||||
})
|
||||
|
||||
return Response(data)
|
||||
|
||||
@api_view(['GET'])
|
||||
def getChallengeOfYear(request):
|
||||
if request.META.get('HTTP_YEAR'):
|
||||
data = []
|
||||
df = getBookChallenge(request.META.get('HTTP_YEAR'))
|
||||
|
||||
for index, row in df.iterrows():
|
||||
data.append({
|
||||
"year": row['year'],
|
||||
"nrofbooks": row['nrofbooks']
|
||||
})
|
||||
|
||||
return Response(data)
|
||||
else:
|
||||
return Response("No year header included")
|
||||
|
||||
@api_view(['GET'])
|
||||
def books_per_genre_per_month(request):
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import React, { Component } from "react";
|
||||
import Challenge from "./components/Challenge";
|
||||
import BookStats from "./components/Stats";
|
||||
|
||||
export default class App extends Component {
|
||||
constructor(props) {
|
||||
|
@ -6,18 +8,14 @@ export default class App extends Component {
|
|||
this.state = {
|
||||
year: new Date().getFullYear(),
|
||||
readingYears: [],
|
||||
totalbooks: 0,
|
||||
totalpages: 0,
|
||||
totalauthors: 0,
|
||||
totalcountries: 0,
|
||||
totalgenres: 0,
|
||||
countries: []
|
||||
countries: [],
|
||||
pagesStats: [],
|
||||
}
|
||||
|
||||
this.yearsArray = [];
|
||||
}
|
||||
|
||||
getGenres(){
|
||||
getGenres() {
|
||||
fetch('/api/books/genres', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
|
@ -27,10 +25,10 @@ export default class App extends Component {
|
|||
.then(response => response.json())
|
||||
.then(books => {
|
||||
this.initChart(books, this.state.year);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getCountries(init){
|
||||
getCountries(init) {
|
||||
fetch('/api/books/countries', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
|
@ -43,7 +41,7 @@ export default class App extends Component {
|
|||
countries: data
|
||||
})
|
||||
|
||||
if(init == true){
|
||||
if (init == true) {
|
||||
$('#DataTable').DataTable({
|
||||
paging: false,
|
||||
ordering: false,
|
||||
|
@ -54,33 +52,31 @@ export default class App extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
getShortestLongestBook(currentyear) {
|
||||
fetch('/api/books/pages/stats', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": currentyear
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(bookstats => {
|
||||
this.setState({
|
||||
pagesStats: bookstats
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
changeYear(event) {
|
||||
|
||||
this.setState({
|
||||
year: event.target.value
|
||||
})
|
||||
|
||||
fetch('/api/books/stats', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": event.target.value
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.setState({
|
||||
totalbooks: data.totalbooks,
|
||||
totalpages: data.totalpages,
|
||||
totalauthors: data.totalauthors,
|
||||
totalcountries: data.totalcountries,
|
||||
totalgenres: data.totalgenres
|
||||
})
|
||||
})
|
||||
|
||||
fetch('/api/books/countries', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": this.state.year
|
||||
"year": event.target.value
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
|
@ -94,19 +90,32 @@ export default class App extends Component {
|
|||
|
||||
var $this = this;
|
||||
|
||||
this.getShortestLongestBook(event.target.value);
|
||||
|
||||
fetch('/api/books/genres/count', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": this.state.year
|
||||
"year": event.target.value
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.initDoughnut(data);
|
||||
})
|
||||
|
||||
fetch('/api/books/genres', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": event.target.value
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(books => {
|
||||
this.initChart(books, event.target.value);
|
||||
})
|
||||
}
|
||||
|
||||
initHorBar(data){
|
||||
initHorBar(data) {
|
||||
|
||||
var countries = [];
|
||||
var counts = [];
|
||||
|
@ -177,10 +186,10 @@ export default class App extends Component {
|
|||
|
||||
const legendMargin = {
|
||||
id: 'legendMargin',
|
||||
beforeInit(chart, legend, options){
|
||||
beforeInit(chart, legend, options) {
|
||||
const fitValue = chart.legend.fit;
|
||||
|
||||
chart.legend.fit = function fit(){
|
||||
chart.legend.fit = function fit() {
|
||||
fitValue.bind(chart.legend)();
|
||||
return this.height += 30;
|
||||
}
|
||||
|
@ -205,19 +214,19 @@ export default class App extends Component {
|
|||
borderColor: '#1f2940',
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(context) {
|
||||
label: function (context) {
|
||||
let label = context.label;
|
||||
let value = context.formattedValue;
|
||||
|
||||
|
||||
if (!label)
|
||||
label = 'Unknown'
|
||||
|
||||
|
||||
let sum = 0;
|
||||
let dataArr = context.chart.data.datasets[0].data;
|
||||
dataArr.map(data => {
|
||||
sum += Number(data);
|
||||
});
|
||||
|
||||
|
||||
let percentage = (value * 100 / sum).toFixed(1) + '%';
|
||||
return label + ": " + percentage;
|
||||
}
|
||||
|
@ -246,24 +255,24 @@ export default class App extends Component {
|
|||
},
|
||||
plugins: [{
|
||||
id: 'legendMargin',
|
||||
beforeInit(chart, legend, options){
|
||||
beforeInit(chart, legend, options) {
|
||||
const fitValue = chart.legend.fit;
|
||||
|
||||
chart.legend.fit = function fit(){
|
||||
|
||||
chart.legend.fit = function fit() {
|
||||
fitValue.bind(chart.legend)();
|
||||
return this.height += 30;
|
||||
}
|
||||
}
|
||||
},{
|
||||
}, {
|
||||
afterDraw: chart => {
|
||||
var ctx = chart.ctx;
|
||||
ctx.save();
|
||||
var image = new Image();
|
||||
var image = new Image();
|
||||
image.src = 'https://www.iconsdb.com/icons/preview/gray/book-xxl.png';
|
||||
var imageSize = 80;
|
||||
ctx.drawImage(image, chart.width / 2 - imageSize / 2, chart.height / 2 - imageSize / 6, imageSize, imageSize);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
@ -335,10 +344,10 @@ export default class App extends Component {
|
|||
|
||||
const legendMargin = {
|
||||
id: 'legendMargin',
|
||||
beforeInit(chart, legend, options){
|
||||
beforeInit(chart, legend, options) {
|
||||
const fitValue = chart.legend.fit;
|
||||
|
||||
chart.legend.fit = function fit(){
|
||||
chart.legend.fit = function fit() {
|
||||
fitValue.bind(chart.legend)();
|
||||
return this.height += 30;
|
||||
}
|
||||
|
@ -358,7 +367,7 @@ export default class App extends Component {
|
|||
legend: {
|
||||
display: true,
|
||||
labels: {
|
||||
usePointStyle: true,
|
||||
usePointStyle: true,
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
|
@ -405,15 +414,11 @@ export default class App extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.getGenres();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
var $this = this;
|
||||
|
||||
var currentyear = this.state.year ? this.state.year : new Date().getFullYear()
|
||||
var currentyear = this.state.year ? this.state.year : new Date().getFullYear();
|
||||
|
||||
fetch('/api/books/genres', {
|
||||
"method": "GET",
|
||||
|
@ -426,6 +431,8 @@ export default class App extends Component {
|
|||
this.initChart(books, currentyear);
|
||||
})
|
||||
|
||||
this.getShortestLongestBook(this.state.year);
|
||||
|
||||
fetch('/api/books/genres/count', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
|
@ -439,48 +446,56 @@ export default class App extends Component {
|
|||
|
||||
this.getCountries(true);
|
||||
|
||||
fetch('/api/books/stats', {
|
||||
fetch('/api/books/years', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": this.state.year
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
$this.setState({
|
||||
totalbooks: data.totalbooks,
|
||||
totalpages: data.totalpages,
|
||||
totalauthors: data.totalauthors,
|
||||
totalcountries: data.totalcountries,
|
||||
totalgenres: data.totalgenres
|
||||
this.setState({
|
||||
readingYears: data
|
||||
})
|
||||
})
|
||||
|
||||
fetch('/api/books/years', {
|
||||
"method": "GET",
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.setState({
|
||||
readingYears: data
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
var url = window.location.href.split("/");
|
||||
var ratingshort = '';
|
||||
var ratinglong = '';
|
||||
|
||||
|
||||
if (this.state.pagesStats.shortestbook) {
|
||||
for (var i = 0; i < this.state.pagesStats.shortestbook.rating; i++) {
|
||||
ratingshort += "<i class='fas fa-star'></i>";
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById("shortest_rating") !== null) {
|
||||
document.getElementById('shortest_rating').innerHTML = ratingshort;
|
||||
}
|
||||
|
||||
if (this.state.pagesStats.longestbook) {
|
||||
for (var i = 0; i < this.state.pagesStats.longestbook.rating; i++) {
|
||||
ratinglong += "<i class='fas fa-star'></i>";
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById("longest_rating") !== null) {
|
||||
document.getElementById('longest_rating').innerHTML = ratinglong;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
|
||||
<React.Fragment>
|
||||
<div className="sidebar">
|
||||
<div className={`menu-item ${ url && url[3] == "" ? 'selected' : ''}`}>
|
||||
<i class="fa fa-chart-bar"></i>
|
||||
<div className={`menu-item ${url && url[3] == "" ? 'selected' : ''}`}>
|
||||
<i className="fa fa-chart-bar"></i>
|
||||
</div>
|
||||
<div className={`menu-item ${ url && url[3] == "books" ? 'selected' : ''}`}>
|
||||
<i class="fa fa-book"></i>
|
||||
<div className={`menu-item ${url && url[3] == "books" ? 'selected' : ''}`}>
|
||||
<i className="fa fa-book"></i>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div className="content">
|
||||
|
||||
|
@ -492,105 +507,94 @@ export default class App extends Component {
|
|||
<div className="row">
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i class="fa fa-calendar"></i>
|
||||
<i className="fa fa-calendar"></i>
|
||||
<span className="stats-number">
|
||||
<select className="yearselector" defaultValue={this.state.year} onChange={(event) => this.changeYear(event)}>
|
||||
{this.state.readingYears.map((year) => {
|
||||
{this.state.readingYears.map((year, i) => {
|
||||
|
||||
if(year === this.state.year){
|
||||
if (year === this.state.year) {
|
||||
var selected = 'selected'
|
||||
}else{
|
||||
} else {
|
||||
selected = ''
|
||||
}
|
||||
|
||||
return(<option selected={selected} value={year}>{year}</option>)
|
||||
return (<option key={i} selected={selected} value={year}>{year}</option>)
|
||||
})}
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i class="fa fa-book"></i>
|
||||
<span className="stats-number">{this.state.totalbooks}</span>
|
||||
<span className="stats-label">Boeken</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i class="fa fa-book-open"></i>
|
||||
<span className="stats-number">{this.state.totalpages}</span>
|
||||
<span className="stats-label">Bladzijdes</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i class="fa fa-pen"></i>
|
||||
<span className="stats-number">{this.state.totalauthors}</span>
|
||||
<span className="stats-label">Schrijvers</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i class="fa fa-book"></i>
|
||||
<span className="stats-number">{this.state.totalgenres}</span>
|
||||
<span className="stats-label">Genres</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i class="fa fa-globe"></i>
|
||||
<span className="stats-number">{this.state.totalcountries}</span>
|
||||
<span className="stats-label">Landen</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BookStats year={this.state.year} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Challenge year={this.state.year} />
|
||||
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-9">
|
||||
<div className="books-per-month"><span className="block_name">Boeken per maand per genre</span><canvas id="chart"></canvas></div>
|
||||
<div className="row">
|
||||
<div className="col-md-6">
|
||||
<div className="book shortest">
|
||||
<span className="block_name">Kortste boek</span>
|
||||
<i className="fa fa-book book-icon"></i>
|
||||
<div className="book_pages">{this.state.pagesStats.shortestbook ? this.state.pagesStats.shortestbook.pages : ''} pagina's</div>
|
||||
<div className="book_title_author">{this.state.pagesStats.shortestbook ? this.state.pagesStats.shortestbook.name : ''} - {this.state.pagesStats.shortestbook ? this.state.pagesStats.shortestbook.author : ''}</div>
|
||||
<div id="shortest_rating" className="book_rating"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<div className="book longest">
|
||||
<span className="block_name">Langste boek</span>
|
||||
<i className="fa fa-book book-icon"></i>
|
||||
<div className="book_pages">{this.state.pagesStats.longestbook ? this.state.pagesStats.longestbook.pages : ''} pagina's</div>
|
||||
<div className="book_title_author">{this.state.pagesStats.longestbook ? this.state.pagesStats.longestbook.name : ''} - {this.state.pagesStats.longestbook ? this.state.pagesStats.longestbook.author : ''}</div>
|
||||
<div id="longest_rating" className="book_rating"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-3">
|
||||
<div className="books-per-country">
|
||||
<div className="books-per-country">
|
||||
<span className="block_name">Landen</span>
|
||||
<table id="DataTable" class="showHead table responsive nowrap" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Land</th>
|
||||
<th>Boeken</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.state.countries.map((country, i) => {
|
||||
<table id="DataTable" className="showHead table responsive nowrap" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Land</th>
|
||||
<th>Boeken</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.state.countries.map((country, i) => {
|
||||
|
||||
var code = country.code.toLowerCase();
|
||||
return(
|
||||
<React.Fragment>
|
||||
<tr>
|
||||
<td>{i+1}</td>
|
||||
<td><img src={`https://flagcdn.com/32x24/${code}.png`} /> {country.country}</td>
|
||||
<td>{country.count}</td>
|
||||
</tr>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
})}
|
||||
</tbody>
|
||||
var code = country.code.toLowerCase();
|
||||
return (
|
||||
<React.Fragment>
|
||||
<tr key="{i}">
|
||||
<td>{i + 1}</td>
|
||||
<td><img src={`https://flagcdn.com/32x24/${code}.png`} /> {country.country}</td>
|
||||
<td>{country.count}</td>
|
||||
</tr>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="genresPercent"><span className="block_name">Genres</span><canvas id="chartGenres"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
import React, { Component } from 'react';
|
||||
import { getChallenge, getStats } from "./Data.js";
|
||||
|
||||
export default class Challenge extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
readingYears: [],
|
||||
challenge: 0
|
||||
}
|
||||
}
|
||||
|
||||
getComponentData(){
|
||||
var $this = this;
|
||||
|
||||
getStats(this.props.year).then(data => {
|
||||
$this.setState({
|
||||
totalbooks: data.totalbooks
|
||||
})
|
||||
});
|
||||
|
||||
getChallenge(this.props.year).then(data => {
|
||||
this.setState({
|
||||
challenge: data && data.length > 0 ? data[0].nrofbooks : 0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getComponentData();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.year !== this.props.year) {
|
||||
this.getComponentData();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
var challengePercentage = (this.state.totalbooks / this.state.challenge) * 100
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.state.challenge && this.state.challenge !== 0 ?
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="stat-block">
|
||||
<span className="block_name">Book Challenge</span>
|
||||
<div className="progress">
|
||||
<div className="progress-bar progress-bar-striped" role="progressbar" style={{ width: challengePercentage + '%' }} aria-valuenow={challengePercentage} aria-valuemin="0" aria-valuemax="100">
|
||||
<div className="progress-bar-number">{challengePercentage}%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span className="stats-number">{this.state.totalbooks}</span><span className="stats-label">van de</span><span className="stats-number">{this.state.challenge}</span><span className="stats-label">boeken gelezen</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: ''}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
export const getStats = (year) => {
|
||||
return fetch('/api/books/stats', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": year
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
return data;
|
||||
})
|
||||
}
|
||||
|
||||
export const getChallenge = (year) => {
|
||||
return fetch('/api/books/challenge', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": year
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
return data
|
||||
})
|
||||
}
|
||||
|
||||
export const getReadingYears = () => {
|
||||
return fetch('/api/books/years', {
|
||||
"method": "GET",
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
return data
|
||||
})
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
import React, { Component } from 'react';
|
||||
import { getStats, getReadingYears } from "./Data.js";
|
||||
|
||||
export default class BookStats extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
readingYears: [],
|
||||
totalbooks: 0,
|
||||
totalpages: 0,
|
||||
totalauthors: 0,
|
||||
totalcountries: 0,
|
||||
totalgenres: 0,
|
||||
}
|
||||
}
|
||||
|
||||
getComponentData(){
|
||||
var $this = this;
|
||||
|
||||
getStats(this.props.year).then(data => {
|
||||
$this.setState({
|
||||
totalbooks: data.totalbooks,
|
||||
totalpages: data.totalpages,
|
||||
totalauthors: data.totalauthors,
|
||||
totalcountries: data.totalcountries,
|
||||
totalgenres: data.totalgenres
|
||||
})
|
||||
});
|
||||
|
||||
getReadingYears().then(data => {
|
||||
this.setState({
|
||||
readingYears: data
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getComponentData();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.year !== this.props.year) {
|
||||
this.getComponentData();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i className="fa fa-book"></i>
|
||||
<span className="stats-number">{this.state.totalbooks}</span>
|
||||
<span className="stats-label">Boeken</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i className="fa fa-book-open"></i>
|
||||
<span className="stats-number">{this.state.totalpages}</span>
|
||||
<span className="stats-label">Bladzijdes</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i className="fa fa-pen"></i>
|
||||
<span className="stats-number">{this.state.totalauthors}</span>
|
||||
<span className="stats-label">Schrijvers</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i className="fa fa-book"></i>
|
||||
<span className="stats-number">{this.state.totalgenres}</span>
|
||||
<span className="stats-label">Genres</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="stat-block">
|
||||
<i className="fa fa-globe"></i>
|
||||
<span className="stats-number">{this.state.totalcountries}</span>
|
||||
<span className="stats-label">Landen</span>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -6,10 +6,22 @@
|
|||
!*** ./src/index.js ***!
|
||||
\**********************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/components/Data.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!*********************************!*\
|
||||
!*** ./src/components/Stats.js ***!
|
||||
\*********************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./node_modules/react/index.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/components/Challenge.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*****************************************!*\
|
||||
!*** ./node_modules/react-dom/index.js ***!
|
||||
\*****************************************/
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
height:600px !important;
|
||||
}
|
||||
|
||||
.books-per-month, .genresPercent, .books-per-country{
|
||||
.books-per-month, .genresPercent, .books-per-country, .book{
|
||||
background: #ffffff;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 0px 1px rgb(0 0 0 / 3%);
|
||||
|
@ -81,6 +81,33 @@
|
|||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.book .book-icon{
|
||||
font-size: 60px;
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 40px;
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.book_rating{
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.book_rating i{
|
||||
font-family: "Font Awesome 5 Free";
|
||||
color: #ffbe0e;
|
||||
}
|
||||
|
||||
.book .book_pages{
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.book .book_title_author{
|
||||
font-size: 16px;
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.sidebar{
|
||||
background: #363a53;
|
||||
width: 70px;
|
||||
|
@ -116,7 +143,7 @@
|
|||
padding: 50px;
|
||||
}
|
||||
|
||||
.books-stats .stat-block{
|
||||
.books-stats .stat-block, .stat-block{
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 0px 1px rgb(0 0 0 / 3%);
|
||||
padding: 15px 5px;
|
||||
|
@ -163,7 +190,7 @@
|
|||
/* box-shadow: 2px 2px 0px 0px rgba(0, 0, 0, 0.3); */
|
||||
}
|
||||
|
||||
.books-stats .stat-block .stats-number{
|
||||
.books-stats .stat-block .stats-number, .stats-number{
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
|
@ -171,7 +198,7 @@
|
|||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.books-stats .stat-block .stats-label{
|
||||
.books-stats .stat-block .stats-label, .stats-label{
|
||||
color: #a7adbd;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
|
@ -218,6 +245,34 @@
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.progress{
|
||||
background: #f8f8fa;
|
||||
height: 50px;
|
||||
border: solid 2px #efefef;
|
||||
padding: 5px;
|
||||
border-radius: 0;
|
||||
margin: 0 15px 15px 15px;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background-color: #8066ee;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
border-right: solid 2px #333;
|
||||
}
|
||||
|
||||
.progress-bar-number{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
background: #333;
|
||||
border-radius: 50%;
|
||||
padding: 10px;
|
||||
top: -20px;
|
||||
right: -20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
|
Loading…
Reference in New Issue