Skip to content

Commit

Permalink
Updating dependencies and using functional components to finish the app.
Browse files Browse the repository at this point in the history
  • Loading branch information
pmaher committed Feb 24, 2021
1 parent ae26155 commit e4e21e4
Show file tree
Hide file tree
Showing 15 changed files with 30,510 additions and 44 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
.DS_STORE
keys.js
3 changes: 3 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ["@babel/preset-env", "@babel/preset-react"],
};
12 changes: 12 additions & 0 deletions client/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

export default (props) => {
return (
<div className="container">
{/* pass any props to the child components */}
{React.Children.map(props.children, child => {
return React.cloneElement(child, { ...props })
})}
</div>
)
}
35 changes: 35 additions & 0 deletions client/components/LyricCreate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useState } from 'react';

import { useMutation } from "@apollo/client";
import { withRouter } from 'react-router-dom';
import { ADD_LYRIC_TO_SONG } from '../queries/apolloQueries';

const LyricCreate = ({songId, history}) => {

const [content, setContent] = useState('');
const [ addLyricToSongMutation] = useMutation(ADD_LYRIC_TO_SONG);

const onSubmit = (event) => {
event.preventDefault();

addLyricToSongMutation({
variables: {
songId,
content
}
}).then(()=> setContent(''))
.then(() => history.push('/'));
}

return (
<form onSubmit={onSubmit}>
<label>Add a Lyric</label>
<input
value={content}
onChange={event => setContent(event.target.value)}
/>
</form>
);
};

export default LyricCreate;
43 changes: 43 additions & 0 deletions client/components/LyricList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';

import { useMutation } from "@apollo/client";
import { LIKE_LYRIC, LIKE_LYRIC_OPTIMISTIC_RESPONSE } from '../queries/apolloQueries';

const LyricList = ({lyrics}) => {

const [ likeLyricMutation ] = useMutation(LIKE_LYRIC);


const onLike = (id, likes) => {
likeLyricMutation({
variables: { id },
optimisticResponse: {
__typename: 'Mutation',
likeLyric: {
id,
__typename: 'LyricType',
likes: likes + 1
}
}
// refetchQueries: [ { query: FETCH_SONGS }]
});
};

return (
<ul className="collection">
{lyrics.map(({ id, content, likes })=> (
<li key={id} className="collection-item">
{content}
<div className="vote-box">
{ likes }
<i className="material-icons"
onClick={() => onLike(id, likes)}
>thumb_up</i>
</div>
</li>
))}
</ul>
);
}

export default LyricList;
36 changes: 36 additions & 0 deletions client/components/SongCreate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState } from 'react';

import { useMutation } from "@apollo/client";
import { withRouter, Link } from 'react-router-dom';
import { ADD_SONG, FETCH_SONGS} from '../queries/apolloQueries';

const SongCreate = ({history}) => {
const [songTitle, setSongTitle] = useState('');
const [ addSongMutation] = useMutation(ADD_SONG);

const onSubmit = (e) => {
e.preventDefault();

addSongMutation({
variables: { title: songTitle },
refetchQueries: [ { query: FETCH_SONGS }]
}).then(() => {
history.push('/');
});
}
return (
<div>
<Link to="/">Back</Link>
<h3>Create a New Song</h3>
<form onSubmit={onSubmit}>
<label>Song Title</label>
<input
onChange={e => setSongTitle(e.target.value)}
value={songTitle}
/>
</form>
</div>
);
}

export default withRouter(SongCreate);
34 changes: 34 additions & 0 deletions client/components/SongDetail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { withRouter } from 'react-router';
import { useParams } from 'react-router-dom';

import { GET_SONG } from '../queries/apolloQueries';
import { useQuery } from "@apollo/client";
import LyricCreate from './LyricCreate';
import LyricList from './LyricList';

const SongDetail = ({history}) => {

let { id } = useParams();
const { data, loading, error } = useQuery(GET_SONG, {
variables: { id }
});

if (loading) return <p>Loading...</p>;
if (error) return <p>ERROR: {error.message}</p>;
if (!data?.song) return <p>Not found</p>;

const { title, lyrics } = data.song;

console.dir(data.song);

return (<div>
<Link to="/">Back</Link>
<h3>{title}</h3>
<LyricList lyrics={lyrics} />
<LyricCreate songId={id} history={history} />
</div>);
}

export default withRouter(SongDetail);
46 changes: 46 additions & 0 deletions client/components/SongList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import { DELETE_SONG, FETCH_SONGS } from '../queries/apolloQueries';
import { Link } from 'react-router-dom';
import { useQuery, useMutation } from "@apollo/client";

const SongList = () => {
const { data, loading, error } = useQuery(FETCH_SONGS);
const [ deleteSongMutation] = useMutation(DELETE_SONG);

if (loading) return <p>Loading...</p>;
if (error) return <p>ERROR: {error.message}</p>;
if (!data) return <p>Not found</p>;

const deleteSong = (id) => {
deleteSongMutation({
variables: { id },
refetchQueries: [ { query: FETCH_SONGS }]
});
}

return (
<div>
<ul className="collection">
{data && data.songs && data.songs.map(({id, title}) => (
<li key={id} className="collection-item">
<Link to={`/songs/${id}`}>
{title}
</Link>
<i
className="material-icons"
onClick={() => deleteSong(id)}
>delete</i>
</li>
))}
</ul>
<Link
to="/songs/new"
className="btn-floating btn-large red right">
<i className="material-icons">add</i>
</Link>
</div>
)

}

export default SongList;
40 changes: 38 additions & 2 deletions client/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,47 @@
import './style/style.css';
import React from 'react';
import { HashRouter, Route, Switch } from 'react-router-dom';
import ReactDOM from 'react-dom';
import { ApolloClient, ApolloProvider } from "@apollo/client";
import { InMemoryCache } from 'apollo-cache-inmemory';
import SongList from './components/SongList';
import SongCreate from './components/SongCreate';
import { createHttpLink } from "apollo-link-http";
import App from './components/App';
import SongDetail from './components/SongDetail';

const cache = new InMemoryCache();

const httpLink = createHttpLink({
uri: "http://localhost:4000/graphql"
});

const client = new ApolloClient({
link: httpLink,
cache
});

const Root = () => {
return <div>Lyrical</div>
return (
<ApolloProvider client={client}>
<HashRouter>
<Switch>
<Route exact path="/">
<App children={<SongList />}></App>
</Route>
<Route exact path="/songs/new">
<App children={<SongCreate />}></App>
</Route>
<Route path="/songs/:id">
<App children={<SongDetail />}></App>
</Route>
</Switch>
</HashRouter>
</ApolloProvider>
)
};

ReactDOM.render(
<Root />,
document.querySelector('#root')
);
);
61 changes: 61 additions & 0 deletions client/queries/apolloQueries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { gql } from "@apollo/client";

export const GET_SONG = gql`
query SongQuery($id: ID!) {
song(id: $id) {
id
title
lyrics {
id
content
likes
}
}
}
`;

export const ADD_SONG = gql`
mutation AddSong($title: String) {
addSong(title: $title) {
id
title
}
}
`;

export const FETCH_SONGS = gql`
{
songs {
id
title
}
}
`;

export const DELETE_SONG = gql`
mutation DeleteSong($id: ID) {
deleteSong(id: $id) {
id
}
}
`;

export const ADD_LYRIC_TO_SONG = gql`
mutation AddLyricToSong($content: String, $songId: ID) {
addLyricToSong(content: $content, songId: $songId) {
id
lyrics {
content
}
}
}
`;

export const LIKE_LYRIC = gql`
mutation LikeLyric($id: ID) {
likeLyric(id: $id) {
id
likes
}
}
`;
14 changes: 14 additions & 0 deletions client/style/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.collection-item {
display: flex;
justify-content: space-between;
}

.material-icons {
cursor: pointer;
margin-left: 5px;
}

.vote-box {
display: flex;
align-items: flex-end;
}
Loading

0 comments on commit e4e21e4

Please sign in to comment.