# Web Programming Product Price :::spoiler HTML ```html <!DOCTYPE html> <html> <head> <title>Product Price Change Inquiry</title> <meta charset="utf-8"> <link rel="stylesheet" href="stylesheets/style.css"> </head> <body> <h1>Product Price Change Inquiry</h1> <h2>Enter the price of the product</h2> <form action="/api/submit" method="POST" id="inputForm"> <label for="date">Date:</label> <input required type="date" id="date" name="date"> <br><br> <label for="product">&nbsp&nbsp&nbspName:</label> <input required type="text" id="product" name="product"> <br><br> <label for="price">&nbsp&nbsp&nbsp&nbspPrice:</label> <input required type="number" id="price" name="price"> <br><br> <input type="submit" value="Submit"> </form> <h2>Search</h2> <form action="/api/search" method="POST" id="searchForm"> <label for="search">Keyword:</label> <input type="text" id="keyword" name="keyword"> <input type="submit" value="Search"> </form> <h3>Product Price Change</h3> <table id="priceTable"> </table> <script src="javascripts/script.js"></script> </body> </html> ``` ::: :::spoiler CSS ```css body { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; margin: 0; padding: 0; font-family: Arial, sans-serif; } h1, h2, h3 { margin-top: 20px; margin-bottom: 10px; } form { margin-bottom: 20px; } input[type="submit"] { margin-top: 10px; } #priceTable { width: 80%; margin: 0 auto; border-collapse: collapse; } #priceTable th, #priceTable td { padding: 8px; border: 1px solid black; } ``` ::: Use JS to render the table :::spoiler JavaScript ```javascript document.getElementById("inputForm").addEventListener("submit", async function (event) { event.preventDefault(); const formData = new FormData(event.target); const date = formData.get('date'); const product = formData.get('product'); const price = formData.get('price'); console.log(date, product, price) const res = await fetch('http://localhost:3001/api/submit', { method: 'POST', body: JSON.stringify({ date, product, price }), headers: { 'Content-Type': 'application/json' } }); // const data = await res.json() // var newRow = document.createElement("tr"); // newRow.innerHTML = "<td>" + date + "</td><td>" + product + "</td><td>" + price + "</td>"; // var table = document.getElementById("priceTable"); // table.appendChild(newRow); document.getElementById("date").value = ""; document.getElementById("product").value = ""; document.getElementById("price").value = ""; alert("Submit successfully!"); }); document.getElementById("searchForm").addEventListener("submit", async function (event) { event.preventDefault(); const formData = new FormData(event.target); const searchKeyword = formData.get('keyword'); const res = await fetch('http://localhost:3001/api/search', { method: 'POST', body: JSON.stringify({ keyword: searchKeyword }), headers: { 'Content-Type': 'application/json' } }); const data = await res.json() var table = document.getElementById("priceTable"); table.innerHTML = "<tr><th>日期</th><th>品項</th><th>價格</th></tr>"; for (var i = 0; i < data.length; i++) { var newRow = document.createElement("tr"); newRow.innerHTML = "<td>" + data[i].date + "</td><td>" + data[i].product + "</td><td>" + data[i].price + "</td>"; table.appendChild(newRow); } document.getElementById("keyword").value = ""; }); ``` ::: :::spoiler API ```javascript const express = require('express'); const app = express.Router(); const bodyParser = require('body-parser'); const sqlite = require('sqlite3').verbose(); db = new sqlite.Database("database/database.db", sqlite.OPEN_READWRITE, (err) => { if (err) { console.error(err.message); } console.log('Connected to the database.'); }); sql = `CREATE TABLE IF NOT EXISTS items ( id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT, product TEXT, price REAL )` app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use("/public", express.static(__dirname + '/public')); app.get("/", (req, res) => { res.sendFile(__dirname + "/index.html"); }); app.post('/submit', (req, res) => { const date = req.body.date; const product = req.body.product; const price = req.body.price; db.run('INSERT INTO items (date, product, price) VALUES (?, ?, ?)', [date, product, price], (err) => { if (err) { console.error(err); return res.status(500).send('Internal Server Error'); } }); res.redirect('/'); return res.status(200); }); app.post('/search', (req, res) => { const keyword = req.body.keyword; console.log(keyword); db.all('SELECT * FROM items WHERE product LIKE ?', ['%' + keyword + '%'], (err, rows) => { if (err) { console.error(err); res.status(500).send('Internal Server Error'); } else { res.send(rows); } }); }); module.exports = app; ``` :::