Ongoing Project — My Shopping Mall
6 min readJul 12, 2021
--
The goal of this short-term project is to model an online shopping mall where one can insert information into a form and place an order. I will be expanding this project as I continue my studies, and updates will be posted below.
Day 1 — HTML, CSS, and JavaScript Foundation
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:wght@600&display=swap" rel="stylesheet">
<title>Project | My Shopping Mall</title>
<style>
*{
font-family: 'EB Garamond', serif;
}
.wrap {
width: 500px;
margin: auto;
display: block;
}
.item-img {
width: 500px;
height: 300px;
background-image: url("https://i.ibb.co/1mk0bp9/IMG-1797.jpg");
background-size: cover;
background-position: center;
margin: auto
display: block;
}
.item-dsc {
margin-top: 20px;
margin-bottom: 20px;
}
.price {
font-size: 20px;
}
.btn-order {
width: 150px;
margin: auto;
margin-top: 30px;
display: block;
}
</style>
<script>
function order(){
alert('Thank you for your order!')
}
</script>
</head>
<body>
<div class="wrap">
<div class="item-img"></div>
<div class="item-dsc">
<h1>Brand New Keyboard <span class="price">Price: $330/KB</span></h1>
<p>A new era of typing brought onto your desk by the culmination of our engineering, design, and craftsmanship.</p>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Name</span>
</div>
<input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="inputGroupSelect01">#</label>
</div>
<select class="custom-select" id="inputGroupSelect01">
<option selected>-- Select Quantity --</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Address</span>
</div>
<input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Phone</span>
</div>
<input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<button type="button" onclick="order()" class="btn btn-primary btn-order">Place Your Order</button>`
</div>
</body>
</html>
- HTML: used in formatting the overall structure.
- CSS: input group bootstraps obtained from https://getbootstrap.com/ for information gathering.
- Javascript: “Thank you for your order!” alert activating upon pressing the “Place Your Order” button.
Day 2— Adding Real-Time Exchange Rates Using Ajax
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:wght@600&display=swap" rel="stylesheet">
<title>Project | My Shopping Mall</title>
<style>
*{
font-family: 'EB Garamond', serif;
}
.wrap {
width: 500px;
margin: auto;
display: block;
}
.item-img {
width: 500px;
height: 300px;
background-image: url("https://i.ibb.co/1mk0bp9/IMG-1797.jpg");
background-size: cover;
background-position: center;
margin: auto
display: block;
}
.item-dsc {
margin-top: 20px;
margin-bottom: 20px;
}
.price {
font-size: 20px;
}
.btn-order {
width: 150px;
margin: auto;
margin-top: 30px;
display: block;
}
.rate {
color: darkslategray;
}
</style>
<script>
$(document).ready(function () {
get_rate();
});
function get_rate(){
$.ajax({
type: "GET",
url: "http://spartacodingclub.shop/sparta_api/rate",
data: {},
success: function (response) {
let now_rate = response['rate'];
$('#now-rate').text(now_rate);
}
})
}
function order(){
alert('Thank you for your order!')
}
</script>
</head>
<body>
<div class="wrap">
<div class="item-img"></div>
<div class="item-dsc">
<h1>Brand New Keyboard <span class="price">Price: $330/KB</span></h1>
<p>A new era of typing brought onto your desk by the culmination of our engineering, design, and craftsmanship.</p>
<p class="rate">Exchange Rate: $1=<span id="now-rate"></span> won</p>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Name</span>
</div>
<input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="inputGroupSelect01">#</label>
</div>
<select class="custom-select" id="inputGroupSelect01">
<option selected>-- Select Quantity --</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Address</span>
</div>
<input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Phone</span>
</div>
<input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<button type="button" onclick="order()" class="btn btn-primary btn-order">Place Your Order</button>
</div>
</body>
</html>
- AJax: OpenAPI Imported to display real-time USD-to-KRW exchange rate:
<script>
$(document).ready(function () {
get_rate();
});
function get_rate(){
$.ajax({
type: "GET",
url: "http://spartacodingclub.shop/sparta_api/rate",
data: {},
success: function (response) {
let now_rate = response['rate'];
$('#now-rate').text(now_rate);
}
})
}
</script>
Day 3 — Linking with a Server for Future Distribution
- HTML File — “index.html”
<!DOCTYPE html>
<html lang="ko">
<head>
<!-- Webpage Title -->
<title>Book Review | Jooyoung Oh</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<!-- JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<!-- Google Font -->
<link href="https://fonts.googleapis.com/css?family=Do+Hyeon&display=swap" rel="stylesheet">
<script type="text/javascript">
$(document).ready(function () {
showReview();
});
function makeReview() {
let title = $('#title').val()
let author = $('#author').val()
let review = $('#bookReview').val()
$.ajax({
type: "POST",
url: "/review",
data: {title_give: title, author_give: author, review_give: review},
success: function (response) {
alert(response["msg"]);
window.location.reload();
}
})
}
function showReview() {
$.ajax({
type: "GET",
url: "/review",
data: {},
success: function (response) {
let reviews = response['all_reviews']
for (let i = 0; i < reviews.length; i++) {
let title = reviews[i]['title']
let author = reviews[i]['author']
let review = reviews[i]['review']
let temp_html = `<tr>
<td>${title}</td>
<td>${author}</td>
<td>${review}</td>
</tr>`
$('#reviews-box').append(temp_html)
}
}
})
}
</script>
<style type="text/css">
* {
font-family: "Do Hyeon", sans-serif;
}
h1,
h5 {
display: inline;
}
.info {
margin-top: 20px;
margin-bottom: 20px;
}
.review {
text-align: center;
}
.reviews {
margin-top: 100px;
}
</style>
</head>
<body>
<div class="container" style="max-width: 600px;">
<img src="https://previews.123rf.com/images/maxxyustas/maxxyustas1511/maxxyustas151100002/47858355-education-concept-books-and-textbooks-on-the-bookshelf-3d.jpg"
class="img-fluid" alt="Responsive image">
<div class="info">
<h1>Leave a Brief Review</h1>
<p>Leaving a short review of the book or any other publications you've read may influence others and make their
lives richer!</p>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">TTL</span>
</div>
<input type="text" class="form-control" id="title">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">ATR</span>
</div>
<input type="text" class="form-control" id="author">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">RW</span>
</div>
<textarea class="form-control" id="bookReview"
cols="30"
rows="5" placeholder="Your review can be as long as 140 words!"></textarea>
</div>
<div class="review">
<button onclick="makeReview()" type="button" class="btn btn-primary">Submit</button>
</div>
</div>
<div class="reviews">
<table class="table">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Author</th>
<th scope="col">Review</th>
</tr>
</thead>
<tbody id="reviews-box">
</tbody>
</table>
</div>
</div>
</body>
</html>
- Server — “app.py”
from flask import Flask, render_template, jsonify, request
app = Flask(__name__)
from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client.dbsparta
## HTML
@app.route('/')
def home():
return render_template('index.html')
## API
@app.route('/review', methods=['POST'])
def write_review():
title_receive = request.form['title_give']
author_receive = request.form['author_give']
review_receive = request.form['review_give']
doc = {
'title':title_receive,
'author':author_receive,
'review':review_receive
}
db.bookreview.insert_one(doc)
return jsonify({'msg': 'Saved!'})
@app.route('/review', methods=['GET'])
def read_reviews():
reviews = list(db.bookreview.find({}, {'_id': False}))
return jsonify({'all_reviews': reviews})
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)