-
목표 페이스 설정:
-
+
+
+
+
+
+ /05 Flow velocity
+
+
+ 시간당 생산 분량과 목표선 비교
+
+
+
= targetPace ? 'success' : 'warning'}>
+ Avg {todayAverage} min/h
+
+
+
+
+ Daily allocation
+
+
+
-
+
);
};
diff --git a/apps/web/src/hooks/useCommandPalette.ts b/apps/web/src/hooks/useCommandPalette.ts
index 87cf0cf..ee17387 100644
--- a/apps/web/src/hooks/useCommandPalette.ts
+++ b/apps/web/src/hooks/useCommandPalette.ts
@@ -14,7 +14,16 @@ export const useCommandPalette = () => {
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
// Cmd+P (Mac) 또는 Ctrl+P (Windows/Linux)
- if ((e.metaKey || e.ctrlKey) && e.key === 'p') {
+ if (
+ !e.isComposing &&
+ !e.altKey &&
+ !e.shiftKey &&
+ (e.metaKey || e.ctrlKey) &&
+ e.key.toLowerCase() === 'p'
+ ) {
+ const hasOpenDialog = document.querySelector('.modal-open') !== null;
+ if (!isOpen && hasOpenDialog) return;
+
e.preventDefault(); // 브라우저 기본 동작(인쇄) 방지
toggle();
}
@@ -22,7 +31,7 @@ export const useCommandPalette = () => {
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
- }, [toggle]);
+ }, [isOpen, toggle]);
return {
isOpen,
diff --git a/apps/web/src/pages/LogWriterPage.tsx b/apps/web/src/pages/LogWriterPage.tsx
index 4c27e6a..1585d6c 100644
--- a/apps/web/src/pages/LogWriterPage.tsx
+++ b/apps/web/src/pages/LogWriterPage.tsx
@@ -1,4 +1,11 @@
-import { Bell, Timer } from 'lucide-react';
+import {
+ Bell,
+ CircleDot,
+ Database,
+ Keyboard,
+ Radio,
+ Timer,
+} from 'lucide-react';
import { lazy, Suspense, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
@@ -7,6 +14,15 @@ import { ConflictDialog } from '../components/common/ConflictDialog';
import { DataManagementButton } from '../components/dataManagement/DataManagementButton';
import { DayNavigator } from '../components/days/DayNavigator';
import { TextLogContainer } from '../components/texts/TextLogContainer';
+import { TimeSummary } from '../components/texts/TimeSummary';
+import { Badge } from '../components/ui/badge';
+import { Button } from '../components/ui/button';
+import {
+ Card,
+ CardContent,
+ CardHeader,
+ CardTitle,
+} from '../components/ui/card';
import { Area_AvailableRestTimeChart } from '../features/AvailableRestTimeChartArea';
import { Area_ProductivePaceChart } from '../features/ProductivePaceChartArea';
import {
@@ -24,6 +40,21 @@ const DataManagementDialog = lazy(() =>
})),
);
+const SYNC_PRESENTATIONS = {
+ idle: { label: 'Local idle', variant: 'muted' as const },
+ pending: { label: 'Write pending', variant: 'warning' as const },
+ syncing: { label: 'Sync in progress', variant: 'default' as const },
+ synced: { label: 'Cloud synced', variant: 'success' as const },
+ error: { label: 'Sync failure', variant: 'danger' as const },
+};
+
+const HOTKEYS = [
+ { shortcut: '/', label: 'Focus activity' },
+ { shortcut: 'Alt 1', label: 'Quick production' },
+ { shortcut: 'Alt 2', label: 'Quick consumption' },
+ { shortcut: '⌘/Ctrl P', label: 'Command palette' },
+];
+
export const LogWriterPage = () => {
// 휴식 알림 시스템 활성화
useRestNotification();
@@ -37,7 +68,9 @@ export const LogWriterPage = () => {
(state: RootState) => state.logs.logsForCharts,
);
- const { currentDate } = useSelector((state: RootState) => state.logs);
+ const { currentDate, rawLogs, syncStatus } = useSelector(
+ (state: RootState) => state.logs,
+ );
const currentNotification = useSelector(
(state: RootState) => state.restNotification.currentNotification,
);
@@ -55,44 +88,151 @@ export const LogWriterPage = () => {
// 잔여 시간 계산
const { remainingTime, isOvertime } = useRemainingTime(currentNotification);
+ const syncPresentation = SYNC_PRESENTATIONS[syncStatus];
+ const logLineCount = rawLogs.trim()
+ ? rawLogs.split('\n').filter((line) => line.trim()).length
+ : 0;
+
return (
-
-
-
-
- [기록지] ({currentDate})
-
- {currentNotification && (
-
-
- 잔여 휴식 시간: {remainingTime}
+
+
+
+
+ MC
+
+
+
+
+ Focus command deck
+
+
+
+ Operational
+
- )}
+
+ My Commit / daily operations console
+
+
-
+
+
+
+
+ Command
+
+ ⌘ / Ctrl P
+
-
+
setIsDataManagementOpen(true)} />
-
-
+
+
+
+
+
+
+
+
+
+
+