Skip to content
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
15 changes: 12 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
"devDependencies": {
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"enzyme-to-json": "^3.3.5",
"gh-pages": "^2.0.1"
},
"jest": {
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
}
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link href="https://fonts.googleapis.com/css?family=Raleway|Permanent+Marker" rel="stylesheet">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Expand Down
4 changes: 3 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import React, { Component } from 'react';
import './App.css';
import Board from './components/Board';


class App extends Component {

render() {
return (
<section>
<header className="header">
<h1 className="header__h1"><span className="header__text">Inspiration Board</span></h1>
</header>
<Board
url="https://inspiration-board.herokuapp.com/boards/"
url="https://inspiration-board.herokuapp.com"
boardName={`Ada-Lovelace`}
/>
</section>
Expand Down
17 changes: 16 additions & 1 deletion src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { shallow } from 'enzyme';
import { mount, shallow } from 'enzyme';
import App from './App';

describe('App', () => {
Expand All @@ -12,3 +12,18 @@ describe('App', () => {
});

});

describe('<App />', () => {
test('that it renders App with shallow rendering', () => {
const wrapper = shallow(<App />);
expect(wrapper).toMatchSnapshot();
});

test('will match the last snapshot with deep rendering', () => {
const wrapper = mount(<App />);
expect(wrapper).toMatchSnapshot;

wrapper.unmount();
});

});
23 changes: 23 additions & 0 deletions src/__snapshots__/App.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<App /> that it renders App with shallow rendering 1`] = `
<section>
<header
className="header"
>
<h1
className="header__h1"
>
<span
className="header__text"
>
Inspiration Board
</span>
</h1>
</header>
<Board
boardName="Ada-Lovelace"
url="https://inspiration-board.herokuapp.com"
/>
</section>
`;
103 changes: 97 additions & 6 deletions src/components/Board.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,117 @@ import NewCardForm from './NewCardForm';
import CARD_DATA from '../data/card-data.json';

class Board extends Component {
constructor() {
super();

constructor(props) {
super(props);

this.state = {
cards: [],
};
}

componentDidMount() {

const url = `${this.props.url}/boards/katrina/cards`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how you constructed this URL! Maybe you could've used the prop boardName if you had set it to katrina (passed in from App)


axios.get(url)
.then((response) => {
this.setState({
cards: response.data,
});
})
.catch((error) => {
const errors = error.response.data.errors.text;
this.setState({
error: errors,
});
});
};


deleteCard = (id) => {

const url = `${this.props.url}/cards/${id}`;

axios.delete(url)
.then(() => {
const updatedCardsList = this.state.cards;
updatedCardsList.forEach((card, i) => {
if (id === card.card.id) {
updatedCardsList.splice(i, 1);
};
});
this.setState({
cards: updatedCardsList
});
})
.catch((error) => {
const errors = error.response.data.errors.text;
this.setState({
error: errors,
});
});
};


addCard = (cardData) => {

const url = `${this.props.url}/boards/katrina/cards`;

axios.post(url, cardData)
.then((response) => {
const updatedCardsList = [...this.state.cards, response.data]
this.setState({
cards: updatedCardsList,
});
})
.catch((error) => {
const errors = error.response.data.errors.text;
this.setState({
error: errors,
});
});
};


render() {
const cardList = this.state.cards.map((card, i) => {
const cardData = card.card;

return (
<Card
key={i}
{...cardData}
onDeleteClickCallback={this.deleteCard}
/>
)
});


const errorMessages = this.state.error ? this.state.error.map((message, i) => {
return (<h3><li key={i}>{message}</li></h3>) }) : '';


return (
<div>
Board
</div>
<section>
<header className="validation-errors-display">
<ul className="validation-errors-display__list">
{errorMessages}
</ul>
</header>
<div className="board">
{cardList}
</div>
<NewCardForm addCardCallback={this.addCard} />
</section>
)
}

}

Board.propTypes = {

Board.propTypes = {
cards: PropTypes.array,
};

export default Board;
Empty file removed src/components/Board.test.js
Empty file.
3 changes: 2 additions & 1 deletion src/components/Card.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
}

.card__delete {
align-self: start;
align-self: center;
margin-top: 2rem;
font-family: 'Permanent Marker', Helvetica, sans-serif;
}
21 changes: 19 additions & 2 deletions src/components/Card.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,34 @@ import emoji from 'emoji-dictionary';
import './Card.css';

class Card extends Component {

render() {

const emojiName = this.props.emoji ? this.props.emoji : '';

return (
<div className="card">
Card
<div className="card__content">
<p className="card__content-text">{this.props.text}</p>
<span className="card__content-emoji">{emoji.getUnicode(emojiName)}</span>
<button
type="button"
aria-label="Delete"
className="card__delete"
onClick={() => this.props.onDeleteClickCallback(this.props.id)}
>
Delete
</button>
</div>
</div>
)
}
}

Card.propTypes = {

id: PropTypes.number,
text: PropTypes.string,
emoji: PropTypes.string,
};

export default Card;
98 changes: 97 additions & 1 deletion src/components/NewCardForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,100 @@ import PropTypes from 'prop-types';
import emoji from 'emoji-dictionary';
import './NewCardForm.css';

const EMOJI_LIST = ["", "heart_eyes", "beer", "clap", "sparkling_heart", "heart_eyes_cat", "dog"]

const EMOJI_LIST = ["", "heart_eyes", "beer", "clap", "sparkling_heart", "heart_eyes_cat", "dog", "poop", "cookie", "doughnut" ];


class NewCardForm extends Component {
constructor(props) {
super(props);

this.state = {
text: '',
emoji: '',
};
};


onInputChange = (event) => {
const field = event.target.name;
const value = event.target.value;
const conditionalValue = field === "emoji" ? emoji.getName(value) : value;

const newState = {};
newState[field] = conditionalValue;

this.setState(newState);
};


onFormSubmit = (event) => {
event.preventDefault();

const { id, text, emoji } = this.state;

this.props.addCardCallback(this.state);

this.setState({
text: '',
});
};


render() {

const dropDownEmoji = EMOJI_LIST.map((emojiIcon, i) => {
return (
<option key={i}>{emoji.getUnicode(emojiIcon)}</option>
);
});

return (
<div className="new-card-form">
<h3 className="new-card-form__header">Give me some inspo!</h3>
<div>

<form
className="new-card-form__form"
onSubmit={this.onFormSubmit}
>

<div>
<label htmlFor="text" className="new-card-form__form-label">
Text
</label>
</div>

<textarea
name="text"
value={this.state.text}
className="new-card-form__form-textarea"
onChange={this.onInputChange}
/>

<label htmlFor="emoji-select">Emoji</label>

<select
id="emoji-select"
className="new-card-form__form-select"
onChange={this.onInputChange}
name="emoji"
>
{dropDownEmoji}
</select>

<input className="new-card-form__form-button" type="submit" name="submit" value="Add Card" />
</form>
</div>
</div>
)
};

};

NewCardForm.propTypes = {
addCardCallback: PropTypes.func.isRequired,
};


export default NewCardForm;
Empty file removed src/components/NewCardForm.test.js
Empty file.
Loading