Commit fb8e80c7 by tungnq

IMPORTANT: Bổ sung thư viện json- server và tái cấu trúc một số file

parent 5fe2ad7c
{}
\ No newline at end of file
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
"ios": "react-native run-ios", "ios": "react-native run-ios",
"lint": "eslint .", "lint": "eslint .",
"start": "react-native start", "start": "react-native start",
"test": "jest" "test": "jest",
"server": "json-server --watch db/database.json --port 3000"
}, },
"dependencies": { "dependencies": {
"@react-native-community/async-storage": "^1.12.1", "@react-native-community/async-storage": "^1.12.1",
...@@ -85,6 +86,7 @@ ...@@ -85,6 +86,7 @@
"babel-jest": "^29.6.3", "babel-jest": "^29.6.3",
"eslint": "^8.19.0", "eslint": "^8.19.0",
"jest": "^29.6.3", "jest": "^29.6.3",
"json-server": "^1.0.0-beta.3",
"prettier": "2.8.8", "prettier": "2.8.8",
"react-native-svg-transformer": "^1.5.1", "react-native-svg-transformer": "^1.5.1",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
......
...@@ -9,7 +9,6 @@ import { ...@@ -9,7 +9,6 @@ import {
} from 'react-native'; } from 'react-native';
import R from '../assets/R'; import R from '../assets/R';
const Button = props => { const Button = props => {
const { const {
title, title,
...@@ -43,11 +42,11 @@ const Button = props => { ...@@ -43,11 +42,11 @@ const Button = props => {
{ {
width: width, width: width,
height: height, height: height,
paddingHorizontal:paddingHorizontal, paddingHorizontal: paddingHorizontal,
paddingVertical:paddingVertical, paddingVertical: paddingVertical,
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
borderRadius: borderRadius, borderRadius: borderRadius,
marginRight: marginRight marginRight: marginRight,
}, },
{...containerStyle}, {...containerStyle},
]} ]}
...@@ -55,14 +54,18 @@ const Button = props => { ...@@ -55,14 +54,18 @@ const Button = props => {
onPress={onPress}> onPress={onPress}>
<View <View
style={{ style={{
flex:1, flex: 1,
justifyContent:'space-around', justifyContent: 'space-around',
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
}}> }}>
{iconLeft && <Image source={iconLeft} tintColor={tintColorLeft} style={iconStyleLeft} />} {iconLeft && (
<Image
source={iconLeft}
tintColor={tintColorLeft}
style={iconStyleLeft}
/>
)}
<Text <Text
style={[ style={[
{ {
...@@ -77,9 +80,9 @@ const Button = props => { ...@@ -77,9 +80,9 @@ const Button = props => {
]}> ]}>
{title} {title}
</Text> </Text>
{icon&& <Image source={icon} style={iconStyle} />} {icon && <Image source={icon} style={iconStyle} />}
</View> </View>
</TouchableOpacity> </TouchableOpacity>
); );
}; };
export default Button ; export default Button;
import React, { useState } from 'react'; import React, {useState} from 'react';
import {Text, View, StyleSheet} from 'react-native'; import {Text, View, StyleSheet} from 'react-native';
import ClassActivityView from './view'; import ClassActivityView from './view';
const ClassActivity = (props) => { const ClassActivity = props => {
const [dataList , setDataList] = useState([ const [dataList, setDataList] = useState([
{ {
id:'1', id: '1',
class_activity:'ATTT2024.1', class_activity: 'ATTT2024.1',
course:'2024', course: '2024',
training_system:'CQUI', training_system: 'CQUI',
class_by_course:'ATTT2024.1', class_by_course: 'ATTT2024.1',
science:'MMT&TT', science: 'MMT&TT',
class_leader:'Nguyễn Minh Đức', class_leader: 'Nguyễn Minh Đức',
}, },
{ {
"id": "2", id: '2',
"class_activity": "IS2024.IP57.1", class_activity: 'IS2024.IP57.1',
"course": "2024", course: '2024',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "IS2024.IP57.1", class_by_course: 'IS2024.IP57.1',
"science": "CNTT", science: 'CNTT',
"class_leader": "Trần Thị Hương" class_leader: 'Trần Thị Hương',
}, },
{ {
"id": "3", id: '3',
"class_activity": "BGF197.47.1", class_activity: 'BGF197.47.1',
"course": "2023", course: '2023',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "BGF197.47.1", class_by_course: 'BGF197.47.1',
"science": "Kinh tế", science: 'Kinh tế',
"class_leader": "Phạm Văn Nam" class_leader: 'Phạm Văn Nam',
}, },
{ {
"id": "4", id: '4',
"class_activity": "CS301.12.3", class_activity: 'CS301.12.3',
"course": "2022", course: '2022',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "CS301.12.3", class_by_course: 'CS301.12.3',
"science": "Khoa học Máy tính", science: 'Khoa học Máy tính',
"class_leader": "Lê Thị Mai" class_leader: 'Lê Thị Mai',
}, },
{ {
"id": "5", id: '5',
"class_activity": "MA205.C33.2", class_activity: 'MA205.C33.2',
"course": "2025", course: '2025',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "MA205.C33.2", class_by_course: 'MA205.C33.2',
"science": "Toán", science: 'Toán',
"class_leader": "Nguyễn Văn Hùng" class_leader: 'Nguyễn Văn Hùng',
}, },
{ {
"id": "6", id: '6',
"class_activity": "ENG101.P2.5", class_activity: 'ENG101.P2.5',
"course": "2024", course: '2024',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "ENG101.P2.5", class_by_course: 'ENG101.P2.5',
"science": "Ngoại ngữ", science: 'Ngoại ngữ',
"class_leader": "Hoàng Thu Trang" class_leader: 'Hoàng Thu Trang',
}, },
{ {
"id": "7", id: '7',
"class_activity": "PHYS202.3A.1", class_activity: 'PHYS202.3A.1',
"course": "2023", course: '2023',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "PHYS202.3A.1", class_by_course: 'PHYS202.3A.1',
"science": "Vật lý", science: 'Vật lý',
"class_leader": "Vũ Đức Anh" class_leader: 'Vũ Đức Anh',
}, },
{ {
"id": "8", id: '8',
"class_activity": "CHEM101.12.2", class_activity: 'CHEM101.12.2',
"course": "2025", course: '2025',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "CHEM101.12.2", class_by_course: 'CHEM101.12.2',
"science": "Hóa học", science: 'Hóa học',
"class_leader": "Đỗ Lan Phương" class_leader: 'Đỗ Lan Phương',
}, },
{ {
"id": "9", id: '9',
"class_activity": "BIO202.A1.1", class_activity: 'BIO202.A1.1',
"course": "2022", course: '2022',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "BIO202.A1.1", class_by_course: 'BIO202.A1.1',
"science": "Sinh học", science: 'Sinh học',
"class_leader": "Nguyễn Thị Ngọc" class_leader: 'Nguyễn Thị Ngọc',
}, },
{ {
"id": "10", id: '10',
"class_activity": "LAW303.L12.1", class_activity: 'LAW303.L12.1',
"course": "2024", course: '2024',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "LAW303.L12.1", class_by_course: 'LAW303.L12.1',
"science": "Luật", science: 'Luật',
"class_leader": "Phan Minh Tuấn" class_leader: 'Phan Minh Tuấn',
}, },
{ {
"id": "11", id: '11',
"class_activity": "HIS204.HB1.3", class_activity: 'HIS204.HB1.3',
"course": "2023", course: '2023',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "HIS204.HB1.3", class_by_course: 'HIS204.HB1.3',
"science": "Lịch sử", science: 'Lịch sử',
"class_leader": "Trần Văn Bình" class_leader: 'Trần Văn Bình',
}, },
{ {
"id": "12", id: '12',
"class_activity": "PSY101.PC2.1", class_activity: 'PSY101.PC2.1',
"course": "2025", course: '2025',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "PSY101.PC2.1", class_by_course: 'PSY101.PC2.1',
"science": "Tâm lý", science: 'Tâm lý',
"class_leader": "Ngô Thị Hạnh" class_leader: 'Ngô Thị Hạnh',
}, },
{ {
"id": "13", id: '13',
"class_activity": "ART203.AR3.2", class_activity: 'ART203.AR3.2',
"course": "2022", course: '2022',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "ART203.AR3.2", class_by_course: 'ART203.AR3.2',
"science": "Mỹ thuật", science: 'Mỹ thuật',
"class_leader": "Bùi Văn Sơn" class_leader: 'Bùi Văn Sơn',
}, },
{ {
"id": "14", id: '14',
"class_activity": "ECON305.EC2.1", class_activity: 'ECON305.EC2.1',
"course": "2024", course: '2024',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "ECON305.EC2.1", class_by_course: 'ECON305.EC2.1',
"science": "Kinh tế quốc tế", science: 'Kinh tế quốc tế',
"class_leader": "Nguyễn Thuỳ Dung" class_leader: 'Nguyễn Thuỳ Dung',
}, },
{ {
"id": "15", id: '15',
"class_activity": "MED401.MC1.1", class_activity: 'MED401.MC1.1',
"course": "2025", course: '2025',
"training_system": "CQUI", training_system: 'CQUI',
"class_by_course": "MED401.MC1.1", class_by_course: 'MED401.MC1.1',
"science": "Y học", science: 'Y học',
"class_leader": "Trần Quốc Việt" class_leader: 'Trần Quốc Việt',
}, },
{ {
"id": "16", id: '16',
"class_activity": "EDU202.ED5.2", class_activity: 'EDU202.ED5.2',
"course": "2023", course: '2023',
"training_system": "CLC", training_system: 'CLC',
"class_by_course": "EDU202.ED5.2", class_by_course: 'EDU202.ED5.2',
"science": "Giáo dục", science: 'Giáo dục',
"class_leader": "Lê Hoài Nam" class_leader: 'Lê Hoài Nam',
} },
]);
]) return <ClassActivityView dataList={dataList} setDataList={setDataList} />;
return (
<ClassActivityView dataList={dataList}
setDataList={setDataList}
/>
);
}; };
export default ClassActivity; export default ClassActivity;
...@@ -2,7 +2,7 @@ import React, {useState} from 'react'; ...@@ -2,7 +2,7 @@ import React, {useState} from 'react';
import {Text, View, StyleSheet} from 'react-native'; import {Text, View, StyleSheet} from 'react-native';
import DetailStudentView from './view'; import DetailStudentView from './view';
const DetailStudent = (props) => { const DetailStudent = props => {
const [student, setStudent] = useState({ const [student, setStudent] = useState({
name: 'Nguyễn Minh Đức', name: 'Nguyễn Minh Đức',
code_student: '2598671', code_student: '2598671',
...@@ -11,49 +11,44 @@ const DetailStudent = (props) => { ...@@ -11,49 +11,44 @@ const DetailStudent = (props) => {
tele_phone: '0123456789', tele_phone: '0123456789',
gender: 'Nam', gender: 'Nam',
average_score: '8.5', average_score: '8.5',
latest_semester_average_score:'8.5', latest_semester_average_score: '8.5',
training_average_score:'100', training_average_score: '100',
type:[ type: [
{ {
id:1, id: 1,
name:'Chuẩn đầu ra NN', name: 'Chuẩn đầu ra NN',
status:true, status: true,
}, },
{ {
id:2, id: 2,
name:'Chuẩn trình NN', name: 'Chuẩn trình NN',
status:true, status: true,
}, },
{ {
id:3, id: 3,
name:'Quá tiến độ học tập', name: 'Quá tiến độ học tập',
status:false, status: false,
}, },
{ {
id:4, id: 4,
name:'Nợ học phí', name: 'Nợ học phí',
status:false, status: false,
}, },
] ],
}); });
const handleCheckboxChange = (itemId, newValue) => { const handleCheckboxChange = (itemId, newValue) => {
setStudent(prevStudent => { setStudent(prevStudent => {
// Sao chép danh sách type cũ
const updatedTypes = prevStudent.type.map(item => { const updatedTypes = prevStudent.type.map(item => {
if (item.id === itemId) { if (item.id === itemId) {
// Nếu id trùng -> tạo object mới với status cập nhật
return { return {
...item, ...item,
status: newValue, status: newValue,
}; };
} else { } else {
// Nếu không trùng -> giữ nguyên item
return item; return item;
} }
}); });
// Trả về student mới với type đã cập nhật
return { return {
...prevStudent, ...prevStudent,
type: updatedTypes, type: updatedTypes,
......
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../../../assets/R' import R from '../../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
}, },
containerCard:{ containerCard: {
marginHorizontal:15, marginHorizontal: 15,
marginVertical:5, marginVertical: 5,
borderRadius:10, borderRadius: 10,
}, },
card:{ card: {
borderBottomEndRadius:10, borderBottomEndRadius: 10,
borderBottomStartRadius:10, borderBottomStartRadius: 10,
paddingHorizontal:10, paddingHorizontal: 10,
paddingVertical:5, paddingVertical: 5,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
shadowColor:R.colors.black, shadowColor: R.colors.black,
shadowOffset:{width:0.5,height:2}, shadowOffset: {width: 0.5, height: 2},
shadowOpacity:Platform.OS === 'ios' ? 0.25 : 1, shadowOpacity: Platform.OS === 'ios' ? 0.25 : 1,
shadowRadius:2, shadowRadius: 2,
elevation:Platform.OS === 'ios' ? 1 : 2, elevation: Platform.OS === 'ios' ? 1 : 2,
}, },
containerText:{ containerText: {
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
marginBottom:5, marginBottom: 5,
}, },
containerTextItemLeft:{ containerTextItemLeft: {
alignItems:'flex-start', alignItems: 'flex-start',
justifyContent:'flex-start', justifyContent: 'flex-start',
width:'45%', width: '45%',
}, },
containerTextItemRight:{ containerTextItemRight: {
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
}, },
sizedBox:{ sizedBox: {
flex:3 flex: 3,
}, },
text:{ text: {
fontSize:R.sizes.sm, fontSize: R.sizes.sm,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
color:R.colors.black, color: R.colors.black,
textAlign:'center', textAlign: 'center',
},
containerSubText:{
flexDirection:'row',
marginBottom:5
}, },
containerSubTextItemLeft:{ containerSubText: {
}, flexDirection: 'row',
containerSubTextItemRight:{ marginBottom: 5,
}, },
textTitle:{ containerSubTextItemLeft: {},
fontSize:R.sizes.md, containerSubTextItemRight: {},
fontFamily:R.fonts.fontMedium, textTitle: {
fontWeight:'600', fontSize: R.sizes.md,
color:R.colors.blue, fontFamily: R.fonts.fontMedium,
marginHorizontal:15, fontWeight: '600',
color: R.colors.blue,
marginHorizontal: 15,
}, },
label:{ label: {
fontSize:R.sizes.sm, fontSize: R.sizes.sm,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
color:R.colors.black, color: R.colors.black,
}, },
checkboxContainer: { checkboxContainer: {
flexDirection: 'row', flexDirection: 'row',
...@@ -81,7 +79,6 @@ const styles = StyleSheet.create({ ...@@ -81,7 +79,6 @@ const styles = StyleSheet.create({
width: '50%', width: '50%',
marginBottom: 15, marginBottom: 15,
}, },
});
}) export default styles;
export default styles
...@@ -23,18 +23,23 @@ const DetailStudentView = props => { ...@@ -23,18 +23,23 @@ const DetailStudentView = props => {
return statusColors[status] || '#9E9E9E'; return statusColors[status] || '#9E9E9E';
}; };
const statusColor = getStatusColor(student.status); const statusColor = getStatusColor(student.status);
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Header title={'Nguyễn Minh Đức - 2598671'} isBack /> <Header title={'Nguyễn Minh Đức - 2598671'} isBack />
<View style={styles.body}> <View style={styles.body}>
<View style={[styles.card ,{marginHorizontal:15, marginTop:10 , borderRadius:10}]}> <View
style={[
styles.card,
{marginHorizontal: 15, marginTop: 10, borderRadius: 10},
]}>
<View style={styles.containerText}> <View style={styles.containerText}>
<View style={styles.containerTextItemLeft}> <View style={styles.containerTextItemLeft}>
<Text style={styles.text}>STC TL / STC CTDT 23 / 102</Text> <Text style={styles.text}>STC TL / STC CTDT 23 / 102</Text>
</View> </View>
<View style={styles.sizedBox}></View> <View style={styles.sizedBox}></View>
<View style={styles.containerTextItemRight}> <View style={styles.containerTextItemRight}>
<Text style={[styles.text]}>Tình trng: {' '}</Text> <Text style={[styles.text]}>Tình trng: </Text>
<Text style={[styles.text, {color: statusColor}]}> <Text style={[styles.text, {color: statusColor}]}>
{student.status} {student.status}
</Text> </Text>
...@@ -44,7 +49,7 @@ const DetailStudentView = props => { ...@@ -44,7 +49,7 @@ const DetailStudentView = props => {
<View style={styles.containerSubText}> <View style={styles.containerSubText}>
<View style={styles.containerSubTextItemLeft}> <View style={styles.containerSubTextItemLeft}>
<Text style={[styles.text]}> <Text style={[styles.text]}>
Ngày sinh: {' '} Ngày sinh:{' '}
<Text <Text
style={[ style={[
styles.text, styles.text,
...@@ -57,7 +62,7 @@ const DetailStudentView = props => { ...@@ -57,7 +62,7 @@ const DetailStudentView = props => {
<View style={styles.sizedBox}></View> <View style={styles.sizedBox}></View>
<View style={styles.containerSubTextItemRight}> <View style={styles.containerSubTextItemRight}>
<Text style={[styles.text]}> <Text style={[styles.text]}>
SDT: {' '} SDT:{' '}
<Text <Text
style={[ style={[
styles.text, styles.text,
...@@ -72,7 +77,7 @@ const DetailStudentView = props => { ...@@ -72,7 +77,7 @@ const DetailStudentView = props => {
<View style={styles.containerSubText}> <View style={styles.containerSubText}>
<View style={styles.containerSubTextItemLeft}> <View style={styles.containerSubTextItemLeft}>
<Text style={[styles.text]}> <Text style={[styles.text]}>
Gii tính: {' '} Gii tính:{' '}
<Text <Text
style={[ style={[
styles.text, styles.text,
...@@ -85,7 +90,7 @@ const DetailStudentView = props => { ...@@ -85,7 +90,7 @@ const DetailStudentView = props => {
<View style={styles.sizedBox}></View> <View style={styles.sizedBox}></View>
<View style={styles.containerSubTextItemRight}> <View style={styles.containerSubTextItemRight}>
<Text style={[styles.text]}> <Text style={[styles.text]}>
Đim trung bình: {' '} Đim trung bình:{' '}
<Text <Text
style={[ style={[
styles.text, styles.text,
...@@ -101,7 +106,7 @@ const DetailStudentView = props => { ...@@ -101,7 +106,7 @@ const DetailStudentView = props => {
<View style={styles.containerSubText}> <View style={styles.containerSubText}>
<View style={styles.containerSubTextItemLeft}> <View style={styles.containerSubTextItemLeft}>
<Text style={[styles.text]}> <Text style={[styles.text]}>
Đim TB hc kì gn nht: {' '} Đim TB hc kì gn nht:{' '}
<Text <Text
style={[ style={[
styles.text, styles.text,
...@@ -116,7 +121,7 @@ const DetailStudentView = props => { ...@@ -116,7 +121,7 @@ const DetailStudentView = props => {
<View style={styles.containerSubText}> <View style={styles.containerSubText}>
<View style={styles.containerSubTextItemLeft}> <View style={styles.containerSubTextItemLeft}>
<Text style={[styles.text]}> <Text style={[styles.text]}>
Đim rèn luyn TB: {' '} Đim rèn luyn TB:{' '}
<Text <Text
style={[ style={[
styles.text, styles.text,
...@@ -146,8 +151,14 @@ const DetailStudentView = props => { ...@@ -146,8 +151,14 @@ const DetailStudentView = props => {
))} ))}
</View> </View>
</View> </View>
<Text style={[styles.textTitle ,{marginTop:10}]}>Lch s tình trng ca sinh viên</Text> <Text style={[styles.textTitle, {marginTop: 10}]}>
<View style={[styles.containerCard, {backgroundColor:getStatusColor(student.status)}]}> Lch s tình trng ca sinh viên
</Text>
<View
style={[
styles.containerCard,
{backgroundColor: getStatusColor(student.status)},
]}>
<Text <Text
style={[ style={[
{ {
...@@ -155,8 +166,8 @@ const DetailStudentView = props => { ...@@ -155,8 +166,8 @@ const DetailStudentView = props => {
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight: '600', fontWeight: '600',
color: R.colors.white, color: R.colors.white,
marginHorizontal:10, marginHorizontal: 10,
marginVertical:3 marginVertical: 3,
}, },
]}> ]}>
Trng thái hc tp:{' '} Trng thái hc tp:{' '}
...@@ -165,7 +176,6 @@ const DetailStudentView = props => { ...@@ -165,7 +176,6 @@ const DetailStudentView = props => {
</Text> </Text>
</Text> </Text>
<View style={styles.card}> <View style={styles.card}>
<Text <Text
style={[ style={[
{ {
...@@ -178,8 +188,6 @@ const DetailStudentView = props => { ...@@ -178,8 +188,6 @@ const DetailStudentView = props => {
Hc k 2, Năm hc 2024 Hc k 2, Năm hc 2024
</Text> </Text>
<Text <Text
style={[ style={[
{ {
......
...@@ -5,7 +5,6 @@ const styles = StyleSheet.create({ ...@@ -5,7 +5,6 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
}, },
//Search
containerSearchBox: { containerSearchBox: {
borderColor: R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderWidth: 1, borderWidth: 1,
...@@ -14,7 +13,7 @@ const styles = StyleSheet.create({ ...@@ -14,7 +13,7 @@ const styles = StyleSheet.create({
marginVertical: 15, marginVertical: 15,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
flexDirection: 'row', flexDirection: 'row',
height:35 height: 35,
}, },
boxIconSearch: { boxIconSearch: {
maxWidth: 35, maxWidth: 35,
...@@ -28,20 +27,18 @@ const styles = StyleSheet.create({ ...@@ -28,20 +27,18 @@ const styles = StyleSheet.create({
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight: '500', fontWeight: '500',
flex: 1, flex: 1,
margin:0, margin: 0,
padding:0, padding: 0,
}, },
//Filter
statusContainer: { statusContainer: {
marginBottom: 15, marginBottom: 15,
marginHorizontal: 15, marginHorizontal: 15,
flexDirection: "row", flexDirection: 'row',
justifyContent: "space-around" justifyContent: 'space-around',
}, },
statusCard: { statusCard: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
}, },
statusDot: { statusDot: {
width: 10, width: 10,
...@@ -64,7 +61,7 @@ const styles = StyleSheet.create({ ...@@ -64,7 +61,7 @@ const styles = StyleSheet.create({
}, },
body: { body: {
flex:1, flex: 1,
}, },
listContainer: { listContainer: {
paddingBottom: 20, paddingBottom: 20,
...@@ -112,8 +109,6 @@ const styles = StyleSheet.create({ ...@@ -112,8 +109,6 @@ const styles = StyleSheet.create({
color: R.colors.black, color: R.colors.black,
}, },
statusIndicator: { statusIndicator: {
width: 15, width: 15,
height: 15, height: 15,
......
...@@ -13,12 +13,11 @@ import Header from '../../../components/Header/Header'; ...@@ -13,12 +13,11 @@ import Header from '../../../components/Header/Header';
import styles from './style'; import styles from './style';
import R from '../../../assets/R'; import R from '../../../assets/R';
import * as SCREENNAME from '../../../routers/ScreenNames'; import * as SCREENNAME from '../../../routers/ScreenNames';
import { useNavigation } from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
const ListStudentView = props => { const ListStudentView = props => {
const {searchText, onSearchChange, filter, statusStats} = props; const {searchText, onSearchChange, filter, statusStats} = props;
console.log(props); console.log(props);
const navigate = useNavigation(); const navigate = useNavigation();
//Search
const renderSearchBox = () => { const renderSearchBox = () => {
return ( return (
<View style={styles.containerSearchBox}> <View style={styles.containerSearchBox}>
...@@ -42,12 +41,9 @@ const ListStudentView = props => { ...@@ -42,12 +41,9 @@ const ListStudentView = props => {
</View> </View>
); );
}; };
//List status
const renderListStatus = () => { const renderListStatus = () => {
return ( return (
<View <View style={styles.statusContainer}>
style={styles.statusContainer}
>
{statusStats.map((stat, index) => ( {statusStats.map((stat, index) => (
<View <View
key={index} key={index}
...@@ -65,8 +61,7 @@ const ListStudentView = props => { ...@@ -65,8 +61,7 @@ const ListStudentView = props => {
); );
}; };
//List student const renderStudentItem = ({item, onPress}) => {
const renderStudentItem = ({item , onPress}) => {
const isLeftIcon = item.gender === 'Nam'; const isLeftIcon = item.gender === 'Nam';
const genderIcon = const genderIcon =
item.gender === 'Nam' ? R.images.icMale : R.images.icFemale; item.gender === 'Nam' ? R.images.icMale : R.images.icFemale;
...@@ -74,17 +69,29 @@ const ListStudentView = props => { ...@@ -74,17 +69,29 @@ const ListStudentView = props => {
const statusColor = getStatusColor(item.status); const statusColor = getStatusColor(item.status);
return ( return (
<TouchableOpacity style={styles.studentCard} onPress={()=>{navigate.navigate(SCREENNAME.DETAILSTUDENT)}}> <TouchableOpacity
style={styles.studentCard}
onPress={() => {
navigate.navigate(SCREENNAME.DETAILSTUDENT);
}}>
<View style={styles.studentCardContent}> <View style={styles.studentCardContent}>
<View style={styles.studentInfo}> <View style={styles.studentInfo}>
{/*Tên sinh viên*/} {/*Tên sinh viên*/}
<View style={styles.leftSection}> <View style={styles.leftSection}>
<Text style={styles.studentName}>{item.name}</Text> <Text style={styles.studentName}>{item.name}</Text>
{isLeftIcon && ( {isLeftIcon && (
<Image source={genderIcon} style={styles.genderIcon} resizeMode="contain"/> <Image
source={genderIcon}
style={styles.genderIcon}
resizeMode="contain"
/>
)} )}
{!isLeftIcon && ( {!isLeftIcon && (
<Image source={genderIcon} style={styles.genderIcon} resizeMode="contain"/> <Image
source={genderIcon}
style={styles.genderIcon}
resizeMode="contain"
/>
)} )}
</View> </View>
<View style={styles.rightSection}> <View style={styles.rightSection}>
...@@ -106,11 +113,23 @@ const ListStudentView = props => { ...@@ -106,11 +113,23 @@ const ListStudentView = props => {
<View style={styles.studentInfo}> <View style={styles.studentInfo}>
{/*Tên sinh viên*/} {/*Tên sinh viên*/}
<View style={styles.leftSection}> <View style={styles.leftSection}>
<Text style={[styles.studentName,{fontFamily:R.fonts.fontRegular,fontWeight:'400'}]}>Ngày sinh: {item.date_student}</Text> <Text
style={[
styles.studentName,
{fontFamily: R.fonts.fontRegular, fontWeight: '400'},
]}>
Ngày sinh: {item.date_student}
</Text>
</View> </View>
<View style={styles.rightSection}> <View style={styles.rightSection}>
{/*Mã sinh viên*/} {/*Mã sinh viên*/}
<Text style={[styles.studentName,{fontFamily:R.fonts.fontRegular,fontWeight:'400'}]}>SĐT: {item.tele_phone}</Text> <Text
style={[
styles.studentName,
{fontFamily: R.fonts.fontRegular, fontWeight: '400'},
]}>
SĐT: {item.tele_phone}
</Text>
</View> </View>
</View> </View>
</View> </View>
......
import { StyleSheet , Platform} from 'react-native' import {StyleSheet, Platform} from 'react-native';
import R from '../../assets/R'; import R from '../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
},
containerList: {
flex: 1,
justifyContent: 'center',
}, },
card:{ card: {
borderWidth:1, borderWidth: 1,
borderColor:R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderRadius:10, borderRadius: 10,
padding:5, padding: 5,
marginTop:15, marginTop: 15,
marginBottom:15, marginBottom: 15,
marginHorizontal:15, marginHorizontal: 15,
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
shadowColor:R.colors.black, shadowColor: R.colors.black,
shadowOffset:{width:0.5,height:2}, shadowOffset: {width: 0.5, height: 2},
shadowOpacity:Platform.OS === 'ios' ? 0.25 : 1, shadowOpacity: Platform.OS === 'ios' ? 0.25 : 1,
shadowRadius:5, shadowRadius: 5,
elevation:Platform.OS === 'ios' ? 1 : 2, elevation: Platform.OS === 'ios' ? 1 : 2,
}, },
btnCard:{ btnCard: {
borderRadius:10, borderRadius: 10,
borderWidth:1, borderWidth: 1,
padding:5, padding: 5,
width:'100%', width: '100%',
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
borderColor:R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
}, },
text_title:{ text_title: {
fontSize:R.fontsize.fontSizeContent, fontSize: R.fontsize.fontSizeContent,
fontWeight:'600', fontWeight: '600',
color:R.colors.black, color: R.colors.black,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
}, },
text:{ text: {
fontSize:R.fontsize.fontSizeContent, fontSize: R.fontsize.fontSizeContent,
color:R.colors.black, color: R.colors.black,
fontFamily:R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
fontWeight:'400', fontWeight: '400',
}, },
containerCard:{ containerCard: {
padding:10, padding: 10,
marginBottom:15 , marginBottom: 15,
borderRadius:10, borderRadius: 10,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
shadowColor:R.colors.black, shadowColor: R.colors.black,
shadowOffset:{width:0,height:2}, shadowOffset: {width: 0, height: 2},
shadowOpacity:Platform.OS === 'ios' ? 0.25 : 1, shadowOpacity: Platform.OS === 'ios' ? 0.25 : 1,
shadowRadius:1, shadowRadius: 1,
elevation:Platform.OS === 'ios' ? 1 : 2, elevation: Platform.OS === 'ios' ? 1 : 2,
marginHorizontal:15, marginHorizontal: 15,
marginVertical:15, marginVertical: 15,
}, },
containerText:{ containerEmpty: {
flexDirection:'row', alignItems: 'center',
justifyContent: 'center',
}, },
sizedBox:{ textEmpty: {
width:'35%', color: R.colors.black,
fontSize: R.fontsize.fontSizeSubTitle,
fontWeight: '500',
fontFamily: R.fonts.fontMedium,
}, },
containerButton:{ textHeader:{
alignItems:'flex-end', fontSize: R.fontsize.fontSizeContent,
} fontWeight: '600',
fontFamily: R.fonts.fontMedium,
}) color: R.colors.black,
},
containerText: {
flexDirection: 'row',
},
sizedBox: {
width: '35%',
},
containerButton: {
alignItems: 'flex-end',
},
});
export default styles export default styles;
\ No newline at end of file
import React from 'react'; import React from 'react';
import { import {Text, View, TouchableOpacity, FlatList, Image} from 'react-native';
Text,
View,
TouchableOpacity,
StyleSheet,
SafeAreaView,
FlatList,
} from 'react-native';
import styles from './style'; import styles from './style';
import Header from '../../components/Header/Header'; import Header from '../../components/Header/Header';
import Button from '../../components/Button'; import Button from '../../components/Button';
import R from '../../assets/R'; import R from '../../assets/R';
import * as SCREENNAME from '../../routers/ScreenNames'; import * as SCREENNAME from '../../routers/ScreenNames';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
const ClassActivityView = props => { const ClassActivityView = props => {
const {dataList, setDataList} = props; const {dataList, setDataList} = props;
const navigate = useNavigation(); const navigate = useNavigation();
const renderItem = ({item}) => { const renderItem = ({item}) => {
return ( return (
<View style={styles.containerCard}> <View style={styles.containerCard}>
<Text style={styles.text_title}>Lp sinh hot:{' '} <Text style={styles.text_title}>
<Text style={styles.text}>{item.class_activity}</Text> Lp sinh hot: <Text style={styles.text}>{item.class_activity}</Text>
</Text> </Text>
<View style={styles.containerText}> <View style={styles.containerText}>
<Text style={styles.text_title}>Khoá: {' '} <Text style={styles.text_title}>
<Text style={styles.text}>{item.course}</Text> Khoá: <Text style={styles.text}>{item.course}</Text>
</Text> </Text>
<View style={styles.sizedBox}></View> <View style={styles.sizedBox}></View>
<Text style={styles.text_title}>H ĐT: {' '} <Text style={styles.text_title}>
<Text style={styles.text}>{item.training_system}</Text> H ĐT: <Text style={styles.text}>{item.training_system}</Text>
</Text> </Text>
</View> </View>
<Text style={styles.text_title}>Lp theo khoa: {' '} <Text style={styles.text_title}>
<Text style={styles.text}>{item.class_by_course}</Text> Lp theo khoa: <Text style={styles.text}>{item.class_by_course}</Text>
</Text> </Text>
<Text style={styles.text_title}>Khoa: {' '} <Text style={styles.text_title}>
<Text style={styles.text}>{item.science}</Text> Khoa: <Text style={styles.text}>{item.science}</Text>
</Text> </Text>
<Text style={styles.text_title}>Lp trưởng: {' '} <Text style={styles.text_title}>
<Text style={styles.text}>{item.class_leader}</Text> Lp trưởng: <Text style={styles.text}>{item.class_leader}</Text>
</Text> </Text>
<View style={styles.containerButton}> <View style={styles.containerButton}>
<Button <Button
...@@ -60,15 +55,16 @@ const ClassActivityView = props => { ...@@ -60,15 +55,16 @@ const ClassActivityView = props => {
</View> </View>
); );
}; };
const renderItemEmpty = () => {
return ( return (
<View style={styles.container}> <View style={styles.containerEmpty}>
<Header title={'Danh sách lớp sinh hoạt'} isBack /> <Image source={R.images.icNoData} maxWidth={50} maxHeight={50} />
<View style={styles.body}> <Text style={styles.textEmpty}>Không có d liu</Text>
<View style={styles.card}>
<TouchableOpacity style={styles.btnCard}>
<Text style={styles.text}>Khoá 2024</Text>
</TouchableOpacity>
</View> </View>
);
};
const renderList = () => {
return (
<FlatList <FlatList
data={dataList || []} data={dataList || []}
renderItem={renderItem} renderItem={renderItem}
...@@ -76,9 +72,35 @@ const ClassActivityView = props => { ...@@ -76,9 +72,35 @@ const ClassActivityView = props => {
vertical vertical
keyExtractor={(item, index) => `${index}`} keyExtractor={(item, index) => `${index}`}
/> />
);
};
const renderHeaderBody = () => {
return (
<View style={styles.card}>
<TouchableOpacity style={styles.btnCard} onPress={() => {}}>
<Text style={[styles.text, styles.textHeader]}>Khoá 2024</Text>
</TouchableOpacity>
</View>
);
};
const renderBody = () => {
return (
<View style={styles.body}>
{renderHeaderBody()}
<View style={styles.containerList}>
{dataList?.length > 0 ? renderList() : renderItemEmpty()}
</View> </View>
</View> </View>
); );
};
return (
<View style={styles.container}>
<Header title={'Danh sách lớp sinh hoạt'} isBack />
{renderBody()}
</View>
);
}; };
export default ClassActivityView; export default ClassActivityView;
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../../assets/R' import R from '../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
...@@ -30,12 +30,13 @@ const styles = StyleSheet.create({ ...@@ -30,12 +30,13 @@ const styles = StyleSheet.create({
fontFamily: R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
color: R.colors.black, color: R.colors.black,
}, },
icon:{ icon: {
width:20, width: 20,
height:15, height: 15,
}, },
info:{ info: {
paddingHorizontal: 15, paddingVertical: 5 paddingHorizontal: 15,
} paddingVertical: 5,
}) },
export default styles });
\ No newline at end of file export default styles;
import React from 'react'; import React from 'react';
import { Text, View, TouchableOpacity, StyleSheet, ImageBackground, Image } from 'react-native'; import {
Text,
View,
TouchableOpacity,
StyleSheet,
ImageBackground,
Image,
} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
import styles from './style'; import styles from './style';
import { useNavigation } from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
const DetailClassScheduleView = (props) => { const DetailClassScheduleView = props => {
const { } = props; const {} = props;
const navigate = useNavigation(); const navigate = useNavigation();
const ArrowLeftIcon = R.images.icBack; const ArrowLeftIcon = R.images.icBack;
return ( return (
<View <View style={styles.container}>
style={styles.container}
>
<ImageBackground <ImageBackground
source={R.images.igBackground} source={R.images.igBackground}
style={styles.background_header} style={styles.background_header}>
> <TouchableOpacity
<TouchableOpacity style={styles.back_button} onPress={() => navigate.goBack()}> style={styles.back_button}
<Image source={ArrowLeftIcon} style= {styles.icon}/> onPress={() => navigate.goBack()}>
<Image source={ArrowLeftIcon} style={styles.icon} />
</TouchableOpacity> </TouchableOpacity>
</ImageBackground> </ImageBackground>
<View style={styles.container_content}> <View style={styles.container_content}>
<Text style={styles.text_title}>Lch dy lp IT0032.47.T1</Text> <Text style={styles.text_title}>Lch dy lp IT0032.47.T1</Text>
<Text style={[styles.text_content, {fontWeight:'600', fontFamily:R.fonts.fontMedium}]}>Th 6: 25/07/2025, 07:00 - 09:00</Text> <Text
style={[
styles.text_content,
{fontWeight: '600', fontFamily: R.fonts.fontMedium},
]}>
Th 6: 25/07/2025, 07:00 - 09:00
</Text>
<View style={[styles.container_content, styles.info]}> <View style={[styles.container_content, styles.info]}>
<Text style={[styles.text_content, {fontWeight:'600', fontFamily:R.fonts.fontMedium}]}>V trí: <Text
style={[
styles.text_content,
{fontWeight: '600', fontFamily: R.fonts.fontMedium},
]}>
V trí:
<Text style={styles.text_content}> Phòng B205</Text> <Text style={styles.text_content}> Phòng B205</Text>
</Text> </Text>
<Text style={[styles.text_content, {fontWeight:'600', fontFamily:R.fonts.fontMedium}]}>Sĩ s: <Text
style={[
styles.text_content,
{fontWeight: '600', fontFamily: R.fonts.fontMedium},
]}>
Sĩ s:
<Text style={styles.text_content}> 40</Text> <Text style={styles.text_content}> 40</Text>
</Text> </Text>
<Text style={[styles.text_content, {fontWeight:'600', fontFamily:R.fonts.fontMedium}]}>Lp hc: <Text
style={[
styles.text_content,
{fontWeight: '600', fontFamily: R.fonts.fontMedium},
]}>
Lp hc:
<Text style={styles.text_content}> C810</Text> <Text style={styles.text_content}> C810</Text>
</Text> </Text>
<Text style={[styles.text_content, {fontWeight:'600', fontFamily:R.fonts.fontMedium}]}>Hình thc hc: <Text
style={[
styles.text_content,
{fontWeight: '600', fontFamily: R.fonts.fontMedium},
]}>
Hình thc hc:
<Text style={styles.text_content}> Thc hành</Text> <Text style={styles.text_content}> Thc hành</Text>
</Text> </Text>
</View> </View>
</View> </View>
</View> </View>
......
...@@ -59,32 +59,50 @@ const Filter3Day = ({navigation}) => { ...@@ -59,32 +59,50 @@ const Filter3Day = ({navigation}) => {
const mockEvents = createMockEvents(); const mockEvents = createMockEvents();
const formatDateToString = (date) => { const formatDateToString = date => {
const year = date.getFullYear(); const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
}; };
const getEventsForDate = (date) => { const getEventsForDate = date => {
const dateStr = formatDateToString(date); const dateStr = formatDateToString(date);
return mockEvents.filter(event => event.date === dateStr); return mockEvents.filter(event => event.date === dateStr);
}; };
const getDayName = (date) => { const getDayName = date => {
const days = ['Chủ nhật', 'Thứ 2', 'Thứ 3', 'Thứ 4', 'Thứ 5', 'Thứ 6', 'Thứ 7']; const days = [
'Chủ nhật',
'Thứ 2',
'Thứ 3',
'Thứ 4',
'Thứ 5',
'Thứ 6',
'Thứ 7',
];
return days[date.getDay()]; return days[date.getDay()];
}; };
const getMonthName = (monthIndex) => { const getMonthName = monthIndex => {
const months = [ const months = [
'Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6', 'Tháng 1',
'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12', 'Tháng 2',
'Tháng 3',
'Tháng 4',
'Tháng 5',
'Tháng 6',
'Tháng 7',
'Tháng 8',
'Tháng 9',
'Tháng 10',
'Tháng 11',
'Tháng 12',
]; ];
return months[monthIndex]; return months[monthIndex];
}; };
const get3DaysDates = (date) => { const get3DaysDates = date => {
const dates = []; const dates = [];
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
const dayDate = new Date(date); const dayDate = new Date(date);
...@@ -94,7 +112,7 @@ const Filter3Day = ({navigation}) => { ...@@ -94,7 +112,7 @@ const Filter3Day = ({navigation}) => {
return dates; return dates;
}; };
const isToday = (date) => { const isToday = date => {
const today = new Date(); const today = new Date();
return ( return (
date.getDate() === today.getDate() && date.getDate() === today.getDate() &&
...@@ -103,7 +121,7 @@ const Filter3Day = ({navigation}) => { ...@@ -103,7 +121,7 @@ const Filter3Day = ({navigation}) => {
); );
}; };
const handleMonthSelect = (monthIndex) => { const handleMonthSelect = monthIndex => {
const newDate = new Date(currentDate); const newDate = new Date(currentDate);
newDate.setMonth(monthIndex); newDate.setMonth(monthIndex);
setCurrentDate(newDate); setCurrentDate(newDate);
...@@ -158,7 +176,7 @@ const Filter3Day = ({navigation}) => { ...@@ -158,7 +176,7 @@ const Filter3Day = ({navigation}) => {
const topPosition = (startTotalMinutes / 60) * HOUR_HEIGHT; const topPosition = (startTotalMinutes / 60) * HOUR_HEIGHT;
const height = (durationMinutes / 60) * HOUR_HEIGHT; const height = (durationMinutes / 60) * HOUR_HEIGHT;
return { topPosition, height }; return {topPosition, height};
}; };
return ( return (
......
import { StyleSheet, Dimensions } from 'react-native'; import {StyleSheet, Dimensions} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
const { width: screenWidth, height: screenHeight } = Dimensions.get('window'); const {width: screenWidth, height: screenHeight} = Dimensions.get('window');
const HOUR_HEIGHT = 80; const HOUR_HEIGHT = 80;
const DAY_COLUMN_WIDTH = (screenWidth - 70) / 3; const DAY_COLUMN_WIDTH = (screenWidth - 70) / 3;
...@@ -71,7 +71,7 @@ const styles = StyleSheet.create({ ...@@ -71,7 +71,7 @@ const styles = StyleSheet.create({
borderRadius: 15, borderRadius: 15,
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
marginVertical: 5 marginVertical: 5,
}, },
todayNumberContainer: { todayNumberContainer: {
backgroundColor: R.colors.blue, backgroundColor: R.colors.blue,
...@@ -90,8 +90,7 @@ const styles = StyleSheet.create({ ...@@ -90,8 +90,7 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
}, },
scrollContent: { scrollContent: {},
},
timelineContainer: { timelineContainer: {
flexDirection: 'row', flexDirection: 'row',
position: 'relative', position: 'relative',
......
...@@ -9,7 +9,7 @@ import { ...@@ -9,7 +9,7 @@ import {
import R from '../../../assets/R'; import R from '../../../assets/R';
import styles from './style'; import styles from './style';
const Filter3DayView = (props) => { const Filter3DayView = props => {
const { const {
currentDate, currentDate,
showMonthPicker, showMonthPicker,
...@@ -21,10 +21,9 @@ const Filter3DayView = (props) => { ...@@ -21,10 +21,9 @@ const Filter3DayView = (props) => {
get3DaysDates, get3DaysDates,
isToday, isToday,
handleMonthSelect, handleMonthSelect,
calculateEventPosition calculateEventPosition,
} = props; } = props;
const renderMonthPicker = () => { const renderMonthPicker = () => {
if (!showMonthPicker) return null; if (!showMonthPicker) return null;
...@@ -45,7 +44,8 @@ const Filter3DayView = (props) => { ...@@ -45,7 +44,8 @@ const Filter3DayView = (props) => {
<Text <Text
style={[ style={[
styles.monthItemText, styles.monthItemText,
currentDate.getMonth() === index && styles.monthItemTextSelected, currentDate.getMonth() === index &&
styles.monthItemTextSelected,
]}> ]}>
{getMonthName(index)} {getMonthName(index)}
</Text> </Text>
...@@ -67,19 +67,22 @@ const Filter3DayView = (props) => { ...@@ -67,19 +67,22 @@ const Filter3DayView = (props) => {
return ( return (
<View key={index} style={styles.dayHeaderCell}> <View key={index} style={styles.dayHeaderCell}>
<Text style={[ <Text
style={[
styles.dayHeaderText, styles.dayHeaderText,
isTodayDate && styles.todayHeaderText isTodayDate && styles.todayHeaderText,
]}> ]}>
{getDayName(date)} {getDayName(date)}
</Text> </Text>
<View style={[ <View
style={[
styles.dayNumberContainer, styles.dayNumberContainer,
isTodayDate && styles.todayNumberContainer isTodayDate && styles.todayNumberContainer,
]}> ]}>
<Text style={[ <Text
style={[
styles.dayHeaderNumber, styles.dayHeaderNumber,
isTodayDate && styles.todayHeaderNumber isTodayDate && styles.todayHeaderNumber,
]}> ]}>
{date.getDate()} {date.getDate()}
</Text> </Text>
...@@ -101,10 +104,9 @@ const Filter3DayView = (props) => { ...@@ -101,10 +104,9 @@ const Filter3DayView = (props) => {
ref={scrollViewRef} ref={scrollViewRef}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
contentContainerStyle={styles.scrollContent}> contentContainerStyle={styles.scrollContent}>
<View style={styles.timelineContainer}> <View style={styles.timelineContainer}>
<View style={styles.timeLabelsColumn}> <View style={styles.timeLabelsColumn}>
{hours.map((hour) => { {hours.map(hour => {
const timeStr = hour.toString().padStart(2, '0') + ':00'; const timeStr = hour.toString().padStart(2, '0') + ':00';
return ( return (
<View key={hour} style={styles.timeSlot}> <View key={hour} style={styles.timeSlot}>
...@@ -117,12 +119,15 @@ const Filter3DayView = (props) => { ...@@ -117,12 +119,15 @@ const Filter3DayView = (props) => {
<View style={styles.daysGridContainer}> <View style={styles.daysGridContainer}>
{threeDaysDates.map((date, dayIndex) => ( {threeDaysDates.map((date, dayIndex) => (
<View key={dayIndex} style={styles.dayColumn}> <View key={dayIndex} style={styles.dayColumn}>
{hours.map((hour) => ( {hours.map(hour => (
<View key={hour} style={styles.gridCell} /> <View key={hour} style={styles.gridCell} />
))} ))}
{getEventsForDate(date).map((event) => { {getEventsForDate(date).map(event => {
const { topPosition, height } = calculateEventPosition(event.time, event.endTime); const {topPosition, height} = calculateEventPosition(
event.time,
event.endTime,
);
return ( return (
<TouchableOpacity <TouchableOpacity
...@@ -137,10 +142,12 @@ const Filter3DayView = (props) => { ...@@ -137,10 +142,12 @@ const Filter3DayView = (props) => {
right: 4, right: 4,
zIndex: 10, zIndex: 10,
backgroundColor: R.colors.blue, backgroundColor: R.colors.blue,
} },
]} ]}
activeOpacity={0.7}> activeOpacity={0.7}>
<Text style={styles.eventTitle} numberOfLines={height > 80 ? 3 : 2}> <Text
style={styles.eventTitle}
numberOfLines={height > 80 ? 3 : 2}>
{event.title} {event.title}
</Text> </Text>
{height > 50 && ( {height > 50 && (
...@@ -149,7 +156,9 @@ const Filter3DayView = (props) => { ...@@ -149,7 +156,9 @@ const Filter3DayView = (props) => {
</Text> </Text>
)} )}
<Text style={styles.eventTime}> <Text style={styles.eventTime}>
Thi gian hc: {event.time} - {event.endTime}, {getDayName(date)} {date.getDate()}/{date.getMonth() + 1}/{date.getFullYear()} Thi gian hc: {event.time} - {event.endTime},{' '}
{getDayName(date)} {date.getDate()}/
{date.getMonth() + 1}/{date.getFullYear()}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
); );
...@@ -172,5 +181,4 @@ const Filter3DayView = (props) => { ...@@ -172,5 +181,4 @@ const Filter3DayView = (props) => {
); );
}; };
export default Filter3DayView;
export default Filter3DayView
import React, {useState, useRef, useEffect} from 'react'; import React, {useState, useRef, useEffect} from 'react';
import { import {Dimensions, DeviceEventEmitter, PanResponder} from 'react-native';
Dimensions,
DeviceEventEmitter,
PanResponder,
} from 'react-native';
import FilterWeekView from './view'; import FilterWeekView from './view';
// ==================== HẰNG SỐ ==================== // ==================== HẰNG SỐ ====================
...@@ -30,7 +26,7 @@ const FilterWeek = ({navigation}) => { ...@@ -30,7 +26,7 @@ const FilterWeek = ({navigation}) => {
// ==================== HÀM TIỆN ÍCH ==================== // ==================== HÀM TIỆN ÍCH ====================
// T1: Định dạng ngày thành chuỗi // T1: Định dạng ngày thành chuỗi
const formatDateToString = (date) => { const formatDateToString = date => {
const year = date.getFullYear(); const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0');
...@@ -38,7 +34,7 @@ const FilterWeek = ({navigation}) => { ...@@ -38,7 +34,7 @@ const FilterWeek = ({navigation}) => {
}; };
// T2: Kiểm tra ngày hôm nay // T2: Kiểm tra ngày hôm nay
const isToday = (someDate) => { const isToday = someDate => {
const today = new Date(); const today = new Date();
return ( return (
someDate.getDate() === today.getDate() && someDate.getDate() === today.getDate() &&
...@@ -48,22 +44,32 @@ const FilterWeek = ({navigation}) => { ...@@ -48,22 +44,32 @@ const FilterWeek = ({navigation}) => {
}; };
// T3: Lấy tên ngày trong tuần // T3: Lấy tên ngày trong tuần
const getDayName = (date) => { const getDayName = date => {
const days = ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7']; const days = ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'];
return days[date.getDay()]; return days[date.getDay()];
}; };
// T4: Lấy tên tháng // T4: Lấy tên tháng
const getMonthName = (monthIndex) => { const getMonthName = monthIndex => {
const months = [ const months = [
'Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6', 'Tháng 1',
'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12', 'Tháng 2',
'Tháng 3',
'Tháng 4',
'Tháng 5',
'Tháng 6',
'Tháng 7',
'Tháng 8',
'Tháng 9',
'Tháng 10',
'Tháng 11',
'Tháng 12',
]; ];
return months[monthIndex]; return months[monthIndex];
}; };
// T5: Lấy các ngày trong tuần // T5: Lấy các ngày trong tuần
const getWeekDates = (date) => { const getWeekDates = date => {
const startOfWeek = new Date(date); const startOfWeek = new Date(date);
startOfWeek.setDate(date.getDate() - date.getDay()); startOfWeek.setDate(date.getDate() - date.getDay());
...@@ -156,7 +162,7 @@ const FilterWeek = ({navigation}) => { ...@@ -156,7 +162,7 @@ const FilterWeek = ({navigation}) => {
const mockEvents = createMockEvents(); const mockEvents = createMockEvents();
// D3: Hàm truy vấn sự kiện // D3: Hàm truy vấn sự kiện
const getEventsForDate = (date) => { const getEventsForDate = date => {
const dateStr = formatDateToString(date); const dateStr = formatDateToString(date);
return mockEvents.filter(event => event.date === dateStr); return mockEvents.filter(event => event.date === dateStr);
}; };
...@@ -179,7 +185,7 @@ const FilterWeek = ({navigation}) => { ...@@ -179,7 +185,7 @@ const FilterWeek = ({navigation}) => {
// ==================== XỬ LÝ SỰ KIỆN ==================== // ==================== XỬ LÝ SỰ KIỆN ====================
// X1: Xử lý chọn tháng // X1: Xử lý chọn tháng
const handleMonthSelect = (monthIndex) => { const handleMonthSelect = monthIndex => {
const newDate = new Date(currentDate); const newDate = new Date(currentDate);
newDate.setMonth(monthIndex); newDate.setMonth(monthIndex);
setCurrentDate(newDate); setCurrentDate(newDate);
......
import React from 'react'; import React from 'react';
import { import {View, Text, TouchableOpacity, ScrollView, FlatList} from 'react-native';
View,
Text,
TouchableOpacity,
ScrollView,
FlatList,
} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
import styles from './style'; import styles from './style';
...@@ -22,7 +16,6 @@ const FilterWeekView = ({ ...@@ -22,7 +16,6 @@ const FilterWeekView = ({
calculateEventPosition, calculateEventPosition,
handleMonthSelect, handleMonthSelect,
}) => { }) => {
const renderMonthPicker = () => { const renderMonthPicker = () => {
if (!showMonthPicker) return null; if (!showMonthPicker) return null;
...@@ -32,7 +25,7 @@ const FilterWeekView = ({ ...@@ -32,7 +25,7 @@ const FilterWeekView = ({
horizontal horizontal
showsHorizontalScrollIndicator={false} showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.monthPickerContent}> contentContainerStyle={styles.monthPickerContent}>
{Array.from({ length: 12 }, (_, index) => ( {Array.from({length: 12}, (_, index) => (
<TouchableOpacity <TouchableOpacity
key={index} key={index}
style={[ style={[
...@@ -43,7 +36,8 @@ const FilterWeekView = ({ ...@@ -43,7 +36,8 @@ const FilterWeekView = ({
<Text <Text
style={[ style={[
styles.monthItemText, styles.monthItemText,
currentDate.getMonth() === index && styles.monthItemTextSelected, currentDate.getMonth() === index &&
styles.monthItemTextSelected,
]}> ]}>
{getMonthName(index)} {getMonthName(index)}
</Text> </Text>
...@@ -65,17 +59,22 @@ const FilterWeekView = ({ ...@@ -65,17 +59,22 @@ const FilterWeekView = ({
return ( return (
<View key={index} style={styles.dayHeaderCell}> <View key={index} style={styles.dayHeaderCell}>
<Text style={[ <Text
style={[
styles.dayHeaderText, styles.dayHeaderText,
isCurrentDay && styles.dayHeaderTextToday isCurrentDay && styles.dayHeaderTextToday,
]}> ]}>
{getDayName(date)} {getDayName(date)}
</Text> </Text>
<View style={isCurrentDay ? styles.dayHeaderNumberContainerToday : {}}> <View
<Text style={[ style={
isCurrentDay ? styles.dayHeaderNumberContainerToday : {}
}>
<Text
style={[
styles.dayHeaderNumber, styles.dayHeaderNumber,
isCurrentDay && styles.dayHeaderNumberToday isCurrentDay && styles.dayHeaderNumberToday,
]}> ]}>
{date.getDate()} {date.getDate()}
</Text> </Text>
...@@ -88,7 +87,7 @@ const FilterWeekView = ({ ...@@ -88,7 +87,7 @@ const FilterWeekView = ({
}; };
const renderTimeSlots = () => { const renderTimeSlots = () => {
const hours = Array.from({ length: 24 }, (_, i) => i); const hours = Array.from({length: 24}, (_, i) => i);
const weekDates = getWeekDates(currentDate); const weekDates = getWeekDates(currentDate);
return ( return (
...@@ -97,10 +96,9 @@ const FilterWeekView = ({ ...@@ -97,10 +96,9 @@ const FilterWeekView = ({
ref={scrollViewRef} ref={scrollViewRef}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
contentContainerStyle={styles.scrollContent}> contentContainerStyle={styles.scrollContent}>
<View style={styles.timelineContainer}> <View style={styles.timelineContainer}>
<View style={styles.timeLabelsColumn}> <View style={styles.timeLabelsColumn}>
{hours.map((hour) => { {hours.map(hour => {
const timeStr = hour.toString().padStart(2, '0') + ':00'; const timeStr = hour.toString().padStart(2, '0') + ':00';
return ( return (
<View key={hour} style={styles.timeSlot}> <View key={hour} style={styles.timeSlot}>
...@@ -113,12 +111,15 @@ const FilterWeekView = ({ ...@@ -113,12 +111,15 @@ const FilterWeekView = ({
<View style={styles.weekGridContainer}> <View style={styles.weekGridContainer}>
{weekDates.map((date, dayIndex) => ( {weekDates.map((date, dayIndex) => (
<View key={dayIndex} style={styles.dayColumn}> <View key={dayIndex} style={styles.dayColumn}>
{hours.map((hour) => ( {hours.map(hour => (
<View key={hour} style={styles.gridCell} /> <View key={hour} style={styles.gridCell} />
))} ))}
{getEventsForDate(date).map((event) => { {getEventsForDate(date).map(event => {
const { topPosition, height } = calculateEventPosition(event.time, event.endTime); const {topPosition, height} = calculateEventPosition(
event.time,
event.endTime,
);
return ( return (
<TouchableOpacity <TouchableOpacity
...@@ -133,10 +134,12 @@ const FilterWeekView = ({ ...@@ -133,10 +134,12 @@ const FilterWeekView = ({
right: 2, right: 2,
zIndex: 10, zIndex: 10,
backgroundColor: R.colors.blue, backgroundColor: R.colors.blue,
} },
]} ]}
activeOpacity={0.7}> activeOpacity={0.7}>
<Text style={styles.eventTitle} numberOfLines={height > 60 ? 2 : 1}> <Text
style={styles.eventTitle}
numberOfLines={height > 60 ? 2 : 1}>
{event.title} {event.title}
</Text> </Text>
{height > 40 && ( {height > 40 && (
...@@ -168,5 +171,4 @@ const FilterWeekView = ({ ...@@ -168,5 +171,4 @@ const FilterWeekView = ({
); );
}; };
export default FilterWeekView; export default FilterWeekView;
...@@ -46,32 +46,42 @@ const FilterDay = ({navigation}) => { ...@@ -46,32 +46,42 @@ const FilterDay = ({navigation}) => {
const mockEvents = createMockEvents(); const mockEvents = createMockEvents();
const formatDateToString = (date) => { const formatDateToString = date => {
const year = date.getFullYear(); const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
}; };
const getEventsForDate = (date) => { const getEventsForDate = date => {
const dateStr = formatDateToString(date); const dateStr = formatDateToString(date);
return mockEvents.filter(event => event.date === dateStr); return mockEvents.filter(event => event.date === dateStr);
}; };
const getDayName = (date) => { const getDayName = date => {
const days = ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7']; const days = ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'];
return days[date.getDay()]; return days[date.getDay()];
}; };
const getMonthName = (monthIndex) => { const getMonthName = monthIndex => {
const months = [ const months = [
'Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6', 'Tháng 1',
'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12', 'Tháng 2',
'Tháng 3',
'Tháng 4',
'Tháng 5',
'Tháng 6',
'Tháng 7',
'Tháng 8',
'Tháng 9',
'Tháng 10',
'Tháng 11',
'Tháng 12',
]; ];
return months[monthIndex]; return months[monthIndex];
}; };
const handleMonthSelect = (monthIndex) => { const handleMonthSelect = monthIndex => {
const newDate = new Date(currentDate); const newDate = new Date(currentDate);
newDate.setMonth(monthIndex); newDate.setMonth(monthIndex);
setCurrentDate(newDate); setCurrentDate(newDate);
...@@ -126,7 +136,7 @@ const FilterDay = ({navigation}) => { ...@@ -126,7 +136,7 @@ const FilterDay = ({navigation}) => {
const topPosition = (startTotalMinutes / 60) * HOUR_HEIGHT; const topPosition = (startTotalMinutes / 60) * HOUR_HEIGHT;
const height = (durationMinutes / 60) * HOUR_HEIGHT; const height = (durationMinutes / 60) * HOUR_HEIGHT;
return { topPosition, height }; return {topPosition, height};
}; };
return ( return (
...@@ -143,7 +153,6 @@ const FilterDay = ({navigation}) => { ...@@ -143,7 +153,6 @@ const FilterDay = ({navigation}) => {
handleMonthSelect={handleMonthSelect} handleMonthSelect={handleMonthSelect}
toggleMonthPicker={toggleMonthPicker} toggleMonthPicker={toggleMonthPicker}
calculateEventPosition={calculateEventPosition} calculateEventPosition={calculateEventPosition}
/> />
); );
}; };
......
...@@ -29,10 +29,10 @@ const styles = StyleSheet.create({ ...@@ -29,10 +29,10 @@ const styles = StyleSheet.create({
paddingHorizontal: 15, paddingHorizontal: 15,
paddingVertical: 12, paddingVertical: 12,
alignItems: 'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
maxWidth:70, maxWidth: 70,
borderRightWidth:1, borderRightWidth: 1,
borderRightColor:R.colors.gray, borderRightColor: R.colors.gray,
}, },
dayName: { dayName: {
fontSize: R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
......
import React from 'react'; import React from 'react';
import { import {View, Text, TouchableOpacity, ScrollView} from 'react-native';
View,
Text,
TouchableOpacity,
ScrollView,
} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
import styles from './style'; import styles from './style';
const FilterDayView = (props) => { const FilterDayView = props => {
const { const {
selectedDate, selectedDate,
showMonthPicker, showMonthPicker,
...@@ -16,9 +11,10 @@ const FilterDayView = (props) => { ...@@ -16,9 +11,10 @@ const FilterDayView = (props) => {
panResponder, panResponder,
getEventsForDate, getEventsForDate,
getDayName, getDayName,
calculateEventPosition, } = props; calculateEventPosition,
} = props;
const isToday = (date) => { const isToday = date => {
const today = new Date(); const today = new Date();
return ( return (
date.getDate() === today.getDate() && date.getDate() === today.getDate() &&
...@@ -28,22 +24,21 @@ const FilterDayView = (props) => { ...@@ -28,22 +24,21 @@ const FilterDayView = (props) => {
}; };
const renderMonthPicker = () => { const renderMonthPicker = () => {
if (!showMonthPicker) return null; if (!showMonthPicker) return null;
} };
const renderDateInfo = () => { const renderDateInfo = () => {
return ( return (
<View style={{backgroundColor: R.colors.grayBorderInputTextHeader}}> <View style={{backgroundColor: R.colors.grayBorderInputTextHeader}}>
<View style={styles.dateInfoContainer}> <View style={styles.dateInfoContainer}>
<Text style={styles.dayName}>{getDayName(selectedDate)}</Text> <Text style={styles.dayName}>{getDayName(selectedDate)}</Text>
<Text style={ <Text
isToday(selectedDate) style={
? styles.dayNumberToday isToday(selectedDate) ? styles.dayNumberToday : styles.dayNumber
: styles.dayNumber }>
{selectedDate.getDate()}
}>{selectedDate.getDate()}</Text> </Text>
</View> </View>
</View> </View>
); );
}; };
...@@ -57,10 +52,9 @@ const FilterDayView = (props) => { ...@@ -57,10 +52,9 @@ const FilterDayView = (props) => {
ref={scrollViewRef} ref={scrollViewRef}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
contentContainerStyle={styles.scrollContent}> contentContainerStyle={styles.scrollContent}>
<View style={styles.timelineContainer}> <View style={styles.timelineContainer}>
<View style={styles.timeLabelsColumn}> <View style={styles.timeLabelsColumn}>
{hours.map((hour) => { {hours.map(hour => {
const timeStr = hour.toString().padStart(2, '0') + ':00'; const timeStr = hour.toString().padStart(2, '0') + ':00';
return ( return (
<View key={hour} style={styles.timeSlot}> <View key={hour} style={styles.timeSlot}>
...@@ -71,12 +65,15 @@ const FilterDayView = (props) => { ...@@ -71,12 +65,15 @@ const FilterDayView = (props) => {
</View> </View>
<View style={styles.eventsColumn}> <View style={styles.eventsColumn}>
{hours.map((hour) => ( {hours.map(hour => (
<View key={hour} style={styles.gridLine} /> <View key={hour} style={styles.gridLine} />
))} ))}
{selectedEvents.map((event) => { {selectedEvents.map(event => {
const { topPosition, height } = calculateEventPosition(event.time, event.endTime); const {topPosition, height} = calculateEventPosition(
event.time,
event.endTime,
);
return ( return (
<TouchableOpacity <TouchableOpacity
...@@ -91,10 +88,12 @@ const FilterDayView = (props) => { ...@@ -91,10 +88,12 @@ const FilterDayView = (props) => {
right: 15, right: 15,
zIndex: 10, zIndex: 10,
backgroundColor: R.colors.blue, backgroundColor: R.colors.blue,
} },
]} ]}
activeOpacity={0.7}> activeOpacity={0.7}>
<Text style={styles.eventTitle} numberOfLines={height > 60 ? 2 : 1}> <Text
style={styles.eventTitle}
numberOfLines={height > 60 ? 2 : 1}>
{event.title} {event.title}
</Text> </Text>
{height > 40 && ( {height > 40 && (
......
...@@ -16,11 +16,13 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -16,11 +16,13 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
const [showBottomSheet, setShowBottomSheet] = useState(false); const [showBottomSheet, setShowBottomSheet] = useState(false);
// B3: Tham chiếu animation // B3: Tham chiếu animation
const bottomSheetTranslateY = useRef(new Animated.Value(BOTTOM_SHEET_HEIGHT)).current; const bottomSheetTranslateY = useRef(
new Animated.Value(BOTTOM_SHEET_HEIGHT),
).current;
// ==================== HÀM TIỆN ÍCH ==================== // ==================== HÀM TIỆN ÍCH ====================
// T1: Định dạng ngày thành chuỗi // T1: Định dạng ngày thành chuỗi
const formatDateToString = (date) => { const formatDateToString = date => {
const year = date.getFullYear(); const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0');
...@@ -28,7 +30,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -28,7 +30,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}; };
// T2: Định dạng ngày để hiển thị // T2: Định dạng ngày để hiển thị
const formatDateToDisplay = (date) => { const formatDateToDisplay = date => {
const day = date.getDate().toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear(); const year = date.getFullYear();
...@@ -36,7 +38,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -36,7 +38,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}; };
// T3: Chuyển đổi chuỗi thành ngày // T3: Chuyển đổi chuỗi thành ngày
const parseLocalDate = (dateString) => { const parseLocalDate = dateString => {
const [year, month, day] = dateString.split('-').map(Number); const [year, month, day] = dateString.split('-').map(Number);
return new Date(year, month - 1, day); return new Date(year, month - 1, day);
}; };
...@@ -176,7 +178,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -176,7 +178,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
const allEvents = [...events, ...mockEvents]; const allEvents = [...events, ...mockEvents];
// D3: Hàm truy vấn sự kiện // D3: Hàm truy vấn sự kiện
const getEventsForDate = (date) => { const getEventsForDate = date => {
const dateStr = formatDateToString(date); const dateStr = formatDateToString(date);
return allEvents.filter(event => event.date === dateStr); return allEvents.filter(event => event.date === dateStr);
}; };
...@@ -216,11 +218,11 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -216,11 +218,11 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}, [currentDate]); }, [currentDate]);
// L2: Hàm kiểm tra ngày tháng // L2: Hàm kiểm tra ngày tháng
const isCurrentMonth = (date) => { const isCurrentMonth = date => {
return date.getMonth() === currentDate.getMonth(); return date.getMonth() === currentDate.getMonth();
}; };
const isToday = (date) => { const isToday = date => {
const today = new Date(); const today = new Date();
return ( return (
date.getDate() === today.getDate() && date.getDate() === today.getDate() &&
...@@ -251,7 +253,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -251,7 +253,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}).start(); }).start();
} }
}, },
}) }),
).current; ).current;
// A2: Hàm animation Bottom Sheet // A2: Hàm animation Bottom Sheet
...@@ -277,7 +279,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -277,7 +279,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
// ==================== XỬ LÝ SỰ KIỆN ==================== // ==================== XỬ LÝ SỰ KIỆN ====================
// X1: Xử lý điều hướng // X1: Xử lý điều hướng
const navigateMonth = (direction) => { const navigateMonth = direction => {
const newDate = new Date(currentDate); const newDate = new Date(currentDate);
if (direction === 'prev') { if (direction === 'prev') {
newDate.setMonth(newDate.getMonth() - 1); newDate.setMonth(newDate.getMonth() - 1);
...@@ -292,7 +294,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -292,7 +294,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}; };
// X2: Xử lý chọn ngày // X2: Xử lý chọn ngày
const handleDatePress = (date) => { const handleDatePress = date => {
const dateStr = formatDateToString(date); const dateStr = formatDateToString(date);
const dayEvents = getEventsForDate(date); const dayEvents = getEventsForDate(date);
...@@ -305,7 +307,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => { ...@@ -305,7 +307,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}; };
// X3: Xử lý tương tác sự kiện // X3: Xử lý tương tác sự kiện
const handleEventPress = (event) => { const handleEventPress = event => {
onEventPress?.(event); onEventPress?.(event);
}; };
......
...@@ -119,9 +119,9 @@ const styles = StyleSheet.create({ ...@@ -119,9 +119,9 @@ const styles = StyleSheet.create({
fontFamily: R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
textAlign: 'center', textAlign: 'center',
}, },
containerBottomSheet:{ containerBottomSheet: {
flex:1, flex: 1,
marginBottom:10, marginBottom: 10,
}, },
modalBackdrop: { modalBackdrop: {
...@@ -137,7 +137,6 @@ const styles = StyleSheet.create({ ...@@ -137,7 +137,6 @@ const styles = StyleSheet.create({
}, },
bottomSheetContent: { bottomSheetContent: {
height: BOTTOM_SHEET_HEIGHT, height: BOTTOM_SHEET_HEIGHT,
}, },
dragHandle: { dragHandle: {
width: 40, width: 40,
...@@ -176,7 +175,7 @@ const styles = StyleSheet.create({ ...@@ -176,7 +175,7 @@ const styles = StyleSheet.create({
fontWeight: '400', fontWeight: '400',
}, },
eventsScrollView: { eventsScrollView: {
paddingTop:10, paddingTop: 10,
}, },
noEventsContainer: { noEventsContainer: {
flex: 1, flex: 1,
...@@ -196,7 +195,7 @@ const styles = StyleSheet.create({ ...@@ -196,7 +195,7 @@ const styles = StyleSheet.create({
borderRadius: 12, borderRadius: 12,
padding: 15, padding: 15,
marginBottom: 10, marginBottom: 10,
marginHorizontal:15, marginHorizontal: 15,
borderLeftWidth: 4, borderLeftWidth: 4,
borderLeftColor: R.colors.blue500, borderLeftColor: R.colors.blue500,
shadowColor: R.colors.black, shadowColor: R.colors.black,
......
...@@ -11,8 +11,8 @@ import { ...@@ -11,8 +11,8 @@ import {
SafeAreaView, SafeAreaView,
} from 'react-native'; } from 'react-native';
import R from '../../assets/R'; import R from '../../assets/R';
import { styles, CELL_WIDTH, BOTTOM_SHEET_HEIGHT } from './style'; import {styles, CELL_WIDTH, BOTTOM_SHEET_HEIGHT} from './style';
import { useNavigation } from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import * as SCREENNAME from '../../routers/ScreenNames'; import * as SCREENNAME from '../../routers/ScreenNames';
const ClassScheduleView = ({ const ClassScheduleView = ({
...@@ -37,8 +37,18 @@ const ClassScheduleView = ({ ...@@ -37,8 +37,18 @@ const ClassScheduleView = ({
const navigation = useNavigation(); const navigation = useNavigation();
const renderHeader = () => { const renderHeader = () => {
const monthNames = [ const monthNames = [
'Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6', 'Tháng 1',
'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12', 'Tháng 2',
'Tháng 3',
'Tháng 4',
'Tháng 5',
'Tháng 6',
'Tháng 7',
'Tháng 8',
'Tháng 9',
'Tháng 10',
'Tháng 11',
'Tháng 12',
]; ];
return ( return (
...@@ -93,7 +103,6 @@ const ClassScheduleView = ({ ...@@ -93,7 +103,6 @@ const ClassScheduleView = ({
]} ]}
onPress={() => handleDatePress(date)} onPress={() => handleDatePress(date)}
activeOpacity={0.7}> activeOpacity={0.7}>
<Text <Text
style={[ style={[
styles.dayText, styles.dayText,
...@@ -109,9 +118,7 @@ const ClassScheduleView = ({ ...@@ -109,9 +118,7 @@ const ClassScheduleView = ({
{dayEvents.slice(0, 2).map((event, eventIndex) => ( {dayEvents.slice(0, 2).map((event, eventIndex) => (
<TouchableOpacity <TouchableOpacity
key={event.id} key={event.id}
style={[ style={[styles.eventBar]}
styles.eventBar,
]}
onPress={() => handleEventPress(event)}> onPress={() => handleEventPress(event)}>
<Text style={styles.eventBarText} numberOfLines={1}> <Text style={styles.eventBarText} numberOfLines={1}>
{event.title} {event.title}
...@@ -150,9 +157,7 @@ const ClassScheduleView = ({ ...@@ -150,9 +157,7 @@ const ClassScheduleView = ({
return ( return (
<View style={styles.bottomSheetContent}> <View style={styles.bottomSheetContent}>
<View style={styles.dragHandle} > <View style={styles.dragHandle}></View>
</View>
<View style={styles.bottomSheetHeader}> <View style={styles.bottomSheetHeader}>
<Text style={styles.bottomSheetTitle}> <Text style={styles.bottomSheetTitle}>
...@@ -171,15 +176,16 @@ const ClassScheduleView = ({ ...@@ -171,15 +176,16 @@ const ClassScheduleView = ({
<View style={styles.noEventsContainer}> <View style={styles.noEventsContainer}>
<Text style={styles.noEventsText}>Không có s kin nào</Text> <Text style={styles.noEventsText}>Không có s kin nào</Text>
</View> </View>
) : ) : (
(selectedEvents.map((event, index) => ( selectedEvents.map((event, index) => (
<View style={styles.containerBottomSheet}> <View style={styles.containerBottomSheet}>
<TouchableOpacity <TouchableOpacity
key={event.id} key={event.id}
style={styles.eventCard} style={styles.eventCard}
onPress={() => navigation.navigate(SCREENNAME.DETAILSCHEDULE, { event })} onPress={() =>
navigation.navigate(SCREENNAME.DETAILSCHEDULE, {event})
}
activeOpacity={0.7}> activeOpacity={0.7}>
<View style={styles.eventTimeContainer}> <View style={styles.eventTimeContainer}>
<Text style={styles.eventTime}> <Text style={styles.eventTime}>
{event.time} {event.time}
...@@ -213,21 +219,19 @@ const ClassScheduleView = ({ ...@@ -213,21 +219,19 @@ const ClassScheduleView = ({
transparent={true} transparent={true}
animationType="none" animationType="none"
onRequestClose={handleCloseBottomSheet}> onRequestClose={handleCloseBottomSheet}>
<TouchableOpacity <TouchableOpacity
style={styles.modalBackdrop} style={styles.modalBackdrop}
activeOpacity={1} activeOpacity={1}
onPress={handleCloseBottomSheet}> onPress={handleCloseBottomSheet}>
<Animated.View <Animated.View
style={[ style={[
styles.bottomSheet, styles.bottomSheet,
{ {
transform: [{ translateY: bottomSheetTranslateY }], transform: [{translateY: bottomSheetTranslateY}],
}, },
]} ]}
{...panResponder.panHandlers}> {...panResponder.panHandlers}>
<TouchableOpacity activeOpacity={1} > <TouchableOpacity activeOpacity={1}>
{renderBottomSheetContent()} {renderBottomSheetContent()}
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>
...@@ -237,7 +241,6 @@ const ClassScheduleView = ({ ...@@ -237,7 +241,6 @@ const ClassScheduleView = ({
}; };
return ( return (
<View style={styles.container}> <View style={styles.container}>
<ScrollView showsVerticalScrollIndicator={false}> <ScrollView showsVerticalScrollIndicator={false}>
<View style={styles.body}> <View style={styles.body}>
...@@ -251,6 +254,4 @@ const ClassScheduleView = ({ ...@@ -251,6 +254,4 @@ const ClassScheduleView = ({
); );
}; };
export default ClassScheduleView; export default ClassScheduleView;
import React, { useState } from 'react'; import React, {useState} from 'react';
import {Text, View, StyleSheet} from 'react-native'; import {Text, View, StyleSheet} from 'react-native';
import CompensateView from './view'; import CompensateView from './view';
const Compensate = (props) => { const Compensate = props => {
const [dataList, setDataList] = useState([ const [dataList, setDataList] = useState([
{id: 1, classCode: 'ATTT2024.1', rest: 5, compensate: 0, total: 25}, {id: 1, classCode: 'ATTT2024.1', rest: 5, compensate: 0, total: 25},
{id: 2, classCode: 'ATTT2024.2', rest: 4, compensate: 1, total: 25}, {id: 2, classCode: 'ATTT2024.2', rest: 4, compensate: 1, total: 25},
...@@ -40,9 +40,7 @@ const Compensate = (props) => { ...@@ -40,9 +40,7 @@ const Compensate = (props) => {
{id: 29, classCode: 'MMT2024.4', rest: 3, compensate: 2, total: 25}, {id: 29, classCode: 'MMT2024.4', rest: 3, compensate: 2, total: 25},
{id: 30, classCode: 'MMT2024.5', rest: 6, compensate: 0, total: 25}, {id: 30, classCode: 'MMT2024.5', rest: 6, compensate: 0, total: 25},
]); ]);
return ( return <CompensateView dataList={dataList} />;
<CompensateView dataList={dataList} />
);
}; };
export default Compensate; export default Compensate;
import React, { useState } from 'react'; import React, {useState} from 'react';
import {Text, View, StyleSheet} from 'react-native'; import {Text, View, StyleSheet} from 'react-native';
import DetailCompensateView from './view'; import DetailCompensateView from './view';
const DetailCompensate = (props) => { const DetailCompensate = props => {
const [item, setItem] = useState({ const [item, setItem] = useState({
rest: 5, rest: 5,
compensate: 0, compensate: 0,
...@@ -17,148 +17,152 @@ const DetailCompensate = (props) => { ...@@ -17,148 +17,152 @@ const DetailCompensate = (props) => {
const [listData, setDataList] = useState([ const [listData, setDataList] = useState([
{ {
id:1, id: 1,
date:'2024-01-01', date: '2024-01-01',
status:'Đã xác nhận', status: 'Đã xác nhận',
dayOfWeek:'Thứ 2', dayOfWeek: 'Thứ 2',
periods:[ periods: [
{ {
id:1, id: 1,
time:'6', time: '6',
}, },
{ {
id:2, id: 2,
time:'7', time: '7',
}, },
{ {
id:3, id: 3,
time:'8', time: '8',
}, },
{ {
id:4, id: 4,
time:'9', time: '9',
} },
], ],
dateStudy:'30/07/2025', dateStudy: '30/07/2025',
location:'Phòng B2.12', location: 'Phòng B2.12',
teacher:'Nguyễn Minh Đức', teacher: 'Nguyễn Minh Đức',
note:'', note: '',
}, },
{ {
id:2, id: 2,
date:'2024-01-01', date: '2024-01-01',
status:'Chờ phê duyệt', status: 'Chờ phê duyệt',
dayOfWeek:'Thứ 2', dayOfWeek: 'Thứ 2',
periods:[ periods: [
{ {
id:1, id: 1,
time:'6', time: '6',
}, },
{ {
id:2, id: 2,
time:'7', time: '7',
}, },
{ {
id:3, id: 3,
time:'8', time: '8',
}, },
{ {
id:4, id: 4,
time:'9', time: '9',
} },
], ],
dateStudy:'30/07/2025', dateStudy: '30/07/2025',
location:'Phòng B2.12', location: 'Phòng B2.12',
teacher:'', teacher: '',
note:'', note: '',
}, },
{ {
id:3, id: 3,
date:'2024-01-01', date: '2024-01-01',
status:'Từ chối', status: 'Từ chối',
dayOfWeek:'Thứ 2', dayOfWeek: 'Thứ 2',
periods:[ periods: [
{ {
id:1, id: 1,
time:'6', time: '6',
}, },
{ {
id:2, id: 2,
time:'7', time: '7',
}, },
{ {
id:3, id: 3,
time:'8', time: '8',
}, },
{ {
id:4, id: 4,
time:'9', time: '9',
} },
], ],
dateStudy:'30/07/2025', dateStudy: '30/07/2025',
location:'Phòng B2.12', location: 'Phòng B2.12',
teacher:'', teacher: '',
note:'', note: '',
}, },
{ {
id:4, id: 4,
date:'2024-01-01', date: '2024-01-01',
status:'Đã xác nhận', status: 'Đã xác nhận',
dayOfWeek:'Thứ 2', dayOfWeek: 'Thứ 2',
periods:[ periods: [
{ {
id:1, id: 1,
time:'6', time: '6',
}, },
{ {
id:2, id: 2,
time:'7', time: '7',
}, },
{ {
id:3, id: 3,
time:'8', time: '8',
}, },
{ {
id:4, id: 4,
time:'9', time: '9',
} },
], ],
dateStudy:'30/07/2025', dateStudy: '30/07/2025',
location:'Phòng B2.12', location: 'Phòng B2.12',
teacher:'', teacher: '',
note:'', note: '',
}, },
{ {
id:5, id: 5,
date:'2024-01-01', date: '2024-01-01',
status:'Đã xác nhận', status: 'Đã xác nhận',
dayOfWeek:'Thứ 2', dayOfWeek: 'Thứ 2',
periods:[ periods: [
{ {
id:1, id: 1,
time:'6', time: '6',
}, },
{ {
id:2, id: 2,
time:'7', time: '7',
}, },
{ {
id:3, id: 3,
time:'8', time: '8',
}, },
{ {
id:4, id: 4,
time:'9', time: '9',
} },
], ],
dateStudy:'30/07/2025', dateStudy: '30/07/2025',
location:'Phòng B2.12', location: 'Phòng B2.12',
teacher:'', teacher: '',
note:'', note: '',
}, },
]) ]);
return ( return (
<DetailCompensateView item={item} listData={listData} itemDetail={itemDetail}/> <DetailCompensateView
item={item}
listData={listData}
itemDetail={itemDetail}
/>
); );
}; };
......
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container:{ container: {
flex:1, flex: 1,
backgroundColor:R.colors.white backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
backgroundColor:R.colors.white backgroundColor: R.colors.white,
}, },
text:{ text: {
fontSize:R.fontsize.fontSizeSubTitle, fontSize: R.fontsize.fontSizeSubTitle,
fontFamily:R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
fontWeight:'400', fontWeight: '400',
color:R.colors.black, color: R.colors.black,
}, },
card:{ card: {
borderRadius:10, borderRadius: 10,
marginVertical:10, marginVertical: 10,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
shadowColor:R.colors.black, shadowColor: R.colors.black,
shadowOffset:{width:0,height:2}, shadowOffset: {width: 0, height: 2},
shadowOpacity:Platform.OS === 'ios' ? 0.25 : 1, shadowOpacity: Platform.OS === 'ios' ? 0.25 : 1,
shadowRadius:5, shadowRadius: 5,
elevation:Platform.OS === 'ios' ? 1 : 2, elevation: Platform.OS === 'ios' ? 1 : 2,
marginHorizontal:15, marginHorizontal: 15,
} },
}) });
export default styles; export default styles;
...@@ -4,7 +4,7 @@ import styles from './style'; ...@@ -4,7 +4,7 @@ import styles from './style';
import Header from '../../../components/Header/Header'; import Header from '../../../components/Header/Header';
import R from '../../../assets/R'; import R from '../../../assets/R';
import Button from '../../../components/Button'; import Button from '../../../components/Button';
const DetailCompensateView = (props) => { const DetailCompensateView = props => {
const {item, listData, itemDetail} = props; const {item, listData, itemDetail} = props;
const getColor = status => { const getColor = status => {
...@@ -26,23 +26,54 @@ const DetailCompensateView = (props) => { ...@@ -26,23 +26,54 @@ const DetailCompensateView = (props) => {
borderTopRightRadius: 10, borderTopRightRadius: 10,
borderTopLeftRadius: 10, borderTopLeftRadius: 10,
}}> }}>
<View style={{borderTopRightRadius:10, borderTopLeftRadius:10, backgroundColor:getColor(item.status)}}> <View
<Text style={[styles.text, {fontSize: R.sizes.sm, paddingHorizontal:10, paddingVertical:2, color:R.colors.white , fontWeight:'bold', fontFamily:R.fonts.fontMedium,}]}> style={{
<Text style={{fontSize: R.sizes.sm ,color:R.colors.white}}>{item.status}</Text> borderTopRightRadius: 10,
borderTopLeftRadius: 10,
backgroundColor: getColor(item.status),
}}>
<Text
style={[
styles.text,
{
fontSize: R.sizes.sm,
paddingHorizontal: 10,
paddingVertical: 2,
color: R.colors.white,
fontWeight: 'bold',
fontFamily: R.fonts.fontMedium,
},
]}>
<Text style={{fontSize: R.sizes.sm, color: R.colors.white}}>
{item.status}
</Text>
</Text> </Text>
</View> </View>
</View> </View>
<View style={{paddingHorizontal:10, paddingTop:3, paddingBottom:10}}> <View style={{paddingHorizontal: 10, paddingTop: 3, paddingBottom: 10}}>
{/* Row 1 */} {/* Row 1 */}
<View <View
style={{ style={{
flexDirection: 'row', flexDirection: 'row',
}}> }}>
<View style={{flex: 1}}> <View style={{flex: 1}}>
<Text style={[styles.text, {fontSize: R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}> <Text
style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Ngày báo ngh:{' '} Ngày báo ngh:{' '}
<Text style={{fontSize: R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}}> <Text
style={{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
}}>
{item.date} {item.date}
</Text> </Text>
</Text> </Text>
...@@ -55,41 +86,103 @@ const DetailCompensateView = (props) => { ...@@ -55,41 +86,103 @@ const DetailCompensateView = (props) => {
</View> </View>
{/* Row 2 */} {/* Row 2 */}
<View> <View>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Thi gian ngh:{' '} <Text
<Text style={{fontSize: R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}}>{item.dayOfWeek} - Tiết:{' '} style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Thi gian ngh:{' '}
<Text
style={{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
}}>
{item.dayOfWeek} - Tiết:{' '}
{item.periods.map((item, index) => { {item.periods.map((item, index) => {
return <Text key={index}>{item.time},</Text>; return <Text key={index}>{item.time},</Text>;
})} })}
- Ngày: {''}{item.dateStudy} - Ngày: {''}
{item.dateStudy}
</Text> </Text>
</Text> </Text>
</View> </View>
{/* Row 3 */} {/* Row 3 */}
<View style={{}}> <View style={{}}>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Địa đim:{' '} <Text
<Text style={{fontSize: R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}}>{item.location}</Text> style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Địa đim:{' '}
<Text
style={{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
}}>
{item.location}
</Text>
</Text> </Text>
</View> </View>
{/* Row 4 */} {/* Row 4 */}
<View style={{}}> <View style={{}}>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Ging viên thay thế:{' '} <Text
<Text style={{fontSize: R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}}>{item.teacher}</Text> style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Ging viên thay thế:{' '}
<Text
style={{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
}}>
{item.teacher}
</Text>
</Text> </Text>
</View> </View>
{/* Row 5 */} {/* Row 5 */}
<View style={{}}> <View style={{}}>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Ghi chú:{' '} <Text
<Text style={{fontSize: R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}}>{item.note}</Text> style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Ghi chú:{' '}
<Text
style={{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
}}>
{item.note}
</Text>
</Text> </Text>
</View> </View>
{item.status === 'Chờ phê duyệt' && (
{ <View style={{alignItems: 'flex-end'}}>
item.status === 'Chờ phê duyệt' && (
<View style={{alignItems:'flex-end'}}>
<Button <Button
title='Huỷ' title="Huỷ"
onPress={()=>{}} onPress={() => {}}
backgroundColor={R.colors.orange} backgroundColor={R.colors.orange}
textColor={R.colors.white} textColor={R.colors.white}
height={25} height={25}
...@@ -101,8 +194,7 @@ const DetailCompensateView = (props) => { ...@@ -101,8 +194,7 @@ const DetailCompensateView = (props) => {
paddingHorizontal={15} paddingHorizontal={15}
/> />
</View> </View>
) )}
}
</View> </View>
</View> </View>
); );
...@@ -112,9 +204,27 @@ const DetailCompensateView = (props) => { ...@@ -112,9 +204,27 @@ const DetailCompensateView = (props) => {
<View style={styles.container}> <View style={styles.container}>
<Header title={'ATTT2024.1'} isBack /> <Header title={'ATTT2024.1'} isBack />
<View style={styles.body}> <View style={styles.body}>
<View style={{alignItems: 'center', marginTop:10}}> <View style={{alignItems: 'center', marginTop: 10}}>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Ngh / Bù / Tng</Text> <Text
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}]}> style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Ngh / Bù / Tng
</Text>
<Text
style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
},
]}>
{itemDetail?.rest} / {itemDetail?.compensate} / {itemDetail?.total} {itemDetail?.rest} / {itemDetail?.compensate} / {itemDetail?.total}
</Text> </Text>
</View> </View>
......
import { StyleSheet, Text, View, Dimensions } from 'react-native' import {StyleSheet, Text, View, Dimensions} from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
//B1: Xác định chiều rộng cột đầu tiên //B1: Xác định chiều rộng cột đầu tiên
const width_first = 100; const width_first = 100;
//B2: Xác định chiều rộng của 15 cột tiếp theo //B2: Xác định chiều rộng của 15 cột tiếp theo
const width_second = 110; const width_second = 110;
//B3: Xác định số tiết diễn ra trong 1 ngày -> để có kích thước bảng //B3: Xác định số tiết diễn ra trong 1 ngày -> để có kích thước bảng
const period_count = 15; const period_count = 15;
//B4: Xác định chiều rộng của bảng //B4: Xác định chiều rộng của bảng
const total_width_table = width_first + (width_second * period_count); const total_width_table = width_first + width_second * period_count;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container:{ container: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
padding:15, padding: 15,
}, },
containerInput:{ containerInput: {
flexDirection:'row', flexDirection: 'row',
justifyContent:'space-between', justifyContent: 'space-between',
marginBottom:15 marginBottom: 15,
}, },
txtSubtitle:{ txtSubtitle: {
fontWeight:'600', fontWeight: '600',
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
color:R.colors.black, color: R.colors.black,
}, },
containerDropDown:{ containerDropDown: {
marginBottom:15 marginBottom: 15,
}, },
btnRegister:{ btnRegister: {
alignItems:'flex-end', alignItems: 'flex-end',
}, },
btnRegister2:{ btnRegister2: {
marginVertical:15 marginVertical: 15,
}, },
//Header bảng lịch //Header bảng lịch
tableContainer:{ tableContainer: {
marginTop:15, marginTop: 15,
borderWidth:1, borderWidth: 1,
borderColor:R.colors.gray, borderColor: R.colors.gray,
width:total_width_table, width: total_width_table,
}, },
headerRow: { headerRow: {
...@@ -62,41 +62,41 @@ container:{ ...@@ -62,41 +62,41 @@ container:{
}, },
dateColumn: { dateColumn: {
height: 40, height: 40,
width:width_first, width: width_first,
paddingHorizontal: 10, paddingHorizontal: 10,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: R.colors.blue2, backgroundColor: R.colors.blue2,
borderRightWidth:1, borderRightWidth: 1,
borderRightColor:R.colors.gray, borderRightColor: R.colors.gray,
}, },
periodColumn: { periodColumn: {
height: 40, height: 40,
width:width_second, width: width_second,
paddingHorizontal: 5, paddingHorizontal: 5,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: R.colors.blue2, backgroundColor: R.colors.blue2,
borderRightWidth:1, borderRightWidth: 1,
borderRightColor:R.colors.gray, borderRightColor: R.colors.gray,
}, },
dateBody:{ dateBody: {
width: width_first, width: width_first,
minHeight: 40, minHeight: 40,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
borderRightWidth:1, borderRightWidth: 1,
borderRightColor:R.colors.gray, borderRightColor: R.colors.gray,
}, },
periodBody:{ periodBody: {
width: width_second, width: width_second,
padding:5, padding: 5,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
borderRightWidth:1, borderRightWidth: 1,
borderRightColor:R.colors.gray, borderRightColor: R.colors.gray,
}, },
dataRow: { dataRow: {
flexDirection: 'row', flexDirection: 'row',
...@@ -111,25 +111,23 @@ container:{ ...@@ -111,25 +111,23 @@ container:{
minHeight: 50, minHeight: 50,
width: '100%', width: '100%',
}, },
dateText:{ dateText: {
fontSize: R.sizes.sm, fontSize: R.sizes.sm,
fontWeight: '400', fontWeight: '400',
fontFamily: R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
color: R.colors.black, color: R.colors.black,
}, },
percentText:{ percentText: {
fontSize: R.sizes.sm, fontSize: R.sizes.sm,
fontWeight: '500', fontWeight: '500',
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
color: R.colors.black, color: R.colors.black,
}, },
codeText:{ codeText: {
fontSize: R.sizes.sm, fontSize: R.sizes.sm,
fontWeight: '500', fontWeight: '500',
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
color: R.colors.black, color: R.colors.black,
}, },
});
export default styles;
})
export default styles
\ No newline at end of file
...@@ -17,8 +17,8 @@ import CheckBox from '../../../components/CheckBox'; ...@@ -17,8 +17,8 @@ import CheckBox from '../../../components/CheckBox';
const CompensateRegisterView = props => { const CompensateRegisterView = props => {
const {isShow, setShowSchedule, scheduleData, onCheckboxChange} = props; const {isShow, setShowSchedule, scheduleData, onCheckboxChange} = props;
const getCheckColor = (item) => { const getCheckColor = item => {
if ( item?.breakTime=== item?.totalSession && item?.percent === '100%') { if (item?.breakTime === item?.totalSession && item?.percent === '100%') {
return R.colors.blue; return R.colors.blue;
} }
return R.colors.red; return R.colors.red;
...@@ -36,7 +36,9 @@ const CompensateRegisterView = props => { ...@@ -36,7 +36,9 @@ const CompensateRegisterView = props => {
</View> </View>
{Array.from({length: 15}, (_, i) => ( {Array.from({length: 15}, (_, i) => (
<View key={i} style={[styles.periodColumn, {backgroundColor: R.colors.blue3}]}> <View
key={i}
style={[styles.periodColumn, {backgroundColor: R.colors.blue3}]}>
<Text style={styles.headerText}>Tiết {i + 1} </Text> <Text style={styles.headerText}>Tiết {i + 1} </Text>
</View> </View>
))} ))}
...@@ -68,31 +70,32 @@ const CompensateRegisterView = props => { ...@@ -68,31 +70,32 @@ const CompensateRegisterView = props => {
<CheckBox <CheckBox
checked={period.available} checked={period.available}
value={period.available} value={period.available}
onValueChange={value => onCheckboxChange(index, periodIndex, value)} onValueChange={value =>
onCheckboxChange(index, periodIndex, value)
}
size={20} size={20}
labelStyle={styles.label} labelStyle={styles.label}
checkedColor={R.colors.main} checkedColor={R.colors.main}
tickColor={R.colors.white} tickColor={R.colors.white}
/> />
<View style={{flexDirection:'row'}}> <View style={{flexDirection: 'row'}}>
<Text <Text
style={[ style={[
styles.percentText, styles.percentText,
period.available && styles.availableText, period.available && styles.availableText,
{color:getCheckColor(period)} {color: getCheckColor(period)},
]}> ]}>
{period.percent} {period.percent}
</Text> </Text>
<Text <Text
style={[ style={[
styles.codeText, styles.codeText,
{color:getCheckColor(period), marginLeft:3}, {color: getCheckColor(period), marginLeft: 3},
period.available && styles.availableText, period.available && styles.availableText,
]}> ]}>
({period.breakTime}/{period.totalSession}) ({period.breakTime}/{period.totalSession})
</Text> </Text>
</View> </View>
</View> </View>
</View> </View>
))} ))}
...@@ -210,20 +213,19 @@ const CompensateRegisterView = props => { ...@@ -210,20 +213,19 @@ const CompensateRegisterView = props => {
/> />
</View> </View>
<ScrollView <ScrollView showsHorizontalScrollIndicator={false} horizontal>
showsHorizontalScrollIndicator={false} {renderSchedule()}
horizontal>{renderSchedule()}</ScrollView> </ScrollView>
<View style={styles.btnRegister2}> <View style={styles.btnRegister2}>
<Button <Button
title={'Đăng kí dạy bù'} title={'Đăng kí dạy bù'}
backgroundColor={R.colors.blue} backgroundColor={R.colors.blue}
textColor={R.colors.white} textColor={R.colors.white}
onPress={()=>{}} onPress={() => {}}
fontSize={R.sizes.sm} fontSize={R.sizes.sm}
fontFamily={R.fonts.fontMedium} fontFamily={R.fonts.fontMedium}
height={35} height={35}
containerStyle={{paddingHorizontal: 15, borderRadius: 10}} containerStyle={{paddingHorizontal: 15, borderRadius: 10}}
/> />
</View> </View>
</View> </View>
......
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../assets/R' import R from '../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container:{ container: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
}, },
card: { card: {
borderRadius: 10, borderRadius: 10,
padding: 5, padding: 5,
marginTop: 15, marginTop: 15,
marginBottom:5, marginBottom: 5,
marginHorizontal: 15, marginHorizontal: 15,
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
...@@ -44,7 +44,7 @@ const styles = StyleSheet.create({ ...@@ -44,7 +44,7 @@ const styles = StyleSheet.create({
containerCard: { containerCard: {
padding: 10, padding: 10,
borderRadius: 10, borderRadius: 10,
marginVertical:10, marginVertical: 10,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
shadowColor: R.colors.black, shadowColor: R.colors.black,
shadowOffset: {width: 0, height: 2}, shadowOffset: {width: 0, height: 2},
...@@ -62,18 +62,17 @@ const styles = StyleSheet.create({ ...@@ -62,18 +62,17 @@ const styles = StyleSheet.create({
}, },
btnRight: {}, btnRight: {},
btnRegister:{ btnRegister: {
borderRadius:10, borderRadius: 10,
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
marginHorizontal:15, marginHorizontal: 15,
marginVertical:10, marginVertical: 10,
backgroundColor:R.colors.blue, backgroundColor: R.colors.blue,
borderRadius:10, borderRadius: 10,
padding:5, padding: 5,
height:35 height: 35,
} },
});
})
export default styles export default styles;
import React from 'react'; import React from 'react';
import {Text, View, TouchableOpacity, StyleSheet, FlatList, Image} from 'react-native'; import {
Text,
View,
TouchableOpacity,
StyleSheet,
FlatList,
Image,
} from 'react-native';
import styles from './style'; import styles from './style';
import Header from '../../components/Header/Header'; import Header from '../../components/Header/Header';
import R from '../../assets/R'; import R from '../../assets/R';
import*as SCREENNAME from '../../routers/ScreenNames'; import * as SCREENNAME from '../../routers/ScreenNames';
import { useNavigation } from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
const CompensateView = (props) => { const CompensateView = props => {
const {dataList} = props; const {dataList} = props;
const navigation = useNavigation(); const navigation = useNavigation();
const renderItem = ({item}) => { const renderItem = ({item}) => {
...@@ -29,9 +36,27 @@ const CompensateView = (props) => { ...@@ -29,9 +36,27 @@ const CompensateView = (props) => {
</Text> </Text>
</View> </View>
<View style={{alignItems:'center'}}> <View style={{alignItems: 'center'}}>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Ngh / Bù / Tng</Text> <Text
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:400, fontFamily:R.fonts.fontRegular}]}> style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Ngh / Bù / Tng
</Text>
<Text
style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 400,
fontFamily: R.fonts.fontRegular,
},
]}>
{item.rest} / {item.compensate} / {item.total} {item.rest} / {item.compensate} / {item.total}
</Text> </Text>
</View> </View>
...@@ -53,7 +78,17 @@ const CompensateView = (props) => { ...@@ -53,7 +78,17 @@ const CompensateView = (props) => {
<View style={styles.body}> <View style={styles.body}>
<View style={styles.card}> <View style={styles.card}>
<TouchableOpacity style={styles.btnCard}> <TouchableOpacity style={styles.btnCard}>
<Text style={[styles.text, {fontSize:R.fontsize.fontSizeContent , fontWeight:600, fontFamily:R.fonts.fontMedium}]}>Hc k 2, Năm 2025</Text> <Text
style={[
styles.text,
{
fontSize: R.fontsize.fontSizeContent,
fontWeight: 600,
fontFamily: R.fonts.fontMedium,
},
]}>
Hc k 2, Năm 2025
</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<FlatList <FlatList
...@@ -63,8 +98,12 @@ const CompensateView = (props) => { ...@@ -63,8 +98,12 @@ const CompensateView = (props) => {
vertical vertical
keyExtractor={(item, index) => `${index}`} keyExtractor={(item, index) => `${index}`}
/> />
<TouchableOpacity style={styles.btnRegister} onPress={ () => navigation.navigate(SCREENNAME.REGISTERMAKEUP)}> <TouchableOpacity
<Text style={[styles.text, {color:R.colors.white}]}>Đăng kí báo bù</Text> style={styles.btnRegister}
onPress={() => navigation.navigate(SCREENNAME.REGISTERMAKEUP)}>
<Text style={[styles.text, {color: R.colors.white}]}>
Đăng kí báo bù
</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
......
import React, { useState } from 'react'; import React, {useState} from 'react';
import {Text, View, StyleSheet} from 'react-native'; import {Text, View, StyleSheet} from 'react-native';
import DetailEmailView from './view'; import DetailEmailView from './view';
const DetailEmail = (props) => { const DetailEmail = props => {
const [incoming_document, setIncomingDocument] = useState({ const [incoming_document, setIncomingDocument] = useState({
title:'Đăng ký tham gia TechX 2025 - Định hình tương lai công nghệ!', title: 'Đăng ký tham gia TechX 2025 - Định hình tương lai công nghệ!',
avatar:'https://i.pinimg.com/736x/a5/71/ca/a571cac1f9e27c642f3b5e13f76f87fb.jpg', avatar:
name:'Vũ công bình', 'https://i.pinimg.com/736x/a5/71/ca/a571cac1f9e27c642f3b5e13f76f87fb.jpg',
date:'27/07/2025', name: 'Vũ công bình',
from:'ducnm@.abc.com', date: '27/07/2025',
cc:[{id:1, name:'ducnm@.abc.com'},{id:2, name:'ducnm@.abc.com'},{id:3, name:'ducnm@.abc.com'}, {id:4, name:'ducnm@.abc.com'}, {id:5, name:'ducnm@.abc.com'}, {id:6, name:'ducnm@.abc.com'}, {id:7, name:'ducnm@.abc.com'}, {id:8, name:'ducnm@.abc.com'}, {id:9, name:'ducnm@.abc.com'}, {id:10, name:'ducnm@.abc.com'}, {id:11, name:'ducnm@.abc.com'}, {id:12, name:'ducnm@.abc.com'}, {id:13, name:'ducnm@.abc.com'}, {id:14, name:'ducnm@.abc.com'}, {id:15, name:'ducnm@.abc.com'}, {id:16, name:'ducnm@.abc.com'}, {id:17, name:'ducnm@.abc.com'}, {id:18, name:'ducnm@.abc.com'}, {id:19, name:'ducnm@.abc.com'}, {id:20, name:'ducnm@.abc.com'}], from: 'ducnm@.abc.com',
bcc:'ducnm@.abc.com', cc: [
to:'ducnm@.abc.com', {id: 1, name: 'ducnm@.abc.com'},
content: "Kính gửi toàn thể Anh/Chị CBNV,\n\nTheo cập nhật mới nhất từ cơ quan khí tượng, bão số 3 (tên quốc tế: Wipha) hiện đang cách Quảng Ninh – Hải Phòng khoảng 233km về phía Đông. Trong 12 giờ qua, bão đã suy yếu 3 cấp (còn cấp 9), tuy nhiên dự báo sẽ mạnh lên khi đi vào khu vực Vịnh Bắc Bộ trong hôm nay (21/7).\n\nDự kiến từ chiều và tối nay, các tỉnh vùng ven biển và khu vực đồng bằng Bắc Bộ, bao gồm cả Hà Nội, có thể xảy ra mưa to, gió lớn, thậm chí có hiện tượng ngập úng cục bộ, cây đổ, mất điện.\n\nĐể đảm bảo an toàn cho toàn thể CBNV, công ty xin lưu ý:\n\n1. CBNV đang sinh sống tại khu vực bị ảnh hưởng bởi mưa bão có thể chủ động làm việc từ xa (remote) vào ngày mai nếu thấy điều kiện di chuyển không an toàn.\n\n2. Trong mọi trường hợp, ưu tiên cao nhất là an toàn cá nhân. Nếu gặp tình trạng ngập sâu, cây gãy đổ, đường trơn trượt nguy hiểm... vui lòng không cố gắng di chuyển đến văn phòng.\n\n3. Các quản lý trực tiếp chủ động nhắc nhở thành viên trong nhóm, và tạo điều kiện linh hoạt để đảm bảo công việc được duy trì hiệu quả, dù làm việc tại nhà.\n\nCông ty khuyến nghị anh/chị:\n\n- Hạn chế ra ngoài khi mưa gió lớn, kiểm tra và gia cố nhà cửa nếu cần thiết;\n- Liên hệ ngay với quản lý hoặc bộ phận HCNS nếu có tình huống khẩn cấp.\n\nRất mong anh/chị giữ gìn sức khỏe, an toàn và chủ động phối hợp trong thời gian này." {id: 2, name: 'ducnm@.abc.com'},
{id: 3, name: 'ducnm@.abc.com'},
{id: 4, name: 'ducnm@.abc.com'},
{id: 5, name: 'ducnm@.abc.com'},
{id: 6, name: 'ducnm@.abc.com'},
{id: 7, name: 'ducnm@.abc.com'},
{id: 8, name: 'ducnm@.abc.com'},
{id: 9, name: 'ducnm@.abc.com'},
{id: 10, name: 'ducnm@.abc.com'},
{id: 11, name: 'ducnm@.abc.com'},
{id: 12, name: 'ducnm@.abc.com'},
{id: 13, name: 'ducnm@.abc.com'},
{id: 14, name: 'ducnm@.abc.com'},
{id: 15, name: 'ducnm@.abc.com'},
{id: 16, name: 'ducnm@.abc.com'},
{id: 17, name: 'ducnm@.abc.com'},
{id: 18, name: 'ducnm@.abc.com'},
{id: 19, name: 'ducnm@.abc.com'},
{id: 20, name: 'ducnm@.abc.com'},
],
bcc: 'ducnm@.abc.com',
to: 'ducnm@.abc.com',
content:
'Kính gửi toàn thể Anh/Chị CBNV,\n\nTheo cập nhật mới nhất từ cơ quan khí tượng, bão số 3 (tên quốc tế: Wipha) hiện đang cách Quảng Ninh – Hải Phòng khoảng 233km về phía Đông. Trong 12 giờ qua, bão đã suy yếu 3 cấp (còn cấp 9), tuy nhiên dự báo sẽ mạnh lên khi đi vào khu vực Vịnh Bắc Bộ trong hôm nay (21/7).\n\nDự kiến từ chiều và tối nay, các tỉnh vùng ven biển và khu vực đồng bằng Bắc Bộ, bao gồm cả Hà Nội, có thể xảy ra mưa to, gió lớn, thậm chí có hiện tượng ngập úng cục bộ, cây đổ, mất điện.\n\nĐể đảm bảo an toàn cho toàn thể CBNV, công ty xin lưu ý:\n\n1. CBNV đang sinh sống tại khu vực bị ảnh hưởng bởi mưa bão có thể chủ động làm việc từ xa (remote) vào ngày mai nếu thấy điều kiện di chuyển không an toàn.\n\n2. Trong mọi trường hợp, ưu tiên cao nhất là an toàn cá nhân. Nếu gặp tình trạng ngập sâu, cây gãy đổ, đường trơn trượt nguy hiểm... vui lòng không cố gắng di chuyển đến văn phòng.\n\n3. Các quản lý trực tiếp chủ động nhắc nhở thành viên trong nhóm, và tạo điều kiện linh hoạt để đảm bảo công việc được duy trì hiệu quả, dù làm việc tại nhà.\n\nCông ty khuyến nghị anh/chị:\n\n- Hạn chế ra ngoài khi mưa gió lớn, kiểm tra và gia cố nhà cửa nếu cần thiết;\n- Liên hệ ngay với quản lý hoặc bộ phận HCNS nếu có tình huống khẩn cấp.\n\nRất mong anh/chị giữ gìn sức khỏe, an toàn và chủ động phối hợp trong thời gian này.',
}); });
return ( return <DetailEmailView incoming_document={incoming_document} />;
<DetailEmailView incoming_document={incoming_document}/>
);
}; };
export default DetailEmail; export default DetailEmail;
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../../assets/R' import R from '../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container:{ container: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
paddingHorizontal:15, paddingHorizontal: 15,
paddingVertical:10 paddingVertical: 10,
}, },
header:{ header: {
backgroundColor:R.colors.blue, backgroundColor: R.colors.blue,
height:50, height: 50,
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
justifyContent:'space-between', justifyContent: 'space-between',
paddingHorizontal:15 paddingHorizontal: 15,
}, },
iconBack:{ iconBack: {
width:25, width: 25,
height:20 height: 20,
}, },
iconDelete:{ iconDelete: {
width:25, width: 25,
height:20 height: 20,
}, },
title:{ title: {
fontSize:R.fontsize.fontSizeSubTitle, fontSize: R.fontsize.fontSizeSubTitle,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
color:R.colors.black, color: R.colors.black,
}, },
avatarBox:{ avatarBox: {
height:50, height: 50,
flexDirection:'row', flexDirection: 'row',
marginVertical:5 marginVertical: 5,
}, },
avatarContainer:{ avatarContainer: {
width:50, width: 50,
height:50, height: 50,
borderRadius:25, borderRadius: 25,
}, },
avatar:{ avatar: {
width:50, width: 50,
height:50, height: 50,
borderRadius:25, borderRadius: 25,
}, },
avatarTextContainer:{ avatarTextContainer: {
flex:1, flex: 1,
marginLeft:10, marginLeft: 10,
paddingVertical:2, paddingVertical: 2,
flexDirection:'row', flexDirection: 'row',
justifyContent:'space-between', justifyContent: 'space-between',
}, },
name:{ name: {
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
color:R.colors.black, color: R.colors.black,
}, },
date:{ date: {
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
color:R.colors.gray, color: R.colors.gray,
}, },
iconDrop:{ iconDrop: {
width:20, width: 20,
height:20 height: 20,
}, },
toMeContainer:{ toMeContainer: {
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
}, },
detailSendContainer:{ detailSendContainer: {
width:'100%', width: '100%',
height:200, height: 200,
backgroundColor:R.colors.blue4, backgroundColor: R.colors.blue4,
borderRadius:15, borderRadius: 15,
paddingHorizontal:15, paddingHorizontal: 15,
paddingVertical:10 paddingVertical: 10,
}, },
textTitleMail:{ textTitleMail: {
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontBold, fontFamily: R.fonts.fontBold,
fontWeight:'600', fontWeight: '600',
color:R.colors.black, color: R.colors.black,
}, },
textSubMail:{ textSubMail: {
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
fontWeight:'400', fontWeight: '400',
color:R.colors.black, color: R.colors.black,
}, },
textContent:{ textContent: {
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
fontWeight:'400', fontWeight: '400',
color:R.colors.black, color: R.colors.black,
}, },
iconReply:{ iconReply: {
width:15, width: 15,
height:15 height: 15,
}, },
iconForward:{ iconForward: {
width:15, width: 15,
height:15 height: 15,
} },
}) });
export default styles export default styles;
...@@ -28,61 +28,61 @@ const DetailEmailView = props => { ...@@ -28,61 +28,61 @@ const DetailEmailView = props => {
</View> </View>
); );
}; };
const renderBottomCard = () =>{ const renderBottomCard = () => {
return( return (
<View style={styles.detailSendContainer}> <View style={styles.detailSendContainer}>
<ScrollView nestedScrollEnabled={true} style={{flex:1} }> <ScrollView nestedScrollEnabled={true} style={{flex: 1}}>
<Text style={styles.textTitleMail}>From:{' '} <Text style={styles.textTitleMail}>
From:{' '}
<Text style={styles.textSubMail}>{incoming_document.from}</Text> <Text style={styles.textSubMail}>{incoming_document.from}</Text>
</Text> </Text>
<Text style={styles.textTitleMail}>CC:{' '} <Text style={styles.textTitleMail}>
<Text style={styles.textSubMail}>{incoming_document.cc.map((item,index)=>{ CC:{' '}
return( <Text style={styles.textSubMail}>
<Text key={index}>{item.name},</Text> {incoming_document.cc.map((item, index) => {
) return <Text key={index}>{item.name},</Text>;
})}</Text> })}
</Text>
</Text> </Text>
<Text style={styles.textTitleMail}>BCC:{' '} <Text style={styles.textTitleMail}>
<Text style={styles.textSubMail}>{incoming_document.bcc}</Text> BCC: <Text style={styles.textSubMail}>{incoming_document.bcc}</Text>
</Text> </Text>
<Text style={styles.textTitleMail}>TO:{' '} <Text style={styles.textTitleMail}>
<Text style={styles.textSubMail}>{incoming_document.to}</Text> TO: <Text style={styles.textSubMail}>{incoming_document.to}</Text>
</Text> </Text>
</ScrollView> </ScrollView>
</View> </View>
) );
};
}
const renderButton =( const renderButton = ({
{
title, title,
onPress, onPress,
style, style,
icon, icon,
textStyle, textStyle,
iconRight, iconRight,
} }) => {
)=>{ return (
return(
<TouchableOpacity style={style} onPress={onPress}> <TouchableOpacity style={style} onPress={onPress}>
<View style={{flexDirection:'row', alignItems:'center', justifyContent:'center', marginHorizontal:10,}}> <View
style={{
<Image flexDirection: 'row',
source={icon} alignItems: 'center',
style={styles.iconReply} justifyContent: 'center',
resizeMode="contain" marginHorizontal: 10,
/> }}>
<Image source={icon} style={styles.iconReply} resizeMode="contain" />
<Text style={textStyle}>{title}</Text> <Text style={textStyle}>{title}</Text>
<Image <Image
source={iconRight} source={iconRight}
style={[styles.iconForward, { transform: [{ rotateY: '180deg' }] }]} style={[styles.iconForward, {transform: [{rotateY: '180deg'}]}]}
resizeMode="contain" resizeMode="contain"
/> />
</View> </View>
</TouchableOpacity> </TouchableOpacity>
) );
} };
const renderBody = () => { const renderBody = () => {
return ( return (
...@@ -102,16 +102,16 @@ const DetailEmailView = props => { ...@@ -102,16 +102,16 @@ const DetailEmailView = props => {
<Text style={styles.name}>{incoming_document.name}</Text> <Text style={styles.name}>{incoming_document.name}</Text>
<TouchableOpacity <TouchableOpacity
style={styles.toMeContainer} style={styles.toMeContainer}
onPress={() => setShowBottomCard(!showBottomCard)} onPress={() => setShowBottomCard(!showBottomCard)}>
> <Text>to me</Text>
<Text>
to me
</Text>
<Image <Image
source={R.images.icDrop} source={R.images.icDrop}
style={[styles.iconDrop, { style={[
transform: [{ rotate: showBottomCard ? '180deg' : '0deg' }] styles.iconDrop,
}]} {
transform: [{rotate: showBottomCard ? '180deg' : '0deg'}],
},
]}
resizeMode="contain" resizeMode="contain"
/> />
</TouchableOpacity> </TouchableOpacity>
...@@ -119,94 +119,90 @@ const DetailEmailView = props => { ...@@ -119,94 +119,90 @@ const DetailEmailView = props => {
<Text style={styles.date}>{incoming_document.date}</Text> <Text style={styles.date}>{incoming_document.date}</Text>
</View> </View>
</View> </View>
{showBottomCard && renderBottomCard()} {showBottomCard && renderBottomCard()}
<View style={{marginVertical:15}}> <View style={{marginVertical: 15}}>
<Text style={styles.textContent}>{incoming_document.content}</Text> <Text style={styles.textContent}>{incoming_document.content}</Text>
</View> </View>
<View style={{marginBottom:35 , flexDirection:'row', justifyContent:'space-between'}}> <View
style={{
marginBottom: 35,
flexDirection: 'row',
justifyContent: 'space-between',
}}>
{renderButton({ {renderButton({
title:'Reply', title: 'Reply',
onPress:()=>{}, onPress: () => {},
icon:R.images.icReply, icon: R.images.icReply,
style:{ style: {
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
padding:5, padding: 5,
borderRadius:15, borderRadius: 15,
borderColor:R.colors.black, borderColor: R.colors.black,
borderWidth:1, borderWidth: 1,
width:105, width: 105,
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
height:40, height: 40,
}, },
textStyle:{ textStyle: {
color:R.colors.black, color: R.colors.black,
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
marginLeft:5 marginLeft: 5,
}, },
})} })}
{renderButton({ {renderButton({
title:'Reply All', title: 'Reply All',
onPress:()=>{}, onPress: () => {},
icon:R.images.icReplyAll, icon: R.images.icReplyAll,
style:{ style: {
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
padding:5, padding: 5,
borderRadius:15, borderRadius: 15,
borderColor:R.colors.black, borderColor: R.colors.black,
borderWidth:1, borderWidth: 1,
width:105, width: 105,
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
height:40, height: 40,
}, },
textStyle:{ textStyle: {
color:R.colors.black, color: R.colors.black,
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
marginLeft:5 marginLeft: 5,
}, },
})} })}
{renderButton({ {renderButton({
title:'Forward', title: 'Forward',
onPress:()=>{}, onPress: () => {},
iconRight:R.images.icReply, iconRight: R.images.icReply,
style:{ style: {
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
padding:5, padding: 5,
borderRadius:15, borderRadius: 15,
borderColor:R.colors.black, borderColor: R.colors.black,
borderWidth:1, borderWidth: 1,
width:105, width: 105,
flexDirection:'row', flexDirection: 'row',
alignItems:'center', alignItems: 'center',
justifyContent:'center', justifyContent: 'center',
height:40, height: 40,
}, },
textStyle:{ textStyle: {
color:R.colors.black, color: R.colors.black,
fontSize:R.fontsize.fontSizeLabel, fontSize: R.fontsize.fontSizeLabel,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
marginRight:5 marginRight: 5,
}, },
})} })}
</View> </View>
</ScrollView> </ScrollView>
); );
}; };
......
import React, { useState, useEffect } from 'react'; import React, {useState, useEffect} from 'react';
import EmailHomeView from './view'; import EmailHomeView from './view';
const EmailHome = (props) => { const EmailHome = props => {
const [emails, setEmails] = useState([]); const [emails, setEmails] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
...@@ -22,65 +22,82 @@ const EmailHome = (props) => { ...@@ -22,65 +22,82 @@ const EmailHome = (props) => {
id: 1, id: 1,
sender: 'Nguyễn Minh Đức', sender: 'Nguyễn Minh Đức',
subject: 'Bảng lương tháng 10', subject: 'Bảng lương tháng 10',
preview: 'Kính gửi nhân viên ưu tú đây là bảng lương tháng 10 của bạn hãy kiểm tra nếu có thắc...', preview:
'Kính gửi nhân viên ưu tú đây là bảng lương tháng 10 của bạn hãy kiểm tra nếu có thắc...',
date: today, date: today,
isRead: true, isRead: true,
hasAttachment: false, hasAttachment: false,
avatar: 'https://via.placeholder.com/40' avatar: 'https://via.placeholder.com/40',
}, },
{ {
id: 2, id: 2,
sender: 'Vũ Công Bình', sender: 'Vũ Công Bình',
subject: 'Re: ĐƠN XIN ỨNG LƯƠNG', subject: 'Re: ĐƠN XIN ỨNG LƯƠNG',
preview: 'Kính gửi nhân viên ưu tú đây là bảng lương tháng 10 của bạn hãy kiểm tra nếu có thắc...', preview:
'Kính gửi nhân viên ưu tú đây là bảng lương tháng 10 của bạn hãy kiểm tra nếu có thắc...',
date: yesterday, date: yesterday,
isRead: false, isRead: false,
hasAttachment: true, hasAttachment: true,
avatar: 'https://via.placeholder.com/40' avatar: 'https://via.placeholder.com/40',
}, },
{ {
id: 3, id: 3,
sender: 'Vũ Công Bình', sender: 'Vũ Công Bình',
subject: 'Re: ĐƠN XIN ỨNG LƯƠNG', subject: 'Re: ĐƠN XIN ỨNG LƯƠNG',
preview: 'Kính gửi nhân viên ưu tú đây là bảng lương tháng 10 của bạn hãy kiểm tra nếu có thắc...', preview:
'Kính gửi nhân viên ưu tú đây là bảng lương tháng 10 của bạn hãy kiểm tra nếu có thắc...',
date: yesterday, date: yesterday,
isRead: false, isRead: false,
hasAttachment: true, hasAttachment: true,
avatar: 'https://via.placeholder.com/40' avatar: 'https://via.placeholder.com/40',
}, },
{ {
id: 4, id: 4,
sender: 'Trần Thị Mai', sender: 'Trần Thị Mai',
subject: 'Thông báo họp tuần', subject: 'Thông báo họp tuần',
preview: 'Cuộc họp tuần sẽ được tổ chức vào thứ 2 tuần tới lúc 9h00 sáng tại phòng họp A...', preview:
'Cuộc họp tuần sẽ được tổ chức vào thứ 2 tuần tới lúc 9h00 sáng tại phòng họp A...',
date: weekAgo, date: weekAgo,
isRead: true, isRead: true,
hasAttachment: false, hasAttachment: false,
avatar: 'https://via.placeholder.com/40' avatar: 'https://via.placeholder.com/40',
}, },
{ {
id: 5, id: 5,
sender: 'Phòng Nhân Sự', sender: 'Phòng Nhân Sự',
subject: 'Thông báo nghỉ lễ', subject: 'Thông báo nghỉ lễ',
preview: 'Công ty thông báo lịch nghỉ lễ Quốc Khánh 2/9 từ ngày 31/8 đến 3/9...', preview:
'Công ty thông báo lịch nghỉ lễ Quốc Khánh 2/9 từ ngày 31/8 đến 3/9...',
date: monthAgo, date: monthAgo,
isRead: true, isRead: true,
hasAttachment: false, hasAttachment: false,
avatar: 'https://via.placeholder.com/40' avatar: 'https://via.placeholder.com/40',
} },
]; ];
}; };
// Logic để format ngày hiển thị // Logic để format ngày hiển thị
const formatEmailDate = (emailDate) => { const formatEmailDate = emailDate => {
const today = new Date(); const today = new Date();
const yesterday = new Date(today); const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1); yesterday.setDate(yesterday.getDate() - 1);
// Reset time để so sánh chỉ ngày // Reset time để so sánh chỉ ngày
const emailDateOnly = new Date(emailDate.getFullYear(), emailDate.getMonth(), emailDate.getDate()); const emailDateOnly = new Date(
const todayOnly = new Date(today.getFullYear(), today.getMonth(), today.getDate()); emailDate.getFullYear(),
const yesterdayOnly = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate()); emailDate.getMonth(),
emailDate.getDate(),
);
const todayOnly = new Date(
today.getFullYear(),
today.getMonth(),
today.getDate(),
);
const yesterdayOnly = new Date(
yesterday.getFullYear(),
yesterday.getMonth(),
yesterday.getDate(),
);
if (emailDateOnly.getTime() === todayOnly.getTime()) { if (emailDateOnly.getTime() === todayOnly.getTime()) {
return 'Hôm nay'; return 'Hôm nay';
...@@ -96,7 +113,7 @@ const EmailHome = (props) => { ...@@ -96,7 +113,7 @@ const EmailHome = (props) => {
} }
}; };
//Nhóm các email trong danh sách theo ngày trả về một đối tượng trong đó các khoá là ngày //Nhóm các email trong danh sách theo ngày trả về một đối tượng trong đó các khoá là ngày
const groupEmailsByDate = (emailList) => { const groupEmailsByDate = emailList => {
const grouped = {}; const grouped = {};
emailList.forEach(email => { emailList.forEach(email => {
...@@ -118,7 +135,7 @@ const EmailHome = (props) => { ...@@ -118,7 +135,7 @@ const EmailHome = (props) => {
}, 1000); }, 1000);
}, []); }, []);
const handleEmailPress = (email) => { const handleEmailPress = email => {
console.log('Email pressed:', email.subject); console.log('Email pressed:', email.subject);
}; };
......
import React, { useState } from 'react'; import React, {useState} from 'react';
import {Text, View, StyleSheet} from 'react-native'; import {Text, View, StyleSheet} from 'react-native';
import SendEmailView from './view'; import SendEmailView from './view';
const SendEmail = (props) => { const SendEmail = props => {
const [chip, setChips] = useState([]); const [chip, setChips] = useState([]);
const handleChange = (newChips) => { const handleChange = newChips => {
setChips(newChips); setChips(newChips);
}; };
const [dataList, setDataList] = useState([ const [dataList, setDataList] = useState([
['john@doe.com', 'jane@doe.com', 'tung@doe.com'] ['john@doe.com', 'jane@doe.com', 'tung@doe.com'],
]); ]);
return ( return (
<SendEmailView handleChange={handleChange} chip={chip} dataList={dataList}/> <SendEmailView
handleChange={handleChange}
chip={chip}
dataList={dataList}
/>
); );
}; };
......
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../../assets/R' import R from '../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container:{ container: {
flex:1, flex: 1,
backgroundColor:R.colors.white backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
backgroundColor:R.colors.white, backgroundColor: R.colors.white,
padding:15 padding: 15,
}, },
header:{ header: {
flexDirection:'row', flexDirection: 'row',
backgroundColor:R.colors.blue, backgroundColor: R.colors.blue,
height:50, height: 50,
alignItems:'center', alignItems: 'center',
justifyContent:'space-between', justifyContent: 'space-between',
paddingHorizontal:15 paddingHorizontal: 15,
}, },
icon:{ icon: {
width:25, width: 25,
height:20 height: 20,
}, },
sendButton:{ sendButton: {
backgroundColor:R.colors.orange, backgroundColor: R.colors.orange,
borderRadius:5, borderRadius: 5,
width:90, width: 90,
paddingHorizontal:5, paddingHorizontal: 5,
height:35, height: 35,
alignItems:'center', alignItems: 'center',
justifyContent:'space-around', justifyContent: 'space-around',
flexDirection:'row' flexDirection: 'row',
}, },
sendText:{ sendText: {
color:R.colors.white, color: R.colors.white,
fontSize:R.fontsize.fontSizeSubTitle, fontSize: R.fontsize.fontSizeSubTitle,
fontFamily:R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
fontWeight:'400', fontWeight: '400',
}, },
iconSend:{ iconSend: {
width:20, width: 20,
height:20 height: 20,
}, },
title:{ title: {
fontSize:R.fontsize.fontSizeSubTitle, fontSize: R.fontsize.fontSizeSubTitle,
fontFamily:R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight:'600', fontWeight: '600',
color:R.colors.white color: R.colors.white,
}, },
iconClose:{ iconClose: {
width:15, width: 15,
height:15 height: 15,
}, },
inputContainer:{ inputContainer: {
flexDirection:'row', flexDirection: 'row',
borderBottomWidth:1, borderBottomWidth: 1,
borderColor:R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderRadius:5, borderRadius: 5,
height:35, height: 35,
alignItems:'center', alignItems: 'center',
}, },
input:{ input: {
flex:1, flex: 1,
padding:0, padding: 0,
paddingHorizontal:10, paddingHorizontal: 10,
paddingVertical:0, paddingVertical: 0,
},
} });
})
export default styles export default styles;
\ No newline at end of file
import React from 'react'; import React from 'react';
import {Text, View, TouchableOpacity, StyleSheet, Image, TextInput} from 'react-native'; import {
Text,
View,
TouchableOpacity,
Image,
TextInput,
} from 'react-native';
import styles from './style'; import styles from './style';
import R from '../../../assets/R'; import R from '../../../assets/R';
import Button from '../../../components/Button'; import {useNavigation} from '@react-navigation/native';
import { useNavigation } from '@react-navigation/native';
import EmailChipInput from '../../../components/Chip/EmailChipInput'; import EmailChipInput from '../../../components/Chip/EmailChipInput';
import TextMulti from '../../../components/Input/TextMulti';
import TextField from '../../../components/Input/TextField';
const SendEmailView = (props) => { const SendEmailView = props => {
const { handleChange, chip, dataList } = props; const {handleChange, chip, dataList} = props;
const navigation = useNavigation(); const navigation = useNavigation();
const renderHeader = () => { const renderHeader = () => {
return ( return (
<View style={styles.header}> <View style={styles.header}>
<TouchableOpacity onPress={() => navigation.goBack()}> <TouchableOpacity onPress={() => navigation.goBack()}>
<Image source={R.images.icBack} style={styles.icon}/> <Image source={R.images.icBack} style={styles.icon} />
</TouchableOpacity> </TouchableOpacity>
<Text style={styles.title}>Son email</Text> <Text style={styles.title}>Son email</Text>
<TouchableOpacity onPress={() => (navigation.goBack())} style={styles.sendButton}> <TouchableOpacity
onPress={() => navigation.goBack()}
style={styles.sendButton}>
<Text style={styles.sendText}>Gi Đi</Text> <Text style={styles.sendText}>Gi Đi</Text>
<Image source={R.images.icSend} style={styles.iconSend} tintColor={R.colors.white}/> <Image
source={R.images.icSend}
style={styles.iconSend}
tintColor={R.colors.white}
/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
); );
} };
return ( return (
<View <View style={styles.container}>
style={styles.container}>
{renderHeader()} {renderHeader()}
<View style={styles.body}> <View style={styles.body}>
<EmailChipInput <EmailChipInput
...@@ -38,16 +46,20 @@ const renderHeader = () => { ...@@ -38,16 +46,20 @@ const renderHeader = () => {
delimiters={dataList} delimiters={dataList}
entries={chip} entries={chip}
onSubmit={handleChange} onSubmit={handleChange}
chipContainerStyle={{ backgroundColor: R.colors.blue4}} chipContainerStyle={{backgroundColor: R.colors.blue4}}
chipTextStyle={{ color:R.colors.black }} chipTextStyle={{color: R.colors.black}}
containerStyle={{ containerStyle={{
borderBottomWidth:1, borderBottomWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderRadius: 5, borderRadius: 5,
marginBottom:10 marginBottom: 10,
}} }}
chipImage={ chipImage={
<Image source={R.images.icCancel} style={styles.iconClose} tintColor={R.colors.black}/> <Image
source={R.images.icCancel}
style={styles.iconClose}
tintColor={R.colors.black}
/>
} }
/> />
<EmailChipInput <EmailChipInput
...@@ -55,16 +67,20 @@ const renderHeader = () => { ...@@ -55,16 +67,20 @@ const renderHeader = () => {
delimiters={dataList} delimiters={dataList}
entries={chip} entries={chip}
onSubmit={handleChange} onSubmit={handleChange}
chipContainerStyle={{ backgroundColor: R.colors.blue4}} chipContainerStyle={{backgroundColor: R.colors.blue4}}
chipTextStyle={{ color:R.colors.black }} chipTextStyle={{color: R.colors.black}}
containerStyle={{ containerStyle={{
borderBottomWidth:1, borderBottomWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderRadius: 5, borderRadius: 5,
marginBottom:10 marginBottom: 10,
}} }}
chipImage={ chipImage={
<Image source={R.images.icCancel} style={styles.iconClose} tintColor={R.colors.black}/> <Image
source={R.images.icCancel}
style={styles.iconClose}
tintColor={R.colors.black}
/>
} }
/> />
<EmailChipInput <EmailChipInput
...@@ -72,16 +88,20 @@ const renderHeader = () => { ...@@ -72,16 +88,20 @@ const renderHeader = () => {
delimiters={dataList} delimiters={dataList}
entries={chip} entries={chip}
onSubmit={handleChange} onSubmit={handleChange}
chipContainerStyle={{ backgroundColor: R.colors.blue4}} chipContainerStyle={{backgroundColor: R.colors.blue4}}
chipTextStyle={{ color:R.colors.black }} chipTextStyle={{color: R.colors.black}}
containerStyle={{ containerStyle={{
borderBottomWidth:1, borderBottomWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderRadius: 5, borderRadius: 5,
marginBottom:10 marginBottom: 10,
}} }}
chipImage={ chipImage={
<Image source={R.images.icCancel} style={styles.iconClose} tintColor={R.colors.black}/> <Image
source={R.images.icCancel}
style={styles.iconClose}
tintColor={R.colors.black}
/>
} }
/> />
<EmailChipInput <EmailChipInput
...@@ -89,20 +109,29 @@ const renderHeader = () => { ...@@ -89,20 +109,29 @@ const renderHeader = () => {
delimiters={dataList} delimiters={dataList}
entries={chip} entries={chip}
onSubmit={handleChange} onSubmit={handleChange}
chipContainerStyle={{ backgroundColor: R.colors.blue4}} chipContainerStyle={{backgroundColor: R.colors.blue4}}
chipTextStyle={{ color:R.colors.black }} chipTextStyle={{color: R.colors.black}}
containerStyle={{ containerStyle={{
borderBottomWidth:1, borderBottomWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader, borderColor: R.colors.grayBorderInputTextHeader,
borderRadius: 5, borderRadius: 5,
marginBottom:10 marginBottom: 10,
}} }}
chipImage={ chipImage={
<Image source={R.images.icCancel} style={styles.iconClose} tintColor={R.colors.black}/> <Image
source={R.images.icCancel}
style={styles.iconClose}
tintColor={R.colors.black}
/>
} }
/> />
<View style={styles.inputContainer}> <View style={styles.inputContainer}>
<Text style={{fontSize:12, color:R.colors.black, fontFamily:R.fonts.fontMedium}}> <Text
style={{
fontSize: 12,
color: R.colors.black,
fontFamily: R.fonts.fontMedium,
}}>
Subject Subject
</Text> </Text>
<TextInput <TextInput
...@@ -110,16 +139,22 @@ const renderHeader = () => { ...@@ -110,16 +139,22 @@ const renderHeader = () => {
style={styles.input} style={styles.input}
/> />
</View> </View>
<View style={[ {height:100, marginTop:10}]}> <View style={[{height: 100, marginTop: 10}]}>
<TextInput <TextInput
placeholderTextColor={R.colors.gray} placeholderTextColor={R.colors.gray}
style={[styles.input , {paddingHorizontal:10 ,borderBottomWidth:1 ,borderColor:R.colors.grayBorderInputTextHeader}]} style={[
styles.input,
{
paddingHorizontal: 10,
borderBottomWidth: 1,
borderColor: R.colors.grayBorderInputTextHeader,
},
]}
multiline={true} multiline={true}
numberOfLines={5} numberOfLines={5}
textAlignVertical='top' textAlignVertical="top"
/> />
</View> </View>
</View> </View>
</View> </View>
); );
......
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({
container: { container: {
flex: 1, flex: 1,
backgroundColor: R.colors.white backgroundColor: R.colors.white,
}, },
loadingContainer: { loadingContainer: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: R.colors.white backgroundColor: R.colors.white,
}, },
loadingText: { loadingText: {
marginTop: 10, marginTop: 10,
fontSize: R.fontsize.fontSizeSubTitle, fontSize: R.fontsize.fontSizeSubTitle,
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
color: R.colors.gray2 color: R.colors.gray2,
},
listContainer: {
}, },
listContainer: {},
dateSection: { dateSection: {
marginBottom: 10, marginBottom: 10,
}, },
...@@ -36,13 +35,12 @@ const styles = StyleSheet.create({ ...@@ -36,13 +35,12 @@ const styles = StyleSheet.create({
paddingHorizontal: 15, paddingHorizontal: 15,
paddingVertical: 10, paddingVertical: 10,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
alignItems: 'flex-start' alignItems: 'flex-start',
},
unreadEmail: {
}, },
unreadEmail: {},
avatarContainer: { avatarContainer: {
marginRight: 10, marginRight: 10,
marginTop: 5 marginTop: 5,
}, },
avatar: { avatar: {
width: 40, width: 40,
...@@ -50,16 +48,16 @@ const styles = StyleSheet.create({ ...@@ -50,16 +48,16 @@ const styles = StyleSheet.create({
borderRadius: 20, borderRadius: 20,
backgroundColor: R.colors.blue, backgroundColor: R.colors.blue,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center',
}, },
avatarText: { avatarText: {
color: R.colors.white, color: R.colors.white,
fontSize: 16, fontSize: 16,
fontWeight: 'bold' fontWeight: 'bold',
}, },
emailContent: { emailContent: {
flex: 1, flex: 1,
marginRight: 10 marginRight: 10,
}, },
emailHeader: { emailHeader: {
flexDirection: 'row', flexDirection: 'row',
...@@ -68,25 +66,25 @@ const styles = StyleSheet.create({ ...@@ -68,25 +66,25 @@ const styles = StyleSheet.create({
}, },
senderName: { senderName: {
fontSize: R.fontsize.fontsSizeTitle, fontSize: R.fontsize.fontsSizeTitle,
fontWeight:'400', fontWeight: '400',
fontFamily: R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
color: R.colors.gray4, color: R.colors.gray4,
flex: 1, flex: 1,
marginRight: 10 marginRight: 10,
}, },
unreadText: { unreadText: {
fontWeight: '600', fontWeight: '600',
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
color: R.colors.black color: R.colors.black,
}, },
unreadEmail: { unreadEmail: {
fontWeight: '600', fontWeight: '600',
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
color: R.colors.gray3 color: R.colors.gray3,
}, },
emailDate: { emailDate: {
fontSize: R.fontsize.fontSizeContent, fontSize: R.fontsize.fontSizeContent,
color: R.colors.gray2 color: R.colors.gray2,
}, },
emailSubject: { emailSubject: {
fontSize: R.fontsize.fontSizeBtn, fontSize: R.fontsize.fontSizeBtn,
...@@ -103,7 +101,7 @@ const styles = StyleSheet.create({ ...@@ -103,7 +101,7 @@ const styles = StyleSheet.create({
backgroundColor: R.colors.blue3, backgroundColor: R.colors.blue3,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
marginTop: 4 marginTop: 4,
}, },
attachmentCount: { attachmentCount: {
color: R.colors.blue, color: R.colors.blue,
...@@ -122,7 +120,7 @@ const styles = StyleSheet.create({ ...@@ -122,7 +120,7 @@ const styles = StyleSheet.create({
bottom: 5, bottom: 5,
width: 95, width: 95,
backgroundColor: R.colors.red, backgroundColor: R.colors.red,
borderRadius:25, borderRadius: 25,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
flexDirection: 'column', flexDirection: 'column',
...@@ -145,7 +143,7 @@ const styles = StyleSheet.create({ ...@@ -145,7 +143,7 @@ const styles = StyleSheet.create({
fontSize: R.fontsize.fontSizeContent, fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontMedium, fontFamily: R.fonts.fontMedium,
fontWeight: '600', fontWeight: '600',
} },
}) });
export default styles export default styles;
\ No newline at end of file
...@@ -16,10 +16,11 @@ import FAB from '../../components/FAB/fab'; ...@@ -16,10 +16,11 @@ import FAB from '../../components/FAB/fab';
import SubButton from '../../components/FAB/sub_button'; import SubButton from '../../components/FAB/sub_button';
import R from '../../assets/R'; import R from '../../assets/R';
import * as SCREENNAME from '../../routers/ScreenNames'; import * as SCREENNAME from '../../routers/ScreenNames';
import { useNavigation } from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
const EmailHomeView = props => { const EmailHomeView = props => {
const {groupedEmails, loading, onEmailPress, onRefresh, formatEmailDate} = props; const {groupedEmails, loading, onEmailPress, onRefresh, formatEmailDate} =
props;
const navigation = useNavigation(); const navigation = useNavigation();
const screenWidth = Dimensions.get('window').width; const screenWidth = Dimensions.get('window').width;
...@@ -27,7 +28,6 @@ const EmailHomeView = props => { ...@@ -27,7 +28,6 @@ const EmailHomeView = props => {
const [localGroupedEmails, setLocalGroupedEmails] = useState(groupedEmails); const [localGroupedEmails, setLocalGroupedEmails] = useState(groupedEmails);
const [swipedEmailId, setSwipedEmailId] = useState(null); const [swipedEmailId, setSwipedEmailId] = useState(null);
// Update local state when props change
React.useEffect(() => { React.useEffect(() => {
setLocalGroupedEmails(groupedEmails); setLocalGroupedEmails(groupedEmails);
}, [groupedEmails]); }, [groupedEmails]);
...@@ -45,7 +45,6 @@ const EmailHomeView = props => { ...@@ -45,7 +45,6 @@ const EmailHomeView = props => {
const translateX = useRef(new Animated.Value(0)).current; const translateX = useRef(new Animated.Value(0)).current;
const deleteThreshold = screenWidth * 0.3; const deleteThreshold = screenWidth * 0.3;
// Reset position when another email is swiped
React.useEffect(() => { React.useEffect(() => {
if (swipedEmailId !== null && swipedEmailId !== item.id) { if (swipedEmailId !== null && swipedEmailId !== item.id) {
Animated.spring(translateX, { Animated.spring(translateX, {
...@@ -66,8 +65,12 @@ const EmailHomeView = props => { ...@@ -66,8 +65,12 @@ const EmailHomeView = props => {
}, },
onPanResponderMove: (evt, gestureState) => { onPanResponderMove: (evt, gestureState) => {
// console.log('gestureState L2', gestureState.dx); // console.log('gestureState L2', gestureState.dx);
if (gestureState.vx < 0 && gestureState.dx > -100 && gestureState.dx < 0) { if (
console.log('gestureState L2', gestureState.dx, gestureState.vx,); gestureState.vx < 0 &&
gestureState.dx > -100 &&
gestureState.dx < 0
) {
console.log('gestureState L2', gestureState.dx, gestureState.vx);
translateX.setValue(-100); translateX.setValue(-100);
setSwipedEmailId(item.id); setSwipedEmailId(item.id);
} else { } else {
...@@ -82,7 +85,7 @@ const EmailHomeView = props => { ...@@ -82,7 +85,7 @@ const EmailHomeView = props => {
onPanResponderRelease: (evt, gestureState) => { onPanResponderRelease: (evt, gestureState) => {
// console.log('gestureState L3', gestureState); // console.log('gestureState L3', gestureState);
if (Math.abs(gestureState.dx) >= 0 && gestureState.vx === 0) { if (Math.abs(gestureState.dx) >= 0 && gestureState.vx === 0) {
console.log('gestureState L3', gestureState.dx, gestureState.vx,); console.log('gestureState L3', gestureState.dx, gestureState.vx);
// // Nếu di chuyển đủ lớn, vuốt để xóa // // Nếu di chuyển đủ lớn, vuốt để xóa
// if (gestureState.dx < -deleteThreshold ) { // if (gestureState.dx < -deleteThreshold ) {
// // Hiển thị nút xóa // // Hiển thị nút xóa
...@@ -103,7 +106,7 @@ const EmailHomeView = props => { ...@@ -103,7 +106,7 @@ const EmailHomeView = props => {
// } // }
navigation.navigate(SCREENNAME.DETAILEMAIL); navigation.navigate(SCREENNAME.DETAILEMAIL);
} }
// } else { // } else {
// // Nếu không có chuyển động đủ lớn (chỉ bấm), chuyển tới màn hình chi tiết // // Nếu không có chuyển động đủ lớn (chỉ bấm), chuyển tới màn hình chi tiết
// navigation.navigate(SCREENNAME.DETAILEMAIL); // navigation.navigate(SCREENNAME.DETAILEMAIL);
...@@ -124,7 +127,6 @@ const EmailHomeView = props => { ...@@ -124,7 +127,6 @@ const EmailHomeView = props => {
}; };
const handleCancelPress = () => { const handleCancelPress = () => {
// Snap back to original position
Animated.spring(translateX, { Animated.spring(translateX, {
toValue: 0, toValue: 0,
useNativeDriver: true, useNativeDriver: true,
...@@ -133,7 +135,6 @@ const EmailHomeView = props => { ...@@ -133,7 +135,6 @@ const EmailHomeView = props => {
}); });
}; };
const handleEmailPress = () => { const handleEmailPress = () => {
// Chỉ điều hướng nếu email chưa bị vuốt
if (swipedEmailId === null) { if (swipedEmailId === null) {
navigation.navigate(SCREENNAME.DETAILEMAIL); navigation.navigate(SCREENNAME.DETAILEMAIL);
} }
...@@ -141,18 +142,16 @@ const EmailHomeView = props => { ...@@ -141,18 +142,16 @@ const EmailHomeView = props => {
return ( return (
<View style={styles.swipeContainer}> <View style={styles.swipeContainer}>
{/* Delete background */} <Animated.View
<Animated.View style={[styles.deleteBackground, {opacity: deleteOpacity}]}> style={[styles.deleteBackground, {opacity: deleteOpacity}]}>
<TouchableOpacity <TouchableOpacity
style={styles.deleteButton} style={styles.deleteButton}
onPress={handleDeletePress} onPress={handleDeletePress}>
>
<Image source={R.images.icDelete} style={styles.deleteIcon} /> <Image source={R.images.icDelete} style={styles.deleteIcon} />
<Text style={styles.deleteText}>Xóa</Text> <Text style={styles.deleteText}>Xóa</Text>
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>
{/* Email item */}
<Animated.View <Animated.View
style={[{transform: [{translateX}]}]} style={[{transform: [{translateX}]}]}
{...panResponder.panHandlers}> {...panResponder.panHandlers}>
...@@ -169,7 +168,11 @@ const EmailHomeView = props => { ...@@ -169,7 +168,11 @@ const EmailHomeView = props => {
<View style={styles.emailContent}> <View style={styles.emailContent}>
<View style={styles.emailHeader}> <View style={styles.emailHeader}>
<Text style={[styles.senderName, !item.isRead && styles.unreadText]}> <Text
style={[
styles.senderName,
!item.isRead && styles.unreadText,
]}>
{item.sender} {item.sender}
</Text> </Text>
</View> </View>
...@@ -181,7 +184,10 @@ const EmailHomeView = props => { ...@@ -181,7 +184,10 @@ const EmailHomeView = props => {
</Text> </Text>
<Text <Text
style={[styles.emailPreview, !item.isRead && styles.unreadEmail]} style={[
styles.emailPreview,
!item.isRead && styles.unreadEmail,
]}
numberOfLines={2}> numberOfLines={2}>
{item.preview} {item.preview}
</Text> </Text>
...@@ -214,12 +220,13 @@ const EmailHomeView = props => { ...@@ -214,12 +220,13 @@ const EmailHomeView = props => {
); );
}; };
const handleDeleteEmail = (emailId) => { const handleDeleteEmail = emailId => {
// Remove email from local state temporarily
const updatedGroupedEmails = {}; const updatedGroupedEmails = {};
Object.keys(localGroupedEmails).forEach(dateKey => { Object.keys(localGroupedEmails).forEach(dateKey => {
const filteredEmails = localGroupedEmails[dateKey].filter(email => email.id !== emailId); const filteredEmails = localGroupedEmails[dateKey].filter(
email => email.id !== emailId,
);
if (filteredEmails.length > 0) { if (filteredEmails.length > 0) {
updatedGroupedEmails[dateKey] = filteredEmails; updatedGroupedEmails[dateKey] = filteredEmails;
} }
...@@ -270,7 +277,6 @@ const EmailHomeView = props => { ...@@ -270,7 +277,6 @@ const EmailHomeView = props => {
backgroundColor={R.colors.orange} backgroundColor={R.colors.orange}
/> />
</FAB> </FAB>
</View> </View>
); );
}; };
......
...@@ -26,42 +26,289 @@ const DetailFeedBack = props => { ...@@ -26,42 +26,289 @@ const DetailFeedBack = props => {
{ {
id: '4', id: '4',
question: 'Sự hỗ trợ của giảng viên trong và ngoài giờ?', question: 'Sự hỗ trợ của giảng viên trong và ngoài giờ?',
} },
], ],
results: [ results: [
{ "id": 1, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Tuyệt vời" }, {id: 1, Q1: 4, Q2: 4, Q3: 4, Q4: 4, GPA: 4, comment: 'Tuyệt vời'},
{ "id": 2, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Học với thầy em cảm thấy tiếp thu được nhiều và bổ ích" }, {
{ "id": 3, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Giảng viên giảng dễ hiểu, tận tình" }, id: 2,
{ "id": 4, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Bài giảng rõ ràng, mạch lạc" }, Q1: 4,
{ "id": 5, "Q1": 3, "Q2": 4, "Q3": 4, "Q4": 3, "GPA": 3.5, "comment": "Một số chỗ hơi nhanh, cần giảng chậm lại" }, Q2: 4,
{ "id": 6, "Q1": 4, "Q2": 3, "Q3": 4, "Q4": 4, "GPA": 3.75, "comment": "Ổn nhưng cần thêm ví dụ thực tế" }, Q3: 4,
{ "id": 7, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 4, "GPA": 3.75, "comment": "Rất dễ hiểu, nên có thêm bài tập nhóm" }, Q4: 4,
{ "id": 8, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 3, "GPA": 3.75, "comment": "Phong cách giảng dạy gần gũi" }, GPA: 4,
{ "id": 9, "Q1": 4, "Q2": 3, "Q3": 3, "Q4": 4, "GPA": 3.5, "comment": "Hài hước, dễ tiếp thu" }, comment: 'Học với thầy em cảm thấy tiếp thu được nhiều và bổ ích',
{ "id": 10, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Rất tận tình và hỗ trợ sinh viên" }, },
{ "id": 11, "Q1": 3, "Q2": 4, "Q3": 4, "Q4": 3, "GPA": 3.5, "comment": "Nên chậm lại phần kiến thức nâng cao" }, {
{ "id": 12, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 4, "GPA": 3.75, "comment": "Cách giải thích dễ hiểu" }, id: 3,
{ "id": 13, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Giảng viên nhiệt huyết" }, Q1: 4,
{ "id": 14, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 3, "GPA": 3.5, "comment": "Có thêm tài liệu tham khảo thì tốt" }, Q2: 4,
{ "id": 15, "Q1": 4, "Q2": 3, "Q3": 4, "Q4": 4, "GPA": 3.75, "comment": "Thầy luôn trả lời câu hỏi tận tình" }, Q3: 4,
{ "id": 16, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 4, "GPA": 3.75, "comment": "Nội dung sát thực tế" }, Q4: 4,
{ "id": 17, "Q1": 3, "Q2": 4, "Q3": 4, "Q4": 3, "GPA": 3.5, "comment": "Bài giảng cần nhiều ví dụ minh họa hơn" }, GPA: 4,
{ "id": 18, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 3, "GPA": 3.75, "comment": "Phong thái chuyên nghiệp" }, comment: 'Giảng viên giảng dễ hiểu, tận tình',
{ "id": 19, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Rất dễ hiểu, rõ ràng" }, },
{ "id": 20, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 3, "GPA": 3.5, "comment": "Một số phần khó nhưng thầy đã hỗ trợ nhiều" }, {
{ "id": 21, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Không khí lớp học vui vẻ" }, id: 4,
{ "id": 22, "Q1": 4, "Q2": 3, "Q3": 4, "Q4": 3, "GPA": 3.5, "comment": "Có thể tăng thêm thời gian luyện tập" }, Q1: 4,
{ "id": 23, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 4, "GPA": 3.75, "comment": "Cách truyền đạt dễ tiếp cận" }, Q2: 4,
{ "id": 24, "Q1": 3, "Q2": 3, "Q3": 4, "Q4": 4, "GPA": 3.5, "comment": "Thầy luôn động viên sinh viên" }, Q3: 4,
{ "id": 25, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Bài giảng rất chất lượng" }, Q4: 4,
{ "id": 26, "Q1": 3, "Q2": 4, "Q3": 3, "Q4": 4, "GPA": 3.5, "comment": "Thầy thân thiện và hỗ trợ nhiệt tình" }, GPA: 4,
{ "id": 27, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 3, "GPA": 3.75, "comment": "Phương pháp giảng hiện đại" }, comment: 'Bài giảng rõ ràng, mạch lạc',
{ "id": 28, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Thầy giải thích kỹ càng" }, },
{ "id": 29, "Q1": 3, "Q2": 3, "Q3": 4, "Q4": 3, "GPA": 3.25, "comment": "Một vài chỗ khó theo kịp" }, {
{ "id": 30, "Q1": 4, "Q2": 4, "Q3": 4, "Q4": 4, "GPA": 4, "comment": "Thầy truyền cảm hứng học tập" }, id: 5,
{ "id": 31, "Q1": 4, "Q2": 3, "Q3": 4, "Q4": 3, "GPA": 3.5, "comment": "Cần nhiều buổi ôn tập hơn" }, Q1: 3,
{ "id": 32, "Q1": 4, "Q2": 4, "Q3": 3, "Q4": 4, "GPA": 3.75, "comment": "Thầy luôn khuyến khích đặt câu hỏi" } Q2: 4,
Q3: 4,
Q4: 3,
GPA: 3.5,
comment: 'Một số chỗ hơi nhanh, cần giảng chậm lại',
},
{
id: 6,
Q1: 4,
Q2: 3,
Q3: 4,
Q4: 4,
GPA: 3.75,
comment: 'Ổn nhưng cần thêm ví dụ thực tế',
},
{
id: 7,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 4,
GPA: 3.75,
comment: 'Rất dễ hiểu, nên có thêm bài tập nhóm',
},
{
id: 8,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 3,
GPA: 3.75,
comment: 'Phong cách giảng dạy gần gũi',
},
{
id: 9,
Q1: 4,
Q2: 3,
Q3: 3,
Q4: 4,
GPA: 3.5,
comment: 'Hài hước, dễ tiếp thu',
},
{
id: 10,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Rất tận tình và hỗ trợ sinh viên',
},
{
id: 11,
Q1: 3,
Q2: 4,
Q3: 4,
Q4: 3,
GPA: 3.5,
comment: 'Nên chậm lại phần kiến thức nâng cao',
},
{
id: 12,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 4,
GPA: 3.75,
comment: 'Cách giải thích dễ hiểu',
},
{
id: 13,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Giảng viên nhiệt huyết',
},
{
id: 14,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 3,
GPA: 3.5,
comment: 'Có thêm tài liệu tham khảo thì tốt',
},
{
id: 15,
Q1: 4,
Q2: 3,
Q3: 4,
Q4: 4,
GPA: 3.75,
comment: 'Thầy luôn trả lời câu hỏi tận tình',
},
{
id: 16,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 4,
GPA: 3.75,
comment: 'Nội dung sát thực tế',
},
{
id: 17,
Q1: 3,
Q2: 4,
Q3: 4,
Q4: 3,
GPA: 3.5,
comment: 'Bài giảng cần nhiều ví dụ minh họa hơn',
},
{
id: 18,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 3,
GPA: 3.75,
comment: 'Phong thái chuyên nghiệp',
},
{
id: 19,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Rất dễ hiểu, rõ ràng',
},
{
id: 20,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 3,
GPA: 3.5,
comment: 'Một số phần khó nhưng thầy đã hỗ trợ nhiều',
},
{
id: 21,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Không khí lớp học vui vẻ',
},
{
id: 22,
Q1: 4,
Q2: 3,
Q3: 4,
Q4: 3,
GPA: 3.5,
comment: 'Có thể tăng thêm thời gian luyện tập',
},
{
id: 23,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 4,
GPA: 3.75,
comment: 'Cách truyền đạt dễ tiếp cận',
},
{
id: 24,
Q1: 3,
Q2: 3,
Q3: 4,
Q4: 4,
GPA: 3.5,
comment: 'Thầy luôn động viên sinh viên',
},
{
id: 25,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Bài giảng rất chất lượng',
},
{
id: 26,
Q1: 3,
Q2: 4,
Q3: 3,
Q4: 4,
GPA: 3.5,
comment: 'Thầy thân thiện và hỗ trợ nhiệt tình',
},
{
id: 27,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 3,
GPA: 3.75,
comment: 'Phương pháp giảng hiện đại',
},
{
id: 28,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Thầy giải thích kỹ càng',
},
{
id: 29,
Q1: 3,
Q2: 3,
Q3: 4,
Q4: 3,
GPA: 3.25,
comment: 'Một vài chỗ khó theo kịp',
},
{
id: 30,
Q1: 4,
Q2: 4,
Q3: 4,
Q4: 4,
GPA: 4,
comment: 'Thầy truyền cảm hứng học tập',
},
{
id: 31,
Q1: 4,
Q2: 3,
Q3: 4,
Q4: 3,
GPA: 3.5,
comment: 'Cần nhiều buổi ôn tập hơn',
},
{
id: 32,
Q1: 4,
Q2: 4,
Q3: 3,
Q4: 4,
GPA: 3.75,
comment: 'Thầy luôn khuyến khích đặt câu hỏi',
},
], ],
}); });
......
import { StyleSheet, Text, View } from 'react-native' import {StyleSheet, Text, View} from 'react-native';
import R from '../../../assets/R' import R from '../../../assets/R';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
}, },
body:{ body: {
flex:1, flex: 1,
paddingHorizontal:15, paddingHorizontal: 15,
paddingVertical:10, paddingVertical: 10,
}, },
textSubTitle:{ textSubTitle: {
fontSize:R.sizes.sm, fontSize: R.sizes.sm,
fontFamily:R.fonts.fontRegular, fontFamily: R.fonts.fontRegular,
fontWeight:'400', fontWeight: '400',
color:R.colors.black, color: R.colors.black,
}, },
boxFeedBack:{ boxFeedBack: {
backgroundColor:R.colors.grayButton, backgroundColor: R.colors.grayButton,
paddingVertical:5, paddingVertical: 5,
borderLeftWidth:3, borderLeftWidth: 3,
paddingLeft:10, paddingLeft: 10,
paddingRight:10, paddingRight: 10,
borderLeftColor:R.colors.gray2, borderLeftColor: R.colors.gray2,
}, },
containerQuestion:{ containerQuestion: {
marginVertical:10, marginVertical: 10,
}, },
tableContainer: { tableContainer: {
borderWidth: 1, borderWidth: 1,
...@@ -84,6 +84,6 @@ const styles = StyleSheet.create({ ...@@ -84,6 +84,6 @@ const styles = StyleSheet.create({
textAlign: 'center', textAlign: 'center',
flexWrap: 'wrap', flexWrap: 'wrap',
}, },
}) });
export default styles export default styles;
import React from 'react'; import React from 'react';
import {Text, View, TouchableOpacity, StyleSheet, FlatList, ScrollView} from 'react-native'; import {
Text,
View,
TouchableOpacity,
StyleSheet,
FlatList,
ScrollView,
} from 'react-native';
import styles from './style'; import styles from './style';
import Header from '../../../components/Header/Header'; import Header from '../../../components/Header/Header';
import R from '../../../assets/R'; import R from '../../../assets/R';
const DetailFeedBackView = (props) => { const DetailFeedBackView = props => {
const {teacher,dataListQuestion} = props; const {teacher, dataListQuestion} = props;
console.log(props); console.log(props);
const renderTableRow = (item, index) => { const renderTableRow = (item, index) => {
...@@ -38,28 +45,40 @@ const DetailFeedBackView = (props) => { ...@@ -38,28 +45,40 @@ const DetailFeedBackView = (props) => {
const renderItem = ({item}) => { const renderItem = ({item}) => {
return ( return (
<View style={styles.boxFeedBack}> <View style={styles.boxFeedBack}>
<Text style={[styles.textSubTitle,{fontFamily:R.fonts.fontRegular,fontWeight:'400',color:R.colors.black,}]}>Q{item.id}: {item.question}</Text> <Text
style={[
styles.textSubTitle,
{
fontFamily: R.fonts.fontRegular,
fontWeight: '400',
color: R.colors.black,
},
]}>
Q{item.id}: {item.question}
</Text>
</View> </View>
); );
}; };
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Header title={'Đánh giá giảng dạy'} isBack/> <Header title={'Đánh giá giảng dạy'} isBack />
<View style={styles.body}> <View style={styles.body}>
<Text style={styles.textSubTitle}>Feedback ca sinh viên lp {teacher.class} môn {teacher.subject} đối vi ging viên {teacher.teacher}.</Text> <Text style={styles.textSubTitle}>
Feedback ca sinh viên lp {teacher.class} môn {teacher.subject} đối
vi ging viên {teacher.teacher}.
</Text>
<View style={styles.containerQuestion}> <View style={styles.containerQuestion}>
<FlatList <FlatList
nestedScrollEnabled nestedScrollEnabled
data={dataListQuestion?.question || []} data={dataListQuestion?.question || []}
renderItem={renderItem} renderItem={renderItem}
keyExtractor={(item) => item.id.toString()} keyExtractor={item => item.id.toString()}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
vertical vertical
/> />
</View> </View>
<ScrollView <ScrollView
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
style={styles.tableContainer}> style={styles.tableContainer}>
...@@ -87,11 +106,11 @@ const DetailFeedBackView = (props) => { ...@@ -87,11 +106,11 @@ const DetailFeedBackView = (props) => {
</View> </View>
</View> </View>
{dataListQuestion?.results?.map((item, index) => renderTableRow(item, index))} {dataListQuestion?.results?.map((item, index) =>
renderTableRow(item, index),
)}
</ScrollView> </ScrollView>
</View> </View>
</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