pipicar/modules/main/views/main.blade.php

502 lines
30 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<div class="container text-center main-page">
<div class="main-page-header">
<p class="top-title">Доступные автомобили</p>
<p class="title">Выберите лучший автомобиль</p>
</div>
<div class="container my-4">
<div class="row">
<div class="col-12 col-md-3 card-catalog-left-container">
<div class="text-end">
<button class="btn btn-outline" id="toggleFilterBtn">
<i class="bi bi-filter-right" style="vertical-align: -.1em;"></i>@lang('Фильтр')
</button>
</div>
<div class="card card-catalog-left-filter collapsible collapsed" id="filterCard">
<div class="card-body">
{{-- Дата начала --}}
<form method="GET" id="filter">
<div class="form-group mb-3 pb-4 d-flex flex-column justify-content-around align-content-center">
<label class="form-label d-block">Даты аренды</label>
<div class="d-flex flex-row justify-content-around align-content-center">
<input type="text"
class="form-control"
name="started_at"
id="started_at"
autocomplete="off"
inputmode="numeric"
pattern="\d{2}\.\d{2}\.\d{4}"
placeholder="дд.мм.гггг"
value="{{ request('started_at') }}"
style="max-width: 120px">
<span class="separator"></span>
<input type="text"
class="form-control"
name="ended_at"
id="ended_at"
autocomplete="off"
inputmode="numeric"
pattern="\d{2}\.\d{2}\.\d{4}"
placeholder="дд.мм.гггг"
value="{{ request('ended_at') }}"
style="max-width: 120px">
</div>
</div>
{{-- Класс авто --}}
<div class="mb-3 pb-4">
<label class="form-label d-block">Класс авто</label>
<div class="btn-group" role="group" aria-label="Класс">
<input type="checkbox" class="btn-check" name="class_filters[]" value="Эконом" id="class_option1" {{ in_array('Эконом', (array) request('class_filters')) ? 'checked' : '' }}>
<label class="btn btn-outline-primary" for="class_option1">Эконом</label>
<input type="checkbox" class="btn-check" name="class_filters[]" value="Средний" id="class_option2" {{ in_array('Средний', (array) request('class_filters')) ? 'checked' : '' }}>
<label class="btn btn-outline-primary" for="class_option2">Средний</label>
<input type="checkbox" class="btn-check" name="class_filters[]" value="Бизнес" id="class_option3" {{ in_array('Бизнес', (array) request('class_filters')) ? 'checked' : '' }}>
<label class="btn btn-outline-primary" for="class_option3">Бизнес</label>
</div>
</div>
{{-- Тип кузова --}}
<div class="mb-3 pb-4">
<label class="form-label d-block">Тип кузова</label>
<div class="btn-group" role="group" aria-label="Кузов">
<input type="checkbox" class="btn-check" name="bodywork_filters[]" value="Седан" id="bodywork_option1" {{ in_array('Седан', (array) request('bodywork_filters')) ? 'checked' : '' }}>
<label class="btn btn-outline-primary" for="bodywork_option1">Седан</label>
<input type="checkbox" class="btn-check" name="bodywork_filters[]" value="Кроссовер" id="bodywork_option2" {{ in_array('Кроссовер', (array) request('bodywork_filters')) ? 'checked' : '' }}>
<label class="btn btn-outline-primary" for="bodywork_option2">Кроссовер</label>
<input type="checkbox" class="btn-check" name="bodywork_filters[]" value="Внедорожник" id="bodywork_option3" {{ in_array('Внедорожник', (array) request('bodywork_filters')) ? 'checked' : '' }}>
<label class="btn btn-outline-primary" for="bodywork_option3">Внедорожник</label>
</div>
</div>
{{-- Кнопка --}}
<div class="filter-buttons d-flex" style="gap: 5px;">
<button type="submit" class="btn btn-danger w-100" id="filter_reset" onclick="resetForm()">
@lang('Сбросить')
</button>
<button type="submit" class="btn btn-success w-100">
@lang('Искать')
</button>
</div>
</form>
</div>
</div>
<div class="card card-catalog-left mt-4">
<div class="card-body">
<p class="title">Все предложения включают:</p>
<ul>
<li><i class="material-symbols-outlined">done</i>
<span>&nbsp;Бесплатное перебронирование и отмена</span></li>
<li><i class="material-symbols-outlined">done</i>
<span>&nbsp;Лимит пробега по городу 200 км</span></li>
<li><i class="material-symbols-outlined">done</i> <span>&nbsp;Страхование гражданской ответственности</span></li>
<li><i class="material-symbols-outlined">done</i> <span>&nbsp;Эконом класс</span></li>
<li><i class="material-symbols-outlined">done</i> <span>&nbsp;Депозит</span></li>
<li><i class="material-symbols-outlined">done</i>
<span>&nbsp;Межгород по дополнительным тарифам</span></li>
</ul>
</div>
</div>
<div class="card card-catalog-left2 mt-4">
<div class="card-body">
<p class="title">Другие условия:</p>
<p class="cr-item">Минимальный возраст водителя - 21 год</p>
<p class="cr-item">Минимальный срок владения водительскими правами - 2 года</p>
<p class="title m-0">Прочие условия:</p>
<a href="https://pcar.kz/#faq" target="_blank" class="btn-link">Условия аренды автомобиля</a>
</div>
</div>
</div>
<div class="col-12 col-md-9 mb-4 d-flex">
<div class="row custom-row w-100">
@php $carsValues = array_values($cars->toArray()); @endphp
@foreach($carsValues as $car)
{{-- @dump($car)--}}
<div class="col-12 col-md-6 mb-4">
<div class="car-card flex-grow-1">
<img class="img-fluid" src="{{ $car['photo'] ?? asset('img/default.png') }}" alt="Car Image">
<div class="title">{{ $car['brand'] . ' ' . $car['mark'] . ' - ' . $car['year'] }}</div>
<div class="card-car-chars">
<div class="add-li"><i class="material-symbols-outlined">ac_unit</i><p>&nbsp;Кондиционер</p></div>
<div class="add-li"><i class="material-symbols-outlined">auto_transmission</i><p>&nbsp;{{ $car['fuel_type'] }}</p></div>
<div class="add-li"><i class="material-symbols-outlined">groups</i><p>&nbsp;{{ $car['people'] }} мест</p></div>
</div>
<div class="car-card-footer">
<div class="cost">
<small>Базовая ставка</small>
@php
$tariffWithMin1 = collect($car['tariffs'])->firstWhere('min', 1);
$tariffWithMin3 = collect($car['tariffs'])->firstWhere('min', 3);
$tariffWithMin6 = collect($car['tariffs'])->firstWhere('min', 6);
$tariffWithMin15 = collect($car['tariffs'])->firstWhere('min', 15);
@endphp
<p class="m-0">
@if($tariffWithMin1)
{{ $tariffWithMin1['price'] }}
@endif
</p>
</div>
<a href="#" class="btn btn-primary open-rent-modal"
data-bs-toggle="modal"
data-bs-target="#rentModal"
data-car='@json($car)'
data-photo="{{ $car['photo'] ?? asset('img/default.png') }}"
{{-- data-brand="{{ $car['brand'] }}"--}}
{{-- data-mark="{{ $car['mark'] }}"--}}
{{-- data-year="{{ $car['year'] }}"--}}
{{-- data-fuel="{{ $car['fuel_type'] }}"--}}
{{-- data-people="{{ $car['people'] }}"--}}
{{-- data-tariffWithMin1 ="{{ $tariffWithMin1['price'] ?? '' }}"--}}
{{-- data-tariffWithMin3="{{ $tariffWithMin3['price'] ?? '' }}"--}}
{{-- data-tariffWithMin6="{{ $tariffWithMin6['price'] ?? '' }}"--}}
{{-- data-tariffWithMin15="{{ $tariffWithMin15['price'] ?? '' }}"--}}
>
@lang('Арендовать')
</a>
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="rentModal" tabindex="-1" aria-labelledby="rentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" style="min-width: 75vw">
<div class="modal-content">
<div class="modal-body">
<div class="row justify-content-center align-items-start">
<form method="post" class="col-12 col-md-7">
<input hidden="" name="mark_id" id="mark_id" value="">
<input hidden="" name="color" id="color" value="">
<div class="car-card d-flex flex-grow-1 flex-row mb-4">
<img id="modalCarImage" class="img-fluid" src="" alt="Car Image" style="width: 50%; margin-right: 2rem;">
<div>
<div class="title" id="modalCarTitle"></div>
<div class="subtitle">@lang('или аналогичный')</div>
<div class="title-small mt-4 mb-2">@lang('Особенности автомобиля')</div>
<div class="card-car-chars">
<div class="add-li"><i class="material-symbols-outlined">ac_unit</i><p>&nbsp;@lang('Кондиционер')</p></div>
<div class="add-li"><i class="material-symbols-outlined">auto_transmission</i><p id="modalFuel">&nbsp;</p></div>
<div class="add-li"><i class="material-symbols-outlined">groups</i><p id="modalPeople">&nbsp;</p></div>
</div>
</div>
</div>
<div class="card m-0 mb-4" style="overflow: visible;">
<div class="card-body">
<div class="mb-3">
<div class="row justify-content-center align-items-end">
<div class="col-12 col-md-6">
<label for="days" class="form-label">Срок аренды, дней <b>*</b></label>
<input type="number" name="days" class="form-control" id="days" value="7" required="">
</div>
<div class="col-12 col-md-6">
<div class="form-text">
Чем больше срок аренды, тем ниже базовая ставка.
<div class="popup-custom">
<span>Условия скидок&nbsp; <i class="material-symbols-outlined">help</i></span>
<div class="popup-block">
<p>@lang('Базовая суточная ставка на аренду данного автомобиля уменьшается в зависимости от срока аренды')</p>
<ul>
<li><b>1-2 дня:</b><span id="tariffWithMin1"></span></li>
<li><b>3-5 дней:</b><span id="tariffWithMin3"></span></li>
<li><b>6-15 дней:</b><span id="tariffWithMin6"></span></li>
<li><b>16-30 дней:</b><span id="tariffWithMin15"></span></li>
<li><b>30+ дней:</b><span id="tariffWithMin30"></span></li>
</ul>
<p>@lang('Расчет итоговой суммы к оплате рассчитывается (кол-во дней * базовую ставку)')</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card m-0 mb-4">
<div class="card-body">
<div class="mb-3">
<label class="form-label">Место и время получения <b>*</b></label>
<input placeholder="Введите адрес получения" type="text" class="form-control" name="pick-up-address" id="pick-up-address" required="">
<div class="row mt-3">
<div class="col-6">
<input type="date" class="form-control" id="pick-up-date" name="pick-up-date" required="" min="2025-05-02">
</div>
<div class="col-6">
<input type="time" class="form-control" name="pick-up-time" id="pick-up-time" value="09:00" required="">
</div>
</div>
</div>
<hr>
<div class="mb-3">
<label class="form-label">Место и время возврата <b>*</b></label>
<input placeholder="Введите адрес возврата" type="text" class="form-control" name="return-address" id="return-address" required="">
<div class="row mt-3">
<div class="col-6">
<input type="date" class="form-control" id="return-date" name="return-date" disabled="" required="">
</div>
<div class="col-6">
<input type="time" class="form-control" id="return-time" name="return-time" value="09:00" required="">
</div>
</div>
</div>
</div>
</div>
<div class="mb-4 lst-btn">
<button type="submit" class="btn btn-primary btn-lg">Забронировать сейчас</button>
<p class="add-text2">Бесплатная отмена в любое время</p>
</div>
</form>
<div class="col-12 col-md-4 right-content">
<div class="card mb-4 card-type-2 price-info" style="border-radius: 8px;">
<div class="card-body">
<div class="title-small mb-3">Базовая ставка</div>
<div class="li-bl">
<div class="li-sp">Без скидки</div>
<div class="li-sp" id="base-without"></div>
</div>
<div class="li-bl">
<div class="li-sp">Со скидкой</div>
<div class="li-sp" id="base-with"></div>
</div>
<hr>
<div class="title-small mb-3">Общая цена</div>
<div class="li-bl">
<div class="li-sp">Аренда без скидки</div>
<div class="li-sp" id="summ-without"></div>
</div>
<div class="li-bl">
<div class="li-sp">Аренда со скидкой</div>
<div class="li-sp" id="sunn-with"></div>
</div>
<hr>
<div class="li-bl">
<div class="title">Итого</div>
<div class="title" id="total"></div>
</div>
</div>
</div>
<div class="card card-type-2" style="border-radius: 8px;">
<div class="card-body">
<div class="muted-card-text">
Общая стоимость, включая установленные законом налоги. <br><br>
Обратите внимание, что на изображении и в технических характеристиках автомобиля представлена только примерная иллюстрация категории автомобиля (за исключением ошибок). Бронирование производится только для категории транспортного средства, но не для конкретного транспортного средства. <br><br>
Вся информация о размерах, весе и т.д. основана на наименьшей доступной категории модели. </div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function debounce(func, wait) {
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
const datepickerConfig = {
buttons: ['today', 'clear'],
autoClose: true
};
const startedAtPicker = new AirDatepicker('#started_at', datepickerConfig);
const endedAtPicker = new AirDatepicker('#ended_at', datepickerConfig);
document.addEventListener('DOMContentLoaded', function () {
const toggleBtn = document.getElementById('toggleFilterBtn');
const filterCard = document.getElementById('filterCard');
// Инициализация состояния по localStorage
let isExpanded = localStorage.getItem('filterOpened') === 'true';
if (isExpanded) {
filterCard.classList.add('expanded');
filterCard.style.transition = 'max-height 1.2s ease, opacity 1.2s ease';
}
toggleBtn.addEventListener('click', function (e) {
e.preventDefault();
if (!filterCard.classList.contains('expanded')) {
filterCard.style.transition = 'max-height 1.2s ease, opacity 1.2s ease';
filterCard.classList.add('expanded');
isExpanded = true;
} else {
filterCard.style.transition = 'max-height 0.4s ease, opacity 0.4s ease';
filterCard.classList.remove('expanded');
isExpanded = false;
}
localStorage.setItem('filterOpened', isExpanded);
});
});
document.querySelectorAll('.open-rent-modal').forEach(button => {
button.addEventListener('click', function () {
const car = JSON.parse(this.getAttribute('data-car'));
modal.setAttribute('data-car', JSON.stringify(car));
document.getElementById('modalCarImage').src = this.getAttribute('data-photo');
document.getElementById('modalCarTitle').innerText = `${car.brand} ${car.mark} - ${car.year}`;
document.getElementById('modalFuel').innerHTML = `&nbsp;${car.fuel_type}`;
document.getElementById('modalPeople').innerHTML = `&nbsp;${car.people} мест`;
document.getElementById('mark_id').value = car.id;
const tariff1 = car.tariffs.find(t => t.min === 1)?.price ?? 0;
const tariff3 = car.tariffs.find(t => t.min === 3)?.price ?? 0;
const tariff6 = car.tariffs.find(t => t.min === 6)?.price ?? 0;
const tariff15 = car.tariffs.find(t => t.min === 15)?.price ?? 0;
document.getElementById('tariffWithMin1').innerHTML = `&nbsp;${tariff1} ₸`;
document.getElementById('tariffWithMin3').innerHTML = `&nbsp;${tariff3} ₸`;
document.getElementById('tariffWithMin6').innerHTML = `&nbsp;${tariff6} ₸`;
document.getElementById('tariffWithMin15').innerHTML = `&nbsp;${tariff15} ₸`;
document.getElementById('tariffWithMin30').innerHTML = `&nbsp;${(tariff1 * 0.4).toFixed(0)} ₸`;
updateReturnDate();
});
const modal = document.getElementById('rentModal');
const pickUpDateInput = document.getElementById('pick-up-date');
const returnDateInput = document.getElementById('return-date');
const daysInput = document.getElementById('days');
const today = new Date();
const yyyy = today.getFullYear();
const mm = String(today.getMonth() + 1).padStart(2, '0');
const dd = String(today.getDate()).padStart(2, '0');
const todayStr = `${yyyy}-${mm}-${dd}`;
pickUpDateInput.value = todayStr;
pickUpDateInput.setAttribute('min', todayStr);
function updateReturnDate() {
const pickUpDate = new Date(pickUpDateInput.value);
const rentalDays = parseInt(daysInput.value, 10);
if (!isNaN(rentalDays)) {
pickUpDate.setDate(pickUpDate.getDate() + rentalDays);
const returnYyyy = pickUpDate.getFullYear();
const returnMm = String(pickUpDate.getMonth() + 1).padStart(2, '0');
const returnDd = String(pickUpDate.getDate()).padStart(2, '0');
returnDateInput.value = `${returnYyyy}-${returnMm}-${returnDd}`;
}
calculateOther(parseInt(daysInput.value));
}
daysInput.addEventListener('input', updateReturnDate);
pickUpDateInput.addEventListener('change', updateReturnDate);
function calculateOther(days) {
let discountRate = null;
if (!days || isNaN(days)) {
days = 1;
}
const car = JSON.parse(modal.getAttribute('data-car'));
const tariffs = car['tariffs'];
const baseRate = car.tariffs.find(t => t.min === 1)?.price ?? 0;
const matchedRange = tariffs.find(range => days >= range.min && days <= range.max);
const baseWith = document.getElementById('base-with');
const baseWithout = document.getElementById('base-without');
const summWithout = document.getElementById('summ-without');
const summWith = document.getElementById('sunn-with');
const total = document.getElementById('total');
if (matchedRange) {
discountRate = matchedRange.price;
} else if (days > 30) {
discountRate = baseWithout * 0.4;
}
const totalWithoutDiscount = baseRate * days;
const totalWithDiscount = discountRate * days;
baseWith.textContent = formatNumberWithSpaces(discountRate) + ' ₸';
baseWithout.textContent = formatNumberWithSpaces(baseRate) + ' ₸';
summWithout.textContent = formatNumberWithSpaces(totalWithoutDiscount) + ' ₸';
summWith.textContent = formatNumberWithSpaces(totalWithDiscount) + ' ₸';
total.textContent = formatNumberWithSpaces(totalWithDiscount) + ' ₸';
if (isNaN(days) || days < 1) {
summWithout.textContent = 0 + ' ₸';
summWith.textContent = 0 + ' ₸';
total.textContent = 0 + ' ₸';
}
}
function formatNumberWithSpaces(number) {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
}
});
document.querySelectorAll('input[name="class_filters[]"]').forEach(checkbox => {
checkbox.addEventListener('click', function () {
if (this.checked) {
const wasChecked = this.dataset.checked === "true";
document.querySelectorAll('input[name="class_filters[]"]').forEach(cb => {
cb.checked = false;
cb.dataset.checked = "false";
});
if (!wasChecked) {
this.checked = true;
this.dataset.checked = "true";
}
} else {
this.dataset.checked = "false";
}
});
});
document.querySelectorAll('input[name="bodywork_filters[]"]').forEach(checkbox => {
checkbox.addEventListener('click', function () {
if (this.checked) {
const wasChecked = this.dataset.checked === "true";
document.querySelectorAll('input[name="bodywork_filters[]"]').forEach(cb => {
cb.checked = false;
cb.dataset.checked = "false";
});
if (!wasChecked) {
this.checked = true;
this.dataset.checked = "true";
}
} else {
this.dataset.checked = "false";
}
});
});
function resetForm() {
const form = document.getElementById('filter');
form.querySelectorAll('input').forEach(input => {
if (input.type === 'checkbox' || input.type === 'radio') {
input.checked = false;
} else {
input.value = '';
}
});
window.location.href = window.location.origin + window.location.pathname;
}
</script>