add other folders
This commit is contained in:
parent
3ca2a19317
commit
9bf0df0594
17
z1/app/Dockerfile
Normal file
17
z1/app/Dockerfile
Normal file
@ -0,0 +1,17 @@
|
||||
FROM python:3.9-slim
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the requirements file and install Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy the application source code
|
||||
COPY app.py .
|
||||
|
||||
# Expose port 5000 for the Flask application
|
||||
EXPOSE 5000
|
||||
|
||||
# Start the Flask application
|
||||
CMD ["python", "app.py"]
|
233
z1/app/app.py
Normal file
233
z1/app/app.py
Normal file
@ -0,0 +1,233 @@
|
||||
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)
|
2
z1/app/requirements.txt
Normal file
2
z1/app/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Flask
|
||||
psycopg2-binary
|
Loading…
Reference in New Issue
Block a user