From 9e2545da7b09a5c7b168af7ed99c662fa429525a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sun, 12 Apr 2026 15:42:36 +0400 Subject: [PATCH 1/4] Add mobile phone numbers --- app/components/place-details.gjs | 24 +++++++++---- .../components/place-details-test.gjs | 36 +++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/app/components/place-details.gjs b/app/components/place-details.gjs index 2f27201..b3b362a 100644 --- a/app/components/place-details.gjs +++ b/app/components/place-details.gjs @@ -130,10 +130,14 @@ export default class PlaceDetails extends Component { formatMultiLine(val, type) { if (!val) return null; - const parts = val - .split(';') - .map((s) => s.trim()) - .filter(Boolean); + const parts = [ + ...new Set( + val + .split(';') + .map((s) => s.trim()) + .filter(Boolean) + ), + ]; if (parts.length === 0) return null; if (type === 'phone') { @@ -165,8 +169,16 @@ export default class PlaceDetails extends Component { } get phone() { - const val = this.tags.phone || this.tags['contact:phone']; - return this.formatMultiLine(val, 'phone'); + const rawValues = [ + this.tags.phone, + this.tags['contact:phone'], + this.tags.mobile, + this.tags['contact:mobile'], + ].filter(Boolean); + + if (rawValues.length === 0) return null; + + return this.formatMultiLine(rawValues.join(';'), 'phone'); } get email() { diff --git a/tests/integration/components/place-details-test.gjs b/tests/integration/components/place-details-test.gjs index d2d50a3..4956952 100644 --- a/tests/integration/components/place-details-test.gjs +++ b/tests/integration/components/place-details-test.gjs @@ -255,4 +255,40 @@ module('Integration | Component | place-details', function (hooks) { assert.dom('.actions button').hasText('Save'); assert.dom('.actions button').doesNotHaveClass('btn-secondary'); }); + + test('it aggregates phone and mobile tags without duplicates', async function (assert) { + const place = { + title: 'Phone Shop', + osmTags: { + phone: '+1 234 567 8900', + 'contact:phone': '+1 234 567 8900; +1 000 000 0000', + mobile: '+1 987 654 3210', + 'contact:mobile': '+1 987 654 3210', + }, + }; + + await render(); + + // Use specific selector for the phone block since there's no cuisine or opening_hours + const metaInfos = Array.from( + this.element.querySelectorAll('.meta-info .content-with-icon') + ); + const phoneBlock = metaInfos.find((el) => { + const iconSpan = el.querySelector('span.icon[title="Phone"]'); + return !!iconSpan; + }); + + assert.ok(phoneBlock, 'Phone block is rendered'); + + const links = phoneBlock.querySelectorAll('a[href^="tel:"]'); + assert.strictEqual( + links.length, + 3, + 'Rendered exactly 3 unique phone links' + ); + + assert.dom(links[0]).hasText('+1 234 567 8900'); + assert.dom(links[1]).hasText('+1 000 000 0000'); + assert.dom(links[2]).hasText('+1 987 654 3210'); + }); }); From ad3e6ea402d9a2a1a48a0280d1feeab00adeae0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sun, 12 Apr 2026 15:47:22 +0400 Subject: [PATCH 2/4] Remove spaces and dashes from tel links --- app/components/place-details.gjs | 5 ++++- app/icons/whatsapp.svg | 4 ++++ tests/integration/components/place-details-test.gjs | 10 +++++++--- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 app/icons/whatsapp.svg diff --git a/app/components/place-details.gjs b/app/components/place-details.gjs index b3b362a..26794f0 100644 --- a/app/components/place-details.gjs +++ b/app/components/place-details.gjs @@ -142,7 +142,10 @@ export default class PlaceDetails extends Component { if (type === 'phone') { return htmlSafe( - parts.map((p) => `${p}`).join('
') + parts.map((p) => { + const safeTel = p.replace(/[\s-]+/g, ''); + return `${p}`; + }).join('
') ); } diff --git a/app/icons/whatsapp.svg b/app/icons/whatsapp.svg new file mode 100644 index 0000000..85109bf --- /dev/null +++ b/app/icons/whatsapp.svg @@ -0,0 +1,4 @@ + + + + diff --git a/tests/integration/components/place-details-test.gjs b/tests/integration/components/place-details-test.gjs index 4956952..9cefb7e 100644 --- a/tests/integration/components/place-details-test.gjs +++ b/tests/integration/components/place-details-test.gjs @@ -260,8 +260,8 @@ module('Integration | Component | place-details', function (hooks) { const place = { title: 'Phone Shop', osmTags: { - phone: '+1 234 567 8900', - 'contact:phone': '+1 234 567 8900; +1 000 000 0000', + phone: '+1-234-567-8900', + 'contact:phone': '+1-234-567-8900; +1 000 000 0000', mobile: '+1 987 654 3210', 'contact:mobile': '+1 987 654 3210', }, @@ -287,7 +287,11 @@ module('Integration | Component | place-details', function (hooks) { 'Rendered exactly 3 unique phone links' ); - assert.dom(links[0]).hasText('+1 234 567 8900'); + assert.strictEqual(links[0].getAttribute('href'), 'tel:+12345678900'); + assert.strictEqual(links[1].getAttribute('href'), 'tel:+10000000000'); + assert.strictEqual(links[2].getAttribute('href'), 'tel:+19876543210'); + + assert.dom(links[0]).hasText('+1-234-567-8900'); assert.dom(links[1]).hasText('+1 000 000 0000'); assert.dom(links[2]).hasText('+1 987 654 3210'); }); From 344a3067fade77c0b848456b3bbb3fd580ba26ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sun, 12 Apr 2026 16:06:02 +0400 Subject: [PATCH 3/4] Add WhatsApp numbers/links --- app/components/place-details.gjs | 29 +++++++++++++++ app/icons/whatsapp.svg | 4 +- app/utils/icons.js | 3 ++ .../components/place-details-test.gjs | 37 +++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/app/components/place-details.gjs b/app/components/place-details.gjs index 26794f0..664a8fc 100644 --- a/app/components/place-details.gjs +++ b/app/components/place-details.gjs @@ -155,6 +155,15 @@ export default class PlaceDetails extends Component { ); } + if (type === 'whatsapp') { + return htmlSafe( + parts.map((p) => { + const safeTel = p.replace(/[\s-]+/g, ''); + return `${p}`; + }).join('
') + ); + } + if (type === 'url') { return htmlSafe( parts @@ -184,6 +193,17 @@ export default class PlaceDetails extends Component { return this.formatMultiLine(rawValues.join(';'), 'phone'); } + get whatsapp() { + const rawValues = [ + this.tags.whatsapp, + this.tags['contact:whatsapp'], + ].filter(Boolean); + + if (rawValues.length === 0) return null; + + return this.formatMultiLine(rawValues.join(';'), 'whatsapp'); + } + get email() { const val = this.tags.email || this.tags['contact:email']; return this.formatMultiLine(val, 'email'); @@ -358,6 +378,15 @@ export default class PlaceDetails extends Component {

{{/if}} + {{#if this.whatsapp}} +

+ + + {{this.whatsapp}} + +

+ {{/if}} + {{#if this.website}}

diff --git a/app/icons/whatsapp.svg b/app/icons/whatsapp.svg index 85109bf..1e0b1b5 100644 --- a/app/icons/whatsapp.svg +++ b/app/icons/whatsapp.svg @@ -1,4 +1,4 @@ - - + + diff --git a/app/utils/icons.js b/app/utils/icons.js index 2168d15..78348fe 100644 --- a/app/utils/icons.js +++ b/app/utils/icons.js @@ -110,6 +110,7 @@ import womensAndMensRestroomSymbol from '@waysidemapping/pinhead/dist/icons/wome import loadingRing from '../icons/270-ring.svg?raw'; import nostrich from '../icons/nostrich-2.svg?raw'; import remotestorage from '../icons/remotestorage.svg?raw'; +import whatsapp from '../icons/whatsapp.svg?raw'; import wikipedia from '../icons/wikipedia.svg?raw'; const ICONS = { @@ -218,6 +219,7 @@ const ICONS = { 'village-buildings': villageBuildings, 'wall-hanging-with-mountains-and-sun': wallHangingWithMountainsAndSun, 'womens-and-mens-restroom-symbol': womensAndMensRestroomSymbol, + whatsapp, wikipedia, parking_p: parkingP, car, @@ -229,6 +231,7 @@ const ICONS = { const FILLED_ICONS = [ 'fork-and-knife', 'wikipedia', + 'whatsapp', 'cup-and-saucer', 'coffee-bean', 'shopping-basket', diff --git a/tests/integration/components/place-details-test.gjs b/tests/integration/components/place-details-test.gjs index 9cefb7e..c7abab0 100644 --- a/tests/integration/components/place-details-test.gjs +++ b/tests/integration/components/place-details-test.gjs @@ -295,4 +295,41 @@ module('Integration | Component | place-details', function (hooks) { assert.dom(links[1]).hasText('+1 000 000 0000'); assert.dom(links[2]).hasText('+1 987 654 3210'); }); + + test('it formats whatsapp tags into wa.me links', async function (assert) { + const place = { + title: 'Chat Shop', + osmTags: { + 'contact:whatsapp': '+1 234-567 8900', + whatsapp: '+44 987 654 321', // Also tests multiple values + }, + }; + + await render(); + + const metaInfos = Array.from( + this.element.querySelectorAll('.meta-info .content-with-icon') + ); + const whatsappBlock = metaInfos.find((el) => { + const iconSpan = el.querySelector('span.icon[title="WhatsApp"]'); + return !!iconSpan; + }); + + assert.ok(whatsappBlock, 'WhatsApp block is rendered'); + + const links = whatsappBlock.querySelectorAll('a[href^="https://wa.me/"]'); + assert.strictEqual( + links.length, + 2, + 'Rendered exactly 2 WhatsApp links' + ); + + // Verify it stripped the dashes and spaces for the wa.me URL + assert.strictEqual(links[0].getAttribute('href'), 'https://wa.me/+44987654321'); + assert.strictEqual(links[1].getAttribute('href'), 'https://wa.me/+12345678900'); + + // Verify it kept the dashes and spaces for the visible text + assert.dom(links[0]).hasText('+44 987 654 321'); + assert.dom(links[1]).hasText('+1 234-567 8900'); + }); }); From 918a794784e9b77823a8a5ef67bbe48f017dd92e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sun, 12 Apr 2026 16:10:05 +0400 Subject: [PATCH 4/4] Fix lint errors --- app/components/place-details.gjs | 20 +++++++++++-------- .../components/place-details-test.gjs | 16 ++++++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/components/place-details.gjs b/app/components/place-details.gjs index 664a8fc..0377e2c 100644 --- a/app/components/place-details.gjs +++ b/app/components/place-details.gjs @@ -142,10 +142,12 @@ export default class PlaceDetails extends Component { if (type === 'phone') { return htmlSafe( - parts.map((p) => { - const safeTel = p.replace(/[\s-]+/g, ''); - return `${p}`; - }).join('
') + parts + .map((p) => { + const safeTel = p.replace(/[\s-]+/g, ''); + return `${p}`; + }) + .join('
') ); } @@ -157,10 +159,12 @@ export default class PlaceDetails extends Component { if (type === 'whatsapp') { return htmlSafe( - parts.map((p) => { - const safeTel = p.replace(/[\s-]+/g, ''); - return `${p}`; - }).join('
') + parts + .map((p) => { + const safeTel = p.replace(/[\s-]+/g, ''); + return `${p}`; + }) + .join('
') ); } diff --git a/tests/integration/components/place-details-test.gjs b/tests/integration/components/place-details-test.gjs index c7abab0..6969046 100644 --- a/tests/integration/components/place-details-test.gjs +++ b/tests/integration/components/place-details-test.gjs @@ -318,15 +318,17 @@ module('Integration | Component | place-details', function (hooks) { assert.ok(whatsappBlock, 'WhatsApp block is rendered'); const links = whatsappBlock.querySelectorAll('a[href^="https://wa.me/"]'); - assert.strictEqual( - links.length, - 2, - 'Rendered exactly 2 WhatsApp links' - ); + assert.strictEqual(links.length, 2, 'Rendered exactly 2 WhatsApp links'); // Verify it stripped the dashes and spaces for the wa.me URL - assert.strictEqual(links[0].getAttribute('href'), 'https://wa.me/+44987654321'); - assert.strictEqual(links[1].getAttribute('href'), 'https://wa.me/+12345678900'); + assert.strictEqual( + links[0].getAttribute('href'), + 'https://wa.me/+44987654321' + ); + assert.strictEqual( + links[1].getAttribute('href'), + 'https://wa.me/+12345678900' + ); // Verify it kept the dashes and spaces for the visible text assert.dom(links[0]).hasText('+44 987 654 321');