v0.1.52 - 이월 배지와 통계 설명 팝업 정리
This commit is contained in:
@@ -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` 기준 설명은 본문 문장 대신 물음표 가이드 팝업으로 제공한다.
|
||||
|
||||
## 갱신 규칙
|
||||
|
||||
|
||||
39
src/App.vue
39
src/App.vue
@@ -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)"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user