Commit df7585d6 by tungnq

TODO: Thêm workaround cho lỗi DeviceEventEmitter.removeListener và đồng bộ tháng ở header Drawer

parent 5cfc51c6
......@@ -7,7 +7,7 @@
*/
import React, {useEffect} from 'react';
import {View, Text} from 'react-native';
import {View, Text, DeviceEventEmitter} from 'react-native';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import rootReducer from './src/reducers/index';
......@@ -16,6 +16,17 @@ import createSagaMiddleware from 'redux-saga';
import rootSaga from './src/saga/rootSaga';
// import FirebaseNotification from "./src/helper/FirebaseNotification";
import SplashScreen from 'react-native-splash-screen';
// Workaround for react-native-modal removeListener issue
if (!DeviceEventEmitter.removeListener) {
DeviceEventEmitter.removeListener = function(eventType, listener) {
// Use the new API
const subscription = this.addListener(eventType, () => {});
if (subscription && subscription.remove) {
subscription.remove();
}
};
}
const sagaMiddleware = createSagaMiddleware();
let store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
......
......@@ -49,11 +49,21 @@ const DrawerNavigatorView = (props) => {
}
);
const updateHeaderMonthListener = DeviceEventEmitter.addListener(
"updateHeaderMonth",
(monthIndex) => {
const newDate = new Date(currentDate);
newDate.setMonth(monthIndex);
setCurrentDate(newDate);
}
);
return () => {
setLanguageListener.remove();
dateChangeListener.remove();
updateHeaderMonthListener.remove();
};
}, []);
}, [currentDate]);
const MenuButton = ({ onPress }) => (
<TouchableOpacity style={styles.menuButton} onPress={onPress}>
......
import {StyleSheet, Dimensions} from 'react-native';
import R from '../../../assets/R';
// ==================== HẰNG SỐ ====================
const {width: screenWidth, height: screenHeight} = Dimensions.get('window');
const HOUR_HEIGHT = 80;
const DAY_COLUMN_WIDTH = (screenWidth - 70) / 3;
const styles = StyleSheet.create({
// ==================== CONTAINER CHÍNH ====================
// Container tổng thể của màn hình Filter 3 ngày
container: {
flex: 1,
backgroundColor: R.colors.white,
},
// ==================== MONTH PICKER SECTION ====================
// Container chứa bộ chọn tháng
monthPickerContainer: {
backgroundColor: R.colors.white,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
paddingVertical: 10,
},
// Nội dung cuộn ngang của bộ chọn tháng
monthPickerContent: {
paddingHorizontal: 15,
},
// Item tháng trong bộ chọn
monthItem: {
paddingHorizontal: 20,
paddingVertical: 10,
......@@ -26,27 +36,40 @@ const styles = StyleSheet.create({
borderRadius: 20,
backgroundColor: R.colors.gray,
},
// Item tháng được chọn
monthItemSelected: {
backgroundColor: R.colors.black,
},
// Text của item tháng
monthItemText: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontRegular,
color: R.colors.black,
},
// Text của item tháng được chọn
monthItemTextSelected: {
color: R.colors.white,
fontFamily: R.fonts.fontMedium,
},
// ==================== 3 DAYS HEADER SECTION ====================
// Container chứa header 3 ngày
daysHeaderContainer: {
flexDirection: 'row',
backgroundColor: R.colors.grayBorderInputTextHeader,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray2,
},
// Header cột thời gian (trống)
timeColumnHeader: {
width: 70,
},
// Cell header của mỗi ngày
dayHeaderCell: {
width: DAY_COLUMN_WIDTH,
alignItems: 'center',
......@@ -54,17 +77,23 @@ const styles = StyleSheet.create({
borderRightWidth: 1,
borderRightColor: R.colors.gray2,
},
// Text tên ngày (Thứ 2, Thứ 3...)
dayHeaderText: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontMedium,
color: R.colors.black,
fontWeight: '600',
},
// Text tên ngày hôm nay
todayHeaderText: {
color: R.colors.black,
fontFamily: R.fonts.fontMedium,
fontWeight: '600',
},
// Container chứa số ngày
dayNumberContainer: {
minWidth: 28,
minHeight: 28,
......@@ -73,43 +102,64 @@ const styles = StyleSheet.create({
justifyContent: 'center',
marginVertical: 5,
},
// Container số ngày hôm nay (có background xanh)
todayNumberContainer: {
backgroundColor: R.colors.blue,
},
// Text số ngày
dayHeaderNumber: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontRegular,
color: R.colors.black,
fontWeight: '400',
},
// Text số ngày hôm nay (màu trắng)
todayHeaderNumber: {
color: R.colors.white,
fontFamily: R.fonts.fontMedium,
},
// ==================== TIME SLOTS SECTION ====================
// Container chứa các khung thời gian
timeSlotsContainer: {
flex: 1,
backgroundColor: R.colors.white,
},
// Nội dung cuộn dọc
scrollContent: {},
// Container timeline tổng thể
timelineContainer: {
flexDirection: 'row',
position: 'relative',
},
// Cột nhãn thời gian bên trái
timeLabelsColumn: {
width: 70,
borderRightWidth: 1,
borderRightColor: R.colors.gray2,
},
// Container chứa grid 3 ngày
daysGridContainer: {
flex: 1,
flexDirection: 'row',
},
// Cột của mỗi ngày
dayColumn: {
width: DAY_COLUMN_WIDTH,
position: 'relative',
borderRightWidth: 1,
borderRightColor: R.colors.gray2,
},
// Khung thời gian (1 giờ)
timeSlot: {
height: HOUR_HEIGHT,
alignItems: 'center',
......@@ -117,35 +167,48 @@ const styles = StyleSheet.create({
borderBottomWidth: 1,
borderBottomColor: R.colors.gray2,
},
// Cell grid của mỗi giờ trong ngày
gridCell: {
height: HOUR_HEIGHT,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray2,
width: '100%',
},
// Text hiển thị giờ (07:00, 08:00...)
timeText: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontRegular,
color: R.colors.black,
fontWeight: '400',
},
// ==================== EVENT CARD SECTION ====================
// Card hiển thị sự kiện
eventCard: {
borderRadius: 8,
paddingHorizontal: 6,
paddingVertical: 4,
},
// Tiêu đề sự kiện
eventTitle: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontMedium,
color: R.colors.white,
marginBottom: 2,
},
// Phụ đề sự kiện
eventSubtitle: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontRegular,
color: R.colors.white,
fontWeight: '400',
},
// Thời gian sự kiện
eventTime: {
fontSize: R.fontsize.fontSizeLabel,
fontFamily: R.fonts.fontRegular,
......
import React, {useState, useRef, useEffect} from 'react';
import {Dimensions, DeviceEventEmitter, PanResponder} from 'react-native';
import {Dimensions, PanResponder} from 'react-native';
import {useNavigation, useFocusEffect} from '@react-navigation/native';
import {DeviceEventEmitter} from 'react-native';
import FilterWeekView from './view';
// ==================== HẰNG SỐ ====================
......@@ -8,6 +10,8 @@ const HOUR_HEIGHT = 80;
const DAY_COLUMN_WIDTH = (screenWidth - 70) / 7;
const FilterWeek = ({navigation}) => {
const navigationHook = useNavigation();
// ==================== QUẢN LÝ STATE ====================
// B1: State ngày tháng và lịch
const [currentDate, setCurrentDate] = useState(new Date());
......@@ -20,6 +24,18 @@ const FilterWeek = ({navigation}) => {
const scrollViewRef = useRef(null);
// ==================== EFFECTS ====================
// Reset về ngày hiện tại khi chuyển màn hình
useFocusEffect(
React.useCallback(() => {
const today = new Date();
setCurrentDate(today);
setSelectedDate(today);
DeviceEventEmitter.emit('onDateChange', today);
// Cập nhật header drawer với tháng hiện tại
DeviceEventEmitter.emit('updateHeaderMonth', today.getMonth());
}, [])
);
useEffect(() => {
DeviceEventEmitter.emit('onDateChange', selectedDate);
}, [selectedDate]);
......@@ -107,7 +123,7 @@ const FilterWeek = ({navigation}) => {
subtitle: 'CS Địa lý 4D',
time: '07:00',
endTime: '09:00',
date: '2025-08-26',
date: '2025-01-08',
type: 'class',
},
{
......@@ -116,7 +132,7 @@ const FilterWeek = ({navigation}) => {
subtitle: 'Phòng họp A1',
time: '10:00',
endTime: '11:30',
date: '2025-07-22',
date: '2025-01-09',
type: 'meeting',
},
{
......@@ -125,34 +141,7 @@ const FilterWeek = ({navigation}) => {
subtitle: 'Online Zoom',
time: '14:00',
endTime: '16:00',
date: '2025-07-23',
type: 'training',
},
{
id: '4',
title: 'Code Review Session',
subtitle: 'Dev Team',
time: '09:00',
endTime: '10:30',
date: '2025-07-24',
type: 'review',
},
{
id: '5',
title: 'Sprint Planning',
subtitle: 'Scrum Team',
time: '15:00',
endTime: '17:00',
date: '2025-07-25',
type: 'meeting',
},
{
id: '6',
title: 'Tech Talk',
subtitle: 'Conference Room',
time: '11:00',
endTime: '12:00',
date: '2025-07-26',
date: '2025-01-10',
type: 'training',
},
];
......@@ -192,6 +181,8 @@ const FilterWeek = ({navigation}) => {
setSelectedDate(newDate);
setShowMonthPicker(false);
DeviceEventEmitter.emit('onDateChange', newDate);
// Cập nhật header drawer với tháng mới
DeviceEventEmitter.emit('updateHeaderMonth', monthIndex);
};
// X2: Xử lý chuyển tuần
......@@ -201,6 +192,8 @@ const FilterWeek = ({navigation}) => {
setCurrentDate(nextWeek);
setSelectedDate(nextWeek);
DeviceEventEmitter.emit('onDateChange', nextWeek);
// Cập nhật header drawer nếu tháng thay đổi
DeviceEventEmitter.emit('updateHeaderMonth', nextWeek.getMonth());
};
const swipeToPrevWeek = () => {
......@@ -209,6 +202,8 @@ const FilterWeek = ({navigation}) => {
setCurrentDate(prevWeek);
setSelectedDate(prevWeek);
DeviceEventEmitter.emit('onDateChange', prevWeek);
// Cập nhật header drawer nếu tháng thay đổi
DeviceEventEmitter.emit('updateHeaderMonth', prevWeek.getMonth());
};
// X3: Xử lý toggle month picker
......
......@@ -5,10 +5,24 @@ const {width} = Dimensions.get('window');
const DAY_COLUMN_WIDTH = (width - 70) / 7;
const styles = StyleSheet.create({
// ==================== CONTAINER CHÍNH ====================
// Tương ứng với View chính trong FilterWeekView (dòng 166)
container: {
flex: 1,
backgroundColor: R.colors.white,
},
// ==================== MONTH PICKER ====================
// Tương ứng với renderMonthPicker() (dòng 19-49)
monthPickerContainer: {
backgroundColor: R.colors.white,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
paddingVertical: 10,
},
monthPickerContent: {
paddingHorizontal: 15,
},
monthItem: {
paddingHorizontal: 20,
paddingVertical: 8,
......@@ -28,6 +42,9 @@ const styles = StyleSheet.create({
color: R.colors.white,
fontFamily: R.fonts.fontMedium,
},
// ==================== WEEK HEADER ====================
// Tương ứng với renderWeekHeader() (dòng 51-87)
weekHeaderContainer: {
flexDirection: 'row',
backgroundColor: R.colors.grayBorderInputTextHeader,
......@@ -57,7 +74,6 @@ const styles = StyleSheet.create({
color: R.colors.black,
fontWeight: '600',
},
dayHeaderNumberContainerToday: {
borderRadius: 15,
justifyContent: 'center',
......@@ -71,8 +87,15 @@ const styles = StyleSheet.create({
backgroundColor: R.colors.blue,
borderRadius: 15,
paddingHorizontal: 8,
paddingVertical: 2,
paddingVertical: 4,
},
dayHeaderTextToday: {
color: R.colors.blue,
fontWeight: '700',
},
// ==================== TIME SLOTS CONTAINER ====================
// Tương ứng với renderTimeSlots() (dòng 89-163)
timeSlotsContainer: {
flex: 1,
backgroundColor: R.colors.white,
......@@ -84,11 +107,30 @@ const styles = StyleSheet.create({
flexDirection: 'row',
position: 'relative',
},
// ==================== TIME LABELS COLUMN ====================
// Tương ứng với timeLabelsColumn (dòng 100-109)
timeLabelsColumn: {
width: 70,
borderRightWidth: 1,
borderRightColor: R.colors.gray,
},
timeSlot: {
height: 80,
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
},
timeText: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontRegular,
fontWeight: '400',
color: R.colors.black,
},
// ==================== WEEK GRID CONTAINER ====================
// Tương ứng với weekGridContainer (dòng 111-158)
weekGridContainer: {
flex: 1,
flexDirection: 'row',
......@@ -99,34 +141,15 @@ const styles = StyleSheet.create({
borderRightWidth: 1,
borderRightColor: R.colors.gray,
},
timeSlot: {
height: 80,
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
},
gridCell: {
height: 80,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
width: '100%',
},
monthPickerContainer: {
backgroundColor: R.colors.white,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
paddingVertical: 10,
},
monthPickerContent: {
paddingHorizontal: 15,
},
timeText: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontRegular,
fontWeight: '400',
color: R.colors.black,
},
// ==================== EVENT CARDS ====================
// Tương ứng với event rendering (dòng 118-155)
eventCard: {
borderRadius: 10,
paddingHorizontal: 4,
......
import React, {useState, useRef, useEffect} from 'react';
import {useNavigation, useFocusEffect} from '@react-navigation/native';
import {DeviceEventEmitter, PanResponder} from 'react-native';
import FilterDayView from './view';
......@@ -12,15 +13,45 @@ const FilterDay = ({navigation}) => {
DeviceEventEmitter.emit('onDateChange', selectedDate);
}, [selectedDate]);
// Reset về ngày hiện tại khi chuyển màn hình
useFocusEffect(
React.useCallback(() => {
const today = new Date();
setCurrentDate(today);
setSelectedDate(today);
DeviceEventEmitter.emit('onDateChange', today);
// Cập nhật header drawer với tháng hiện tại
DeviceEventEmitter.emit('updateHeaderMonth', today.getMonth());
}, [])
);
const createMockEvents = () => {
const today = new Date();
const formatDateToString = date => {
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
};
const todayStr = formatDateToString(today);
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
const tomorrowStr = formatDateToString(tomorrow);
const yesterday = new Date(today);
yesterday.setDate(today.getDate() - 1);
const yesterdayStr = formatDateToString(yesterday);
return [
// Sự kiện hôm nay
{
id: '1',
title: 'Lịch vào trực lớp TTCĐT 445.T1',
subtitle: 'CS Địa lý 4D',
time: '07:00',
endTime: '09:00',
date: '2025-08-25',
date: todayStr,
type: 'class',
},
{
......@@ -29,18 +60,141 @@ const FilterDay = ({navigation}) => {
subtitle: 'Phòng họp A1',
time: '10:00',
endTime: '11:30',
date: '2025-07-24',
date: todayStr,
type: 'meeting',
},
{
id: '3',
title: 'Nghỉ giải lao',
subtitle: 'Thư giãn',
time: '11:30',
endTime: '12:30',
date: todayStr,
type: 'break',
},
{
id: '3',
title: 'Đang ngủ',
subtitle: 'Thư giãn',
time: '12:30',
endTime: '13:30',
date: todayStr,
type: 'break',
},
{
id: '4',
title: 'Ăn trưa',
subtitle: 'Căng tin trường',
time: '12:00',
endTime: '13:00',
date: todayStr,
type: 'meal',
},
{
id: '5',
title: 'Training React Native',
subtitle: 'Online Zoom',
time: '14:00',
endTime: '16:00',
date: '2025-07-25',
date: todayStr,
type: 'training',
},
{
id: '6',
title: 'Code Review Session',
subtitle: 'Dev Team',
time: '16:30',
endTime: '17:30',
date: todayStr,
type: 'review',
},
// Sự kiện ngày mai
{
id: '7',
title: 'Họp nội bộ khoa CNTT',
subtitle: 'Phòng họp B2',
time: '08:00',
endTime: '10:00',
date: tomorrowStr,
type: 'meeting',
},
{
id: '8',
title: 'Lịch học lớp EWC45.364.L1',
subtitle: 'Tiếng Anh chuyên ngành',
time: '10:30',
endTime: '12:00',
date: tomorrowStr,
type: 'class',
},
{
id: '9',
title: 'Workshop AI trong giáo dục',
subtitle: 'Hội trường lớn',
time: '13:30',
endTime: '17:00',
date: tomorrowStr,
type: 'workshop',
},
// Sự kiện hôm qua
{
id: '10',
title: 'Seminar Công nghệ mới',
subtitle: 'Phòng 301',
time: '09:00',
endTime: '11:00',
date: yesterdayStr,
type: 'seminar',
},
{
id: '11',
title: 'Chấm bài thi cuối kỳ',
subtitle: 'Văn phòng giảng viên',
time: '14:00',
endTime: '17:00',
date: yesterdayStr,
type: 'grading',
},
// Sự kiện ngày cố định
{
id: '12',
title: 'Lịch vào trực lớp IT47.8F7',
subtitle: 'Môn học chuyên ngành',
time: '07:30',
endTime: '09:00',
date: '2025-01-15',
type: 'class',
},
{
id: '13',
title: 'Hội nghị khoa học sinh viên',
subtitle: 'Hội trường A',
time: '08:30',
endTime: '14:00',
date: '2025-01-20',
type: 'conference',
},
{
id: '14',
title: 'Bảo vệ đồ án tốt nghiệp',
subtitle: 'Phòng 205',
time: '13:00',
endTime: '17:30',
date: '2025-01-25',
type: 'defense',
},
{
id: '15',
title: 'Tổng kết học kỳ',
subtitle: 'Phòng họp khoa',
time: '15:00',
endTime: '18:00',
date: '2025-01-30',
type: 'summary',
},
];
};
......@@ -88,6 +242,8 @@ const FilterDay = ({navigation}) => {
setSelectedDate(newDate);
setShowMonthPicker(false);
DeviceEventEmitter.emit('onDateChange', newDate);
// Cập nhật header drawer với tháng mới
DeviceEventEmitter.emit('updateHeaderMonth', monthIndex);
};
const swipeToNextDay = () => {
......@@ -96,6 +252,8 @@ const FilterDay = ({navigation}) => {
setSelectedDate(nextDay);
setCurrentDate(nextDay);
DeviceEventEmitter.emit('onDateChange', nextDay);
// Cập nhật header drawer nếu tháng thay đổi
DeviceEventEmitter.emit('updateHeaderMonth', nextDay.getMonth());
};
const swipeToPrevDay = () => {
......@@ -104,6 +262,8 @@ const FilterDay = ({navigation}) => {
setSelectedDate(prevDay);
setCurrentDate(prevDay);
DeviceEventEmitter.emit('onDateChange', prevDay);
// Cập nhật header drawer nếu tháng thay đổi
DeviceEventEmitter.emit('updateHeaderMonth', prevDay.getMonth());
};
const toggleMonthPicker = () => {
......@@ -139,6 +299,26 @@ const FilterDay = ({navigation}) => {
return {topPosition, height};
};
const calculateEventLayout = (events) => {
return events.map((event, index) => {
const {topPosition, height} = calculateEventPosition(event.time, event.endTime);
// Simple stacking - each subsequent event gets slightly offset
const stackOffset = index * 8; // 8px offset for each event
const leftOffset = 5 + stackOffset;
const rightOffset = 15 + stackOffset;
return {
...event,
topPosition,
height,
leftOffset,
rightOffset,
zIndex: 10 + index // Higher z-index for later events
};
});
};
return (
<FilterDayView
navigation={navigation}
......@@ -153,6 +333,7 @@ const FilterDay = ({navigation}) => {
handleMonthSelect={handleMonthSelect}
toggleMonthPicker={toggleMonthPicker}
calculateEventPosition={calculateEventPosition}
calculateEventLayout={calculateEventLayout}
/>
);
};
......
......@@ -5,10 +5,15 @@ const {width: screenWidth, height: screenHeight} = Dimensions.get('window');
const HOUR_HEIGHT = 80;
const styles = StyleSheet.create({
// ==================== CONTAINER CHÍNH ====================
// Tương ứng với View chính trong FilterDayView dòng 117
container: {
flex: 1,
backgroundColor: R.colors.white,
},
// ==================== MONTH PICKER ====================
// Tương ứng với renderMonthPicker dòng 25-27
monthPickerContainer: {
backgroundColor: R.colors.white,
borderBottomWidth: 1,
......@@ -25,6 +30,9 @@ const styles = StyleSheet.create({
borderRadius: 20,
backgroundColor: R.colors.gray,
},
// ==================== DATE INFO CONTAINER ====================
// Tương ứng với renderDateInfo dòng 29-43
dateInfoContainer: {
paddingHorizontal: 15,
paddingVertical: 12,
......@@ -47,6 +55,19 @@ const styles = StyleSheet.create({
color: R.colors.black,
fontWeight: '400',
},
dayNumberToday: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontRegular,
color: R.colors.white,
fontWeight: '400',
backgroundColor: R.colors.blue,
borderRadius: 15,
paddingHorizontal: 8,
paddingVertical: 4,
},
// ==================== TIME SLOTS CONTAINER ====================
// Tương ứng với renderTimeSlots dòng 45-115
timeSlotsContainer: {
flex: 1,
backgroundColor: R.colors.white,
......@@ -58,16 +79,14 @@ const styles = StyleSheet.create({
flexDirection: 'row',
position: 'relative',
},
// ==================== TIME LABELS COLUMN ====================
// Tương ứng với timeLabelsColumn dòng 56-65
timeLabelsColumn: {
minWidth: 70,
borderRightWidth: 1,
borderRightColor: R.colors.gray,
},
eventsColumn: {
flex: 1,
position: 'relative',
minHeight: 24 * HOUR_HEIGHT,
},
timeSlot: {
height: HOUR_HEIGHT,
alignItems: 'center',
......@@ -75,22 +94,34 @@ const styles = StyleSheet.create({
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
},
gridLine: {
height: HOUR_HEIGHT,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
width: '100%',
},
timeText: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontRegular,
color: R.colors.black,
fontWeight: '400',
},
// ==================== EVENTS COLUMN ====================
// Tương ứng với eventsColumn dòng 67-110
eventsColumn: {
flex: 1,
position: 'relative',
height: 24 * HOUR_HEIGHT,
},
gridLine: {
height: HOUR_HEIGHT,
borderBottomWidth: 1,
borderBottomColor: R.colors.gray,
width: '100%',
},
// ==================== EVENT CARDS ====================
// Tương ứng với event rendering dòng 72-109
eventCard: {
borderRadius: 15,
paddingLeft: 15,
paddingTop: 10,
paddingHorizontal: 8,
paddingVertical: 4,
justifyContent: 'flex-start',
},
eventTitle: {
fontSize: R.fontsize.fontSizeContent,
......@@ -106,16 +137,6 @@ const styles = StyleSheet.create({
color: R.colors.white,
marginBottom: 5,
},
dayNumberToday: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontRegular,
color: R.colors.white,
fontWeight: '400',
backgroundColor: R.colors.blue,
borderRadius: 15,
paddingHorizontal: 8,
paddingVertical: 2,
},
eventTime: {
fontSize: R.fontsize.fontSizeContent,
fontFamily: R.fonts.fontRegular,
......
......@@ -5,13 +5,18 @@ import styles from './style';
const FilterDayView = props => {
const {
currentDate,
selectedDate,
showMonthPicker,
scrollViewRef,
panResponder,
getEventsForDate,
getDayName,
getMonthName,
handleMonthSelect,
toggleMonthPicker,
calculateEventPosition,
calculateEventLayout,
} = props;
const isToday = date => {
......@@ -69,12 +74,7 @@ const FilterDayView = props => {
<View key={hour} style={styles.gridLine} />
))}
{selectedEvents.map(event => {
const {topPosition, height} = calculateEventPosition(
event.time,
event.endTime,
);
{calculateEventLayout(selectedEvents).map(event => {
return (
<TouchableOpacity
key={event.id}
......@@ -82,21 +82,21 @@ const FilterDayView = props => {
styles.eventCard,
{
position: 'absolute',
top: topPosition,
height: Math.max(height, 40),
left: 5,
right: 15,
zIndex: 10,
top: event.topPosition,
height: event.height,
left: event.leftOffset,
right: event.rightOffset,
zIndex: event.zIndex,
backgroundColor: R.colors.blue,
},
]}
activeOpacity={0.7}>
<Text
style={styles.eventTitle}
numberOfLines={height > 60 ? 2 : 1}>
numberOfLines={event.height > 60 ? 2 : 1}>
{event.title}
</Text>
{height > 40 && (
{event.height > 40 && (
<Text style={styles.eventSubtitle} numberOfLines={1}>
{event.subtitle}
</Text>
......
import React, {useState, useMemo, useRef} from 'react';
import React, {useState, useMemo, useRef, useEffect} from 'react';
import {Animated, PanResponder, Dimensions, DeviceEventEmitter} from 'react-native';
import {useFocusEffect} from '@react-navigation/native';
import ClassScheduleView from './view';
// ==================== HẰNG SỐ ====================
......@@ -12,6 +13,19 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
const [currentDate, setCurrentDate] = useState(new Date());
const [selectedDate, setSelectedDate] = useState(null);
// ==================== EFFECTS ====================
// Reset về ngày hiện tại khi chuyển màn hình
useFocusEffect(
React.useCallback(() => {
const today = new Date();
setCurrentDate(today);
setSelectedDate(null);
DeviceEventEmitter.emit('onDateChange', today);
// Cập nhật header drawer với tháng hiện tại
DeviceEventEmitter.emit('updateHeaderMonth', today.getMonth());
}, [])
);
// B2: State bottom sheet
const [showBottomSheet, setShowBottomSheet] = useState(false);
......@@ -291,6 +305,8 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
// Phát sự kiện để cập nhật header title
DeviceEventEmitter.emit('onDateChange', newDate.toISOString());
// Cập nhật header drawer với tháng mới
DeviceEventEmitter.emit('updateHeaderMonth', newDate.getMonth());
if (showBottomSheet) {
hideBottomSheetModal();
......
......@@ -3,7 +3,7 @@ import R from '../../assets/R';
const {width: screenWidth, height: screenHeight} = Dimensions.get('window');
const CELL_WIDTH = (screenWidth - 30) / 7;
const CELL_HEIGHT = (screenHeight - 140) / 6;
const CELL_HEIGHT = (screenHeight - 160) / 6;
const BOTTOM_SHEET_HEIGHT = screenHeight * 0.6;
const styles = StyleSheet.create({
......@@ -40,6 +40,7 @@ const styles = StyleSheet.create({
color: R.colors.white,
fontSize: R.fontsize.fontsSizeTitle,
fontFamily: R.fonts.fontMedium,
height: '100%',
},
// Tiêu đề các ngày trong tuần
......@@ -227,7 +228,7 @@ const styles = StyleSheet.create({
marginBottom: 10,
marginHorizontal: 15,
borderLeftWidth: 4,
borderLeftColor: R.colors.blue500,
borderLeftColor: R.colors.blue,
shadowColor: R.colors.black,
shadowOffset: {
width: 0,
......
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