Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
AppUms_Lecturer
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_Lecturer
Commits
8a6ebbb7
Commit
8a6ebbb7
authored
Sep 17, 2025
by
tungnq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TODO: Bổ sung hàm check render
parent
1f57d4df
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
38 additions
and
23 deletions
+38
-23
Button.js
src/components/Button.js
+0
-2
view.js
src/components/TabView/view.js
+16
-14
Functions.js
src/config/Functions.js
+21
-7
view.js
src/screens/list_work/view.js
+1
-0
No files found.
src/components/Button.js
View file @
8a6ebbb7
...
...
@@ -7,8 +7,6 @@ import {
Text
,
Image
,
}
from
'react-native'
;
import
R
from
'../assets/R'
;
const
Button
=
props
=>
{
const
{
title
,
...
...
src/components/TabView/view.js
View file @
8a6ebbb7
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'react'
;
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'react'
;
import
{
View
,
Text
,
...
...
@@ -10,7 +10,7 @@ import {
import
Icon
from
'react-native-vector-icons/MaterialIcons'
;
import
R
from
'../../assets/R'
;
const
{
width
:
screenWidth
}
=
Dimensions
.
get
(
'window'
);
const
{
width
:
screenWidth
}
=
Dimensions
.
get
(
'window'
);
/**
* Component TabView có thể tái sử dụng
...
...
@@ -65,7 +65,9 @@ const TabViewComponent = ({
if
(
defaultActiveKey
)
{
const
keyExists
=
data
.
some
(
item
=>
item
.
key
===
defaultActiveKey
);
if
(
!
keyExists
)
{
console
.
warn
(
`TabView: defaultActiveKey "
${
defaultActiveKey
}
" không tìm thấy trong data. Sử dụng tab đầu tiên.`
);
console
.
warn
(
`TabView: defaultActiveKey "
${
defaultActiveKey
}
" không tìm thấy trong data. Sử dụng tab đầu tiên.`
,
);
initialKey
=
data
[
0
].
key
;
}
}
else
{
...
...
@@ -84,7 +86,9 @@ const TabViewComponent = ({
const
uniqueKeys
=
[...
new
Set
(
keys
)];
if
(
keys
.
length
!==
uniqueKeys
.
length
)
{
console
.
warn
(
'TabView: Phát hiện key trùng lặp trong mảng data. Có thể gây lỗi không mong muốn.'
);
console
.
warn
(
'TabView: Phát hiện key trùng lặp trong mảng data. Có thể gây lỗi không mong muốn.'
,
);
}
},
[
data
]);
...
...
@@ -107,13 +111,13 @@ const TabViewComponent = ({
animated
:
true
,
});
},
()
=>
{}
// Callback khi đo thất bại
()
=>
{}
,
// Callback khi đo thất bại
);
}
},
[
activeKey
,
scrollable
]);
// Xử lý khi người dùng nhấn vào tab
const
handleTabPress
=
(
item
)
=>
{
const
handleTabPress
=
item
=>
{
// Không làm gì nếu tab bị disabled
if
(
item
.
disabled
)
return
;
...
...
@@ -143,7 +147,7 @@ const TabViewComponent = ({
return
(
<
TouchableOpacity
key
=
{
item
.
key
}
ref
=
{
ref
=>
tabRefs
.
current
[
item
.
key
]
=
ref
}
// Lưu ref để dùng cho auto scroll
ref
=
{
ref
=>
(
tabRefs
.
current
[
item
.
key
]
=
ref
)
}
// Lưu ref để dùng cho auto scroll
style
=
{[
styles
.
tab
,
// Style cơ bản
tabStyle
,
// Style tùy chỉnh từ props
...
...
@@ -153,8 +157,7 @@ const TabViewComponent = ({
]}
onPress
=
{()
=>
handleTabPress
(
item
)}
disabled
=
{
isDisabled
}
activeOpacity
=
{
0.7
}
>
activeOpacity
=
{
0.7
}
>
<
View
style
=
{
styles
.
tabContent
}
>
{
/* Hiển thị icon nếu có */
}
{
item
.
icon
&&
(
...
...
@@ -169,14 +172,13 @@ const TabViewComponent = ({
<
Text
style
=
{[
styles
.
tabText
,
// Style text cơ bản
{
color
:
isActive
?
activeColor
:
inactiveColor
},
// Dùng màu từ props
{
color
:
isActive
?
activeColor
:
inactiveColor
},
// Dùng màu từ props
textStyle
,
// Style text tùy chỉnh
isActive
&&
styles
.
activeTabText
,
// Style text khi active
isActive
&&
activeTextStyle
,
// Style text active tùy chỉnh
isDisabled
&&
styles
.
disabledTabText
,
// Style text khi disabled
]}
numberOfLines
=
{
1
}
>
numberOfLines
=
{
1
}
>
{
/* Ưu tiên label, sau đó title, name, cuối cùng là 'Tab' */
}
{
item
.
label
||
item
.
title
||
item
.
name
||
'Tab'
}
<
/Text
>
...
...
@@ -186,7 +188,7 @@ const TabViewComponent = ({
<
View
style
=
{[
styles
.
activeIndicator
,
{
backgroundColor
:
activeIndicatorColor
||
activeColor
}
// Dùng màu từ props
{
backgroundColor
:
activeIndicatorColor
||
activeColor
},
// Dùng màu từ props
]}
/
>
)}
...
...
@@ -306,4 +308,4 @@ const styles = StyleSheet.create({
});
// Export component để sử dụng ở nơi khác
export
default
TabViewComponent
;
export
default
React
.
memo
(
TabViewComponent
)
;
src/config/Functions.js
View file @
8a6ebbb7
import
React
from
'react'
;
import
React
,
{
useRef
,
useEffect
}
from
'react'
;
import
{
Dimensions
,
Platform
,
...
...
@@ -234,9 +234,8 @@ export const removeItemFromArr2 = (items, index) => {
return
fill
;
};
export
const
isValidEmail
=
(
email
)
=>
email
.
length
>
0
&&
/
(
.+
)
@
(
.+
){2,}\.(
.+
){2,}
/gmi
.
test
(
email
);
export
const
isValidEmail
=
email
=>
email
.
length
>
0
&&
/
(
.+
)
@
(
.+
){2,}\.(
.+
){2,}
/gim
.
test
(
email
);
export
const
removeItemFromArr
=
(
items
,
index
)
=>
{
items
.
splice
(
index
,
1
);
...
...
@@ -607,7 +606,7 @@ export const getMimeType = fileExt => {
};
//Calendar
export
const
parseMinutes
=
(
timeStr
)
=>
{
export
const
parseMinutes
=
timeStr
=>
{
if
(
!
timeStr
||
typeof
timeStr
!==
'string'
)
return
0
;
const
parts
=
timeStr
.
split
(
':'
);
if
(
parts
.
length
!==
2
)
return
0
;
...
...
@@ -616,7 +615,7 @@ export const parseMinutes = (timeStr) => {
return
h
*
60
+
m
;
};
export
const
formatDateToString
=
(
date
)
=>
{
export
const
formatDateToString
=
date
=>
{
const
y
=
date
.
getFullYear
();
const
m
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
);
const
d
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
);
...
...
@@ -652,7 +651,7 @@ export const layoutDayEvents = (events, hourHeight = 80) => {
let
cur
=
null
;
for
(
const
ev
of
mapped
)
{
if
(
!
cur
||
ev
.
start
>=
cur
.
maxEnd
)
{
cur
=
{
id
:
groups
.
length
,
items
:
[
ev
],
maxEnd
:
ev
.
end
};
cur
=
{
id
:
groups
.
length
,
items
:
[
ev
],
maxEnd
:
ev
.
end
};
groups
.
push
(
cur
);
}
else
{
cur
.
items
.
push
(
ev
);
...
...
@@ -709,4 +708,19 @@ export const layoutDayEvents = (events, hourHeight = 80) => {
// Trả về theo thứ tự ban đầu để render ổn định
return
out
.
sort
((
a
,
b
)
=>
a
.
_idx
-
b
.
_idx
);
/**
* Hook đếm số lần render của một component
*/
};
export
const
useRenderCount
=
(
name
=
'Component'
)
=>
{
const
renderCount
=
useRef
(
0
);
renderCount
.
current
+=
1
;
useEffect
(()
=>
{
console
.
log
(
`
${
name
}
đã render
${
renderCount
.
current
}
lần`
);
});
return
renderCount
.
current
;
};
src/screens/list_work/view.js
View file @
8a6ebbb7
...
...
@@ -176,6 +176,7 @@ const ListWorkView = props => {
const
renderBody
=
()
=>
{
return
(
<
View
style
=
{
styles
.
body
}
>
{
renderTabView
()}
{
renderCard
()}
<
View
style
=
{
styles
.
listContainer
}
>
...
...
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