Fix RajaOngkir address integration bugs and styling issues
This commit is contained in:
@@ -18,6 +18,7 @@ interface Address {
|
||||
email?: string;
|
||||
phone?: string;
|
||||
is_default: boolean;
|
||||
formatted_address?: string;
|
||||
}
|
||||
|
||||
interface AddressSelectorProps {
|
||||
@@ -148,14 +149,22 @@ export function AddressSelector({
|
||||
)}
|
||||
|
||||
{/* Address */}
|
||||
<p className="text-sm text-gray-600 mt-2">
|
||||
{address.address_1}
|
||||
{address.address_2 && `, ${address.address_2}`}
|
||||
</p>
|
||||
<p className="text-sm text-gray-600">
|
||||
{address.city}, {address.state} {address.postcode}
|
||||
</p>
|
||||
<p className="text-sm text-gray-600">{address.country}</p>
|
||||
<div className="text-sm text-gray-600 mt-2">
|
||||
{address.formatted_address ? (
|
||||
<p className="whitespace-pre-wrap">{address.formatted_address}</p>
|
||||
) : (
|
||||
<>
|
||||
<p>
|
||||
{address.address_1}
|
||||
{address.address_2 && `, ${address.address_2}`}
|
||||
</p>
|
||||
<p>
|
||||
{address.city}, {address.state} {address.postcode}
|
||||
</p>
|
||||
<p>{address.country}</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -28,6 +28,7 @@ interface CheckoutField {
|
||||
interface DynamicCheckoutFieldProps {
|
||||
field: CheckoutField;
|
||||
value: string;
|
||||
valueLabel?: string;
|
||||
onChange: (value: string) => void;
|
||||
countryOptions?: { value: string; label: string }[];
|
||||
stateOptions?: { value: string; label: string }[];
|
||||
@@ -41,6 +42,7 @@ interface SearchOption {
|
||||
export function DynamicCheckoutField({
|
||||
field,
|
||||
value,
|
||||
valueLabel,
|
||||
onChange,
|
||||
countryOptions = [],
|
||||
stateOptions = [],
|
||||
@@ -54,9 +56,11 @@ export function DynamicCheckoutField({
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a value but no options yet, we might need to load it
|
||||
// This handles pre-selected values
|
||||
}, [field.type, field.search_endpoint, value]);
|
||||
// If we have a value and a label, inject it into searchOptions so it renders properly when mounted
|
||||
if (value && valueLabel && searchOptions.length === 0) {
|
||||
setSearchOptions([{ value, label: valueLabel }]);
|
||||
}
|
||||
}, [field.type, field.search_endpoint, value, valueLabel]);
|
||||
|
||||
// Handle API search for searchable_select
|
||||
const handleApiSearch = async (searchTerm: string) => {
|
||||
|
||||
@@ -345,10 +345,18 @@ export default function Addresses() {
|
||||
<div className="text-sm text-gray-700 space-y-1 mb-4">
|
||||
<p className="font-medium">{address.first_name} {address.last_name}</p>
|
||||
{address.company && <p>{address.company}</p>}
|
||||
<p>{address.address_1}</p>
|
||||
{address.address_2 && <p>{address.address_2}</p>}
|
||||
<p>{address.city}, {address.state} {address.postcode}</p>
|
||||
<p>{address.country}</p>
|
||||
{address.formatted_address ? (
|
||||
<p className="whitespace-pre-wrap">{address.formatted_address}</p>
|
||||
) : (
|
||||
<>
|
||||
<p>{address.address_1}</p>
|
||||
{address.address_2 && <p>{address.address_2}</p>}
|
||||
{[address.city, address.state, address.postcode].filter(Boolean).length > 0 && (
|
||||
<p>{[address.city, address.state, address.postcode].filter(Boolean).join(', ')}</p>
|
||||
)}
|
||||
<p>{address.country}</p>
|
||||
</>
|
||||
)}
|
||||
{address.phone && <p className="pt-2">Phone: {address.phone}</p>}
|
||||
{address.email && <p>Email: {address.email}</p>}
|
||||
</div>
|
||||
@@ -429,6 +437,7 @@ export default function Addresses() {
|
||||
key={field.key}
|
||||
field={field}
|
||||
value={getFieldValue(field.key)}
|
||||
valueLabel={getFieldValue(field.key + '_label')}
|
||||
onChange={(v) => setFieldValue(field.key, v)}
|
||||
countryOptions={countryOptions}
|
||||
stateOptions={stateOptions}
|
||||
|
||||
@@ -33,6 +33,7 @@ interface SavedAddress {
|
||||
email?: string;
|
||||
phone?: string;
|
||||
is_default: boolean;
|
||||
formatted_address?: string;
|
||||
}
|
||||
|
||||
export default function Checkout() {
|
||||
@@ -389,7 +390,13 @@ export default function Checkout() {
|
||||
state: addressData.state,
|
||||
city: addressData.city,
|
||||
postcode: addressData.postcode,
|
||||
destination_id: undefined,
|
||||
// Include custom fields for shipping calculation (e.g., RajaOngkir destination_id)
|
||||
...Object.fromEntries(
|
||||
(shipToDifferentAddress ? shippingCustomFields : billingCustomFields).map(f => [
|
||||
f.key.replace(/^(shipping_|billing_)/, ''),
|
||||
customFieldData[f.key] || ''
|
||||
])
|
||||
),
|
||||
},
|
||||
items,
|
||||
});
|
||||
@@ -795,7 +802,16 @@ export default function Checkout() {
|
||||
<div className="bg-primary/5 border-2 border-primary rounded-lg p-4 text-sm">
|
||||
<p className="font-semibold">{sel.label}{sel.is_default && <span className="ml-2 text-xs bg-green-100 text-green-700 px-1.5 rounded">Default</span>}</p>
|
||||
<p>{sel.first_name} {sel.last_name}</p>
|
||||
<p className="text-gray-600">{sel.address_1}, {sel.city}, {sel.state} {sel.postcode}</p>
|
||||
{sel.formatted_address ? (
|
||||
<p className="text-gray-600 whitespace-pre-wrap">{sel.formatted_address}</p>
|
||||
) : (
|
||||
<div className="text-gray-600">
|
||||
<p>{sel.address_1}</p>
|
||||
{[sel.city, sel.state, sel.postcode].filter(Boolean).length > 0 && (
|
||||
<p>{[sel.city, sel.state, sel.postcode].filter(Boolean).join(', ')}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : null;
|
||||
})()}
|
||||
@@ -866,7 +882,7 @@ export default function Checkout() {
|
||||
</div>
|
||||
)}
|
||||
{billingCustomFields.map(field => (
|
||||
<DynamicCheckoutField key={field.key} field={field} value={customFieldData[field.key] || ''} onChange={v => handleCustomFieldChange(field.key, v)} countryOptions={countryOptions} stateOptions={billingStateOptions} />
|
||||
<DynamicCheckoutField key={field.key} field={field} value={customFieldData[field.key] || ''} valueLabel={customFieldData[`${field.key}_label`]} onChange={v => handleCustomFieldChange(field.key, v)} countryOptions={countryOptions} stateOptions={billingStateOptions} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
@@ -908,7 +924,16 @@ export default function Checkout() {
|
||||
<div className="bg-primary/5 border-2 border-primary rounded-lg p-4 text-sm">
|
||||
<p className="font-semibold">{sel.label}</p>
|
||||
<p>{sel.first_name} {sel.last_name}</p>
|
||||
<p className="text-gray-600">{sel.address_1}, {sel.city} {sel.postcode}</p>
|
||||
{sel.formatted_address ? (
|
||||
<p className="text-gray-600 whitespace-pre-wrap">{sel.formatted_address}</p>
|
||||
) : (
|
||||
<div className="text-gray-600">
|
||||
<p>{sel.address_1}</p>
|
||||
{[sel.city, sel.state, sel.postcode].filter(Boolean).length > 0 && (
|
||||
<p>{[sel.city, sel.state, sel.postcode].filter(Boolean).join(', ')}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : null;
|
||||
})()}
|
||||
@@ -926,7 +951,7 @@ export default function Checkout() {
|
||||
{getShippingField('shipping_country') && <div><label className="block text-sm font-medium mb-1">Country</label><SearchableSelect options={countryOptions} value={shippingData.country} onChange={v => setShippingData({ ...shippingData, country: v })} placeholder="Select country" disabled={countries.length === 1} /></div>}
|
||||
{getShippingField('shipping_state') && <div><label className="block text-sm font-medium mb-1">State</label>{shippingStateOptions.length > 0 ? <SearchableSelect options={shippingStateOptions} value={shippingData.state} onChange={v => setShippingData({ ...shippingData, state: v })} placeholder="Select state" /> : <input type="text" value={shippingData.state} onChange={e => setShippingData({ ...shippingData, state: e.target.value })} className="w-full border rounded-lg px-4 py-2" />}</div>}
|
||||
{getShippingField('shipping_postcode') && <div><label className="block text-sm font-medium mb-1">Postcode</label><input type="text" value={shippingData.postcode} onChange={e => setShippingData({ ...shippingData, postcode: e.target.value })} className="w-full border rounded-lg px-4 py-2" /></div>}
|
||||
{shippingCustomFields.map(field => <DynamicCheckoutField key={field.key} field={field} value={customFieldData[field.key] || ''} onChange={v => handleCustomFieldChange(field.key, v)} countryOptions={countryOptions} stateOptions={shippingStateOptions} />)}
|
||||
{shippingCustomFields.map(field => <DynamicCheckoutField key={field.key} field={field} value={customFieldData[field.key] || ''} valueLabel={customFieldData[`${field.key}_label`]} onChange={v => handleCustomFieldChange(field.key, v)} countryOptions={countryOptions} stateOptions={shippingStateOptions} />)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user