custom_ui/frontend/src/components/clientSubPages/AddressInformationForm.vue

189 lines
4.2 KiB
Vue

<template>
<div class="form-section">
<h3>Address Information</h3>
<div class="form-grid">
<div class="form-field full-width">
<label for="address-line1"> Address Line 1 <span class="required">*</span> </label>
<InputText
id="address-line1"
v-model="localFormData.addressLine1"
:disabled="isSubmitting"
placeholder="Street address"
class="w-full"
/>
</div>
<div class="form-field full-width">
<label for="address-line2">Address Line 2</label>
<InputText
id="address-line2"
v-model="localFormData.addressLine2"
:disabled="isSubmitting"
placeholder="Apt, suite, unit, etc."
class="w-full"
/>
</div>
<div class="form-field">
<label for="zipcode"> Zip Code <span class="required">*</span> </label>
<InputText
id="zipcode"
v-model="localFormData.pincode"
:disabled="isSubmitting"
@input="handleZipcodeInput"
maxlength="5"
placeholder="12345"
class="w-full"
/>
</div>
<div class="form-field">
<label for="city"> City <span class="required">*</span> </label>
<InputText
id="city"
v-model="localFormData.city"
:disabled="isSubmitting || zipcodeLookupDisabled"
placeholder="City"
class="w-full"
/>
</div>
<div class="form-field">
<label for="state"> State <span class="required">*</span> </label>
<InputText
id="state"
v-model="localFormData.state"
:disabled="isSubmitting || zipcodeLookupDisabled"
placeholder="State"
class="w-full"
/>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
import InputText from "primevue/inputtext";
import Api from "../../api";
import { useNotificationStore } from "../../stores/notifications-primevue";
const props = defineProps({
formData: {
type: Object,
required: true,
},
isSubmitting: {
type: Boolean,
default: false,
},
isEditMode: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["update:formData"]);
const notificationStore = useNotificationStore();
const localFormData = computed({
get: () => props.formData,
set: (value) => emit("update:formData", value),
});
const zipcodeLookupDisabled = ref(true);
const handleZipcodeInput = async (event) => {
const input = event.target.value;
// Only allow digits
const digitsOnly = input.replace(/\D/g, "");
// Limit to 5 digits
if (digitsOnly.length > 5) {
return;
}
localFormData.value.pincode = digitsOnly;
// Reset city/state if zipcode is not complete
if (digitsOnly.length < 5 && zipcodeLookupDisabled.value) {
localFormData.value.city = "";
localFormData.value.state = "";
zipcodeLookupDisabled.value = false;
}
// Fetch city/state when 5 digits entered
if (digitsOnly.length === 5) {
try {
console.log("DEBUG: Looking up city/state for zip code:", digitsOnly);
const places = await Api.getCityStateByZip(digitsOnly);
console.log("DEBUG: Retrieved places:", places);
if (places && places.length > 0) {
// Auto-populate city and state
localFormData.value.city = places[0]["city"];
localFormData.value.state = places[0]["state"];
zipcodeLookupDisabled.value = true;
notificationStore.addSuccess(`Found: ${places[0]["city"]}, ${places[0]["state"]}`);
}
} catch (error) {
// Enable manual entry if lookup fails
zipcodeLookupDisabled.value = false;
notificationStore.addWarning(
"Could not find city/state for this zip code. Please enter manually.",
);
}
}
};
</script>
<style scoped>
.form-section {
background: var(--surface-card);
border-radius: 8px;
padding: 1.5rem;
border: 1px solid var(--surface-border);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.form-section h3 {
margin: 0 0 1rem 0;
color: var(--text-color);
font-size: 1.25rem;
font-weight: 600;
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.form-field {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-field.full-width {
grid-column: 1 / -1;
}
.form-field label {
font-weight: 500;
color: var(--text-color-secondary);
font-size: 0.9rem;
}
.required {
color: var(--red-500);
}
.w-full {
width: 100% !important;
}
@media (max-width: 768px) {
.form-grid {
grid-template-columns: 1fr;
}
}
</style>