Parts Detail
This supports a software dev. class for businesspeople that you can find here: https://www.alexandercowan.com/making-html-manageable And a case you can find here: https://www.alexandercowan.com/making-html-manageable
by Alex Cowan
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine.min.js"></script>
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/8.2.5/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.5/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.5/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: "AIzaSyCOPgDQ4PAwNtOxZQtkkRpy0LV37VVEzJg",
authDomain: "hinh-78995.firebaseapp.com",
projectId: "hinh-78995",
storageBucket: "hinh-78995.appspot.com",
messagingSenderId: "389014950808",
appId: "1:389014950808:web:5599635662f42697b091ed",
measurementId: "G-XL6BSRZLQE"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div class="top-bar">
<ul class="nav-list">
<li><a href="#">Home</a></li>
<li><a href="#">Parts</a></li>
<li><a href="#">Search</a></li>
<li><a href="#">Help</a></li>
</ul>
<div id="search-box">
<input type="text" name="parts-search" placeholder="Mfg., Model, or Part Number" size=30>
</div>
</div>
<div id="part-info">
<img id='part-img' alt="PCB board" style="width:300px;">
<h2 id='part-title'></h2> <button type="button" id='order-btn'>Add to Cart</button><button type="button" id='checkout-btn'>Checkout</button>
<h3 id='availability'>...
CSS
.top-bar,
#search-box,
.nav-list li,
.nav-list a {
background-color: #002D45;
font-family: Proxima Nova, helvetica neue, helvetica, sans-serif;
font-weight: bold;
font-size: 110%;
color: #ffffff;
}
.top-bar {
color: #FFFFFF;
height: 40px;
margin: 0px;
padding: 10px;
display: flex;
align-items: center;
}
.nav-list {
list-style-type: none;
padding: 0;
display: inline;
}
.nav-list li {
float: left;
}
.nav-list a {
display: inline;
padding: 8px;
text-decoration: none;
}
#search-box {
margin-left: auto;
margin-right: 0;
padding: 10px;
}
/* PH */
p {
font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
/* line-height: 1; */
overflow: scroll;
}
#part-info {
margin: 15px;
padding: 0px 5px;
width: 100%;
}
#part-info img {
float: left;
padding: 5px;
}
#part-info h2 {
display: inline;
}
/* PH */
button {
display: inline;
font-size: 20px;
margin: 0px 5px 5px 0px;
}
#part-info h3 {
margin: 0px;
}
#review-form h3 {
clear: both;
margin: 20px 0px 5px 0px;
}
/* PH */
.stars {
width: 70px;
}
input.star {
display: none;
}
label.star {
float: right;
padding: 0px;
font-size: 15px;
color: #444;
}
input.star:checked~label.star:before {
content: '\f005';
color: #000;
transition: all .25s;
}
label.star:before {
content: '\f006';
font-family: FontAwesome;
}
#review-text {
clear: both;
width: 100%;
}
/* PH
#review-form {
float: right;
display: relative;
}
*/
/* PH
#part-reviews {
float: left;
}
*/
.indReview {
border-style: solid;
}
.fa-star {
opacity: .5;
}
.checked {
color: black;
opacity: 1;
}
#review {
display: none;
}
#add-review {
display: none;
}
/* PH */
#user-reviews {
clear: both;
/*
display: grid;
float: left;
*/
}
/* PH */
#user-reviews h2 {
margin: 5px 5px 5px 0px;
}
JavaScript
var db = firebase.firestore();
//get just the part number. Splits on '#' and takes second element of the array
var partnum = localStorage.getItem('part-index').split('#', 2)[1];
//Define the file path for where the part data lives
part_file_path = '/parts/' + partnum
//Go get the part data from the applicable document in Firestore
doc = db.doc(part_file_path).get().then((doc) => {
//draw the part information on the page
var part = doc.data()
var id = doc.id
$('#partnum').text('Part #: ' + id)
$('#availability').text('Availability: ' + part.availability)
$('#orders').text('Orders (90 day): ' + part.orders)
//Make sure prices show two digits and have a dollar sign. We'll have to ensure that these are floats in the rules when new parts are added
$('#price').text('Price: $' + part.Price.toFixed(2))
$('#part-title').text(part.Manufacturer + ' ' + part.Model + ' ' + part.Type)
$('#part-img').attr('src', 'https://' + part.imageURL)
//add the stars and num ratings
review_file_path = '/parts/' + partnum + '/reviews'
//initialize these parameters for the next function
var total_rating = 0
var numReviews = 0
// loop through each review document associated with the part and to get total rating and number of reviews
db.collection(review_file_path).get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
total_rating += doc.data().rating
numReviews += 1
//console.log(numReviews)
})
}).then(function() {
var avgRating = total_rating / numReviews;
roundedRating = Math.floor(avgRating);
//update the star icons to match the average rating
for (var i = 1; i <= 5; i++) {
$starSpan = $('<span class="fa fa-star" />');
if (i <= roundedRating) {
$starSpan.addClass('checked')
}
$('#part-info').append($starSpan);
}
//add number of reviews
$('#numReviews').text(numReviews + ' Reviews');
})
// Check if someone is logged in and show add-review button if they...