Snap reservation only to available dates on the gridpositions

This commit is contained in:
jordi fita mas 2025-01-24 17:13:00 +01:00
parent 579b4f3f55
commit 8c222c6f6b
5 changed files with 74 additions and 3 deletions

View File

@ -7,6 +7,8 @@ Label {
required property Item dragParent required property Item dragParent
required property string holder required property string holder
required property int nights
required property int reservationId
required property string reservationStatus required property string reservationStatus
Drag.active: dragHandler.active Drag.active: dragHandler.active

View File

@ -189,13 +189,48 @@ Control {
} }
DropArea { DropArea {
property int prevDay
property int prevLodging
function addDays(date, days) {
var newDate = new Date(date);
newDate.setDate(date.getDate() + days);
return newDate;
}
function findDayAndLodging(drag: DragEvent): list<int> {
const pos = timelineList.contentItem.mapFromItem(this, drag.x, drag.y);
const day = Math.floor(pos.x / control.dayWidth);
const lodging = Math.floor(pos.y / control.rowHeight);
return [day, lodging];
}
function isSpotAvailable(day: int, lodging: int, reservation: Reservation): bool {
const view = timelineList.itemAtIndex(lodging);
if (!view) {
return false;
}
return view.timeline.areDatesAvailable(addDays(control.fromDate, day), addDays(control.fromDate, day + reservation.nights), reservation.reservationId);
}
anchors.fill: timelineList anchors.fill: timelineList
anchors.leftMargin: -30 * control.dayWidth anchors.leftMargin: -30 * control.dayWidth
onEntered: function (drag) {
[prevDay, prevLodging] = findDayAndLodging(drag);
}
onPositionChanged: function (drag) { onPositionChanged: function (drag) {
const pos = timelineList.contentItem.mapFromItem(this, drag.x, drag.y); let [day, lodging] = findDayAndLodging(drag);
drag.source.y = (Math.floor(pos.y / control.rowHeight)) * control.rowHeight; if ((day != prevDay || lodging != prevLodging) && isSpotAvailable(day, lodging, drag.source)) {
drag.source.x = (Math.floor(pos.x / control.dayWidth) + .5) * control.dayWidth; prevDay = day;
prevLodging = lodging;
} else {
day = prevDay;
lodging = prevLodging;
}
drag.source.y = lodging * control.rowHeight;
drag.source.x = (day + .5) * control.dayWidth;
} }
} }
} }

View File

@ -16,6 +16,31 @@ void TimelineModel::update(const QList<Item *> &items)
m_items.assign(items.begin(), items.end()); m_items.assign(items.begin(), items.end());
} }
bool TimelineModel::areDatesAvailable(QDate arrival, QDate departure, int excludedId) const
{
auto [begin, end] = indexesOf(arrival, departure);
if (begin == end) {
return true;
}
const Item *first = m_items.at(begin);
if (first->id == excludedId) {
begin++;
if (begin == end) {
return true;
}
first = m_items.at(begin);
}
const Item *last = m_items.at(end - 1);
if (last->id == excludedId) {
--end;
if (begin == end) {
return true;
}
last = m_items.at(end - 1);
}
return arrival >= last->departure() || departure <= first->arrival;
}
std::pair<qsizetype, qsizetype> TimelineModel::indexesOf(QDate from, QDate to) const std::pair<qsizetype, qsizetype> TimelineModel::indexesOf(QDate from, QDate to) const
{ {
qsizetype begin = searchIndex(from); qsizetype begin = searchIndex(from);
@ -31,6 +56,10 @@ std::pair<qsizetype, qsizetype> TimelineModel::indexesOf(QDate from, QDate to) c
} }
} }
if (begin == 0 && m_items.at(begin)->arrival >= to) {
return std::make_pair(begin, begin);
}
for (qsizetype end = begin + 1; end < m_items.count(); end++) { for (qsizetype end = begin + 1; end < m_items.count(); end++) {
if (m_items.at(end)->arrival >= to) { if (m_items.at(end)->arrival >= to) {
return std::make_pair(begin, end); return std::make_pair(begin, end);

View File

@ -31,6 +31,7 @@ public:
void update(const QList<Item *> &items); void update(const QList<Item *> &items);
Q_INVOKABLE bool areDatesAvailable(QDate arrival, QDate departure, int excludeId) const;
std::pair<qsizetype, qsizetype> indexesOf(QDate from, QDate to) const; std::pair<qsizetype, qsizetype> indexesOf(QDate from, QDate to) const;
const Item *at(qsizetype index) const; const Item *at(qsizetype index) const;

View File

@ -174,6 +174,8 @@ TimelineView::Item *TimelineView::createItem(qint64 day, const TimelineModel::It
if (m_reusableItems.isEmpty()) { if (m_reusableItems.isEmpty()) {
QVariantMap initialProperties{ QVariantMap initialProperties{
{"holder", modelItem.holder}, {"holder", modelItem.holder},
{"nights", modelItem.nights},
{"reservationId", modelItem.id},
{"reservationStatus", modelItem.status}, {"reservationStatus", modelItem.status},
}; };
item = qobject_cast<QQuickItem *>( item = qobject_cast<QQuickItem *>(
@ -186,6 +188,8 @@ TimelineView::Item *TimelineView::createItem(qint64 day, const TimelineModel::It
} else { } else {
item = m_reusableItems.takeLast(); item = m_reusableItems.takeLast();
item->setProperty("holder", modelItem.holder); item->setProperty("holder", modelItem.holder);
item->setProperty("nights", modelItem.nights);
item->setProperty("reservationId", modelItem.id);
item->setProperty("reservationStatus", modelItem.status); item->setProperty("reservationStatus", modelItem.status);
} }
auto *viewItem = new TimelineView::Item(day, modelItem.nights, *item, *this); auto *viewItem = new TimelineView::Item(day, modelItem.nights, *item, *this);