Commit 9ce41d07 by tungnq

TODO: Đã bổ sung thêm logic để lọc công việc theo role và status

parent fb8e80c7
...@@ -33,3 +33,35 @@ export const ADD_PRODUCT = "ADD_PRODUCT"; ...@@ -33,3 +33,35 @@ export const ADD_PRODUCT = "ADD_PRODUCT";
export const REMOVE_PRODUCT = "REMOVE_PRODUCT"; export const REMOVE_PRODUCT = "REMOVE_PRODUCT";
export const CLEAR_CART = "CLEAR_CART"; export const CLEAR_CART = "CLEAR_CART";
//ACTION CÔNG VIỆC VAI TRÒ
export const ROLE = {
ALL : 'ALL',
ASSIGNEE : 'ASSIGNEE', //Giao cho tôi (Giảng viên nhận công việc)
SUPERVISOR : 'SUPERVISOR' //Đang giám sát (Giảng viên giám sát)
}
//ACTION TRẠNG THÁI THEO VAI TRÒ
export const STATUS_BY_ROLE ={
[ROLE.ASSIGNEE]: [
'Đang thực hiện',
'Cần chỉnh sửa',
'Chờ duyệt',
'Đợi báo cáo',
'Đã hoàn thành'
],
[ROLE.SUPERVISOR]:[
'Đang thực hiện',
'Đợi chỉnh sửa',
'Chờ duyệt',
'Đợi báo cáo',
'Đã hoàn thành'
]
}
//ACTION TIẾN ĐỘ CÔNG VIỆC
export const WORK_PROGRESS = {
ALL_WORK_PROGRESS: 'ALL_WORK_PROGRESS',
SUCCESS_WORK_PROGRESS: 'SUCCESS_WORK_PROGRESS',
CONTINUE_WORK_PROGRESS: 'CONTINUE_WORK_PROGRESS',
}
\ No newline at end of file
import React, {useState} from 'react'; import React, {useState, useMemo} from 'react';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import ListWorkView from './view'; import ListWorkView from './view';
import * as ScreenName from '../../routers/ScreenNames'; import * as ScreenName from '../../routers/ScreenNames';
import {WORK_PROGRESS, ROLE} from '../../actions/actionTypes';
import R from '../../assets/R';
/**
* 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 ListWork = props => {
const {searchQuery, setSearchQuery} = props;
const navigation = useNavigation(); const navigation = useNavigation();
const [searchQuery, setSearchQuery] = useState('');
// ==================== STATE MANAGEMENT ====================
// Trạng thái hiển thị modal thêm công việc
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
const [currentTabKey, setCurrentTabKey] = useState(ROLE.ALL);
const [currentDropDownKey, setCurrentDropDownKey] = useState(
WORK_PROGRESS.ALL_WORK_PROGRESS,
);
// Danh sách công việc mẫu với các trạng thái khác nhau
const [dataList, setDataList] = useState([ const [dataList, setDataList] = useState([
{ {
id: 1, id: 1,
title: 'Tạo thời khóa biểu cho sinh viến khai giảng và học kỳ 2 năm 2025', title: 'Tạo thời khóa biểu cho sinh viên khai giảng và học kỳ 2 năm 2025',
status: 'Đang thực hiện', status: 'Đang thực hiện', // hợp lệ cho cả 2 role
deadline: '2025-09-04', deadline: '2025-09-04',
assignedToMe: true,
supervisedByMe: false,
supervisor: [ supervisor: [
{id: 1, name: 'Trần Văn Hùng'}, {id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'}, {id: 2, name: 'Nguyễn Văn A'},
], ],
document: 'BM255, Nguyễn Minh Đức', document: 'BM255, Nguyễn Minh Đức',
workProgress: 'Đang thực hiện',
}, },
{ {
id: 2, id: 2,
title: 'Tạo thời khóa biểu cho sinh viến khai giảng và học kỳ 2 năm 2025', title: 'Tạo thời khóa biểu cho sinh viên khai giảng và học kỳ 2 năm 2025',
status: 'Cần chỉnh sửa', status: 'Cần chỉnh sửa', // chỉ hợp lệ với role Giao cho tôi
deadline: '2025-09-04', deadline: '2025-09-04',
assignedToMe: true,
supervisedByMe: false,
supervisor: [ supervisor: [
{id: 1, name: 'Trần Văn Hùng'}, {id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'}, {id: 2, name: 'Nguyễn Văn A'},
], ],
document: 'BM255, Nguyễn Minh Đức', document: 'BM255, Nguyễn Minh Đức',
workProgress: 'Đang hoàn thành',
}, },
{ {
id: 3, id: 3,
title: 'Tạo thời khóa biểu cho sinh viến khai giảng và học kỳ 2 năm 2025', title: 'Tạo thời khóa biểu cho sinh viên khai giảng và học kỳ 2 năm 2025',
status: 'Chờ duyệt', status: 'Hoàn thành', // hợp lệ cho cả 2 role
deadline: '2025-09-04', deadline: '2025-09-04',
assignedToMe: true,
supervisedByMe: false,
supervisor: [ supervisor: [
{id: 1, name: 'Trần Văn Hùng'}, {id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'}, {id: 2, name: 'Nguyễn Văn A'},
], ],
document: 'BM255, Nguyễn Minh Đức', document: 'BM255, Nguyễn Minh Đức',
workProgress: 'Đang hoàn thành',
}, },
{ {
id: 4, id: 4,
title: 'Tạo thời khóa biểu cho sinh viên khai giảng và học kỳ 2 năm 2025', title: 'Tạo thời khóa biểu cho sinh viên khai giảng và học kỳ 2 năm 2025',
status: 'Đợi báo cáo', status: 'Đợi báo cáo', // chỉ hợp lệ với role Đang giám sát
deadline: '2025-09-04', deadline: '2025-09-04',
assignedToMe: false,
supervisedByMe: true,
supervisor: [ supervisor: [
{id: 1, name: 'Trần Văn Hùng'}, {id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'}, {id: 2, name: 'Nguyễn Văn A'},
], ],
document: 'BM255, Nguyễn Minh Đức', document: 'BM255, Nguyễn Minh Đức',
workProgress: 'Đang hoàn thành',
}, },
{ {
id: 5, id: 5,
title: 'Tạo thời khóa biểu cho sinh viến khai giảng và học kỳ 2 năm 2025', title: 'Tạo thời khóa biểu cho sinh viên khai giảng và học kỳ 2 năm 2025',
status: 'Đã hoàn thành', status: 'Hoàn thành',
deadline: '2025-09-04', deadline: '2025-09-04',
assignedToMe: false,
supervisedByMe: true,
supervisor: [ supervisor: [
{id: 1, name: 'Trần Văn Hùng'}, {id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'}, {id: 2, name: 'Nguyễn Văn A'},
], ],
document: 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', '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',
workProgress: 'Đang thực hiện',
}, },
]); ]);
...@@ -99,9 +111,43 @@ const ListWork = props => { ...@@ -99,9 +111,43 @@ const ListWork = props => {
// Xử lý thay đổi bộ lọc tab // Xử lý thay đổi bộ lọc tab
const handleFilterChange = item => { const handleFilterChange = item => {
console.log('Bộ lọc đã thay đổi:', item); setCurrentTabKey(item?.key || ROLE.ALL);
// TODO: Thêm logic lọc danh sách theo tab được chọn console.log('Tab changed to:', item?.key);
}; };
// Hiển thị dữ liệu sau khi chọn
const filterList = useMemo(() => {
let base = dataList;
console.log('Dữ liệu danh sách đầu vào', base);
// Lọc theo tab role
if (currentTabKey === ROLE.ASSIGNEE) {
base = base.filter(x => x.assignedToMe);
} else if (currentTabKey === ROLE.SUPERVISOR) {
base = base.filter(x => x.supervisedByMe);
}
// ROLE.ALL không cần filter
// Lọc theo search query
if (searchQuery && searchQuery.trim()) {
const q = searchQuery.trim().toLowerCase();
base = base.filter(
x =>
x.title.toLowerCase().includes(q) ||
x.status.toLowerCase().includes(q),
);
}
// Lọc theo dropdown progress (chỉ khi không phải ALL)
if (currentDropDownKey === WORK_PROGRESS.SUCCESS_WORK_PROGRESS) {
base = base.filter(x => x.status === 'Đã hoàn thành');
} else if (currentDropDownKey === WORK_PROGRESS.CONTINUE_WORK_PROGRESS) {
base = base.filter(x => x.status !== 'Đã hoàn thành');
}
// WORK_PROGRESS.ALL_WORK_PROGRESS không cần filter
console.log('Dữ liệu sau khi lọc:', base);
return base;
}, [dataList, currentTabKey, searchQuery, currentDropDownKey]);
// ==================== NAVIGATION HANDLERS ==================== // ==================== NAVIGATION HANDLERS ====================
...@@ -151,8 +197,10 @@ const ListWork = props => { ...@@ -151,8 +197,10 @@ const ListWork = props => {
case 'Chờ duyệt': case 'Chờ duyệt':
return '#007AFF'; // Xanh dương return '#007AFF'; // Xanh dương
case 'Cần chỉnh sửa': case 'Cần chỉnh sửa':
return '#FF9500'; // Cam return '#FF9500'; // Cam (assignee)
case 'Đã hoàn thành': case 'Đợi chỉnh sửa':
return '#FF9500'; // Cam (supervisor)
case 'Hoàn thành':
return '#34C759'; // Xanh lá return '#34C759'; // Xanh lá
case 'Đợi báo cáo': case 'Đợi báo cáo':
return '#007AFF'; // Xanh dương return '#007AFF'; // Xanh dương
...@@ -163,66 +211,84 @@ const ListWork = props => { ...@@ -163,66 +211,84 @@ const ListWork = props => {
// Lấy danh sách button theo trạng thái công việc // Lấy danh sách button theo trạng thái công việc
const getButtonsForStatus = status => { 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 // Đang giám sát
if (['Đã hoàn thành', 'Cần chỉnh sửa', 'Đợi báo cáo'].includes(status)) { if (currentTabKey === ROLE.SUPERVISOR) {
return []; switch (status) {
case 'Đang thực hiện':
return [
{title: 'Yêu cầu báo cáo', backgroundColor: R.colors.orange, action: 'requestReport'},
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Đợi chỉnh sửa':
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
case 'Chờ duyệt':
return [
{title: 'Cần chỉnh sửa', backgroundColor: R.colors.orange, action: 'needsEdit'},
{title: 'Phê duyệt', backgroundColor: R.colors.blue, action: 'approve'},
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Đợi báo cáo':
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
case 'Đã hoàn thành':
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
default:
return [];
}
} }
// Trường hợp đặc biệt cho "Chờ duyệt" - hiển thị 2 button // Giao cho tôi
if (status === 'Chờ duyệt') { if (currentTabKey === ROLE.ASSIGNEE) {
return [ switch (status) {
{ case 'Đang thực hiện':
title: 'Cần chỉnh sửa', case 'Cần chỉnh sửa':
backgroundColor: '#FF9500', case 'Đợi báo cáo':
action: 'needsEdit', return [
}, {title: 'Báo cáo', backgroundColor: R.colors.orange, action: 'report'},
{ {title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
title: 'Phê duyệt', ];
backgroundColor: '#007AFF', case 'Chờ duyệt':
action: 'approve', return [
}, {title: 'Sửa báo cáo', backgroundColor: R.colors.orange, action: 'editReport'},
]; {title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Hoàn thành':
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
default:
return [];
}
} }
// Button mặc định cho các trạng thái khác // Tất cả - hiển thị tất cả buttons có thể
const buttonTitle = return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
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',
},
];
}; };
const [tabView, setTabView] = useState([ const [tabView, setTabView] = useState([
{key: 'all', label: 'Tất cả'}, {key: ROLE.ALL, label: 'Tất cả'},
{key: 'public', label: 'Giao cho tôi'}, {key: ROLE.ASSIGNEE, label: 'Giao cho tôi'},
{key: 'private', label: 'Đang giám sát'}, {key: ROLE.SUPERVISOR, label: 'Đang giám sát'},
]); ]);
// ==================== RENDER ==================== // ==================== RENDER ====================
return ( return (
<ListWorkView <ListWorkView
// Props dữ liệu // Dữ liệu
searchQuery={searchQuery} searchQuery={searchQuery}
setSearchQuery={setSearchQuery} setSearchQuery={setSearchQuery}
dataList={dataList} dataList={filterList}
modalVisible={modalVisible} modalVisible={modalVisible}
// Props xử lý sự kiện tabView={tabView}
onFilterChange={handleFilterChange} // Sự kiện
onAddWork={handleAddWork} onFilterChange={handleFilterChange}
onSaveWork={handleSaveWork} onAddWork={handleAddWork}
onCloseModal={handleCloseModal} onSaveWork={handleSaveWork}
onViewDetail={handleViewDetail} onCloseModal={handleCloseModal}
onReportAction={handleReportAction} onViewDetail={handleViewDetail}
onApprovalAction={handleApprovalAction} onReportAction={handleReportAction}
tabView={tabView} onApprovalAction={handleApprovalAction}
// Props utility functions // Utils
getStatusColor={getStatusColor} getStatusColor={getStatusColor}
getButtonsForStatus={getButtonsForStatus} getButtonsForStatus={getButtonsForStatus}
/> />
); );
}; };
......
...@@ -3,10 +3,8 @@ import { ...@@ -3,10 +3,8 @@ import {
Modal, Modal,
View, View,
Text, Text,
TextInput,
TouchableOpacity, TouchableOpacity,
ScrollView, ScrollView,
StyleSheet,
Image, Image,
FlatList, FlatList,
} from 'react-native'; } from 'react-native';
......
...@@ -37,6 +37,26 @@ const styles = StyleSheet.create({ ...@@ -37,6 +37,26 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
borderColor: R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
}, },
container_tab_view:{
marginVertical:5
},
item_tab_view:{
backgroundColor: R.colors.gray,
marginHorizontal: 5,
borderRadius: 10,
width: 107,
justifyContent: 'center',
alignItems: 'center',
},
active_tab_view:{
backgroundColor: R.colors.blue,
},
text_tab_view:{
color: R.colors.white,
fontWeight: '400',
fontFamily: R.fonts.fontRegular,
fontSize: R.fontsize.fontSizeContent,
},
text: { text: {
fontSize: R.sizes.sm, fontSize: R.sizes.sm,
color: R.colors.black, color: R.colors.black,
......
...@@ -23,6 +23,7 @@ const ListWorkView = props => { ...@@ -23,6 +23,7 @@ const ListWorkView = props => {
setSearchQuery, setSearchQuery,
dataList, dataList,
modalVisible, modalVisible,
tabView,
onFilterChange, onFilterChange,
onAddWork, onAddWork,
onSaveWork, onSaveWork,
...@@ -31,37 +32,20 @@ const ListWorkView = props => { ...@@ -31,37 +32,20 @@ const ListWorkView = props => {
onReportAction, onReportAction,
onApprovalAction, onApprovalAction,
getStatusColor, getStatusColor,
getButtonsForStatus, getButtonsForStatus
tabView,
} = props; } = props;
const renderTabView = () => { const renderTabView = () => {
return ( return (
<TabViewComponent <TabViewComponent
data={tabView} data={tabView}
tabStyle={{ tabStyle={styles.item_tab_view}
backgroundColor: R.colors.gray, style={styles.container_tab_view}
marginHorizontal: 5,
borderRadius: 10,
width: 107,
justifyContent: 'center',
alignItems: 'center',
}}
style={{
marginVertical: 5,
}}
mode="filter" mode="filter"
defaultActiveKey="all" defaultActiveKey="all"
scrollable={true} scrollable={true}
activeTabStyle={{ activeTabStyle={styles.active_tab_view}
backgroundColor: R.colors.blue, textStyle={styles.text_tab_view}
}}
textStyle={{
color: R.colors.white,
fontWeight: '400',
fontFamily: R.fonts.fontRegular,
fontSize: R.fontsize.fontSizeContent,
}}
showActiveIndicator={false} showActiveIndicator={false}
onFilterChange={onFilterChange} onFilterChange={onFilterChange}
/> />
...@@ -69,6 +53,7 @@ const ListWorkView = props => { ...@@ -69,6 +53,7 @@ const ListWorkView = props => {
}; };
const renderActionButtons = item => { const renderActionButtons = item => {
const buttons = getButtonsForStatus(item.status); const buttons = getButtonsForStatus(item.status);
return buttons.map((button, index) => ( return buttons.map((button, index) => (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment