├── documentation ├── Layout.png ├── state.png ├── designdocs │ ├── login.png │ ├── signup.png │ ├── bookinfo.png │ ├── mockupflow.png │ ├── navbaropen.png │ ├── landingpage.png │ ├── userlibrary.png │ ├── userprofile.png │ ├── passwordreset.png │ ├── emailnotification.png │ ├── figmadesignoverview.png │ └── design.md ├── theme.md └── routes.md ├── frontend ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── index.html │ ├── library_icon.svg │ └── library_logo.svg ├── src │ ├── fonts │ │ ├── Quicksand.woff2 │ │ ├── Raleway.woff2 │ │ ├── Raleway-Italic.woff2 │ │ ├── fontWeight.scss │ │ └── font-face.scss │ ├── stylesUtils │ │ ├── sizes.scss │ │ ├── noBulletList.scss │ │ ├── stack.scss │ │ ├── userText.scss │ │ └── mixins │ │ │ └── mediaqueries.scss │ ├── components │ │ ├── Footer.jsx │ │ ├── BookCard.jsx │ │ ├── Navigation.jsx │ │ ├── Header.jsx │ │ ├── navigation.scss │ │ └── header.scss │ ├── SERVER.js │ ├── pages │ │ ├── About.jsx │ │ ├── Profile.jsx │ │ ├── Login.jsx │ │ ├── Layout.jsx │ │ ├── Book.jsx │ │ ├── login.scss │ │ ├── Home.jsx │ │ └── home.scss │ ├── setupTests.js │ ├── App.jsx │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── App.scss │ ├── serviceWorker.js │ └── library_logo.svg ├── index.html ├── client.js ├── package.json └── README.md ├── .gitignore ├── .prettierrc.json ├── apidoc.json ├── learning └── datastructures │ ├── ReadMe.txt │ ├── index.html │ ├── data.js │ ├── test.js │ ├── datastructures.js │ └── expected.js ├── db ├── schemas.js └── mongoose.js ├── mongo-replicaset └── docker-compose.yml ├── server.js ├── package.json ├── test ├── books.test.js └── users.test.js ├── LICENSE ├── routers ├── users.js └── books.js └── README.md /documentation/Layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/Layout.png -------------------------------------------------------------------------------- /documentation/state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/state.png -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .vscode 3 | node_modules 4 | frontend/node_modules 5 | .DS_Store 6 | out 7 | mongo-replicaset/data -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/frontend/public/logo192.png -------------------------------------------------------------------------------- /frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/frontend/public/logo512.png -------------------------------------------------------------------------------- /documentation/designdocs/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/login.png -------------------------------------------------------------------------------- /frontend/src/fonts/Quicksand.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/frontend/src/fonts/Quicksand.woff2 -------------------------------------------------------------------------------- /frontend/src/fonts/Raleway.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/frontend/src/fonts/Raleway.woff2 -------------------------------------------------------------------------------- /documentation/designdocs/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/signup.png -------------------------------------------------------------------------------- /documentation/designdocs/bookinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/bookinfo.png -------------------------------------------------------------------------------- /documentation/designdocs/mockupflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/mockupflow.png -------------------------------------------------------------------------------- /documentation/designdocs/navbaropen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/navbaropen.png -------------------------------------------------------------------------------- /frontend/src/fonts/Raleway-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/frontend/src/fonts/Raleway-Italic.woff2 -------------------------------------------------------------------------------- /documentation/designdocs/landingpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/landingpage.png -------------------------------------------------------------------------------- /documentation/designdocs/userlibrary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/userlibrary.png -------------------------------------------------------------------------------- /documentation/designdocs/userprofile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/userprofile.png -------------------------------------------------------------------------------- /frontend/src/stylesUtils/sizes.scss: -------------------------------------------------------------------------------- 1 | $sm: 31; 2 | $md: 48; 3 | $xl: 67; 4 | $xxl: 110; 5 | $media1920: 120; 6 | 7 | $navigationSwitch: 85; 8 | -------------------------------------------------------------------------------- /documentation/designdocs/passwordreset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/passwordreset.png -------------------------------------------------------------------------------- /documentation/designdocs/emailnotification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/emailnotification.png -------------------------------------------------------------------------------- /documentation/designdocs/figmadesignoverview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/threedevs/3dev-fullstack/HEAD/documentation/designdocs/figmadesignoverview.png -------------------------------------------------------------------------------- /frontend/src/components/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function Footer() { 4 | // TODO add content 5 | 6 | return
; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/SERVER.js: -------------------------------------------------------------------------------- 1 | const databaseURL = 'http://localhost:1337'; 2 | 3 | export const allBooksURL = `${databaseURL}/api/books`; 4 | export const bookURL = `${databaseURL}/api/books/`; 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "singleQuote": true, 5 | "printWidth": 150, 6 | "jsxBracketSameLine": true, 7 | "useTabs": true 8 | } -------------------------------------------------------------------------------- /frontend/src/stylesUtils/noBulletList.scss: -------------------------------------------------------------------------------- 1 | %NoBulletList { 2 | list-style-type: none; 3 | 4 | > li::before { 5 | display: block; 6 | height: 0; 7 | 8 | content: '\200B'; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/fonts/fontWeight.scss: -------------------------------------------------------------------------------- 1 | $thin: 100; 2 | $extra-light: 200; 3 | $light: 300; 4 | $regular: 400; 5 | $medium: 500; 6 | $semi-bold: 600; 7 | $bold: 700; 8 | $extra-bold: 800; 9 | $black: 900; 10 | -------------------------------------------------------------------------------- /apidoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3dev-fullstack", 3 | "version": "0.1.0", 4 | "description": "A practice full stack application for 3devs", 5 | "title": "Custom apiDoc browser title", 6 | "url": "https://localhost:1337" 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/pages/About.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function About() { 4 | return ( 5 | <> 6 |

About page

7 |

this is the about page

8 | 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /learning/datastructures/ReadMe.txt: -------------------------------------------------------------------------------- 1 | - you can just usa a liveserver with index.html 2 | - solve the exercises in datastructure.js 3 | - data.js is holding the data you need for the exercises 4 | - the tests are run on reload or clicking the button -------------------------------------------------------------------------------- /frontend/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /frontend/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.scss'; 3 | import Layout from './pages/Layout'; 4 | import { BrowserRouter as Router } from 'react-router-dom'; 5 | 6 | function App() { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /frontend/src/pages/Profile.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useParams } from 'react-router-dom'; 3 | 4 | export default function Profile() { 5 | let { id } = useParams(); 6 | 7 | return ( 8 | <> 9 |

Profile

10 |

Change your profile

11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/stylesUtils/stack.scss: -------------------------------------------------------------------------------- 1 | %Stack { 2 | --stackMargin: 1.2em; 3 | 4 | > * { 5 | margin-top: 0; 6 | margin-bottom: 0; 7 | 8 | + * { 9 | margin-top: var(--stackMargin); 10 | } 11 | } 12 | 13 | &--recursive { 14 | --stackMargin: 1.2em; 15 | 16 | * { 17 | margin-top: 0; 18 | margin-bottom: 0; 19 | 20 | + * { 21 | margin-top: var(--stackMargin); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /db/schemas.js: -------------------------------------------------------------------------------- 1 | const user = { 2 | username: { type: String, required: true, unique: true }, 3 | password: { type: String, required: true }, 4 | }; 5 | 6 | const book = { 7 | title: { type: String }, 8 | author: { type: String }, 9 | genre: { type: String }, 10 | yearPublished: { type: String }, 11 | dateAdded: { type: Date, default: Date.now() }, 12 | }; 13 | 14 | module.exports = { 15 | book, 16 | user, 17 | }; 18 | -------------------------------------------------------------------------------- /mongo-replicaset/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | docker-mongo-local-replicaset: 4 | ports: 5 | - '27001:27001' 6 | - '27002:27002' 7 | - '27003:27003' 8 | container_name: mongo 9 | volumes: 10 | - ./data/mongodb:/data 11 | environment: 12 | - REPLICA_SET_NAME=mongo-rs 13 | restart: always 14 | image: flqw/docker-mongo-local-replicaset 15 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Snippets 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /documentation/theme.md: -------------------------------------------------------------------------------- 1 | colors 2 | 3 | 5BA788 primary 4 | 323031 navigation background 5 | 3D3B3C content background 6 | B75252 cancel buttons 7 | FFFFFF fonts 8 | 9 | 10 | fonts 11 | 12 | "Quicksand" for titles, "Raleway" for paragraphs/texts 13 | https://fonts.google.com/specimen/Quicksand?vfonly=true#glyphs 14 | https://fonts.google.com/specimen/Raleway?vfonly=true#glyphs 15 | 16 | 17 | logos: 18 | 19 | main logo: 20 | /frontend/public/library log.svg 21 | 22 | favico: 23 | /frontend/public/library icon.svg -------------------------------------------------------------------------------- /frontend/src/stylesUtils/userText.scss: -------------------------------------------------------------------------------- 1 | @import 'stack'; 2 | @import '../fonts/fontWeight'; 3 | 4 | %UserText { 5 | display: flex; 6 | flex-direction: column; 7 | 8 | @extend %Stack; 9 | 10 | h3 { 11 | font: $bold 1.75em/1.2 'Raleway', sans-serif; 12 | } 13 | 14 | h4 { 15 | font: $bold 1.3em/1.2 'Raleway', sans-serif; 16 | } 17 | 18 | p, 19 | li { 20 | font: $regular 1em/1.75 'Raleway', sans-serif; 21 | } 22 | 23 | a { 24 | text-decoration: none; 25 | color: currentColor; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /frontend/client.js: -------------------------------------------------------------------------------- 1 | window.onload = () => { 2 | //make a POST request 3 | fetch('http://localhost:3000', { 4 | method: 'POST', 5 | headers: { 'Content-Type': 'application/json' }, 6 | body: JSON.stringify({ username: 'testuser2', password: 'supersafepw', password2: 'supersafepw' }), 7 | }) 8 | .then((res) => { 9 | console.log(res); 10 | return res.status === 200 ? res.json() : Promise.reject(); 11 | }) 12 | .then((data) => { 13 | console.log(data); 14 | }) 15 | .catch((err) => { 16 | console.error(err); 17 | }) 18 | .finally(() => { 19 | console.log('done'); 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /frontend/src/fonts/font-face.scss: -------------------------------------------------------------------------------- 1 | @import 'fontWeight'; 2 | 3 | @font-face { 4 | font-family: 'Quicksand'; 5 | src: url('Quicksand.woff2') format('woff2'); 6 | font-style: normal; 7 | font-weight: $thin $black; 8 | font-display: swap; 9 | } 10 | 11 | @font-face { 12 | font-family: 'Raleway'; 13 | font-style: normal; 14 | font-weight: $thin $black; 15 | src: url('Raleway.woff2') format('woff2'); 16 | font-display: swap; 17 | } 18 | 19 | @font-face { 20 | font-family: 'Raleway Italic'; 21 | font-style: italic; 22 | font-weight: $thin $black; 23 | src: url('Raleway-Italic.woff2') format('woff2'); 24 | font-display: swap; 25 | } 26 | -------------------------------------------------------------------------------- /learning/datastructures/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Snippets 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |

20 |

21 |

22 | 23 | 24 | -------------------------------------------------------------------------------- /frontend/src/components/BookCard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | export default function BookCard({ book }) { 4 | return ( 5 |
6 |

{book.title}

7 |
8 |
author :
9 |
{book.author}
10 |
Published in :
11 |
{book.yearPublished}
12 |
13 | book cover 14 | 15 | 16 | See more 17 | 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/pages/Login.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './login.scss'; 3 | 4 | export default function Login() { 5 | return ( 6 |
7 |

Login Form

8 |



9 |



10 |



11 |



12 | Forgot your password



13 | 14 | 15 |
16 | ); 17 | } -------------------------------------------------------------------------------- /frontend/src/stylesUtils/mixins/mediaqueries.scss: -------------------------------------------------------------------------------- 1 | @import '../sizes'; 2 | 3 | @mixin mediaSm { 4 | @media screen and (min-width: #{$sm}em) { 5 | @content; 6 | } 7 | } 8 | 9 | @mixin mediaMd { 10 | @media screen and (min-width: #{$md}em) { 11 | @content; 12 | } 13 | } 14 | 15 | @mixin mediaXl { 16 | @media screen and (min-width: #{$xl}em) { 17 | @content; 18 | } 19 | } 20 | 21 | @mixin mediaXxl { 22 | @media screen and (min-width: #{$xxl}em) { 23 | @content; 24 | } 25 | } 26 | 27 | @mixin media1920 { 28 | @media screen and (min-width: #{$media1920}em) { 29 | @content; 30 | } 31 | } 32 | 33 | @mixin navigationSwitch { 34 | @media screen and (min-width: #{$navigationSwitch}em) { 35 | @content; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /documentation/routes.md: -------------------------------------------------------------------------------- 1 | - get all books, GET, /api/books 2 | - get one book by id, GET, /api/books/:id 3 | - search multiple by title, GET, /api/books/s/:search 4 | - create a new book, POST, /api/books 5 | - delete a book, DELETE, /api/books/:id 6 | - updates a book, PATCH, /api/books/:id 7 | - get all books of same genre, GET, /api/books/:genre 8 | 9 | - get user by id, GET, /api/users/:id 10 | - create a new user, POST, /api/auth/register 11 | - user login, POST, /api/auth/login 12 | - deletes a user, DELETE, /api/profile/:id 13 | - updates a user, PATCH, /api/profile/:id 14 | -------------------------------------------------------------------------------- /frontend/src/pages/Layout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from '../components/Header'; 3 | import Footer from '../components/Footer'; 4 | import Home from './Home'; 5 | import { Switch, Route } from 'react-router-dom'; 6 | import About from './About'; 7 | import Login from './Login'; 8 | import Book from './Book'; 9 | import Profile from './Profile'; 10 | 11 | export default function Layout() { 12 | return ( 13 | <> 14 |
15 |
16 | 17 | } /> 18 | } /> 19 | } /> 20 | } /> 21 | } /> 22 | 23 |
24 |