MHM Rentiva v4.26.5: Vendor Dashboard Identity Card and Messaging Parity Fixes
v4.26.5 delivers the results of an extended UX polish session on the vendor dashboard: a premium identity card (Gravatar + last login) at the bottom of the left menu, a fix for vendor bookings not appearing in the messaging form, a premium redesign of message list cards, and a set of silent bug fixes alongside.
👤 Vendor Dashboard Identity Card
The vendor dashboard's left menu previously showed only the username and a "Log Out" link. Now it includes:
- Gravatar photo (40 px, rounded, white border, soft shadow)
- User display name (overflow controlled with ellipsis)
- Last successful login date and time (e.g.
Last login: 15/04/2026 04:57) - Log Out button moved outside the card as a standalone action; turns red on hover.
<?php
$last_login_raw = (string) get_user_meta($user->ID, 'last_login', true);
if ($last_login_raw !== '') {
$ts = strtotime($last_login_raw);
if ($ts) {
echo date_i18n(get_option('date_format') . ' H:i', $ts);
}
}
?>
last_login user meta — a key read but never written
An interesting discovery: the last_login user meta was already being read in our GDPR/Privacy and DataRetentionManager code — but was never written anywhere. This meant "this user hasn't logged in for N days" decisions in data retention calculations were always based on an empty value.
v4.26.5 closes this gap: SessionManager::set_session_timeout() now accepts the second parameter of the wp_login action (WP_User $user) and updates last_login with current_time('mysql').
add_action('wp_login', array(self::class, 'set_session_timeout'), 10, 2);
public static function set_session_timeout($user_login = '', $user = null): void
{
$user_id = ($user instanceof \WP_User) ? (int) $user->ID : get_current_user_id();
if (! $user_id) return;
update_user_meta($user_id, 'mhm_rentiva_last_activity', time());
update_user_meta($user_id, 'last_login', current_time('mysql'));
}
📥 Messaging: Vendors Now See Their Own Bookings
The Related Booking dropdown in the "New Message" form always came up empty — from the vendor's perspective. The REST endpoint only queried the _mhm_customer_user_id meta, i.e. "bookings I made as a customer". Bookings made by others on the vendor's own vehicles were not visible.
The fix: the endpoint runs two queries, merges the results by ID, deduplicates them, and sorts by post_date DESC:
// Customer-side: the user who made the booking
$customer_query = new WP_Query([
'post_type' => 'vehicle_booking',
'meta_query' => [[
'key' => '_mhm_customer_user_id',
'value' => $user_id,
]],
]);
// Vendor-side: bookings on vehicles owned by this vendor
$vendor_vehicle_ids = get_posts([
'post_type' => 'vehicle',
'author' => $user_id,
'posts_per_page' => -1,
'fields' => 'ids',
]);
if (!empty($vendor_vehicle_ids)) {
$vendor_query = new WP_Query([
'post_type' => 'vehicle_booking',
'meta_query' => [[
'key' => '_mhm_vehicle_id',
'value' => $vendor_vehicle_ids,
'compare' => 'IN',
]],
]);
}
🎨 Premium Message List Cards
Message list cards have moved from plain white boxes to a premium design:
- Gradient background (
#ffffff → #fafbff) - Purple pill ID badge (
#4F46E5background,#eef2fffill) - Orange gradient "NEW" label (
#f59e0b → #f97316, box-shadow amber glow) - On hover, an indigo accent bar appears on the card's left edge and the card lifts 2 px
- Unread state uses an amber background + left accent bar
- Mobile breakpoint: padding and typography adapt automatically
🗂️ .hidden — A Rule We Didn't Know Was Missing
The messages page template has three views:
- Message list
- Conversation (thread) view
- New message form
The template tried to hide all three with class="hidden" initially — but the .hidden CSS rule was defined nowhere. As a result, all three rendered as display: block simultaneously. When the user scrolled down, they saw a confusing stack of overlapping panels.
The fix is a CSS utility:
.mhm-messages-section .hidden,
.mhm-messages-section .thread-reply.hidden,
.mhm-messages-section .new-message-form.hidden,
.mhm-messages-section .message-thread.hidden {
display: none !important;
}
Now the three views are mutually exclusive: whichever is active is shown; the others are hidden.
🔁 No More Button Accumulation When Reopening a Thread
When a thread was closed and reopened, the "Close Message" button and "This conversation is closed" notice banner were appended to the DOM again without removing the stale elements first. The result: opening the same thread twice showed two "Close Message" buttons.
// Remove stale elements before re-rendering
$('#message-thread .close-thread-btn').remove();
$('#message-thread .thread-closed-notice').remove();
🔣 Mojibake Box and Translation Fixes
- The back-arrow (
←) before the "Back to Messages" text intemplates/account/messages.phpwas double-encoded UTF-8 (rendered asâ†) and a stray C1 control byte (0xC2 0x90) remained in the template. Fix:<span aria-hidden="true">←</span>HTML entity + PowerShell script to strip the C1 byte. - In the Turkish
.pofile, the "Booking Association" label was translated as "Rezervasyon Derneği" (Booking Society) 😄 — corrected to "İlgili Rezervasyon".
📦 Filemtime Cache Busting
During this session we hit the "browser cache keeps serving old CSS/JS" loop twice. To prevent this going forward, asset enqueues now use filemtime versioning:
$customer_messages_css_ver = file_exists($path)
? MHM_RENTIVA_VERSION . '.' . filemtime($path)
: MHM_RENTIVA_VERSION;
wp_enqueue_style('mhm-customer-messages', $url, [], $customer_messages_css_ver);
Even when the plugin version stays the same, every file change produces a unique query string like ?ver=4.26.5.1744742822 — the browser never serves the old file.
✅ Tests
720 tests, 2601 assertions, 6 skipped — fully green. No regressions.
Download
- GitHub Release v4.26.5
- ZIP asset:
mhm-rentiva.4.26.5.zip(2.61 MB, 764 files)
The next minor version (v4.27.0) is dedicated to the vendor report and dispute system — a unified infrastructure for booking, penalty, and vehicle reports.
