Skip to content

Commit 17f7306

Browse files
Render contact topics as pill badges in case contacts table
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
1 parent fe5c01d commit 17f7306

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

app/datatables/case_contact_datatable.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def data
2929
},
3030
contact_made: case_contact.contact_made,
3131
duration_minutes: case_contact.duration_minutes,
32-
contact_topics: case_contact.contact_topics.map(&:question).join(" | "),
32+
contact_topics: case_contact.contact_topics.map(&:question),
3333
contact_topic_answers: case_contact.contact_topic_answers
3434
.reject { |a| a.value.blank? }
3535
.map { |a| { question: a.contact_topic&.question, value: a.value } },

app/javascript/__tests__/dashboard.test.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,33 @@ describe('defineCaseContactsTable', () => {
309309
expect(columns[8].orderable).toBe(false)
310310
})
311311

312-
it('renders contact topics string', () => {
313-
expect(columns[8].render('Topic 1 | Topic 2')).toBe('Topic 1 | Topic 2')
312+
it('renders each topic as a pill badge', () => {
313+
const rendered = columns[8].render(['Topic 1', 'Topic 2'])
314+
expect(rendered).toContain('<span class="badge badge-pill light-bg text-black">Topic 1</span>')
315+
expect(rendered).toContain('<span class="badge badge-pill light-bg text-black">Topic 2</span>')
316+
})
317+
318+
it('renders empty string when there are no topics', () => {
314319
expect(columns[8].render(null)).toBe('')
320+
expect(columns[8].render([])).toBe('')
321+
})
322+
323+
it('shows only the first two topics when there are more than two', () => {
324+
const rendered = columns[8].render(['A', 'B', 'C', 'D'])
325+
expect(rendered).toContain('>A<')
326+
expect(rendered).toContain('>B<')
327+
expect(rendered).not.toContain('>C<')
328+
expect(rendered).not.toContain('>D<')
329+
})
330+
331+
it('shows a +N More badge for overflow topics', () => {
332+
const rendered = columns[8].render(['A', 'B', 'C', 'D'])
333+
expect(rendered).toContain('+2 More')
334+
})
335+
336+
it('does not show an overflow badge when there are two or fewer topics', () => {
337+
expect(columns[8].render(['A', 'B'])).not.toContain('More')
338+
expect(columns[8].render(['A'])).not.toContain('More')
315339
})
316340
})
317341

app/javascript/src/dashboard.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,21 @@
33
const { Notifier } = require('./notifier')
44
let pageNotifier
55

6+
const MAX_VISIBLE_TOPIC_PILLS = 2
7+
8+
function buildTopicPills (topics) {
9+
if (!topics || topics.length === 0) return ''
10+
const visible = topics.slice(0, MAX_VISIBLE_TOPIC_PILLS)
11+
const overflowCount = topics.length - visible.length
12+
const pills = visible
13+
.map(topic => `<span class="badge badge-pill light-bg text-black">${topic}</span>`)
14+
.join(' ')
15+
const overflowPill = overflowCount > 0
16+
? ` <span class="badge badge-pill light-bg text-black">+${overflowCount} More</span>`
17+
: ''
18+
return pills + overflowPill
19+
}
20+
621
function buildExpandedContent (data) {
722
const answers = (data.contact_topic_answers || [])
823
.map(answer => `<div class="expanded-topic"><strong>${answer.question}</strong><p>${answer.value}</p></div>`)
@@ -120,7 +135,7 @@ const defineCaseContactsTable = function () {
120135
{ // Topics column (index 8)
121136
data: 'contact_topics',
122137
orderable: false,
123-
render: (data) => data || ''
138+
render: (data) => buildTopicPills(data)
124139
},
125140
{ // Draft column (index 9)
126141
data: 'is_draft',

spec/requests/case_contacts/case_contacts_new_design_spec.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,31 @@
239239
expect(record[:notes]).to be_blank
240240
end
241241
end
242+
243+
context "contact_topics field" do
244+
let(:contact_topic) { create(:contact_topic, casa_org: organization) }
245+
let(:case_contact_with_topics) { create(:case_contact, :active, casa_case: casa_case) }
246+
247+
before do
248+
case_contact_with_topics.contact_topics << contact_topic
249+
end
250+
251+
it "returns contact_topics as an array of strings" do
252+
post datatable_case_contacts_new_design_path, params: datatable_params, as: :json
253+
254+
json = JSON.parse(response.body, symbolize_names: true)
255+
record = json[:data].find { |d| d[:id] == case_contact_with_topics.id.to_s }
256+
expect(record[:contact_topics]).to be_an(Array)
257+
end
258+
259+
it "includes the topic question in the array" do
260+
post datatable_case_contacts_new_design_path, params: datatable_params, as: :json
261+
262+
json = JSON.parse(response.body, symbolize_names: true)
263+
record = json[:data].find { |d| d[:id] == case_contact_with_topics.id.to_s }
264+
expect(record[:contact_topics]).to include(contact_topic.question)
265+
end
266+
end
242267
end
243268
end
244269
end

0 commit comments

Comments
 (0)