Show Open/Closed status on listing block

Hey,

Would you be able to provide a snippets/guidance on how to best achieve the following idea, and/or, consider adding it as a baked-in feature, as well.

If you’re using the Opening Hours extension, it would be nice if we could add an optional status to the listing block that pulls from the opening hours information to display a dynamic ’ :green_circle: Open’ or ’ :red_circle: Closed’ label.

In my use-case, I’d like it displayed as a Block (Primary) item as I’m not currently showing anything else in that position other than the reply/favourite icons.

Cheers,
Chris :victory_hand:

Hi,

Thanks for your suggestion, we’ll consider adding this feature.

If you want to add this using a custom implementation, please use hook hivepress/v1/templates/listing_view_block and there you can add custom HTML checking $listing->get_opening_hours(), go through each of them, and thus display different labels using various conditions.

I hope it helps

Hi @andrii,

Thanks for your reply!

I’ve finally had a chance to play around with this idea and seem to have things working on my end.

Snippet for Available/Unavailable status:

add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_style( 'font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css' );
} );

add_filter( 'hivepress/v1/templates/listing_view_block', function( $template ) {
    // Function to get status HTML
    $get_status_html = function( $listing ) {
        if ( ! is_a( $listing, 'HivePress\Models\Listing' ) ) {
            error_log( 'Invalid listing object in get_status_html for listing ID: ' . ( $listing ? $listing->get_id() : 'unknown' ) );
            return '';
        }

        $listing_id = $listing->get_id();
        $opening_hours = $listing->get_opening_hours();
        $is_24_7 = $listing->is_always_open();

        error_log( 'Opening Hours for Listing ' . $listing_id . ': ' . print_r( $opening_hours, true ) );
        error_log( 'Listing ' . $listing_id . ' is_24_7: ' . ( $is_24_7 ? 'true' : 'false' ) );

        // If 24/7 is set, show available
        if ( $is_24_7 ) {
            error_log( 'Listing ' . $listing_id . ' detected as 24/7 open' );
            return '<span class="hp-listing__status status-icon available"><i class="fas fa-check-circle"></i> Available</span>';
        }

        // If no opening hours or not an array, hide the status
        if ( empty( $opening_hours ) || ! is_array( $opening_hours ) ) {
            error_log( 'No valid opening hours for Listing ' . $listing_id . ', hiding status' );
            return '';
        }

        // Get current day and time (BST, respecting WordPress timezone)
        $current_day = wp_date( 'l', current_time( 'timestamp' ) ); // e.g., 'Sunday'
        $current_time = wp_date( 'H:i', current_time( 'timestamp' ) ); // e.g., '15:32'

        // Check if current day exists in opening hours
        if ( ! isset( $opening_hours[ $current_day ] ) || empty( $opening_hours[ $current_day ] ) ) {
            error_log( 'No hours set for ' . $current_day . ' in Listing ' . $listing_id );
            return '<span class="hp-listing__status status-icon unavailable"><i class="fas fa-times-circle"></i> Unavailable</span>';
        }

        // Get open and close times
        $open_time = $opening_hours[ $current_day ]['open'] ?? '';
        $close_time = $opening_hours[ $current_day ]['close'] ?? '';

        error_log( 'Listing ' . $listing_id . ' on ' . $current_day . ': open=' . $open_time . ', close=' . $close_time . ', current=' . $current_time );

        // Validate times
        if ( empty( $open_time ) || empty( $close_time ) ) {
            error_log( 'Invalid open/close times for Listing ' . $listing_id );
            return '<span class="hp-listing__status status-icon unavailable"><i class="fas fa-times-circle"></i> Unavailable</span>';
        }

        // Handle 24/7 case (e.g., open and close are 00:00 or 23:59)
        if ( $open_time === '00:00' && ( $close_time === '00:00' || $close_time === '23:59' ) ) {
            error_log( 'Listing ' . $listing_id . ' detected as 24/7 open (time-based)' );
            return '<span class="hp-listing__status status-icon available"><i class="fas fa-check-circle"></i> Available</span>';
        }

        // Compare times
        $is_open = $current_time >= $open_time && $current_time < $close_time;
        error_log( 'Listing ' . $listing_id . ' is_open=' . ( $is_open ? 'true' : 'false' ) );

        if ( $is_open ) {
            return '<span class="hp-listing__status status-icon available"><i class="fas fa-check-circle"></i> Available</span>';
        } else {
            return '<span class="hp-listing__status status-icon unavailable"><i class="fas fa-times-circle"></i> Unavailable</span>';
        }
    };

    // Get the listing from the template context
    $listing = $template['context']['listing'] ?? null;
    $status_html = '';

    if ( $listing && is_a( $listing, 'HivePress\Models\Listing' ) ) {
        $status_html = $get_status_html( $listing );
    } else {
        error_log( 'Listing context missing or invalid in listing_view_block filter' );
    }

    // Add status block to the primary area
    return hivepress()->helper->merge_trees(
        $template,
        [
            'blocks' => [
                'listing_actions_primary' => [
                    'blocks' => [
                        'listing_status' => [
                            'type'   => 'content',
                            'content' => $status_html, // Pre-rendered string
                            '_order' => 50,
                        ],
                    ],
                ],
            ],
        ]
    );
} );

Alternate Snippet for Open/Closed text status:

add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_style( 'font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css' );
} );

add_filter( 'hivepress/v1/templates/listing_view_block', function( $template ) {
    // Function to get status HTML
    $get_status_html = function( $listing ) {
        if ( ! is_a( $listing, 'HivePress\Models\Listing' ) ) {
            error_log( 'Invalid listing object in get_status_html for listing ID: ' . ( $listing ? $listing->get_id() : 'unknown' ) );
            return '';
        }

        $listing_id = $listing->get_id();
        $opening_hours = $listing->get_opening_hours();
        $is_24_7 = $listing->is_always_open();

        error_log( 'Opening Hours for Listing ' . $listing_id . ': ' . print_r( $opening_hours, true ) );
        error_log( 'Listing ' . $listing_id . ' is_24_7: ' . ( $is_24_7 ? 'true' : 'false' ) );

        // If 24/7 is set, show open
        if ( $is_24_7 ) {
            error_log( 'Listing ' . $listing_id . ' detected as 24/7 open' );
            return '<span class="hp-listing__status status-icon open"><i class="fas fa-check-circle"></i> Open</span>';
        }

        // If no opening hours or not an array, hide the status
        if ( empty( $opening_hours ) || ! is_array( $opening_hours ) ) {
            error_log( 'No valid opening hours for Listing ' . $listing_id . ', hiding status' );
            return '';
        }

        // Get current day and time (BST, respecting WordPress timezone)
        $current_day = wp_date( 'l', current_time( 'timestamp' ) ); // e.g., 'Sunday'
        $current_time = wp_date( 'H:i', current_time( 'timestamp' ) ); // e.g., '15:32'

        // Check if current day exists in opening hours
        if ( ! isset( $opening_hours[ $current_day ] ) || empty( $opening_hours[ $current_day ] ) ) {
            error_log( 'No hours set for ' . $current_day . ' in Listing ' . $listing_id );
            return '<span class="hp-listing__status status-icon closed"><i class="fas fa-times-circle"></i> Closed</span>';
        }

        // Get open and close times
        $open_time = $opening_hours[ $current_day ]['open'] ?? '';
        $close_time = $opening_hours[ $current_day ]['close'] ?? '';

        error_log( 'Listing ' . $listing_id . ' on ' . $current_day . ': open=' . $open_time . ', close=' . $close_time . ', current=' . $current_time );

        // Validate times
        if ( empty( $open_time ) || empty( $close_time ) ) {
            error_log( 'Invalid open/close times for Listing ' . $listing_id );
            return '<span class="hp-listing__status status-icon closed"><i class="fas fa-times-circle"></i> Closed</span>';
        }

        // Handle 24/7 case (e.g., open and close are 00:00 or 23:59)
        if ( $open_time === '00:00' && ( $close_time === '00:00' || $close_time === '23:59' ) ) {
            error_log( 'Listing ' . $listing_id . ' detected as 24/7 open (time-based)' );
            return '<span class="hp-listing__status status-icon open"><i class="fas fa-check-circle"></i> Open</span>';
        }

        // Compare times
        $is_open = $current_time >= $open_time && $current_time < $close_time;
        error_log( 'Listing ' . $listing_id . ' is_open=' . ( $is_open ? 'true' : 'false' ) );

        if ( $is_open ) {
            return '<span class="hp-listing__status status-icon open"><i class="fas fa-check-circle"></i> Open</span>';
        } else {
            return '<span class="hp-listing__status status-icon closed"><i class="fas fa-times-circle"></i> Closed</span>';
        }
    };

    // Get the listing from the template context
    $listing = $template['context']['listing'] ?? null;
    $status_html = '';

    if ( $listing && is_a( $listing, 'HivePress\Models\Listing' ) ) {
        $status_html = $get_status_html( $listing );
    } else {
        error_log( 'Listing context missing or invalid in listing_view_block filter' );
    }

    // Add status block to the primary area
    return hivepress()->helper->merge_trees(
        $template,
        [
            'blocks' => [
                'listing_actions_primary' => [
                    'blocks' => [
                        'listing_status' => [
                            'type'   => 'content',
                            'content' => $status_html, // Pre-rendered string
                            '_order' => 50, // Before reply/favorite icons (adjust to 10-20 for after)
                        ],
                    ],
                ],
            ],
        ]
    );
} );

CSS:

/* Style the status text and icon */
.hp-listing__status.status-icon.available {
    color: green;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    margin-left: 155px;
}

/* Style the unavailable status */
.hp-listing__status.status-icon.unavailable {
    color: red;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    margin-left: 155px;
}

/* Responsive adjustments for tablets */
@media (max-width: 768px) {
    .hp-listing__status.status-icon.available,
    .hp-listing__status.status-icon.unavailable {
        margin-left: 440px;
        font-size: 13px;
    }
}

/* Responsive adjustments for smaller screens */
@media (max-width: 450px) {
    .hp-listing__status.status-icon.available,
    .hp-listing__status.status-icon.unavailable {
        margin-left: 100px;
        font-size: 12px;
    }
}

/* Space between icon and text in status */
.hp-listing__status i {
    margin-right: 5px; /* Adjust spacing between icon and text */
}

Result:

Shows an Available / Unavailable status where applicable, and hides the status if no opening hours are set.

image
image
image

Cheers,
Chris :victory_hand:

Hi,

Thank you for your solution, it will be useful for our community.

Hey @andrii,

I’m going to try and adjust the code, so that it uses the information from the Bookings extension instead of the Openings Hours extension. Could you please provide guidance on the best approach to check if the current day/time falls between the booking time ranges specified for each listing.

Many thanks in advance!

Cheers,
Chris :victory_hand:

Hi Chris,

The booking from/to times are stored in the booking_min_time and booking_max_time meta fields for a listing (or you can use the same field names to access them via the HivePress listing object). To show the custom status, you can try checking the current timestamp via time() and calculate the number of seconds since midnight (this is how the booking from/to times are stored) and compare them php - How to get seconds elapsed since midnight - Stack Overflow

Hope this helps

1 Like

Many thanks as always, @Ihor.

I’m tweaking some other parts of my site at the moment, but I’ll give this a try soon!

Cheers,
Chris :victory_hand:

Thanks again for your help, Ihor!

I managed to get the custom availability status showing whilst taking the booking days and start from/to times from a listing into consideration.

However, I’ve realised I need to implement a few more checks to determine if a listing is actually available or not.

Would you be able to tell me how I can check if the vendor has blocked the dates in their calendar. As, if these dates = current date, this should show as unavailable.

Also, if the current time is whilst an existing booking is taking place, the status would also show as unavailable.

I hope that makes sense!

Cheers,
Chris :victory_hand:

I recommend using this helper function Loom | Free Screen & Video Recording Software | Loom You can access it via hivepress()->booking->get_overlapping_query(... and check examples on how it’s used in the Bookings code. This way you can check if any given date range already contains bookings or blocked dates.

Hope this helps

1 Like

Many thanks for your help, @ihor!

I’m tinkering with a few ideas at the moment, but I’ll get back to trying this soon and report back.

Cheers,
Chris :victory_hand:

Thanks again for all of your help with this, @ihor!

Things seems to be working smoothly. I’ve now merged two ideas I had into one, and utilised the helper function to display a range of different custom badges depending on certain criteria for each listing.

:partying_face:

Cheers,
Chris :victory_hand:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.