diff --git a/backend/app/routers/schedules.py b/backend/app/routers/schedules.py
index 3f6e31b..e1f0cfc 100644
--- a/backend/app/routers/schedules.py
+++ b/backend/app/routers/schedules.py
@@ -11,6 +11,7 @@ from app.schemas.schedule import (
ScheduleTemplateOut,
ScheduleTemplateUpdate,
ScheduleBlockCreate,
+ ScheduleBlockUpdate,
ScheduleBlockOut,
)
@@ -144,6 +145,34 @@ async def add_block(
return block
+@router.patch("/{template_id}/blocks/{block_id}", response_model=ScheduleBlockOut)
+async def update_block(
+ template_id: int,
+ block_id: int,
+ body: ScheduleBlockUpdate,
+ current_user: User = Depends(get_current_user),
+ db: AsyncSession = Depends(get_db),
+):
+ result = await db.execute(
+ select(ScheduleBlock)
+ .join(ScheduleTemplate)
+ .where(
+ ScheduleBlock.id == block_id,
+ ScheduleBlock.template_id == template_id,
+ ScheduleTemplate.user_id == current_user.id,
+ )
+ )
+ block = result.scalar_one_or_none()
+ if not block:
+ raise HTTPException(status_code=404, detail="Block not found")
+
+ for field, value in body.model_dump(exclude_unset=True).items():
+ setattr(block, field, value)
+ await db.commit()
+ await db.refresh(block)
+ return block
+
+
@router.delete("/{template_id}/blocks/{block_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_block(
template_id: int,
diff --git a/backend/app/schemas/schedule.py b/backend/app/schemas/schedule.py
index 6fafef5..78c4d2a 100644
--- a/backend/app/schemas/schedule.py
+++ b/backend/app/schemas/schedule.py
@@ -11,6 +11,15 @@ class ScheduleBlockCreate(BaseModel):
order_index: int = 0
+class ScheduleBlockUpdate(BaseModel):
+ subject_id: int | None = None
+ time_start: time | None = None
+ time_end: time | None = None
+ label: str | None = None
+ notes: str | None = None
+ order_index: int | None = None
+
+
class ScheduleBlockOut(BaseModel):
id: int
subject_id: int | None
diff --git a/frontend/src/views/AdminView.vue b/frontend/src/views/AdminView.vue
index 8919345..d969061 100644
--- a/frontend/src/views/AdminView.vue
+++ b/frontend/src/views/AdminView.vue
@@ -154,11 +154,32 @@
-
- {{ block.time_start }} – {{ block.time_end }}
- {{ block.label || subjectName(block.subject_id) || 'Unnamed' }}
-
-
+
+
+
+
+
+ {{ block.time_start }} – {{ block.time_end }}
+ {{ block.label || subjectName(block.subject_id) || 'Unnamed' }}
+
+
+
+
No blocks yet.
@@ -275,6 +296,7 @@ const showCreateForm = ref(false)
const editingTemplate = ref(null)
const newTemplate = ref({ name: '', child_id: null, is_default: false })
const newBlock = ref({ subject_id: null, time_start: '', time_end: '', label: '', order_index: 0 })
+const editingBlock = ref(null)
function childName(id) {
return childrenStore.children.find((c) => c.id === id)?.name || 'Unknown'
@@ -313,6 +335,23 @@ async function addBlock(templateId) {
await loadTemplates()
}
+function startEditBlock(block) {
+ editingBlock.value = {
+ id: block.id,
+ subject_id: block.subject_id,
+ time_start: block.time_start ? block.time_start.slice(0, 5) : '',
+ time_end: block.time_end ? block.time_end.slice(0, 5) : '',
+ label: block.label || '',
+ }
+}
+
+async function saveBlock(templateId) {
+ const { id, ...payload } = editingBlock.value
+ await api.patch(`/api/schedules/${templateId}/blocks/${id}`, payload)
+ editingBlock.value = null
+ await loadTemplates()
+}
+
async function deleteBlock(templateId, blockId) {
await api.delete(`/api/schedules/${templateId}/blocks/${blockId}`)
await loadTemplates()
@@ -442,7 +481,8 @@ h2 { font-size: 1.1rem; color: #94a3b8; text-transform: uppercase; letter-spacin
.block-time { font-size: 0.8rem; color: #64748b; font-variant-numeric: tabular-nums; }
.block-label { flex: 1; font-size: 0.9rem; }
-.add-block-form {
+.add-block-form,
+.edit-block-form {
display: flex;
align-items: center;
gap: 0.5rem;
@@ -452,7 +492,9 @@ h2 { font-size: 1.1rem; color: #94a3b8; text-transform: uppercase; letter-spacin
border-radius: 0.75rem;
}
.add-block-form select,
-.add-block-form input {
+.add-block-form input,
+.edit-block-form select,
+.edit-block-form input {
padding: 0.4rem 0.6rem;
background: #1e293b;
border: 1px solid #334155;
@@ -460,7 +502,9 @@ h2 { font-size: 1.1rem; color: #94a3b8; text-transform: uppercase; letter-spacin
color: #f1f5f9;
font-size: 0.85rem;
}
-.add-block-form span { color: #64748b; }
+.add-block-form span,
+.edit-block-form span { color: #64748b; }
+.edit-block-form { border: 1px solid #4f46e5; }
.empty-small { color: #64748b; font-size: 0.9rem; padding: 1rem 0; }