Show duration on schedule block lists
Display effective duration (time window or custom override) on every block list — Admin, Dashboard, and TV sidebar. Custom duration_minutes values are highlighted in indigo to distinguish them from the default time-window calculation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,12 @@
|
|||||||
<div class="block-title">
|
<div class="block-title">
|
||||||
{{ block.label || subjectName || 'Block' }}
|
{{ block.label || subjectName || 'Block' }}
|
||||||
</div>
|
</div>
|
||||||
<div class="block-time">{{ block.time_start }} – {{ block.time_end }}</div>
|
<div class="block-time">
|
||||||
|
{{ block.time_start }} – {{ block.time_end }}
|
||||||
|
<span class="block-duration" :class="{ 'block-duration-custom': block.duration_minutes != null }">
|
||||||
|
· {{ durationLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="block-status" v-if="isCompleted">✓</div>
|
<div class="block-status" v-if="isCompleted">✓</div>
|
||||||
<div class="block-status active" v-else-if="isCurrent">▶</div>
|
<div class="block-status active" v-else-if="isCurrent">▶</div>
|
||||||
@@ -31,6 +36,19 @@ const props = defineProps({
|
|||||||
|
|
||||||
const subjectColor = computed(() => props.block.subject?.color || '#475569')
|
const subjectColor = computed(() => props.block.subject?.color || '#475569')
|
||||||
const subjectName = computed(() => props.block.subject?.name || null)
|
const subjectName = computed(() => props.block.subject?.name || null)
|
||||||
|
|
||||||
|
const durationLabel = computed(() => {
|
||||||
|
if (props.block.duration_minutes != null) return `${props.block.duration_minutes} min`
|
||||||
|
const start = props.block.time_start
|
||||||
|
const end = props.block.time_end
|
||||||
|
if (start && end) {
|
||||||
|
const [sh, sm] = start.split(':').map(Number)
|
||||||
|
const [eh, em] = end.split(':').map(Number)
|
||||||
|
const mins = (eh * 60 + em) - (sh * 60 + sm)
|
||||||
|
if (mins > 0) return `${mins} min`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -90,6 +108,9 @@ const subjectName = computed(() => props.block.subject?.name || null)
|
|||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.block-duration { color: #475569; }
|
||||||
|
.block-duration-custom { color: #818cf8; }
|
||||||
|
|
||||||
.block-status {
|
.block-status {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
|
|||||||
@@ -182,6 +182,9 @@
|
|||||||
<div v-else class="block-row">
|
<div v-else class="block-row">
|
||||||
<span class="block-time">{{ block.time_start }} – {{ block.time_end }}</span>
|
<span class="block-time">{{ block.time_start }} – {{ block.time_end }}</span>
|
||||||
<span class="block-label">{{ block.label || subjectName(block.subject_id) || 'Unnamed' }}</span>
|
<span class="block-label">{{ block.label || subjectName(block.subject_id) || 'Unnamed' }}</span>
|
||||||
|
<span class="block-duration" :class="{ 'block-duration-custom': block.duration_minutes != null }">
|
||||||
|
{{ blockDurationLabel(block) }}
|
||||||
|
</span>
|
||||||
<button class="btn-sm" @click="startEditBlock(block)">Edit</button>
|
<button class="btn-sm" @click="startEditBlock(block)">Edit</button>
|
||||||
<button class="btn-sm btn-danger" @click="deleteBlock(template.id, block.id)">✕</button>
|
<button class="btn-sm btn-danger" @click="deleteBlock(template.id, block.id)">✕</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -318,6 +321,17 @@ function subjectName(id) {
|
|||||||
return subjects.value.find((s) => s.id === id)?.name || null
|
return subjects.value.find((s) => s.id === id)?.name || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function blockDurationLabel(block) {
|
||||||
|
if (block.duration_minutes != null) return `${block.duration_minutes} min`
|
||||||
|
if (block.time_start && block.time_end) {
|
||||||
|
const [sh, sm] = block.time_start.split(':').map(Number)
|
||||||
|
const [eh, em] = block.time_end.split(':').map(Number)
|
||||||
|
const mins = (eh * 60 + em) - (sh * 60 + sm)
|
||||||
|
if (mins > 0) return `${mins} min`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
async function loadTemplates() {
|
async function loadTemplates() {
|
||||||
const res = await api.get('/api/schedules')
|
const res = await api.get('/api/schedules')
|
||||||
templates.value = res.data
|
templates.value = res.data
|
||||||
@@ -493,6 +507,8 @@ h2 { font-size: 1.1rem; color: #94a3b8; text-transform: uppercase; letter-spacin
|
|||||||
.block-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem; background: #0f172a; border-radius: 0.5rem; }
|
.block-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem; background: #0f172a; border-radius: 0.5rem; }
|
||||||
.block-time { font-size: 0.8rem; color: #64748b; font-variant-numeric: tabular-nums; }
|
.block-time { font-size: 0.8rem; color: #64748b; font-variant-numeric: tabular-nums; }
|
||||||
.block-label { flex: 1; font-size: 0.9rem; }
|
.block-label { flex: 1; font-size: 0.9rem; }
|
||||||
|
.block-duration { font-size: 0.78rem; color: #475569; }
|
||||||
|
.block-duration-custom { color: #818cf8; }
|
||||||
|
|
||||||
.add-block-form,
|
.add-block-form,
|
||||||
.edit-block-form {
|
.edit-block-form {
|
||||||
|
|||||||
Reference in New Issue
Block a user