Skip to content

Commit 8d85960

Browse files
committed
feat: implement Phase 3 visualization enhancements with improved colors, stats, and UX
1 parent a4be1f2 commit 8d85960

3 files changed

Lines changed: 225 additions & 89 deletions

File tree

‎src/renderer/components/SettingsPanel.tsx‎

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Moon, Sun, X } from 'lucide-react'
1+
import { Moon, Sun, X, Check, AlertCircle } from 'lucide-react'
2+
import { useState } from 'react'
23

34
interface SettingsPanelProps {
45
darkMode: boolean
@@ -11,9 +12,30 @@ export function SettingsPanel({
1112
onDarkModeChange,
1213
onClose,
1314
}: SettingsPanelProps) {
15+
const [checkingUpdates, setCheckingUpdates] = useState(false)
16+
const [updateStatus, setUpdateStatus] = useState<'idle' | 'checking' | 'available' | 'uptodate'>('idle')
17+
18+
async function handleCheckUpdates() {
19+
setCheckingUpdates(true)
20+
setUpdateStatus('checking')
21+
22+
try {
23+
const result = await window.electron.checkUpdates()
24+
setUpdateStatus(result ? 'available' : 'uptodate')
25+
26+
setTimeout(() => {
27+
setCheckingUpdates(false)
28+
setTimeout(() => setUpdateStatus('idle'), 3000)
29+
}, 1500)
30+
} catch (err) {
31+
setCheckingUpdates(false)
32+
setUpdateStatus('idle')
33+
}
34+
}
35+
1436
return (
15-
<div className="w-80 bg-slate-100 dark:bg-slate-900 border-l border-slate-300 dark:border-slate-700 flex flex-col">
16-
<div className="p-6 border-b border-slate-300 dark:border-slate-700 flex items-center justify-between">
37+
<div className="w-96 bg-slate-50 dark:bg-slate-900 border-l border-slate-200 dark:border-slate-700 flex flex-col">
38+
<div className="p-6 border-b border-slate-200 dark:border-slate-700 flex items-center justify-between">
1739
<h2 className="text-xl font-bold text-slate-900 dark:text-white">
1840
Settings
1941
</h2>
@@ -26,9 +48,9 @@ export function SettingsPanel({
2648
</div>
2749

2850
<div className="flex-1 overflow-y-auto p-6">
29-
<div className="space-y-6">
51+
<div className="space-y-8">
3052
<div>
31-
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3">
53+
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 uppercase tracking-wide mb-4">
3254
Appearance
3355
</h3>
3456
<button
@@ -37,41 +59,90 @@ export function SettingsPanel({
3759
>
3860
{darkMode ? (
3961
<>
40-
<Moon size={20} />
41-
<span>Dark Mode: ON</span>
62+
<Moon size={20} className="text-blue-600" />
63+
<span className="font-medium">Dark Mode</span>
64+
<span className="ml-auto text-xs font-semibold text-green-600 dark:text-green-400">ON</span>
4265
</>
4366
) : (
4467
<>
45-
<Sun size={20} />
46-
<span>Light Mode: ON</span>
68+
<Sun size={20} className="text-amber-600" />
69+
<span className="font-medium">Light Mode</span>
70+
<span className="ml-auto text-xs font-semibold text-green-600 dark:text-green-400">ON</span>
4771
</>
4872
)}
4973
</button>
5074
</div>
5175

5276
<div>
53-
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3">
77+
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 uppercase tracking-wide mb-4">
5478
Updates
5579
</h3>
56-
<button className="w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition">
57-
Check for Updates
80+
<button
81+
onClick={handleCheckUpdates}
82+
disabled={checkingUpdates}
83+
className="w-full px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 transition font-medium"
84+
>
85+
{checkingUpdates ? 'Checking...' : 'Check for Updates'}
5886
</button>
59-
<p className="text-xs text-slate-500 dark:text-slate-400 mt-2">
60-
Last checked: never
87+
88+
{updateStatus === 'checking' && (
89+
<div className="mt-3 p-3 bg-blue-50 dark:bg-blue-900 rounded-lg flex items-center gap-2">
90+
<div className="animate-spin h-4 w-4 border-2 border-blue-600 border-t-transparent rounded-full" />
91+
<p className="text-sm text-blue-900 dark:text-blue-100">Checking for updates...</p>
92+
</div>
93+
)}
94+
95+
{updateStatus === 'available' && (
96+
<div className="mt-3 p-3 bg-amber-50 dark:bg-amber-900 rounded-lg flex items-center gap-2">
97+
<AlertCircle size={16} className="text-amber-600 dark:text-amber-400 flex-shrink-0" />
98+
<p className="text-sm text-amber-900 dark:text-amber-100">Update available</p>
99+
</div>
100+
)}
101+
102+
{updateStatus === 'uptodate' && (
103+
<div className="mt-3 p-3 bg-green-50 dark:bg-green-900 rounded-lg flex items-center gap-2">
104+
<Check size={16} className="text-green-600 dark:text-green-400 flex-shrink-0" />
105+
<p className="text-sm text-green-900 dark:text-green-100">You are up to date</p>
106+
</div>
107+
)}
108+
109+
<p className="text-xs text-slate-500 dark:text-slate-500 mt-3">
110+
Automatically checks on startup. Updates install on next launch.
61111
</p>
62112
</div>
63113

64114
<div>
65-
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3">
115+
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 uppercase tracking-wide mb-4">
66116
About
67117
</h3>
68-
<div className="p-4 rounded-lg bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700">
69-
<p className="text-sm text-slate-600 dark:text-slate-400">
70-
<strong>DiskOH</strong> v0.1.0
71-
</p>
72-
<p className="text-xs text-slate-500 dark:text-slate-500 mt-2">
73-
Modern disk space analyzer for Windows
74-
</p>
118+
<div className="space-y-3">
119+
<div className="p-4 rounded-lg bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700">
120+
<div className="flex items-center justify-between mb-2">
121+
<p className="font-semibold text-slate-900 dark:text-white">DiskOH</p>
122+
<p className="text-xs font-mono bg-slate-100 dark:bg-slate-700 px-2 py-1 rounded text-slate-700 dark:text-slate-300">
123+
v0.1.0
124+
</p>
125+
</div>
126+
<p className="text-sm text-slate-600 dark:text-slate-400">
127+
Modern disk space analyzer for Windows
128+
</p>
129+
</div>
130+
131+
<div className="p-4 rounded-lg bg-slate-100 dark:bg-slate-800 border border-slate-200 dark:border-slate-700">
132+
<p className="text-xs font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wide mb-2">
133+
Built with
134+
</p>
135+
<div className="flex flex-wrap gap-2">
136+
{['Electron', 'React', 'TypeScript', 'Tailwind'].map((tech) => (
137+
<span
138+
key={tech}
139+
className="text-xs px-2 py-1 bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded"
140+
>
141+
{tech}
142+
</span>
143+
))}
144+
</div>
145+
</div>
75146
</div>
76147
</div>
77148
</div>

‎src/renderer/components/Sidebar.tsx‎

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,79 @@ export function Sidebar({
1717
onSettingsClick,
1818
}: SidebarProps) {
1919
return (
20-
<div className="w-64 bg-slate-100 dark:bg-slate-900 border-r border-slate-300 dark:border-slate-700 flex flex-col">
21-
<div className="p-6 border-b border-slate-300 dark:border-slate-700">
22-
<h1 className="text-2xl font-bold text-slate-900 dark:text-white">
20+
<div className="w-72 bg-slate-50 dark:bg-slate-900 border-r border-slate-200 dark:border-slate-700 flex flex-col">
21+
<div className="p-6 border-b border-slate-200 dark:border-slate-700">
22+
<h1 className="text-3xl font-bold text-slate-900 dark:text-white">
2323
DiskOH
2424
</h1>
25-
<p className="text-sm text-slate-600 dark:text-slate-400">
25+
<p className="text-sm text-slate-600 dark:text-slate-400 mt-1">
2626
Disk Space Analyzer
2727
</p>
2828
</div>
2929

3030
<div className="flex-1 overflow-y-auto p-4">
31-
<h2 className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-4">
32-
Drives
31+
<h2 className="text-xs font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wider mb-3 px-2">
32+
Your Drives
3333
</h2>
3434

3535
<div className="space-y-2">
36-
{drives.map((drive) => (
37-
<button
38-
key={drive.letter}
39-
onClick={() => onSelectDrive(drive.letter)}
40-
className={`w-full text-left p-3 rounded-lg transition flex items-center gap-2 ${
41-
selectedDrive === drive.letter
42-
? 'bg-blue-600 text-white'
43-
: 'bg-white dark:bg-slate-800 text-slate-900 dark:text-white hover:bg-slate-200 dark:hover:bg-slate-700'
44-
} ${scanning ? 'opacity-50 cursor-not-allowed' : ''}`}
45-
disabled={scanning}
46-
>
47-
<HardDrive size={18} />
48-
<div className="flex-1">
49-
<div className="font-medium">{drive.name}</div>
50-
<div className="text-xs opacity-75">
51-
{formatBytes(drive.free)} free
36+
{drives.map((drive) => {
37+
const usagePercent = ((drive.used / drive.total) * 100).toFixed(0)
38+
const isSelected = selectedDrive === drive.letter
39+
40+
return (
41+
<button
42+
key={drive.letter}
43+
onClick={() => onSelectDrive(drive.letter)}
44+
disabled={scanning}
45+
className={`w-full text-left p-4 rounded-lg transition group ${
46+
isSelected
47+
? 'bg-blue-600 text-white shadow-md'
48+
: 'bg-white dark:bg-slate-800 text-slate-900 dark:text-white hover:bg-slate-100 dark:hover:bg-slate-700'
49+
} ${scanning ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`}
50+
>
51+
<div className="flex items-center gap-3 mb-2">
52+
<HardDrive
53+
size={20}
54+
className={isSelected ? 'text-white' : 'text-slate-600 dark:text-slate-400'}
55+
/>
56+
<div className="flex-1">
57+
<div className="font-semibold">{drive.name}</div>
58+
<div className={`text-xs ${isSelected ? 'text-blue-100' : 'text-slate-500 dark:text-slate-500'}`}>
59+
{usagePercent}% used
60+
</div>
61+
</div>
62+
</div>
63+
64+
<div className="mb-2">
65+
<div className="h-1.5 bg-slate-300 dark:bg-slate-600 rounded-full overflow-hidden">
66+
<div
67+
className={`h-full transition-all ${
68+
isSelected ? 'bg-white' : 'bg-blue-600 dark:bg-blue-500'
69+
}`}
70+
style={{ width: `${Math.min(parseInt(usagePercent), 100)}%` }}
71+
/>
72+
</div>
73+
</div>
74+
75+
<div className={`flex justify-between text-xs ${isSelected ? 'text-blue-100' : 'text-slate-600 dark:text-slate-400'}`}>
76+
<span>{formatBytes(drive.used)} used</span>
77+
<span>{formatBytes(drive.free)} free</span>
78+
</div>
79+
80+
<div className={`text-xs mt-1 font-medium ${isSelected ? 'text-blue-100' : 'text-slate-500 dark:text-slate-500'}`}>
81+
{formatBytes(drive.total)} total
5282
</div>
53-
</div>
54-
</button>
55-
))}
83+
</button>
84+
)
85+
})}
5686
</div>
5787
</div>
5888

59-
<div className="p-4 border-t border-slate-300 dark:border-slate-700">
89+
<div className="p-4 border-t border-slate-200 dark:border-slate-700">
6090
<button
6191
onClick={onSettingsClick}
62-
className="w-full flex items-center justify-center gap-2 p-2 rounded-lg bg-white dark:bg-slate-800 text-slate-900 dark:text-white hover:bg-slate-200 dark:hover:bg-slate-700 transition"
92+
className="w-full flex items-center justify-center gap-2 p-3 rounded-lg bg-slate-200 dark:bg-slate-800 text-slate-900 dark:text-white hover:bg-slate-300 dark:hover:bg-slate-700 transition font-medium"
6393
>
6494
<Settings size={18} />
6595
Settings

0 commit comments

Comments
 (0)