Commit 1f57d4df by tungnq

TODO: Tái cấu trúc component Dropdown để chấp nhận margin động và cải thiện…

TODO: Tái cấu trúc component Dropdown để chấp nhận margin động và cải thiện DetailListWorkMonitoring với xử lý báo cáo và nâng cấp các thành phần giao diện người dùng.
parent 63488e16
...@@ -15,7 +15,7 @@ const Dropdown = ({ ...@@ -15,7 +15,7 @@ const Dropdown = ({
onSelect, onSelect,
height, height,
backgroundColor, backgroundColor,
containerMarginBottom = 5,
// mới thêm // mới thêm
editable = true, editable = true,
disabledBackgroundColor = R.colors.blue1, disabledBackgroundColor = R.colors.blue1,
...@@ -49,7 +49,7 @@ const Dropdown = ({ ...@@ -49,7 +49,7 @@ const Dropdown = ({
const resolvedBorderColor = editable ? R.colors?.grayBorderInputTextHeader || '#ccc' : '#ddd'; const resolvedBorderColor = editable ? R.colors?.grayBorderInputTextHeader || '#ccc' : '#ddd';
return ( return (
<View style={styles.container}> <View style={[styles.container , {marginBottom:containerMarginBottom}]}>
{/* Header */} {/* Header */}
<TouchableOpacity <TouchableOpacity
activeOpacity={editable ? 0.7 : 1} activeOpacity={editable ? 0.7 : 1}
......
...@@ -344,7 +344,6 @@ const ListWork = props => { ...@@ -344,7 +344,6 @@ const ListWork = props => {
// Hiển thị dữ liệu sau khi chọn // Hiển thị dữ liệu sau khi chọn
const filterList = useMemo(() => { const filterList = useMemo(() => {
let base = dataList; let base = dataList;
console.log('Dữ liệu danh sách đầu vào', base);
// Lọc theo tab role // Lọc theo tab role
if (currentTabKey === ROLE.ASSIGNEE) { if (currentTabKey === ROLE.ASSIGNEE) {
......
import React, {useState} from 'react'; import React, {useState} from 'react';
import DetailListWorkMonitoringView from './view'; import DetailListWorkMonitoringView from './view';
const DetailListWorkMonitoring = (props) => { const DetailListWorkMonitoring = props => {
const {route} = props; const {route} = props;
const workItem = route?.params?.workItem || {}; const workItem = route?.params?.workItem || {};
const [showRequestReport, setShowRequyestReport] = useState(false);
const [data, setData] = useState({ const [data, setData] = useState({
id: workItem.id || 1, id: workItem.id || 1,
title: workItem.title || 'Công việc giám sát', title: workItem.title || 'Công việc giám sát',
...@@ -31,8 +32,19 @@ const DetailListWorkMonitoring = (props) => { ...@@ -31,8 +32,19 @@ const DetailListWorkMonitoring = (props) => {
}, },
], ],
document: workItem.document || 'Văn bản công việc giám sát', document: workItem.document || 'Văn bản công việc giám sát',
content: workItem.content || 'Nội dung công việc đang được giám sát và theo dõi tiến độ thực hiện', content:
workItem.content ||
'Nội dung công việc đang được giám sát và theo dõi tiến độ thực hiện',
}); });
const handleReportPress = () => {
if (data.status === 'Đang thực hiện') {
setShowRequyestReport(true);
}else{
setShowRequyestReport(false);
}
};
const [dataList, setDataList] = useState([ const [dataList, setDataList] = useState([
{id: 1, name: 'Nguyễn Minh Đức'}, {id: 1, name: 'Nguyễn Minh Đức'},
...@@ -48,7 +60,8 @@ const DetailListWorkMonitoring = (props) => { ...@@ -48,7 +60,8 @@ const DetailListWorkMonitoring = (props) => {
title: 'Báo cáo tiến độ lần 1', title: 'Báo cáo tiến độ lần 1',
time: '14:30', time: '14:30',
date: '2025-09-10', date: '2025-09-10',
content: 'Báo cáo tiến độ thực hiện công việc được giao. Hiện tại đã hoàn thành 60% công việc theo kế hoạch.', content:
'Báo cáo tiến độ thực hiện công việc được giao. Hiện tại đã hoàn thành 60% công việc theo kế hoạch.',
fileTitle: 'Báo cáo tiến độ - BC001', fileTitle: 'Báo cáo tiến độ - BC001',
responder: [ responder: [
{ {
...@@ -57,7 +70,8 @@ const DetailListWorkMonitoring = (props) => { ...@@ -57,7 +70,8 @@ const DetailListWorkMonitoring = (props) => {
code: '12345', code: '12345',
time: '14:30', time: '14:30',
date: '2025-09-10', date: '2025-09-10',
content: 'Đã hoàn thành phần phân tích yêu cầu và đang triển khai thiết kế hệ thống.', content:
'Đã hoàn thành phần phân tích yêu cầu và đang triển khai thiết kế hệ thống.',
}, },
], ],
}, },
...@@ -66,7 +80,8 @@ const DetailListWorkMonitoring = (props) => { ...@@ -66,7 +80,8 @@ const DetailListWorkMonitoring = (props) => {
title: 'Báo cáo tiến độ lần 2', title: 'Báo cáo tiến độ lần 2',
time: '16:00', time: '16:00',
date: '2025-09-12', date: '2025-09-12',
content: 'Cập nhật tiến độ thực hiện. Đã hoàn thành 80% công việc, dự kiến hoàn thành đúng hạn.', content:
'Cập nhật tiến độ thực hiện. Đã hoàn thành 80% công việc, dự kiến hoàn thành đúng hạn.',
fileTitle: 'Báo cáo tiến độ - BC002', fileTitle: 'Báo cáo tiến độ - BC002',
responder: [ responder: [
{ {
...@@ -75,7 +90,8 @@ const DetailListWorkMonitoring = (props) => { ...@@ -75,7 +90,8 @@ const DetailListWorkMonitoring = (props) => {
code: '12345', code: '12345',
time: '16:00', time: '16:00',
date: '2025-09-12', date: '2025-09-12',
content: 'Đã hoàn thành phần thiết kế và đang trong giai đoạn kiểm thử hệ thống.', content:
'Đã hoàn thành phần thiết kế và đang trong giai đoạn kiểm thử hệ thống.',
}, },
], ],
}, },
...@@ -86,6 +102,8 @@ const DetailListWorkMonitoring = (props) => { ...@@ -86,6 +102,8 @@ const DetailListWorkMonitoring = (props) => {
data={data} data={data}
dataList={dataList} dataList={dataList}
dataReport={dataReport} dataReport={dataReport}
onHandleReportPress={handleReportPress}
setShowRequyestReport={setShowRequyestReport}
/> />
); );
}; };
......
import { StyleSheet } from 'react-native'; import {StyleSheet} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
...@@ -38,6 +38,62 @@ const styles = StyleSheet.create({ ...@@ -38,6 +38,62 @@ const styles = StyleSheet.create({
paddingHorizontal: 10, paddingHorizontal: 10,
borderRadius: 5, borderRadius: 5,
}, },
textChip: {
fontSize: R.fontsize.fontSizeContent,
fontWeight: '400',
fontFamily: R.fonts.fontRegular,
color: R.colors.blueTextChip,
},
containerContent: {
borderWidth: 1,
borderRadius: 10,
padding: 10,
marginVertical: 3,
borderColor: R.colors.grayBorderInputTextHeader,
},
flatListSelect: {
flexDirection: 'row',
flexWrap: 'wrap',
},
chip: {
flexDirection: 'row',
alignItems: 'center',
paddingLeft: 10,
paddingRight: 10,
height: 25,
borderRadius: 10,
marginBottom: 10,
marginRight: 5,
backgroundColor: R.colors.blue2,
alignSelf: 'flex-start',
},
imageIcon: {
width: 15,
height: 15,
},
containerIcon: {
marginRight: 2,
},
attachmentContainer: {
borderWidth: 1,
borderColor: R.colors.blue,
borderRadius: 10,
padding: 20,
alignItems: 'center',
marginTop:3,
marginBottom: 50,
},
uploadIcon: {
width: 23,
height: 28,
tintColor: R.colors.blue,
marginBottom: 5,
},
attachmentText: {
fontSize: R.fontsize.fontSizeContent,
color: R.colors.blue,
fontWeight: '500',
},
sizedBox: { sizedBox: {
height: 10, height: 10,
}, },
...@@ -62,4 +118,4 @@ const styles = StyleSheet.create({ ...@@ -62,4 +118,4 @@ const styles = StyleSheet.create({
}, },
}); });
export default styles; export default styles;
\ No newline at end of file
...@@ -14,13 +14,13 @@ import SubButton from '../../../components/FAB/sub_button'; ...@@ -14,13 +14,13 @@ import SubButton from '../../../components/FAB/sub_button';
import R from '../../../assets/R'; import R from '../../../assets/R';
import Header from '../../../components/Header/Header'; import Header from '../../../components/Header/Header';
import Dropdown from '../../../components/DropdownAlert/Dropdown'; import Dropdown from '../../../components/DropdownAlert/Dropdown';
import Button from '../../../components/Button';
const DetailListWorkMonitoringView = props => { const DetailListWorkMonitoringView = props => {
LogBox.ignoreLogs(['VirtualizedLists should never be nested']); LogBox.ignoreLogs(['VirtualizedLists should never be nested']);
const {data, dataList, dataReport} = props; const {data, dataList, dataReport, onHandleReportPress, setShowRequestReport} = props;
const [showApprovalModal, setShowApprovalModal] = useState(false);
const [showRequestEditModal, setShowRequestEditModal] = useState(false);
const getColor = status => { const getColor = status => {
switch (status) { switch (status) {
case 'Chờ duyệt': case 'Chờ duyệt':
...@@ -37,62 +37,183 @@ const DetailListWorkMonitoringView = props => { ...@@ -37,62 +37,183 @@ const DetailListWorkMonitoringView = props => {
return R.colors.gray; return R.colors.gray;
} }
}; };
const shouldShowFAB = () => {
return data.status === 'Đang thực hiện';
};
const renderReportItem = ({item}) => { const renderItem_1 = ({item, onPress}) => {
return ( return (
<View style={styles.containerCard}> <View style={styles.chip}>
<View style={{flexDirection: 'row', marginBottom: 3}}> <TouchableOpacity
<Text style={[styles.text, {color: R.colors.blue}]}> style={styles.containerIcon}
{item.title} -{' '} onPress={() => handleItemPress(item)}>
</Text> <Image
<Text style={[styles.text, {color: R.colors.blue}]}> resizeMode="cover"
{item.time}{' '} source={R.images.icCancel}
style={styles.imageIcon}
tintColor={R.colors.blue}
/>
</TouchableOpacity>
<Text style={styles.textChip}> {`${item.id}, ${item.name}`}</Text>
</View>
);
};
const renderButton = () => {
return (
<View style={styles.btnRegister2}>
<Button
title={'Cập nhật thông tin công việc'}
backgroundColor={R.colors.blue}
textColor={R.colors.white}
onPress={() => handleReportPress()}
fontSize={R.sizes.sm}
fontFamily={R.fonts.fontMedium}
height={35}
containerStyle={{paddingHorizontal: 15, borderRadius: 10}}
/>
</View>
);
};
const renderBody = item => {
return (
<View style={styles.body}>
<Text
style={[
styles.text,
{fontSize: R.fontsize.fontSizeSubTitle, marginBottom: 3},
]}>
{data.title}
</Text>
<Text style={[styles.text, {marginBottom: 3, textAlign: 'right'}]}>
Trng thái:{' '}
<Text style={{color: getColor(data.status)}}>{data.status}</Text>
</Text>
<Text style={[styles.text, {marginBottom: 3}]}>
Công vic thuc văn bn:{' '}
<Text style={[styles.sub_text, {color: R.colors.blue}]}>
{data.document}
</Text> </Text>
<Text style={[styles.text, {color: R.colors.blue}]}> </Text>
{item.date} <Text style={[styles.text, {marginBottom: 3}]}>Ni dung công vic</Text>
<View style={styles.containerContent}>
<Text style={[styles.text, {color: R.colors.gray}]}>
{data.content}
</Text> </Text>
</View> </View>
<Text style={styles.text}>{item.content}</Text> <Text style={styles.text}>
<View style={styles.sizedBox} /> Ngày đến hn <Text style={{color: R.colors.red}}>*</Text>
<View style={styles.containerText}> </Text>
<Text style={styles.text}>Tp đính kèm: </Text> <View style={styles.containerContent}>
<Text style={[styles.text, {color: R.colors.blue}]}> <Text style={styles.text}>{data.deadline}</Text>
{item.fileTitle} </View>
<View style={styles.containerDropDown}>
<Text
style={[
styles.text,
{
marginBottom: 3,
},
]}>
Người theo dõi
</Text> </Text>
<Dropdown
height={35}
items={item}
placeholder="Công việc theo văn bản"
/>
</View> </View>
<View style={styles.sizedBox} /> <Text style={[styles.text, {marginBottom: 3}]}>
Danh sách người theo dõi đã chn
</Text>
<FlatList <FlatList
data={item.responder} data={dataList}
renderItem={renderResponderItem} renderItem={({item}) => renderItem_1({item, onPress: () => {}})}
keyExtractor={item => item.id.toString()} keyExtractor={(item, index) =>
item.id?.toString() || index.toString()
}
numColumns={2}
style={{maxHeight: 150}}
showsVerticalScrollIndicator={true}
columnWrapperStyle={styles.flatListSelect}
nestedScrollEnabled={true}
scrollEnabled={true}
/> />
</View>
);
};
const renderResponderItem = ({item}) => { <View style={styles.containerDropDown}>
return ( <Text
<View style={styles.containerCard}> style={[
<View style={{flexDirection: 'row', marginBottom: 3}}> styles.text,
<Text style={[styles.text, {color: R.colors.blue}]}> {
{item.name} - {item.code} -{' '} marginBottom: 3,
</Text> },
<Text style={[styles.text, {color: R.colors.blue}]}> ]}>
{item.time}{' '} Người thc hin công vic
</Text> </Text>
<Text style={[styles.text, {color: R.colors.blue}]}> <Dropdown height={35} items={item} />
{item.date} </View>
<Text style={[styles.text, {marginBottom: 3}]}>
Danh sách người thc hin công vic đã chn
</Text>
<FlatList
data={dataList}
renderItem={({item}) => renderItem_1({item, onPress: () => {}})}
keyExtractor={(item, index) =>
item.id?.toString() || index.toString()
}
numColumns={2}
style={{maxHeight: 150}}
showsVerticalScrollIndicator={true}
columnWrapperStyle={styles.flatListSelect}
nestedScrollEnabled={true}
scrollEnabled={true}
/>
<View style={styles.containerDropDown}>
<Text
style={[
styles.text,
{
marginBottom: 3,
},
]}>
Th
</Text> </Text>
<Dropdown height={35} items={item} />
</View> </View>
<Text style={styles.text}>{item.content}</Text> <Text style={[styles.text, {marginBottom: 3}]}>
</View> Danh sách th đã chn
); </Text>
}; <FlatList
data={dataList}
renderItem={({item}) => renderItem_1({item, onPress: () => {}})}
keyExtractor={(item, index) =>
item.id?.toString() || index.toString()
}
numColumns={2}
style={{maxHeight: 150}}
showsVerticalScrollIndicator={true}
columnWrapperStyle={styles.flatListSelect}
nestedScrollEnabled={true}
scrollEnabled={true}
/>
const renderImplementerItem = ({item}) => { <Text style={[styles.text, {marginBottom: 3}]}>Tài liu đính kèm</Text>
return ( <TouchableOpacity style={styles.containerFile}>
<View style={styles.containerText}> <Text style={[styles.text, {fontSize: R.sizes.xs}]}>
<Text style={styles.text}>{item.name}</Text> Quyết định thông báo đào to - QD347583
</Text>
<Image source={R.images.icDownload} style={styles.image} />
</TouchableOpacity>
<TouchableOpacity style={styles.attachmentContainer}>
<Image source={R.images.icDocument} style={styles.uploadIcon} />
<Text style={styles.attachmentText}>Thêm tài liu</Text>
</TouchableOpacity>
{renderButton()}
</View> </View>
); );
}; };
...@@ -100,73 +221,21 @@ const DetailListWorkMonitoringView = props => { ...@@ -100,73 +221,21 @@ const DetailListWorkMonitoringView = props => {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Header title={'Chi tiết công việc giám sát'} /> <Header title={'Chi tiết công việc giám sát'} />
<ScrollView style={styles.body}> <ScrollView showsVerticalScrollIndicator={false}>
<View style={styles.containerCard}> {renderBody()}
<View
style={[
styles.containerText,
{backgroundColor: getColor(data.status)},
]}>
<Text style={[styles.text, {color: R.colors.white}]}>
{data.status}
</Text>
</View>
<View style={styles.sizedBox} />
<Text style={styles.text}>{data.title}</Text>
<View style={styles.sizedBox} />
<View style={styles.containerText}>
<Text style={styles.text}>Ngày đến hn: </Text>
<Text style={[styles.text, {color: R.colors.blue}]}>
{data.deadline}
</Text>
</View>
<View style={styles.sizedBox} />
<View style={styles.containerText}>
<Text style={styles.text}>Người thc hin: </Text>
</View>
<FlatList
data={data.implementer}
renderItem={renderImplementerItem}
keyExtractor={item => item.id.toString()}
/>
<View style={styles.sizedBox} />
<View style={styles.containerText}>
<Text style={styles.text}>Thuc văn bn: </Text>
<Text style={[styles.text, {color: R.colors.blue}]}>
{data.document}
</Text>
</View>
<View style={styles.sizedBox} />
<Text style={styles.text}>{data.content}</Text>
</View>
<View style={styles.containerCard}>
<Text style={styles.text}>Lch s báo cáo</Text>
<View style={styles.sizedBox} />
<FlatList
data={dataReport}
renderItem={renderReportItem}
keyExtractor={item => item.id.toString()}
/>
</View>
</ScrollView> </ScrollView>
<FAB {shouldShowFAB() && (
style={styles.fab} <FAB>
onPress={() => console.log('FAB pressed for monitoring actions')}> <SubButton
<SubButton onPress={onHandleReportPress}
onPress={() => setShowApprovalModal(true)} label={'Yêu cầu báo cáo'}
title={'Phê duyệt'} images={R.images.icEdit}
/> backgroundColor={R.colors.orange}
<SubButton />
onPress={() => setShowRequestEditModal(true)} </FAB>
title={'Yêu cầu chỉnh sửa'} )}
/>
<SubButton
onPress={() => console.log('Request report')}
title={'Yêu cầu báo cáo'}
/>
</FAB>
</View> </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