diff --git a/Client/__init__.py b/Client/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Client/__init__.py @@ -0,0 +1 @@ + diff --git a/Client/app.py b/Client/app.py index 93b99a0..d63417f 100644 --- a/Client/app.py +++ b/Client/app.py @@ -1,21 +1,34 @@ +from Client.tcp_client import TCPClient + from flask import Flask, render_template, request, jsonify, redirect, url_for, session, flash -from tcp_client import TCPClient + import time import base64 import os + from datetime import datetime -from database import Database +from Client.database import Database app = Flask(__name__) app.secret_key = os.urandom(24) +app.secret_key = os.urandom(24) tcp_client = TCPClient(server_host='localhost', server_port=5001) + +# comment_manager = CommentManager() +# image_manager = ImageManager() + +upload_images = [] db = Database() + @app.route('/') def login(): # Check if user is already logged in + if 'user_id' in session: + return redirect(url_for('index')) + # Check if user is already logged in if 'user_id' in session: return redirect(url_for('index')) return render_template('login.html') diff --git a/Client/database.py b/Client/database.py index 8cbda1f..d91ef47 100644 --- a/Client/database.py +++ b/Client/database.py @@ -124,7 +124,20 @@ def _insert_default_data(self): (8, "/static/images/8.jpg", "Clothes that Guarantee Survival", "Clothes", 1, 1), (9, "/static/images/9.jpg", "If you don'T have these in your pantry, uh oh", "Meal Prep", 1, 1), (10, "/static/images/10.jpg", "Rebuild after the apocalypse is over with these plants", "Gardening", 1, 1), - (11, "/static/images/11.jpg", "Flowers will be worth millions soon, enjoy them now", "Gardening", 1, 1) + (11, "/static/images/11.jpg", "Flowers will be worth millions soon, enjoy them now", "Gardening", 1, 1), + (12, "/static/images/12.jpg", "Are you ready? Are you sure?", "Tips", 1, 1), + (13, "/static/images/13.jpg", "Read this to help!", "Hacks", 1, 1), + (14, "/static/images/14.jpg", "All natural weapons", "Tools", 1, 1), + (15, "/static/images/15.jpg", "Delicious bread for when the world ends ", "Food", 1, 1), + (16, "/static/images/16.jpg", "The end is near..", "Tips", 1, 1), + (17, "/static/images/17.jpg", "15 Reasons you need to prep NOW", "Tips", 1, 1), + (18, "/static/images/18.jpg", "Stockpile = Survival", "Tips", 1, 1), + (19, "/static/images/19.jpg", "18 Best foods you NEED to prep", "Meal Prep", 1, 1), + (20, "/static/images/20.jpg", "Number 27 is shocking..", "Tips", 1, 1), + (21, "/static/images/21.jpg", "THESE IDEAS WILL SAVE YOUR LIFE", "Tips", 1, 1), + (22, "/static/images/22.jpg", "This is our future world.. get ready", "Tips", 1, 1), + (23, "/static/images/23.jpg", "You NEED to know about this..", "Tips", 1, 1), + (24, "/static/images/24.jpg", "Which prepper type are you??", "Tips", 1, 1) ] self.cursor.executemany( diff --git a/Client/image_manager.py b/Client/image_manager.py index 49dffba..d12fcf1 100644 --- a/Client/image_manager.py +++ b/Client/image_manager.py @@ -51,8 +51,7 @@ def upload_image(self, image_file, caption, tags): 'id': len(self.uploaded_images) + 1, 'url': f"/static/uploads/{image_filename}", 'caption': caption, - 'category': tags, - 'image': base64_image + 'category': tags } #store in file (while db not up) diff --git a/Client/images.json b/Client/images.json index 05b7328..802ee2d 100644 --- a/Client/images.json +++ b/Client/images.json @@ -64,12 +64,5 @@ "url": "./static/images/11.jpg", "caption": "Flowers will be worth millions soon, enjoy them now", "category": "Gardening" - }, - { - "id": 12, - "url": "./static/uploads/A.png", - "caption": "test", - "category": "cool", - "image": "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" } ] \ No newline at end of file diff --git a/Client/preppersdb.sqlite b/Client/preppersdb.sqlite index 75c6320..ec93c05 100644 Binary files a/Client/preppersdb.sqlite and b/Client/preppersdb.sqlite differ diff --git a/Client/saved_images.json b/Client/saved_images.json index 9e891d2..1960e08 100644 --- a/Client/saved_images.json +++ b/Client/saved_images.json @@ -17,6 +17,12 @@ "url": "./static/images/3.jpg", "caption": "Amazing Survival Recipes", "category": "Meal Prep" + }, + { + "id": 6, + "url": "./static/images/6.jpg", + "caption": "World War 3 is Coming, are you Prepared??", + "category": "Tips" } ] } \ No newline at end of file diff --git a/Client/static/css/style.css b/Client/static/css/style.css index ccb908b..76d39b4 100644 --- a/Client/static/css/style.css +++ b/Client/static/css/style.css @@ -19,6 +19,27 @@ body { } + +body { + background-color: #f5f1e8; +} + +/* Container styling */ +.container.mt-4 { + background-color: #f9f7f3; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0,0,0,0.03); +} + + +.navbar { + background-color: #e8ded1 !important; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); + margin-bottom: 20px; +} + + .card { margin-bottom: 20px; border-radius: 16px; @@ -26,13 +47,16 @@ body { transition: transform 0.3s ease; max-width: 300px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); + box-shadow: 0 2px 8px rgba(0,0,0,0.05); } + .card:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0,0,0,0.1); } + .card-img-top { width: 100%; object-fit: cover; @@ -64,10 +88,21 @@ body.login-page { .form-group { color: white; + + background-color: transparent; } -.formbg { +body.login-page { + + background-color: transparent; +} + +.form-group { color: white; +} + +.formbg { + width: 75%; } @@ -76,6 +111,13 @@ body.login-page { background-color: rgba(14, 13, 13, 0.5); } +.login-container { + background-color: rgba(14, 13, 13, 0.7); + border-radius: 8px; + padding: 30px; + color: white; +} +/* upload */ .login-container { background-color: rgba(14, 13, 13, 0.7); border-radius: 8px; @@ -112,10 +154,13 @@ body.login-page { max-height: 250px; border-radius: 4px; } + +/* comment */ /* comment */ #modalImage { max-height: 600px; width: 100%; + width: 100%; object-fit: contain; } @@ -214,3 +259,89 @@ body.login-page { padding: 8px 20px; } + + +/* Button */ +.btn-sm { + border-radius: 20px; + padding: 0.25rem 0.8rem; +} + +.btn-outline-success:hover { + background-color: #28a745; + border-color: #28a745; +} + +/* Profile Page*/ +.profile-image { + width: 200px; + height: 200px; + object-fit: cover; + border-radius: 50%; + border: 5px solid #fff; + box-shadow: 0 5px 15px rgba(0,0,0,0.1); + margin-bottom: 20px; + transition: transform 0.3s; +} + +.profile-image:hover { + transform: scale(1.05); +} + +.profile-card { + text-align: center; + padding: 20px; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0,0,0,0.1); + background-color: #fff; + margin-bottom: 20px; +} + +.stat-card { + border-radius: 10px; + padding: 15px; + margin-bottom: 15px; + background-color: #f8f9fa; + transition: transform 0.3s, box-shadow 0.3s; +} + +.stat-card:hover { + transform: translateY(-5px); + box-shadow: 0 10px 20px rgba(0,0,0,0.1); +} + +.stat-number { + font-size: 2.5rem; + font-weight: bold; + color: #198754; +} + +.stat-label { + color: #6c757d; + font-size: 1rem; +} + +.user-info { + margin: 20px 0; +} + +.user-info-item { + display: flex; + margin-bottom: 15px; + padding-bottom: 15px; + border-bottom: 1px solid #eee; +} + +.user-info-label { + font-weight: bold; + min-width: 120px; +} + +.action-buttons { + margin-top: 20px; +} + +.action-buttons .btn { + margin: 0 5px; + padding: 8px 20px; +} \ No newline at end of file diff --git a/Client/static/images/13.jpg b/Client/static/images/13.jpg new file mode 100644 index 0000000..e5f9a20 Binary files /dev/null and b/Client/static/images/13.jpg differ diff --git a/Client/static/images/14.jpg b/Client/static/images/14.jpg new file mode 100644 index 0000000..37b0268 Binary files /dev/null and b/Client/static/images/14.jpg differ diff --git a/Client/static/images/15.jpg b/Client/static/images/15.jpg new file mode 100644 index 0000000..9205338 Binary files /dev/null and b/Client/static/images/15.jpg differ diff --git a/Client/static/images/16.jpg b/Client/static/images/16.jpg new file mode 100644 index 0000000..7828a56 Binary files /dev/null and b/Client/static/images/16.jpg differ diff --git a/Client/static/images/17.jpg b/Client/static/images/17.jpg new file mode 100644 index 0000000..46235c0 Binary files /dev/null and b/Client/static/images/17.jpg differ diff --git a/Client/static/images/18.jpg b/Client/static/images/18.jpg new file mode 100644 index 0000000..f6d942d Binary files /dev/null and b/Client/static/images/18.jpg differ diff --git a/Client/static/images/19.jpg b/Client/static/images/19.jpg new file mode 100644 index 0000000..8d7be3a Binary files /dev/null and b/Client/static/images/19.jpg differ diff --git a/Client/static/images/20.jpg b/Client/static/images/20.jpg new file mode 100644 index 0000000..7fc7ce6 Binary files /dev/null and b/Client/static/images/20.jpg differ diff --git a/Client/static/images/21.jpg b/Client/static/images/21.jpg new file mode 100644 index 0000000..ce6df19 Binary files /dev/null and b/Client/static/images/21.jpg differ diff --git a/Client/static/images/22.jpg b/Client/static/images/22.jpg new file mode 100644 index 0000000..e77a7c6 Binary files /dev/null and b/Client/static/images/22.jpg differ diff --git a/Client/static/images/23.jpg b/Client/static/images/23.jpg new file mode 100644 index 0000000..96f6c91 Binary files /dev/null and b/Client/static/images/23.jpg differ diff --git a/Client/static/images/24.jpg b/Client/static/images/24.jpg new file mode 100644 index 0000000..6a03989 Binary files /dev/null and b/Client/static/images/24.jpg differ diff --git a/Client/static/js/image-grid.js b/Client/static/js/image-grid.js index 561271a..23e1cc1 100644 --- a/Client/static/js/image-grid.js +++ b/Client/static/js/image-grid.js @@ -16,6 +16,55 @@ document.addEventListener('DOMContentLoaded', function () { }); }); +//when clicking the save image button on a specific image +document.addEventListener("DOMContentLoaded", function() { + const saveButtons = document.querySelectorAll(".save-btn"); + + saveButtons.forEach(button => { + button.addEventListener("click", function() { + const imageId = this.getAttribute("data-id"); + + fetch('/save_image', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ image_id: imageId }) + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + alert('Image saved to your vault!!'); + } else { + alert('Couldnt save the image, please try again later.' + data.message); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Couldnt save the image, please try again later.'); + }); + }); + }); +}); + +document.addEventListener('DOMContentLoaded', function () { + //masonry info: https://masonry.desandro.com/ + //to make a grid, pinterest style + var grid = document.querySelector('#masonry-grid'); + var masonry = new Masonry(grid, { + itemSelector: '.card', + columnWidth: '.card', + percentPosition: true, + gutter: 15 + }); + + //layout after loading images + var imgLoad = imagesLoaded(grid); + imgLoad.on('progress', function () { + masonry.layout(); + }); +}); + //when clicking the save image button on a specific image document.addEventListener("DOMContentLoaded", function() { // Handle Save to Vault buttons diff --git a/Client/tcp_client.py b/Client/tcp_client.py index bec9f19..d0302ac 100644 --- a/Client/tcp_client.py +++ b/Client/tcp_client.py @@ -4,7 +4,9 @@ import hashlib import time -logging.basicConfig( + +# Logging structure for btoh clent and server +logging.basicConfig( filename='client_log.txt', filemode='w', level=logging.INFO, @@ -47,7 +49,8 @@ def connect(self): self.connected = False return False - def disconnect(self): + def disconnect(self): # pragma: no cover + """Disconnect from the server""" if self.socket: self.socket.close() self.socket = None @@ -59,6 +62,7 @@ def send_request(self, command, data): if not self.connect(): return False, "Failed to connect to server" + # Create request packet packet = self.create_packet(command, data) #ALL NAMING FUNCTIONS THAT SERVER SHOULD CALL try: @@ -148,12 +152,15 @@ def receive_response(self, timeout=10): logger.warning("Received empty response from server") return None + response = json.loads(data) + # Validate header if 'header' not in response: logger.warning("Invalid response format - missing header") return None + # Validate checksum if 'footer' in response and 'checksum' in response['footer']: if not self.validate_checksum(json.dumps(response['body']), response['footer']['checksum']): logger.warning("Response checksum validation failed") diff --git a/Client/templates/base.html b/Client/templates/base.html index 5e3ff6f..b246d6f 100644 --- a/Client/templates/base.html +++ b/Client/templates/base.html @@ -52,6 +52,7 @@ {% else %} Login {% endif %} + @@ -68,6 +69,7 @@ + diff --git a/Client/templates/image-grid.html b/Client/templates/image-grid.html index 72cc1ec..e219c65 100644 --- a/Client/templates/image-grid.html +++ b/Client/templates/image-grid.html @@ -22,5 +22,5 @@