Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
AppUms_Lecturer
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tungnq
AppUms_Lecturer
Commits
7e09ce25
Commit
7e09ce25
authored
Sep 04, 2025
by
tungnq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TODO: Đã hoàn thiện giao diện danh sách công việc
parent
3804c1b7
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
264 additions
and
180 deletions
+264
-180
index.js
src/screens/list_work/index.js
+169
-43
style.js
src/screens/list_work/style.js
+1
-1
view.js
src/screens/list_work/view.js
+94
-136
No files found.
src/screens/list_work/index.js
View file @
7e09ce25
import
React
,
{
useState
}
from
'react'
;
import
{
Text
,
View
,
StyleSheet
}
from
'react-
native'
;
import
React
,
{
useState
}
from
'react'
;
import
{
useNavigation
}
from
'@react-navigation/
native'
;
import
ListWorkView
from
'./view'
;
import
*
as
ScreenName
from
'../../routers/ScreenNames'
;
/**
* Container component quản lý logic nghiệp vụ cho màn hình danh sách công việc
* Chứa tất cả state và business logic, truyền xuống view component thông qua props
*/
const
ListWork
=
props
=>
{
const
{
searchQuery
,
setSearchQuery
}
=
props
;
const
navigation
=
useNavigation
();
// ==================== STATE MANAGEMENT ====================
// Trạng thái hiển thị modal thêm công việc
const
[
modalVisible
,
setModalVisible
]
=
useState
(
false
);
// Danh sách công việc mẫu với các trạng thái khác nhau
const
[
dataList
,
setDataList
]
=
useState
([
{
id
:
1
,
...
...
@@ -11,14 +24,8 @@ const ListWork = props => {
status
:
'Đang thực hiện'
,
deadline
:
'2025-09-04'
,
supervisor
:
[
{
id
:
1
,
name
:
'Trần Văn Hùng'
,
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
,
},
{
id
:
1
,
name
:
'Trần Văn Hùng'
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
},
],
document
:
'BM255, Nguyễn Minh Đức'
,
},
...
...
@@ -28,14 +35,8 @@ const ListWork = props => {
status
:
'Cần chỉnh sửa'
,
deadline
:
'2025-09-04'
,
supervisor
:
[
{
id
:
1
,
name
:
'Trần Văn Hùng'
,
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
,
},
{
id
:
1
,
name
:
'Trần Văn Hùng'
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
},
],
document
:
'BM255, Nguyễn Minh Đức'
,
},
...
...
@@ -45,14 +46,8 @@ const ListWork = props => {
status
:
'Chờ duyệt'
,
deadline
:
'2025-09-04'
,
supervisor
:
[
{
id
:
1
,
name
:
'Trần Văn Hùng'
,
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
,
},
{
id
:
1
,
name
:
'Trần Văn Hùng'
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
},
],
document
:
'BM255, Nguyễn Minh Đức'
,
},
...
...
@@ -62,14 +57,8 @@ const ListWork = props => {
status
:
'Đợi báo cáo'
,
deadline
:
'2025-09-04'
,
supervisor
:
[
{
id
:
1
,
name
:
'Trần Văn Hùng'
,
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
,
},
{
id
:
1
,
name
:
'Trần Văn Hùng'
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
},
],
document
:
'BM255, Nguyễn Minh Đức'
,
},
...
...
@@ -79,19 +68,156 @@ const ListWork = props => {
status
:
'Đã hoàn thành'
,
deadline
:
'2025-09-04'
,
supervisor
:
[
{
id
:
1
,
name
:
'Trần Văn Hùng'
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
},
],
document
:
'Văn bản thông báo lịch nộp thời khóa biểu của học kỳ 2 năm 2025'
,
},
]);
// ==================== MODAL HANDLERS ====================
// Mở modal thêm công việc mới
const
handleAddWork
=
()
=>
{
setModalVisible
(
true
);
};
// Đóng modal thêm công việc
const
handleCloseModal
=
()
=>
{
setModalVisible
(
false
);
};
// Xử lý lưu công việc mới
const
handleSaveWork
=
workData
=>
{
console
.
log
(
'Đang lưu công việc:'
,
workData
);
// TODO: Thêm logic lưu công việc vào database
setModalVisible
(
false
);
};
// ==================== FILTER & SEARCH HANDLERS ====================
// Xử lý thay đổi bộ lọc tab
const
handleFilterChange
=
item
=>
{
console
.
log
(
'Bộ lọc đã thay đổi:'
,
item
);
// TODO: Thêm logic lọc danh sách theo tab được chọn
};
// ==================== NAVIGATION HANDLERS ====================
// Điều hướng đến màn hình chi tiết công việc
const
handleViewDetail
=
item
=>
{
navigation
.
navigate
(
ScreenName
.
DETAILWORK
,
{
workItem
:
item
});
};
// ==================== ACTION HANDLERS ====================
// Xử lý các hành động báo cáo (báo cáo, yêu cầu báo cáo)
const
handleReportAction
=
(
item
,
action
)
=>
{
console
.
log
(
`Thực hiện hành động
${
action
}
cho công việc:`
,
item
.
id
);
// TODO: Thêm logic xử lý các hành động báo cáo
switch
(
action
)
{
case
'report'
:
// Xử lý báo cáo công việc
break
;
default
:
break
;
}
};
// Xử lý các hành động phê duyệt (phê duyệt, yêu cầu chỉnh sửa)
const
handleApprovalAction
=
(
item
,
action
)
=>
{
console
.
log
(
`Thực hiện hành động
${
action
}
cho công việc:`
,
item
.
id
);
// TODO: Thêm logic xử lý phê duyệt
switch
(
action
)
{
case
'approve'
:
// Xử lý phê duyệt công việc
break
;
case
'needsEdit'
:
// Xử lý yêu cầu chỉnh sửa
break
;
default
:
break
;
}
};
// ==================== UTILITY FUNCTIONS ====================
// Lấy màu sắc theo trạng thái công việc
const
getStatusColor
=
status
=>
{
switch
(
status
)
{
case
'Đang thực hiện'
:
return
'#FF9500'
;
// Cam
case
'Chờ duyệt'
:
return
'#007AFF'
;
// Xanh dương
case
'Cần chỉnh sửa'
:
return
'#FF9500'
;
// Cam
case
'Đã hoàn thành'
:
return
'#34C759'
;
// Xanh lá
case
'Đợi báo cáo'
:
return
'#007AFF'
;
// Xanh dương
default
:
return
'#8E8E93'
;
// Xám
}
};
// Lấy danh sách button theo trạng thái công việc
const
getButtonsForStatus
=
status
=>
{
// Ẩn button cho các trạng thái: hoàn thành, cần chỉnh sửa, đợi báo cáo
if
([
'Đã hoàn thành'
,
'Cần chỉnh sửa'
,
'Đợi báo cáo'
].
includes
(
status
))
{
return
[];
}
// Trường hợp đặc biệt cho "Chờ duyệt" - hiển thị 2 button
if
(
status
===
'Chờ duyệt'
)
{
return
[
{
id
:
1
,
name
:
'Trần Văn Hùng'
,
title
:
'Cần chỉnh sửa'
,
backgroundColor
:
'#FF9500'
,
action
:
'needsEdit'
,
},
{
id
:
2
,
name
:
'Nguyễn Văn A'
,
title
:
'Phê duyệt'
,
backgroundColor
:
'#007AFF'
,
action
:
'approve'
,
},
],
document
:
'Văn bản thông báo lịch nộp thời khóa biểu của học kỳ 2 năm 2025 '
,
},
]);
return
<
ListWorkView
searchQuery
=
{
searchQuery
}
setSearchQuery
=
{
setSearchQuery
}
dataList
=
{
dataList
}
/>
;
];
}
// Button mặc định cho các trạng thái khác
const
buttonTitle
=
status
===
'Đang thực hiện'
?
'Yêu cầu báo cáo'
:
'Báo cáo'
;
return
[
{
title
:
buttonTitle
,
backgroundColor
:
'#FF9500'
,
action
:
'report'
,
},
];
};
// ==================== RENDER ====================
return
(
<
ListWorkView
// Props dữ liệu
searchQuery
=
{
searchQuery
}
setSearchQuery
=
{
setSearchQuery
}
dataList
=
{
dataList
}
modalVisible
=
{
modalVisible
}
// Props xử lý sự kiện
onFilterChange
=
{
handleFilterChange
}
onAddWork
=
{
handleAddWork
}
onSaveWork
=
{
handleSaveWork
}
onCloseModal
=
{
handleCloseModal
}
onViewDetail
=
{
handleViewDetail
}
onReportAction
=
{
handleReportAction
}
onApprovalAction
=
{
handleApprovalAction
}
// Props utility functions
getStatusColor
=
{
getStatusColor
}
getButtonsForStatus
=
{
getButtonsForStatus
}
/
>
);
};
export
default
ListWork
;
src/screens/list_work/style.js
View file @
7e09ce25
...
...
@@ -61,8 +61,8 @@ const styles = StyleSheet.create({
},
containerCard
:{
backgroundColor
:
R
.
colors
.
white
,
padding
:
10
,
borderBottomLeftRadius
:
15
,
paddingBottom
:
10
,
borderBottomRightRadius
:
15
,
shadowColor
:
R
.
colors
.
black
,
shadowOffset
:
{
width
:
0.5
,
height
:
2
},
...
...
src/screens/list_work/view.js
View file @
7e09ce25
import
React
,
{
useState
}
from
'react'
;
import
React
from
'react'
;
import
{
Text
,
View
,
TouchableOpacity
,
StyleSheet
,
Image
,
TextInput
,
FlatList
,
...
...
@@ -17,49 +16,25 @@ import R from '../../assets/R';
import
TabViewComponent
from
'../../components/TabView'
;
import
AddWorkModal
from
'../list_work/modal_add/index'
;
import
Button
from
'../../components/Button'
;
import
*
as
ScreenName
from
'../../routers/ScreenNames'
;
import
{
useNavigation
}
from
'@react-navigation/native'
;
const
ListWorkView
=
props
=>
{
const
{
searchQuery
,
setSearchQuery
,
dataList
}
=
props
;
const
navigation
=
useNavigation
();
const
[
modalVisible
,
setModalVisible
]
=
useState
(
false
);
const
handleFilterChange
=
item
=>
{
console
.
log
(
item
);
};
const
handleAddWork
=
()
=>
{
setModalVisible
(
true
);
};
const
handleSaveWork
=
workData
=>
{
console
.
log
(
'Saving work:'
,
workData
);
};
const
handleCloseModal
=
()
=>
{
setModalVisible
(
false
);
};
const
getColor
=
(
status
)
=>
{
switch
(
status
)
{
case
'Đang thực hiện'
:
return
R
.
colors
.
orange
;
case
'Chờ duyệt'
:
return
R
.
colors
.
blue
;
case
'Cần chỉnh sửa'
:
return
R
.
colors
.
orange
;
case
'Đã hoàn thành'
:
return
R
.
colors
.
green
;
case
'Đợi báo cáo'
:
return
R
.
colors
.
blue
;
default
:
return
R
.
colors
.
gray
;
}
};
const
renderTabView
=
(
)
=>
{
const
{
searchQuery
,
setSearchQuery
,
dataList
,
modalVisible
,
onFilterChange
,
onAddWork
,
onSaveWork
,
onCloseModal
,
onViewDetail
,
onReportAction
,
onApprovalAction
,
getStatusColor
,
getButtonsForStatus
,
}
=
props
;
const
renderTabView
=
()
=>
{
return
(
<
TabViewComponent
data
=
{[
...
...
@@ -93,109 +68,93 @@ const ListWorkView = props => {
fontSize
:
R
.
fontsize
.
fontSizeContent
,
}}
showActiveIndicator
=
{
false
}
onFilterChange
=
{
handle
FilterChange
}
onFilterChange
=
{
on
FilterChange
}
/
>
);
};
const
renderReportButton
=
(
item
)
=>
{
// Hide report button for completed, needs editing, and waiting for report status
if
(
item
.
status
===
'Đã hoàn thành'
||
item
.
status
===
'Cần chỉnh sửa'
||
item
.
status
===
'Đợi báo cáo'
)
{
return
null
;
}
// Special case for "Chờ duyệt" - show two buttons
if
(
item
.
status
===
'Chờ duyệt'
)
{
return
(
<>
<
Button
title
=
"Cần chỉnh sửa"
onPress
=
{()
=>
{}}
backgroundColor
=
{
R
.
colors
.
orange
}
textColor
=
{
R
.
colors
.
white
}
fontSize
=
{
R
.
fontsize
.
fontSizeContent
}
height
=
{
35
}
width
=
{
100
}
containerStyle
=
{{
marginRight
:
10
,
borderRadius
:
20
}}
/
>
<
Button
title
=
"Phê duyệt"
onPress
=
{()
=>
{}}
backgroundColor
=
{
R
.
colors
.
green
}
textColor
=
{
R
.
colors
.
white
}
fontSize
=
{
R
.
fontsize
.
fontSizeContent
}
height
=
{
35
}
width
=
{
100
}
containerStyle
=
{{
marginRight
:
10
,
borderRadius
:
20
}}
/
>
<
/
>
);
}
let
buttonTitle
=
'Báo cáo'
;
const
renderActionButtons
=
item
=>
{
const
buttons
=
getButtonsForStatus
(
item
.
status
);
switch
(
item
.
status
)
{
case
'Đang thực hiện'
:
buttonTitle
=
'Yêu cầu báo cáo'
;
break
;
default
:
buttonTitle
=
'Báo cáo'
;
break
;
}
return
(
return
buttons
.
map
((
button
,
index
)
=>
(
<
Button
title
=
{
buttonTitle
}
onPress
=
{()
=>
{}}
backgroundColor
=
{
R
.
colors
.
orange
}
key
=
{
index
}
title
=
{
button
.
title
}
onPress
=
{()
=>
{
if
(
button
.
action
===
'approve'
||
button
.
action
===
'needsEdit'
)
{
onApprovalAction
(
item
,
button
.
action
);
}
else
{
onReportAction
(
item
,
button
.
action
);
}
}}
backgroundColor
=
{
button
.
backgroundColor
}
textColor
=
{
R
.
colors
.
white
}
fontSize
=
{
R
.
fontsize
.
fontSizeContent
}
height
=
{
35
}
width
=
{
120
}
width
=
{
120
}
containerStyle
=
{{
marginRight
:
10
,
borderRadius
:
20
}}
/
>
);
)
)
;
};
const
renderListView
=
(
{
item
}
)
=>
{
return
(
<
View
style
=
{{
marginHorizontal
:
15
,
marginVertical
:
10
}}
>
<
View
style
=
{{
backgroundColor
:
getColor
(
item
.
status
),
borderTopLeftRadius
:
15
,
borderTopRightRadius
:
15
}}
>
<
Text
style
=
{[
styles
.
subText
,
{
marginHorizontal
:
15
,
fontFamily
:
R
.
fonts
.
fontMedium
,
fontWeight
:
'600'
,
color
:
R
.
colors
.
white
,}]}
>
{
item
.
status
}
<
/Text
>
<
/View
>
<
View
style
=
{
styles
.
containerCard
}
>
<
Text
style
=
{
styles
.
text
}
>
{
item
.
title
}
<
/Text
>
<
View
style
=
{{
flexDirection
:
'row'
,
justifyContent
:
'space-between'
}}
>
<
Text
style
=
{
styles
.
text
}
>
Ng
à
y
đế
n
h
ạ
n
:
<
Text
style
=
{
styles
.
subText
}
>
{
item
.
deadline
}
<
/Text
>
const
renderListView
=
({
item
})
=>
{
return
(
<
TouchableOpacity
style
=
{{
marginHorizontal
:
15
,
marginVertical
:
10
}}
onPress
=
{()
=>
onViewDetail
(
item
)}
activeOpacity
=
{
0.7
}
>
<
View
style
=
{{
backgroundColor
:
getStatusColor
(
item
.
status
),
borderTopLeftRadius
:
15
,
borderTopRightRadius
:
15
,
}}
>
<
Text
style
=
{[
styles
.
subText
,
{
marginHorizontal
:
15
,
fontFamily
:
R
.
fonts
.
fontMedium
,
fontWeight
:
'600'
,
color
:
R
.
colors
.
white
,
},
]}
>
{
item
.
status
}
<
/Text
>
<
/View
>
<
Text
style
=
{
styles
.
text
}
>
Ng
ườ
i
gi
á
m
s
á
t
:
<
Text
style
=
{
styles
.
subText
}
>
{
item
.
supervisor
.
map
((
item
)
=>
item
.
name
).
join
(
', '
)}
<
/Text
>
<
/Text
>
<
Text
style
=
{
styles
.
text
}
>
Thu
ộ
c
v
ă
n
b
ả
n
:
<
Text
style
=
{
styles
.
subText
}
>
{
item
.
document
}
<
/Text
>
<
/Text
>
<
View
style
=
{{
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
,
marginTop
:
10
}}
>
{
renderReportButton
(
item
)}
<
Button
title
=
"Chi tiết"
onPress
=
{()
=>
navigation
.
navigate
(
ScreenName
.
DETAILWORK
)}
backgroundColor
=
{
R
.
colors
.
blue
}
textColor
=
{
R
.
colors
.
white
}
fontSize
=
{
R
.
fontsize
.
fontSizeContent
}
height
=
{
35
}
width
=
{
100
}
containerStyle
=
{{
borderRadius
:
20
}}
/
>
<
View
style
=
{
styles
.
containerCard
}
>
<
View
style
=
{{
paddingHorizontal
:
15
,
paddingTop
:
10
}}
>
<
Text
style
=
{
styles
.
text
}
>
{
item
.
title
}
<
/Text
>
<
View
style
=
{{
flexDirection
:
'row'
,
justifyContent
:
'space-between'
}}
>
<
Text
style
=
{
styles
.
text
}
>
Ng
à
y
đế
n
h
ạ
n
:
<
Text
style
=
{
styles
.
subText
}
>
{
item
.
deadline
}
<
/Text
>
<
/Text
>
<
/View
>
<
Text
style
=
{
styles
.
text
}
>
Ng
ườ
i
gi
á
m
s
á
t
:
<
Text
style
=
{
styles
.
subText
}
>
{
item
.
supervisor
.
map
(
item
=>
item
.
name
).
join
(
', '
)}
<
/Text
>
<
/Text
>
<
Text
style
=
{
styles
.
text
}
>
Thu
ộ
c
v
ă
n
b
ả
n
:
<
Text
style
=
{
styles
.
subText
}
>
{
item
.
document
}
<
/Text
>
<
/Text
>
<
/View
>
<
View
style
=
{{
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
,
marginTop
:
10
,
}}
>
{
renderActionButtons
(
item
)}
<
/View
>
<
/View
>
<
/View
>
<
/View
>
)
<
/TouchableOpacity
>
);
};
return
(
...
...
@@ -204,7 +163,7 @@ const ListWorkView = props => {
<
View
style
=
{
styles
.
body
}
>
{
renderTabView
()}
<
View
style
=
{{
marginBottom
:
15
,
flex
:
1
}}
>
<
View
style
=
{{
marginBottom
:
15
,
flex
:
1
}}
>
<
View
style
=
{
styles
.
card
}
>
<
TouchableOpacity
style
=
{
styles
.
btnCard
}
>
<
Text
style
=
{
styles
.
text
}
>
H
ọ
c
k
ỳ
2
,
N
ă
m
2025
<
/Text
>
...
...
@@ -228,21 +187,20 @@ const ListWorkView = props => {
<
/View
>
<
View
style
=
{{
flex
:
0.1
}}
><
/View
>
<
View
style
=
{{
flex
:
1
}}
>
<
View
style
=
{{
flex
:
1
}}
>
<
Dropdown
title
=
{
'Tìm kiếm'
}
height
=
{
40
}
/
>
<
/View
>
<
/View
>
<
FlatList
data
=
{
dataList
}
renderItem
=
{
renderListView
}
keyExtractor
=
{
item
=>
item
.
id
.
toString
()}
/
>
<
/View
>
<
/View
>
<
FAB
>
<
SubButton
onPress
=
{
handle
AddWork
}
onPress
=
{
on
AddWork
}
label
=
"Tạo công việc"
images
=
{
R
.
images
.
icMenuEdit
}
backgroundColor
=
{
R
.
colors
.
blue
}
...
...
@@ -251,8 +209,8 @@ const ListWorkView = props => {
<
AddWorkModal
visible
=
{
modalVisible
}
onClose
=
{
handle
CloseModal
}
onSave
=
{
handle
SaveWork
}
onClose
=
{
on
CloseModal
}
onSave
=
{
on
SaveWork
}
/
>
<
/View
>
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment