refaktor címjegyzék
This commit is contained in:
229
frontend_admin/components/SharedAddressForm.vue
Normal file
229
frontend_admin/components/SharedAddressForm.vue
Normal file
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="bg-slate-800 rounded-xl border border-slate-700 p-6 mb-6">
|
||||
<h2 class="text-lg font-semibold text-white mb-4">Cím adatok</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<!-- Smart Location Input (zip + city autocomplete) -->
|
||||
<div class="md:col-span-2">
|
||||
<SmartLocationInput
|
||||
:model-value="selectedLocation"
|
||||
@update:model-value="onLocationSelected"
|
||||
label="Irányítószám / Város"
|
||||
placeholder="Kezdj el gépelni (pl. 1011 vagy Budapest)..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Street name -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Utca neve</label>
|
||||
<input
|
||||
:value="modelValue.street_name"
|
||||
@input="updateField('street_name', ($event.target as HTMLInputElement).value)"
|
||||
placeholder="pl. Egressy"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Street type -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Közterület jellege</label>
|
||||
<select
|
||||
:value="modelValue.street_type"
|
||||
@change="updateField('street_type', ($event.target as HTMLSelectElement).value)"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
>
|
||||
<option value="">Válassz...</option>
|
||||
<option value="utca">utca</option>
|
||||
<option value="út">út</option>
|
||||
<option value="tér">tér</option>
|
||||
<option value="körút">körút</option>
|
||||
<option value="sugárút">sugárút</option>
|
||||
<option value="köz">köz</option>
|
||||
<option value="sétány">sétány</option>
|
||||
<option value="lakópark">lakópark</option>
|
||||
<option value="liget">liget</option>
|
||||
<option value="erdő">erdő</option>
|
||||
<option value="dűlő">dűlő</option>
|
||||
<option value="major">major</option>
|
||||
<option value="puszta">puszta</option>
|
||||
<option value="sziget">sziget</option>
|
||||
<option value="telep">telep</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- House number -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Házszám</label>
|
||||
<input
|
||||
:value="modelValue.house_number"
|
||||
@input="updateField('house_number', ($event.target as HTMLInputElement).value)"
|
||||
placeholder="pl. 4/b"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Stairwell -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Lépcsőház</label>
|
||||
<input
|
||||
:value="modelValue.stairwell"
|
||||
@input="updateField('stairwell', ($event.target as HTMLInputElement).value)"
|
||||
placeholder="pl. 1"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Floor -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Emelet</label>
|
||||
<input
|
||||
:value="modelValue.floor"
|
||||
@input="updateField('floor', ($event.target as HTMLInputElement).value)"
|
||||
placeholder="pl. 3"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Door -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Ajtó</label>
|
||||
<input
|
||||
:value="modelValue.door"
|
||||
@input="updateField('door', ($event.target as HTMLInputElement).value)"
|
||||
placeholder="pl. A"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Parcel ID (hrsz) -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-1">Helyrajzi szám (hrsz)</label>
|
||||
<input
|
||||
:value="modelValue.parcel_id"
|
||||
@input="updateField('parcel_id', ($event.target as HTMLInputElement).value)"
|
||||
placeholder="pl. 12345/6"
|
||||
class="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* SharedAddressForm.vue
|
||||
* ======================
|
||||
*
|
||||
* Reusable address form component that uses SmartLocationInput for
|
||||
* zip/city autocomplete and provides all other address fields.
|
||||
*
|
||||
* Usage:
|
||||
* <SharedAddressForm v-model="form.address" />
|
||||
*
|
||||
* The v-model expects an object matching the AddressIn schema:
|
||||
* {
|
||||
* zip?: string
|
||||
* city?: string
|
||||
* street_name?: string
|
||||
* street_type?: string
|
||||
* house_number?: string
|
||||
* stairwell?: string
|
||||
* floor?: string
|
||||
* door?: string
|
||||
* parcel_id?: string
|
||||
* full_address_text?: string
|
||||
* latitude?: number
|
||||
* longitude?: number
|
||||
* }
|
||||
*/
|
||||
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
interface AddressForm {
|
||||
zip?: string | null
|
||||
city?: string | null
|
||||
street_name?: string | null
|
||||
street_type?: string | null
|
||||
house_number?: string | null
|
||||
stairwell?: string | null
|
||||
floor?: string | null
|
||||
door?: string | null
|
||||
parcel_id?: string | null
|
||||
full_address_text?: string | null
|
||||
latitude?: number | null
|
||||
longitude?: number | null
|
||||
}
|
||||
|
||||
interface LocationItem {
|
||||
id: number
|
||||
zip_code: string
|
||||
city: string
|
||||
country_code: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue?: AddressForm
|
||||
}>(), {
|
||||
modelValue: () => ({
|
||||
zip: null,
|
||||
city: null,
|
||||
street_name: null,
|
||||
street_type: null,
|
||||
house_number: null,
|
||||
stairwell: null,
|
||||
floor: null,
|
||||
door: null,
|
||||
parcel_id: null,
|
||||
full_address_text: null,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
}),
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: AddressForm]
|
||||
}>()
|
||||
|
||||
/**
|
||||
* Computed property for the SmartLocationInput selected value.
|
||||
* Converts the address zip/city to a LocationItem if both are present.
|
||||
*/
|
||||
const selectedLocation = computed<LocationItem | null>(() => {
|
||||
if (props.modelValue?.zip && props.modelValue?.city) {
|
||||
return {
|
||||
id: 0, // We don't have the DB id here, but SmartLocationInput handles this
|
||||
zip_code: props.modelValue.zip,
|
||||
city: props.modelValue.city,
|
||||
country_code: 'HU',
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
/**
|
||||
* Handle location selection from SmartLocationInput.
|
||||
* Updates the zip and city fields in the address model.
|
||||
*/
|
||||
function onLocationSelected(location: LocationItem | null) {
|
||||
const updated = { ...props.modelValue }
|
||||
if (location) {
|
||||
updated.zip = location.zip_code
|
||||
updated.city = location.city
|
||||
} else {
|
||||
updated.zip = null
|
||||
updated.city = null
|
||||
}
|
||||
emit('update:modelValue', updated)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single field in the address model.
|
||||
*/
|
||||
function updateField(field: keyof AddressForm, value: string) {
|
||||
const updated = { ...props.modelValue }
|
||||
;(updated as any)[field] = value || null
|
||||
emit('update:modelValue', updated)
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user