This shows you the differences between two versions of the page.
ii:assignments:s2:shopping-cart-2025 [2025/04/10 11:45] florin.stancu created |
ii:assignments:s2:shopping-cart-2025 [2025/05/15 17:09] (current) florin.stancu |
||
---|---|---|---|
Line 4: | Line 4: | ||
**Deadline**: | **Deadline**: | ||
- | * **//07.05.2025// Deadline** <color red>HARD!</color>; | + | * **//23.05.2025// <color red>Deadline</color>** 😥! |
**Changelog:** | **Changelog:** | ||
+ | * **//15.05.2025//**: new deadline (+4 days :D)! | ||
* **//10.04.2025//**: assignment published! | * **//10.04.2025//**: assignment published! | ||
Line 26: | Line 27: | ||
* a personalized HTML + CSS web template / design to base the rest of the application on (Bootstrap is recommended, but not required -- you can use whatever design framework you want); it is mandatory to use some sort of server-based template engine (e.g., Jinja2) to avoid duplicate code; | * a personalized HTML + CSS web template / design to base the rest of the application on (Bootstrap is recommended, but not required -- you can use whatever design framework you want); it is mandatory to use some sort of server-based template engine (e.g., Jinja2) to avoid duplicate code; | ||
- | * a front page showcasing your shop's products (see example screenshots below); see extra restrictions below! | + | * a front page showcasing your shop's products (see example screenshots below); optionally, you can implement per-product dynamic pages too (for bonuses); |
- | * a shopping cart products can be added to; this must be persistent across page refreshes (e.g., stored inside a browser session)! | + | * a shopping cart for products to be added to before issuing the order; this must be persistent across page refreshes (e.g., stored inside a browser session)! |
- | * a checkout form listing the cart products to be ordered with the final computed price (optionally, you may add mock taxes) and for taking in customer data (name, email, address fields); | + | * a checkout form listing the cart products to be ordered with the final computed price to pay (optionally, you may add mock taxes) and for taking in customer data (name, email, address fields); |
* a method for persisting (storing) the user-submitted order details on the server (either using text files, some other format, e.g. JSON/YAML or a database -- for bonus points); | * a method for persisting (storing) the user-submitted order details on the server (either using text files, some other format, e.g. JSON/YAML or a database -- for bonus points); | ||
* an additional //"contact"// page (fill it with a fake company details or whatever you want); | * an additional //"contact"// page (fill it with a fake company details or whatever you want); | ||
- | * you **must respect** the required route naming convention (specified in each of the sub-sections)! | + | * you **must respect** the required route & fields naming convention (specified in each of the sub-sections)! |
* a ''Readme.(md|txt)'', a ''requirements.txt'' containing Python dependencies, a Docker container image with all dependencies to quickly start up the web application (important for making the evaluation process error-proof -- a container will work everywhere else!) + other misc. files (see the archive structure in the last section); | * a ''Readme.(md|txt)'', a ''requirements.txt'' containing Python dependencies, a Docker container image with all dependencies to quickly start up the web application (important for making the evaluation process error-proof -- a container will work everywhere else!) + other misc. files (see the archive structure in the last section); | ||
Line 37: | Line 38: | ||
**Now carefully read below for a description & recommendations for each of these requirements**! | **Now carefully read below for a description & recommendations for each of these requirements**! | ||
+ | |||
+ | ==== Web frontend design (HTML/CSS) ==== | ||
+ | |||
+ | The design (aspect) of the web pages does not really matter as long as it meets the functionality requirements described in this document (just don't make it too ugly). | ||
+ | |||
+ | As a minimum, you must display photo thumbnails for each product listed on the front page. | ||
+ | |||
+ | Although you can use whatever CSS framework you'd like, we recommend [[https://getbootstrap.com/|Bootstrap]]. If you wish, you could base it on the lab's template, though you should further personalize it. | ||
+ | |||
+ | All requested pages must have a common menu bar directly linking to eachother. The currently active item must be differentiated (e.g., different background or text colors). A human should able to easily figure out which link to press for accessing the required functionality (add to cart, view shopping cart & order items). | ||
+ | |||
+ | Bootstrap design element recommendations: | ||
+ | |||
+ | * [[https://getbootstrap.com/docs/5.3/components/navs-tabs/|Navs]] for the website menu(s); | ||
+ | * [[https://getbootstrap.com/docs/5.3/components/card/|Cards]] for the frontpage product showcase (may also be used for listing shopping cart items too!); | ||
+ | * [[https://getbootstrap.com/docs/5.3/utilities/flex/|Flexbox utility classes]] for positioning the product cards; | ||
+ | * [[https://getbootstrap.com/docs/5.3/components/badge/|Badges]] for displaying current shopping cart items; | ||
+ | * [[https://getbootstrap.com/docs/5.3/forms/overview/|Forms]] for the ordering/checkout form (and, optionally, for the contact page); | ||
+ | |||
+ | The use of JavaScript-based templating/rendering (e.g., React, EJS and 1000 others like them) is forbidden (//not studied here//). Stick to HTML + CSS for now ;) you can, of course, optionally use **some** JavaScript to make some UX prettier as bonus (e.g., cart add animation). | ||
+ | |||
+ | Here's some screenshots for example & inspiration: | ||
+ | |||
+ | {{ii:assignments:s2:shopping-cart-2025:design-frontpage.png?300}} {{ii:assignments:s2:shopping-cart-2025:design-cart.png?300}} | ||
+ | |||
+ | ==== Front page (product showcase) ==== | ||
+ | |||
+ | The URL (route) for this page **must be ''/''**, though it is allowed to redirect to another route (e.g., ''/products/promo'') if you wish to implement categories (for bonus). If you wish to make individual dynamic pages for each product, no further routing restrictions will apply there (as it is a bonus feature). | ||
+ | |||
+ | The product listing must be dynamically rendered from Python data (e.g., using a Jinja2 ''for'' loop). The products may either be hardcoded in a separate Python module, loaded from a configuration file (ofc, a more elegant approach) or database (for bonus points). | ||
+ | |||
+ | Each of the products must have a "Add to cart" button/icon beside it to add the item to cart (see the next section for specifics). | ||
+ | |||
+ | //Bonus ideas:// filtering / ordering the products, multiple categories, database storage (SQL/NoSQL). | ||
+ | |||
+ | ==== Shopping Cart ==== | ||
+ | |||
+ | As the shopping cart represents the main functionality of such websites, this is also where the assignment's main complexity comes from. | ||
+ | At minimum, you should display the product name, order count and price in tabular-like fashion, have a total price computed plus a button to proceed with the order (which must open the Checkout form described in the next sub-section). | ||
+ | |||
+ | You **must route** ''/cart'' for displaying the current shopping cart. | ||
+ | |||
+ | As mentioned before, a product may be added from the front page (and, optionally, from each product's page, if implemented as bonus). For this, you must use a REST-ful route named ''/cart/add-item'' with a ''id'' GET parameter, e.g., ''/cart/add-item/?id=123''. This is important as we will use automation for quickly testing the website's functionality (a simple script will be supplied later for testing this convention). | ||
+ | |||
+ | A product may be added multiple times, each time incrementing its count. You may (optionally) have modification buttons / text field for editing . | ||
+ | |||
+ | You MUST have a deletion link/button for each product inside the shopping cart. Use ''/cart/remove-item?id=PRODUCT_ID'', which will also be used as REST-ful API for automation. | ||
+ | |||
+ | ==== Checkout page ==== | ||
+ | |||
+ | As a final step before ordering, you will implement a page with a form where the user will see the products to be ordered and the totals and fill with the user's contact info. Please don't forget the //submit// button! | ||
+ | |||
+ | The checkout form MUST be reachable using GET (i.e., the usual browser navigation) at the ''/checkout'' URL. | ||
+ | |||
+ | The checkout form must submit the data using the POST method at the same ''/checkout'' URL, with the following field names (obligatory! use them for naming the inputs): | ||
+ | |||
+ | * ''full_name'': user's full name; | ||
+ | * ''email'': the email of the user; | ||
+ | * ''phone'': the phone number; | ||
+ | * ''address'': the full address (for simplicity), you may use a ''<textarea>'' for it; | ||
+ | * ''payment_method'': multiple choices between ''card'', ''bank_transfer'' and ''cash'' (don't worry, you won't have to implement any of them, just make the server store them as such). | ||
+ | |||
+ | You may add more fields if desired, but please make them optional (since the automation script will NOT submit them). | ||
+ | |||
+ | Note: data validation is optional, but nice to have nevertheless ;) | ||
+ | |||
+ | On checkout form submission, at minimum, you should print all of the data in any human readable format (i.e., NOT binary!) on the Flask console, which should also help you with debugging. | ||
+ | |||
+ | For a more realistic implementation and obtaining full points for this task, we require you to also save the order on the server, either by creating small text-based files in a directory (e.g., ''./submitted-data/<date>.txt''), use a structured format (e.g. ''json / yaml'') or, for an extensive bonus, insert them into a database. | ||
+ | |||
+ | |||
+ | ==== Flask server and containerization ==== | ||
+ | |||
+ | First of all, you **must** use a virtual environment for development and [[https://pip.pypa.io/en/stable/reference/requirements-file-format/|declare all of your Python dependencies]] in a ''requirements.txt'' file. You can easily obtain this by using ''pip freeze > requirements.txt'' command inside your virtual environment (obligatory, otherwise it will output ALL of your system installed packages!) or by manually inserting the name of each installed package. | ||
+ | |||
+ | **Obligatory / common sense:** use Flask's standard port of ''5000'' when serving from any of your scripts. PLEASE DO NOT CHANGE IT, otherwise we will have to manually edit the ''http://localhost:<port>'' URL for each non-conforming solution and will be greatly penalized! | ||
+ | |||
+ | In order for your web application to be easily shared (with us :P), you should add a proper Dockerfile that can be used to readily build + run it. | ||
+ | |||
+ | You may start from any base image, although we recommend [[https://hub.docker.com/_/python|''python:<version>-alpine'']] due to its low disk footprint. | ||
+ | |||
+ | Thus, a containerized solution must work using the following steps: | ||
+ | * the ''docker build -t iap1-tema ./'' command should run successfully; | ||
+ | * ''docker run -p 5000:5000 -it iap1-tema'' should start the Flask server and make it accessible on ''http://localhost:5000''. | ||
+ | |||
+ | <note important> | ||
+ | If you do not wish to implement containerization but wish to avoid further penalizations regarding the testability of your website, you **must** name the Flask entrypoint as ''server.py'' and make it runnable using ''python3 server.py'' (a proper virtual environment with the declared ''requirements.txt'' will be automatically setup by our scripts beforehand). | ||
+ | </note> | ||
+ | |||
+ | ===== Grading ===== | ||
+ | |||
+ | The base assignment constitutes **4p** out of your final grade (100p homework = **4p** final grade). | ||
+ | The 100p are split between the following tasks: | ||
+ | |||
+ | * **[20p] Flask server & basic design**: the basic Flask server routing + server-side template for a online shopping website; this includes having at least two pages sharing the same base template! | ||
+ | * **[20p] Front page** showcasing your products with (mock/sample) images (dynamically rendered using the template engine from structured data, as requested)! | ||
+ | * **[20p] Shopping Cart** for a working Add to Cart feature for the front page, displaying the current cart's items count inside your global menu & building the cart's dedicated page; | ||
+ | * **[20p] Checkout page** with a functional form & submission data console printing and saving them to persistent storage; | ||
+ | * **[20p] Docker container:** must respect all backend testing conventions & supply a working Dockerfile for quickly setting up your website during the grading process; | ||
+ | * **[up to 20% of the assignment's points] Bonuses!** Almost everything extra counts, so don't be shy (make sure to also mention them inside your Readme). | ||
+ | |||
+ | You must also write a Readme (.txt / .md) containing a description of your implementation, design choices, third party libraries (and the whys), challenges you encountered, bonuses you thought of etc. | ||
+ | |||
+ | The project's source code (i.e., no binary / generated files need to be included) must be archived (''.zip'', please) and make sure the scripts (incl. Dockerfile) are placed directly in the root folder (i.e. depth=0) of the archive! Otherwise, the grading process will be encumbered => penalizations++ :( | ||
+ | |||
+ | <note> | ||
+ | Please follow the archiving conventions and have everything (especially the ''Dockerfile'') inside its root directory! | ||
+ | </note> | ||
+ | |||
+ | <note important> | ||
+ | **NOTE:** Assistants are free do deduct points for bad / illegible code, e.g., if you have lots of hardcoded items data in the same file as the Flask code! | ||
+ | |||
+ | Also, please double-check if you followed all naming conventions! | ||
+ | </note> | ||
+ | |||
+ | ===== Resources ===== | ||
+ | |||
+ | **TODO: //some automation scripts / conventions checker will be posted here in a couple of days! Please stand by :D //** | ||
+ | |||
+ | * [[https://getbootstrap.com/docs/5.3/getting-started/introduction/|Bootstrap]] CSS framework, as per recommendations. | ||
+ | * [[https://flask.palletsprojects.com/en/3.0.x/|Flask]] web framework for Python. | ||
+ | * [[https://jinja.palletsprojects.com/en/3.1.x/templates/|Jinja2]] template engine (integrated with Flask). | ||
+ | * [[https://docs.docker.com/get-started/|Docker]] container engine (Getting started tutorial). | ||
+ | |||
+ | ===== FAQ ===== | ||
+ | |||
+ | **Q: Can I write the tool in something other than Python?** \\ | ||
+ | A: No, please use Python. You can have some (but not exceedingly) JavaScript for enhancing your frontend, but the sever-side and all dynamic functionality must be done on the server-side, in Python. | ||
+ | |||
+ | **Q: What platform will this assignment be tested on?** \\ | ||
+ | A: Linux (though, you don't need to use any platform-specific APIs + containers/Docker is the pinnacle of portability!). | ||
+ | |||