You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rappli/src/components/Address.tsx

83 lines
1.9 KiB
TypeScript

import { Component, Show } from "solid-js";
import z, { Infer } from "myzod";
const addressSchema_ = () => ({
type: z.literals("S", "K").optional(),
name: z.string(),
line1: z.string().optional(),
line2: z.string().optional(),
city: z.string().optional(),
zip: z.number().optional(),
country: z.string(),
});
export const addressSchema = z.object(addressSchema_());
export const postalAddressSchema = z.object({
...addressSchema_(),
name2: z.string().optional(),
});
export type AddressData = Infer<typeof addressSchema>;
export type PostalAddressData = Infer<typeof postalAddressSchema>;
export const createAddress = <T extends AddressData = AddressData>(
data: Partial<T> = {}
): T => {
return {
name: "",
line1: "",
line2: "",
city: "",
zip: undefined,
country: "CH",
...data,
} as any;
};
export const isStructuredAddress = (address: AddressData) => {
if (address.type) {
return address.type === "S";
}
return address.city || address.zip != null;
};
export const getLine1 = (address: AddressData) => {
if (isStructuredAddress(address)) {
return `${address.line1 || ""} ${address.line2 || ""}`;
}
return address.line1;
};
export const getLine2 = (address: AddressData) => {
if (isStructuredAddress(address)) {
return `${address.zip || ""} ${address.city || ""}`;
}
return address.line2;
};
const Address: Component<{ address: PostalAddressData }> = (props) => (
<>
<div>{props.address.name}</div>
<Show when={props.address.name2}>
<div>{props.address.name2}</div>
</Show>
<div>{getLine1(props.address)}</div>
<div>{getLine2(props.address)}</div>
</>
);
export const applyAddress = (target: AddressData, values: AddressData) => {
target.name = values.name;
target.line1 = values.line1;
target.line2 = values.line2;
target.zip = values.zip;
target.city = values.city;
};
export default Address;