init
This commit is contained in:
105
app.py
Normal file
105
app.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from flask import Flask, render_template, request, redirect, session, jsonify
|
||||
import sqlite3
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = "supersecretkey"
|
||||
|
||||
DB = "database.db"
|
||||
|
||||
# ---------------- DATABASE ----------------
|
||||
def get_db():
|
||||
conn = sqlite3.connect(DB)
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
def init_db():
|
||||
conn = get_db()
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS toner (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
quantity INTEGER NOT NULL
|
||||
)
|
||||
''')
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT,
|
||||
password TEXT
|
||||
)
|
||||
''')
|
||||
conn.commit()
|
||||
|
||||
# ---------------- ROUTES ----------------
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
|
||||
@app.route("/api/toner")
|
||||
def get_toner():
|
||||
conn = get_db()
|
||||
toner = conn.execute("SELECT * FROM toner").fetchall()
|
||||
return jsonify([dict(row) for row in toner])
|
||||
|
||||
@app.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
if request.method == "POST":
|
||||
user = request.form["username"]
|
||||
pw = request.form["password"]
|
||||
|
||||
conn = get_db()
|
||||
result = conn.execute(
|
||||
"SELECT * FROM users WHERE username=? AND password=?",
|
||||
(user, pw)
|
||||
).fetchone()
|
||||
|
||||
if result:
|
||||
session["user"] = user
|
||||
return redirect("/admin")
|
||||
|
||||
return render_template("login.html")
|
||||
|
||||
@app.route("/admin")
|
||||
def admin():
|
||||
if "user" not in session:
|
||||
return redirect("/login")
|
||||
return render_template("admin.html")
|
||||
|
||||
@app.route("/api/add", methods=["POST"])
|
||||
def add_item():
|
||||
if "user" not in session:
|
||||
return "Unauthorized", 401
|
||||
|
||||
data = request.json
|
||||
conn = get_db()
|
||||
conn.execute(
|
||||
"INSERT INTO toner (name, quantity) VALUES (?, ?)",
|
||||
(data["name"], data["quantity"])
|
||||
)
|
||||
conn.commit()
|
||||
return "OK"
|
||||
|
||||
@app.route("/api/update", methods=["POST"])
|
||||
def update_item():
|
||||
if "user" not in session:
|
||||
return "Unauthorized", 401
|
||||
|
||||
data = request.json
|
||||
conn = get_db()
|
||||
conn.execute(
|
||||
"UPDATE toner SET quantity=? WHERE id=?",
|
||||
(data["quantity"], data["id"])
|
||||
)
|
||||
conn.commit()
|
||||
return "OK"
|
||||
|
||||
@app.route("/logout")
|
||||
def logout():
|
||||
session.clear()
|
||||
return redirect("/")
|
||||
|
||||
# ---------------- RUN ----------------
|
||||
if __name__ == "__main__":
|
||||
init_db()
|
||||
app.run(debug=True)
|
||||
BIN
database.db
Normal file
BIN
database.db
Normal file
Binary file not shown.
50
static/script.js
Normal file
50
static/script.js
Normal file
@@ -0,0 +1,50 @@
|
||||
async function loadInventory() {
|
||||
const res = await fetch('/api/toner');
|
||||
const data = await res.json();
|
||||
|
||||
const table = document.getElementById("inventory") || document.getElementById("adminInventory");
|
||||
table.innerHTML = "";
|
||||
|
||||
data.forEach(item => {
|
||||
const row = document.createElement("tr");
|
||||
|
||||
row.innerHTML = `
|
||||
<td>${item.name}</td>
|
||||
<td>
|
||||
<input value="${item.quantity}" id="qty-${item.id}">
|
||||
</td>
|
||||
<td>
|
||||
<button onclick="updateItem(${item.id})">Save</button>
|
||||
</td>
|
||||
`;
|
||||
|
||||
table.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
async function addItem() {
|
||||
const name = document.getElementById("name").value;
|
||||
const qty = document.getElementById("qty").value;
|
||||
|
||||
await fetch("/api/add", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({name: name, quantity: qty})
|
||||
});
|
||||
|
||||
loadInventory();
|
||||
}
|
||||
|
||||
async function updateItem(id) {
|
||||
const qty = document.getElementById(`qty-${id}`).value;
|
||||
|
||||
await fetch("/api/update", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({id: id, quantity: qty})
|
||||
});
|
||||
|
||||
loadInventory();
|
||||
}
|
||||
|
||||
window.onload = loadInventory;
|
||||
22
templates/admin.html
Normal file
22
templates/admin.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<h1>Admin Panel</h1>
|
||||
|
||||
<h3>Add Toner</h3>
|
||||
<input id="name" placeholder="Toner Name">
|
||||
<input id="qty" type="number" placeholder="Quantity">
|
||||
<button onclick="addItem()">Add</button>
|
||||
|
||||
<h3>Update Inventory</h3>
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Quantity</th>
|
||||
<th>Update</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="adminInventory"></tbody>
|
||||
</table>
|
||||
|
||||
<a href="/logout">Logout</a>
|
||||
|
||||
<script src="/static/script.js"></script>
|
||||
20
templates/index.html
Normal file
20
templates/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Toner Inventory</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Toner Inventory</h1>
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Quantity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="inventory"></tbody>
|
||||
</table>
|
||||
|
||||
<script src="/static/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
6
templates/login.html
Normal file
6
templates/login.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<form method="POST">
|
||||
<h2>Admin Login</h2>
|
||||
<input name="username" placeholder="Username" required>
|
||||
<input name="password" type="password" placeholder="Password" required>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
Reference in New Issue
Block a user