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

Lesson 29 #11

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
5 changes: 5 additions & 0 deletions .firebaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "net-ninja-pwa"
}
}
65 changes: 65 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log*

# Firebase cache
.firebase/

# Firebase config

# Uncomment this if you'd like others to create their own Firebase project.
# For a team working on the same Firebase project(s), it is recommended to leave
# it commented so all members can deploy to the same project(s) in .firebaserc.
# .firebaserc

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
2 changes: 0 additions & 2 deletions README.md

This file was deleted.

10 changes: 10 additions & 0 deletions firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
33 changes: 33 additions & 0 deletions public/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Not Found</title>

<style media="screen">
body { background: #ECEFF1; color: rgba(0,0,0,0.87); font-family: Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 0; }
#message { background: white; max-width: 360px; margin: 100px auto 16px; padding: 32px 24px 16px; border-radius: 3px; }
#message h3 { color: #888; font-weight: normal; font-size: 16px; margin: 16px 0 12px; }
#message h2 { color: #ffa100; font-weight: bold; font-size: 16px; margin: 0 0 8px; }
#message h1 { font-size: 22px; font-weight: 300; color: rgba(0,0,0,0.6); margin: 0 0 16px;}
#message p { line-height: 140%; margin: 16px 0 24px; font-size: 14px; }
#message a { display: block; text-align: center; background: #039be5; text-transform: uppercase; text-decoration: none; color: white; padding: 16px; border-radius: 4px; }
#message, #message a { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }
#load { color: rgba(0,0,0,0.4); text-align: center; font-size: 13px; }
@media (max-width: 600px) {
body, #message { margin-top: 0; background: white; box-shadow: none; }
body { border-top: 16px solid #ffa100; }
}
</style>
</head>
<body>
<div id="message">
<h2>404</h2>
<h1>Page Not Found</h1>
<p>The specified file was not found on this website. Please check the URL for mistakes and try again.</p>
<h3>Why am I seeing this?</h3>
<p>This page was generated by the Firebase Command-Line Interface. To modify it, edit the <code>404.html</code> file in your project's configured <code>public</code> directory.</p>
</div>
</body>
</html>
13 changes: 13 additions & 0 deletions public/css/materialize.min.css

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions public/css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* colours */
:root{
--primary: #FFE9D2;
--secondary: #FFE1C4;
--title: #FF8816;
}

/* layout styles */
nav{
background: var(--primary);
border-bottom: 10px solid var(--secondary);
}
nav a{
text-transform: uppercase;
color: var(--title);
}
nav a span{
font-weight: bold;
}
nav .sidenav-trigger{
margin: 0;
}

/* recipe styles */
.recipes{
margin-top: 20px;
}
.card-panel.recipe{
border-radius: 8px;
padding: 10px;
box-shadow: 0px 1px 3px rgba(90,90,90,0.1);
display: grid;
grid-template-columns: 2fr 6fr 1fr;
grid-template-areas: "image details delete";
position: relative;
}
.recipe img{
grid-area: image;
max-width: 60px;
}
.recipe-details{
grid-area: details;
margin-top: 6px;
}
.recipe-delete{
grid-area: delete;
position: absolute;
bottom: 0px;
right: 0px;
}
.recipe-delete i{
font-size: 18px;
}
.recipe-title{
font-weight: bold;
}
.recipe-ingredients{
font-size: 0.8em;
}

/* form-styles */
.add-btn{
background: var(--title) !important;
}
input{
box-shadow: none !important;
-webkit-box-shadow: none !important;
}
.side-form button{
background: var(--title);
box-shadow: 1px 1px 3px rgba(90,90,90,0.2);
}
form .input-field{
margin-top: 30px;
}
Binary file added public/img/dish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-144x144.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-152x152.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-384x384.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-72x72.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/icons/icon-96x96.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Food Ninja</title>
<!-- materialize icons, css & js -->
<link type="text/css" href="/css/materialize.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link type="text/css" href="/css/styles.css" rel="stylesheet">
<script type="text/javascript" src="/js/materialize.min.js"></script>
<link rel="manifest" href="/manifest.json">
<!-- ios support -->
<link rel="apple-touch-icon" href="/img/icons/icon-96x96.png">
<meta name="apple-mobile-web-app-status-bar" content="#FFE1C4">
<meta name="theme-color" content="#FFE1C4">
</head>
<body class="grey lighten-4">

<!-- top nav -->
<nav class="z-depth-0">
<div class="nav-wrapper container">
<a href="/">Food<span>Ninja</span></a>
<span class="right grey-text text-darken-1">
<i class="material-icons sidenav-trigger" data-target="side-menu">menu</i>
</span>
</div>
</nav>

<!-- side nav -->
<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader">FOODNINJA</a></li>
<li><a href="/" class="waves-effect">Home</a></li>
<li><a href="/pages/about.html" class="waves-effect">About</a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/contact.html" class="waves-effect">
<i class="material-icons">mail_outline</i>Contact</a>
</li>
</ul>

<!-- recipes -->
<div class="recipes container grey-text text-darken-1">

</div>

<div class="center">
<a class="btn-floating btn-small btn-large add-btn sidenav-trigger" data-target="side-form">
<i class="material-icons">add</i>
</a>
</div>

<!-- add recipe side nav -->
<div id="side-form" class="sidenav side-form">
<form class="add-recipe container section">
<h6 >New Recipe</h6>
<div class="divider"></div>
<div class="input-field">
<input placeholder="e.g. Ninja soup" id="title" type="text" class="validate">
<label for="title">Recipe Title</label>
</div>
<div class="input-field">
<input placeholder="e.g. Tofu, mushroom, garlic" id="ingredients" type="text" class="validate">
<label for="ingredients">Ingredients</label>
</div>
<div class="input-field center">
<button class="btn-small">Add</button>
</div>
</form>
</div>


<script src="https://www.gstatic.com/firebasejs/5.11.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.11.0/firebase-firestore.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "AIzaSyDuDGcpHGU-Sx1Hla3wYwZvXbjeKpHqPjA",
authDomain: "net-ninja-pwa.firebaseapp.com",
databaseURL: "https://net-ninja-pwa.firebaseio.com",
projectId: "net-ninja-pwa",
storageBucket: "net-ninja-pwa.appspot.com",
messagingSenderId: "1008745109838"
};
firebase.initializeApp(config);
const db = firebase.firestore();
</script>
<script src="/js/app.js"></script>
<script src="/js/db.js"></script>
<script src="/js/ui.js"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions public/js/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if('serviceWorker' in navigator){
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('service worker registered'))
.catch(err => console.log('service worker not registered', err));
}
50 changes: 50 additions & 0 deletions public/js/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// enable offline data
db.enablePersistence()
.catch(function(err) {
if (err.code == 'failed-precondition') {
// probably multible tabs open at once
console.log('persistance failed');
} else if (err.code == 'unimplemented') {
// lack of browser support for the feature
console.log('persistance not available');
}
});

// real-time listener
db.collection('recipes').onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if(change.type === 'added'){
renderRecipe(change.doc.data(), change.doc.id);
}
if(change.type === 'removed'){
removeRecipe(change.doc.id);
}
});
});

// add new recipe
const form = document.querySelector('form');
form.addEventListener('submit', evt => {
evt.preventDefault();

const recipe = {
name: form.title.value,
ingredients: form.ingredients.value
};

db.collection('recipes').add(recipe)
.catch(err => console.log(err));

form.title.value = '';
form.ingredients.value = '';
});

// remove a recipe
const recipeContainer = document.querySelector('.recipes');
recipeContainer.addEventListener('click', evt => {
if(evt.target.tagName === 'I'){
const id = evt.target.getAttribute('data-id');
//console.log(id);
db.collection('recipes').doc(id).delete();
}
})
6 changes: 6 additions & 0 deletions public/js/materialize.min.js

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions public/js/ui.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const recipes = document.querySelector('.recipes');

document.addEventListener('DOMContentLoaded', function() {
// nav menu
const menus = document.querySelectorAll('.side-menu');
M.Sidenav.init(menus, {edge: 'right'});
// add recipe form
const forms = document.querySelectorAll('.side-form');
M.Sidenav.init(forms, {edge: 'left'});
});

// render recipe data
const renderRecipe = (data, id) => {

const html = `
<div class="card-panel recipe white row" data-id="${id}">
<img src="/img/dish.png" alt="recipe thumb">
<div class="recipe-details">
<div class="recipe-title">${data.name}</div>
<div class="recipe-ingredients">${data.ingredients}</div>
</div>
<div class="recipe-delete">
<i class="material-icons" data-id="${id}">delete_outline</i>
</div>
</div>
`;
recipes.innerHTML += html;

};

// remove recipe
const removeRecipe = (id) => {
const recipe = document.querySelector(`.recipe[data-id=${id}]`);
recipe.remove();
};
Loading