v0.1.52 - 이월 배지와 통계 설명 팝업 정리

This commit is contained in:
2026-04-23 15:32:48 +09:00
parent 6c69658d33
commit b80994d114
5 changed files with 46 additions and 47 deletions

View File

@@ -234,6 +234,8 @@
- 오른쪽 플래너 사이드바의 중복 `STATS` 카드는 제거했다. 미완료 항목 이월 버튼은 `READ NEXT` 카드 아래로 이동했다.
- 통계 화면은 진입 시 END DATE를 오늘로 보정한다. `최근 1주`, `최근 1달` 빠른 선택을 추가했고, 기존 `WEEKLY FLOW`는 선택 범위 안에서 기록이 있는 날짜별 집중 흐름을 보여주는 `RANGE FLOW`로 이름과 라벨을 정리했다.
- `BEST DAY`는 선택 기간 안에서 집중 시간이 가장 긴 날짜를 고르고, `RECENT RECORDS`는 선택 기간 안의 기록을 날짜 내림차순으로 최대 5개 보여준다.
- `CARRYOVER TASK` 선택 모달은 ESC로 닫힌다. 이월 배지의 시작일 안내는 오른쪽 패널 메시지 대신 배지 옆 팝업으로 표시한다.
- 통계의 `BEST DAY`, `RECENT RECORDS` 기준 설명은 본문 문장 대신 물음표 가이드 팝업으로 제공한다.
## 갱신 규칙

View File

@@ -85,7 +85,6 @@ const passwordBusy = ref(false)
const profileMessage = ref('')
const passwordMessage = ref('')
const carryoverMessage = ref('')
const carryoverInspectMessage = ref('')
const carryoverCheckPolicy = ref(readCarryoverCheckPolicy())
const carryoverCheckPrompt = ref(null)
const guideTooltipResetMessage = ref('')
@@ -665,7 +664,6 @@ function shiftDate(amount) {
selectedDate.value = next
calendarViewDate.value = new Date(next)
carryoverMessage.value = ''
carryoverInspectMessage.value = ''
}
function shiftCalendarMonth(amount) {
@@ -684,7 +682,6 @@ function selectDate(date) {
selectedDate.value = new Date(date)
calendarViewDate.value = new Date(date)
carryoverMessage.value = ''
carryoverInspectMessage.value = ''
}
function updateComment(record, value) {
@@ -803,6 +800,13 @@ function closeCarryoverCheckPrompt() {
carryoverCheckPrompt.value = null
}
function handleGlobalKeydown(event) {
if (event.key === 'Escape' && carryoverCheckPrompt.value) {
event.preventDefault()
closeCarryoverCheckPrompt()
}
}
function clearTasks(record, indexes) {
indexes.forEach((index) => {
if (!record.tasks[index]) {
@@ -858,15 +862,6 @@ function carryIncompleteTasksToNextDay() {
: `${nextDateLabel} 빈칸 ${copyCount}개까지만 이월했습니다.`
}
function inspectCarryoverTask(task) {
if (!task.carryoverFrom) {
carryoverInspectMessage.value = ''
return
}
carryoverInspectMessage.value = `"${task.title}" 항목은 ${createDateLabel(task.carryoverFrom)}부터 이월된 할 일입니다.`
}
function updateMemo(record, { index, value }) {
record.memo[index].text = value
schedulePlannerSyncForRecord(record)
@@ -1853,11 +1848,13 @@ onMounted(() => {
})
updateWindowWidth()
window.addEventListener('resize', updateWindowWidth)
window.addEventListener('keydown', handleGlobalKeydown)
restoreAuthSession()
})
onBeforeUnmount(() => {
window.removeEventListener('resize', updateWindowWidth)
window.removeEventListener('keydown', handleGlobalKeydown)
})
</script>
@@ -2414,7 +2411,6 @@ onBeforeUnmount(() => {
@update:task-title="updateTaskTitle(planner, $event)"
@toggle:task="toggleTask(planner, $event)"
@clear:tasks="clearTasks(planner, $event)"
@inspect:carryover="inspectCarryoverTask"
@update:memo-label="updateMemoLabel(planner, $event)"
@update:memo="updateMemo(planner, $event)"
@update:timetable="updateTimetable(planner, $event)"
@@ -2545,12 +2541,6 @@ onBeforeUnmount(() => {
>
{{ carryoverMessage }}
</p>
<p
v-if="carryoverInspectMessage"
class="mt-3 rounded-2xl border border-stone-200 bg-white px-4 py-3 text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600"
>
{{ carryoverInspectMessage }}
</p>
</div>
<div class="mt-5 border-t border-stone-200 pt-5">
@@ -2695,12 +2685,6 @@ onBeforeUnmount(() => {
>
{{ carryoverMessage }}
</p>
<p
v-if="carryoverInspectMessage"
class="mt-3 rounded-2xl border border-stone-200 bg-white px-4 py-3 text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600"
>
{{ carryoverInspectMessage }}
</p>
</div>
<div class="mt-5 border-t border-stone-200 pt-5">
@@ -2747,7 +2731,6 @@ onBeforeUnmount(() => {
@update:task-title="updateTaskTitle(planner, $event)"
@toggle:task="toggleTask(planner, $event)"
@clear:tasks="clearTasks(planner, $event)"
@inspect:carryover="inspectCarryoverTask"
@update:memo-label="updateMemoLabel(planner, $event)"
@update:memo="updateMemo(planner, $event)"
@update:timetable="updateTimetable(planner, $event)"
@@ -2772,7 +2755,6 @@ onBeforeUnmount(() => {
@update:task-title="updateTaskTitle(secondaryPlanner, $event)"
@toggle:task="toggleTask(secondaryPlanner, $event)"
@clear:tasks="clearTasks(secondaryPlanner, $event)"
@inspect:carryover="inspectCarryoverTask"
@update:memo-label="updateMemoLabel(secondaryPlanner, $event)"
@update:memo="updateMemo(secondaryPlanner, $event)"
@update:timetable="updateTimetable(secondaryPlanner, $event)"
@@ -2865,7 +2847,6 @@ onBeforeUnmount(() => {
@update:task-title="updateTaskTitle(planner, $event)"
@toggle:task="toggleTask(planner, $event)"
@clear:tasks="clearTasks(planner, $event)"
@inspect:carryover="inspectCarryoverTask"
@update:memo-label="updateMemoLabel(planner, $event)"
@update:memo="updateMemo(planner, $event)"
@update:timetable="updateTimetable(planner, $event)"
@@ -2892,7 +2873,6 @@ onBeforeUnmount(() => {
@update:task-title="updateTaskTitle(planner, $event)"
@toggle:task="toggleTask(planner, $event)"
@clear:tasks="clearTasks(planner, $event)"
@inspect:carryover="inspectCarryoverTask"
@update:memo-label="updateMemoLabel(planner, $event)"
@update:memo="updateMemo(planner, $event)"
@update:timetable="updateTimetable(planner, $event)"
@@ -2916,7 +2896,6 @@ onBeforeUnmount(() => {
@update:task-title="updateTaskTitle(secondaryPlanner, $event)"
@toggle:task="toggleTask(secondaryPlanner, $event)"
@clear:tasks="clearTasks(secondaryPlanner, $event)"
@inspect:carryover="inspectCarryoverTask"
@update:memo-label="updateMemoLabel(secondaryPlanner, $event)"
@update:memo="updateMemo(secondaryPlanner, $event)"
@update:timetable="updateTimetable(secondaryPlanner, $event)"

View File

@@ -14,6 +14,14 @@ const props = defineProps({
type: Boolean,
default: true,
},
dismissible: {
type: Boolean,
default: true,
},
buttonLabel: {
type: String,
default: '?',
},
})
const emit = defineEmits(['dismiss'])
@@ -68,7 +76,7 @@ onBeforeUnmount(() => {
:aria-expanded="open"
@click.stop="toggle"
>
?
{{ buttonLabel }}
</button>
<span
@@ -79,6 +87,7 @@ onBeforeUnmount(() => {
<span class="block text-[10px] font-bold uppercase tracking-[0.2em] text-stone-500">{{ title }}</span>
<span class="mt-2 block text-[11px] font-semibold leading-5 tracking-[0.04em] text-stone-700">{{ description }}</span>
<button
v-if="dismissible"
type="button"
class="mt-3 rounded-full border border-stone-200 px-3 py-2 text-[10px] font-bold tracking-[0.14em] text-stone-600 transition hover:border-stone-500 hover:text-stone-900"
@click="dismiss"

View File

@@ -1,5 +1,6 @@
<script setup>
import { onBeforeUnmount, ref } from 'vue'
import GuideTooltip from './GuideTooltip.vue'
const props = defineProps({
dateMain: {
@@ -62,7 +63,6 @@ const emit = defineEmits([
'update:task-title',
'toggle:task',
'clear:tasks',
'inspect:carryover',
'update:memo-label',
'update:memo',
'update:timetable',
@@ -349,14 +349,13 @@ onBeforeUnmount(() => {
@focus="clearTaskSelectionOnFocus"
@input="emit('update:task-title', { index, value: $event.target.value })"
/>
<button
<GuideTooltip
v-if="task.carryoverFrom"
type="button"
class="shrink-0 rounded-full border border-stone-300 px-2 py-1 text-[8px] font-bold tracking-[0.12em] text-stone-500 transition hover:border-stone-500 hover:text-stone-900"
@click="emit('inspect:carryover', task)"
>
이월
</button>
:title="'이월된 할 일'"
:description="`이 항목은 ${task.carryoverFrom}부터 이월된 할 일입니다.`"
:dismissible="false"
button-label="이월"
/>
</div>
<div class="flex h-full w-[36px] shrink-0 items-center justify-center p-[8px] sm:w-[42px] sm:p-[10px]">
<button

View File

@@ -1,4 +1,6 @@
<script setup>
import GuideTooltip from './GuideTooltip.vue'
defineProps({
overviewCards: {
type: Array,
@@ -140,10 +142,14 @@ const emit = defineEmits(['update:range-start', 'update:range-end', 'quick-range
<div class="grid gap-6">
<article class="rounded-[28px] border border-stone-200 bg-white/86 p-6">
<p class="text-[11px] font-bold tracking-[0.22em] text-stone-500">BEST DAY</p>
<p class="mt-2 text-[11px] font-semibold leading-5 text-stone-500">
선택 기간 안에서 집중 시간이 가장 날짜입니다.
</p>
<div class="flex items-center gap-2">
<p class="text-[11px] font-bold tracking-[0.22em] text-stone-500">BEST DAY</p>
<GuideTooltip
title="Best Day"
description="선택 범위 안에서 FOCUSED TIME이 가장 큰 날짜를 보여줍니다."
:dismissible="false"
/>
</div>
<div v-if="bestDay" class="mt-4">
<h2 class="text-2xl font-semibold tracking-[-0.05em] text-stone-900">
{{ bestDay.dateLabel }}
@@ -158,10 +164,14 @@ const emit = defineEmits(['update:range-start', 'update:range-end', 'quick-range
</article>
<article class="rounded-[28px] border border-stone-200 bg-white/86 p-6">
<p class="text-[11px] font-bold tracking-[0.22em] text-stone-500">RECENT RECORDS</p>
<p class="mt-2 text-[11px] font-semibold leading-5 text-stone-500">
선택 기간 안의 최근 기록을 날짜 내림차순으로 최대 5 표시합니다.
</p>
<div class="flex items-center gap-2">
<p class="text-[11px] font-bold tracking-[0.22em] text-stone-500">RECENT RECORDS</p>
<GuideTooltip
title="Recent Records"
description="선택 범위 안의 기록을 날짜 내림차순으로 최대 5개까지 보여줍니다."
:dismissible="false"
/>
</div>
<div class="mt-4 space-y-4">
<div
v-for="record in recentRecords"