use crate::block::Block;
use crate::field::{Field, Select, TextInput};
use crate::validation::rules::Pattern;
const US_STATES: &[(&str, &str)] = &[
("AL", "Alabama"),
("AK", "Alaska"),
("AZ", "Arizona"),
("AR", "Arkansas"),
("CA", "California"),
("CO", "Colorado"),
("CT", "Connecticut"),
("DE", "Delaware"),
("FL", "Florida"),
("GA", "Georgia"),
("HI", "Hawaii"),
("ID", "Idaho"),
("IL", "Illinois"),
("IN", "Indiana"),
("IA", "Iowa"),
("KS", "Kansas"),
("KY", "Kentucky"),
("LA", "Louisiana"),
("ME", "Maine"),
("MD", "Maryland"),
("MA", "Massachusetts"),
("MI", "Michigan"),
("MN", "Minnesota"),
("MS", "Mississippi"),
("MO", "Missouri"),
("MT", "Montana"),
("NE", "Nebraska"),
("NV", "Nevada"),
("NH", "New Hampshire"),
("NJ", "New Jersey"),
("NM", "New Mexico"),
("NY", "New York"),
("NC", "North Carolina"),
("ND", "North Dakota"),
("OH", "Ohio"),
("OK", "Oklahoma"),
("OR", "Oregon"),
("PA", "Pennsylvania"),
("RI", "Rhode Island"),
("SC", "South Carolina"),
("SD", "South Dakota"),
("TN", "Tennessee"),
("TX", "Texas"),
("UT", "Utah"),
("VT", "Vermont"),
("VA", "Virginia"),
("WA", "Washington"),
("WV", "West Virginia"),
("WI", "Wisconsin"),
("WY", "Wyoming"),
("DC", "District of Columbia"),
];
pub struct AddressBlock {
prefix: String,
title: Option<String>,
required: bool,
}
impl AddressBlock {
pub fn new(prefix: impl Into<String>) -> Self {
Self {
prefix: prefix.into(),
title: None,
required: false,
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn required(mut self) -> Self {
self.required = true;
self
}
fn field_id(&self, name: &str) -> String {
format!("{}_{}", self.prefix, name)
}
}
impl Block for AddressBlock {
fn prefix(&self) -> &str {
&self.prefix
}
fn title(&self) -> Option<&str> {
self.title.as_deref()
}
fn fields(&self) -> Vec<Box<dyn Field>> {
let mut fields: Vec<Box<dyn Field>> = Vec::new();
let mut street1 = TextInput::new(self.field_id("street1"), "Street Address")
.placeholder("123 Main St");
if self.required {
street1 = street1.required();
}
fields.push(Box::new(street1));
let street2 = TextInput::new(self.field_id("street2"), "Address Line 2")
.placeholder("Apt, Suite, Unit, etc. (optional)");
fields.push(Box::new(street2));
let mut city = TextInput::new(self.field_id("city"), "City")
.placeholder("City");
if self.required {
city = city.required();
}
fields.push(Box::new(city));
let mut state = Select::new(self.field_id("state"), "State");
for (abbr, name) in US_STATES {
state = state.option(*abbr, format!("{} ({})", name, abbr));
}
if self.required {
state = state.required();
}
fields.push(Box::new(state));
let mut zip = TextInput::new(self.field_id("zip"), "ZIP Code")
.placeholder("12345 or 12345-6789")
.validator(Box::new(Pattern::zip_code()));
if self.required {
zip = zip.required();
}
fields.push(Box::new(zip));
fields
}
}