{"id":466,"date":"2025-10-07T16:59:06","date_gmt":"2025-10-07T16:59:06","guid":{"rendered":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/?page_id=466"},"modified":"2025-10-07T16:59:06","modified_gmt":"2025-10-07T16:59:06","slug":"groups","status":"publish","type":"page","link":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/groups\/","title":{"rendered":"Groups"},"content":{"rendered":"<div class=\"buddyUpPjaxContainer\" data-buddyup-pjax-container=\"1\"><style>@media (max-width: 1000px) {\n\t#buddyUpGroupFilterMobileButton {\n\t\tmargin: 0 0 .65rem auto;\n\t}\n}\n\n.buddyUpFilterDropdownToggle {\n\twidth: 100%;\n\ttext-align: left;\n\tmargin-top: .35rem;\n\tmargin-bottom: .35rem;\n}\n\n.buddyUpFilterDropdownMenu {\n\tborder: 1px solid rgba(0,0,0,.12);\n\tborder-radius: var(--border-radius);\n\tbackground: #fff;\n\tmax-height: 220px;\n\toverflow: auto;\n\tpadding: .4rem .55rem;\n}\n\n.buddyUpFilterCheckboxList {\n\tdisplay: grid;\n\tgap: .3rem;\n}\n\n.buddyUpFilterCheckboxItem {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: .45rem;\n\tfont-size: .95rem;\n}\n<\/style><section id=\"buddyUpGroupsSearchWrapper\" class=\"buddyUpContainer buddyUp\">\n    <div class=\"buddyUpHeaderWrapper flexWrapper\">\n        <h1 class=\"textH1\">Join a group and explore together<\/h1>\n        <div>\n            <button id=\"buddyUpCreateGroupButton\" class=\"buddyUpCreateGroupButton buddyUpButton1 hidden\" aria-label=\"Create a group\" disabled=\"disabled\">Create a Group<\/button>\n        <\/div>\n    <\/div>\n    <div id=\"buddyUpGroupsTabs\" class=\"buddyUpListTabs\">\n        <div class=\"buddyUpListTabButtons\" role=\"tablist\" aria-label=\"Groups tabs\">\n            <button id=\"buddyUpGroupsTabSearch\" type=\"button\" class=\"buddyUpButton1 buddyUpListTabButton isActive\" data-tab=\"search\" role=\"tab\" aria-selected=\"true\">Search<\/button>\n            <button id=\"buddyUpGroupsTabMy\" type=\"button\" class=\"buddyUpButton3 buddyUpListTabButton\" data-tab=\"my\" role=\"tab\" aria-selected=\"false\">My<\/button>\n            <button id=\"buddyUpGroupsTabJoined\" type=\"button\" class=\"buddyUpButton3 buddyUpListTabButton\" data-tab=\"joined\" role=\"tab\" aria-selected=\"false\">Joined<\/button>\n        <\/div>\n\n        <div class=\"buddyUpListTabPanels\">\n            <section class=\"buddyUpListTabPanel isActive\" data-tab-panel=\"search\" role=\"tabpanel\" aria-labelledby=\"buddyUpGroupsTabSearch\">\n                <div class=\"flexWrapper buddyUpSearchWrapper \">\n                    <aside id=\"groupSearchSidebar\" class=\"buddyUpSearchSidebar buddyUpElWrapper buddyUpFiltersShelf\" aria-hidden=\"true\">\n                        <form id=\"groupsSearchForm\" class=\"buddyUpSearchSidebarSection\">\n                            <label for=\"groupsTextSearch\" aria-label=\"Type to search for groups\">Search by name<\/label>\n                            <div class=\"buddyUpSearchButtonInput\">\n                                <input type=\"text\" id=\"groupsTextSearch\" name=\"groupsTextSearch\" aria-label=\"Type to search for groups\" placeholder=\"Hiking\" required \/>\n                                <button type=\"submit\" id=\"groupSearchButton\" class=\"buddyUpButton1\" aria-label=\"Search for group\"><i class=\"fa fa-search\"><\/i><\/button>\n                            <\/div>\n                        <\/form>\n\n                        <form id=\"groupsSearchByLocationForm\" class=\"buddyUpSearchSidebarSection\">\n                            <label for=\"groupsTextSearchByLocation\" aria-label=\"Type to search for groups by location\">Search by location<\/label>\n                            <div class=\"buddyUpSearchButtonInput\">\n                                <input type=\"text\" id=\"groupsTextSearchByLocation\" name=\"groupsTextSearchByLocation\" aria-label=\"Type a location to search for nearby groups\" placeholder=\"Address, city, state, or zip\" \/>\n                            <\/div>\n                            <input type=\"hidden\" id=\"groupsLocationLatitude\" value=\"\" \/>\n                            <input type=\"hidden\" id=\"groupsLocationLongitude\" value=\"\" \/>\n                            <div id=\"groupsLocationSearchHint\" class=\"textSmall\" style=\"margin-top:.35rem; opacity:.85;\"><\/div>\n                        <\/form>\n\n                        <div class=\"buddyUpSearchSidebarSection\">\n                            <label for=\"groupsFilterRadius\">Radius<\/label>\n                            <select id=\"groupsFilterRadius\">\n                                <option value=\"0\" selected>Any distance<\/option>\n                                <option value=\"10\">Within 10 miles<\/option>\n                                <option value=\"25\">Within 25 miles<\/option>\n                                <option value=\"50\">Within 50 miles<\/option>\n                                <option value=\"100\">Within 100 miles<\/option>\n                            <\/select>\n                        <\/div>\n\n                        <div class=\"buddyUpSearchSidebarSection\">\n                            <div class=\"buddyUpCheckboxWrapper\">\n                                <input type=\"checkbox\" id=\"groupsFilterMyInterests\" \/>\n                                <label for=\"groupsFilterMyInterests\">My interests<\/label>\n                            <\/div>\n                        <\/div>\n\n                        <div id=\"groupsSidebarInterestWrapper\" class=\"buddyUpSearchSidebarSection hidden\">\n                            <strong>Categories<\/strong><br\/>\n                            <button type=\"button\" id=\"groupsInterestsDropdownToggle\" class=\"buddyUpButton3 buddyUpFilterDropdownToggle\" aria-expanded=\"false\">Choose categories<\/button>\n                            <div id=\"groupsInterestsDropdownMenu\" class=\"buddyUpFilterDropdownMenu hidden\">\n                                <div id=\"interestsFilterList\" class=\"buddyUpFilterCheckboxList\"><\/div>\n                            <\/div>\n                        <\/div>\n\n                        <button id=\"filtersSearchMobile\" class=\"buddyUpButton1\">Apply Filters<\/button>\n                    <\/aside>\n\n                    <div class=\"groupsWrapper buddyUpSearchListWrapper\">\n                        <div id=\"groupsListWrapper\" class=\"buddyUpGroupsList buddyUpSearchList\"><\/div>\n                    <\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"buddyUpListTabPanel\" data-tab-panel=\"my\" role=\"tabpanel\" aria-labelledby=\"buddyUpGroupsTabMy\" hidden>\n                <div class=\"buddyUpElWrapper buddyUpMySection\">\n                    <div class=\"buddyUpMySectionHeader\">\n                        <h2 class=\"textHeading\" style=\"margin:0;\">My Groups<\/h2>\n                        <div class=\"textSmall\" id=\"buddyUpMyGroupsSummary\"><\/div>\n                    <\/div>\n                    <div id=\"buddyUpMyGroupsOwnedList\" class=\"buddyUpMySectionList\"><\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"buddyUpListTabPanel\" data-tab-panel=\"joined\" role=\"tabpanel\" aria-labelledby=\"buddyUpGroupsTabJoined\" hidden>\n                <div class=\"buddyUpElWrapper buddyUpMySection\">\n                    <div class=\"buddyUpMySectionHeader\">\n                        <h2 class=\"textHeading\" style=\"margin:0;\">Joined Groups<\/h2>\n                    <\/div>\n                    <div id=\"buddyUpMyGroupsJoinedList\" class=\"buddyUpMySectionList\"><\/div>\n                <\/div>\n            <\/section>\n        <\/div>\n    <\/div>\n\n    <button class=\"buddyUpSideTab\" data-target=\"groupSearchSidebar\" aria-controls=\"groupSearchSidebar\" aria-expanded=\"false\" aria-label=\"Open filters\">\n        <i class=\"fa-solid fa-sliders\" aria-hidden=\"true\"><\/i>\n        <span>Filters<\/span>\n    <\/button>\n<\/section><script>(async function () {\n    const currentUser = BUDDYUP.getCurrentUser();\n    const wrapper = document.getElementById('buddyUpGroupsSearchWrapper');\n    const groupCreateButton = document.getElementById('buddyUpCreateGroupButton');\n\n    if (!wrapper) return;\n\n    if (!currentUser || !currentUser.id) {\n        document.body.style.background = 'var(--buddyup-background)';\n        const errMessageContent = `<p>Please log in or register to search for groups!<\/p>\n            <a href=\"${buddyUpVariables.login_link}\" class=\"buddyUpButton1\">Log in<\/a>\n            <a href=\"${buddyUpVariables.register_link}\" class=\"buddyUpButton1\" style=\"margin-left:.5rem;\">Sign Up<\/a>`;\n        wrapper.innerHTML = BUDDYUP.errorPage('Please log in', errMessageContent);\n        return;\n    }\n\n    const userId = Number(currentUser.id || 0);\n    const tabsRoot = document.getElementById('buddyUpGroupsTabs');\n    const tabButtons = tabsRoot ? tabsRoot.querySelectorAll('.buddyUpListTabButton[data-tab]') : [];\n    const tabPanels = tabsRoot ? tabsRoot.querySelectorAll('.buddyUpListTabPanel[data-tab-panel]') : [];\n\n    const groupsListWrapper = document.getElementById('groupsListWrapper');\n    const mySummaryEl = document.getElementById('buddyUpMyGroupsSummary');\n    const myOwnedEl = document.getElementById('buddyUpMyGroupsOwnedList');\n    const joinedEl = document.getElementById('buddyUpMyGroupsJoinedList');\n\n    let updateGroupsTimer = null;\n    const groupsGeoCache = {};\n\n    const locationSearchEl = document.getElementById('groupsTextSearchByLocation');\n    const locationHintEl = document.getElementById('groupsLocationSearchHint');\n    const locationLatEl = document.getElementById('groupsLocationLatitude');\n    const locationLngEl = document.getElementById('groupsLocationLongitude');\n    const radiusSelectEl = document.getElementById('groupsFilterRadius');\n    const myInterestsEl = document.getElementById('groupsFilterMyInterests');\n    const interestsToggleBtn = document.getElementById('groupsInterestsDropdownToggle');\n    const interestsDropdownMenu = document.getElementById('groupsInterestsDropdownMenu');\n\n    const haversineMiles = (lat1, lon1, lat2, lon2) => {\n        const toRad = (d) => d * (Math.PI \/ 180);\n        const R = 3958.8;\n        const dLat = toRad(lat2 - lat1);\n        const dLon = toRad(lon2 - lon1);\n        const a = Math.sin(dLat \/ 2) * Math.sin(dLat \/ 2) +\n            Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *\n            Math.sin(dLon \/ 2) * Math.sin(dLon \/ 2);\n        return R * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));\n    };\n\n    const groupLocationText = (group) => {\n        const parts = [\n            group && group.address_1 ? String(group.address_1) : '',\n            group && group.city ? String(group.city) : '',\n            group && group.state ? String(group.state) : '',\n            group && group.zip ? String(group.zip) : '',\n        ].filter(Boolean);\n        return parts.join(', ');\n    };\n\n    const resolveGeoText = async (text) => {\n        const q = String(text || '').trim();\n        if (q === '') return null;\n\n        const key = q.toLowerCase();\n        if (groupsGeoCache[key]) return groupsGeoCache[key];\n\n        const rows = await BUDDYUP.locationAutocompleteSearch(q);\n        if (!Array.isArray(rows) || rows.length === 0) return null;\n\n        const first = rows[0];\n        if (!first || !isFinite(Number(first.latitude)) || !isFinite(Number(first.longitude))) return null;\n\n        const point = {\n            latitude: Number(first.latitude),\n            longitude: Number(first.longitude),\n            label: String(first.label || q),\n        };\n        groupsGeoCache[key] = point;\n        return point;\n    };\n\n    const filterByRadius = async (rows, center, miles) => {\n        if (!Array.isArray(rows) || !center || !isFinite(Number(center.latitude)) || !isFinite(Number(center.longitude)) || !isFinite(Number(miles)) || Number(miles) <= 0) {\n            return Array.isArray(rows) ? rows : [];\n        }\n\n        const out = [];\n        for (let i = 0; i < rows.length; i++) {\n            const row = rows[i];\n            const text = groupLocationText(row);\n            if (!text) continue;\n\n            const point = await resolveGeoText(text);\n            if (!point) continue;\n\n            const distance = haversineMiles(\n                Number(center.latitude),\n                Number(center.longitude),\n                Number(point.latitude),\n                Number(point.longitude)\n            );\n\n            if (distance <= Number(miles)) {\n                out.push(row);\n            }\n        }\n\n        return out;\n    };\n\n    const activateTab = (tabName) => {\n        tabButtons.forEach((btn) => {\n            const active = btn.getAttribute('data-tab') === tabName;\n            btn.classList.toggle('isActive', active);\n            btn.classList.toggle('buddyUpButton1', active);\n            btn.classList.toggle('buddyUpButton3', !active);\n            btn.setAttribute('aria-selected', active ? 'true' : 'false');\n        });\n\n        tabPanels.forEach((panel) => {\n            const active = panel.getAttribute('data-tab-panel') === tabName;\n            panel.classList.toggle('isActive', active);\n            panel.hidden = !active;\n        });\n    };\n\n    tabButtons.forEach((btn) => {\n        btn.addEventListener('click', () => {\n            activateTab(String(btn.getAttribute('data-tab') || 'search'));\n        });\n    });\n\n    const normalizeGroupId = (group) => {\n        const id = Number(group && (group.id || group.group_id || group.groupId || 0));\n        return Number.isFinite(id) && id > 0 ? id : 0;\n    };\n\n    const groupOwnerId = (group) => Number(\n        group && (\n            group.group_owner ||\n            group.owner_id ||\n            (group.owner && group.owner.id) ||\n            group.user_id ||\n            group.created_by ||\n            0\n        )\n    );\n\n    const isOwnedGroup = (group) => {\n        const ownerId = groupOwnerId(group);\n        return ownerId > 0 && ownerId === userId;\n    };\n\n    const isJoinedGroup = (group) => {\n        if (!group) return false;\n\n        if (group.is_joined === true || Number(group.is_joined) === 1) return true;\n\n        const membershipStatus = String(group.membership_status || '').toLowerCase();\n        if (membershipStatus === 'member' || membershipStatus === 'organizer' || membershipStatus === 'owner' || membershipStatus === 'joined') {\n            return true;\n        }\n\n        const members = Array.isArray(group.members) ? group.members : [];\n        return members.some((member) => Number(member && (member.id || member.user_id || 0)) === userId);\n    };\n\n    const renderGroupList = (targetEl, groups, emptyText, roleLabel) => {\n        if (!targetEl) return;\n\n        if (!Array.isArray(groups) || groups.length === 0) {\n            targetEl.innerHTML = `<div class=\"textSmall buddyUpMySectionEmpty\">${emptyText}<\/div>`;\n            return;\n        }\n\n        targetEl.innerHTML = groups.map((group) => `\n            <div class=\"buddyUpMySectionItem\">\n                ${roleLabel ? `<div class=\"buddyUpMySectionRole\">${roleLabel}<\/div>` : ''}\n                ${BUDDYUP.groupCardElement(group)}\n            <\/div>\n        `).join('');\n    };\n\n    const accountGroups = (accountResp) => {\n        if (accountResp && Array.isArray(accountResp.groups)) return accountResp.groups;\n        if (accountResp && accountResp.data && Array.isArray(accountResp.data.groups)) return accountResp.data.groups;\n        return [];\n    };\n\n    async function loadConnectedGroups() {\n        if (!myOwnedEl || !joinedEl) return;\n\n        myOwnedEl.innerHTML = BUDDYUP.loading('Loading your groups');\n        joinedEl.innerHTML = BUDDYUP.loading('Loading joined groups');\n\n        const accountResp = await BUDDYUP.apiRequest('account-get', {\n            id: userId,\n            include: 'groups',\n            fields: 'id,groups'\n        });\n        if (!accountResp || accountResp.status !== 'success') {\n            renderGroupList(myOwnedEl, [], 'Could not load owned groups right now.');\n            renderGroupList(joinedEl, [], 'Could not load joined groups right now.');\n            if (mySummaryEl) mySummaryEl.textContent = '';\n            return;\n        }\n\n        const groups = accountGroups(accountResp);\n        const seen = new Set();\n        const owned = [];\n        const joined = [];\n\n        groups.forEach((group) => {\n            const id = normalizeGroupId(group);\n            if (!id || seen.has(id)) return;\n            seen.add(id);\n\n            if (isOwnedGroup(group)) {\n                owned.push(group);\n                return;\n            }\n\n            if (isJoinedGroup(group)) {\n                joined.push(group);\n            }\n        });\n\n        renderGroupList(myOwnedEl, owned, 'You do not own any groups yet.', 'Owner');\n        renderGroupList(joinedEl, joined, 'You have not joined any groups yet.', 'Member');\n\n        if (mySummaryEl) {\n            mySummaryEl.textContent = `${owned.length} owned \u2022 ${joined.length} joined`;\n        }\n    }\n\n    const normalizeGroupsResponse = (resp) => {\n        if (resp && Array.isArray(resp.groups)) return resp.groups;\n        if (resp && resp.data && Array.isArray(resp.data.groups)) return resp.data.groups;\n        if (resp && Array.isArray(resp.data)) return resp.data;\n        return [];\n    };\n\n    function updateGroups(timer) {\n        clearTimeout(updateGroupsTimer);\n\n        if (!groupsListWrapper) return;\n\n        const placeholderCard = BUDDYUP.placeholderCardElement();\n        if (groupsListWrapper.loading !== true) {\n            groupsListWrapper.innerHTML = `${placeholderCard}${placeholderCard}${placeholderCard}${placeholderCard}${placeholderCard}${placeholderCard}`;\n            groupsListWrapper.loading = true;\n        }\n\n        const wait = timer ? timer : 1500;\n        updateGroupsTimer = setTimeout(() => {\n            getGroupsData();\n        }, wait);\n    }\n\n    const getCheckedCategories = () => {\n        const checked = [];\n        document.querySelectorAll('.interestFilterCheckbox:checked').forEach((input) => {\n            const categoryName = input.getAttribute('data-type');\n            if (categoryName && categoryName !== '') checked.push(categoryName);\n        });\n        return checked;\n    };\n\n    async function getGroupsData() {\n        if (!groupsListWrapper) return;\n\n        const filterParams = {\n            name: '',\n            location: '',\n            date: '',\n            categories: [],\n            radius: 0,\n        };\n\n        const textSearchEl = document.getElementById('groupsTextSearch');\n        if (textSearchEl) filterParams.name = textSearchEl.value;\n\n        if (locationSearchEl) filterParams.location = locationSearchEl.value;\n\n        const dateSelected = document.querySelector('[data-dateselected=\"true\"]');\n        if (dateSelected && dateSelected.value) filterParams.date = dateSelected.value;\n\n        filterParams.categories = getCheckedCategories();\n        filterParams.radius = Number(radiusSelectEl && radiusSelectEl.value ? radiusSelectEl.value : 0) || 0;\n\n        if (myInterestsEl && myInterestsEl.checked && Array.isArray(currentUser.interests)) {\n            currentUser.interests.forEach((interest) => {\n                const normalized = String(interest || '').trim().replace(\/\\s+\/g, '-');\n                if (!normalized || filterParams.categories.indexOf(normalized) >= 0) return;\n                filterParams.categories.push(normalized);\n            });\n        }\n\n        const mobileFilterMenuCheck = document.querySelectorAll('#groupSearchSidebar.buddyUpSearchSidebar.activeMobileMenu');\n        if (mobileFilterMenuCheck.length > 0) {\n            BUDDYUP.closeMobileMenu();\n        }\n\n        let groupsResp = await BUDDYUP.getGroups(filterParams, true);\n        try { groupsResp = JSON.parse(groupsResp); } catch (e) {}\n\n        if (groupCreateButton) {\n            groupCreateButton.removeAttribute('disabled');\n            groupCreateButton.classList.remove('hidden');\n        }\n\n        groupsListWrapper.innerHTML = '';\n        groupsListWrapper.loading = false;\n\n        let groupsList = normalizeGroupsResponse(groupsResp);\n\n        if (groupsResp && groupsResp.status && groupsResp.status !== 'success') {\n            const msg = groupsResp.message || (groupsResp.data && groupsResp.data.message) || 'Error loading groups.';\n            groupsListWrapper.innerHTML = `<div style=\"text-align:center; padding: 3rem 1rem; background: rgba(0,0,0,0.035);\"><strong>Something went wrong<\/strong><div style=\"margin-top:.5rem;\">${msg}<\/div><\/div>`;\n            return;\n        }\n\n        if (filterParams.radius > 0 && String(filterParams.location || '').trim() !== '') {\n            const center = await resolveGeoText(filterParams.location);\n            if (center) {\n                if (locationLatEl) locationLatEl.value = String(center.latitude);\n                if (locationLngEl) locationLngEl.value = String(center.longitude);\n                if (locationHintEl) locationHintEl.innerText = `Radius filter: ${filterParams.radius} miles around ${center.label}.`;\n                groupsList = await filterByRadius(groupsList, center, filterParams.radius);\n            } else if (locationHintEl) {\n                locationHintEl.innerText = 'Could not geocode this location for radius filtering.';\n            }\n        } else if (locationHintEl && String(filterParams.location || '').trim() === '') {\n            locationHintEl.innerText = '';\n        }\n\n        if (groupsList.length > 0) {\n            groupsList.forEach((group) => {\n                groupsListWrapper.innerHTML += BUDDYUP.groupCardElement(group);\n            });\n        } else {\n            groupsListWrapper.innerHTML = '<div style=\"text-align: center; padding: 3rem 1rem; background: rgba(0,0,0,0.035);\">No groups found<\/div>';\n        }\n    }\n\n    async function handleCreateGroupClick(e) {\n        if (e) {\n            try { e.preventDefault(); } catch (err) {}\n            try { e.stopPropagation(); } catch (err) {}\n            try { e.stopImmediatePropagation(); } catch (err) {}\n        }\n\n        let canCreate = true;\n        try {\n            const limitsResp = await BUDDYUP.getUserLimits({ force: true });\n            const limit = Number(limitsResp?.limits?.groups?.create_limit ?? 0);\n            const current = Number(limitsResp?.current?.groups?.current_count ?? 0);\n            if (limit > 0 && current >= limit) canCreate = false;\n        } catch (err) {}\n\n        if (!canCreate) {\n            BUDDYUP.subscriptionModal('You have reached your group creation limit. Upgrade to increase your limit.', 'Group limit reached');\n            return false;\n        }\n\n        BUDDYUP.pjaxNavigate(`${buddyUpVariables.group_link}create`);\n        return true;\n    }\n\n    if (groupCreateButton) {\n        groupCreateButton.addEventListener('click', handleCreateGroupClick, true);\n    }\n\n    BUDDYUP.setGlobalHandler('groups.createGroupClick', document, 'click', (e) => {\n        const target = e.target && e.target.closest ? e.target.closest('#buddyUpCreateGroupButton, .buddyUpCreateGroupButton') : null;\n        if (!target) return;\n        handleCreateGroupClick(e);\n    }, true);\n\n    async function loadGroupInterests() {\n        const interestsWrapper = document.getElementById('groupsSidebarInterestWrapper');\n        const listEl = document.getElementById('interestsFilterList');\n        if (!interestsWrapper || !listEl) return;\n\n        const names = [];\n        const seen = new Set();\n        let sourcedFromGroups = false;\n\n        try {\n            let groupsResp = await BUDDYUP.getGroups({}, true);\n            try { groupsResp = JSON.parse(groupsResp); } catch (e) {}\n\n            let groupsList = [];\n            if (groupsResp && Array.isArray(groupsResp.groups)) groupsList = groupsResp.groups;\n            else if (groupsResp && groupsResp.data && Array.isArray(groupsResp.data.groups)) groupsList = groupsResp.data.groups;\n\n            groupsList.forEach((group) => {\n                const categories = Array.isArray(group.categories) ? group.categories : [];\n                categories.forEach((cat) => {\n                    const name = String(cat || '').trim();\n                    const key = name.toLowerCase();\n                    if (!name || seen.has(key)) return;\n                    seen.add(key);\n                    names.push(name);\n                });\n            });\n\n            sourcedFromGroups = names.length > 0;\n        } catch (e) {}\n\n        if (names.length === 0 && Array.isArray(currentUser.interests)) {\n            currentUser.interests.forEach((interest) => {\n                const name = String(interest || '').trim();\n                const key = name.toLowerCase();\n                if (!name || seen.has(key)) return;\n                seen.add(key);\n                names.push(name);\n            });\n        }\n\n        if (names.length === 0) return;\n\n        const interestEls = names.map((name) => {\n            const dataType = name.replace(\/\\s+\/g, '-');\n            const rowId = `group_interest_${dataType.toLowerCase().replace(\/[^a-z0-9_\\-]\/g, '')}`;\n            return `<label class=\"buddyUpFilterCheckboxItem\" for=\"${rowId}\"><input type=\"checkbox\" id=\"${rowId}\" class=\"interestFilterCheckbox\" data-type=\"${dataType}\" \/> <span>${name}<\/span><\/label>`;\n        }).join('');\n\n        interestsWrapper.querySelector('strong').textContent = sourcedFromGroups ? 'Filter by group interests' : 'Categories';\n        listEl.innerHTML = interestEls;\n        interestsWrapper.classList.remove('hidden');\n\n        listEl.querySelectorAll('.interestFilterCheckbox').forEach((btn) => {\n            btn.addEventListener('change', () => {\n                const mobileCheck = document.querySelectorAll('#groupSearchSidebar.buddyUpSearchSidebar.activeMobileMenu');\n                if (mobileCheck.length === 0) updateGroups(1200);\n            });\n        });\n    }\n\n    const groupSearchForms = document.querySelectorAll('#groupsSearchForm, #groupsSearchByLocationForm');\n    groupSearchForms.forEach((groupSearchForm) => {\n        groupSearchForm.addEventListener('submit', (e) => {\n            e.preventDefault();\n            activateTab('search');\n            updateGroups(1);\n        });\n    });\n\n    if (radiusSelectEl) {\n        radiusSelectEl.addEventListener('change', () => {\n            const mobileCheck = document.querySelectorAll('#groupSearchSidebar.buddyUpSearchSidebar.activeMobileMenu');\n            if (mobileCheck.length === 0) updateGroups(350);\n        });\n    }\n\n    if (myInterestsEl) {\n        myInterestsEl.addEventListener('change', () => {\n            const mobileCheck = document.querySelectorAll('#groupSearchSidebar.buddyUpSearchSidebar.activeMobileMenu');\n            if (mobileCheck.length === 0) updateGroups(350);\n        });\n    }\n\n    if (interestsToggleBtn && interestsDropdownMenu) {\n        interestsToggleBtn.addEventListener('click', (e) => {\n            e.preventDefault();\n            const opening = interestsDropdownMenu.classList.contains('hidden');\n            interestsDropdownMenu.classList.toggle('hidden', !opening);\n            interestsToggleBtn.setAttribute('aria-expanded', opening ? 'true' : 'false');\n        });\n\n        document.addEventListener('click', (e) => {\n            if (!interestsDropdownMenu.contains(e.target) && !interestsToggleBtn.contains(e.target)) {\n                interestsDropdownMenu.classList.add('hidden');\n                interestsToggleBtn.setAttribute('aria-expanded', 'false');\n            }\n        });\n    }\n\n    document.querySelectorAll('#filtersSearchMobile').forEach((button) => {\n        button.addEventListener('click', (e) => {\n            e.preventDefault();\n            activateTab('search');\n            updateGroups(1);\n        });\n    });\n\n    BUDDYUP.setGlobalHandler('groups.resize', window, 'resize', () => {\n        if (window.innerWidth >= 1001 && document.querySelector('.activeMobileMenu')) {\n            BUDDYUP.closeMobileMenu();\n        }\n    });\n\n    (function initGroupsSwipe() {\n        const shelf = document.getElementById('groupSearchSidebar');\n        const tab = document.querySelector('.buddyUpSideTab[data-target=\"groupSearchSidebar\"]');\n        if (shelf && typeof BUDDYUP.initShelfSwipeGestures === 'function') {\n            BUDDYUP.initShelfSwipeGestures({\n                shelf: shelf,\n                tab: tab,\n                onOpen: function() { BUDDYUP.openFiltersShelf(shelf); },\n                onClose: function() { BUDDYUP.closeFiltersShelf(); },\n                isOpen: function() { return shelf.classList.contains('isOpen'); },\n                key: 'groups.filterShelf',\n            });\n        }\n    })();\n\n    activateTab('search');\n    updateGroups(1);\n    await Promise.all([\n        loadConnectedGroups(),\n        loadGroupInterests(),\n    ]);\n})();\n<\/script><\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"templates\/full-width-no-header.php","meta":{"footnotes":""},"class_list":["post-466","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/pages\/466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/comments?post=466"}],"version-history":[{"count":1,"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/pages\/466\/revisions"}],"predecessor-version":[{"id":467,"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/pages\/466\/revisions\/467"}],"wp:attachment":[{"href":"https:\/\/buddyupapi-staging.us35.cdn-alpha.com\/api\/wp\/v2\/media?parent=466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}