bd-geo-info
Version:
A comprehensive Bangladesh geographical data package with hierarchical selection and address form components
140 lines (139 loc) • 9.4 kB
JavaScript
import React, { useState } from 'react';
import DivisionSelect from './DivisionSelect';
import DistrictSelect from './DistrictSelect';
import UpazilaSelect from './UpazilaSelect';
import UnionSelect from './UnionSelect';
import getPostCode from '../utils/getPostCode';
export default function AddressForm({ language = 'en', onChange, className = '', children, theme, validation, showPostCode = true, showLabels = true, customLabels, customErrors, containerClassName = '', labelClassName = '', errorClassName = '', inputContainerClassName = '' }) {
const [address, setAddress] = useState({});
const [errors, setErrors] = useState({});
const [selectedDivision, setSelectedDivision] = useState();
const [selectedDistrict, setSelectedDistrict] = useState();
const [selectedUpazila, setSelectedUpazila] = useState();
const [selectedUnion, setSelectedUnion] = useState();
const handleDivisionChange = (division) => {
setSelectedDivision(division);
handleChange({ division: language === 'bn' ? division.bn_name : division.name });
};
const handleDistrictChange = (district) => {
setSelectedDistrict(district);
handleChange({ district: language === 'bn' ? district.bn_name : district.name });
};
const handleUpazilaChange = (upazila) => {
setSelectedUpazila(upazila);
handleChange({ upazila: language === 'bn' ? upazila.bn_name : upazila.name });
};
const handleUnionChange = (union) => {
setSelectedUnion(union);
handleChange({ union: language === 'bn' ? union.bn_name : union.name });
};
const validateField = (field, value) => {
var _a, _b, _c;
if (!(validation === null || validation === void 0 ? void 0 : validation[field]))
return true;
if (((_a = validation[field]) === null || _a === void 0 ? void 0 : _a.required) && !value) {
return language === 'bn' ? 'এই ক্ষেত্রটি আবশ্যক' : 'This field is required';
}
if ((_b = validation[field]) === null || _b === void 0 ? void 0 : _b.customValidation) {
return (_c = validation[field]) === null || _c === void 0 ? void 0 : _c.customValidation(value);
}
return true;
};
const handleChange = (newData) => {
var _a, _b, _c, _d;
const updatedAddress = Object.assign(Object.assign({}, address), newData);
const newErrors = {};
// Reset dependent fields when parent field changes
if ('division' in newData) {
updatedAddress.district = undefined;
updatedAddress.upazila = undefined;
updatedAddress.union = undefined;
updatedAddress.postCode = undefined;
}
else if ('district' in newData) {
updatedAddress.upazila = undefined;
updatedAddress.union = undefined;
updatedAddress.postCode = undefined;
}
else if ('upazila' in newData) {
updatedAddress.union = undefined;
// Update postcode when upazila changes
const postcodes = getPostCode({
division: ((_a = updatedAddress.division) === null || _a === void 0 ? void 0 : _a.toString()) || '',
district: ((_b = updatedAddress.district) === null || _b === void 0 ? void 0 : _b.toString()) || '',
upazila: ((_c = updatedAddress.upazila) === null || _c === void 0 ? void 0 : _c.toString()) || '',
});
updatedAddress.postCode = (_d = postcodes[0]) === null || _d === void 0 ? void 0 : _d.postCode;
}
// Validate fields
Object.keys(updatedAddress).forEach((key) => {
const validationResult = validateField(key, updatedAddress[key]);
if (typeof validationResult === 'string') {
newErrors[key] = validationResult;
}
});
setErrors(newErrors);
setAddress(updatedAddress);
onChange === null || onChange === void 0 ? void 0 : onChange(updatedAddress);
};
const getStyles = () => {
var _a, _b, _c, _d, _e, _f;
if (!theme) {
return {
'--primary-color': '#3b82f6',
'--background-color': '#ffffff',
'--border-color': '#e5e7eb',
'--border-radius': '0.375rem',
'--font-size': '0.875rem',
'--padding': '0.625rem 0.875rem',
'--margin': '0.5rem',
'--select-height': '2.5rem',
'--transition': 'all 0.2s ease-in-out',
'--hover-border-color': '#93c5fd',
'--hover-bg-color': '#f8fafc',
'--error-color': '#ef4444',
'--label-color': '#374151',
'--placeholder-color': '#9ca3af',
'--mobile-width': '100%',
'--desktop-width': '24rem'
};
}
return {
'--primary-color': ((_a = theme.colors) === null || _a === void 0 ? void 0 : _a.primary) || '#3b82f6',
'--background-color': ((_b = theme.colors) === null || _b === void 0 ? void 0 : _b.background) || '#ffffff',
'--border-color': ((_c = theme.colors) === null || _c === void 0 ? void 0 : _c.border) || '#e5e7eb',
'--border-radius': theme.borderRadius || '0.375rem',
'--font-size': ((_d = theme.fontSize) === null || _d === void 0 ? void 0 : _d.input) || '0.875rem',
'--padding': ((_e = theme.spacing) === null || _e === void 0 ? void 0 : _e.input) || '0.625rem 0.875rem',
'--margin': ((_f = theme.spacing) === null || _f === void 0 ? void 0 : _f.label) || '0.5rem',
'--select-height': '2.5rem',
'--transition': 'all 0.2s ease-in-out',
'--hover-border-color': '#93c5fd',
'--hover-bg-color': '#f8fafc',
'--error-color': '#ef4444',
'--label-color': '#374151',
'--placeholder-color': '#9ca3af',
'--mobile-width': '100%',
'--desktop-width': '24rem'
};
};
const selectProps = {
theme,
errorClassName: `${errorClassName} text-[var(--error-color)] text-xs mt-1`,
labelClassName: `${labelClassName} block text-[var(--label-color)] text-sm font-medium mb-2`,
containerClassName: `${inputContainerClassName} flex flex-col mb-6 w-full md:w-[var(--desktop-width)]`,
language,
className: `w-full h-[var(--select-height)] px-4 py-2.5 bg-[var(--background-color)] border border-[var(--border-color)] rounded-[var(--border-radius)] text-[var(--font-size)] transition-[var(--transition)] focus:outline-none focus:ring-2 focus:ring-[var(--primary-color)] focus:border-transparent hover:border-[var(--hover-border-color)] hover:bg-[var(--hover-bg-color)] disabled:opacity-50 disabled:cursor-not-allowed shadow-sm`
};
return (React.createElement("div", { className: `${containerClassName} bg-white rounded-lg shadow-sm w-full max-w-[1200px] mx-auto p-6`, style: getStyles() },
React.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" },
React.createElement("div", { className: "relative" },
React.createElement(DivisionSelect, Object.assign({}, selectProps, { value: selectedDivision, onChange: handleDivisionChange, placeholder: language === 'bn' ? 'বিভাগ নির্বাচন করুন' : 'Select Division', customLabel: customLabels === null || customLabels === void 0 ? void 0 : customLabels.division, customError: (customErrors === null || customErrors === void 0 ? void 0 : customErrors.division) || errors.division }))),
React.createElement("div", { className: "relative" },
React.createElement(DistrictSelect, Object.assign({}, selectProps, { division: selectedDivision, value: selectedDistrict, onChange: handleDistrictChange, placeholder: language === 'bn' ? 'জেলা নির্বাচন করুন' : 'Select District', customLabel: customLabels === null || customLabels === void 0 ? void 0 : customLabels.district, customError: (customErrors === null || customErrors === void 0 ? void 0 : customErrors.district) || errors.district }))),
React.createElement("div", { className: "relative" },
React.createElement(UpazilaSelect, Object.assign({}, selectProps, { district: selectedDistrict, value: selectedUpazila, onChange: handleUpazilaChange, placeholder: language === 'bn' ? 'উপজেলা নির্বাচন করুন' : 'Select Upazila', customLabel: customLabels === null || customLabels === void 0 ? void 0 : customLabels.upazila, customError: (customErrors === null || customErrors === void 0 ? void 0 : customErrors.upazila) || errors.upazila }))),
React.createElement("div", { className: "relative" },
React.createElement(UnionSelect, Object.assign({}, selectProps, { upazila: selectedUpazila, value: selectedUnion, onChange: handleUnionChange, placeholder: language === 'bn' ? 'ইউনিয়ন নির্বাচন করুন' : 'Select Union', customLabel: customLabels === null || customLabels === void 0 ? void 0 : customLabels.union, customError: (customErrors === null || customErrors === void 0 ? void 0 : customErrors.union) || errors.union })))),
children));
}