Skip to content

Commit

Permalink
Add search day-care funconallity to dog-owner homepage.
Browse files Browse the repository at this point in the history
The dog-owner user can search for day-care that relevant for him.
If the user didnt search for day-care he will see all Day-Cares in the application.

Signed-off-by: tamirmatok <[email protected]>
  • Loading branch information
tamirmatok committed May 2, 2022
1 parent bd7bf3a commit 89ae30a
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 36 deletions.
31 changes: 31 additions & 0 deletions daycare/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from django import forms
from .models import DayCare, Area
from django.db.models import Max, Min


class DayCareSearchForm(forms.Form):
min_price = DayCare.objects.all().aggregate(Min('price_per_day')).get('price_per_day__min')
max_price = DayCare.objects.all().aggregate(Max('price_per_day')).get('price_per_day__max')
start_date = forms.DateField(required=True, label=' Start date',
widget=forms.widgets.DateInput(attrs={'class': 'form-control', 'type': 'date'}))
end_date = forms.DateField(required=True, label=' End date',
widget=forms.widgets.DateInput(attrs={'class': 'form-control', 'type': 'date'}))

area = forms.ChoiceField(required=False, label='Area',
choices=(Area.choices + [('', 'All'), ]), initial="")
city = forms.CharField(required=False, label='City')
name = forms.CharField(required=False, label='Day care name')
price_per_day = forms.ChoiceField(required=False, label='Max price',
choices=((str(x), x) for x in range(min_price, max_price + 11, 10)),
initial=str(max_price))

def clean(self):
cleaned_data = super().clean()
start_date = cleaned_data.get("start_date")
end_date = cleaned_data.get("end_date")

if start_date and end_date:
if end_date < start_date:
self._errors['end_date'] = self.error_class(["End date should be greater!"])

return cleaned_data
60 changes: 46 additions & 14 deletions dogowner/templates/dogowner/dog_owner_homepage.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,58 @@
{% extends "main/base_template.html" %}
{% load crispy_forms_tags %}
{% load static %}

{% block stylesheets %}
<link rel="stylesheet" href="{% static 'CSS/dog_owner_homepage.css' %}">
{% endblock %}

{% block content %}
<div class="row row-cols-1 g-3 cards">
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
{% for daycare in daycares %}
<div class="card">
<img src="{{ daycare.get_daycare_primary_image_url }}" alt="{{ daycare.name }} image" class="card-img-top">
<div class="card-body">
<div style="display: flex; flex-direction: row">
<h5 class="card-title">{{ daycare.name }}</h5>

<div class="row">
<form method='POST' action=''>{% csrf_token %}
<div class="col-4" id="searchBoxArea">
<span>Search for daycare:</span>
<div class="form-group">
{{ form.start_date|as_crispy_field }}
</div>
<div class="form-group">
{{ form.end_date|as_crispy_field }}
</div>
<div class="form-group">
{{ form.price_per_day|as_crispy_field }}
</div>
<div class="form-group">
{{ form.area|as_crispy_field }}
</div>
<div class="form-group">
{{ form.city|as_crispy_field }}
</div>
<div class="form-group">
{{ form.name|as_crispy_field }}
</div>
<input type="submit" value='Search' style="height:30px;width:70px">
</div>
</form>
<div class="col-10">
<span id="searchResult">Found {{ day_care_queryset.count }} results for your dog!</span>
<div class="cards">
{% for daycare in day_care_queryset %}
<div class="card">
<img src="{{ daycare.get_daycare_primary_image_url }}" alt="{{ daycare.name }} image" class="card-img-top">
<div class="card-body">
<div style="display: flex; flex-direction: row">
<h5 class="card-title">{{ daycare.name }}</h5>
</div>
<p class="card-text">{{ daycare.area | truncatechars:20 }}</p>
<p class="card-text">{{ daycare.city | truncatechars:20 }}</p>
<p class="card-text">{{ daycare.price_per_day | truncatechars:20 }}</p>
<p class="card-text">{{ daycare.description | truncatechars:35}}</p>
<a href="/daycare/{{ daycare.id }}" class="btn btn-warning">Daycare Profile</a>
</div>
</div>
{% endfor %}
</div>
</div>
<p class="card-text">{{ daycare.description | truncatechars:250 }}</p>
<a href="/daycare/{{ daycare.id }}" class="btn btn-primary">Daycare Profile</a>
</div>
</div>
{% endfor %}
</div>
</div>

{% endblock %}
27 changes: 26 additions & 1 deletion dogowner/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from daycare.models import DayCare
from daycare.forms import DayCareSearchForm
from orders.models import Order
import datetime


@login_required()
def dog_owner_home(request):
title = 'Search for day-cares'
form = DayCareSearchForm(request.POST or None)
day_care_queryset = DayCare.objects.all()
context = {
'daycares': DayCare.objects.all(),
'day_care_queryset': day_care_queryset,
'form': form
}
if request.method == 'POST':
if form.is_valid():
day_care_queryset = DayCare.objects.filter(area__startswith=form['area'].value(),
city__icontains=form['city'].value(),
name__icontains=form['name'].value(),
price_per_day__lte=form['price_per_day'].value())
for day_care in day_care_queryset:
start_date = datetime.date.fromisoformat(form['start_date'].value())
end_date = datetime.date.fromisoformat(form['end_date'].value())
if not Order.day_care_is_available_on_dates(day_care, start_date, end_date):
day_care_queryset.delete(day_care)

context = {
'title': title,
'day_care_queryset': day_care_queryset,
'form': form
}

return render(request, 'dogowner/dog_owner_homepage.html', context)
1 change: 0 additions & 1 deletion main/templates/main/base_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
{% if request.user.is_authenticated %}
<li class="nav-item"><a class="nav-link text-white" href="">Profile</a></li>
<li class="nav-item"><a class="nav-link text-white" href="">Orders</a></li>
<li class="nav-item"><a class="nav-link text-white" href="">Search</a></li>
<li class="nav-item"><a class="nav-link text-white" href="">Chats</a></li>
{% endif %}
<li class="nav-item"><a class="nav-link text-white" href="/about">About</a></li>
Expand Down
43 changes: 43 additions & 0 deletions main/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
from dogowner.models import DogOwner
from daycare.models import DayCare


@pytest.fixture
Expand Down Expand Up @@ -87,3 +88,45 @@ def test_unlogged_user_access_to_homepage(self, client):
response = client.get("/homepage/")
assert response.status_code == 302
assert response['Location'] == '/login/?next=/homepage/'


@pytest.mark.django_db
class TestDogOwnerHomePageView:
def test_dog_owner_present_all_day_cares_at_entrypoint(self, client, create_dog_owner_user):
client.force_login(user=create_dog_owner_user.user)
response = client.get("/homepage/")
day_care_queryset = response.context['day_care_queryset']
assert day_care_queryset.count() == DayCare.objects.all().count()

def test_successful_dog_owner_search_for_day_care(self, client, create_dog_owner_user):
client.force_login(user=create_dog_owner_user.user)
search_form = {'area': "center",
'city': "tel aviv",
'price_per_day': 800,
'name': "",
'start_date': "25/05/2022",
'end_date': "28/05/2022",
}
response = client.post('/homepage/', search_form, follow=True)
day_care_queryset = response.context['day_care_queryset']
for day_care in DayCare.objects.all():
if day_care.price_per_day <= 800 and day_care.area.lower() == 'center'\
and day_care.city.lower() == 'tel aviv':
assert day_care in day_care_queryset
assert response.context['form_show_errors']

def test_search_for_day_care_with_start_date_greater_than_end_date_show_error_and_present_all_daycares(
self, client,create_dog_owner_user):
client.force_login(user=create_dog_owner_user.user)
search_form = {'area': "center",
'city': "tel aviv",
'price_per_day': 800,
'name': "",
'start_date': "28/05/2022",
'end_date': "25/05/2022",
}
response = client.post('/homepage/', search_form, follow=True)
day_care_queryset = response.context['day_care_queryset']
for day_care in DayCare.objects.all():
assert day_care in day_care_queryset
assert response.context['form_show_errors']
59 changes: 39 additions & 20 deletions static/CSS/dog_owner_homepage.css
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
.cards
{
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: 50px;
justify-content: center;
align-items: center;
float:left;
margin: 0 0 0 5em;
position:relative;
width:100%;
}

.row
{
height: 30rem;
width: 120rem;
margin-left: 200px;
#searchResult {
font-weight:bold;
position: relative;
left: 6.3em;
top:30px;
}

.card
{
width: 18.5%;
width: 330px;
height: 30rem;
margin: 60px 60px 0 60px;
max-width: 100%;
}

.card-body
{
display: flex;
flex-direction: column;
float:left;
margin: 60px 20px 0 20px;
}

.card-body .btn
Expand All @@ -39,3 +31,30 @@
{
height: 200px;
}

#searchBoxArea {
background-color:#dcdcdc;
left:5em;
top: 5.2em;
max-width:100%;
padding: 2em 2em 2em 2em;
}

#searchBoxArea span {
font-weight:bold;
font-size:18px;
color:#3e3e3e;
padding: 5px 0 1em 0;
float:left;
}

#searchBoxArea input[type="submit"] {
background-color:#3e3e3e;
border: 0;
border-radius:12px;
color:#FFF;
}

#searchBoxArea input[type="submit"]:hover {
background-color:#1e1e1e;
}

0 comments on commit 89ae30a

Please sign in to comment.