zkt25/z1/app/app.py

234 lines
8.6 KiB
Python

from flask import Flask, request, render_template_string, redirect, url_for
import os
import psycopg2
app = Flask(__name__)
# Retrieve database connection settings from environment variables.
db_host = os.environ.get("DB_HOST", "postgres_db")
db_name = os.environ.get("POSTGRES_DB", "sampledb")
db_user = os.environ.get("POSTGRES_USER", "user")
db_password = os.environ.get("POSTGRES_PASSWORD", "password")
# Function to get the database connection.
def get_db_connection():
conn = psycopg2.connect(
host=db_host,
database=db_name,
user=db_user,
password=db_password
)
return conn
# Initialize the database and create the shopping list table if it doesn't exist.
def init_db():
conn = get_db_connection()
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS shopping_list (
id SERIAL PRIMARY KEY,
item VARCHAR(255) NOT NULL UNIQUE,
category VARCHAR(100) NOT NULL
);
""")
conn.commit()
cur.close()
conn.close()
# Function to categorize items intelligently.
def categorize_item(item_name):
item_name = item_name.lower()
categories = {
'fruits': ['apple', 'banana', 'orange', 'grape', 'pear'],
'vegetables': ['carrot', 'broccoli', 'lettuce', 'spinach'],
'dairy': ['milk', 'cheese', 'yogurt', 'butter'],
'beverages': ['coffee', 'tea', 'water', 'juice'],
'snacks': ['chips', 'cookies', 'chocolate', 'nuts'],
'others': []
}
# Check each category and see if the item belongs.
for category, items in categories.items():
if any(item in item_name for item in items):
return category
# Default category if no match is found
return 'others'
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
item = request.form.get("item")
if item:
# Check if item already exists in the database to avoid duplicates.
conn = get_db_connection()
cur = conn.cursor()
cur.execute("SELECT * FROM shopping_list WHERE item = %s", (item,))
existing_item = cur.fetchone()
if not existing_item: # Only insert if item doesn't exist already.
category = categorize_item(item)
cur.execute("INSERT INTO shopping_list (item, category) VALUES (%s, %s)", (item, category))
conn.commit()
cur.close()
conn.close()
conn = get_db_connection()
cur = conn.cursor()
cur.execute("SELECT * FROM shopping_list;")
items = cur.fetchall()
cur.close()
conn.close()
# Group items by category for display purposes.
categorized_items = {}
for item in items:
if item[2] not in categorized_items:
categorized_items[item[2]] = []
categorized_items[item[2]].append(item[1])
return render_template_string("""
<html>
<head>
<title>Smart Shopping List</title>
<style>
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #ff6e7f, #bfe9ff);
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: #fff;
}
h1 {
font-size: 3em;
text-align: center;
margin-bottom: 30px;
text-transform: uppercase;
letter-spacing: 5px;
}
.container {
width: 100%;
max-width: 800px;
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
padding: 30px;
box-shadow: 0 4px 40px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(10px);
}
form {
display: flex;
justify-content: center;
margin-bottom: 40px;
}
input[type="text"] {
padding: 15px;
width: 70%;
border: none;
border-radius: 10px;
font-size: 1.2em;
outline: none;
margin-right: 15px;
background: #fff;
color: #333;
transition: all 0.3s ease-in-out;
}
input[type="text"]:focus {
transform: scale(1.05);
border: 2px solid #ff6e7f;
}
button {
padding: 15px 30px;
background-color: #ff6e7f;
border: none;
border-radius: 10px;
color: #fff;
font-size: 1.2em;
cursor: pointer;
transition: all 0.3s ease-in-out;
}
button:hover {
background-color: #ff3b4d;
transform: scale(1.05);
}
ul {
list-style-type: none;
padding: 0;
display: flex;
flex-direction: column;
gap: 15px;
}
li {
background: #ffffff;
color: #333;
padding: 15px;
font-size: 1.5em;
border-radius: 10px;
transition: all 0.3s ease;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: space-between;
}
li:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.category {
font-size: 1.8em;
margin-bottom: 20px;
text-align: center;
}
.remove {
background-color: #ff3b4d;
padding: 8px;
border-radius: 5px;
color: white;
cursor: pointer;
}
.remove:hover {
background-color: #ff1f2d;
}
</style>
</head>
<body>
<div class="container">
<h1>Smart Shopping List</h1>
<form method="post">
<input type="text" name="item" placeholder="What do you need to buy?" required>
<button type="submit">Add Item</button>
</form>
{% for category, items in categorized_items.items() %}
<div class="category">{{ category|capitalize }}</div>
<ul>
{% for item in items %}
<li>
{{ item }}
<a href="{{ url_for('remove_item', item_name=item) }}" class="remove">Remove</a>
</li>
{% endfor %}
</ul>
{% endfor %}
</div>
</body>
</html>
""", categorized_items=categorized_items)
# Route to remove an item from the shopping list.
@app.route("/remove/<item_name>")
def remove_item(item_name):
conn = get_db_connection()
cur = conn.cursor()
cur.execute("DELETE FROM shopping_list WHERE item = %s", (item_name,))
conn.commit()
cur.close()
conn.close()
return redirect(url_for('index'))
if __name__ == "__main__":
init_db() # Initialize the database and table
app.run(host='0.0.0.0', port=5000)