• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jcubic / 10xDevs / 19946653658

04 Dec 2025 10:56PM UTC coverage: 62.673%. Remained the same
19946653658

push

github

jcubic
10xDev Project

303 of 501 branches covered (60.48%)

Branch coverage included in aggregate %.

555 of 864 new or added lines in 49 files covered. (64.24%)

4 existing lines in 1 file now uncovered.

555 of 868 relevant lines covered (63.94%)

214.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.76
/src/components/notes/MiddlePanel.tsx
1
/**
2
 * Middle panel component for note editing and content display.
3
 *
4
 * @remarks
5
 * Dependencies: Chakra UI v3, React, Editor component
6
 *
7
 * **Features:**
8
 * - Note title display
9
 * - Real-time save status indicator
10
 * - CodeMirror-based markdown editor
11
 * - Line selection support
12
 * - Empty state for no selected note
13
 * - Editor reference callback for parent control
14
 *
15
 * **Save Status:**
16
 * - idle: No indicator shown
17
 * - saving: Blue "Saving..." text
18
 * - saved: Green "Saved" text
19
 * - error: Red "Save failed" text
20
 *
21
 * **Performance:**
22
 * - Memoized component and computed values
23
 * - useCallback for event handlers
24
 *
25
 * @example
26
 * ```tsx
27
 * <MiddlePanel
28
 *   note={currentNote}
29
 *   content={noteContent}
30
 *   saveStatus="saved"
31
 *   selectedLine={42}
32
 *   onContentChange={handleChange}
33
 *   onSave={handleSave}
34
 *   onEditorReady={(ref) => editorRef.current = ref}
35
 * />
36
 * ```
37
 *
38
 * @public
39
 */
40
'use client';
41

42
import { Box, Text, Flex } from '@chakra-ui/react';
43
import { memo, useMemo, useCallback } from 'react';
44
import type { NoteTreeNode } from '@/types/tree';
45
import type { SaveStatus } from '@/types/notes';
46
import type { EditorRef } from '@/types/editor';
47
import Editor from '@/components/Editor';
48

49
/**
50
 * Props for the MiddlePanel component.
51
 *
52
 * @public
53
 */
54
interface MiddlePanelProps {
55
  /** Currently selected note or null if none selected */
56
  note: NoteTreeNode | null;
57
  /** Current content of the note */
58
  content: string;
59
  /** Current save status of the note */
60
  saveStatus: SaveStatus;
61
  /** Optional line number to highlight in editor */
62
  selectedLine?: number;
63
  /** Callback invoked when content changes */
64
  onContentChange: (content: string) => void;
65
  /** Callback invoked when save is triggered */
66
  onSave: () => void;
67
  /** Optional callback invoked when editor is ready */
68
  onEditorReady?: (editorRef: EditorRef) => void;
69
}
70

71
/**
72
 * Renders the middle panel with note editor and status bar.
73
 *
74
 * @param props - Component props
75
 * @param props.note - Currently selected note
76
 * @param props.content - Note content string
77
 * @param props.saveStatus - Current save status
78
 * @param props.selectedLine - Line number to highlight
79
 * @param props.onContentChange - Handler for content changes
80
 * @param props.onSave - Handler for save action
81
 * @param props.onEditorReady - Handler for editor initialization
82
 * @returns Memoized middle panel component
83
 *
84
 * @remarks
85
 * Displays empty state when no note is selected.
86
 * Save status bar shows note name and color-coded status.
87
 *
88
 * @public
89
 */
90
const MiddlePanel = memo(function MiddlePanel({
36✔
91
  note,
92
  content,
93
  saveStatus,
94
  selectedLine,
95
  onContentChange,
96
  onSave,
97
  onEditorReady
98
}: MiddlePanelProps) {
99
  const saveStatusText = useMemo(() => {
920✔
100
    switch (saveStatus) {
98!
101
      case 'saving':
102
        return 'Saving...';
2✔
103
      case 'saved':
104
        return 'Saved';
2✔
105
      case 'error':
NEW
106
        return 'Save failed';
×
107
      default:
108
        return '';
94✔
109
    }
110
  }, [saveStatus]);
111

112
  const saveStatusColor = useMemo(() => {
920✔
113
    switch (saveStatus) {
98!
114
      case 'saving':
115
        return 'blue.500';
2✔
116
      case 'saved':
117
        return 'green.500';
2✔
118
      case 'error':
NEW
119
        return 'red.500';
×
120
      default:
121
        return 'gray.500';
94✔
122
    }
123
  }, [saveStatus]);
124

125
  const handleContentChange = useCallback(
920✔
126
    (value: string | undefined) => {
127
      onContentChange(value || '');
323✔
128
    },
129
    [onContentChange]
130
  );
131

NEW
132
  return (
×
133
    <Box as="main" h="100%" display="flex" flexDirection="column">
134
      {/* Save status bar */}
135
      <Flex
136
        justify="space-between"
137
        align="center"
138
        p={4}
139
        borderBottom="1px solid"
140
        borderColor="border"
141
      >
142
        <Text fontSize="lg" fontWeight="semibold">
143
          {note?.name || 'Select a note'}
1,030✔
144
        </Text>
145
        {saveStatus !== 'idle' && (
920!
146
          <Text fontSize="sm" color={saveStatusColor}>
147
            {saveStatusText}
148
          </Text>
149
        )}
150
      </Flex>
151

152
      {/* Editor area */}
153
      <Box flex={1} overflow="hidden" position="relative" minH={0}>
154
        {note ? (
×
155
          <Editor
810✔
156
            value={content}
157
            onChange={handleContentChange}
158
            selectedLine={selectedLine}
159
            onEditorReady={onEditorReady}
160
            onSave={onSave}
161
            placeholder="Start writing your note..."
162
          />
163
        ) : (
164
          <Flex h="100%" align="center" justify="center">
165
            <Text color="fg.muted">Select or create a note to start editing</Text>
166
          </Flex>
167
        )}
168
      </Box>
169
    </Box>
170
  );
171
});
172

173
export default MiddlePanel;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc