Skip to content

Commit 9bdda08

Browse files
author
Marvin Zhang
committed
refactor: Refactor code structure for improved readability and maintainability
1 parent 526aa22 commit 9bdda08

File tree

10 files changed

+1789
-551
lines changed

10 files changed

+1789
-551
lines changed

packages/web/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"react-dom": "^18.2.0",
3939
"@types/react": "^18.2.48",
4040
"@types/react-dom": "^18.2.18",
41+
"antd": "^5.12.8",
42+
"@ant-design/icons": "^5.2.6",
4143
"tailwindcss": "^3.4.1",
4244
"autoprefixer": "^10.4.17",
4345
"postcss": "^8.4.33",

packages/web/src/client/src/App.tsx

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { useState, useEffect } from 'react';
2+
import { ConfigProvider, Layout, Alert, theme } from 'antd';
23
import { DevlogEntry, DevlogStats } from '@devlog/types';
34
import { Dashboard } from './components/Dashboard';
45
import { DevlogList } from './components/DevlogList';
@@ -9,6 +10,8 @@ import { Header } from './components/Header';
910
import { useDevlogs } from './hooks/useDevlogs';
1011
import { useWebSocket } from './hooks/useWebSocket';
1112

13+
const { Content } = Layout;
14+
1215
type View = 'dashboard' | 'list' | 'create' | 'details';
1316

1417
function App() {
@@ -55,7 +58,7 @@ function App() {
5558
await updateDevlog(data);
5659
if (selectedDevlog) {
5760
// Refresh the selected devlog
58-
const updated = devlogs.find(d => d.id === selectedDevlog.id);
61+
const updated = devlogs.find((d: DevlogEntry) => d.id === selectedDevlog.id);
5962
setSelectedDevlog(updated || null);
6063
}
6164
} catch (error) {
@@ -82,15 +85,15 @@ function App() {
8285
<Dashboard
8386
stats={stats}
8487
recentDevlogs={devlogs.slice(0, 5)}
85-
onViewDevlog={(devlog) => handleViewChange('details', devlog)}
88+
onViewDevlog={(devlog: DevlogEntry) => handleViewChange('details', devlog)}
8689
/>
8790
);
8891
case 'list':
8992
return (
9093
<DevlogList
9194
devlogs={devlogs}
9295
loading={loading}
93-
onViewDevlog={(devlog) => handleViewChange('details', devlog)}
96+
onViewDevlog={(devlog: DevlogEntry) => handleViewChange('details', devlog)}
9497
onDeleteDevlog={handleDevlogDelete}
9598
/>
9699
);
@@ -118,27 +121,41 @@ function App() {
118121
};
119122

120123
return (
121-
<div className="flex h-screen bg-gray-50">
122-
<Sidebar
123-
currentView={currentView}
124-
onViewChange={handleViewChange}
125-
stats={stats}
126-
/>
127-
<div className="flex-1 flex flex-col">
128-
<Header
129-
connected={connected}
130-
onRefresh={refetch}
124+
<ConfigProvider
125+
theme={{
126+
algorithm: theme.defaultAlgorithm,
127+
token: {
128+
colorPrimary: '#3b82f6',
129+
borderRadius: 8,
130+
},
131+
}}
132+
>
133+
<Layout style={{ height: '100vh' }}>
134+
<Sidebar
135+
currentView={currentView}
136+
onViewChange={handleViewChange}
137+
stats={stats}
131138
/>
132-
<main className="flex-1 overflow-auto p-6">
133-
{error && (
134-
<div className="mb-4 p-4 bg-red-50 border border-red-200 rounded-md">
135-
<p className="text-red-800">{error}</p>
136-
</div>
137-
)}
138-
{renderCurrentView()}
139-
</main>
140-
</div>
141-
</div>
139+
<Layout>
140+
<Header
141+
connected={connected}
142+
onRefresh={refetch}
143+
/>
144+
<Content style={{ margin: '24px', overflow: 'auto' }}>
145+
{error && (
146+
<Alert
147+
message="Error"
148+
description={error}
149+
type="error"
150+
showIcon
151+
style={{ marginBottom: 16 }}
152+
/>
153+
)}
154+
{renderCurrentView()}
155+
</Content>
156+
</Layout>
157+
</Layout>
158+
</ConfigProvider>
142159
);
143160
}
144161

Lines changed: 153 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
import React from 'react';
2+
import { Typography, Card, Row, Col, List, Tag, Avatar, Statistic, Empty } from 'antd';
3+
import {
4+
FileTextOutlined,
5+
SyncOutlined,
6+
CheckCircleOutlined,
7+
StopOutlined,
8+
ClockCircleOutlined,
9+
ExclamationCircleOutlined,
10+
WarningOutlined,
11+
MinusCircleOutlined
12+
} from '@ant-design/icons';
13+
14+
const { Title, Paragraph, Text } = Typography;
215

316
interface DevlogEntry {
417
id: string;
@@ -27,123 +40,165 @@ interface DashboardProps {
2740
export function Dashboard({ stats, recentDevlogs, onViewDevlog }: DashboardProps) {
2841
const getStatusColor = (status: string) => {
2942
switch (status) {
30-
case 'done': return 'bg-green-100 text-green-800';
31-
case 'in-progress': return 'bg-blue-100 text-blue-800';
32-
case 'blocked': return 'bg-red-100 text-red-800';
33-
case 'todo': return 'bg-gray-100 text-gray-800';
34-
default: return 'bg-gray-100 text-gray-800';
43+
case 'done': return 'success';
44+
case 'in-progress': return 'processing';
45+
case 'blocked': return 'error';
46+
case 'todo': return 'default';
47+
default: return 'default';
48+
}
49+
};
50+
51+
const getStatusIcon = (status: string) => {
52+
switch (status) {
53+
case 'done': return <CheckCircleOutlined />;
54+
case 'in-progress': return <SyncOutlined spin />;
55+
case 'blocked': return <StopOutlined />;
56+
case 'todo': return <ClockCircleOutlined />;
57+
default: return <MinusCircleOutlined />;
3558
}
3659
};
3760

3861
const getPriorityColor = (priority: string) => {
3962
switch (priority) {
40-
case 'critical': return 'bg-red-100 text-red-800';
41-
case 'high': return 'bg-orange-100 text-orange-800';
42-
case 'medium': return 'bg-yellow-100 text-yellow-800';
43-
case 'low': return 'bg-green-100 text-green-800';
44-
default: return 'bg-gray-100 text-gray-800';
63+
case 'critical': return 'red';
64+
case 'high': return 'orange';
65+
case 'medium': return 'gold';
66+
case 'low': return 'green';
67+
default: return 'default';
68+
}
69+
};
70+
71+
const getPriorityIcon = (priority: string) => {
72+
switch (priority) {
73+
case 'critical': return <ExclamationCircleOutlined />;
74+
case 'high': return <WarningOutlined />;
75+
case 'medium': return <MinusCircleOutlined />;
76+
case 'low': return <CheckCircleOutlined />;
77+
default: return <MinusCircleOutlined />;
4578
}
4679
};
4780

4881
return (
49-
<div className="space-y-6">
50-
<div>
51-
<h1 className="text-2xl font-bold text-gray-900">Dashboard</h1>
52-
<p className="text-gray-600">Overview of your development progress</p>
82+
<div>
83+
<div style={{ marginBottom: '24px' }}>
84+
<Title level={2}>Dashboard</Title>
85+
<Paragraph type="secondary">
86+
Overview of your development progress
87+
</Paragraph>
5388
</div>
5489

5590
{/* Stats Cards */}
5691
{stats && (
57-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
58-
<div className="bg-white rounded-lg shadow p-6">
59-
<div className="flex items-center">
60-
<div className="p-2 bg-blue-100 rounded-lg">
61-
<span className="text-blue-600 text-xl">📝</span>
62-
</div>
63-
<div className="ml-4">
64-
<p className="text-sm font-medium text-gray-600">Total Devlogs</p>
65-
<p className="text-2xl font-bold text-gray-900">{stats.total}</p>
66-
</div>
67-
</div>
68-
</div>
69-
70-
<div className="bg-white rounded-lg shadow p-6">
71-
<div className="flex items-center">
72-
<div className="p-2 bg-yellow-100 rounded-lg">
73-
<span className="text-yellow-600 text-xl">🏃</span>
74-
</div>
75-
<div className="ml-4">
76-
<p className="text-sm font-medium text-gray-600">In Progress</p>
77-
<p className="text-2xl font-bold text-gray-900">{stats.byStatus['in-progress'] || 0}</p>
78-
</div>
79-
</div>
80-
</div>
81-
82-
<div className="bg-white rounded-lg shadow p-6">
83-
<div className="flex items-center">
84-
<div className="p-2 bg-green-100 rounded-lg">
85-
<span className="text-green-600 text-xl"></span>
86-
</div>
87-
<div className="ml-4">
88-
<p className="text-sm font-medium text-gray-600">Completed</p>
89-
<p className="text-2xl font-bold text-gray-900">{stats.byStatus['done'] || 0}</p>
90-
</div>
91-
</div>
92-
</div>
93-
94-
<div className="bg-white rounded-lg shadow p-6">
95-
<div className="flex items-center">
96-
<div className="p-2 bg-red-100 rounded-lg">
97-
<span className="text-red-600 text-xl">🚫</span>
98-
</div>
99-
<div className="ml-4">
100-
<p className="text-sm font-medium text-gray-600">Blocked</p>
101-
<p className="text-2xl font-bold text-gray-900">{stats.byStatus['blocked'] || 0}</p>
102-
</div>
103-
</div>
104-
</div>
105-
</div>
92+
<Row gutter={[16, 16]} style={{ marginBottom: '32px' }}>
93+
<Col xs={24} sm={12} lg={6}>
94+
<Card>
95+
<Statistic
96+
title="Total Devlogs"
97+
value={stats.total}
98+
prefix={<FileTextOutlined style={{ color: '#1890ff' }} />}
99+
valueStyle={{ color: '#1890ff' }}
100+
/>
101+
</Card>
102+
</Col>
103+
<Col xs={24} sm={12} lg={6}>
104+
<Card>
105+
<Statistic
106+
title="In Progress"
107+
value={stats.byStatus['in-progress'] || 0}
108+
prefix={<SyncOutlined spin style={{ color: '#faad14' }} />}
109+
valueStyle={{ color: '#faad14' }}
110+
/>
111+
</Card>
112+
</Col>
113+
<Col xs={24} sm={12} lg={6}>
114+
<Card>
115+
<Statistic
116+
title="Completed"
117+
value={stats.byStatus['done'] || 0}
118+
prefix={<CheckCircleOutlined style={{ color: '#52c41a' }} />}
119+
valueStyle={{ color: '#52c41a' }}
120+
/>
121+
</Card>
122+
</Col>
123+
<Col xs={24} sm={12} lg={6}>
124+
<Card>
125+
<Statistic
126+
title="Blocked"
127+
value={stats.byStatus['blocked'] || 0}
128+
prefix={<StopOutlined style={{ color: '#ff4d4f' }} />}
129+
valueStyle={{ color: '#ff4d4f' }}
130+
/>
131+
</Card>
132+
</Col>
133+
</Row>
106134
)}
107135

108136
{/* Recent Devlogs */}
109-
<div className="bg-white rounded-lg shadow">
110-
<div className="px-6 py-4 border-b border-gray-200">
111-
<h2 className="text-lg font-medium text-gray-900">Recent Devlogs</h2>
112-
</div>
113-
<div className="divide-y divide-gray-200">
114-
{recentDevlogs.length === 0 ? (
115-
<div className="px-6 py-8 text-center">
116-
<p className="text-gray-500">No devlogs found</p>
117-
</div>
118-
) : (
119-
recentDevlogs.map((devlog) => (
120-
<div
121-
key={devlog.id}
122-
className="px-6 py-4 hover:bg-gray-50 cursor-pointer"
137+
<Card
138+
title="Recent Devlogs"
139+
bodyStyle={{ padding: 0 }}
140+
>
141+
{recentDevlogs.length === 0 ? (
142+
<Empty
143+
image={Empty.PRESENTED_IMAGE_SIMPLE}
144+
description="No devlogs found"
145+
style={{ padding: '40px' }}
146+
/>
147+
) : (
148+
<List
149+
itemLayout="horizontal"
150+
dataSource={recentDevlogs}
151+
renderItem={(devlog) => (
152+
<List.Item
153+
style={{ cursor: 'pointer', padding: '16px 24px' }}
123154
onClick={() => onViewDevlog(devlog)}
155+
actions={[
156+
<Text type="secondary" key="date">
157+
{new Date(devlog.updatedAt).toLocaleDateString()}
158+
</Text>
159+
]}
124160
>
125-
<div className="flex items-center justify-between">
126-
<div className="flex-1">
127-
<h3 className="text-sm font-medium text-gray-900">{devlog.title}</h3>
128-
<p className="text-sm text-gray-500 mt-1">{devlog.description}</p>
129-
<div className="flex items-center space-x-4 mt-2">
130-
<span className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getStatusColor(devlog.status)}`}>
131-
{devlog.status}
132-
</span>
133-
<span className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getPriorityColor(devlog.priority)}`}>
134-
{devlog.priority}
135-
</span>
136-
<span className="text-xs text-gray-500">
137-
{new Date(devlog.updatedAt).toLocaleDateString()}
138-
</span>
161+
<List.Item.Meta
162+
avatar={
163+
<Avatar
164+
icon={getStatusIcon(devlog.status)}
165+
style={{
166+
backgroundColor: getStatusColor(devlog.status) === 'success' ? '#52c41a' :
167+
getStatusColor(devlog.status) === 'processing' ? '#1890ff' :
168+
getStatusColor(devlog.status) === 'error' ? '#ff4d4f' : '#d9d9d9'
169+
}}
170+
/>
171+
}
172+
title={
173+
<div>
174+
<Text strong>{devlog.title}</Text>
175+
<div style={{ marginTop: '4px' }}>
176+
<Tag
177+
color={getStatusColor(devlog.status)}
178+
icon={getStatusIcon(devlog.status)}
179+
>
180+
{devlog.status}
181+
</Tag>
182+
<Tag
183+
color={getPriorityColor(devlog.priority)}
184+
icon={getPriorityIcon(devlog.priority)}
185+
>
186+
{devlog.priority}
187+
</Tag>
188+
</div>
139189
</div>
140-
</div>
141-
</div>
142-
</div>
143-
))
144-
)}
145-
</div>
146-
</div>
190+
}
191+
description={
192+
<Text type="secondary" ellipsis>
193+
{devlog.description}
194+
</Text>
195+
}
196+
/>
197+
</List.Item>
198+
)}
199+
/>
200+
)}
201+
</Card>
147202
</div>
148203
);
149204
}

0 commit comments

Comments
 (0)