#\controllers\customer.py import config, re, json from bottle import template, route, request, redirect from models import customerdb @route('/customer') def displayCustomer(): config.kargs['customers'] = json.dumps(customerdb.select()) return template('customer', data=config.kargs) @route('/custform') def getCustomerForm(): return template('custform', data=config.kargs) @route('/custform/edit/<id>') def editCustomerForm(id): config.kargs['rowedit'] = customerdb.edit(id) config.kargs['id'] = id return template('custform', data=config.kargs) @route("/customer/delete/<id>") def deleteCustomer(id): config.kargs['id'] = id customerdb.delete(id) redirect('/customer') @route("/customer/<key>/<index>") def sortCustomer(key, index): config.kargs['customers'] = json.dumps(customerdb.sort(key)) config.kargs['sortIndex'] = index return template('customer', data=config.kargs) @route("/search/customer/<query>") def searchCustomer(query): config.kargs['customers'] = json.dumps(customerdb.search(query)) return template('customer', data=config.kargs) @route('/customer', method="POST") def getFormData(): name = request.forms.get("fname") phone = request.forms.get("fphone") if not re.match(r"^(\+\d{1,2}\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$", phone): config.kargs['message'] = "You need to enter a right phone number." return template('custform', data=config.kargs) else: if 'rowedit' in config.kargs: customerdb.update(name, phone, config.kargs['id']) del config.kargs['rowedit'] redirect('/customer') else: customerdb.insert(name, phone) redirect('/customer')
#\models\customerdb.py import sqlite3 def insert(*customer): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() sql ='''CREATE TABLE IF NOT EXISTS CUSTOMER( NAME TEXT, PHONE TEXT ) ''' cursor.execute(sql) cursor.execute("INSERT INTO CUSTOMER VALUES (?, ?)", customer) conn.commit() conn.close() def select(): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() sql ='''CREATE TABLE IF NOT EXISTS CUSTOMER( NAME TEXT, PHONE TEXT ) ''' cursor.execute(sql) cursor.execute("SELECT ROWID, * from CUSTOMER") customers = cursor.fetchall() conn.commit() conn.close() return customers def edit(id): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() cursor.execute("SELECT ROWID, * from CUSTOMER WHERE ROWID = " + id) customer = cursor.fetchone() conn.commit() conn.close() return customer def update(*args): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() sql = "UPDATE CUSTOMER SET NAME=?, PHONE=? WHERE ROWID=?" cursor.execute(sql, args) conn.commit() conn.close() def delete(id): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() cursor.execute("DELETE FROM CUSTOMER WHERE ROWID=?", (id,)) conn.commit() conn.close() def sort(key): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() cursor.execute("SELECT ROWID, * from CUSTOMER ORDER BY " + key) customers = cursor.fetchall() conn.commit() conn.close() return customers def search(query): conn = sqlite3.connect('sqlite.db') cursor = conn.cursor() sql = "SELECT ROWID, * from CUSTOMER WHERE NAME LIKE '%"+query+"%'" sql += " OR PHONE LIKE '%"+query+"%'" cursor.execute(sql) customers = cursor.fetchall() conn.commit() conn.close() return customers
<!--\views\customer.tpl--> %include("./partials/header.tpl") <div class="main" id="main"> <div class="content" id="content"> <div class="top-widget"> <span>CUSTOMERS</span><input onclick="location.href='/custform'" type="button" value="Add Customer" /> </div> <div class="bottom-widget"> <span> <select id="custkey"> <option value="Name" >Name</option> <option value="Phone" >Phone</option> </select> <input onclick="bicycle.sortCustomer()" type="button" value="Sort" /> </span> <span class="search"> <input id="query" type="text" /><input onclick="bicycle.searchCustomer()" type="button" value="Search" /> </span> </div><!--bottom-widget--> <div id="table"></div> <script>bicycle.showCustomer({{!data['customers']}}, {{!data['sortIndex']}})</script> </div><!--content--> </div><!--main--> %include("./partials/footer")
//\public\js\main.js class Bicycle{ setActiveMenu(){ const pathName = window.location.pathname; $("#menu a").each(function(){ if($(this).attr("href") === pathName) $(this).parent().addClass( "active" ); }); } bicycleForm(formId){ var brand = document.forms[formId]['fbrand'].value; var country = document.forms[formId]['fcountry'].value; var year = document.forms[formId]['fyear'].value; var amount = document.forms[formId]['famount'].value; var price = document.forms[formId]['fprice'].value; if((brand == "") || (country == "") || (year == "") || (amount == "") || (price == "")){ return false; }else{ var numberRGEX = /^(?:[1-9]\d*|0)?(?:\.\d+)?$/; var intRGEX = /^[0-9]+$/; var numberResult = numberRGEX.test(price); var intResult = (intRGEX.test(year) && intRGEX.test(amount)); if(!numberResult){ alert('Please enter a number for price.'); return false; } if(!intResult){ alert('Please enter a whole number for year and amount.'); return false; } } } showBicycle(bicycles,sortIndex){ var html = ''; if(bicycles.length > 0){ html += "<table>"; html += "<tr>"; for(var k in {id:0, brand:0, country:0, year:0, amount:0, price:0}){ html += "<th>" + k.toUpperCase() + "</th>"; } html += "<th>OPTION</th>"; html += "</tr>"; for(var i=0; i<bicycles.length; i++){ html += "<tr>"; html += "<td>" + (i+1) + "</td>"; for(var j in bicycles[i]){ if(j > 0) html += "<td>" + bicycles[i][j] + "</td>"; } html += `<td class="option"><a href="/bikeform/edit/${bicycles[i][0]}" class="edit">Edit</a>|<a href="/bikeform/delete/${bicycles[i][0]}" class="delete" >Delete</a></td>`; html += "</tr>"; } html += "</table>"; } document.getElementById("table").innerHTML = html; document.getElementById("bikekey").selectedIndex = sortIndex; } sortBicycle(){ var element = document.getElementById("bikekey"); var sortIndex = element.selectedIndex; var key = element.options[sortIndex].value; window.location.href = "/bicycle/" + key + "/" + sortIndex; } searchBicycle(){ var query = $("#query").val(); location.href= "/search/bicycle/" + query; } customerForm(formId){ var name = document.forms[formId]['fname'].value; var phone = document.forms[formId]['fphone'].value; if((name == "") || (phone == "")){ alert("Please fill this form with your name and phone number!"); return false; }else{ var phoneRegex = /^(\+\d{1,2}\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/; var numberResult = phoneRegex.test(phone); if(!numberResult){ alert("Please fill this form with the right phone number."); return false; } } } showCustomer(customers, sortIndex){ var html = ''; if(customers.length > 0){ html += "<table>"; html += "<tr>"; for(var k in {id:0, name:0, phone:0}){ html += "<th>" + k.toUpperCase() + "</th>"; } html += "<th>OPTION</th>"; html += "</tr>"; for(var i=0; i<customers.length; i++){ html += "<tr>"; html += "<td>" + (i+1) + "</td>"; for(var j in customers[i]){ if(j > 0) html += "<td>" + customers[i][j] + "</td>"; } html += `<td class="option"><a href="/custform/edit/${customers[i][0]}" class="edit">Edit</a>|<a href="/customer/delete/${customers[i][0]}" class="delete" >Delete</a></td>`; html += "</tr>"; } html += "</table>"; } document.getElementById("table").innerHTML = html; document.getElementById("custkey").selectedIndex = sortIndex; } sortCustomer(){ var element = document.getElementById("custkey"); var sortIndex = element.selectedIndex; var key = element.options[sortIndex].value; window.location.href = "/customer/" + key + "/" + sortIndex; } searchCustomer(){ var query = $("#query").val(); location.href= "/search/customer/" + query; } }//end of class var bicycle = new Bicycle();
GitHub: https://github.com/Sokhavuth/Rental-Bicycle-App
Heroku: https://khmerweb-rba.herokuapp.com/