diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6769e21
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,160 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..1377d8c
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+Zappster_app.iml
\ No newline at end of file
diff --git a/.idea/Zappster_app.iml b/.idea/Zappster_app.iml
new file mode 100644
index 0000000..286f873
--- /dev/null
+++ b/.idea/Zappster_app.iml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..b9c87af
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..0688661
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..393d2d6
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8325952
Binary files /dev/null and b/README.md differ
diff --git a/create_db.py b/create_db.py
new file mode 100644
index 0000000..c4df5ff
--- /dev/null
+++ b/create_db.py
@@ -0,0 +1,39 @@
+# import the sqlite3 library to work with SQLite databases in Python
+import sqlite3
+
+# connect and open the database file database.db, the database will be created when it does not exists
+conn = sqlite3.connect('database.db')
+print("Opened database successfully")
+
+# drop table if exists:
+conn.execute('DROP TABLE IF EXISTS card;')
+conn.execute('DROP TABLE IF EXISTS wish;')
+
+# create a new table card with two columns:
+# cardid - title
+conn.execute('CREATE TABLE card (cardid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, title TEXT)')
+print("Table card created successfully")
+
+# insert four rows in the newly created table
+conn.execute("INSERT INTO card (title) VALUES ('Greetings')")
+conn.execute("INSERT INTO card (title) VALUES ('Happy valentine''s day')")
+conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')")
+conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')")
+conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')")
+conn.execute("INSERT INTO card (title) VALUES ('I love you')")
+conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')")
+conn.execute("INSERT INTO card (title) VALUES ('Merry Christmas')")
+conn.execute("INSERT INTO card (title) VALUES ('Congratulations')")
+print("Cards inserted successfully")
+
+# create a second table wish:
+# wishid - uid - sender - message - cardid
+conn.execute('CREATE TABLE wish (wishid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,uid TEXT, sender TEXT, message TEXT, cardid INTEGER)')
+# there are no wishes already sent, so the table stays empty
+print("Table wish created successfully")
+
+# commit all changes to the database, otherwise they will be lost
+conn.commit()
+
+# close the connection
+conn.close()
diff --git a/database.db b/database.db
new file mode 100644
index 0000000..9c4c724
Binary files /dev/null and b/database.db differ
diff --git a/flask_app.py b/flask_app.py
new file mode 100644
index 0000000..60be3e3
--- /dev/null
+++ b/flask_app.py
@@ -0,0 +1,112 @@
+import secrets
+import sqlite3
+import string
+import os.path
+
+from flask import Flask, jsonify, request, render_template
+
+app = Flask(__name__)
+
+
+def generate_uid(db_id):
+ alphabet = string.ascii_lowercase + string.digits
+ return f"{db_id}-" + ''.join(secrets.choice(alphabet) for _ in range(4))
+
+
+def dict_factory(cursor, row):
+ dic = dict()
+ for idx, col in enumerate(cursor.description):
+ dic[col[0]] = row[idx]
+ return dic
+
+
+def db_connect():
+ connection = sqlite3.connect('database.db')
+ connection.row_factory = dict_factory
+ cursor = connection.cursor()
+ return cursor, connection
+
+
+@app.route('/')
+def home():
+ print(os.getcwd())
+ return render_template("index.html")
+
+
+@app.route('/about')
+def about():
+ return render_template("base.html")
+
+
+@app.route('/cards')
+def list_cards():
+ cur, conn = db_connect()
+ cards = cur.execute('SELECT * FROM card;').fetchall()
+ conn.close()
+ return render_template("cards.html", cards=cards)
+
+
+@app.route('/wish/')
+def wish_form(card_id):
+ cur, conn = db_connect()
+ card = cur.execute(f'SELECT * FROM card WHERE cardid={card_id};').fetchall()
+ conn.close()
+ return render_template("send_wish.html", card=card[0])
+
+
+@app.route('/wish_insert', methods=['POST'])
+def wish_insert():
+ sender = request.form.get("sender")
+ message = request.form.get("message")
+ card_id = request.form.get("card_id")
+
+ cur, conn = db_connect()
+
+ max_id = cur.execute('select MAX(wishid) as wishid from wish;').fetchone()['wishid']
+ if max_id is None:
+ db_id = 1
+ else:
+ db_id = max_id + 1
+ uid = generate_uid(db_id)
+
+ card = cur.execute('SELECT * FROM card WHERE cardid' + '=' + str(card_id) + ';').fetchone()
+ conn.execute(
+ f"INSERT INTO wish (uid, sender, message, cardid) VALUES (\'{uid}\', \'{sender}\', \'{message}\', {card_id})")
+ conn.commit()
+ conn.close()
+ return render_template("confirm_wish.html", card=card)
+
+
+@app.route('/get_wish')
+def get_wish():
+ return render_template("get_wish.html")
+
+
+@app.route('/show_wish', methods=['POST'])
+def result_wish():
+ uid = request.form.get("uuid")
+ cur, conn = db_connect()
+ personal_card = cur.execute(f"SELECT * FROM wish WHERE uid=\'{uid}\';").fetchone()
+ conn.close()
+ return render_template("show_wish.html", card=personal_card)
+
+
+# extra route for our API to request the personal message
+# use the http get method in the web request
+@app.route('/api/get_wish', methods=['GET'])
+def get_personal_wish():
+ # the function has one parameter, the unique code
+ # get the value of this parameter
+ code = request.args.get('code')
+
+ # connect and open the database file database.db
+ cur, conn = db_connect()
+ # read the associated personal wish, you will need an extra integer field code in your wish table!
+ wish = cur.execute(f"SELECT * FROM wish WHERE code={code}").fetchall()
+ conn.close()
+ # there's only one wish because the code is unique
+ response = jsonify(wish[0])
+
+ # allow cross-domain Ajax requests, more info in later years
+ response.headers.add("Access-Control-Allow-Origin", "*")
+ return response
diff --git a/read_db.py b/read_db.py
new file mode 100644
index 0000000..8d43bbb
--- /dev/null
+++ b/read_db.py
@@ -0,0 +1,20 @@
+import sqlite3
+
+# connect and open the database file database.db
+conn = sqlite3.connect('database.db')
+print("Opened database successfully")
+
+# use the opened connection to read all cards into a cursor
+cursor = conn.execute("SELECT cardid, title from card")
+# loop over all rows in the cursor and print the cardid and title column
+for row in cursor:
+ print("CARDID = ", row[0], "TITLE = ", row[1])
+
+cursor = conn.execute("SELECT * from wish")
+# loop over all rows in the cursor and print the cardid and title column
+for row in cursor:
+ print(row)
+
+# close the connection
+print("Operation done successfully")
+conn.close()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..591be0e
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+Flask~=2.1.2
\ No newline at end of file
diff --git a/static/1.jpg b/static/1.jpg
new file mode 100644
index 0000000..1773192
Binary files /dev/null and b/static/1.jpg differ
diff --git a/static/2.jpg b/static/2.jpg
new file mode 100644
index 0000000..9f01cc4
Binary files /dev/null and b/static/2.jpg differ
diff --git a/static/3.jpg b/static/3.jpg
new file mode 100644
index 0000000..fef7a85
Binary files /dev/null and b/static/3.jpg differ
diff --git a/static/4.jpg b/static/4.jpg
new file mode 100644
index 0000000..a6c901b
Binary files /dev/null and b/static/4.jpg differ
diff --git a/static/5.jpg b/static/5.jpg
new file mode 100644
index 0000000..8de44ea
Binary files /dev/null and b/static/5.jpg differ
diff --git a/static/6.jpg b/static/6.jpg
new file mode 100644
index 0000000..a0fbb4c
Binary files /dev/null and b/static/6.jpg differ
diff --git a/static/7.jpg b/static/7.jpg
new file mode 100644
index 0000000..9dacaa1
Binary files /dev/null and b/static/7.jpg differ
diff --git a/static/8.jpg b/static/8.jpg
new file mode 100644
index 0000000..ac40433
Binary files /dev/null and b/static/8.jpg differ
diff --git a/static/9.jpg b/static/9.jpg
new file mode 100644
index 0000000..17cbcc1
Binary files /dev/null and b/static/9.jpg differ
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..f70c4af
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,5 @@
+#title {
+ font-size: 5em;
+ text-decoration: underline;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..cb2aa3f
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+ {% block title %} {% endblock %}
+
+
+
+