Commit 408a922c by tungnq

TODO: Refactor ListWork và Modals: Cải thiện cấu trúc và khả năng đọc của code

Cập nhật component ListWork để tối ưu định dạng và dễ bảo trì hơn.

Refactor AddWorkModal và AddMonitoringModal nhằm tách biệt logic với phần giao diện.

Thêm quản lý state cho dữ liệu form và lựa chọn trong các modal.

Cải thiện cách xử lý dropdown và logic chọn item.

Nâng cao tính nhất quán trong styling giữa các component.

Bổ sung style mới cho tính năng chỉnh sửa báo cáo trong modal.
parent 6625758a
import WorkReportModal from './view';
import React, {useState} from 'react';
import WorkReportModalView from './view';
const WorkReportModal = ({visible, onClose, onSubmit}) => {
const [reportContent, setReportContent] = useState('');
const handleSubmit = () => {
if (reportContent.trim()) {
onSubmit(reportContent);
setReportContent('');
onClose();
}
};
const handleCancel = () => {
setReportContent('');
onClose();
};
const handleContentChange = (content) => {
setReportContent(content);
};
const handleAddAttachment = () => {
// Handle add attachment logic
console.log('Add attachment');
};
return (
<WorkReportModalView
visible={visible}
onClose={onClose}
reportContent={reportContent}
onContentChange={handleContentChange}
onSubmit={handleSubmit}
onCancel={handleCancel}
onAddAttachment={handleAddAttachment}
/>
);
};
export default WorkReportModal;
import React, {useState} from 'react';
import {
Modal,
View,
Text,
TouchableOpacity,
Image,
} from 'react-native';
import React from 'react';
import {Modal, View, Text, TouchableOpacity, Image} from 'react-native';
import TextMulti from '../../../../../components/Input/TextMulti';
import R from '../../../../../assets/R';
import Button from '../../../../../components/Button';
import styles from './style';
const WorkReportModal = ({visible, onClose, onSubmit}) => {
const [reportContent, setReportContent] = useState('');
const handleSubmit = () => {
if (reportContent.trim()) {
onSubmit(reportContent);
setReportContent('');
onClose();
}
};
const handleCancel = () => {
setReportContent('');
onClose();
};
const WorkReportModalView = ({
visible,
onClose,
reportContent,
onContentChange,
onSubmit,
onCancel,
onAddAttachment,
}) => {
return (
<Modal
......@@ -41,10 +29,12 @@ const WorkReportModal = ({visible, onClose, onSubmit}) => {
title="Nội dung báo cáo"
required={true}
containerMarginBottom={10}
value={reportContent}
onChangeText={onContentChange}
/>
<Text style={styles.label}>Tài liu đính kèm</Text>
<TouchableOpacity style={styles.attachmentContainer}>
<TouchableOpacity style={styles.attachmentContainer} onPress={onAddAttachment}>
<Image source={R.images.icDocument} style={styles.uploadIcon} />
<Text style={styles.attachmentText}>Thêm tài liu</Text>
</TouchableOpacity>
......@@ -57,7 +47,7 @@ const WorkReportModal = ({visible, onClose, onSubmit}) => {
backgroundColor={R.colors.orange}
borderRadius={100}
fontSize={R.fontsize.fontSizeContent}
onPress={handleCancel}
onPress={onCancel}
txtStyle={{
color: R.colors.white,
fontWeight: '600',
......@@ -72,7 +62,7 @@ const WorkReportModal = ({visible, onClose, onSubmit}) => {
backgroundColor={R.colors.blue}
borderRadius={100}
fontSize={R.fontsize.fontSizeContent}
onPress={handleSubmit}
onPress={onSubmit}
txtStyle={{
color: R.colors.white,
fontWeight: '600',
......@@ -86,4 +76,4 @@ const WorkReportModal = ({visible, onClose, onSubmit}) => {
);
};
export default WorkReportModal;
export default WorkReportModalView;
import EditReportModal from './view';
import React, {useState, useEffect} from 'react';
import EditReportModalView from './view';
const EditReportModal = ({visible, onClose, onSubmit, initialContent = ''}) => {
const [reportContent, setReportContent] = useState(initialContent);
// Update reportContent when initialContent changes
useEffect(() => {
setReportContent(initialContent);
}, [initialContent]);
const handleSubmit = () => {
if (reportContent.trim()) {
onSubmit(reportContent);
onClose();
}
};
const handleCancel = () => {
setReportContent(initialContent);
onClose();
};
const handleContentChange = (content) => {
setReportContent(content);
};
const handleDeleteAttachment = () => {
// Handle attachment deletion logic
console.log('Delete attachment');
};
const handleAddAttachment = () => {
// Handle add attachment logic
console.log('Add attachment');
};
return (
<EditReportModalView
visible={visible}
onClose={onClose}
reportContent={reportContent}
onContentChange={handleContentChange}
onSubmit={handleSubmit}
onCancel={handleCancel}
onDeleteAttachment={handleDeleteAttachment}
onAddAttachment={handleAddAttachment}
/>
);
};
export default EditReportModal;
import { StyleSheet } from "react-native";
import R from "../../../../../assets/R";
const styles = StyleSheet.create({
overlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
modalContainer: {
backgroundColor: 'white',
borderRadius: 12,
padding: 20,
width: '90%',
maxWidth: 400,
},
title: {
fontSize: R.fontsize.fontsSizeTitle,
fontWeight: '600',
color: R.colors.blue,
textAlign: 'center',
},
description: {
fontSize: R.fontsize.fontSizeContent,
color: R.colors.gray1,
lineHeight: 18,
marginBottom: 10,
textAlign: 'left',
borderWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader,
borderRadius: 10,
padding: 10,
},
required: {
color: R.colors.red,
},
attachedFileContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: R.colors.blue1,
borderRadius: 10,
padding: 10,
marginBottom: 10,
},
text: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontMedium,
fontWeight: '600',
color: R.colors.black,
},
fileName: {
fontSize: R.sizes.xs,
color: R.colors.black,
},
deleteIcon: {
width: 20,
height: 20,
tintColor: R.colors.blue,
},
attachmentContainer: {
borderWidth: 1,
borderColor: R.colors.blue,
borderRadius: 10,
padding: 20,
alignItems: 'center',
marginBottom: 20,
},
uploadIcon: {
width: 23,
height: 28,
tintColor: R.colors.blue,
marginBottom: 5,
},
attachmentText: {
fontSize: 14,
color: R.colors.blue,
fontWeight: '500',
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
},
cancelButton: {
flex: 1,
backgroundColor: R.colors.orange,
borderRadius: 8,
paddingVertical: 12,
alignItems: 'center',
},
submitButton: {
flex: 1,
backgroundColor: R.colors.blue,
borderRadius: 8,
paddingVertical: 12,
alignItems: 'center',
},
cancelButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
submitButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
});
export default styles
\ No newline at end of file
import React, {useState} from 'react';
import {
Modal,
View,
Text,
TextInput,
TouchableOpacity,
StyleSheet,
Image,
} from 'react-native';
import React from 'react';
import {Modal, View, Text, TouchableOpacity, Image} from 'react-native';
import R from '../../../../../assets/R';
import Button from '../../../../../components/Button';
import styles from './style';
const EditReportModal = ({visible, onClose, onSubmit, initialContent = ''}) => {
const [reportContent, setReportContent] = useState(initialContent);
const handleSubmit = () => {
if (reportContent.trim()) {
onSubmit(reportContent);
onClose();
}
};
const handleCancel = () => {
setReportContent(initialContent);
onClose();
};
const EditReportModalView = ({
visible,
onClose,
reportContent,
onContentChange,
onSubmit,
onCancel,
onDeleteAttachment,
onAddAttachment,
}) => {
return (
<Modal
......@@ -50,12 +39,12 @@ const EditReportModal = ({visible, onClose, onSubmit, initialContent = ''}) => {
<Text style={styles.fileName}>
Quyết định thông báo đào to - QD347583
</Text>
<TouchableOpacity>
<TouchableOpacity onPress={onDeleteAttachment}>
<Image source={R.images.icCancel} style={styles.deleteIcon} />
</TouchableOpacity>
</View>
<TouchableOpacity style={styles.attachmentContainer}>
<TouchableOpacity style={styles.attachmentContainer} onPress={onAddAttachment}>
<Image source={R.images.icDocument} style={styles.uploadIcon} />
<Text style={styles.attachmentText}>Thêm tài liu</Text>
</TouchableOpacity>
......@@ -63,7 +52,7 @@ const EditReportModal = ({visible, onClose, onSubmit, initialContent = ''}) => {
<View style={styles.buttonContainer}>
<Button
title="Hủy"
onPress={handleCancel}
onPress={onCancel}
backgroundColor={R.colors.orange}
width={100}
height={35}
......@@ -74,7 +63,7 @@ const EditReportModal = ({visible, onClose, onSubmit, initialContent = ''}) => {
/>
<Button
title="Cập nhật"
onPress={handleSubmit}
onPress={onSubmit}
backgroundColor={R.colors.blue}
width={100}
height={35}
......@@ -89,112 +78,4 @@ const EditReportModal = ({visible, onClose, onSubmit, initialContent = ''}) => {
);
};
const styles = StyleSheet.create({
overlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
modalContainer: {
backgroundColor: 'white',
borderRadius: 12,
padding: 20,
width: '90%',
maxWidth: 400,
},
title: {
fontSize: R.fontsize.fontsSizeTitle,
fontWeight: '600',
color: R.colors.blue,
textAlign: 'center',
},
description: {
fontSize: R.fontsize.fontSizeContent,
color: R.colors.gray1,
lineHeight: 18,
marginBottom: 10,
textAlign: 'left',
borderWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader,
borderRadius: 10,
padding: 10,
},
required: {
color: R.colors.red,
},
attachedFileContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: R.colors.blue1,
borderRadius: 10,
padding: 10,
marginBottom: 10,
},
text: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontMedium,
fontWeight: '600',
color: R.colors.black,
},
fileName: {
fontSize: R.sizes.xs,
color: R.colors.black,
},
deleteIcon: {
width: 20,
height: 20,
tintColor: R.colors.blue,
},
attachmentContainer: {
borderWidth: 1,
borderColor: R.colors.blue,
borderRadius: 10,
padding: 20,
alignItems: 'center',
marginBottom: 20,
},
uploadIcon: {
width: 23,
height: 28,
tintColor: R.colors.blue,
marginBottom: 5,
},
attachmentText: {
fontSize: 14,
color: R.colors.blue,
fontWeight: '500',
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
},
cancelButton: {
flex: 1,
backgroundColor: R.colors.orange,
borderRadius: 8,
paddingVertical: 12,
alignItems: 'center',
},
submitButton: {
flex: 1,
backgroundColor: R.colors.blue,
borderRadius: 8,
paddingVertical: 12,
alignItems: 'center',
},
cancelButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
submitButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
});
export default EditReportModal;
export default EditReportModalView;
......@@ -94,7 +94,10 @@ const ListWork = props => {
deadline: '2025-09-10',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'BM301, Phòng Đào tạo',
workProgress: 'Đang thực hiện',
},
......@@ -105,7 +108,10 @@ const ListWork = props => {
deadline: '2025-09-12',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Công văn 12/MN',
workProgress: 'Đã hoàn thành',
},
......@@ -116,7 +122,10 @@ const ListWork = props => {
deadline: '2025-09-15',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'BM-Exam-2025',
workProgress: 'Đã hoàn thành',
},
......@@ -127,7 +136,10 @@ const ListWork = props => {
deadline: '2025-09-11',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Slide_v2.pptx',
workProgress: 'Đã hoàn thành',
},
......@@ -138,7 +150,10 @@ const ListWork = props => {
deadline: '2025-09-05',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'AI-Syllabus-Final.pdf',
workProgress: 'Đang thực hiện',
},
......@@ -149,7 +164,10 @@ const ListWork = props => {
deadline: '2025-09-18',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Biên bản họp 09/2025',
workProgress: 'Đang thực hiện',
},
......@@ -160,7 +178,10 @@ const ListWork = props => {
deadline: '2025-09-20',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Report-Draft.docx',
workProgress: 'Đã hoàn thành',
},
......@@ -171,7 +192,10 @@ const ListWork = props => {
deadline: '2025-09-22',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Checklist-KDCL.xlsx',
workProgress: 'Đã hoàn thành',
},
......@@ -182,7 +206,10 @@ const ListWork = props => {
deadline: '2025-09-13',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'SeminarPlan.docx',
workProgress: 'Đang thực hiện',
},
......@@ -193,7 +220,10 @@ const ListWork = props => {
deadline: '2025-09-03',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Textbook-Final.pdf',
workProgress: 'Đã hoàn thành',
},
......@@ -204,7 +234,10 @@ const ListWork = props => {
deadline: '2025-09-16',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'RN-Lab3.md',
workProgress: 'Đang thực hiện',
},
......@@ -215,7 +248,10 @@ const ListWork = props => {
deadline: '2025-09-17',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Issue#127',
workProgress: 'Đang thực hiện',
},
......@@ -226,7 +262,10 @@ const ListWork = props => {
deadline: '2025-09-19',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'BigData-Slides-v1.pptx',
workProgress: 'Đang thực hiện',
},
......@@ -237,7 +276,10 @@ const ListWork = props => {
deadline: '2025-09-14',
assignedToMe: true,
supervisedByMe: false,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Minutes-Dept-0909.docx',
workProgress: 'Đang thực hiện',
},
......@@ -248,7 +290,10 @@ const ListWork = props => {
deadline: '2025-09-21',
assignedToMe: false,
supervisedByMe: true,
supervisor: [{id: 1, name: 'Trần Văn Hùng'}, {id: 2, name: 'Nguyễn Văn A'}],
supervisor: [
{id: 1, name: 'Trần Văn Hùng'},
{id: 2, name: 'Nguyễn Văn A'},
],
document: 'Thesis-List.xlsx',
workProgress: 'Chờ duyệt',
},
......@@ -296,8 +341,8 @@ const ListWork = props => {
setCurrentTabKey(item?.key || ROLE.ALL);
console.log('Tab changed to:', item?.key);
};
// Hiển thị dữ liệu sau khi chọn
const filterList = useMemo(() => {
// 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);
......@@ -414,67 +459,105 @@ const ListWork = props => {
}
}
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
return [
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
};
// Helper function cho buttons của Supervisor
const getButtonsForSupervisor = (status) => {
const getButtonsForSupervisor = status => {
switch (status) {
case 'Đang thực hiện':
// Supervisor có thể yêu cầu báo cáo từ người được giao việc
return [
{title: 'Yêu cầu báo cáo', backgroundColor: R.colors.orange, action: 'requestReport'},
{
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':
// Đang chờ người được giao việc chỉnh sửa
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
return [
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Chờ duyệt':
// Supervisor cần phê duyệt hoặc yêu cầu chỉnh sửa
return [
{title: 'Cần chỉnh sửa', backgroundColor: R.colors.orange, action: 'needsEdit'},
{title: 'Phê duyệt', backgroundColor: R.colors.green, action: 'approve'},
{
title: 'Cần chỉnh sửa',
backgroundColor: R.colors.orange,
action: 'needsEdit',
},
{
title: 'Phê duyệt',
backgroundColor: R.colors.green,
action: 'approve',
},
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Đợi báo cáo':
// Đang chờ người được giao việc nộp báo cáo
return [{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'}];
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'}];
return [
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
default:
return [];
}
};
// Helper function cho buttons của Assignee
const getButtonsForAssignee = (status) => {
const getButtonsForAssignee = status => {
switch (status) {
case 'Đang thực hiện':
// Người được giao việc đang thực hiện và có thể nộp báo cáo
return [
{title: 'Báo cáo', backgroundColor: R.colors.orange, action: 'report'},
{
title: 'Báo cáo',
backgroundColor: R.colors.orange,
action: 'report',
},
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Cần chỉnh sửa':
// Supervisor yêu cầu chỉnh sửa, người được giao việc cần báo cáo lại
return [
{title: 'Báo cáo', backgroundColor: R.colors.orange, action: 'report'},
{
title: 'Báo cáo',
backgroundColor: R.colors.orange,
action: 'report',
},
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Đợi báo cáo':
// Supervisor yêu cầu báo cáo, người được giao việc cần nộp báo cáo
return [
{title: 'Báo cáo', backgroundColor: R.colors.orange, action: 'report'},
{
title: 'Báo cáo',
backgroundColor: R.colors.orange,
action: 'report',
},
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
case 'Chờ duyệt':
// Đã nộp báo cáo, đang chờ supervisor duyệt, có thể sửa báo cáo
return [
{title: 'Sửa báo cáo', backgroundColor: R.colors.orange, action: 'editReport'},
{
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'}];
return [
{title: 'Chi tiết', backgroundColor: R.colors.blue, action: 'detail'},
];
default:
return [];
}
......@@ -495,28 +578,28 @@ const ListWork = props => {
return (
<ListWorkView
// Dữ liệu
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
dataList={filterList}
modalDeliverToMeVisible={modalDeliverToMeVisible}
modalMonitoringVisible={modalMonitoringVisible}
tabView={tabView}
currentTabKey={currentTabKey}
shouldShowFAB={shouldShowFAB()}
// Sự kiện
onFilterChange={handleFilterChange}
onAddWork={handleAddWork}
onSaveDeliverToMeWork={handleSaveDeliverToMeWork}
onSaveMonitoringWork={handleSaveMonitoringWork}
onCloseDeliverToMeModal={handleCloseDeliverToMeModal}
onCloseMonitoringModal={handleCloseMonitoringModal}
onViewDetailDeliverToMe={handleViewDetailDeliverToMe}
onReportAction={handleReportAction}
onApprovalAction={handleApprovalAction}
// Utils
getStatusColor={getStatusColor}
getButtonsForStatus={getButtonsForStatus}
// Dữ liệu
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
dataList={filterList}
modalDeliverToMeVisible={modalDeliverToMeVisible}
modalMonitoringVisible={modalMonitoringVisible}
tabView={tabView}
currentTabKey={currentTabKey}
shouldShowFAB={shouldShowFAB()}
// Sự kiện
onFilterChange={handleFilterChange}
onAddWork={handleAddWork}
onSaveDeliverToMeWork={handleSaveDeliverToMeWork}
onSaveMonitoringWork={handleSaveMonitoringWork}
onCloseDeliverToMeModal={handleCloseDeliverToMeModal}
onCloseMonitoringModal={handleCloseMonitoringModal}
onViewDetailDeliverToMe={handleViewDetailDeliverToMe}
onReportAction={handleReportAction}
onApprovalAction={handleApprovalAction}
// Utils
getStatusColor={getStatusColor}
getButtonsForStatus={getButtonsForStatus}
/>
);
};
......
import AddWorkModal from './view';
import React, {useState} from 'react';
import AddWorkModalView from './view';
const AddWorkModal = ({visible, onClose, onSave}) => {
const [formData, setFormData] = useState({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
const [dataList, setDataList] = useState([
{id: 1, name: 'Nguyễn Minh Đức'},
{id: 2, name: 'Trần Văn Hùng'},
{id: 3, name: 'Lê Thị Mai'},
{id: 4, name: 'Phạm Quốc Khánh'},
{id: 5, name: 'Hoàng Anh Tuấn'},
{id: 6, name: 'Vũ Thị Hằng'},
{id: 7, name: 'Ngô Văn Nam'},
{id: 8, name: 'Đinh Thị Lan'},
{id: 9, name: 'Bùi Văn Phúc'},
{id: 10, name: 'Lý Thị Hoa'},
{id: 11, name: 'Phan Minh Hoàng'},
{id: 12, name: 'Tạ Thị Hương'},
{id: 13, name: 'Đoàn Văn Dũng'},
{id: 14, name: 'Nguyễn Thị Vân'},
{id: 15, name: 'Trương Văn Long'},
{id: 16, name: 'Mai Thị Ngọc'},
{id: 17, name: 'Huỳnh Quốc Việt'},
{id: 18, name: 'Lâm Thị Thu'},
{id: 19, name: 'Nguyễn Hữu Tài'},
{id: 20, name: 'Phạm Thị Kim'},
]);
const categoryData = [
{name: 'Công việc theo văn bản', value: 'document'},
{name: 'Công việc khác', value: 'other'},
];
const items = [
{id: 1, label: 'Option 1'},
{id: 2, label: 'Option 2'},
{id: 3, label: 'Option 3'},
];
const responsibleData = [
{name: 'Công việc theo văn bản', value: 'document'},
{name: 'Công việc cá nhân', value: 'personal'},
];
const assigneeData = [
{name: 'BM255, Nguyễn Minh Đức', value: 'duc'},
{name: 'Khác', value: 'other'},
];
const implementerData = [
{name: 'BM255, Nguyễn Minh Đức', value: 'duc'},
{name: 'Khác', value: 'other'},
];
const updateFormData = (field, value) => {
setFormData(prev => ({...prev, [field]: value}));
};
const handleSave = () => {
onSave(formData);
resetForm();
onClose();
};
const resetForm = () => {
setFormData({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
};
const handleCancel = () => {
resetForm();
onClose();
};
const handleItemPress = (item) => {
// Logic xử lý khi nhấn vào item trong danh sách
console.log('Item pressed:', item);
};
const handleDropdownSelect = (item, field) => {
console.log('Dropdown selected:', item, field);
updateFormData(field, item);
};
return (
<AddWorkModalView
visible={visible}
formData={formData}
dataList={dataList}
categoryData={categoryData}
items={items}
responsibleData={responsibleData}
assigneeData={assigneeData}
implementerData={implementerData}
updateFormData={updateFormData}
handleSave={handleSave}
handleCancel={handleCancel}
handleItemPress={handleItemPress}
handleDropdownSelect={handleDropdownSelect}
/>
);
};
export default AddWorkModal;
import React, {useState} from 'react';
import React from 'react';
import {
Modal,
View,
......@@ -15,88 +15,26 @@ import TextMulti from '../../../components/Input/TextMulti';
import Dropdown from '../../../components/DropdownAlert/Dropdown';
import Button from '../../../components/Button';
const AddWorkModal = ({visible, onClose, onSave}) => {
const [formData, setFormData] = useState({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
const [dataList, setDataList] = useState([
{id: 1, name: 'Nguyễn Minh Đức'},
{id: 2, name: 'Trần Văn Hùng'},
{id: 3, name: 'Lê Thị Mai'},
{id: 4, name: 'Phạm Quốc Khánh'},
{id: 5, name: 'Hoàng Anh Tuấn'},
{id: 6, name: 'Vũ Thị Hằng'},
{id: 7, name: 'Ngô Văn Nam'},
{id: 8, name: 'Đinh Thị Lan'},
{id: 9, name: 'Bùi Văn Phúc'},
{id: 10, name: 'Lý Thị Hoa'},
{id: 11, name: 'Phan Minh Hoàng'},
{id: 12, name: 'Tạ Thị Hương'},
{id: 13, name: 'Đoàn Văn Dũng'},
{id: 14, name: 'Nguyễn Thị Vân'},
{id: 15, name: 'Trương Văn Long'},
{id: 16, name: 'Mai Thị Ngọc'},
{id: 17, name: 'Huỳnh Quốc Việt'},
{id: 18, name: 'Lâm Thị Thu'},
{id: 19, name: 'Nguyễn Hữu Tài'},
{id: 20, name: 'Phạm Thị Kim'},
]);
const categoryData = [
{name: 'Công việc theo văn bản', value: 'document'},
{name: 'Công việc khác', value: 'other'},
];
const items = [
{id: 1, label: 'Option 1'},
{id: 2, label: 'Option 2'},
{id: 3, label: 'Option 3'},
];
const responsibleData = [
{name: 'Công việc theo văn bản', value: 'document'},
{name: 'Công việc cá nhân', value: 'personal'},
];
const assigneeData = [
{name: 'BM255, Nguyễn Minh Đức', value: 'duc'},
{name: 'Khác', value: 'other'},
];
const implementerData = [
{name: 'BM255, Nguyễn Minh Đức', value: 'duc'},
{name: 'Khác', value: 'other'},
];
const handleSave = () => {
onSave(formData);
onClose();
};
const handleCancel = () => {
setFormData({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
onClose();
};
const AddWorkModalView = props => {
const {
visible,
formData,
dataList,
categoryData,
items,
responsibleData,
assigneeData,
implementerData,
updateFormData,
handleSave,
handleCancel,
handleItemPress,
handleDropdownSelect,
} = props;
const renderItem_1 = ({item, onPress}) => {
return (
<View style={styles.chip}>
<TouchableOpacity style={styles.containerIcon} onPress={onPress}>
<TouchableOpacity style={styles.containerIcon} onPress={() => handleItemPress(item)}>
<Image
resizeMode="cover"
source={R.images.icCancel}
......@@ -113,7 +51,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
visible={visible}
animationType="slide"
transparent={true}
onRequestClose={onClose}>
onRequestClose={handleCancel}>
<View style={styles.overlay}>
<View style={styles.modalContainer}>
<ScrollView showsVerticalScrollIndicator={false}>
......@@ -126,6 +64,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
title="Tiêu đề"
required
value={formData.title}
onChangeText={(value) => updateFormData('title', value)}
containerMarginBottom={10}
/>
......@@ -133,6 +72,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
title="Mô tả"
required
value={formData.content}
onChangeText={(value) => updateFormData('content', value)}
containerMarginBottom={10}
fontFamily={R.fonts.fontMedium}
titleFontSize={R.fontsize.fontSizeContent}
......@@ -156,7 +96,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
height={35}
items={items}
placeholder="Công việc theo văn bản"
onSelect={item => console.log('Bạn đã chọn:', item)}
onSelect={item => handleDropdownSelect(item, 'category')}
/>
</View>
<Text style={[styles.text_2, {marginBottom: 3}]}>
......@@ -194,7 +134,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
height={35}
items={items}
placeholder="Công việc theo văn bản"
onSelect={item => console.log('Bạn đã chọn:', item)}
onSelect={item => handleDropdownSelect(item, 'document')}
/>
</View>
<Text style={[styles.text_2, {marginBottom: 3}]}>
......@@ -217,7 +157,8 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
<TextField
title="Ngày đến hạn"
required
value={formData.title}
value={formData.deadline}
onChangeText={(value) => updateFormData('deadline', value)}
containerMarginBottom={10}
/>
......@@ -238,7 +179,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
<Dropdown
height={35}
items={items}
onSelect={item => console.log('Bạn đã chọn:', item)}
onSelect={item => handleDropdownSelect(item, 'supervisor')}
/>
</View>
<Text style={[styles.text_2, {marginBottom: 3}]}>
......@@ -275,7 +216,7 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
<Dropdown
height={35}
items={items}
onSelect={item => console.log('Bạn đã chọn:', item)}
onSelect={item => handleDropdownSelect(item, 'implementer')}
/>
</View>
<Text style={[styles.text_2, {marginBottom: 3}]}>
......@@ -327,4 +268,4 @@ const AddWorkModal = ({visible, onClose, onSave}) => {
);
};
export default AddWorkModal;
export default AddWorkModalView;
import AddMonitoringModal from './view';
import React, {useState} from 'react';
import AddMonitoringModalView from './view';
const AddMonitoringModal = ({visible, onClose, onSave}) => {
const [formData, setFormData] = useState({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
const [dataList, setDataList] = useState([
{id: 1, name: 'Nguyễn Minh Đức'},
{id: 2, name: 'Trần Văn Hùng'},
{id: 3, name: 'Lê Thị Mai'},
{id: 4, name: 'Phạm Quốc Khánh'},
{id: 5, name: 'Hoàng Anh Tuấn'},
{id: 6, name: 'Vũ Thị Hằng'},
{id: 7, name: 'Ngô Văn Nam'},
{id: 8, name: 'Đinh Thị Lan'},
{id: 9, name: 'Bùi Văn Phúc'},
{id: 10, name: 'Lý Thị Hoa'},
{id: 11, name: 'Phan Minh Hoàng'},
{id: 12, name: 'Tạ Thị Hương'},
{id: 13, name: 'Đoàn Văn Dũng'},
{id: 14, name: 'Nguyễn Thị Vân'},
{id: 15, name: 'Trương Văn Long'},
{id: 16, name: 'Mai Thị Ngọc'},
{id: 17, name: 'Huỳnh Quốc Việt'},
{id: 18, name: 'Lâm Thị Thu'},
{id: 19, name: 'Nguyễn Hữu Tài'},
{id: 20, name: 'Phạm Thị Kim'},
]);
const [selectedItems, setSelectedItems] = useState([]);
const updateFormData = (field, value) => {
setFormData(prev => ({...prev, [field]: value}));
};
const handleSave = () => {
if (formData.title.trim() && formData.content.trim()) {
const workData = {
...formData,
selectedImplementers: selectedItems,
type: 'monitoring', // Đánh dấu đây là công việc giám sát
};
onSave(workData);
resetForm();
} else {
alert('Vui lòng điền đầy đủ thông tin bắt buộc');
}
};
const resetForm = () => {
setFormData({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
setSelectedItems([]);
};
const handleClose = () => {
resetForm();
onClose();
};
const handleSelectItem = item => {
const isSelected = selectedItems.some(selected => selected.id === item.id);
if (isSelected) {
setSelectedItems(prev => prev.filter(selected => selected.id !== item.id));
} else {
setSelectedItems(prev => [...prev, item]);
}
};
const handleRemoveItem = itemId => {
setSelectedItems(prev => prev.filter(item => item.id !== itemId));
};
return (
<AddMonitoringModalView
visible={visible}
formData={formData}
dataList={dataList}
selectedItems={selectedItems}
updateFormData={updateFormData}
handleSave={handleSave}
handleClose={handleClose}
handleSelectItem={handleSelectItem}
handleRemoveItem={handleRemoveItem}
/>
);
};
export default AddMonitoringModal;
import React, {useState} from 'react';
import React from 'react';
import {
Modal,
View,
......@@ -15,92 +15,18 @@ import TextMulti from '../../../components/Input/TextMulti';
import Dropdown from '../../../components/DropdownAlert/Dropdown';
import Button from '../../../components/Button';
const AddMonitoringModal = ({visible, onClose, onSave}) => {
const [formData, setFormData] = useState({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
const [dataList, setDataList] = useState([
{id: 1, name: 'Nguyễn Minh Đức'},
{id: 2, name: 'Trần Văn Hùng'},
{id: 3, name: 'Lê Thị Mai'},
{id: 4, name: 'Phạm Quốc Khánh'},
{id: 5, name: 'Hoàng Anh Tuấn'},
{id: 6, name: 'Vũ Thị Hằng'},
{id: 7, name: 'Ngô Văn Nam'},
{id: 8, name: 'Đinh Thị Lan'},
{id: 9, name: 'Bùi Văn Phúc'},
{id: 10, name: 'Lý Thị Hoa'},
{id: 11, name: 'Phan Minh Hoàng'},
{id: 12, name: 'Tạ Thị Hương'},
{id: 13, name: 'Đoàn Văn Dũng'},
{id: 14, name: 'Nguyễn Thị Vân'},
{id: 15, name: 'Trương Văn Long'},
{id: 16, name: 'Mai Thị Ngọc'},
{id: 17, name: 'Huỳnh Quốc Việt'},
{id: 18, name: 'Lâm Thị Thu'},
{id: 19, name: 'Nguyễn Hữu Tài'},
{id: 20, name: 'Phạm Thị Kim'},
]);
const [selectedItems, setSelectedItems] = useState([]);
const updateFormData = (field, value) => {
setFormData(prev => ({...prev, [field]: value}));
};
const handleSave = () => {
if (formData.title.trim() && formData.content.trim()) {
const workData = {
...formData,
selectedImplementers: selectedItems,
type: 'monitoring', // Đánh dấu đây là công việc giám sát
};
onSave(workData);
resetForm();
} else {
alert('Vui lòng điền đầy đủ thông tin bắt buộc');
}
};
const resetForm = () => {
setFormData({
title: '',
content: '',
category: null,
responsible: null,
deadline: null,
assignee: null,
implementer: null,
attachments: [],
});
setSelectedItems([]);
};
const handleClose = () => {
resetForm();
onClose();
};
const handleSelectItem = item => {
const isSelected = selectedItems.some(selected => selected.id === item.id);
if (isSelected) {
setSelectedItems(prev => prev.filter(selected => selected.id !== item.id));
} else {
setSelectedItems(prev => [...prev, item]);
}
};
const handleRemoveItem = itemId => {
setSelectedItems(prev => prev.filter(item => item.id !== itemId));
};
const AddMonitoringModalView = props => {
const {
visible,
formData,
dataList,
selectedItems,
updateFormData,
handleSave,
handleClose,
handleSelectItem,
handleRemoveItem,
} = props;
const renderItem = ({item}) => {
const isSelected = selectedItems.some(selected => selected.id === item.id);
......@@ -268,4 +194,4 @@ const AddMonitoringModal = ({visible, onClose, onSave}) => {
);
};
export default AddMonitoringModal;
export default AddMonitoringModalView;
......@@ -37,21 +37,21 @@ const styles = StyleSheet.create({
justifyContent: 'center',
borderColor: R.colors.grayBorderInputTextHeader,
},
container_tab_view:{
marginVertical:5
container_tab_view: {
marginVertical: 5,
},
item_tab_view:{
backgroundColor: R.colors.gray,
marginHorizontal: 5,
borderRadius: 10,
width: 107,
justifyContent: 'center',
alignItems: 'center',
item_tab_view: {
backgroundColor: R.colors.gray,
marginHorizontal: 5,
borderRadius: 10,
width: 107,
justifyContent: 'center',
alignItems: 'center',
},
active_tab_view:{
active_tab_view: {
backgroundColor: R.colors.blue,
},
text_tab_view:{
text_tab_view: {
color: R.colors.white,
fontWeight: '400',
fontFamily: R.fonts.fontRegular,
......
......@@ -39,7 +39,7 @@ const ListWorkView = props => {
onReportAction,
onApprovalAction,
getStatusColor,
getButtonsForStatus
getButtonsForStatus,
} = props;
const renderTabView = () => {
......@@ -143,61 +143,80 @@ const ListWorkView = props => {
);
};
return (
<View style={styles.container}>
<Header title={'Danh sách công việc'} isBack />
<View style={styles.body}>
{renderTabView()}
const renderCard = () => {
return (
<View style={styles.card}>
<TouchableOpacity style={styles.btnCard}>
<Text style={styles.text}>Hc k 2, Năm 2025</Text>
</TouchableOpacity>
</View>
);
};
<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>
</TouchableOpacity>
const renderFilter = () => {
return (
<View style={styles.box_3}>
<View style={styles.searchBox}>
<Image source={R.images.icSearch} style={{width: 20, height: 20}} />
<View style={{flex: 1, padding: 0, margin: 0, height: 30}}>
<TextInput
placeholder="Tìm kiếm"
style={[styles.text, {height: 30, padding: 0, marginRight: 15}]}
value={searchQuery}
onChangeText={setSearchQuery}
/>
</View>
</View>
<View style={{flex: 0.1}}></View>
<View style={styles.box_3}>
<View style={styles.searchBox}>
<Image
source={R.images.icSearch}
style={{width: 20, height: 20}}
/>
<View style={{flex: 1 , padding:0 , margin:0, height:30}}>
<TextInput
placeholder="Tìm kiếm"
style={[styles.text, {height:30 , padding:0, marginRight:15}]}
value={searchQuery}
onChangeText={setSearchQuery}
/>
</View>
</View>
<View style={{flex: 0.1}}></View>
<View style={{flex: 1}}>
<Dropdown title={'Tìm kiếm'} height={30} />
</View>
</View>
);
};
<View style={{flex: 1}}>
<Dropdown title={'Tìm kiếm'} height={30} />
</View>
</View>
<FlatList
data={dataList}
renderItem={renderListView}
keyExtractor={item => item.id.toString()}
showsVerticalScrollIndicator={false}
/>
const renderListItem = () => {
return (
<FlatList
data={dataList}
renderItem={renderListView}
keyExtractor={item => item.id.toString()}
showsVerticalScrollIndicator={false}
/>
);
};
const renderBody = () =>{
return (
<View style={styles.body}>
{renderTabView()}
{renderCard()}
<View style={{marginBottom: 15, flex: 1}}>
{renderFilter()}
{renderListItem()}
</View>
</View>
)
}
return (
<View style={styles.container}>
<Header title={'Danh sách công việc'} isBack />
{renderBody()}
{shouldShowFAB && (
<FAB>
<SubButton
onPress={onAddWork}
label={currentTabKey === ROLE.ASSIGNEE ? "Tạo công việc" : "Tạo giám sát"}
label={
currentTabKey === ROLE.ASSIGNEE ? 'Tạo công việc' : 'Tạo giám sát'
}
images={R.images.icMenuEdit}
backgroundColor={R.colors.blue}
/>
</FAB>
)}
<AddWorkModal
visible={modalDeliverToMeVisible}
onClose={onCloseDeliverToMeModal}
......
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