Commit 7e09ce25 by tungnq

TODO: Đã hoàn thiện giao diện danh sách công việc

parent 3804c1b7
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;
......@@ -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},
......
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={handleFilterChange}
onFilterChange={onFilterChange}
/>
);
};
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 hn:
<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}>
Thuc văn bn:
<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 hn:
<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}>
Thuc văn bn:
<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}>Hc 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={handleAddWork}
onPress={onAddWork}
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={handleCloseModal}
onSave={handleSaveWork}
onClose={onCloseModal}
onSave={onSaveWork}
/>
</View>
);
......
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