Skip to content
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

Exquisite Corpse #8

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TESTING=Yay!
75 changes: 27 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,27 @@
# Pick your own project

Build an app of your choice.

- You are free to use any technologies covered so far, but feel free to try new technologies you find interesting.
- Keep it simple. Aim to get the basic functionality working on day one. You can then extend it on days two and three.
- Feel free to use an external API to provide additional functionality to your app. Use an API that either does not have any authentication or uses API keys.
- This is an opportunity to practice the parts you have challenging so far and improve your understanding of them.
- Use pen and paper to draw a diagram of the webpage layout before starting to code. Have a think about what components you will need in advance.
- Use prop-types and stateless components where appropriate.
- Try to use Sass to create a separate stylesheet for each component.
- Try to add some unit testing. Some parts will be easier to test than others, focus on those first.
- Think about how to organise your data in advance
- Make sure your app is responsive
- Commit frequently
- Create pull request at the end
- Demos will be at 4pm on Friday
- Keep it simple

## Technical notes

* Run `npm install` after cloning to download all dependencies
* Use `npm run dev -- --watch` to build React
* Use `npm test` or `npm test -- --watchAll` to run tests

## README

* Produce a README.md which explains
* what the project does
* what technologies it uses
* how to build it and run it
* any unresolved issues the user should be aware of

## Inspiration

- Take a look at [https://public-apis.jeremyfairbank.com/](https://public-apis.jeremyfairbank.com/) or [https://github.com/toddmotto/public-apis](https://github.com/toddmotto/public-apis) for possible APIs to use.

## Default option

If you are struggling to think of a project to build. Try to create a Top Trumps using the [Star Wars API](https://swapi.co/) which allows one user to play the game against the computer.

- On load, fetch all vehicles from [https://swapi.co/api/vehicles/](https://swapi.co/api/vehicles/) end point.
- Randomise the cards and deal half to player and half to computer.
- Display top card to user
- Allow user to pick an attribute from their card such as `cost_in_credits`, `length`, `max_atmosphering_speed`, `crew`, `passengers`, `cargo_capacity`.
- If the value for chosen attribute is higher on the user's card than on computer's top card, they win the computer's card and it should be taken from computer's deck and added to the bottom of the user's deck. If the attribute is higher on the computer's top card, then user's card should be taken from the user's deck and added to the bottom of computer's deck.
- Game continues until either user or computer has all the cards.
- Implement some features of your choosing.
![Screenshot](./static/exquisite-corpse-1.png)

# Exquisite Corpse

Exquisite corpse (_cadavre exquis_ in French) is a game invented by the Surrealists aimed at stimulating creative response. The method involves the collection and assemblage of generated words or images, according to an agreed rule (in this case “Adjective-Noun”).

This game seeks to mimic the original by randomly generating lists of words, selected by type (adjective/adverb - noun/verb) and combining the results to create unique combinations. Intriguing combinations may then be chosen for 'workshopping' - with a timer allowing 5 minutes \* of free-flow writing.

### Features

- "random" endpoint on API is used to fetch 3 cycles of words, which the user may select by type - adjective/adverb, noun/verb
- local storage is used to select generatedword combinations for workshopping (may be added or deleted from selected stock)
- timer set on adding word combo to the workshop textarea
- css classes (with animation) indicate when word combo has been added, and when the timer is reaching end

**The app is currently under development:**

- Add descriptions as tooltips to generated word lists - this requires rebuild of word list arrays as objects with keys word: and definition, so as to pull in definition with Fetch.
- Textarea functionality set to fade… whenever user pauses
- Currently desktop-oriented design; address UX for mobile usage - server a different view for writing
- Resets required for select menus

### Looking forward

- Develop using GraphQL API approach, with OED

\* set to 10s for testing!
10 changes: 7 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="./style.css">
<title>YouJuke</title>
<link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="./style.css"> -->

<title>Exquisite Corpse</title>
</head>
<body>
<div className="container">

<div class="container">
<div id="root"></div>
</div>
<script src="dist/bundle.js"></script>
Expand Down
28 changes: 21 additions & 7 deletions package-lock.json

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

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
},
"dependencies": {
"classnames": "^2.2.6",
"prop-types": "^15.6.1",
"dotenv": "^6.1.0",
"prop-types": "^15.6.2",
"react": "^16.2.0",
"react-dom": "^16.2.0"
"react-dom": "^16.2.0",
"react-timer-machine": "^1.0.1",
"timer-machine": "^1.1.0"
},
"devDependencies": {
"babel-jest": "^22.4.1",
Expand Down
108 changes: 100 additions & 8 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,111 @@
import React from 'react';
// https://wordsapiv1.p.mashape.com/words/?partOfSpeech=noun
// https://wordsapiv1.p.mashape.com/words/?partOfSpeech=adjective

import '../styles/components/app.scss';
import React from "react";
import Generate from "./Generate";
import Favourites from "./Favourites";

class App extends React.Component {
import "../styles/base/base.scss";
import "../styles/components/app.scss";

constructor(){
class App extends React.Component {
constructor() {
super();
this.state = {
type1Result: [],
type2Result: [],
favourites: []
};
this.receiveType = this.receiveType.bind(this);
this.addFavourites = this.addFavourites.bind(this);
this.removeFromFavourites = this.removeFromFavourites.bind(this);
}

// want to add this into the fetch content.results[0].definition

fetchWords(type, source) {
let tempArr = [];
const wordsUrl = `https://wordsapiv1.p.mashape.com/words/?partOfSpeech=${type}&random=true`;

for (let i = 0; i < 3; i++) {
fetch(wordsUrl, {
headers: {
"X-Mashape-Key": "wZCRY1mr7wmsh03nJhT5o7UZZ6uYp16uOdRjsnMQ91Z2XQEGFb",
"X-Mashape-Host": "wordsapiv1.p.mashape.com"
}
})
.then(response => response.json())
.then(content => {
tempArr = tempArr.concat([content.word]);
if (source === "type1") {
this.setState({ type1Result: tempArr });
}
if (source === "type2") {
this.setState({ type2Result: tempArr });
}
});
}
}

receiveType(type, source) {
this.fetchWords(type, source);
}

addFavourites(corpseitem) {
const favourites = this.state.favourites.concat(corpseitem);
this.setState({
Copy link
Contributor

Choose a reason for hiding this comment

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

rather than using a callback here, it would be better to use

const favourites = this.state.favourites.concat(corpseitem);
this.setState({
  favourites: favourites
});
window.localStorage.setItem('favourites', favourites);

favourites: favourites
});
window.localStorage.setItem("favourites", favourites);
}

render(){
removeFromFavourites(corpseitem) {
const filteredFavourites = this.state.favourites.filter(
currentFavourite => {
return currentFavourite !== corpseitem;
}
);
this.setState({
favourites: filteredFavourites
});
}

render() {
return (
<div className="app">
App goes here
<div className="app container">
<header className="masthead">
<h1 className="masthead__title">Exquisite Corpse</h1>
<div className="masthead__description">
<p>
Exquisite corpse (<em>cadavre exquis</em> in French) is a game
invented by the Surrealists aimed at stimulating creative
response. The method involves the collection and assemblage of
generated words or images, according to an agreed rule (in this
case &ldquo;Adjective-Noun&rdquo;).
</p>
<p>
This game seeks to mimic the original by randomly generating lists
of adjectives and nouns and combining the results to create unique
combinations. Intriguing combinations may then be chosen for
'workshopping' – 5 minutes of free-flow writing.
</p>
</div>
</header>

<main className="main">
<Favourites favourites={this.state.favourites} />

<Generate
receiveType={this.receiveType}
typeresult1={this.state.type1Result}
typeresult2={this.state.type2Result}
addFavourites={this.addFavourites}
removeFromFavourites={this.removeFromFavourites}
favourites={this.state.favourites}
/>
</main>
</div>
)
);
}
}

Expand Down
38 changes: 38 additions & 0 deletions src/components/Favourite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react";
import TimerMachine from "./TimerMachine";
import cx from "classnames";

import "../styles/components/favourite.scss";

class Favourite extends React.Component {
constructor() {
super();
this.state = { active: false };
this.handleClick = this.handleClick.bind(this);
}

handleClick(event) {
this.setState({
active: !this.state.active
});
}

render() {
const favouriteclasses = cx("workshop__favourite", {
active: this.state.active
});

return (
<li className="workshop__listitem">
<h4>
<a href="#" className={favouriteclasses} onClick={this.handleClick}>
{this.props.favourite}
</a>
</h4>
{this.state.active ? <TimerMachine /> : null}
</li>
);
}
}

export default Favourite;
33 changes: 33 additions & 0 deletions src/components/Favourites.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import Favourite from "./Favourite";
import "../styles/components/favourites.scss";

function Favourites({ favourites }) {
return (
<section className="workshop">
<h2>Workshop</h2>
<ol>
<li>
<strong>Generate</strong> nouns and adjectives to create a list of
&lsquo;exquisite corpses&rsquo;
</li>
<li>
<i className="fas fa-plus-circle" /> appealing exquisite corpses to
the workshop area
</li>
<li>
<strong>Select</strong> a corpse to start the timer and begin writing.
Do not pause.
</li>
</ol>
<ul className="workshop__favourites menu--settings">
{favourites.map(favourite => (
<Favourite favourite={favourite} key={favourite} />
))}
</ul>
<textarea className="workshop__textarea" />
</section>
);
}

export default Favourites;
Loading