diff --git a/Dockerfile b/Dockerfile index c74c5c5..6719b4f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,8 @@ WORKDIR /usr/src/app ENV INLINE_RUNTIME_CHUNK false +ENV API_URL http://localhost:3000/api + COPY package*.json ./ RUN npm install diff --git a/docker-compose.yml b/docker-compose.yml index 72ae06e..bbc940a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: depends_on: - postgres environment: - API_URL: http://localhost:3000/ + API_URL: http://localhost:3000/api DATABASE_URL: postgres://user:pass@postgres:5432/db NODE_ENV: development PORT: 3000 diff --git a/server/data/seeds/002_seed_resolutions.js b/server/data/seeds/002_seed_resolutions.js index 430d50f..3a78a50 100644 --- a/server/data/seeds/002_seed_resolutions.js +++ b/server/data/seeds/002_seed_resolutions.js @@ -1,10 +1,15 @@ exports.seed = (knex) => { return knex('resolution') .del() - .then(() => { - return knex('resolution').insert([ - { user_id: 1, content: 'lose 15 lbs' }, - { user_id: 1, content: 'actually fulfill resolutions this year' }, - ]); - }); + .then(() => + knex + .select('id') + .from('user') + .then(([{ id }]) => + knex('resolution').insert([ + { user_id: id, content: 'Lose 15 lbs' }, + { user_id: id, content: 'Actually fulfill resolutions this year' }, + ]) + ) + ); }; diff --git a/src/client/client.js b/src/client/client.js index 8d4b57c..0b0f3bf 100644 --- a/src/client/client.js +++ b/src/client/client.js @@ -21,4 +21,10 @@ module.exports = { password, }), logoutClient: () => instance.post('/logout'), + getAllResolutions: () => instance.get('/resolution'), + getResloutionById: (id) => instance.get(`/resolution/${id}`), + createResolution: ({ content }) => instance.post('/resolution', { content }), + patchResolution: ({ id, content }) => + instance.patch(`/resolution/${id}`, { content }), + deleteResolution: ({ id }) => instance.delete(`/resolution/${id}`), }; diff --git a/src/components/App/App.js b/src/components/App/App.js index eb454af..845bb15 100644 --- a/src/components/App/App.js +++ b/src/components/App/App.js @@ -6,7 +6,15 @@ import LandingPage from '../LandingPage/LandingPage'; import PageHeader from '../PageHeader/PageHeader'; import RegistrationPage from '../RegistrationPage/RegistrationPage'; import LoginPage from '../LoginPage/LoginPage'; -import { registerUser, loginClient, logoutClient } from '../../client/client'; +import HomePage from '../HomePage/HomePage'; +import CreateResolutionPage from '../CreateResolutionPage/CreateResolutionPage'; +import { + registerUser, + loginClient, + logoutClient, + getAllResolutions, + createResolution, +} from '../../client/client'; const theme = createMuiTheme({ palette: { @@ -36,7 +44,9 @@ function App() { handleSetUser={handleSetUser} /> - + + + @@ -47,6 +57,15 @@ function App() { handleLogin={handleSetUser} /> + + + + + + diff --git a/src/components/CreateResolutionPage/CreateResolutionPage.js b/src/components/CreateResolutionPage/CreateResolutionPage.js new file mode 100644 index 0000000..060263c --- /dev/null +++ b/src/components/CreateResolutionPage/CreateResolutionPage.js @@ -0,0 +1,97 @@ +import React, { useEffect, useState } from 'react'; +import { Link as RouterLink, Redirect } from 'react-router-dom'; +import { makeStyles } from '@material-ui/core/styles'; +import { Container, Typography, TextField, Button } from '@material-ui/core'; + +const useStyles = makeStyles((theme) => ({ + paper: { + marginTop: theme.spacing(8), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + }, + avatar: { + margin: theme.spacing(1), + backgroundColor: theme.palette.secondary.main, + }, + form: { + width: '100%', + marginTop: theme.spacing(3), + }, + submit: { + margin: theme.spacing(3, 0, 2), + }, +})); + +function CreateResolutionPage({ user, createResolution }) { + const classes = useStyles(); + + const [content, setContent] = useState(''); + const [redirect, setRedirect] = useState(false); + const [contentError, setContentError] = useState(''); + + useEffect(() => { + setContentError(''); + }, [content]); + + const handleChangeContent = (event) => { + setContent(event.target.value); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + + if (!content.trim()) { + setContentError('Resolution is required'); + } + + const noErrors = content.trim(); + + if (noErrors) { + createResolution({ content }); + setRedirect(true); + } + }; + + return ( + + {user ? null : } + {redirect ? : null} +
+ + Create Resolution + +
e.preventDefault()}> + + + +
+
+ ); +} + +export default CreateResolutionPage; diff --git a/src/components/CreateResolutionPage/CreateResolutionPage.test.js b/src/components/CreateResolutionPage/CreateResolutionPage.test.js new file mode 100644 index 0000000..4f1fdc4 --- /dev/null +++ b/src/components/CreateResolutionPage/CreateResolutionPage.test.js @@ -0,0 +1,5 @@ +describe('CreateResolutionPage', () => { + it('should', () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/src/components/HomePage/HomePage.js b/src/components/HomePage/HomePage.js new file mode 100644 index 0000000..5f6ec18 --- /dev/null +++ b/src/components/HomePage/HomePage.js @@ -0,0 +1,51 @@ +import React, { useEffect, useState } from 'react'; +import { Link as RouterLink, Redirect } from 'react-router-dom'; +import { Container, Fab } from '@material-ui/core'; +import Resolution from '../Resolution/Resolution'; +import AddIcon from '@material-ui/icons/Add'; +import { makeStyles } from '@material-ui/core/styles'; + +const useStyles = makeStyles((theme) => ({ + fab: { + position: 'absolute', + bottom: theme.spacing(10), + right: theme.spacing(10), + }, + root: { + padding: theme.spacing(3), + }, +})); + +function HomePage({ user, getAllResolutions }) { + const classes = useStyles(); + const [resolutions, setResolutions] = useState([]); + + useEffect(() => { + getAllResolutions().then(({ data }) => { + console.log(data); + setResolutions(data); + }); + }, [getAllResolutions]); + + return ( +
+ {user ? null : } + + {resolutions.map((resolution) => ( + + ))} + + + + +
+ ); +} + +export default HomePage; diff --git a/src/components/HomePage/HomePage.test.js b/src/components/HomePage/HomePage.test.js new file mode 100644 index 0000000..b8d6356 --- /dev/null +++ b/src/components/HomePage/HomePage.test.js @@ -0,0 +1,5 @@ +describe('HomePage', () => { + it('should', () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/src/components/LandingPage/LandingPage.js b/src/components/LandingPage/LandingPage.js index 0e4d882..2f6a386 100644 --- a/src/components/LandingPage/LandingPage.js +++ b/src/components/LandingPage/LandingPage.js @@ -1,6 +1,5 @@ import React from 'react'; -import { Link as RouterLink } from 'react-router-dom'; - +import { Link as RouterLink, Redirect } from 'react-router-dom'; import { Container, Typography, @@ -30,10 +29,11 @@ const useStyles = makeStyles((theme) => ({ }, })); -function LandingPage(props) { +function LandingPage({ user }) { const classes = useStyles(); return (
+ {user ? : null} - +
diff --git a/src/components/LoginPage/LoginPage.js b/src/components/LoginPage/LoginPage.js index e759e53..1c862c1 100644 --- a/src/components/LoginPage/LoginPage.js +++ b/src/components/LoginPage/LoginPage.js @@ -10,7 +10,7 @@ import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import Container from '@material-ui/core/Container'; import Copyright from '../Copyright/Copyright'; -import { Link as RouterLink } from 'react-router-dom'; +import { Link as RouterLink, Redirect } from 'react-router-dom'; const useStyles = makeStyles((theme) => ({ paper: { @@ -32,7 +32,7 @@ const useStyles = makeStyles((theme) => ({ }, })); -export default function LoginPage({ loginClient, handleLogin }) { +export default function LoginPage({ loginClient, handleLogin, user }) { const classes = useStyles(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); @@ -48,6 +48,7 @@ export default function LoginPage({ loginClient, handleLogin }) { }, [password]); const handleSubmit = (event) => { + event.preventDefault(); if (email.trim() && password.trim()) { loginClient({ email, password }).then((res) => { handleLogin(res.data); @@ -67,6 +68,7 @@ export default function LoginPage({ loginClient, handleLogin }) { return ( + {user ? : null}
diff --git a/src/components/Resolution/Resolution.js b/src/components/Resolution/Resolution.js new file mode 100644 index 0000000..867bc56 --- /dev/null +++ b/src/components/Resolution/Resolution.js @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { Paper, Avatar, IconButton } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import FavoriteIcon from '@material-ui/icons/Favorite'; +import FavoriteBorderIcon from '@material-ui/icons/FavoriteBorder'; +import BookmarkIcon from '@material-ui/icons/Bookmark'; +import BookmarkBorderIcon from '@material-ui/icons/BookmarkBorder'; + +const useStyles = makeStyles((theme) => ({ + paper: { + marginTop: theme.spacing(1), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + padding: theme.spacing(1), + }, + upperContent: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + width: '100%', + }, + buttonGroup: { width: '100%', paddingLeft: theme.spacing(8) }, + avatar: { + margin: theme.spacing(1), + marginRight: theme.spacing(3), + backgroundColor: theme.palette.secondary.main, + }, +})); + +function Resolution({ resolution }) { + const classes = useStyles(); + const [favorited, setFavorited] = useState(false); + const [bookmarked, setBookmarked] = useState(false); + + const handleFavorited = () => { + setFavorited(!favorited); + }; + const handleBookmarked = () => { + setBookmarked(!bookmarked); + }; + + return ( + +
+ + {resolution?.content} +
+
+ + {favorited ? : } + + {favorited ? '1' : '0'} + + {bookmarked ? : } + + {bookmarked ? '1' : '0'} +
+
+ ); +} + +export default Resolution; diff --git a/src/components/Resolution/Resolution.test.js b/src/components/Resolution/Resolution.test.js new file mode 100644 index 0000000..0ed5280 --- /dev/null +++ b/src/components/Resolution/Resolution.test.js @@ -0,0 +1,5 @@ +describe('Resolution', () => { + it('should', () => { + expect(true).toBeTruthy(); + }); +});