TRI-293: edit form-poster + page styles

This commit is contained in:
2024-12-25 16:54:57 +03:00
parent 951315a1a4
commit 7d00e92aac
6 changed files with 282 additions and 148 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,96 +1,115 @@
!function () {
'use strict';
var posterApp = {
// todo определение фоормата даты можно вынести на бэк для контроля
initDatePickerr: function () {
const _this = this;
[this._selector.inpDeparture, this._selector.inpArrival].forEach(i => {
let date = i.val();
if (!i.length) return false
if(!i.length) return
let date = i.val().trim() ? i.val() : new Date();
let startDate = null
if (window.location.href.includes("/ru/")) {
startDate = moment(date, "D MMMM YYYY г. HH:mm", 'ru');
startDate = moment(date, this._data.formatDateClient, 'ru');
} else {
startDate = moment(date, "MMMM D, YYYY, h:mm a", 'en');
startDate = moment(date, this._data.formatDateClient, 'en');
}
if (!i.attr('hidden')) {
i.daterangepicker({
"autoapply": true,
"linkedCalendars": false,
"singleDatePicker": true,
"timePicker": true,
"timePicker24Hour": true,
"timePicker": false,
"timePicker24Hour": false,
"minDate": startDate,
"locale": changeLangForDateTimePicker(),
}, function (start, end, label) {
i.val(start.format('DD.MM.YYYY HH:mm'));
i.val(start.format('DD.MM.YYYY'));
});
}
i.off('mouseleave.i-disable').on('mouseleave.i-disable', e => {
i.attr('readonly', false);
i.blur();
})
i.off('mouseover.i-disable').on('mouseover.i-disable', e => {
i.attr('readonly', true);
})
i.off('focus.i-disable').on('focus.i-disable', e => {
i.blur()
})
});
},
changeCargoType: function () {
let inpTypeAvia = this._selector.typeItems.filter((d,i)=>i.value === 'avia');
let inpTypePassenger = this._selector.cargoItems.filter((d,i)=>i.value === 'passenger');
this._selector.cargoItems.off('change.i-disable').on('change.i-disable', (e)=>{
this.handlerDisabled(e.target,inpTypeAvia,'passenger')
let inpTypeAvia = this._selector.typeItems.filter((d, i) => i.value === 'avia');
let inpTypePassenger = this._selector.cargoItems.filter((d, i) => i.value === 'passenger');
this._selector.cargoItems.off('change.i-disable').on('change.i-disable', (e) => {
this.handlerDisabled(e.target, inpTypeAvia, 'passenger')
})
// change other type
this.handlerDisabled(inpTypePassenger,inpTypeAvia,'passenger')
this.handlerDisabled(inpTypePassenger, inpTypeAvia, 'passenger')
},
handlerDisabled: function (el,el2,text) {
if($(el).val() === text) {
$(el2).attr('disabled', true);
} else {
$(el2).attr('disabled', false);
}
handlerDisabled: function (el, el2, text) {
if ($(el).val() === text) {
$(el2).attr('disabled', true);
} else {
$(el2).attr('disabled', false);
}
},
changeTransportType: function () {
let inpTypePassenger = this._selector.cargoItems.filter((d,i)=>i.value === 'passenger');
this._selector.typeItems.off('change.i-disable').on('change.i-disable', (e)=>{
this.handlerDisabled(e.target,inpTypePassenger,'avia')
let inpTypePassenger = this._selector.cargoItems.filter((d, i) => i.value === 'passenger');
this._selector.typeItems.off('change.i-disable').on('change.i-disable', (e) => {
this.handlerDisabled(e.target, inpTypePassenger, 'avia');
})
},
createInpCoutryData: function (el, data) {
el.dataCoutry?.remove();
let template =
`<div class="poster__inp-country">
<img src="${data[4]}" alt="${data[1]}">
<span>${data[2] || 'BY'}</span>
</div>`;
el.after(template);
el.dataCoutry = el.next('.poster__inp-country');
el.parent().addClass('is-set')
},
initHandlerItemsTowns: function (el) {
el.list.off('click.item').on('click.item', (e) => {
let target = $(e.target)
let item = target.hasClass('autocomplete-result') ? target : target.parents('.autocomplete-result')
let dataStr = item.data('attr')
if (!dataStr.length) return
dataStr = dataStr.slice(1, -1).replace(/"/g, '');
let item = target.hasClass('poster__towns-item') ? target : target.parents('.poster__towns-item')
let data = item.data('attrs')
if (!data.length) return
let [id, txt] = data;
this.createInpCoutryData(el, data);
let [id, txt, name, date] = dataStr.split(', ');
let inpNames = {
id: 'from_address_point',
id: 'from_city',
txt: 'from_address_point_txt',
date: 'departure_DT'
}
if (name.match(/to/)) {
if (el[0].name.match(/to/)) {
inpNames = {
id: 'to_address_point',
id: 'to_city',
txt: 'to_address_point_txt',
date: 'arrival_DT'
}
}
const collection = this._selector.root[0].elements;
collection[inpNames.id].value = id;
collection[inpNames.txt].value = txt;
collection[inpNames.date].value = date;
this.handlerShowList(el)
this.handlerShowList(el);
el.prevValue = el.val();
})
},
setDataTowns: function (data, inp) {
if (!data.res_search_list.length) return
const newSearchlist = data.res_search_list.replace(/onmousedown=\'selectItemAddrPoint/g, 'data-attr=\'')
const newSearchlist = data.res_search_list;
inp.list.html(newSearchlist);
},
@@ -111,7 +130,7 @@
subtree: false,
characterDataOldValue: false
});
},
},
handlerShowList: function (i, isHide) {
if (!isHide && i.list.text()) {
@@ -127,16 +146,30 @@
return formData;
},
validForm: function () {
let elems = this._selector.root[0].elements
//todo пустые значения
elems.departure_DT.value = elems.departure_DT.value.trim()
if (!elems.departure_DT.value) {
elems.departure_DT.value = moment(new Date()).format(this._data.formatDate);
}
// console.log(elems.departure_DT.value.trim(), elems.departure_DT.value === '', elems.departure_DT.value, elems.departure_DT)
},
initSubmit: function () {
const _this = this;
this._selector.root.off('submit').on('submit', function (e) {
e.preventDefault();
_this.validForm();
let routeId = _this._selector.submitBtn.data('routeId');
var formData = _this.getDataForm();
let url = '/routes/create_or_change_route/'
if (routeId) {
url = '/routes/change_route/' + routeId + '/'
}
if (_this.getDataForm(true))
console.log(_this.getDataForm(true))
$.ajax({
headers: {"X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val()},
url: url,
@@ -146,7 +179,7 @@
contentType: false,
data: formData,
success: function (data) {
return
// return
let data_route_id = data.route_id
document.querySelector(".info_profile").innerHTML = data.html
@@ -154,7 +187,7 @@
if (routeId) {
el_route = document.querySelector(`[data-number-of-route="${routeId}"]`);
}
if(el_route) {
if (el_route) {
el_route.scrollIntoView({
behavior: "smooth",
block: 'start',
@@ -172,6 +205,7 @@
window.history.replaceState(null, '', newUrl);
},
error: function (data, exception) {
console.log(data)
document.querySelector(".info_profile").innerHTML = data.responseJSON.html;
document.getElementById('departure_DT')?.scrollIntoView({
behavior: "smooth",
@@ -185,62 +219,71 @@
getTowns: function (el) {
const _this = this;
let timer = null
if (timer) {
clearTimeout(timer);
let data = _this.getDataForm(true);
let getTownData = {
type_transport: data.type_transport,
search_str: el.val(),
ctrl_name: el.attr('name')
}
timer = setTimeout(function () {
timer = null;
let data = _this.getDataForm(true);
let getTownData = {
type_transport: data.type_transport,
search_str: el.val(),
ctrl_name: el.attr('name')
}
$.ajax({
headers: {"X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val()},
url: '/reference_data/get_address_point/',
type: "POST",
cache: false,
processData: false,
contentType: false,
data: JSON.stringify(getTownData),
success: function (data) {
el.removeClass('loading');
const {res_search_list, unanswered_msgs_count} = data;
_this.setDataTowns(data, el)
_this.initHandlerItemsTowns(el)
_this.handlerShowList(el)
if (res_search_list.length) {
el.addClass('is-items')
el.parent().addClass('is-items')
el.list.addClass('is-items')
} else {
el.parent().removeClass('is-items')
el.removeClass('is-items')
el.list.removeClass('is-items')
}
console.log('fetch', data)
},
error: function (data) {
console.log('Error')
$.ajax({
headers: {"X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val()},
url: '/reference_data/get_address_point/',
type: "POST",
cache: false,
processData: false,
contentType: false,
data: JSON.stringify(getTownData),
success: function (data) {
el.removeClass('loading');
const {res_search_list, unanswered_msgs_count} = data;
_this.setDataTowns(data, el)
_this.initHandlerItemsTowns(el)
_this.handlerShowList(el)
if (res_search_list.length) {
el.addClass('is-items')
el.parent().addClass('is-items')
el.list.addClass('is-items')
} else {
el.parent().removeClass('is-items')
el.removeClass('is-items')
el.list.removeClass('is-items')
}
});
}, 500);
console.log('fetch', data)
},
error: function (data) {
console.log('Error')
}
});
},
handlerSearchTown: function (e, i) {
this._cl('handlerSearchTown');
let el = i;
console.log('out', el.prevValue, el.val())
if (el.prevValue && el.val().length < el.prevValue.length) {
el.parent().removeClass('is-set')
el.next('.poster__inp-country').remove()
console.log(el, `${el[0].name.split('_')[0]}_city`, this._selector.root[0].elements[`${el[0].name.split('_')[0]}_city`])
this._selector.root[0].elements[`${el[0].name.split('_')[0]}_city`].value = ''
el.val('');
}
if (el.val().length > 2) {
console.log('in')
el.addClass('loading');
this.getTowns(el);
clearTimeout(el.timer)
el.timer = setTimeout(() => {
this.getTowns(el);
el.timer = null;
}, 500)
} else {
el.removeClass('loading');
}
el.prevValue = el.val();
},
initHandlerRoute: function () {
@@ -249,8 +292,8 @@
[this._selector.inpFrom, this._selector.inpTo].forEach(i => {
if (!i.length) return false
i.off('input.routes').on('input.routes', (e) => _this.handlerSearchTown(e, i));
i.off('click.routes').on('click.routes', () => _this.handlerShowList(i));
i.list.off('mouseleave.routes').on('mouseleave.routes', () => _this.handlerShowList(i, true));
i.parent().off('click.routes').on('click.routes', () => _this.handlerShowList(i));
i.parent().parent().off('mouseleave.routes').on('mouseleave.routes', () => _this.handlerShowList(i, true));
});
},
@@ -267,15 +310,20 @@
initData: function (root) {
window.posterApp = this;
this._data = {
debug: true
debug: true,
formatDate: 'DD.MM.YYYY',
formatDateClient: window.location.href.includes("/ru/")
? "D MMMM YYYY г."
: "MMMM D, YYYY",
};
this._selector = {
root: root,
wrapper: $('.info_profile'),
inpFrom: root.find('#from'),
inpFromList: root.find('#from').siblings('.poster__towns-list'),
inpFromList: root.find('#from').parent().siblings('.poster__towns-list'),
inpTo: root.find('#to'),
inpToList: root.find('#to').siblings('.poster__towns-list'),
inpToList: root.find('#to').parent().siblings('.poster__towns-list'),
cargoItems: root.find('.cargo__inp[name="cargo_type"]'),
typeItems: root.find('.cargo__inp[name="type_transport"]'),
inpDeparture: root.find('#departure_DT'),
@@ -296,10 +344,10 @@
this._cl(this);
this.handlerPageOut();
this.initHandlerRoute();
this.initDatePickerr()
this.initDatePickerr();
this.initSubmit();
this.changeCargoType();
this.changeTransportType()
this.changeTransportType();
},
};

View File

@@ -273,6 +273,36 @@ $row-gap: 40px;
&__label {
margin-bottom: 10px;
cursor: default;
}
&__inp-box {
position: relative;
&.is-set {
.poster__locate {
padding-left: 65px;
}
}
input {
}
.poster__inp-country {
position: absolute;
display: flex;
align-items: center;
left: 10px;
top: 50%;
gap: 5px;
transform: translateY(-50%);
img {
width: 24px;
}
}
}
&__area-descr {
@@ -320,8 +350,42 @@ $row-gap: 40px;
}
&__towns-item {
display: flex;
align-items: center;
padding: 5px 5px;
font-size: 16px;
line-height: 22px;
cursor: pointer;
&:hover {
background: var(--brand-grey);
}
img {
width: 24px;
margin-right: 5px;
}
span {
margin-right: 8px;
}
}
&__locate {
appearance: none;
//&:not(:placeholder-shown) {
// padding-left: 65px;
//}
//&:placeholder-shown {
//
// +.poster__inp-country {
// display: none;
// }
//}
}
.btn {

View File

@@ -27,9 +27,9 @@
<div hidden>
csrfmiddlewaretoken: eoN2nLYYo46PpDIhi82dmTFASHH4ONiBdEQOz1jQNyUpsHJ4RrvcmFwfnM45TNtl
type_transport: road
from_address_point: 59613 4267
from_city: 59613 4267
from_address_point_txt: Москаленки / Россия
to_address_point: 2824
to_city: 2824
to_address_point_txt: Берлар / Бельгия
departure_DT: 17.12.2024 23:04
arrival_DT: 29.12.2024 20:04
@@ -54,20 +54,20 @@
{% csrf_token %}
<input
type="number"
name="from_address_point"
id="from_address_point"
name="from_city"
id="from_city"
hidden
{% if form.initial.from_address_point %}value="{{ form.initial.from_address_point }}"{% endif %}
{% if form.initial.from_city %}value="{{ form.initial.from_city }}"{% endif %}
/>
<input
type="number"
name="to_address_point"
id="to_address_point"
name="to_city"
id="to_city"
hidden
{% if form.initial.to_address_point %}value="{{ form.initial.to_address_point }}"{% endif %}
{% if form.initial.to_city %}value="{{ form.initial.to_city }}"{% endif %}
/>
<input
id="hide_owner_type"
id="owner_type"
name="owner_type"
hidden
{% if form.initial.owner_type %}
@@ -76,17 +76,6 @@
value="{{ form.data.owner_type }}"
{% endif %}
>
<input
id="hiddenTime"
type="text"
name="hiddenTime"
hidden
{% if route.departure_DT %}
value="{{ route.from_city.get_current_datetime }}"
{% elif form.initial.departure_DT %}
value="{{ form.initial.departure_DT }}"
{% endif %}
>
{#type-transport#}
<div class="poster__row poster__row--transport">
<div class="poster__col col-12">
@@ -126,8 +115,18 @@
<label for="from" class="poster__label " required>
{{ l_from }}
</label>
<input type="text" autocomplete="off" name="from_address_point_txt" id="from" class="poster__locate locate"
placeholder="{% translate "Укажите город" %}" required>
<div class="poster__inp-box">
<input type="text" autocomplete="off" name="from_address_point_txt" id="from" class="poster__locate locate"
placeholder="{% translate "Укажите город" %}" required
{% if form.initial.from_address_point_txt %}value="{{ form.initial.from_address_point_txt }}"{% endif %}
>
{# <div class="poster__inp-country">#}
{# <img src="/media/uploads/flags/HU_-_Hungary.svg" alt="Венгрия">#}
{# <span>BY</span>#}
{# </div>#}
</div>
<div class="poster__towns-list"></div>
{% if not errors_off and form.errors and form.errors.from_address_point %}
<span id="error_from_address_point">{{ form.errors.from_address_point }}</span>
@@ -137,8 +136,18 @@
<label for="to" class="poster__label " required>
{{ l_to }}
</label>
<input type="text" autocomplete="off" name="to_address_point_txt" id="to" class="poster__locate locate"
placeholder="{% translate "Укажите город" %}" required>
<div class="poster__inp-box">
<input
type="text"
autocomplete="off"
name="to_address_point_txt"
id="to"
class="poster__locate locate"
placeholder="{% translate "Укажите город" %}"
required
{% if form.initial.to_address_point_txt %}value="{{ form.initial.to_address_point_txt }}"{% endif %}
>
</div>
<div class="poster__towns-list"></div>
{% if not errors_off and form.errors and form.errors.from_address_point %}
<span id="error_to_address_point">{{ form.errors.from_address_point }}</span>
@@ -149,7 +158,7 @@
<div class="poster__col poster__col--inner">
{#date-from#}
<div class="poster__col">
<label for="departure_DT" required class="poster__label col-12 ">
<label for="departure_DT" class="poster__label col-12" required>
{{ l_date_from }}
</label>
<input
@@ -158,11 +167,15 @@
id="departure_DT"
name="departure_DT"
readonly
value="{% if route.departure_DT %}
{{ route.from_city.get_current_datetime }}{% elif form.initial.departure_DT %}{{ form.initial.departure_DT }}{% endif %}"
required
{% if route.departure_DT %}
value="{{ route.from_city.get_current_datetime.strip }}"
{% elif form.initial.departure_DT %}
value="{{ form.initial.departure_DT }}"
{% endif %}
/>
{% if not errors_off and form.errors and form.errors.departure_DT %}
<span id="error_arrival_DT">{{ form.errors.departure_DT }}</span>
<span id="error_departure_DT">{{ form.errors.departure_DT }}</span>
{% endif %}
</div>
{#date-to#}
@@ -176,11 +189,11 @@
id="arrival_DT"
name="arrival_DT"
readonly
value="{% if route.departure_DT %}
{{ route.from_city.get_current_datetime }}
{% if route.arrival_DT %}
value="{{ route.from_city.get_current_datetime }}"
{% elif form.initial.arrival_DT %}
{{ form.initial.arrival_DT }}
{% endif %}"
value="{{ form.initial.arrival_DT }}"
{% endif %}
/>
{% if not errors_off and form.errors and form.errors.arrival_DT %}
<span id="error_arrival_DT">{{ form.errors.arrival_DT }}</span>
@@ -229,7 +242,7 @@
<div class="poster__row poster__row--date">
{#date-to#}
<div class="poster__col">
<label for="arrival_DT" required class="poster__label col-12 ">
<label for="arrival_DT" class="poster__label col-12" required>
{{ l_date_to }}
</label>
<input
@@ -237,12 +250,13 @@
class="poster__date date"
id="arrival_DT"
name="arrival_DT"
readonly
value="{% if route.arrival_DT %}
{{ route.from_city.get_current_datetime }}
{% elif form.initial.arrival_DT %}
{{ form.initial.arrival_DT }}
{% endif %}"
placeholder="{% translate "Выберите дату" %}"
required
{% if route.arrival_DT %}
value="{{ route.from_city.get_current_datetime }}"
{% elif form.initial.arrival_DT %}
value="{{ form.initial.arrival_DT }}"
{% endif %}
/>
{% if not errors_off and form.errors and form.errors.arrival_DT %}
<span id="error_arrival_DT">{{ form.errors.arrival_DT }}</span>
@@ -254,12 +268,11 @@
id="departure_DT"
name="departure_DT"
hidden
value="
{% if route.departure_DT %}
{{ route.from_city.get_current_datetime }}
value="{{ route.from_city.get_current_datetime.strip }}"
{% elif form.initial.departure_DT %}
{{ form.initial.departure_DT }}
{% endif %}"
value="{{ form.initial.departure_DT }}"
{% endif %}
/>
</div>
</div>
@@ -271,8 +284,16 @@
<label for="phone" class="col-12">
{% translate "Контактный номер телефона, по которому с Вами могут связаться перевозчики" %}
</label>
<input class="col-12 col-xl-6" type="text" pattern="[0-9\-+]{5,}" maxlength="30"
placeholder="{% translate "Укажите телефон" %}" title="{% translate "Только цифры или - или +" %}">
<input id="phone"
name="phone"
class="col-12 col-xl-6"
type="text"
pattern="[0-9\-+]{5,}"
maxlength="30"
{% if form.initial.phone %}value="{{ form.initial.phone}}"{% endif %}
placeholder="{% translate "Укажите телефон" %}"
title="{% translate "Только цифры или - или +" %}"
>
<div class="poster__info">
{% translate "Если вы оставите это поле пустым - перевозчики смогут только написать вам в личные сообщения на нашем сайте TripWB.com" %}
</div>
@@ -281,16 +302,17 @@
{% endif %}
</div>
</div>
{#description#}
{#comment#}
<div class="poster__row poster__row--description">
<div class="poster__col col-12">
<label for="description" class="col-12">
<label for="comment" class="col-12">
{% translate "Примечание (необязательно)" %}
</label>
<textarea
name="description"
id="description"
name="comment"
id="comment"
value="{{ form.initial.comment }}"
maxlength="{{ maxLetterLength }}"
placeholder="{% translate "Если желаете, то здесь можно указать важную информацию, например: вес, габариты посылки, количество попутчиков и т.д.)" %}"
></textarea>
@@ -310,7 +332,7 @@
name="receive_msg_by_email"
class="cargo__inp"
{% if form.initial.receive_msg_by_email == True %}
checked="checked"
checked
{% endif %}
id="receive_msg_by_email">

View File

@@ -1,5 +1,5 @@
<div onmousedown='selectItemAddrPoint({{ id }}, "{{ name }} / {{ country__name }}", "{{ ctrl_name }}", "{{ timezone }}")' class="autocomplete-result" data-index="{{ index }}">
{# {% if airport_fullname %}<div>{{ airport_fullname|safe }}</div>{% endif %}#}
<div class="autocomplete-location">{{ name }} / {{ country__name }}</div>
<div class="poster__towns-item" data-attrs='[{{ id }}, "{{ name }}/{{ country__name }}", "{{ ctrl_name }}", "{{ timezone }}", "{{ MEDIA_URL }}{{ country__flag }}"]'>
<img src="{{ MEDIA_URL }}{{ country__flag }}" alt="{{ country__name }}" />
<span>BY{# {{ TODO нужны правильные значения }} #}</span>
{{ name }}/{{ country__name }}
</div>