Skip to content

Commit bca97a5

Browse files
committed
Update GitPanel
1 parent 1bdc75e commit bca97a5

File tree

1 file changed

+172
-165
lines changed

1 file changed

+172
-165
lines changed

src/components/GitPanel.jsx

Lines changed: 172 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -506,189 +506,196 @@ function GitPanel({ selectedProject, isMobile }) {
506506
</button>
507507
</div>
508508

509-
{/* Tab Navigation */}
510-
<div className="flex border-b border-gray-200 dark:border-gray-700">
511-
<button
512-
onClick={() => setActiveView('changes')}
513-
className={`flex-1 px-4 py-2 text-sm font-medium transition-colors ${
514-
activeView === 'changes'
515-
? 'text-blue-600 dark:text-blue-400 border-b-2 border-blue-600 dark:border-blue-400'
516-
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
517-
}`}
518-
>
519-
<div className="flex items-center justify-center gap-2">
520-
<FileText className="w-4 h-4" />
521-
<span>Changes</span>
509+
{/* Git Repository Not Found Message */}
510+
{gitStatus?.error ? (
511+
<div className="flex-1 flex flex-col items-center justify-center text-gray-500 dark:text-gray-400 px-6 py-12">
512+
<GitBranch className="w-20 h-20 mb-6 opacity-30" />
513+
<h3 className="text-xl font-medium mb-3 text-center">{gitStatus.error}</h3>
514+
{gitStatus.details && (
515+
<p className="text-sm text-center leading-relaxed mb-6 max-w-md">{gitStatus.details}</p>
516+
)}
517+
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800 max-w-md">
518+
<p className="text-sm text-blue-700 dark:text-blue-300 text-center">
519+
<strong>Tip:</strong> Run <code className="bg-blue-100 dark:bg-blue-900 px-2 py-1 rounded font-mono text-xs">git init</code> in your project directory to initialize git source control.
520+
</p>
522521
</div>
523-
</button>
524-
<button
525-
onClick={() => setActiveView('history')}
526-
className={`flex-1 px-4 py-2 text-sm font-medium transition-colors ${
527-
activeView === 'history'
528-
? 'text-blue-600 dark:text-blue-400 border-b-2 border-blue-600 dark:border-blue-400'
529-
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
530-
}`}
531-
>
532-
<div className="flex items-center justify-center gap-2">
533-
<History className="w-4 h-4" />
534-
<span>History</span>
522+
</div>
523+
) : (
524+
<>
525+
{/* Tab Navigation - Only show when git is available */}
526+
<div className="flex border-b border-gray-200 dark:border-gray-700">
527+
<button
528+
onClick={() => setActiveView('changes')}
529+
className={`flex-1 px-4 py-2 text-sm font-medium transition-colors ${
530+
activeView === 'changes'
531+
? 'text-blue-600 dark:text-blue-400 border-b-2 border-blue-600 dark:border-blue-400'
532+
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
533+
}`}
534+
>
535+
<div className="flex items-center justify-center gap-2">
536+
<FileText className="w-4 h-4" />
537+
<span>Changes</span>
538+
</div>
539+
</button>
540+
<button
541+
onClick={() => setActiveView('history')}
542+
className={`flex-1 px-4 py-2 text-sm font-medium transition-colors ${
543+
activeView === 'history'
544+
? 'text-blue-600 dark:text-blue-400 border-b-2 border-blue-600 dark:border-blue-400'
545+
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
546+
}`}
547+
>
548+
<div className="flex items-center justify-center gap-2">
549+
<History className="w-4 h-4" />
550+
<span>History</span>
551+
</div>
552+
</button>
535553
</div>
536-
</button>
537-
</div>
538554

539-
{/* Changes View */}
540-
{activeView === 'changes' && (
541-
<>
542-
{/* Commit Message Input */}
543-
<div className="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
544-
<div className="relative">
545-
<textarea
546-
ref={textareaRef}
547-
value={commitMessage}
548-
onChange={(e) => setCommitMessage(e.target.value)}
549-
placeholder="Message (Ctrl+Enter to commit)"
550-
className="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 resize-none pr-20"
551-
rows="3"
552-
onKeyDown={(e) => {
553-
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
554-
handleCommit();
555-
}
556-
}}
557-
/>
558-
<div className="absolute right-2 top-2 flex gap-1">
555+
{/* Changes View */}
556+
{activeView === 'changes' && (
557+
<>
558+
{/* Commit Message Input */}
559+
<div className="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
560+
<div className="relative">
561+
<textarea
562+
ref={textareaRef}
563+
value={commitMessage}
564+
onChange={(e) => setCommitMessage(e.target.value)}
565+
placeholder="Message (Ctrl+Enter to commit)"
566+
className="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 resize-none pr-20"
567+
rows="3"
568+
onKeyDown={(e) => {
569+
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
570+
handleCommit();
571+
}
572+
}}
573+
/>
574+
<div className="absolute right-2 top-2 flex gap-1">
575+
<button
576+
onClick={generateCommitMessage}
577+
disabled={selectedFiles.size === 0 || isGeneratingMessage}
578+
className="p-1.5 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 disabled:opacity-50 disabled:cursor-not-allowed"
579+
title="Generate commit message"
580+
>
581+
{isGeneratingMessage ? (
582+
<RefreshCw className="w-4 h-4 animate-spin" />
583+
) : (
584+
<Sparkles className="w-4 h-4" />
585+
)}
586+
</button>
587+
<div style={{ display: 'none' }}>
588+
<MicButton
589+
onTranscript={(transcript) => setCommitMessage(transcript)}
590+
mode="default"
591+
className="p-1.5"
592+
/>
593+
</div>
594+
</div>
595+
</div>
596+
<div className="flex items-center justify-between mt-2">
597+
<span className="text-xs text-gray-500">
598+
{selectedFiles.size} file{selectedFiles.size !== 1 ? 's' : ''} selected
599+
</span>
600+
<button
601+
onClick={handleCommit}
602+
disabled={!commitMessage.trim() || selectedFiles.size === 0 || isCommitting}
603+
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1"
604+
>
605+
<Check className="w-3 h-3" />
606+
<span>{isCommitting ? 'Committing...' : 'Commit'}</span>
607+
</button>
608+
</div>
609+
</div>
610+
</>
611+
)}
612+
613+
{/* File Selection Controls - Only show in changes view and when git is working */}
614+
{activeView === 'changes' && gitStatus && !gitStatus.error && (
615+
<div className="px-4 py-2 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
616+
<span className="text-xs text-gray-600 dark:text-gray-400">
617+
{selectedFiles.size} of {(gitStatus?.modified?.length || 0) + (gitStatus?.added?.length || 0) + (gitStatus?.deleted?.length || 0) + (gitStatus?.untracked?.length || 0)} files selected
618+
</span>
619+
<div className="flex gap-2">
559620
<button
560-
onClick={generateCommitMessage}
561-
disabled={selectedFiles.size === 0 || isGeneratingMessage}
562-
className="p-1.5 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 disabled:opacity-50 disabled:cursor-not-allowed"
563-
title="Generate commit message"
621+
onClick={() => {
622+
const allFiles = new Set([
623+
...(gitStatus?.modified || []),
624+
...(gitStatus?.added || []),
625+
...(gitStatus?.deleted || []),
626+
...(gitStatus?.untracked || [])
627+
]);
628+
setSelectedFiles(allFiles);
629+
}}
630+
className="text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
564631
>
565-
{isGeneratingMessage ? (
566-
<RefreshCw className="w-4 h-4 animate-spin" />
567-
) : (
568-
<Sparkles className="w-4 h-4" />
569-
)}
632+
Select All
633+
</button>
634+
<span className="text-gray-300 dark:text-gray-600">|</span>
635+
<button
636+
onClick={() => setSelectedFiles(new Set())}
637+
className="text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
638+
>
639+
Deselect All
570640
</button>
571-
<div style={{ display: 'none' }}>
572-
<MicButton
573-
onTranscript={(transcript) => setCommitMessage(transcript)}
574-
mode="default"
575-
className="p-1.5"
576-
/>
577-
</div>
578641
</div>
579642
</div>
580-
<div className="flex items-center justify-between mt-2">
581-
<span className="text-xs text-gray-500">
582-
{selectedFiles.size} file{selectedFiles.size !== 1 ? 's' : ''} selected
583-
</span>
643+
)}
644+
645+
{/* Status Legend Toggle */}
646+
{!gitStatus?.error && (
647+
<div className="border-b border-gray-200 dark:border-gray-700">
584648
<button
585-
onClick={handleCommit}
586-
disabled={!commitMessage.trim() || selectedFiles.size === 0 || isCommitting}
587-
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1"
649+
onClick={() => setShowLegend(!showLegend)}
650+
className="w-full px-4 py-2 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-750 text-xs text-gray-600 dark:text-gray-400 flex items-center justify-center gap-1"
588651
>
589-
<Check className="w-3 h-3" />
590-
<span>{isCommitting ? 'Committing...' : 'Commit'}</span>
652+
<Info className="w-3 h-3" />
653+
<span>File Status Guide</span>
654+
{showLegend ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
591655
</button>
656+
657+
{showLegend && (
658+
<div className="px-4 py-3 bg-gray-50 dark:bg-gray-800 text-xs">
659+
<div className={`${isMobile ? 'grid grid-cols-2 gap-3 justify-items-center' : 'flex justify-center gap-6'}`}>
660+
<div className="flex items-center gap-2">
661+
<span className="inline-flex items-center justify-center w-5 h-5 bg-yellow-100 text-yellow-700 dark:bg-yellow-900 dark:text-yellow-300 rounded border border-yellow-200 dark:border-yellow-800 font-bold text-xs">
662+
M
663+
</span>
664+
<span className="text-gray-600 dark:text-gray-400 italic">Modified</span>
665+
</div>
666+
<div className="flex items-center gap-2">
667+
<span className="inline-flex items-center justify-center w-5 h-5 bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300 rounded border border-green-200 dark:border-green-800 font-bold text-xs">
668+
A
669+
</span>
670+
<span className="text-gray-600 dark:text-gray-400 italic">Added</span>
671+
</div>
672+
<div className="flex items-center gap-2">
673+
<span className="inline-flex items-center justify-center w-5 h-5 bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300 rounded border border-red-200 dark:border-red-800 font-bold text-xs">
674+
D
675+
</span>
676+
<span className="text-gray-600 dark:text-gray-400 italic">Deleted</span>
677+
</div>
678+
<div className="flex items-center gap-2">
679+
<span className="inline-flex items-center justify-center w-5 h-5 bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300 rounded border border-gray-300 dark:border-gray-600 font-bold text-xs">
680+
U
681+
</span>
682+
<span className="text-gray-600 dark:text-gray-400 italic">Untracked</span>
683+
</div>
684+
</div>
685+
</div>
686+
)}
592687
</div>
593-
</div>
688+
)}
594689
</>
595690
)}
596691

597-
{/* File Selection Controls - Only show in changes view and when git is working */}
598-
{activeView === 'changes' && gitStatus && !gitStatus.error && (
599-
<div className="px-4 py-2 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
600-
<span className="text-xs text-gray-600 dark:text-gray-400">
601-
{selectedFiles.size} of {(gitStatus?.modified?.length || 0) + (gitStatus?.added?.length || 0) + (gitStatus?.deleted?.length || 0) + (gitStatus?.untracked?.length || 0)} files selected
602-
</span>
603-
<div className="flex gap-2">
604-
<button
605-
onClick={() => {
606-
const allFiles = new Set([
607-
...(gitStatus?.modified || []),
608-
...(gitStatus?.added || []),
609-
...(gitStatus?.deleted || []),
610-
...(gitStatus?.untracked || [])
611-
]);
612-
setSelectedFiles(allFiles);
613-
}}
614-
className="text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
615-
>
616-
Select All
617-
</button>
618-
<span className="text-gray-300 dark:text-gray-600">|</span>
619-
<button
620-
onClick={() => setSelectedFiles(new Set())}
621-
className="text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
622-
>
623-
Deselect All
624-
</button>
625-
</div>
626-
</div>
627-
)}
628-
629-
{/* Status Legend Toggle */}
630-
<div className="border-b border-gray-200 dark:border-gray-700">
631-
<button
632-
onClick={() => setShowLegend(!showLegend)}
633-
className="w-full px-4 py-2 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-750 text-xs text-gray-600 dark:text-gray-400 flex items-center justify-center gap-1"
634-
>
635-
<Info className="w-3 h-3" />
636-
<span>File Status Guide</span>
637-
{showLegend ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
638-
</button>
639-
640-
{showLegend && (
641-
<div className="px-4 py-3 bg-gray-50 dark:bg-gray-800 text-xs">
642-
<div className={`${isMobile ? 'grid grid-cols-2 gap-3 justify-items-center' : 'flex justify-center gap-6'}`}>
643-
<div className="flex items-center gap-2">
644-
<span className="inline-flex items-center justify-center w-5 h-5 bg-yellow-100 text-yellow-700 dark:bg-yellow-900 dark:text-yellow-300 rounded border border-yellow-200 dark:border-yellow-800 font-bold text-xs">
645-
M
646-
</span>
647-
<span className="text-gray-600 dark:text-gray-400 italic">Modified</span>
648-
</div>
649-
<div className="flex items-center gap-2">
650-
<span className="inline-flex items-center justify-center w-5 h-5 bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300 rounded border border-green-200 dark:border-green-800 font-bold text-xs">
651-
A
652-
</span>
653-
<span className="text-gray-600 dark:text-gray-400 italic">Added</span>
654-
</div>
655-
<div className="flex items-center gap-2">
656-
<span className="inline-flex items-center justify-center w-5 h-5 bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300 rounded border border-red-200 dark:border-red-800 font-bold text-xs">
657-
D
658-
</span>
659-
<span className="text-gray-600 dark:text-gray-400 italic">Deleted</span>
660-
</div>
661-
<div className="flex items-center gap-2">
662-
<span className="inline-flex items-center justify-center w-5 h-5 bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300 rounded border border-gray-300 dark:border-gray-600 font-bold text-xs">
663-
U
664-
</span>
665-
<span className="text-gray-600 dark:text-gray-400 italic">Untracked</span>
666-
</div>
667-
</div>
668-
</div>
669-
)}
670-
</div>
671-
672-
{/* File List - Changes View */}
673-
{activeView === 'changes' && (
692+
{/* File List - Changes View - Only show when git is available */}
693+
{activeView === 'changes' && !gitStatus?.error && (
674694
<div className={`flex-1 overflow-y-auto ${isMobile ? 'pb-20' : ''}`}>
675695
{isLoading ? (
676696
<div className="flex items-center justify-center h-32">
677697
<RefreshCw className="w-6 h-6 animate-spin text-gray-400" />
678698
</div>
679-
) : gitStatus?.error ? (
680-
<div className="flex flex-col items-center justify-center h-48 text-gray-500 dark:text-gray-400 px-6">
681-
<GitBranch className="w-16 h-16 mb-4 opacity-30" />
682-
<p className="text-lg font-medium mb-2 text-center">{gitStatus.error}</p>
683-
{gitStatus.details && (
684-
<p className="text-sm text-center leading-relaxed">{gitStatus.details}</p>
685-
)}
686-
<div className="mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800">
687-
<p className="text-xs text-blue-700 dark:text-blue-300 text-center">
688-
<strong>Tip:</strong> Run <code className="bg-blue-100 dark:bg-blue-900 px-1 rounded">git init</code> in your project directory to initialize git source control.
689-
</p>
690-
</div>
691-
</div>
692699
) : !gitStatus || (!gitStatus.modified?.length && !gitStatus.added?.length && !gitStatus.deleted?.length && !gitStatus.untracked?.length) ? (
693700
<div className="flex flex-col items-center justify-center h-32 text-gray-500 dark:text-gray-400">
694701
<GitCommit className="w-12 h-12 mb-2 opacity-50" />
@@ -705,8 +712,8 @@ function GitPanel({ selectedProject, isMobile }) {
705712
</div>
706713
)}
707714

708-
{/* History View */}
709-
{activeView === 'history' && (
715+
{/* History View - Only show when git is available */}
716+
{activeView === 'history' && !gitStatus?.error && (
710717
<div className={`flex-1 overflow-y-auto ${isMobile ? 'pb-20' : ''}`}>
711718
{isLoading ? (
712719
<div className="flex items-center justify-center h-32">

0 commit comments

Comments
 (0)