diff --git a/app/pets/routes.py b/app/pets/routes.py index 2756cc7..f9cc8b1 100644 --- a/app/pets/routes.py +++ b/app/pets/routes.py @@ -1,6 +1,7 @@ from flask import request, render_template from app.pets import bp from app.services.pet_service import PetService +from app.utils.helpers import login_required @bp.route('/') def index(): @@ -8,4 +9,11 @@ def index(): "pets/index.html", options=PetService.get_options(request), pagination_result=PetService.get_pets(request) - ) \ No newline at end of file + ) + +@bp.route('register', methods=["GET", "POST"]) +def register(): + if request.method == 'POST': + PetService.register_pet(request) + types = PetService.get_pets_kind() + return render_template("pets/register.html", types=types) \ No newline at end of file diff --git a/app/services/pet_service.py b/app/services/pet_service.py index 66ce083..a5302b8 100644 --- a/app/services/pet_service.py +++ b/app/services/pet_service.py @@ -1,22 +1,34 @@ -from flask import Request +from flask import flash, Request from app.extensions import db from app.models.pet import Pet from app.models.pet_kind import PetKind - +from app.utils.alert_type import AlertType +from app.utils.errors.pets.pet_register_errors import PetRegisterError +from app.utils.flash_message import FlashMessage +from app.utils.helpers import pet_sex_id_to_str +from app.utils.validators.pet_validators import PetValidators class PetService: @staticmethod - def get_pets(request: Request,results_per_page=8): - def sex_n_to_str(sex: str): - if sex == '1': - return 'F' - elif sex == '2': - return 'M' - else: - return None - + def register_pet(request: Request): + """Validations""" + try: + name = PetValidators.is_valid_name(request.form.get('name')) + age = PetValidators.is_valid_age(request.form.get('age')) + sex = PetValidators.is_valid_sex(request.form.get('sex')) + heigth = PetValidators.is_valid_height(request.form.get('height')) + weight = PetValidators.is_valid_weight(request.form.get('weight')) + kind = PetValidators.is_valid_type(request.form.get('type')) + location = PetValidators.is_valid_location(request.form.get('location')) + """uploading image to cloudinary""" + """saving the data in the db""" + except PetRegisterError as e: + flash(FlashMessage(e.message, AlertType.DANGER.value )) + + @staticmethod + def get_pets(request: Request,results_per_page=8): type = request.args.get('type') - sex = sex_n_to_str(request.args.get('sex')) + sex = pet_sex_id_to_str(request.args.get('sex')) age_from = request.args.get('age-from') age_to = request.args.get('age-to') query = db.select(Pet) @@ -61,6 +73,10 @@ class PetService: options["age_from"] = PetService.get_age_from_options(age_from) return options + @staticmethod + def get_pets_kind(): + return db.session.execute(db.select(PetKind)).scalars() + @staticmethod def get_pets_kind_options(selected_kind=None): pet_kinds = db.session.execute(db.select(PetKind)).scalars() diff --git a/app/static/css/pets-register.css b/app/static/css/pets-register.css new file mode 100644 index 0000000..fc9dfd8 --- /dev/null +++ b/app/static/css/pets-register.css @@ -0,0 +1,12 @@ +.pets-register { + max-width: 480px; +} + +.pets-register__form-img-container { + max-height: 150px; + max-width: 150px; + overflow: hidden; +} +.pets-register__form-img:hover { + cursor: pointer; +} \ No newline at end of file diff --git a/app/static/js/pet-form-img-updater.js b/app/static/js/pet-form-img-updater.js new file mode 100644 index 0000000..2a7346f --- /dev/null +++ b/app/static/js/pet-form-img-updater.js @@ -0,0 +1,30 @@ +(() => { + 'use strict' + function readImage(file) { + if (!file.type || !file.type.match('image\/(png|jpeg|jpg|webp)')) { + alert("Invalid image format!"); + return; + } + if(file.size > 2097152) { + alert("File is too big!"); + return; + } + + const img = document.querySelector('#img-card'); + const reader = new FileReader(); + reader.addEventListener('load', (event) => { + const imgObj = new Image(); + imgObj.src = event.target.result; + imgObj.onload = function(ev) { + if(ev.target.naturalWidth > 512 || ev.target.naturalHeight > 512) { + alert("Image max dimesions allowed is 512x512"); + return; + } + img.src = event.target.result; + } + }); + reader.readAsDataURL(file); + } + document.querySelector('#img-selector') + .addEventListener('change', function(ev){readImage(ev.target.files[0])}) +})() \ No newline at end of file diff --git a/app/templates/pets/register.html b/app/templates/pets/register.html new file mode 100644 index 0000000..1aebe30 --- /dev/null +++ b/app/templates/pets/register.html @@ -0,0 +1,152 @@ +{% extends "layout/layout.html" %} +{% from "forms/submit-btn.html" import form_submit_button %} +{% from "layout/inner_header.html" import inner_header%} +{% block title %} Home {% endblock %} +{% block head %} + {{ super() }} + +{% endblock %} +{% block content %} +
+
+
+ {{ inner_header("Pet Details") }} +
+
+ {% include 'message.html' %} +
+
+
+
+ +
+
+ +
+
+
+
+
+ Name + +
+
+
+
+
+ Age + +
+
+
+
+ Sex + +
+
+
+
+
+
+ height + +
+
+
+
+ Weight + +
+
+
+
+
+
+
+
+ Type + +
+
+
+
+ Location + +
+
+
+
+
+ {{ form_submit_button("Submit") }} +
+
+
+
+
+
+ + +{% endblock %} diff --git a/app/utils/errors/pets/pet_register_errors.py b/app/utils/errors/pets/pet_register_errors.py new file mode 100644 index 0000000..d850404 --- /dev/null +++ b/app/utils/errors/pets/pet_register_errors.py @@ -0,0 +1,4 @@ +class PetRegisterError(Exception): + def __init__(self, message): + self.message = message + super().__init__(self.message) \ No newline at end of file diff --git a/app/utils/helpers.py b/app/utils/helpers.py index de97aa4..6aa6a93 100644 --- a/app/utils/helpers.py +++ b/app/utils/helpers.py @@ -15,3 +15,11 @@ def only_guests(html: str): if not session["id"]: return html return None + +def pet_sex_id_to_str(sex: str): + if sex == '1': + return 'F' + elif sex == '2': + return 'M' + else: + return None \ No newline at end of file diff --git a/app/utils/validators/pet_validators.py b/app/utils/validators/pet_validators.py new file mode 100644 index 0000000..ab49d01 --- /dev/null +++ b/app/utils/validators/pet_validators.py @@ -0,0 +1,66 @@ +from app.extensions import db +from app.models.pet_kind import PetKind +from app.utils.errors.pets.pet_register_errors import PetRegisterError +from app.utils.helpers import pet_sex_id_to_str +from app.utils.validators.validators import Validators + +class PetValidators: + + @staticmethod + def is_valid_name(name: str|None): + if Validators.is_valid_str_and_pattern(name,'^[A-Za-z ]{2,255}$'): + return name + raise PetRegisterError("Invalid pet name") + + @staticmethod + def is_valid_age(age: str|None): + try: + if int(age) >= 0: + return age + except: + raise PetRegisterError("Invalid age") + raise PetRegisterError("Invalid age") + + @staticmethod + def is_valid_weight(w: str|None): + if w is None: + return None + if Validators.is_valid_decimal(w) and float(w) >= 0: + return w + raise PetRegisterError("Invalid pet weight") + + @staticmethod + def is_valid_height(h: str|None): + if h is None: + return None + if Validators.is_valid_decimal(h) and float(h) >= 0: + return h + raise PetRegisterError("Invalid pet height") + + @staticmethod + def is_valid_sex(sex: str|None): + pet_sex = pet_sex_id_to_str(sex) + if pet_sex is None: + raise PetRegisterError("Invalid pet sex") + return pet_sex + + @staticmethod + def is_valid_type(pet_type: str|None): + INVALID_MSG = "Invalid pet type" + if pet_type is None: + raise PetRegisterError(INVALID_MSG) + types = db.session.execute(db.select(PetKind)).scalars() + try: + for type in types: + if int(pet_type) == type.id: + return pet_type + except: + raise PetRegisterError(INVALID_MSG) + raise PetRegisterError(INVALID_MSG) + + @staticmethod + def is_valid_location(location: str|None): + if location is not None: + if Validators.is_valid_str_and_pattern(location,'^[A-Za-z ]{2,255}$'): + return location + raise PetRegisterError("Invalid location") \ No newline at end of file