Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
AppUms_Student
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tungnq
AppUms_Student
Commits
10a23b76
Commit
10a23b76
authored
Sep 18, 2025
by
tungnq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TODO: Đã refactor xong tháng
parent
03cfc11f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
379 additions
and
287 deletions
+379
-287
index.js
src/screens/class_schedule/index.js
+118
-72
style.js
src/screens/class_schedule/style.js
+256
-210
view.js
src/screens/class_schedule/view.js
+5
-4
view.js
src/screens/home/view.js
+0
-1
No files found.
src/screens/class_schedule/index.js
View file @
10a23b76
import
React
,
{
useState
,
useMemo
,
useRef
}
from
'react'
;
import
React
,
{
useState
,
useMemo
,
useRef
,
useEffect
}
from
'react'
;
import
{
Animated
,
PanResponder
,
Dimensions
}
from
'react-native'
;
import
{
Animated
,
PanResponder
,
Dimensions
,
DeviceEventEmitter
}
from
'react-native'
;
import
{
useFocusEffect
}
from
'@react-navigation/native'
;
import
ClassScheduleView
from
'./view'
;
import
ClassScheduleView
from
'./view'
;
// ==================== HẰNG SỐ ====================
const
{
height
:
screenHeight
}
=
Dimensions
.
get
(
'window'
);
const
{
height
:
screenHeight
}
=
Dimensions
.
get
(
'window'
);
const
BOTTOM_SHEET_HEIGHT
=
screenHeight
*
0.6
;
const
BOTTOM_SHEET_HEIGHT
=
screenHeight
*
0.6
;
const
ClassSchedule
=
({
events
=
[],
onDateSelect
,
onEventPress
})
=>
{
const
ClassSchedule
=
({
events
=
[],
onDateSelect
,
onEventPress
})
=>
{
const
[
currentDate
,
setCurrentDate
]
=
useState
(
new
Date
(
2025
,
7
,
1
));
// ==================== QUẢN LÝ STATE ====================
// B1: State ngày tháng và lịch
const
[
currentDate
,
setCurrentDate
]
=
useState
(
new
Date
());
const
[
selectedDate
,
setSelectedDate
]
=
useState
(
null
);
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
);
const
[
showBottomSheet
,
setShowBottomSheet
]
=
useState
(
false
);
const
bottomSheetTranslateY
=
useRef
(
new
Animated
.
Value
(
BOTTOM_SHEET_HEIGHT
)).
current
;
const
formatDateToString
=
(
date
)
=>
{
// B3: Tham chiếu animation
const
bottomSheetTranslateY
=
useRef
(
new
Animated
.
Value
(
BOTTOM_SHEET_HEIGHT
),
).
current
;
// ==================== HÀM TIỆN ÍCH ====================
// T1: Định dạng ngày thành chuỗi
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
}
`
;
};
};
// T2: Định dạng ngày để hiển thị
const
formatDateToDisplay
=
date
=>
{
const
day
=
date
.
getDate
().
toString
().
padStart
(
2
,
'0'
);
const
month
=
(
date
.
getMonth
()
+
1
).
toString
().
padStart
(
2
,
'0'
);
const
year
=
date
.
getFullYear
();
return
`Lịch ngày
${
day
}
/
${
month
}
/
${
year
}
`
;
};
// T3: Chuyển đổi chuỗi thành ngày
const
parseLocalDate
=
dateString
=>
{
const
[
year
,
month
,
day
]
=
dateString
.
split
(
'-'
).
map
(
Number
);
return
new
Date
(
year
,
month
-
1
,
day
);
};
// ==================== QUẢN LÝ DỮ LIỆU ====================
// D1: Tạo dữ liệu sự kiện mẫu
const
createMockEvents
=
()
=>
{
const
createMockEvents
=
()
=>
{
const
today
=
new
Date
();
const
today
=
new
Date
();
const
todayStr
=
formatDateToString
(
today
);
const
todayStr
=
formatDateToString
(
today
);
...
@@ -147,32 +187,25 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -147,32 +187,25 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
];
];
};
};
// D2: Xử lý dữ liệu sự kiện
const
mockEvents
=
createMockEvents
();
const
mockEvents
=
createMockEvents
();
const
allEvents
=
[...
events
,
...
mockEvents
];
const
allEvents
=
[...
events
,
...
mockEvents
];
const
panResponder
=
useRef
(
// D3: Hàm truy vấn sự kiện
PanResponder
.
create
({
const
getEventsForDate
=
date
=>
{
onMoveShouldSetPanResponder
:
(
evt
,
gestureState
)
=>
{
const
dateStr
=
formatDateToString
(
date
);
return
Math
.
abs
(
gestureState
.
dy
)
>
10
;
return
allEvents
.
filter
(
event
=>
event
.
date
===
dateStr
);
},
};
onPanResponderMove
:
(
evt
,
gestureState
)
=>
{
if
(
gestureState
.
dy
>
0
)
{
bottomSheetTranslateY
.
setValue
(
gestureState
.
dy
);
}
},
onPanResponderRelease
:
(
evt
,
gestureState
)
=>
{
if
(
gestureState
.
dy
>
100
)
{
hideBottomSheetModal
();
}
else
{
Animated
.
spring
(
bottomSheetTranslateY
,
{
toValue
:
0
,
useNativeDriver
:
true
,
}).
start
();
}
},
})
).
current
;
const
getSelectedEvents
=
()
=>
{
if
(
!
selectedDate
)
return
[];
return
allEvents
.
filter
(
event
=>
event
.
date
===
selectedDate
)
.
sort
((
a
,
b
)
=>
a
.
time
.
localeCompare
(
b
.
time
));
};
// ==================== LOGIC LỊCH ====================
// L1: Tạo dữ liệu tháng
const
getMonthData
=
useMemo
(()
=>
{
const
getMonthData
=
useMemo
(()
=>
{
const
year
=
currentDate
.
getFullYear
();
const
year
=
currentDate
.
getFullYear
();
const
month
=
currentDate
.
getMonth
();
const
month
=
currentDate
.
getMonth
();
...
@@ -198,28 +231,12 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -198,28 +231,12 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
};
};
},
[
currentDate
]);
},
[
currentDate
]);
const
getEventsForDate
=
(
date
)
=>
{
// L2: Hàm kiểm tra ngày tháng
const
dateStr
=
formatDateToString
(
date
);
const
isCurrentMonth
=
date
=>
{
return
allEvents
.
filter
(
event
=>
event
.
date
===
dateStr
);
};
const
parseLocalDate
=
(
dateString
)
=>
{
const
[
year
,
month
,
day
]
=
dateString
.
split
(
'-'
).
map
(
Number
);
return
new
Date
(
year
,
month
-
1
,
day
);
};
const
formatDateToDisplay
=
(
date
)
=>
{
const
day
=
date
.
getDate
().
toString
().
padStart
(
2
,
'0'
);
const
month
=
(
date
.
getMonth
()
+
1
).
toString
().
padStart
(
2
,
'0'
);
const
year
=
date
.
getFullYear
();
return
`Lịch ngày
${
day
}
/
${
month
}
/
${
year
}
`
;
};
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
()
&&
...
@@ -228,20 +245,32 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -228,20 +245,32 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
);
);
};
};
const
navigateMonth
=
(
direction
)
=>
{
// ==================== HỆ THỐNG ANIMATION ====================
const
newDate
=
new
Date
(
currentDate
);
// A1: Thiết lập PanResponder
if
(
direction
===
'prev'
)
{
const
panResponder
=
useRef
(
newDate
.
setMonth
(
newDate
.
getMonth
()
-
1
);
PanResponder
.
create
({
}
else
{
onMoveShouldSetPanResponder
:
(
evt
,
gestureState
)
=>
{
newDate
.
setMonth
(
newDate
.
getMonth
()
+
1
);
return
Math
.
abs
(
gestureState
.
dy
)
>
10
;
}
},
setCurrentDate
(
newDate
);
onPanResponderMove
:
(
evt
,
gestureState
)
=>
{
setSelectedDate
(
null
);
if
(
gestureState
.
dy
>
0
)
{
if
(
showBottomSheet
)
{
bottomSheetTranslateY
.
setValue
(
gestureState
.
dy
);
hideBottomSheetModal
();
}
}
},
};
onPanResponderRelease
:
(
evt
,
gestureState
)
=>
{
if
(
gestureState
.
dy
>
100
)
{
hideBottomSheetModal
();
}
else
{
Animated
.
spring
(
bottomSheetTranslateY
,
{
toValue
:
0
,
useNativeDriver
:
true
,
}).
start
();
}
},
}),
).
current
;
// A2: Hàm animation Bottom Sheet
const
showBottomSheetModal
=
()
=>
{
const
showBottomSheetModal
=
()
=>
{
setShowBottomSheet
(
true
);
setShowBottomSheet
(
true
);
Animated
.
spring
(
bottomSheetTranslateY
,
{
Animated
.
spring
(
bottomSheetTranslateY
,
{
...
@@ -262,10 +291,33 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -262,10 +291,33 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
});
});
};
};
const
handleDatePress
=
(
date
)
=>
{
// ==================== XỬ LÝ SỰ KIỆN ====================
// X1: Xử lý điều hướng
const
navigateMonth
=
direction
=>
{
const
newDate
=
new
Date
(
currentDate
);
if
(
direction
===
'prev'
)
{
newDate
.
setMonth
(
newDate
.
getMonth
()
-
1
);
}
else
{
newDate
.
setMonth
(
newDate
.
getMonth
()
+
1
);
}
setCurrentDate
(
newDate
);
setSelectedDate
(
null
);
// 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
();
}
};
// X2: Xử lý chọn ngày
const
handleDatePress
=
date
=>
{
const
dateStr
=
formatDateToString
(
date
);
const
dateStr
=
formatDateToString
(
date
);
const
dayEvents
=
getEventsForDate
(
date
);
const
dayEvents
=
getEventsForDate
(
date
);
setSelectedDate
(
dateStr
);
setSelectedDate
(
dateStr
);
onDateSelect
?.(
dateStr
);
onDateSelect
?.(
dateStr
);
...
@@ -274,7 +326,8 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -274,7 +326,8 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
}
}
};
};
const
handleEventPress
=
(
event
)
=>
{
// X3: Xử lý tương tác sự kiện
const
handleEventPress
=
event
=>
{
onEventPress
?.(
event
);
onEventPress
?.(
event
);
};
};
...
@@ -282,13 +335,6 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -282,13 +335,6 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
hideBottomSheetModal
();
hideBottomSheetModal
();
};
};
const
getSelectedEvents
=
()
=>
{
if
(
!
selectedDate
)
return
[];
return
allEvents
.
filter
(
event
=>
event
.
date
===
selectedDate
)
.
sort
((
a
,
b
)
=>
a
.
time
.
localeCompare
(
b
.
time
));
};
return
(
return
(
<
ClassScheduleView
<
ClassScheduleView
currentDate
=
{
currentDate
}
currentDate
=
{
currentDate
}
...
@@ -300,6 +346,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -300,6 +346,7 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
getEventsForDate
=
{
getEventsForDate
}
getEventsForDate
=
{
getEventsForDate
}
parseLocalDate
=
{
parseLocalDate
}
parseLocalDate
=
{
parseLocalDate
}
formatDateToDisplay
=
{
formatDateToDisplay
}
formatDateToDisplay
=
{
formatDateToDisplay
}
formatDateToString
=
{
formatDateToString
}
isCurrentMonth
=
{
isCurrentMonth
}
isCurrentMonth
=
{
isCurrentMonth
}
isToday
=
{
isToday
}
isToday
=
{
isToday
}
navigateMonth
=
{
navigateMonth
}
navigateMonth
=
{
navigateMonth
}
...
@@ -311,4 +358,4 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
...
@@ -311,4 +358,4 @@ const ClassSchedule = ({events = [], onDateSelect, onEventPress}) => {
);
);
};
};
export
default
ClassSchedule
;
export
default
ClassSchedule
;
\ No newline at end of file
src/screens/class_schedule/style.js
View file @
10a23b76
...
@@ -3,225 +3,271 @@ import R from '../../assets/R';
...
@@ -3,225 +3,271 @@ import R from '../../assets/R';
const
{
width
:
screenWidth
,
height
:
screenHeight
}
=
Dimensions
.
get
(
'window'
);
const
{
width
:
screenWidth
,
height
:
screenHeight
}
=
Dimensions
.
get
(
'window'
);
const
CELL_WIDTH
=
(
screenWidth
-
30
)
/
7
;
const
CELL_WIDTH
=
(
screenWidth
-
30
)
/
7
;
const
CELL_HEIGHT
=
(
screenHeight
-
1
4
0
)
/
6
;
const
CELL_HEIGHT
=
(
screenHeight
-
1
6
0
)
/
6
;
const
BOTTOM_SHEET_HEIGHT
=
screenHeight
*
0.6
;
const
BOTTOM_SHEET_HEIGHT
=
screenHeight
*
0.6
;
const
styles
=
StyleSheet
.
create
({
const
styles
=
StyleSheet
.
create
({
// Container chính của màn hình
container
:
{
container
:
{
flex
:
1
,
flex
:
1
,
backgroundColor
:
R
.
colors
.
white
,
backgroundColor
:
R
.
colors
.
white
,
alignItems
:
'center'
,
alignItems
:
'center'
,
},
},
// Header tháng/năm với nút điều hướng
header
:
{
header
:
{
flexDirection
:
'row'
,
flexDirection
:
'row'
,
alignItems
:
'center'
,
alignItems
:
'center'
,
justifyContent
:
'space-between'
,
justifyContent
:
'space-between'
,
paddingVertical
:
15
,
paddingVertical
:
15
,
},
},
header_title
:
{
header_title
:
{
fontSize
:
R
.
fontsize
.
fontsSize16
,
fontSize
:
R
.
fontsize
.
fontsSizeTitle
,
fontFamily
:
R
.
fonts
.
InterMedium
,
fontFamily
:
R
.
fonts
.
fontMedium
,
color
:
R
.
colors
.
black
,
color
:
R
.
colors
.
black
,
fontWeight
:
'600'
,
fontWeight
:
'600'
,
},
},
navButton
:
{
// Nút điều hướng tháng trước/sau
width
:
30
,
navButton
:
{
height
:
30
,
width
:
30
,
borderRadius
:
20
,
height
:
30
,
backgroundColor
:
R
.
colors
.
blue500
,
borderRadius
:
20
,
alignItems
:
'center'
,
backgroundColor
:
R
.
colors
.
blue
,
justifyContent
:
'center'
,
alignItems
:
'center'
,
},
justifyContent
:
'center'
,
navButtonText
:
{
},
color
:
R
.
colors
.
white
,
navButtonText
:
{
fontSize
:
R
.
fontsize
.
fontsSize16
,
color
:
R
.
colors
.
white
,
fontFamily
:
R
.
fonts
.
InterMedium
,
fontSize
:
R
.
fontsize
.
fontsSizeTitle
,
},
fontFamily
:
R
.
fonts
.
fontMedium
,
weekDaysContainer
:
{
height
:
'100%'
,
flexDirection
:
'row'
,
},
paddingBottom
:
5
,
marginBottom
:
5
,
// Tiêu đề các ngày trong tuần
},
weekDaysContainer
:
{
weekDayCell
:
{
flexDirection
:
'row'
,
width
:
CELL_WIDTH
,
paddingBottom
:
5
,
alignItems
:
'center'
,
marginBottom
:
5
,
},
},
weekDayText
:
{
weekDayCell
:
{
fontFamily
:
R
.
fonts
.
InterRegular
,
width
:
CELL_WIDTH
,
fontSize
:
R
.
fontsize
.
fontsSize10
,
alignItems
:
'center'
,
fontWeight
:
'400'
,
},
color
:
R
.
colors
.
black
,
weekDayText
:
{
},
fontFamily
:
R
.
fonts
.
fontMedium
,
calendarGrid
:
{
fontSize
:
R
.
fontsize
.
fontSizeLabel
,
},
fontWeight
:
'600'
,
weekRow
:
{
color
:
R
.
colors
.
black
,
flexDirection
:
'row'
,
},
},
dayCell
:
{
// Lưới lịch
width
:
CELL_WIDTH
,
calendarGrid
:
{},
minHeight
:
CELL_HEIGHT
,
weekRow
:
{
borderWidth
:
1
,
flexDirection
:
'row'
,
borderColor
:
R
.
colors
.
grey_200
,
},
padding
:
4
,
alignItems
:
'center'
,
// Ô ngày trong lịch
},
dayCell
:
{
selectedDayCell
:
{
width
:
CELL_WIDTH
,
borderColor
:
R
.
colors
.
blue500
,
minHeight
:
CELL_HEIGHT
,
borderWidth
:
1
,
borderWidth
:
1
,
},
borderColor
:
R
.
colors
.
grayBorderInputTextHeader
,
dayText
:
{
padding
:
6
,
fontSize
:
R
.
fontsize
.
fontsSize12
,
alignItems
:
'center'
,
fontWeight
:
'500'
,
},
fontFamily
:
R
.
fonts
.
InterMedium
,
// Ô ngày được chọn
color
:
R
.
colors
.
black
,
selectedDayCell
:
{
marginBottom
:
2
,
borderColor
:
R
.
colors
.
blue
,
},
borderWidth
:
1
,
dayTextInactive
:
{
},
color
:
R
.
colors
.
grey_100
,
// Text số ngày
opacity
:
1
,
dayText
:
{
},
fontSize
:
R
.
fontsize
.
fontSizeLabel
,
selectedDayText
:
{
fontWeight
:
'400'
,
color
:
R
.
colors
.
black
,
fontFamily
:
R
.
fonts
.
fontRegular
,
fontWeight
:
'bold'
,
color
:
R
.
colors
.
black
,
fontFamily
:
R
.
fonts
.
InterSemiBold
,
marginBottom
:
2
,
},
},
todayText
:
{
// Text ngày không thuộc tháng hiện tại
color
:
R
.
colors
.
white
,
dayTextInactive
:
{
fontWeight
:
'bold'
,
color
:
R
.
colors
.
black
,
fontFamily
:
R
.
fonts
.
InterSemiBold
,
opacity
:
1
,
backgroundColor
:
R
.
colors
.
blue500
,
},
borderRadius
:
10
,
// Text ngày được chọn
paddingHorizontal
:
5
,
selectedDayText
:
{
},
color
:
R
.
colors
.
black
,
fontWeight
:
'500'
,
eventsContainer
:
{
fontFamily
:
R
.
fonts
.
fontSemiBold
,
width
:
'100%'
,
},
flex
:
1
,
// Text ngày hôm nay
},
todayText
:
{
eventBar
:
{
color
:
R
.
colors
.
white
,
paddingVertical
:
2
,
fontWeight
:
'bold'
,
paddingHorizontal
:
5
,
fontFamily
:
R
.
fonts
.
fontSemiBold
,
borderRadius
:
5
,
backgroundColor
:
R
.
colors
.
blue
,
marginBottom
:
2
,
borderRadius
:
15
,
},
paddingHorizontal
:
6
,
eventBarText
:
{
paddingVertical
:
4
,
fontSize
:
R
.
fontsize
.
fontsSize10
,
},
color
:
R
.
colors
.
white
,
fontWeight
:
'500'
,
// Sự kiện trong ô ngày
fontFamily
:
R
.
fonts
.
InterRegular
eventsContainer
:
{
},
width
:
'100%'
,
moreEventsText
:
{
flex
:
1
,
fontSize
:
R
.
fontsize
.
fontsSize10
,
},
color
:
R
.
colors
.
grey_100
,
// Thanh sự kiện nhỏ trong ô ngày
textAlign
:
'center'
,
eventBar
:
{
},
paddingVertical
:
2
,
paddingHorizontal
:
5
,
modalBackdrop
:
{
borderRadius
:
10
,
flex
:
1
,
marginBottom
:
2
,
backgroundColor
:
R
.
colors
.
grey_200
,
backgroundColor
:
R
.
colors
.
blue
,
justifyContent
:
'flex-end'
,
},
},
eventBarText
:
{
bottomSheet
:
{
fontSize
:
R
.
fontsize
.
fontSizeLabel
,
height
:
BOTTOM_SHEET_HEIGHT
,
color
:
R
.
colors
.
white
,
backgroundColor
:
R
.
colors
.
white
,
fontWeight
:
'400'
,
borderTopLeftRadius
:
20
,
fontFamily
:
R
.
fonts
.
fontRegular
,
borderTopRightRadius
:
20
,
},
// Text hiển thị số sự kiện còn lại
},
moreEventsText
:
{
bottomSheetContent
:
{
fontSize
:
R
.
fontsize
.
fontSizeLabel
,
paddingHorizontal
:
15
,
color
:
R
.
colors
.
gray
,
},
fontWeight
:
'400'
,
dragHandle
:
{
fontFamily
:
R
.
fonts
.
fontRegular
,
width
:
40
,
textAlign
:
'center'
,
height
:
4
,
},
backgroundColor
:
R
.
colors
.
grey_200
,
borderRadius
:
2
,
// Modal bottom sheet
alignSelf
:
'center'
,
modalBackdrop
:
{
marginTop
:
10
,
flex
:
1
,
marginBottom
:
15
,
backgroundColor
:
R
.
colors
.
grayBorderInputTextHeader
,
},
justifyContent
:
'flex-end'
,
bottomSheetHeader
:
{
},
flexDirection
:
'row'
,
bottomSheet
:
{
alignItems
:
'center'
,
height
:
BOTTOM_SHEET_HEIGHT
,
justifyContent
:
'space-between'
,
backgroundColor
:
R
.
colors
.
white
,
marginBottom
:
20
,
borderTopLeftRadius
:
20
,
},
borderTopRightRadius
:
20
,
bottomSheetTitle
:
{
},
fontSize
:
R
.
fontsize
.
fontSizeHeader1
,
fontFamily
:
R
.
fonts
.
InterMedium
,
// Nội dung bottom sheet
color
:
R
.
colors
.
black
,
bottomSheetContent
:
{
flex
:
1
,
height
:
BOTTOM_SHEET_HEIGHT
,
},
},
closeButton
:
{
// Thanh kéo
width
:
30
,
dragHandle
:
{
height
:
30
,
width
:
40
,
borderRadius
:
15
,
height
:
4
,
backgroundColor
:
R
.
colors
.
grey_200
,
backgroundColor
:
R
.
colors
.
gray
,
alignItems
:
'center'
,
borderRadius
:
5
,
justifyContent
:
'center'
,
alignSelf
:
'center'
,
},
marginTop
:
10
,
closeButtonText
:
{
marginBottom
:
15
,
fontSize
:
R
.
fontsize
.
fontsSize12
,
},
color
:
R
.
colors
.
grey_800
,
// Header của bottom sheet
fontFamily
:
R
.
fonts
.
InterRegular
,
bottomSheetHeader
:
{
},
flexDirection
:
'row'
,
alignItems
:
'center'
,
noEventsContainer
:
{
justifyContent
:
'space-between'
,
flex
:
1
,
paddingHorizontal
:
15
,
alignItems
:
'center'
,
},
justifyContent
:
'center'
,
bottomSheetTitle
:
{
paddingVertical
:
40
,
fontSize
:
R
.
fontsize
.
fontSizeContent
,
},
fontFamily
:
R
.
fonts
.
fontMedium
,
noEventsText
:
{
color
:
R
.
colors
.
black
,
fontSize
:
R
.
fontsize
.
fontsSize12
,
fontWeight
:
'600'
,
fontFamily
:
R
.
fonts
.
InterRegular
,
flex
:
1
,
color
:
R
.
colors
.
grey_800
,
},
fontWeight
:
'400'
// Nút đóng bottom sheet
},
closeButton
:
{
eventCard
:
{
width
:
30
,
flexDirection
:
'row'
,
height
:
30
,
backgroundColor
:
R
.
colors
.
white
,
borderRadius
:
15
,
borderRadius
:
12
,
backgroundColor
:
R
.
colors
.
gray
,
padding
:
15
,
alignItems
:
'center'
,
marginBottom
:
12
,
justifyContent
:
'center'
,
borderLeftWidth
:
4
,
},
borderLeftColor
:
R
.
colors
.
blue500
,
closeButtonText
:
{
shadowColor
:
R
.
colors
.
black
,
fontSize
:
R
.
fontsize
.
fontSizeContent
,
shadowOffset
:
{
color
:
R
.
colors
.
black
,
width
:
0
,
fontFamily
:
R
.
fonts
.
fontRegular
,
height
:
2
,
fontWeight
:
'400'
,
},
},
shadowOpacity
:
1
,
shadowRadius
:
1
,
// Danh sách sự kiện trong bottom sheet
elevation
:
2
,
// ScrollView chứa danh sách sự kiện
},
eventsScrollView
:
{
eventTimeContainer
:
{
paddingTop
:
10
,
minWidth
:
80
,
},
alignItems
:
'flex-start'
,
// Container cho từng sự kiện
justifyContent
:
'flex-start'
,
containerBottomSheet
:
{
marginRight
:
15
,
flex
:
1
,
},
marginBottom
:
10
,
eventTime
:
{
},
fontSize
:
R
.
fontsize
.
fontsSize12
,
// Trạng thái không có sự kiện
fontFamily
:
R
.
fonts
.
InterMedium
,
noEventsContainer
:
{
color
:
R
.
colors
.
blue500
,
flex
:
1
,
fontWeight
:
'600'
,
alignItems
:
'center'
,
},
justifyContent
:
'center'
,
eventContent
:
{
paddingVertical
:
40
,
flex
:
1
,
},
},
noEventsText
:
{
eventTitle
:
{
fontSize
:
R
.
fontsize
.
fontSizeContent
,
fontSize
:
R
.
fontsize
.
fontsSize12
,
fontFamily
:
R
.
fonts
.
fontRegular
,
fontFamily
:
R
.
fonts
.
InterMedium
,
color
:
R
.
colors
.
gray
,
color
:
R
.
colors
.
black
,
fontWeight
:
'400'
,
fontWeight
:
'600'
,
},
marginBottom
:
4
,
},
// Card sự kiện chi tiết
eventDescription
:
{
eventCard
:
{
fontSize
:
R
.
fontsize
.
fontsSize12
,
flexDirection
:
'row'
,
fontFamily
:
R
.
fonts
.
InterRegular
,
backgroundColor
:
R
.
colors
.
white
,
color
:
R
.
colors
.
grey_800
,
borderRadius
:
12
,
},
padding
:
15
,
marginBottom
:
10
,
marginHorizontal
:
15
,
borderLeftWidth
:
4
,
borderLeftColor
:
R
.
colors
.
blue
,
shadowColor
:
R
.
colors
.
black
,
shadowOffset
:
{
width
:
0
,
height
:
2
,
},
shadowOpacity
:
1
,
shadowRadius
:
1
,
elevation
:
2
,
},
// Container thời gian sự kiện
eventTimeContainer
:
{
minWidth
:
80
,
alignItems
:
'flex-start'
,
justifyContent
:
'flex-start'
,
marginRight
:
15
,
},
eventTime
:
{
fontSize
:
R
.
fontsize
.
fontSizeContent
,
fontFamily
:
R
.
fonts
.
fontMedium
,
color
:
R
.
colors
.
blue
,
fontWeight
:
'600'
,
},
// Container nội dung sự kiện
eventContent
:
{
flex
:
1
,
},
eventTitle
:
{
fontSize
:
R
.
fontsize
.
fontSizeContent
,
fontFamily
:
R
.
fonts
.
fontMedium
,
color
:
R
.
colors
.
black
,
fontWeight
:
'600'
,
marginBottom
:
4
,
},
eventDescription
:
{
fontSize
:
R
.
fontsize
.
fontSizeContent
,
fontFamily
:
R
.
fonts
.
fontRegular
,
color
:
R
.
colors
.
gray2
,
fontWeight
:
'400'
,
},
});
});
export
{
styles
,
CELL_WIDTH
,
BOTTOM_SHEET_HEIGHT
};
export
{
styles
,
CELL_WIDTH
,
BOTTOM_SHEET_HEIGHT
};
src/screens/class_schedule/view.js
View file @
10a23b76
...
@@ -3,18 +3,19 @@ import {
...
@@ -3,18 +3,19 @@ import {
Text
,
Text
,
View
,
View
,
TouchableOpacity
,
TouchableOpacity
,
StyleSheet
,
ScrollView
,
ScrollView
,
Dimensions
,
Modal
,
Modal
,
Animated
,
Animated
,
SafeAreaView
,
SafeAreaView
,
LogBox
,
}
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'
;
LogBox
.
ignoreAllLogs
(
true
);
const
ClassScheduleView
=
({
const
ClassScheduleView
=
({
currentDate
,
currentDate
,
selectedDate
,
selectedDate
,
...
@@ -150,7 +151,7 @@ const ClassScheduleView = ({
...
@@ -150,7 +151,7 @@ const ClassScheduleView = ({
};
};
const
renderBottomSheetContent
=
()
=>
{
const
renderBottomSheetContent
=
()
=>
{
if
(
!
selectedDate
)
return
null
;
if
(
!
selectedDate
||
typeof
selectedDate
!==
'string'
)
return
null
;
const
selectedDateObj
=
parseLocalDate
(
selectedDate
);
const
selectedDateObj
=
parseLocalDate
(
selectedDate
);
const
selectedEvents
=
getSelectedEvents
();
const
selectedEvents
=
getSelectedEvents
();
...
...
src/screens/home/view.js
View file @
10a23b76
...
@@ -20,7 +20,6 @@ import ItemGrid from './item';
...
@@ -20,7 +20,6 @@ import ItemGrid from './item';
import
styles
from
'./style'
;
import
styles
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'
;
import
TextSearchView
from
'../../components/Input/TextSearch/TextSearch'
;
const
HomeView
=
props
=>
{
const
HomeView
=
props
=>
{
const
{
const
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment