feat(pets): adds bp, service and filters template and logic
This commit is contained in:
@@ -31,5 +31,7 @@ def create_app(config_class=Config):
|
|||||||
app.register_blueprint(main_bp)
|
app.register_blueprint(main_bp)
|
||||||
from app.users import bp as users_bp
|
from app.users import bp as users_bp
|
||||||
app.register_blueprint(users_bp, url_prefix="/users")
|
app.register_blueprint(users_bp, url_prefix="/users")
|
||||||
|
from app.pets import bp as pets_bp
|
||||||
|
app.register_blueprint(pets_bp, url_prefix="/pets")
|
||||||
|
|
||||||
return app
|
return app
|
||||||
4
app/pets/__init__.py
Normal file
4
app/pets/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('pets', __name__)
|
||||||
|
from app.pets import routes
|
||||||
7
app/pets/routes.py
Normal file
7
app/pets/routes.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from flask import request, render_template
|
||||||
|
from app.pets import bp
|
||||||
|
from app.services.pet_service import PetService
|
||||||
|
|
||||||
|
@bp.route('/')
|
||||||
|
def index():
|
||||||
|
return render_template("pets/index.html", options=PetService.get_options(request))
|
||||||
93
app/services/pet_service.py
Normal file
93
app/services/pet_service.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
from flask import Request
|
||||||
|
from app.extensions import db
|
||||||
|
from app.models.pet_kind import PetKind
|
||||||
|
|
||||||
|
class PetService:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_options(request: Request):
|
||||||
|
type = request.args.get('type')
|
||||||
|
sex = request.args.get('sex')
|
||||||
|
age_from = request.args.get('age-from')
|
||||||
|
options = dict()
|
||||||
|
options["type"] = PetService.get_pets_kind_options(type)
|
||||||
|
options["sex"] = PetService.get_sex_options(sex)
|
||||||
|
options["age_from"] = PetService.get_age_from_options(age_from)
|
||||||
|
return options
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_pets_kind_options(selected_kind=None):
|
||||||
|
pet_kinds = db.session.execute(db.select(PetKind)).scalars()
|
||||||
|
options = []
|
||||||
|
options.append({
|
||||||
|
"value": "",
|
||||||
|
"text": "Type",
|
||||||
|
"selected": selected_kind == None
|
||||||
|
})
|
||||||
|
options.append({
|
||||||
|
"value": "0",
|
||||||
|
"text": "Any",
|
||||||
|
"selected": selected_kind == "0"
|
||||||
|
})
|
||||||
|
for pet_kind in pet_kinds:
|
||||||
|
options.append({
|
||||||
|
"value": str(pet_kind.id),
|
||||||
|
"text": pet_kind.name,
|
||||||
|
"selected": selected_kind == str(pet_kind.id)
|
||||||
|
})
|
||||||
|
PetService.selected_safeguard(selected_kind,options[0],len(options))
|
||||||
|
return options
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_age_from_options(selected_year=None):
|
||||||
|
options = []
|
||||||
|
options.append({
|
||||||
|
"value": "0",
|
||||||
|
"text": "0",
|
||||||
|
"selected": selected_year == "0" or selected_year == None
|
||||||
|
})
|
||||||
|
for i in range(1,7):
|
||||||
|
options.append({
|
||||||
|
"value": str(i),
|
||||||
|
"text": str(i),
|
||||||
|
"selected": selected_year == str(i)
|
||||||
|
})
|
||||||
|
options.append({
|
||||||
|
"value": "7",
|
||||||
|
"text": "7+",
|
||||||
|
"selected": selected_year == "7"
|
||||||
|
})
|
||||||
|
PetService.selected_safeguard(selected_year,options[0],len(options))
|
||||||
|
return options
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_sex_options(selected_sex=None):
|
||||||
|
options = [
|
||||||
|
{
|
||||||
|
"value": "",
|
||||||
|
"text": "Sex",
|
||||||
|
"selected": selected_sex == None
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "0",
|
||||||
|
"text": "Any",
|
||||||
|
"selected": selected_sex == "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "1",
|
||||||
|
"text": "Female",
|
||||||
|
"selected": selected_sex == "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "2",
|
||||||
|
"text": "Male",
|
||||||
|
"selected": selected_sex == "2"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
PetService.selected_safeguard(selected_sex,options[0],len(options))
|
||||||
|
return options
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def selected_safeguard(selected_arg, select_default, options_length):
|
||||||
|
if selected_arg is not isinstance(selected_arg, int) or selected_arg < 0 or selected_arg > len(options_length):
|
||||||
|
select_default["selected"] = True
|
||||||
47
app/static/js/pets-filter.js
Normal file
47
app/static/js/pets-filter.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
(() => {
|
||||||
|
'use strict'
|
||||||
|
const fromYearsFilter = document.querySelector('#from-years-filter');
|
||||||
|
const toYearsFilter = document.querySelector('#to-years-filter');
|
||||||
|
const toTextSpan = document.querySelector('#to-text');
|
||||||
|
fromYearsFilter.addEventListener('change', updateToYearsFilter);
|
||||||
|
fromYearsFilter.dispatchEvent(new Event('change'));
|
||||||
|
updateToYearsFilterWithQueryParams();
|
||||||
|
|
||||||
|
function updateToYearsFilter(event) {
|
||||||
|
const startYear = event.target.value;
|
||||||
|
toYearsFilter.replaceChildren(null);
|
||||||
|
if(startYear == 7) {
|
||||||
|
toYearsFilter.removeAttribute('name');
|
||||||
|
toYearsFilter.classList.add('d-none');
|
||||||
|
toTextSpan.classList.add('d-none');
|
||||||
|
} else {
|
||||||
|
toYearsFilter.setAttribute('name', 'age-to');
|
||||||
|
toYearsFilter.classList.remove('d-none');
|
||||||
|
toTextSpan.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = "7";
|
||||||
|
option.innerText = "7+";
|
||||||
|
option.selected = true;
|
||||||
|
toYearsFilter.appendChild(option);
|
||||||
|
|
||||||
|
for(let i = 6; i > startYear; i--) {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
const value = i.toString();
|
||||||
|
option.value = value;
|
||||||
|
option.innerText = value;
|
||||||
|
toYearsFilter.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateToYearsFilterWithQueryParams() {
|
||||||
|
let address = window.location.search;
|
||||||
|
let parameterList = new URLSearchParams(address)
|
||||||
|
let ageToParam = parameterList.get('age-to');
|
||||||
|
for (const option of toYearsFilter.children) {
|
||||||
|
if (option.value === ageToParam) option.setAttribute("selected","")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
||||||
77
app/templates/pets/index.html
Normal file
77
app/templates/pets/index.html
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
{% extends "layout/layout.html" %}
|
||||||
|
{% block title %} Home {% endblock %}
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="pets container">
|
||||||
|
<div class="row px-2">
|
||||||
|
<div class="card py-4 my-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<form action="" method="get">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-3 col-lg-3 mb-3 mb-lg-0">
|
||||||
|
<select aria-label="type select field" class="form-select" name="type">
|
||||||
|
{% for option in options['type'] %}
|
||||||
|
<option
|
||||||
|
{% if loop.index0 == 0 %} {{"disabled"}} {% endif %}
|
||||||
|
value="{{option['value']}}"
|
||||||
|
{%if option['selected'] %} {{"selected"}} {% endif %}
|
||||||
|
>{{option['text']}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-3 col-lg-3 mb-3 mb-lg-0">
|
||||||
|
<select aria-label="sex select field" class="form-select" name="sex">
|
||||||
|
{% for option in options['sex'] %}
|
||||||
|
<option
|
||||||
|
{% if loop.index0 == 0 %} {{"disabled"}} {% endif %}
|
||||||
|
value="{{option['value']}}"
|
||||||
|
{%if option['selected'] %} {{"selected"}} {% endif %}
|
||||||
|
>{{option['text']}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-4 mb-3 mb-lg-0">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">From</span>
|
||||||
|
<select
|
||||||
|
aria-label="from years select field"
|
||||||
|
class="form-select"
|
||||||
|
id="from-years-filter"
|
||||||
|
name="age-from"
|
||||||
|
>
|
||||||
|
{% for option in options["age_from"] %}
|
||||||
|
<option
|
||||||
|
value="{{option['value']}}"
|
||||||
|
{%if option['selected'] %} {{"selected"}} {% endif %}
|
||||||
|
>{{option['text']}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<span class="input-group-text" id="to-text">to</span>
|
||||||
|
<select
|
||||||
|
aria-label="years to select field"
|
||||||
|
class="form-select"
|
||||||
|
id="to-years-filter"
|
||||||
|
name="age-to"
|
||||||
|
>
|
||||||
|
<option value="7" default>7+</option>
|
||||||
|
</select>
|
||||||
|
<span class="input-group-text">yrs old</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-12 col-lg-2">
|
||||||
|
<button class="btn btn-outline-primary w-100" type="submit">Filter</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h1>This is pets!</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="{{ url_for('static', filename='js/pets-filter.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user