Skip to content

Commit 5a59ae6

Browse files
authored
Phone numbers on address! (#62)
* add phone column to addresses * phone number! * lint
1 parent bbc504d commit 5a59ae6

File tree

8 files changed

+85
-20
lines changed

8 files changed

+85
-20
lines changed
Lines changed: 1 addition & 0 deletions
Loading

app/models/address.rb

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22
#
33
# Table name: addresses
44
#
5-
# id :bigint not null, primary key
6-
# city :string
7-
# country :integer
8-
# first_name :string
9-
# last_name :string
10-
# line_1 :string
11-
# line_2 :string
12-
# postal_code :string
13-
# state :string
14-
# created_at :datetime not null
15-
# updated_at :datetime not null
16-
# identity_id :bigint not null
5+
# id :bigint not null, primary key
6+
# city :string
7+
# country :integer
8+
# first_name :string
9+
# last_name :string
10+
# line_1 :string
11+
# line_2 :string
12+
# phone_number :string
13+
# postal_code :string
14+
# state :string
15+
# created_at :datetime not null
16+
# updated_at :datetime not null
17+
# identity_id :bigint not null
1718
#
1819
# Indexes
1920
#
@@ -43,10 +44,16 @@ class Address < ApplicationRecord
4344

4445
def self.strip_gremlins(str) = str&.delete(GREMLINS)&.presence
4546

46-
validates_presence_of :first_name, :line_1, :city, :state, :postal_code, :country
47+
validates_presence_of :first_name, :line_1, :city, :state, :postal_code, :country, :phone_number
4748

4849
before_validation :strip_gremlins_from_fields
4950

51+
before_validation :normalize_phone_number
52+
53+
def self.country_calling_code(country_alpha2)
54+
ISO3166::Country[country_alpha2]&.country_code
55+
end
56+
5057
private def strip_gremlins_from_fields
5158
self.first_name = Address.strip_gremlins(first_name)
5259
self.last_name = Address.strip_gremlins(last_name)
@@ -56,4 +63,14 @@ def self.strip_gremlins(str) = str&.delete(GREMLINS)&.presence
5663
self.state = Address.strip_gremlins(state)
5764
self.postal_code = Address.strip_gremlins(postal_code)
5865
end
66+
67+
private def normalize_phone_number
68+
return if phone_number.blank?
69+
cleaned = phone_number.gsub(/[^\d+]/, "")
70+
calling_code = Address.country_calling_code(country)
71+
unless cleaned.start_with?("+")
72+
cleaned = "+#{calling_code}#{cleaned}"
73+
end
74+
self.phone_number = cleaned
75+
end
5976
end

app/views/addresses/_address.html.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
<% end %>
1818
<%= address.city %>, <%= address.state %> <%= address.postal_code %><br>
1919
<%= address.country %>
20+
<% if address.phone_number.present? %>
21+
<br><%= inline_icon("phone", size: 14) %> <%= address.phone_number %>
22+
<% end %>
2023
</div>
2124

2225
<div class="form-actions" style="gap: 0.5rem;">

app/views/addresses/_form.html.erb

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
<%
2+
country_calling_codes = Address.countries.keys.each_with_object({}) do |alpha2, hash|
3+
hash[alpha2] = Address.country_calling_code(alpha2)
4+
end
5+
initial_country = address.country || current_identity&.country || "US"
6+
initial_calling_code = Address.country_calling_code(initial_country) || "1"
7+
8+
# Strip country code prefix for display (it's shown separately)
9+
raw_phone = address.phone_number.presence || current_identity&.phone_number
10+
display_phone = if raw_phone.present? && raw_phone.start_with?("+")
11+
raw_phone.sub(/^\+#{initial_calling_code}/, "")
12+
else
13+
raw_phone
14+
end
15+
%>
16+
117
<%= form_with model: address, url: local_assigns[:url], local: true do |f| %>
218
<% if local_assigns[:from_program] %>
319
<%= f.hidden_field :from_program, value: true %>
@@ -27,12 +43,32 @@
2743
<%= f.text_field :state, placeholder: t("addresses.state"), required: true %>
2844
</div>
2945

30-
<div class="grid">
31-
<%= f.text_field :postal_code, placeholder: t("addresses.postal_code"), required: true %>
32-
<%= f.collection_select :country, Address.countries_for_select,
33-
:first, :last,
34-
{ include_blank: "Country" },
35-
{ required: true } %>
46+
<div x-data="{
47+
callingCodes: <%= country_calling_codes.to_json %>,
48+
callingCode: '<%= initial_calling_code %>',
49+
updateCallingCode(countrySelect) {
50+
const code = this.callingCodes[countrySelect.value];
51+
if (code) this.callingCode = code;
52+
}
53+
}">
54+
<div class="grid">
55+
<%= f.text_field :postal_code, placeholder: t("addresses.postal_code"), required: true %>
56+
<%= f.collection_select :country, Address.countries_for_select,
57+
:first, :last,
58+
{ include_blank: "Country" },
59+
{ required: true, "@change": "updateCallingCode($event.target)" } %>
60+
</div>
61+
62+
<div class="grid" style="grid-template-columns: auto 1fr; margin-top: 1rem;">
63+
<span style="padding: 0.5rem 0.75rem; background: var(--input-bg); border: 1px solid var(--input-border); border-radius: var(--radius); display: flex; align-items: center; font-size: 0.95rem; color: var(--text-muted);">
64+
+<span x-text="callingCode"></span>
65+
</span>
66+
<%= f.telephone_field :phone_number,
67+
placeholder: t("addresses.phone_number"),
68+
value: display_phone,
69+
required: true,
70+
style: "margin: 0;" %>
71+
</div>
3672
</div>
3773

3874
<div class="form-actions">

app/views/api/v1/addresses/_address.jb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
state: address.state,
99
postal_code: address.postal_code,
1010
country: address.country,
11+
phone_number: address.phone_number,
1112
primary: address.id == address&.identity&.primary_address&.id
1213
}.compact_blank

config/locales/en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ en:
120120
city: City
121121
state: State/Province
122122
postal_code: Postal code
123+
phone_number: Phone number
123124
save: Save address
124125
cancel: Cancel
125126
primary: Primary
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddPhoneNumberToAddresses < ActiveRecord::Migration[8.0]
2+
def change
3+
add_column :addresses, :phone_number, :string
4+
end
5+
end

db/schema.rb

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)