diff --git a/daycare/forms.py b/daycare/forms.py new file mode 100644 index 0000000..3e8d3d0 --- /dev/null +++ b/daycare/forms.py @@ -0,0 +1,25 @@ +from django import forms +from .models import Area + + +class DayCareSearchForm(forms.Form): + 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.IntegerField(required=False, label='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 diff --git a/dogowner/templates/dogowner/dog_owner_homepage.html b/dogowner/templates/dogowner/dog_owner_homepage.html index 8434a05..cb6ff3d 100644 --- a/dogowner/templates/dogowner/dog_owner_homepage.html +++ b/dogowner/templates/dogowner/dog_owner_homepage.html @@ -1,4 +1,5 @@ {% extends "main/base_template.html" %} +{% load crispy_forms_tags %} {% load static %} {% block stylesheets %} @@ -6,21 +7,51 @@ {% endblock %} {% block content %} -
-
- {% for daycare in daycares %} -
- {{ daycare.name }} image -
-
-
{{ daycare.name }}
+ +
+
{% csrf_token %} +
+ Search for daycare: +
+ {{ form.start_date|as_crispy_field }} +
+
+ {{ form.end_date|as_crispy_field }} +
+
+ {{ form.price_per_day|as_crispy_field }} +
+
+ {{ form.area|as_crispy_field }} +
+
+ {{ form.city|as_crispy_field }} +
+
+ {{ form.name|as_crispy_field }} +
+ +
+
+
+ Found {{ day_care_queryset.count }} results for your dog! +
+ {% for daycare in day_care_queryset %} +
+ {{ daycare.name }} image +
+
+
{{ daycare.name }}
+
+

{{ daycare.area | truncatechars:20 }}

+

{{ daycare.city | truncatechars:20 }}

+

{{ daycare.price_per_day | truncatechars:20 }}

+

{{ daycare.description | truncatechars:35}}

+ Daycare Profile +
+
+ {% endfor %} +
-

{{ daycare.description | truncatechars:250 }}

- Daycare Profile -
- {% endfor %} -
-
- -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/dogowner/views.py b/dogowner/views.py index 53333ed..7fc3285 100644 --- a/dogowner/views.py +++ b/dogowner/views.py @@ -1,11 +1,27 @@ 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 @login_required() def dog_owner_home(request): + form = DayCareSearchForm(request.POST or None) + day_care_queryset = DayCare.objects.all() + if request.method == 'POST': + if form.is_valid(): + filter_day_cares = 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()) + + available_day_cares = Order.get_all_day_cares_available_on_dates(form['start_date'].value(), + form['end_date'].value()) + day_care_queryset = filter_day_cares.intersection(available_day_cares) + context = { - 'daycares': DayCare.objects.all(), + 'day_care_queryset': day_care_queryset, + 'form': form } return render(request, 'dogowner/dog_owner_homepage.html', context) diff --git a/main/templates/main/base_template.html b/main/templates/main/base_template.html index b045033..87360af 100644 --- a/main/templates/main/base_template.html +++ b/main/templates/main/base_template.html @@ -26,7 +26,6 @@ {% if request.user.is_authenticated %} - {% endif %} diff --git a/main/tests.py b/main/tests.py index 3d3107c..8a2547a 100644 --- a/main/tests.py +++ b/main/tests.py @@ -1,5 +1,7 @@ import pytest +from dogowner.models import DogOwner from daycare.models import DayCare +from orders.models import Order @pytest.mark.django_db @@ -72,8 +74,66 @@ def test_unlogged_user_access_to_homepage(self, client): assert response.status_code == 302 assert response['Location'] == '/login/?next=/homepage/' - def test_dog_owner_homepage_is_visible_for_dog_owner(self, client, create_dog_owner_user): + +@pytest.mark.django_db +class TestDogOwnerHomePageView: + def test_dog_owner_homepage_present_all_daycares(self, client, create_dog_owner_user): client.force_login(user=create_dog_owner_user.user) response = client.get("/homepage/") assert response.status_code == 200 - assert list(response.context['daycares']) == list(DayCare.objects.all()) + assert set(response.context['day_care_queryset']) == set(DayCare.objects.all()) + + def test_daycare_not_appears_in_search_after_reduce_capacity_on_dates_to_0(self, client, + create_dog_owner_user, + create_daycare_user): + search_form = {'area': "", + 'city': "", + 'price_per_day': 100, + 'name': "", + 'start_date': "2022-05-03", + 'end_date': "2022-05-08", + } + daycare_user = create_daycare_user + client.force_login(user=create_dog_owner_user.user) + response = client.post('/homepage/', search_form, follow=True) + day_care_queryset = response.context['day_care_queryset'] + assert daycare_user in day_care_queryset + + for _ in range(daycare_user.capacity): + Order.create(dog_owner_id=DogOwner.objects.get(id=1), daycare_id=daycare_user, + start_date="2022-05-02", end_date="2022-08-02", price_per_day=100).approve_order() + response = client.post('/homepage/', search_form, follow=True) + assert daycare_user not in response.context['day_care_queryset'] + + 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': "C", + 'city': "tel aviv", + 'price_per_day': 800, + 'name': "", + 'start_date': "2022-05-03", + 'end_date': "2022-05-08", + } + response = client.post('/homepage/', search_form, follow=True) + day_care_queryset = response.context['day_care_queryset'] + available_day_cares = Order.get_all_day_cares_available_on_dates("2022-05-03", "2022-05-08") + filter_day_cares = DayCare.objects.filter(area__startswith='C', + city__icontains="tel aviv", + price_per_day__lte=800) + expected_queryset = available_day_cares.intersection(filter_day_cares) + assert set(day_care_queryset) == set(expected_queryset) + + 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': "C", + 'city': "tel aviv", + 'price_per_day': 800, + 'name': "", + 'start_date': "2022-05-03", + 'end_date': "2022-05-01", + } + response = client.post('/homepage/', search_form, follow=True) + day_care_queryset = response.context['day_care_queryset'] + assert set(day_care_queryset) == set(DayCare.objects.all()) + assert response.context['form']._errors['end_date'] diff --git a/static/CSS/dog_owner_homepage.css b/static/CSS/dog_owner_homepage.css index 7c77f17..092071b 100644 --- a/static/CSS/dog_owner_homepage.css +++ b/static/CSS/dog_owner_homepage.css @@ -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 @@ -38,4 +30,31 @@ .card-img-top { height: 200px; -} \ No newline at end of file +} + +#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; +}