Group: 312CC
Year: I
I used Flask as the Python server, SQLite as the database, Jinja2 as the template engine, and Tailwind CSS as the CSS framework. I chose Tailwind because I have worked with it before and find it more flexible than Bootstrap, allowing me to customize the design exactly to my liking.
The database is named shop.db and lives in the /database folder. If it doesn’t exist (or is empty), it’s automatically created and populated in server.py from the products.json file (used as a template). I designed three tables: products, order, and orderitem. The orderitem table stores item details (ID, quantity, etc.), and I set up a SQLAlchemy relationship between order.items and orderitem.
-
base.html:
- Base HTML template including header and footer.
- The header has 5 links to the main pages (Home, Products, Cart, Contact, Admin).
- On the left is a “UPBshop.” logo linking to the homepage (
/), and on the right a cart icon showing the number of items in the cart (fetched from the backend and updated on add/remove). - The active page link is highlighted with a darker color.
-
index.html: (
/)- Hero banner with two buttons: Explore Deals (scrolls to
#products) and View Cart (navigates to/cart). - Categories dropdown (populated from the backend) and a search bar (server-side).
- Products grid showing each product’s name, seller (or “Admin” if seeded), category, and total sales.
- “Add to cart” icon adds the item; “Preview” link goes to
/product/{product_id}.
- Hero banner with two buttons: Explore Deals (scrolls to
-
cart.html: (
/cart)- Displays all items in the cart.
- Quantity controls (
–/+) and a remove button (removes all of that item). - Proceed to Checkout button →
/checkout.
-
checkout.html: (
/checkout)- Two-column layout:
- Order summary (product names + quantities)
- Billing form (all fields required)
- On submit, posts to the same route and renders
order_confirm.html, saves the order to the database, logs details to console, and updates product sales counts.
- Two-column layout:
-
contact.html: (
/contact)- Shop contact information and a contact form (logs submissions to console).
-
order_confirm.html:
- Rendered after checkout form submission.
- Displays billing details and an itemized order summary (unit prices + totals).
- Logs data to console and saves to DB.
-
product.html: (
/product/{product_id})- Shows full product details (name, price, description, etc.) with an Add to Cart button.
-
admin_order.html (
/admin/order):- Lists all orders from the database with customer details, order ID, date/time, and items.
-
admin_products.html (
/admin/products):- Lists all products (price, total sales).
- Options to delete products or add new ones (name, description, category, price, image upload).
Note: I considered adding a login/register system, but since it was optional and only superficial, I omitted it.
The site is responsive, and the mobile menu uses Alpine.js. All cart actions, filtering, and search logic run on the server in server.py, causing page reloads. I thought about using JS middleware for AJAX but opted for a fully server-driven approach to meet the assignment requirements.
In the Dockerfile, I declare VOLUME /database so shop.db persists. The .dockerignore excludes the database/ folder during build to prevent copying the volume and causing errors.
# Build and run with Docker
docker build -t upbshop .
docker run -p 5000:5000 upbshop