Refactor forms to use EntityEditForm component; enhance styles and improve structure
Some checks failed
Gitea Actions Demo / build-and-push (push) Failing after 6s

This commit is contained in:
2026-01-23 19:29:27 -05:00
parent 63769fbe32
commit 74d6f5819c
7 changed files with 416 additions and 310 deletions

View File

@@ -1,56 +1,35 @@
<template>
<div class="child-edit-view">
<h2>{{ isEdit ? 'Edit Child' : 'Create Child' }}</h2>
<div v-if="loading" class="loading-message">Loading child...</div>
<form v-else @submit.prevent="submit" class="child-edit-form">
<div class="group">
<label for="child-name">Name</label>
<input type="text" id="child-name" ref="nameInput" v-model="name" required maxlength="64" />
</div>
<div class="group">
<label for="child-age">Age</label>
<input id="child-age" v-model.number="age" type="number" min="0" max="120" required />
</div>
<div class="group">
<label for="child-image">Image</label>
<ImagePicker
id="child-image"
v-model="selectedImageId"
:image-type="1"
@add-image="onAddImage"
/>
</div>
<div v-if="error" class="error">{{ error }}</div>
<div class="actions">
<button type="button" class="btn btn-secondary" @click="onCancel" :disabled="loading">
Cancel
</button>
<button type="submit" class="btn btn-primary" :disabled="loading">
{{ isEdit ? 'Save' : 'Create' }}
</button>
</div>
</form>
</div>
<EntityEditForm
entityLabel="Child"
:fields="fields"
:initialData="initialData"
:isEdit="isEdit"
:loading="loading"
:error="error"
@submit="handleSubmit"
@cancel="handleCancel"
@add-image="handleAddImage"
/>
</template>
<script setup lang="ts">
import { ref, onMounted, computed, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import ImagePicker from '@/components/utils/ImagePicker.vue'
import '@/assets/edit-forms.css'
import EntityEditForm from '../shared/EntityEditForm.vue'
const route = useRoute()
const router = useRouter()
// Accept id as a prop for edit mode
const props = defineProps<{ id?: string }>()
const isEdit = computed(() => !!props.id)
const name = ref('')
const age = ref<number | null>(null)
const selectedImageId = ref<string | null>(null)
const fields = [
{ name: 'name', label: 'Name', type: 'text', required: true, maxlength: 64 },
{ name: 'age', label: 'Age', type: 'number', required: true, min: 0, max: 120 },
{ name: 'image_id', label: 'Image', type: 'image', imageType: 1 },
]
const initialData = ref({ name: '', age: null, image_id: null })
const localImageFile = ref<File | null>(null)
const nameInput = ref<HTMLInputElement | null>(null)
const loading = ref(false)
const error = ref<string | null>(null)
@@ -61,36 +40,34 @@ onMounted(async () => {
const resp = await fetch(`/api/child/${props.id}`)
if (!resp.ok) throw new Error('Failed to load child')
const data = await resp.json()
name.value = data.name ?? ''
age.value = Number(data.age) ?? null
selectedImageId.value = data.image_id ?? null
initialData.value = {
name: data.name ?? '',
age: Number(data.age) ?? null,
image_id: data.image_id ?? null,
}
} catch (e) {
error.value = 'Could not load child.'
} finally {
loading.value = false
await nextTick()
nameInput.value?.focus()
}
} else {
await nextTick()
nameInput.value?.focus()
}
})
function onAddImage({ id, file }: { id: string; file: File }) {
function handleAddImage({ id, file }: { id: string; file: File }) {
if (id === 'local-upload') {
localImageFile.value = file
}
}
const submit = async () => {
let imageId = selectedImageId.value
async function handleSubmit(form: any) {
let imageId = form.image_id
error.value = null
if (!name.value.trim()) {
if (!form.name.trim()) {
error.value = 'Child name is required.'
return
}
if (age.value === null || age.value < 0) {
if (form.age === null || form.age < 0) {
error.value = 'Age must be a non-negative number.'
return
}
@@ -111,7 +88,7 @@ const submit = async () => {
const data = await resp.json()
imageId = data.id
} catch (err) {
alert('Failed to upload image.')
error.value = 'Failed to upload image.'
loading.value = false
return
}
@@ -125,8 +102,8 @@ const submit = async () => {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: name.value,
age: age.value,
name: form.name,
age: form.age,
image_id: imageId,
}),
})
@@ -135,8 +112,8 @@ const submit = async () => {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: name.value,
age: age.value,
name: form.name,
age: form.age,
image_id: imageId,
}),
})
@@ -144,14 +121,12 @@ const submit = async () => {
if (!resp.ok) throw new Error('Failed to save child')
await router.push({ name: 'ParentChildrenListView' })
} catch (err) {
alert('Failed to save child.')
error.value = 'Failed to save child.'
}
loading.value = false
}
function onCancel() {
function handleCancel() {
router.back()
}
</script>
<style scoped></style>