Skip to content

solution without persistence #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
1 change: 1 addition & 0 deletions img/add-circle-fill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions img/add-circle-line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<title>Awesome book info collection</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>
7,521 changes: 7,521 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

30 changes: 28 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,38 @@
"version": "1.0.0",
"description": "A package containing a simple dummy book API, which should be used in the challenge",
"scripts": {
"start": "json-server --port 3010 --watch api.json"
"start": "webpack-dev-server --mode development --open --hot",
"json": "json-server --port 3010 --watch api.json"
},
"keywords": ["react challenge", "tryouts", "react developer", "hiring"],
"keywords": [
"react challenge",
"tryouts",
"react developer",
"hiring"
],
"author": "Adapt A/S",
"license": "ISC",
"devDependencies": {
"@babel/preset-env": "^7.7.6",
"@babel/preset-react": "^7.7.4",
"json-server": "0.10.1"
},
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/adaptdk/react-coding-challenge.git"
},
"bugs": {
"url": "https://github.com/adaptdk/react-coding-challenge/issues"
},
"homepage": "https://github.com/adaptdk/react-coding-challenge#readme",
"dependencies": {
"@babel/core": "^7.7.5",
"babel-loader": "^8.0.6",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
}
}
11 changes: 11 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from "react"
import BooksSubjectSelecor from "./BooksSubjectSelecor"

function App(props) {
return (
<div className="container">
<h1>Awesome book info collection</h1>
<BooksSubjectSelecor />
</div>)
}
export default App
112 changes: 112 additions & 0 deletions src/BookDetails.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, {useState, useEffect} from "react"
import BookDetailsAuthors from "./BookDetailsAuthors"
import BookDetailsArray from "./BookDetailsArray"
import BookDetailsFromats from "./BookDetailsFormats"

function BookDetails({book, setNewBookDetails}) {
if (!book) return (<></>)

const [formData, setFormData] = useState(book)

useEffect(()=> {
setFormData(book)
}, [book.id])

let {
id,
authors,
bookshelves,
download_count,
formats,
languages,
media_type,
subjects,
title
} = formData


const setNewArray = (itemsKey, newArray) => {
setFormData(prev => ({
...prev,
[itemsKey]: newArray
}))
}

const handleChange = ({target}) => {
const {name, value} = target
setFormData(prev => ({
...prev,
[name]:value

}))
if (name === "title") {
setNewBookDetails(formData)
}
}
return (
<div>
<h2>Book details</h2>

<div className="title">
<h3>Title</h3>
<input
className="input input-title"
type="text"
name="title"
value={title}
onChange={handleChange}/>
</div>

<div className="mediatype">
<h3>Media type</h3>
<input
className="input input-mediatype"
type="text"
name="media_type"
value={media_type}
onChange={handleChange}/>
</div>

<BookDetailsArray
itemsName={"Languages"}
itemsKey={"languages"}
inputArray={languages}
setNewArray={setNewArray}/>

<BookDetailsArray
itemsName={"Subjects"}
itemsKey={"subjects"}
inputArray={subjects}
setNewArray={setNewArray}/>

<BookDetailsArray
itemsName={"Bookshelves"}
itemsKey={"bookshelves"}
inputArray={bookshelves}
setNewArray={setNewArray}/>

<BookDetailsAuthors
authors={authors}
itemsKey={"authors"}
setNewAuthors={setNewArray} />

<div className="downloadcount">
<h3>Download count</h3>
<input
className="input-downloadcount"
type="number"
name="download_count"
value={download_count}
onChange={handleChange}/>
</div>

<BookDetailsFromats
itemsKey={"formats"}
formats={formats}
setNewFormats={setNewArray}
/>
</div>
)
}

export default BookDetails
78 changes: 78 additions & 0 deletions src/BookDetailsArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, {useState, useEffect, useRef} from "react"

function BookDetailsArray({itemsName, itemsKey, inputArray, setNewArray}) {
const lastField = useRef(null)
const [localArrayState, setlocalArrayState] = useState(inputArray)
const [isNewFieldAdded, setIsNewFieldAdded] = useState(false)

useEffect(()=> {
setlocalArrayState(inputArray)
},[inputArray])

useEffect(()=> {
setNewArray(itemsKey, localArrayState)
if (isNewFieldAdded) {
lastField.current.focus()
setIsNewFieldAdded(false)
}
},[localArrayState])

const handleLanguageChange = (newLanguage, idx) => {
setlocalArrayState(prev => {
const arrayCopy = [...prev]
arrayCopy[idx] = newLanguage
return arrayCopy
})
}

const handleEmpty = value => {
if (value === "") {
setlocalArrayState(prev => [...prev].filter(language => language !== ""))
}
}

const addMore = (fromLink) => {
if (fromLink) {
fromLink.preventDefault()
}
setIsNewFieldAdded(true)
setlocalArrayState([
...localArrayState.filter(language => language !== ""),
""
])
}

const lastInputIndex = localArrayState.length-1
const displayLoacalArray = localArrayState.map((item, idx) => {
return (
<li key={idx}>
<input
className={`input-${itemsKey}`}
ref={idx === lastInputIndex ? lastField: null}
onBlur={({target}) => handleEmpty(target.value)}
onKeyPress={({key}) => key === "Enter" && addMore()}
type="text"
name={`${itemsKey}-${idx}`}
value={item}
onChange={e => handleLanguageChange(e.target.value, idx)}
/>
</li>
)
})

return (
<div className={`${itemsKey}`}>
<div className={`${itemsKey}-lbl`}>
<h3>{itemsName}</h3>
</div>
<ul>{displayLoacalArray}</ul>
<a className={`btn btn-${itemsKey} btn-add`}
onClick={addMore}
href="#"
>
Add more
</a>
</div>
)
}
export default BookDetailsArray
63 changes: 63 additions & 0 deletions src/BookDetailsAuthors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, {useState, useEffect} from "react"
import BookDetailsOneAuthor from "./BookDetailsOneAuthor"

function BookDetailsAuthors({itemsKey, authors, setNewAuthors}) {
if (!authors) return (<></>)

const [localAuthorsArray, setlocalAuthorsArray] = useState(authors)
useEffect(()=> {
setlocalAuthorsArray(authors)
}, [authors])

useEffect(()=> {
setNewAuthors(itemsKey, localAuthorsArray)
}, [localAuthorsArray])

const setAuthor = (prevAuthor, newAuthor) => {
setlocalAuthorsArray(prev => {
return prev.map(author =>
prevAuthor === author ? newAuthor : author)
})
}

const addMore = (fromLink)=> {
if (fromLink){
fromLink.preventDefault()
}
const emptyAuthor = {
"birth_year":"",
"death_year":"",
"name":""
}
setlocalAuthorsArray(prevAuthors => (
[
...prevAuthors,
emptyAuthor
]
))
}

const displayAuthors = localAuthorsArray.map((author, idx) => (
<li key={idx}>
<BookDetailsOneAuthor
author={author}
setAuthor={setAuthor}
idx={idx}
/>
</li>
))

return (
<div>
<h3>Authors</h3>
<ul className="authors">{displayAuthors}</ul>
<a className={`btn btn-authors btn-add`}
onClick={addMore}
href="#"
>
Add author
</a>
</div>
)
}
export default BookDetailsAuthors
Loading