Add inline edit for children and subjects in admin, restore port 8054
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,15 +20,26 @@
|
||||
|
||||
<div class="item-list">
|
||||
<div v-for="child in childrenStore.children" :key="child.id" class="item-row">
|
||||
<div class="item-color" :style="{ background: child.color }"></div>
|
||||
<span class="item-name">{{ child.name }}</span>
|
||||
<span class="item-meta">{{ child.is_active ? 'Active' : 'Inactive' }}</span>
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm" @click="toggleChild(child)">
|
||||
{{ child.is_active ? 'Deactivate' : 'Activate' }}
|
||||
</button>
|
||||
<button class="btn-sm btn-danger" @click="deleteChild(child.id)">Delete</button>
|
||||
</div>
|
||||
<template v-if="editingChild && editingChild.id === child.id">
|
||||
<input v-model="editingChild.name" class="edit-input" required />
|
||||
<input v-model="editingChild.color" type="color" title="Color" />
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm btn-primary" @click="saveChild">Save</button>
|
||||
<button class="btn-sm" @click="editingChild = null">Cancel</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="item-color" :style="{ background: child.color }"></div>
|
||||
<span class="item-name">{{ child.name }}</span>
|
||||
<span class="item-meta">{{ child.is_active ? 'Active' : 'Inactive' }}</span>
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm" @click="startEditChild(child)">Edit</button>
|
||||
<button class="btn-sm" @click="toggleChild(child)">
|
||||
{{ child.is_active ? 'Deactivate' : 'Activate' }}
|
||||
</button>
|
||||
<button class="btn-sm btn-danger" @click="deleteChild(child.id)">Delete</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="childrenStore.children.length === 0" class="empty-small">No children added yet.</div>
|
||||
</div>
|
||||
@@ -51,12 +62,24 @@
|
||||
|
||||
<div class="item-list">
|
||||
<div v-for="subject in subjects" :key="subject.id" class="item-row">
|
||||
<div class="item-color" :style="{ background: subject.color }"></div>
|
||||
<span class="item-icon">{{ subject.icon }}</span>
|
||||
<span class="item-name">{{ subject.name }}</span>
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm btn-danger" @click="deleteSubject(subject.id)">Delete</button>
|
||||
</div>
|
||||
<template v-if="editingSubject && editingSubject.id === subject.id">
|
||||
<input v-model="editingSubject.name" class="edit-input" required />
|
||||
<input v-model="editingSubject.icon" placeholder="Icon" maxlength="4" style="width:60px" class="edit-input" />
|
||||
<input v-model="editingSubject.color" type="color" title="Color" />
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm btn-primary" @click="saveSubject">Save</button>
|
||||
<button class="btn-sm" @click="editingSubject = null">Cancel</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="item-color" :style="{ background: subject.color }"></div>
|
||||
<span class="item-icon">{{ subject.icon }}</span>
|
||||
<span class="item-name">{{ subject.name }}</span>
|
||||
<div class="item-actions">
|
||||
<button class="btn-sm" @click="startEditSubject(subject)">Edit</button>
|
||||
<button class="btn-sm btn-danger" @click="deleteSubject(subject.id)">Delete</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="subjects.length === 0" class="empty-small">No subjects added yet.</div>
|
||||
</div>
|
||||
@@ -78,6 +101,8 @@ const showChildForm = ref(false)
|
||||
const showSubjectForm = ref(false)
|
||||
const newChild = ref({ name: '', color: '#4F46E5' })
|
||||
const newSubject = ref({ name: '', icon: '📚', color: '#10B981' })
|
||||
const editingChild = ref(null)
|
||||
const editingSubject = ref(null)
|
||||
|
||||
async function createChild() {
|
||||
await childrenStore.createChild(newChild.value)
|
||||
@@ -85,6 +110,19 @@ async function createChild() {
|
||||
showChildForm.value = false
|
||||
}
|
||||
|
||||
function startEditChild(child) {
|
||||
editingChild.value = { ...child }
|
||||
showChildForm.value = false
|
||||
}
|
||||
|
||||
async function saveChild() {
|
||||
await childrenStore.updateChild(editingChild.value.id, {
|
||||
name: editingChild.value.name,
|
||||
color: editingChild.value.color,
|
||||
})
|
||||
editingChild.value = null
|
||||
}
|
||||
|
||||
async function toggleChild(child) {
|
||||
await childrenStore.updateChild(child.id, { is_active: !child.is_active })
|
||||
}
|
||||
@@ -100,6 +138,22 @@ async function loadSubjects() {
|
||||
subjects.value = res.data
|
||||
}
|
||||
|
||||
function startEditSubject(subject) {
|
||||
editingSubject.value = { ...subject }
|
||||
showSubjectForm.value = false
|
||||
}
|
||||
|
||||
async function saveSubject() {
|
||||
const res = await api.patch(`/api/subjects/${editingSubject.value.id}`, {
|
||||
name: editingSubject.value.name,
|
||||
icon: editingSubject.value.icon,
|
||||
color: editingSubject.value.color,
|
||||
})
|
||||
const idx = subjects.value.findIndex((s) => s.id === editingSubject.value.id)
|
||||
if (idx !== -1) subjects.value[idx] = res.data
|
||||
editingSubject.value = null
|
||||
}
|
||||
|
||||
async function createSubject() {
|
||||
const res = await api.post('/api/subjects', newSubject.value)
|
||||
subjects.value.push(res.data)
|
||||
@@ -171,6 +225,17 @@ h2 { font-size: 1.1rem; color: #94a3b8; text-transform: uppercase; letter-spacin
|
||||
|
||||
.empty-small { color: #64748b; font-size: 0.9rem; padding: 1rem 0; }
|
||||
|
||||
.edit-input {
|
||||
padding: 0.35rem 0.6rem;
|
||||
background: #0f172a;
|
||||
border: 1px solid #4f46e5;
|
||||
border-radius: 0.5rem;
|
||||
color: #f1f5f9;
|
||||
font-size: 0.9rem;
|
||||
flex: 1;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
padding: 0.5rem 1rem;
|
||||
background: #4f46e5;
|
||||
|
||||
Reference in New Issue
Block a user