feat: Add infinite scroll to contacts search page (#13376)
## Summary - Add `has_more` to contacts search API response to enable infinite scroll without expensive count queries - Set `count` to the number of items in the current page instead of total count - Implement "Load more" button for contacts search results - Keep existing contacts visible while loading additional pages ## Changes ### Backend - Add `fetch_contacts_with_has_more` method that fetches N+1 records to determine if more pages exist - Return `has_more` in search endpoint meta response - Set `count` to current page size instead of total count ### Frontend - Add `APPEND_CONTACTS` mutation for appending contacts without clearing existing ones - Update search action to support `append` parameter - Add `ContactsLoadMore` component with loading state - Update `ContactsListLayout` to support infinite scroll mode - Update `ContactsIndex` to use infinite scroll for search view
This commit is contained in:
@@ -369,6 +369,50 @@ RSpec.describe 'Contacts API', type: :request do
|
||||
expect(response.body).to include(contact_special.identifier)
|
||||
expect(response.body).not_to include(contact_normal.identifier)
|
||||
end
|
||||
|
||||
it 'returns has_more as false when results fit in one page' do
|
||||
get "/api/v1/accounts/#{account.id}/contacts/search",
|
||||
params: { q: contact2.email },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
response_body = response.parsed_body
|
||||
expect(response_body['meta']['has_more']).to be(false)
|
||||
expect(response_body['meta']['count']).to eq(1)
|
||||
end
|
||||
|
||||
it 'returns has_more as true when there are more results' do
|
||||
# Create 16 contacts (more than RESULTS_PER_PAGE which is 15)
|
||||
create_list(:contact, 16, account: account, name: 'searchable_contact')
|
||||
|
||||
get "/api/v1/accounts/#{account.id}/contacts/search",
|
||||
params: { q: 'searchable_contact' },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
response_body = response.parsed_body
|
||||
expect(response_body['meta']['has_more']).to be(true)
|
||||
expect(response_body['meta']['count']).to eq(15)
|
||||
expect(response_body['payload'].length).to eq(15)
|
||||
end
|
||||
|
||||
it 'returns has_more as false on the last page' do
|
||||
# Create 16 contacts
|
||||
create_list(:contact, 16, account: account, name: 'searchable_contact')
|
||||
|
||||
get "/api/v1/accounts/#{account.id}/contacts/search",
|
||||
params: { q: 'searchable_contact', page: 2 },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
response_body = response.parsed_body
|
||||
expect(response_body['meta']['has_more']).to be(false)
|
||||
expect(response_body['meta']['count']).to eq(1)
|
||||
expect(response_body['payload'].length).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user