-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.tsx
More file actions
196 lines (176 loc) · 7.65 KB
/
Copy pathApp.tsx
File metadata and controls
196 lines (176 loc) · 7.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import React, { useState } from 'react';
import { SalesTask, Role, User, AssessmentResult, TaskStatus } from './types';
import { INITIAL_TASKS, MOCK_USERS } from './constants';
import { TaskList } from './components/TaskList';
import { CreateTaskModal } from './components/CreateTaskModal';
import { ReviewTaskModal } from './components/ReviewTaskModal';
import { ViewTaskModal } from './components/ViewTaskModal';
import { LayoutDashboard, LogOut, UserCircle, FileText, ClipboardCheck } from 'lucide-react';
const App: React.FC = () => {
// State for mock data
const [tasks, setTasks] = useState<SalesTask[]>(INITIAL_TASKS);
// State for user simulation (switching roles)
const [currentUser, setCurrentUser] = useState<User>(MOCK_USERS[0]); // Default to Sales
// State for Navigation (Simplified as per new requirement)
const [currentView, setCurrentView] = useState<'dashboard' | 'tasks'>('tasks');
// Modal States
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [viewTask, setViewTask] = useState<SalesTask | null>(null);
const [reviewTask, setReviewTask] = useState<SalesTask | null>(null);
// Handlers
const handleCreateTask = (newTaskData: Omit<SalesTask, 'id'>) => {
const newTask: SalesTask = {
...newTaskData,
id: `t-${Date.now()}`,
};
setTasks([newTask, ...tasks]);
};
const handleSubmitReview = (taskId: string, assessment: AssessmentResult) => {
setTasks(prevTasks => prevTasks.map(t => {
if (t.id === taskId) {
return {
...t,
status: TaskStatus.REVIEWED,
assessment: assessment
};
}
return t;
}));
};
const handleRoleSwitch = (e: React.ChangeEvent<HTMLSelectElement>) => {
const user = MOCK_USERS.find(u => u.id === e.target.value);
if (user) setCurrentUser(user);
};
return (
<div className="min-h-screen bg-gray-50 flex">
{/* Sidebar Mock */}
<aside className="w-64 bg-slate-800 text-white hidden md:flex flex-col">
<div className="p-6 text-xl font-bold tracking-wider border-b border-slate-700">
普什模具管理系统
</div>
<nav className="flex-1 p-4 space-y-2">
{/* Home */}
<div
onClick={() => setCurrentView('dashboard')}
className={`flex items-center space-x-3 px-4 py-3 rounded cursor-pointer transition-colors ${
currentView === 'dashboard' ? 'bg-blue-600 text-white shadow-md' : 'text-slate-300 hover:bg-slate-700'
}`}
>
<LayoutDashboard size={20} />
<span>首页</span>
</div>
{/* Sales Task Assessment Tracking - Visible for BOTH Sales and Reviewer */}
<div
onClick={() => setCurrentView('tasks')}
className={`flex items-center space-x-3 px-4 py-3 rounded cursor-pointer transition-colors ${
currentView === 'tasks' ? 'bg-blue-600 text-white shadow-md' : 'text-slate-300 hover:bg-slate-700'
}`}
>
{/* Icon can change or stay generic */}
<FileText size={20} />
<span>销售任务评估跟踪</span>
</div>
</nav>
<div className="p-4 border-t border-slate-700">
<button className="flex items-center space-x-2 text-slate-400 hover:text-white transition-colors w-full">
<LogOut size={18} />
<span>退出系统</span>
</button>
</div>
</aside>
{/* Main Content */}
<main className="flex-1 flex flex-col min-w-0">
{/* Header */}
<header className="bg-white shadow-sm h-16 flex items-center justify-between px-8 z-10">
<h1 className="text-xl font-semibold text-gray-800">
{currentView === 'dashboard' ? '首页' : '销售任务评估跟踪'}
</h1>
<div className="flex items-center gap-4">
{/* Simulation Control */}
<div className="flex items-center gap-2 bg-indigo-50 px-3 py-1 rounded border border-indigo-100">
<span className="text-xs font-bold text-indigo-800 uppercase tracking-wide">用户角色模拟:</span>
<select
className="bg-transparent text-sm text-indigo-900 font-medium focus:outline-none cursor-pointer"
value={currentUser.id}
onChange={handleRoleSwitch}
>
{MOCK_USERS.map(u => (
<option key={u.id} value={u.id}>{u.name}</option>
))}
</select>
</div>
<div className="h-8 w-px bg-gray-200 mx-2"></div>
<div className="flex items-center gap-2 text-gray-600">
<UserCircle size={24} />
<span className="text-sm font-medium">{currentUser.name}</span>
</div>
</div>
</header>
{/* Content Body */}
<div className="p-8 overflow-y-auto flex-1">
{currentView === 'dashboard' ? (
<div className="flex flex-col items-center justify-center h-full text-gray-400">
<LayoutDashboard size={64} className="mb-4 opacity-20" />
<p className="text-lg">欢迎使用普什模具管理系统</p>
<p className="text-sm">请选择左侧菜单进行操作</p>
</div>
) : (
<>
{/* Action Bar */}
<div className="flex justify-between items-center mb-6">
<div className="flex gap-2">
{/* Only show "My Tasks" hint for Reviewer */}
{currentUser.role === Role.REVIEWER && (
<span className="text-sm text-gray-500 bg-gray-100 px-3 py-1 rounded-full flex items-center gap-1">
<ClipboardCheck size={14} />
您已被分配的任务将显示【审核】按钮
</span>
)}
</div>
{/* Only show Create button if user is Sales */}
{currentUser.role === Role.SALES && (
<button
onClick={() => setIsCreateModalOpen(true)}
className="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded shadow transition-colors flex items-center gap-2"
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
新增任务
</button>
)}
</div>
{/* Table */}
<TaskList
tasks={tasks}
currentUserRole={currentUser.role}
currentUserId={currentUser.id}
isReviewEnabled={currentUser.role === Role.REVIEWER}
onView={(t) => setViewTask(t)}
onReview={(t) => setReviewTask(t)}
/>
</>
)}
</div>
</main>
{/* Modals */}
<CreateTaskModal
isOpen={isCreateModalOpen}
onClose={() => setIsCreateModalOpen(false)}
onSubmit={handleCreateTask}
currentUser={currentUser}
/>
<ReviewTaskModal
isOpen={!!reviewTask}
onClose={() => setReviewTask(null)}
task={reviewTask}
onSubmit={handleSubmitReview}
currentUser={currentUser}
/>
<ViewTaskModal
isOpen={!!viewTask}
onClose={() => setViewTask(null)}
task={viewTask}
/>
</div>
);
};
export default App;