Add greeting and countdown timer to TV dashboard before session starts
Shows "Good Morning! Ready to start school?" placeholder when a session is active but no block has been selected, along with a live countdown to the first scheduled block's start time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,15 @@
|
||||
<!-- Active session -->
|
||||
<div v-else class="tv-main">
|
||||
<!-- Left: timer -->
|
||||
<div class="tv-timer-col" v-if="scheduleStore.currentBlock">
|
||||
<div class="tv-timer-col tv-greeting-col" v-if="!scheduleStore.currentBlock">
|
||||
<div class="tv-greeting">Good Morning!</div>
|
||||
<div class="tv-greeting-sub">Ready to start school?</div>
|
||||
<div v-if="firstBlockCountdown !== null" class="tv-countdown-wrap">
|
||||
<div class="tv-countdown-label">First block starts in</div>
|
||||
<div class="tv-countdown">{{ firstBlockCountdown }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tv-timer-col" v-else>
|
||||
<div class="tv-subject-badge" :style="{ background: currentSubjectColor }">
|
||||
{{ currentSubjectIcon }} {{ currentSubjectName }}
|
||||
</div>
|
||||
@@ -129,6 +137,23 @@ const dayProgressPercent = computed(() => {
|
||||
return Math.max(0, Math.min(100, Math.round((nowMin - start) / (end - start) * 100)))
|
||||
})
|
||||
|
||||
// Countdown to first block
|
||||
const firstBlockCountdown = computed(() => {
|
||||
const first = scheduleStore.blocks[0]
|
||||
if (!first?.time_start) return null
|
||||
const [h, m, s] = first.time_start.split(':').map(Number)
|
||||
const target = new Date(now.value)
|
||||
target.setHours(h, m, s || 0, 0)
|
||||
const diffMs = target - now.value
|
||||
if (diffMs <= 0) return null
|
||||
const totalSec = Math.floor(diffMs / 1000)
|
||||
const hours = Math.floor(totalSec / 3600)
|
||||
const mins = Math.floor((totalSec % 3600) / 60)
|
||||
const secs = totalSec % 60
|
||||
if (hours > 0) return `${hours}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`
|
||||
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`
|
||||
})
|
||||
|
||||
// Subject display helpers
|
||||
const currentSubjectColor = computed(() => {
|
||||
const block = scheduleStore.currentBlock
|
||||
@@ -228,6 +253,47 @@ onMounted(async () => {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tv-greeting-col {
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.tv-greeting {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
color: #818cf8;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tv-greeting-sub {
|
||||
font-size: 1.6rem;
|
||||
color: #64748b;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tv-countdown-wrap {
|
||||
margin-top: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.tv-countdown-label {
|
||||
font-size: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.tv-countdown {
|
||||
font-size: 4rem;
|
||||
font-weight: 300;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: #c7d2fe;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.tv-block-notes {
|
||||
font-size: 1rem;
|
||||
color: #94a3b8;
|
||||
|
||||
Reference in New Issue
Block a user