Update all
@ -10,23 +10,17 @@ class OfferCreateForm(forms.ModelForm):
|
|||||||
price = forms.DecimalField(min_value=0.01,max_digits=10, decimal_places=2)
|
price = forms.DecimalField(min_value=0.01,max_digits=10, decimal_places=2)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Offer
|
model = Offer
|
||||||
fields = ('title','category','price','DMC','Places_to_sleep','cooker','fridge', 'microwave', 'Webasto', 'auto_temp_control', 'water_level_indicator', 'battery_level', 'photovoltaic_panels', 'gearbox', 'tempomat')
|
fields = ('title','category','price','description','DMC','Places_to_sleep','cooker','fridge', 'microwave', 'Webasto', 'auto_temp_control', 'water_level_indicator', 'battery_level', 'photovoltaic_panels', 'gearbox', 'tempomat')
|
||||||
|
|
||||||
class OfferImageCreateForm(forms.ModelForm):
|
class OfferImageCreateForm(forms.ModelForm):
|
||||||
image = forms.ImageField()
|
image = forms.ImageField(required = True)
|
||||||
|
main_image = forms.BooleanField(initial=False, required=False)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Image_offer
|
model = Image_offer
|
||||||
fields = ('image','main_image')
|
fields = ('image','main_image')
|
||||||
|
|
||||||
class BaseOfferImageFormSet(BaseFormSet):
|
class BaseOfferImageFormSet(BaseFormSet):
|
||||||
def clean(self):
|
pass
|
||||||
if any(self.errors):
|
|
||||||
return
|
|
||||||
count = 0
|
|
||||||
for form in self.forms:
|
|
||||||
if form.cleaned_data['main_image']:
|
|
||||||
count += 1
|
|
||||||
if count > 1:
|
|
||||||
raise forms.ValidationError(_("Mozna ustawić tylko jedno zdjecie jako miniaturka."))
|
|
||||||
|
|
||||||
OfferImageFormSet = formset_factory(OfferImageCreateForm,formset = BaseOfferImageFormSet)
|
OfferImageFormSet = formset_factory(OfferImageCreateForm,formset = BaseOfferImageFormSet)
|
@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.3 on 2021-01-12 17:44
|
# Generated by Django 3.1.3 on 2021-02-06 00:07
|
||||||
|
|
||||||
import camper.models
|
import camper.models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -15,12 +15,6 @@ class Migration(migrations.Migration):
|
|||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
|
||||||
name='AlbumImage',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Offer_Category',
|
name='Offer_Category',
|
||||||
fields=[
|
fields=[
|
||||||
@ -40,6 +34,7 @@ class Migration(migrations.Migration):
|
|||||||
('status', models.CharField(choices=[('Active', 'Active offer'), ('Inactive', 'Inactive offer'), ('Verification', 'Waiting for verication'), ('Blocked', 'Blocked Offer')], default='Inactive', max_length=32)),
|
('status', models.CharField(choices=[('Active', 'Active offer'), ('Inactive', 'Inactive offer'), ('Verification', 'Waiting for verication'), ('Blocked', 'Blocked Offer')], default='Inactive', max_length=32)),
|
||||||
('title', models.CharField(default='Tytuł oferty', max_length=50, verbose_name='Title')),
|
('title', models.CharField(default='Tytuł oferty', max_length=50, verbose_name='Title')),
|
||||||
('slug', models.SlugField(default='', editable=False, max_length=70, unique=True)),
|
('slug', models.SlugField(default='', editable=False, max_length=70, unique=True)),
|
||||||
|
('description', models.TextField(default='', max_length=1000)),
|
||||||
('price', models.DecimalField(decimal_places=2, max_digits=10)),
|
('price', models.DecimalField(decimal_places=2, max_digits=10)),
|
||||||
('DMC', models.CharField(choices=[('B', 'Do 3.5 tony.'), ('C', 'Między 3.5 a 7.5 tony'), ('C1', 'Powyzej 7.5 tony')], default='B', max_length=32)),
|
('DMC', models.CharField(choices=[('B', 'Do 3.5 tony.'), ('C', 'Między 3.5 a 7.5 tony'), ('C1', 'Powyzej 7.5 tony')], default='B', max_length=32)),
|
||||||
('Places_to_sleep', models.IntegerField(default=2)),
|
('Places_to_sleep', models.IntegerField(default=2)),
|
||||||
@ -53,7 +48,6 @@ class Migration(migrations.Migration):
|
|||||||
('photovoltaic_panels', models.BooleanField(default=False)),
|
('photovoltaic_panels', models.BooleanField(default=False)),
|
||||||
('gearbox', models.CharField(choices=[('Manual', 'Skrzynia manualna'), ('Automat', 'Skrzynia automatyczna')], default='Manual', max_length=32)),
|
('gearbox', models.CharField(choices=[('Manual', 'Skrzynia manualna'), ('Automat', 'Skrzynia automatyczna')], default='Manual', max_length=32)),
|
||||||
('tempomat', models.BooleanField(default=False)),
|
('tempomat', models.BooleanField(default=False)),
|
||||||
('album', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='album', to='camper.albumimage', verbose_name='')),
|
|
||||||
('category', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='camper.offer_category')),
|
('category', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='camper.offer_category')),
|
||||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
@ -66,7 +60,7 @@ class Migration(migrations.Migration):
|
|||||||
name='Image_offer',
|
name='Image_offer',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('image', models.ImageField(blank=True, null=True, upload_to=camper.models._upload_path)),
|
('image', models.ImageField(upload_to=camper.models._upload_path)),
|
||||||
('main_image', models.BooleanField(default=False)),
|
('main_image', models.BooleanField(default=False)),
|
||||||
('offer', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='images', to='camper.offer', verbose_name='')),
|
('offer', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='images', to='camper.offer', verbose_name='')),
|
||||||
],
|
],
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# Generated by Django 3.1.3 on 2021-01-12 17:48
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('camper', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='offer',
|
|
||||||
name='album',
|
|
||||||
),
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name='AlbumImage',
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 3.1.3 on 2021-01-24 16:53
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('camper', '0002_auto_20210112_1748'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='offer',
|
|
||||||
name='description',
|
|
||||||
field=models.TextField(default='', max_length=1000),
|
|
||||||
),
|
|
||||||
]
|
|
BIN
vagus/camper/migrations/__pycache__/0004_auto_20210202_1834.cpython-37.pyc
Executable file
BIN
vagus/camper/migrations/__pycache__/0005_auto_20210202_1834.cpython-37.pyc
Executable file
BIN
vagus/camper/migrations/__pycache__/0006_auto_20210204_1352.cpython-37.pyc
Executable file
@ -85,7 +85,7 @@ class Offer(models.Model):
|
|||||||
return super(Offer, self).save(*args, **kwargs)
|
return super(Offer, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('detail_offer_page', kwargs = {'slug': self.slug })
|
return reverse('offer_detail', kwargs = {'slug': self.slug })
|
||||||
|
|
||||||
|
|
||||||
def _upload_path(instance,filename):
|
def _upload_path(instance,filename):
|
||||||
|
@ -7,8 +7,10 @@ from django.conf.urls.static import static
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
re_path('add-offer/', views.CreateOffer.as_view(), name='create_offer'),
|
re_path('add-offer/', views.CreateOffer.as_view(), name='create_offer'),
|
||||||
#path('offer/<slug:slug>', views.OfferDetailView.as_view(), name = 'offer_detail_view'),
|
path('offer/<slug:slug>', views.OfferDetailView.as_view(), name = 'offer_detail'),
|
||||||
|
path('update-offer/<slug:slug>',views.EditOffer.as_view(), name = 'update-offer'),
|
||||||
path('offers/', views.OfferListView.as_view(), name = 'list_offers'),
|
path('offers/', views.OfferListView.as_view(), name = 'list_offers'),
|
||||||
|
#path('offer/<slug:slug>', views.OfferDetailView.as_view(), name = 'detail_offer_page'),
|
||||||
path('', views.Home.as_view(), name='homepage')
|
path('', views.Home.as_view(), name='homepage')
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,21 +28,12 @@ def check_user_is_owner(request):
|
|||||||
else:
|
else:
|
||||||
render (request,'upgrade-to-onwer.html')
|
render (request,'upgrade-to-onwer.html')
|
||||||
|
|
||||||
#def check_offer_belong_to_user(request):
|
|
||||||
# if request.check_user_is_owner() == True:
|
|
||||||
# if offer.author == request.users.id:
|
|
||||||
# return True
|
|
||||||
# else:
|
|
||||||
# raise ValueError("To chyba nie twoje :)")
|
|
||||||
|
|
||||||
# if check_users_is_owner == True:
|
|
||||||
|
|
||||||
# Create your views here.
|
|
||||||
|
|
||||||
class CreateOffer(CreateView):
|
class CreateOffer(CreateView):
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def get(self, request,*args,**kwargs):
|
def get(self, request,*args,**kwargs):
|
||||||
|
if check_user_is_owner(request) == True or request.user.is_staff == True:
|
||||||
form = OfferCreateForm()
|
form = OfferCreateForm()
|
||||||
formset = OfferImageFormSet()
|
formset = OfferImageFormSet()
|
||||||
context = {
|
context = {
|
||||||
@ -50,8 +41,10 @@ class CreateOffer(CreateView):
|
|||||||
'formset': formset,
|
'formset': formset,
|
||||||
}
|
}
|
||||||
#if check_user_is_owner(request) == True or request.Base_user.is_staff == True:
|
#if check_user_is_owner(request) == True or request.Base_user.is_staff == True:
|
||||||
|
|
||||||
return render(request,'offer/add-offer.html', context)
|
return render(request,'offer/add-offer.html', context)
|
||||||
|
else:
|
||||||
|
messages.error(request, 'Nie masz uprawnień!')
|
||||||
|
return redirect('/') #Redirect to login / register page for owner
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def post(self,request,*args,**kwargs):
|
def post(self,request,*args,**kwargs):
|
||||||
@ -64,7 +57,6 @@ class CreateOffer(CreateView):
|
|||||||
offer.created_by = request.user
|
offer.created_by = request.user
|
||||||
offer.status = 'Verification'
|
offer.status = 'Verification'
|
||||||
offer.save()
|
offer.save()
|
||||||
|
|
||||||
for photo in formset:
|
for photo in formset:
|
||||||
try:
|
try:
|
||||||
imageoffer = Image_offer(offer = offer,main_image = photo.cleaned_data['main_image'],image = photo.cleaned_data['image'])
|
imageoffer = Image_offer(offer = offer,main_image = photo.cleaned_data['main_image'],image = photo.cleaned_data['image'])
|
||||||
@ -74,7 +66,6 @@ class CreateOffer(CreateView):
|
|||||||
offer.save()
|
offer.save()
|
||||||
messages.error(request,'Dodaj zdjęcia aby przesłać ofertę do weryfikacji')
|
messages.error(request,'Dodaj zdjęcia aby przesłać ofertę do weryfikacji')
|
||||||
return redirect('/') #Redirect to offe-update-page or user's offers list
|
return redirect('/') #Redirect to offe-update-page or user's offers list
|
||||||
|
|
||||||
messages.success(request,'Oferta utworzona i przesłana do weryfikacji')
|
messages.success(request,'Oferta utworzona i przesłana do weryfikacji')
|
||||||
return redirect('/') #Redirect to offer page or user's offers list
|
return redirect('/') #Redirect to offer page or user's offers list
|
||||||
else:
|
else:
|
||||||
@ -91,8 +82,6 @@ class CreateOffer(CreateView):
|
|||||||
|
|
||||||
|
|
||||||
class EditOffer(UpdateView):
|
class EditOffer(UpdateView):
|
||||||
|
model = Offer
|
||||||
def get(self,request,*args, **kwargs):
|
template_name = 'offer/update-offer.html'
|
||||||
pass
|
fields = ('title','category','price','description','DMC','Places_to_sleep','cooker','fridge', 'microwave', 'Webasto', 'auto_temp_control', 'water_level_indicator', 'battery_level', 'photovoltaic_panels', 'gearbox', 'tempomat')
|
||||||
def post(self,request,*args,**kwargs):
|
|
||||||
pass
|
|
||||||
|
@ -2,28 +2,72 @@ from django.shortcuts import render,redirect, get_object_or_404
|
|||||||
from django.views.generic import (
|
from django.views.generic import (
|
||||||
ListView,
|
ListView,
|
||||||
DetailView,
|
DetailView,
|
||||||
View
|
View,
|
||||||
|
FormView,
|
||||||
|
CreateView,
|
||||||
)
|
)
|
||||||
from camper.models import Offer, Image_offer
|
from camper.models import Offer, Image_offer,Offer_Category
|
||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.core.paginator import Paginator ,EmptyPage, PageNotAnInteger
|
from django.core.paginator import Paginator ,EmptyPage, PageNotAnInteger
|
||||||
|
from reservation.forms import ReservationForm
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
|
from django.views.generic.edit import FormMixin
|
||||||
|
from reservation.models import Reservation
|
||||||
|
|
||||||
|
|
||||||
class Home(View):
|
class Home(View):
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
return render(request, 'index.html')
|
context = {}
|
||||||
|
offers= Offer.objects.filter(status = 'Active').order_by('-date_added')[:2]
|
||||||
|
context['offers'] = offers
|
||||||
|
return render(request,'home.html', context=context)
|
||||||
|
|
||||||
|
################################################
|
||||||
class OfferDetailView(DetailView):
|
class OfferDetailView(DetailView):
|
||||||
template_name = 'offer/offer-detail.html'
|
|
||||||
model = Offer
|
model = Offer
|
||||||
context_object_name = 'offer'
|
template_name = 'offer/offer-detail.html'
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
context = super(OfferDetailView,self).get_context_data(*args, **kwargs)
|
||||||
|
context.update({
|
||||||
|
'form': ReservationForm(),
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
@method_decorator(login_required)
|
||||||
|
def post(self,request,*args,**kwargs):
|
||||||
|
self.object = self.get_object(self.get_queryset())
|
||||||
|
form = ReservationForm(self.request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
reservation = form.save(commit = False)
|
||||||
|
reservation.user = request.user
|
||||||
|
reservation.offer = self.object
|
||||||
|
reservation.status = 'Confirmed'
|
||||||
|
reservation.save()
|
||||||
|
messages.success(request,'Twoja rezerwacja została potwierdzona.')
|
||||||
|
return redirect('/')
|
||||||
|
else:
|
||||||
|
context = self.get_context_data(**kwargs)
|
||||||
|
context.update({'form': ReservationForm()})
|
||||||
|
messages.error(request, 'Wprowadzone dane są nieprawidłowe.')
|
||||||
|
return render(request,'offer/offer-detail.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
################################################
|
||||||
|
|
||||||
class OfferListView(ListView):
|
class OfferListView(ListView):
|
||||||
model = Offer
|
model = Offer
|
||||||
template_name = 'offer/offers.html'
|
template_name = 'offer/offers.html'
|
||||||
context_object_name = 'active_offers_list'
|
context_object_name = 'active_offers_list'
|
||||||
paginate_by = 4
|
paginate_by = 4
|
||||||
|
allow_empty_first_page = True
|
||||||
ordering = ['-date_added']
|
ordering = ['-date_added']
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
BIN
vagus/media/ian-usher-Af1OMQpuN14-unsplash.jpg
Executable file
After Width: | Height: | Size: 1.1 MiB |
BIN
vagus/media/uploads/._default.png
Executable file
BIN
vagus/media/uploads/default.png
Executable file
After Width: | Height: | Size: 713 B |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 3.1 MiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 124 KiB |
BIN
vagus/media/uploads/offer-images/id-17/DSCF5544.jpg
Executable file
After Width: | Height: | Size: 287 KiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 173 KiB |
BIN
vagus/media/uploads/offer-images/id-24/DSCF5544.jpg
Executable file
After Width: | Height: | Size: 287 KiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 3.1 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 3.1 MiB |
After Width: | Height: | Size: 622 KiB |
After Width: | Height: | Size: 3.1 MiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 251 KiB |
After Width: | Height: | Size: 378 KiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 378 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 622 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 148 KiB |
444938
vagus/mysite.log
Executable file
@ -2,10 +2,23 @@ from django.contrib import admin
|
|||||||
from .models import Reservation
|
from .models import Reservation
|
||||||
from .forms import ReservationForm
|
from .forms import ReservationForm
|
||||||
|
|
||||||
class ReservationAdmin(admin.ModelAdmin):
|
|
||||||
list_display = ('__str__','offer','status')
|
|
||||||
ordering = ['reservation_start_date']
|
|
||||||
group_by = ['offer','user']
|
|
||||||
|
|
||||||
|
class CustomReservation(admin.ModelAdmin):
|
||||||
|
|
||||||
admin.site.register(Reservation, ReservationAdmin)
|
model = Reservation
|
||||||
|
|
||||||
|
list_display = ('created_date','user','offer','reservation_start_date','reservation_end_date','reservation_cost')
|
||||||
|
fieldsets = (
|
||||||
|
(None, {'fields': ('user','offer','reservation_start_date','reservation_end_date','status','message_to_owner',)}),
|
||||||
|
|
||||||
|
)
|
||||||
|
add_fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'classes': ('wide',),
|
||||||
|
'fields': ('user','offer','reservation_start_date','reservation_end_date','status',)}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
ordering = ('offer','user')
|
||||||
|
search_fields = ('offer','user')
|
||||||
|
|
||||||
|
admin.site.register(Reservation, CustomReservation)
|
@ -3,20 +3,24 @@ from .models import Reservation
|
|||||||
from camper.models import Offer
|
from camper.models import Offer
|
||||||
from users.models import Base_User
|
from users.models import Base_User
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from bootstrap_datepicker_plus import DatePickerInput
|
||||||
|
|
||||||
|
|
||||||
class ReservationForm(forms.ModelForm):
|
class ReservationForm(forms.ModelForm):
|
||||||
reservation_start_date = forms.DateField(required=True)
|
reservation_start_date = forms.DateField(
|
||||||
reservation_end_date = forms.DateField(required=True,)
|
widget=DatePickerInput(format='%m/%d/%Y')
|
||||||
|
)
|
||||||
|
reservation_end_date = forms.DateField(
|
||||||
|
widget=DatePickerInput(format='%m/%d/%Y')
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Reservation
|
model = Reservation
|
||||||
exclude = ('user',)
|
exclude = ('user','offer','status','reservation_cost')
|
||||||
|
fields = ['reservation_start_date','reservation_end_date','message_to_owner']
|
||||||
|
|
||||||
widget = {
|
|
||||||
'reservation_start_date': forms.DateInput(format =['%d/%m/%y']),
|
|
||||||
'reservation_end_date': forms.DateInput(format =['%d/%m/%y']),
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
class ReservationStatus(forms.ModelForm):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Reservation
|
||||||
|
fields = ['status']
|
@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.3 on 2021-01-14 00:40
|
# Generated by Django 3.1.3 on 2021-02-06 09:49
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
@ -11,8 +11,8 @@ class Migration(migrations.Migration):
|
|||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
('camper', '0001_initial'),
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
('camper', '0002_auto_20210112_1748'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
@ -20,11 +20,15 @@ class Migration(migrations.Migration):
|
|||||||
name='Reservation',
|
name='Reservation',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('reservation_start_date', models.DateField(default=django.utils.timezone.now)),
|
('reservation_start_date', models.DateField(default=django.utils.timezone.now)),
|
||||||
('reservation_end_date', models.DateField()),
|
('reservation_end_date', models.DateField()),
|
||||||
|
('reservation_cost', models.DecimalField(decimal_places=2, default=0, max_digits=12)),
|
||||||
|
('message_to_owner', models.TextField(blank=True, max_length=500, null=True)),
|
||||||
('status', models.CharField(choices=[('Confirmed', 'Rezerwacja potwierdzona'), ('Requsted', 'Oczekuję na potwierdzenie'), ('Cancelled', 'Anulowana'), ('In_progress', 'Trwająca rezerwacja')], max_length=50)),
|
('status', models.CharField(choices=[('Confirmed', 'Rezerwacja potwierdzona'), ('Requsted', 'Oczekuję na potwierdzenie'), ('Cancelled', 'Anulowana'), ('In_progress', 'Trwająca rezerwacja')], max_length=50)),
|
||||||
('offer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='camper.offer', verbose_name='')),
|
('slug', models.SlugField(default='', editable=False, max_length=255)),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='')),
|
('offer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='camper.offer', verbose_name='Offer')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
# Generated by Django 3.1.3 on 2021-01-15 00:37
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import django.utils.timezone
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('camper', '0002_auto_20210112_1748'),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
('reservation', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='reservation',
|
|
||||||
name='offer',
|
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='camper.offer', verbose_name='Offer'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='reservation',
|
|
||||||
name='reservation_start_date',
|
|
||||||
field=models.DateTimeField(default=django.utils.timezone.now),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='reservation',
|
|
||||||
name='user',
|
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User'),
|
|
||||||
),
|
|
||||||
]
|
|
18
vagus/reservation/migrations/0002_auto_20210206_1048.py
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.1.3 on 2021-02-06 10:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('reservation', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='reservation',
|
||||||
|
name='id',
|
||||||
|
field=models.AutoField(primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
]
|
@ -1,19 +0,0 @@
|
|||||||
# Generated by Django 3.1.3 on 2021-01-24 14:57
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.utils.timezone
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('reservation', '0002_auto_20210115_0037'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='reservation',
|
|
||||||
name='reservation_start_date',
|
|
||||||
field=models.DateField(default=django.utils.timezone.now),
|
|
||||||
),
|
|
||||||
]
|
|
BIN
vagus/reservation/migrations/__pycache__/0002_auto_20210206_0041.cpython-37.pyc
Executable file
BIN
vagus/reservation/migrations/__pycache__/0002_auto_20210206_1048.cpython-37.pyc
Executable file
BIN
vagus/reservation/migrations/__pycache__/0003_auto_20210206_0030.cpython-37.pyc
Executable file
BIN
vagus/reservation/migrations/__pycache__/0003_reservation_slug.cpython-37.pyc
Executable file
BIN
vagus/reservation/migrations/__pycache__/0004_auto_20210206_0030.cpython-37.pyc
Executable file
BIN
vagus/reservation/migrations/__pycache__/0004_auto_20210206_0946.cpython-37.pyc
Executable file
@ -6,23 +6,31 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import NON_FIELD_ERRORS
|
from django.core.exceptions import NON_FIELD_ERRORS
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django import forms
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.template.defaultfilters import slugify
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
|
||||||
STATUS = (
|
STATUS = (
|
||||||
('Confirmed',_('Rezerwacja potwierdzona')),
|
('Confirmed',_('Rezerwacja potwierdzona')),
|
||||||
('Requsted',_('Oczekuję na potwierdzenie')),
|
('Requsted',_('Oczekuję na potwierdzenie')),
|
||||||
('Cancelled',_('Anulowana')),
|
('Cancelled',_('Anulowana')),
|
||||||
('In_progress',_('Trwająca rezerwacja')),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Reservation(models.Model):
|
class Reservation(models.Model):
|
||||||
|
id = models.AutoField(primary_key= True)
|
||||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("User"), on_delete=models.CASCADE)
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("User"), on_delete=models.CASCADE)
|
||||||
offer = models.ForeignKey("camper.Offer", verbose_name=_("Offer"), on_delete=models.CASCADE)
|
offer = models.ForeignKey("camper.Offer", verbose_name=_("Offer"), on_delete=models.CASCADE)
|
||||||
|
created_date = models.DateTimeField(auto_now_add=True)
|
||||||
reservation_start_date = models.DateField(default = timezone.now,)
|
reservation_start_date = models.DateField(default = timezone.now,)
|
||||||
reservation_end_date = models.DateField()
|
reservation_end_date = models.DateField()
|
||||||
|
reservation_cost = models.DecimalField(max_digits=12,default=0,decimal_places=2)
|
||||||
|
message_to_owner = models.TextField(max_length=500, blank = True, null = True)
|
||||||
status = models.CharField(choices = STATUS, max_length = 50)
|
status = models.CharField(choices = STATUS, max_length = 50)
|
||||||
|
slug = models.SlugField(max_length=255,editable = False, default='', unique = False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s (%s to %s)" % (self.user.email,
|
return "%s (%s to %s)" % (self.user.email,
|
||||||
@ -30,13 +38,38 @@ class Reservation(models.Model):
|
|||||||
"%Y/%m/%d"),
|
"%Y/%m/%d"),
|
||||||
self.reservation_end_date.strftime(
|
self.reservation_end_date.strftime(
|
||||||
"%Y/%m/%d"),)
|
"%Y/%m/%d"),)
|
||||||
|
@property
|
||||||
|
def get_total_cost(self):
|
||||||
|
diff_days = self.reservation_end_date - self.reservation_start_date
|
||||||
|
self.reservation_cost = diff_days.days * self.offer.price
|
||||||
|
return self.reservation_cost
|
||||||
|
|
||||||
def clean(self):
|
def clean(self,*args,**kwargs):
|
||||||
errors = {}
|
errors = {}
|
||||||
|
today_date = timezone.now().date()
|
||||||
|
if self.created_date != None:
|
||||||
|
if self.reservation_start_date < today_date:
|
||||||
|
errors['reservation_start_date'] = "Rezerwacja nie moze rozpoczynać sie w przeszłości"
|
||||||
if self.reservation_end_date < self.reservation_start_date:
|
if self.reservation_end_date < self.reservation_start_date:
|
||||||
errors['reservation_end_date'] = "Data zakończenia wynajmu nie moze byc data wczesniejsza od daty rozpoczecia."
|
errors['reservation_end_date'] = "Data zakończenia wynajmu nie moze byc data wczesniejsza / równa od daty rozpoczecia."
|
||||||
|
if self.reservation_end_date == self.reservation_start_date:
|
||||||
|
errors['reservation_end_date'] = "Wynajem nie moze kończyc sie w dniu rozpoczecia wynajmu."
|
||||||
|
if errors:
|
||||||
|
raise forms.ValidationError(errors)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("reservation_detail", kwargs={"slug": self.slug})
|
||||||
|
|
||||||
|
|
||||||
|
def save(self,*args,**kwargs):
|
||||||
|
errors = {}
|
||||||
filter_params = dict(reservation_end_date__lte=self.reservation_end_date, reservation_start_date__gte=self.reservation_start_date,offer =self.offer)
|
filter_params = dict(reservation_end_date__lte=self.reservation_end_date, reservation_start_date__gte=self.reservation_start_date,offer =self.offer)
|
||||||
if Reservation.objects.filter(**filter_params).exists():
|
if Reservation.objects.filter(**filter_params):
|
||||||
errors[NON_FIELD_ERRORS] = "Kamper w tym okresie jest juz zarezerwowany."
|
errors[NON_FIELD_ERRORS] = "Kamper w tym okresie jest juz zarezerwowany."
|
||||||
raise ValidationError(errors)
|
if errors:
|
||||||
|
raise forms.ValidationError(errors)
|
||||||
|
else:
|
||||||
|
self.slug = slugify(f'{self.offer.title}-{self.id}-/{self.reservation_start_date}-{self.reservation_end_date}')
|
||||||
|
return super(Reservation,self).save(*args,**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,28 +7,3 @@ from users.models import Base_User
|
|||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
||||||
class ReservationCreate(TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
testauthor = Base_User.objects.create(email ='test2@vagus.pl', password = '13test45')
|
|
||||||
testoffer = Offer.objects.create(title = 'tytul',created_by = testauthor,price = 23, category = Offer_Category.objects.get(name = 'CamperVan'))
|
|
||||||
|
|
||||||
def test_correct_date(self):
|
|
||||||
today= datetime.date.today()
|
|
||||||
ed = datetime.date(year=2021, month=1, day=20)
|
|
||||||
Reservation.objects.create(
|
|
||||||
user = Base_User.objects.get(email = 'test2@vagus.pl'),
|
|
||||||
offer = Offer.objects.get(id = 16),
|
|
||||||
reservation_start_date = today,
|
|
||||||
reservation_end_date = ed,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_incorret_date(self):
|
|
||||||
today = datetime.date.today()
|
|
||||||
ed = datetime.date(year = 2020, month=5, day = 15)
|
|
||||||
Reservation.objects.create(
|
|
||||||
user = Base_User.objects.get(email = 'test2@vagus.pl'),
|
|
||||||
offer = Offer.objects.get(id = 16),
|
|
||||||
reservation_start_date = today,
|
|
||||||
reservation_end_date = ed,
|
|
||||||
)
|
|
@ -3,9 +3,10 @@ from django.urls import path
|
|||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from camper.models import Offer
|
from camper.models import Offer
|
||||||
from . import views
|
from . import views
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('offer/<slug:slug>', views.DetailOfferPage.as_view(), name = 'detail_offer_page'),
|
path('reservation-detail/<slug:slug>', login_required(views.Reservation_Detail.as_view()), name = 'reservation_detail'),
|
||||||
|
|
||||||
]
|
]
|
@ -1,22 +1,12 @@
|
|||||||
from django.shortcuts import render,get_object_or_404
|
from django.shortcuts import render,get_object_or_404
|
||||||
from django.utils.decorators import method_decorator
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from .forms import ReservationForm
|
|
||||||
from camper.models import Offer, Image_offer
|
|
||||||
from django.views.generic import (
|
from django.views.generic import (
|
||||||
DetailView
|
DetailView,
|
||||||
|
UpdateView
|
||||||
)
|
)
|
||||||
|
from .models import Reservation
|
||||||
|
from .forms import ReservationStatus
|
||||||
|
|
||||||
class DetailOfferPage(DetailView):
|
class Reservation_Detail(UpdateView):
|
||||||
model = Offer
|
model = Reservation
|
||||||
template_name = 'offer/offer-detail.html'
|
template_name = 'reservation/reservation-detail.html'
|
||||||
|
form_class = ReservationStatus
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(DetailOfferPage, self).get_context_data(**kwargs)
|
|
||||||
context['form'] = ReservationForm
|
|
||||||
context['Image_offer'] = Image_offer.objects.filter(offer = self.object)
|
|
||||||
return context
|
|
||||||
|
|
||||||
@method_decorator(login_required)
|
|
||||||
def post(self,request,*args,**kwargs):
|
|
||||||
pass
|
|
||||||
|
@ -20,8 +20,7 @@ body a:hover {
|
|||||||
text-decoration: none;}
|
text-decoration: none;}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
width: 1380px;
|
max-width: 1380px;
|
||||||
max-width: 100%;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,13 +117,6 @@ body a:hover {
|
|||||||
font-weight: 600!important;
|
font-weight: 600!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.header-nav-bar-avatar {
|
|
||||||
min-width: 36px;
|
|
||||||
max-height: 36px;
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-nav-bar img {
|
.header-nav-bar img {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@ -157,8 +149,8 @@ body a:hover {
|
|||||||
|
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
padding-left: 20px;
|
padding-left: 10px;
|
||||||
padding-right: 20px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OFFERS BOX */
|
/* OFFERS BOX */
|
||||||
@ -235,7 +227,44 @@ body a:hover {
|
|||||||
|
|
||||||
.offer-detail-row {
|
.offer-detail-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.offer-detail-content {
|
||||||
|
min-width: 600px;
|
||||||
|
}
|
||||||
|
.offer-detail-status-info {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.offer-detail-title-text {
|
||||||
|
font-size: 1.8em;
|
||||||
|
}
|
||||||
|
.offer-detail-description {
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
.offer-detail-parameters {
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
.offer-detail-parameters li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offer-detail-price {
|
||||||
|
margin:15px;
|
||||||
|
font-size: 1.5em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.offer-reservation {
|
||||||
|
flex:40%;
|
||||||
|
min-width: 300px;
|
||||||
|
margin-top: 50px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PROFILE */
|
/* PROFILE */
|
||||||
|
|
||||||
.profile-wrapper {
|
.profile-wrapper {
|
||||||
@ -250,7 +279,6 @@ body a:hover {
|
|||||||
}
|
}
|
||||||
.profile-wrapper-row-information {
|
.profile-wrapper-row-information {
|
||||||
flex:20%;
|
flex:20%;
|
||||||
background-color: crimson;
|
|
||||||
}
|
}
|
||||||
.profile-wrapper-row-content {
|
.profile-wrapper-row-content {
|
||||||
flex:70%;
|
flex:70%;
|
||||||
@ -295,3 +323,60 @@ body a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* HOME PAGE */
|
||||||
|
.home-header{
|
||||||
|
background:
|
||||||
|
linear-gradient(
|
||||||
|
rgba(0, 0, 0, 0.5),
|
||||||
|
rgba(0, 0, 0, 0.5)
|
||||||
|
),
|
||||||
|
url(/media/ian-usher-Af1OMQpuN14-unsplash.jpg);
|
||||||
|
background-size: cover;
|
||||||
|
height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-header-title {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 3em;
|
||||||
|
top: 45%;
|
||||||
|
left: 35%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.home-header-button {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 25px;
|
||||||
|
height: 40px;
|
||||||
|
width: 300px
|
||||||
|
}
|
||||||
|
.home-header-button p {
|
||||||
|
font-size: 0.5em;
|
||||||
|
}
|
||||||
|
.home-row{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.home-grid-offer {
|
||||||
|
flex:2;
|
||||||
|
text-align: center;
|
||||||
|
padding: 50px 25px 50px 25px;
|
||||||
|
}
|
||||||
|
.home-grid-offer a, a:hover {
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
.home-grid-offer img {
|
||||||
|
width: 450px;
|
||||||
|
}
|
||||||
|
.home-footer-copyright {
|
||||||
|
width: 100%;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
text-align: right;
|
||||||
|
padding: 50px 10px 1px 10px;
|
||||||
|
}
|
||||||
|
.home-footer-copyright p {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
|
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
|
||||||
<link rel="stylesheet" href = 'style.css'>
|
|
||||||
<link href = "https://fonts.googleapis.com/css?family=Dosis" rel='stylesheet'>
|
|
||||||
<link href = "https://fonts.googleapis.com/css?family=Poppins" rel='stylesheet'>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class='header-smart-baner'> <!-- TOP HEADER SMART BANER-->
|
|
||||||
<div class='header-smart-baner-text'> Lubisz ciasteczka? Mamy ich naprawdę duzo.</div>
|
|
||||||
</div> <!-- TOP HEADER SMART BANER END-->
|
|
||||||
<div class='header'>
|
|
||||||
<div class='container'>
|
|
||||||
<div class='header-inner'>
|
|
||||||
<div class='header-logo'> <a href='#'> vagus </a> </div>
|
|
||||||
<div class='header-nav'>
|
|
||||||
<a href='#'>KAMPERY </a>
|
|
||||||
<a href='#'>O NAS </a>
|
|
||||||
<a href='#'>FAQ</a>
|
|
||||||
<a href='#'>KONTAKT </a>
|
|
||||||
<div class='header-nav-bar'>
|
|
||||||
<div class='header-nav-bar-container'>
|
|
||||||
<div class='header-nav-bar-menu-mobile'>
|
|
||||||
<div class='header-nav-bar-menu-mobile-icon'></div>
|
|
||||||
<div class='header-nav-bar-menu-mobile-icon'></div>
|
|
||||||
<div class='header-nav-bar-menu-mobile-icon'></div>
|
|
||||||
</div>
|
|
||||||
<div class='header-nav-bar-text'> Witaj, Krzysztof</div>
|
|
||||||
<div class='header-nav-bar-avatar'> <img src='photo.jpg'> </div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
33
vagus/template/home.html
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
{% extends 'index.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class='container'>
|
||||||
|
<div class='home-wrapper'>
|
||||||
|
<section class='home-header'>
|
||||||
|
<div class="home-header-title">
|
||||||
|
<h1>Stress is caused by</h1>
|
||||||
|
<p>not camping enough!</p>
|
||||||
|
<a href = "{{ request.scheme }}://{{ request.META.HTTP_HOST }}/offers"><button class='home-header-button'> <p>Zarezerwuj swój kamper</p> </button> </a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div class='home-row'>
|
||||||
|
{% for offer in offers%}
|
||||||
|
<div class='home-grid-offer'>
|
||||||
|
<a href ="{{ offer.get_absolute_url}}"> <h4> {{ offer.title}} </h4></a>
|
||||||
|
{% for photo in offer.images.all %}
|
||||||
|
{% if photo.main_image == True%}
|
||||||
|
<img src="{{ photo.image.url }}">
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class='home-footer-copyright'>
|
||||||
|
<p> Copyright by Krzysztof Bonecki 2021 </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -14,7 +14,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class='header-smart-baner'> <!-- TOP HEADER SMART BANER-->
|
<div class='header-smart-baner'> <!-- TOP HEADER SMART BANER-->
|
||||||
<div class='header-smart-baner-text'> Lubisz ciasteczka? Mamy ich naprawdę duzo.</div>
|
<div class='header-smart-baner-text'> Lorem Ipsum is simply dummy text of the print...</div>
|
||||||
</div> <!-- TOP HEADER SMART BANER END-->
|
</div> <!-- TOP HEADER SMART BANER END-->
|
||||||
<div class='header'>
|
<div class='header'>
|
||||||
<div class='container'>
|
<div class='container'>
|
||||||
@ -22,12 +22,10 @@
|
|||||||
<div class='header-logo'> <a href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/'> vagus </a> </div>
|
<div class='header-logo'> <a href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/'> vagus </a> </div>
|
||||||
<div class='header-nav'>
|
<div class='header-nav'>
|
||||||
<a href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/offers'>KAMPERY </a>
|
<a href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/offers'>KAMPERY </a>
|
||||||
|
|
||||||
<a href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/add-offer'>DODAJ OFERTĘ </a>
|
<a href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/add-offer'>DODAJ OFERTĘ </a>
|
||||||
<div class='header-nav-bar'>
|
<div class='header-nav-bar'>
|
||||||
<div class='header-nav-bar-container'>
|
<div class='header-nav-bar-container'>
|
||||||
<div class='header-nav-bar-text'>
|
<div class='header-nav-bar-text'>
|
||||||
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
{% if user.status != 'Moderator' %}
|
{% if user.status != 'Moderator' %}
|
||||||
<a class='link' href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/profile'> Witaj, {{ user.first_name }} </a>
|
<a class='link' href='{{ request.scheme }}://{{ request.META.HTTP_HOST }}/profile'> Witaj, {{ user.first_name }} </a>
|
||||||
|
@ -38,31 +38,30 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='offer-detail-parameters'>
|
<div class='offer-detail-parameters'>
|
||||||
<ul>
|
<ul class="list-group">
|
||||||
<li> 'DMC' <b> {{offer.DMC}} </b> </li>
|
<li class="list-group-item"> 'DMC' <b> {{offer.DMC}} </b> </li>
|
||||||
<li> 'Places_to_sleep' <b> {{offer.Places_to_sleep}} </b></li>
|
<li class="list-group-item"> 'Places_to_sleep' <b> {{offer.Places_to_sleep}} </b></li>
|
||||||
<li> 'cooker' <b> {{offer.cooker}} </b></li>
|
<li class="list-group-item"> 'cooker' <b> {{offer.cooker}} </b></li>
|
||||||
<li> 'fridge' <b> {{offer.fridge}} </b></li>
|
<li class="list-group-item"> 'fridge' <b> {{offer.fridge}} </b></li>
|
||||||
<li> 'microwave' <b> {{offer.microwave}} </b></li>
|
<li class="list-group-item"> 'microwave' <b> {{offer.microwave}} </b></li>
|
||||||
<li> 'Webasto' <b> {{offer.Webasto}} </b></li>
|
<li class="list-group-item"> 'Webasto' <b> {{offer.Webasto}} </b></li>
|
||||||
<li> 'auto_temp_control' <b> {{offer.auto_temp_control}} </b></li>
|
<li class="list-group-item"> 'auto_temp_control' <b> {{offer.auto_temp_control}} </b></li>
|
||||||
<li> 'water_level_indicator' <b> {{offer.water_level_indicator}} </b> </li>
|
<li class="list-group-item"> 'water_level_indicator' <b> {{offer.water_level_indicator}} </b> </li>
|
||||||
<li> 'battery_level'<b> {{offer.battery_level}} </b> </li>
|
<li class="list-group-item"> 'battery_level'<b> {{offer.battery_level}} </b> </li>
|
||||||
<li> 'photovoltaic_panels' <b> {{offer.photovoltaic_panels}} </b> </li>
|
<li class="list-group-item"> 'photovoltaic_panels' <b> {{offer.photovoltaic_panels}} </b> </li>
|
||||||
<li> 'gearbox <b> {{offer.gearbox}} </b> </li>
|
<li class="list-group-item"> 'gearbox <b> {{offer.gearbox}} </b> </li>
|
||||||
<li> 'tempomat' <b> {{offer.tempomat}} </b> </li>
|
<li class="list-group-item"> 'tempomat' <b> {{offer.tempomat}} </b> </li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class ='offer-detail-price'> KOSZT: {{offer.price}} PLN / dzień</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='offer-reservation'>
|
<div class='offer-reservation'>
|
||||||
<form id="form-container" method="POST" class="reservation-form">
|
<form id="form-container" method="POST" class="reservation-form">
|
||||||
|
<h3> Zarezerwuj kamper </h3>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.media }}
|
{{ form.media }}
|
||||||
{{form.as_p}}
|
{{form.as_p}}
|
||||||
|
|
||||||
<button style="background-color:black; color:white" class="btn btn-outline-info" type="submit">Wyślij zapytanie</button>
|
<button style="background-color:black; color:white" class="btn btn-outline-info" type="submit">Wyślij zapytanie</button>
|
||||||
</form>
|
</form>
|
||||||
<div>
|
<div>
|
||||||
|
11
vagus/template/offer/update-offer.html
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends 'index.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form method="post">{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
{{formset.as_p}}
|
||||||
|
<input type="submit" value="Update">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
30
vagus/template/reservation/reservation-detail.html
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
{% extends 'index.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Tytuł oferty</th>
|
||||||
|
<th scope="col">Data rezerwacji</th>
|
||||||
|
<th scope="col">Początek rezerwacji</th>
|
||||||
|
<th scope="col">Koniec rezerwacji</th>
|
||||||
|
<th scope ="col"> Koszt </th>
|
||||||
|
<th scope="col">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ reservation.offer.get_absolute_url }}">{{ reservation.offer.title }}</a>
|
||||||
|
</td>
|
||||||
|
<td >{{reservation.user.email}}</td>
|
||||||
|
<td>{{ reservation.reservation_start_date }}</td>
|
||||||
|
<td>{{ reservation.reservation_end_date }}</td>
|
||||||
|
<td> {{ reservation.get_total_cost}} </td>
|
||||||
|
<td>{{reservation.status}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -48,6 +48,37 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% endif%}
|
{% endif%}
|
||||||
|
|
||||||
|
{% if reservations %}
|
||||||
|
<h4> Rezerwacje klientów </h4>
|
||||||
|
<table class="table ">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Wynajęty kamper</th>
|
||||||
|
<th scope="col">Uzytkownik </th>
|
||||||
|
<th scope="col">Początek rezerwacji</th>
|
||||||
|
<th scope="col">Koniec rezerwacji</th>
|
||||||
|
<th scope="col"> Koszt </th>
|
||||||
|
<th scope="col">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for reservation in reservations %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ reservation.get_absolute_url }}">{{ reservation.offer.title }}</a>
|
||||||
|
</td>
|
||||||
|
<td >{{reservation.user.email}}</td>
|
||||||
|
<td>{{ reservation.reservation_start_date }}</td>
|
||||||
|
<td>{{ reservation.reservation_end_date }}</td>
|
||||||
|
<td> {{ reservation.get_total_cost}} </td>
|
||||||
|
<td> {{reservation.status}} </td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if user_reservations %}
|
{% if user_reservations %}
|
||||||
<h4> Moje rezerwacje </h4>
|
<h4> Moje rezerwacje </h4>
|
||||||
<table class="table ">
|
<table class="table ">
|
||||||
@ -64,7 +95,7 @@
|
|||||||
{% for reservation in user_reservations %}
|
{% for reservation in user_reservations %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ reservation.offer.get_absolute_url }}">{{ reservation.offer.title }}</a>
|
<a href="{{ reservation.get_absolute_url }}">{{ reservation.offer.title }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td title="{{ reservation.created_date}}">{{ reservation.created_date }}</td>
|
<td title="{{ reservation.created_date}}">{{ reservation.created_date }}</td>
|
||||||
<td>{{ reservation.reservation_start_date }}</td>
|
<td>{{ reservation.reservation_start_date }}</td>
|
||||||
|