classement tout les mois
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import { Portal } from "@gorhom/portal";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
@@ -52,8 +53,27 @@ const ProjectDropDown = ({
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [triggerLayout, setTriggerLayout] = useState(null);
|
||||
const [triggerWindowLayout, setTriggerWindowLayout] = useState(null);
|
||||
const triggerRef = useRef(null);
|
||||
const dropdownAnimation = useRef(new Animated.Value(0)).current;
|
||||
|
||||
const measureTriggerPosition = useCallback(() => {
|
||||
if (triggerRef.current?.measureInWindow) {
|
||||
try {
|
||||
triggerRef.current.measureInWindow((x, y, width, height) => {
|
||||
setTriggerWindowLayout({
|
||||
x: x ?? 0,
|
||||
y: y ?? 0,
|
||||
width: width ?? triggerLayout?.width ?? 0,
|
||||
height: height ?? triggerLayout?.height ?? 0,
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn("ProjectDropDown: measureInWindow failed", error);
|
||||
}
|
||||
}
|
||||
}, [triggerLayout?.height, triggerLayout?.width]);
|
||||
|
||||
const normalizedProjects = Array.isArray(projects) ? projects : [];
|
||||
const isDisabled = normalizedProjects.length === 0;
|
||||
|
||||
@@ -80,8 +100,11 @@ const ProjectDropDown = ({
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
if (!isOpen) {
|
||||
measureTriggerPosition();
|
||||
}
|
||||
setIsOpen((prev) => !prev);
|
||||
}, [isDisabled]);
|
||||
}, [isDisabled, isOpen, measureTriggerPosition]);
|
||||
|
||||
const closeDropdown = useCallback(() => setIsOpen(false), []);
|
||||
|
||||
@@ -121,6 +144,12 @@ const ProjectDropDown = ({
|
||||
}).start();
|
||||
}, [dropdownAnimation, isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
measureTriggerPosition();
|
||||
}
|
||||
}, [isOpen, measureTriggerPosition]);
|
||||
|
||||
const overlayTranslateY = useMemo(
|
||||
() =>
|
||||
dropdownAnimation.interpolate({
|
||||
@@ -158,15 +187,81 @@ const ProjectDropDown = ({
|
||||
[dropdownAnimation]
|
||||
);
|
||||
|
||||
const overlayPositionStyle = useMemo(() => {
|
||||
const widthCandidate =
|
||||
dropdownWidth ||
|
||||
triggerWindowLayout?.width ||
|
||||
triggerLayout?.width ||
|
||||
0;
|
||||
|
||||
const width = widthCandidate || 0;
|
||||
const windowWidth = Dimensions.get("window").width || 0;
|
||||
const leftBase = triggerWindowLayout?.x ?? 0;
|
||||
const left =
|
||||
width > 0 && windowWidth > 0
|
||||
? Math.min(Math.max(leftBase, 0), Math.max(0, windowWidth - width))
|
||||
: Math.max(leftBase, 0);
|
||||
|
||||
return {
|
||||
top: triggerWindowLayout?.y ?? 0,
|
||||
left,
|
||||
width: width || undefined,
|
||||
};
|
||||
}, [dropdownWidth, triggerLayout?.width, triggerWindowLayout]);
|
||||
|
||||
const dropdownContent = (
|
||||
<BlurView
|
||||
intensity={BUTTON_BLUR_INTENSITY}
|
||||
tint="dark"
|
||||
style={styles.dropdownOverlay}
|
||||
>
|
||||
<ProjectRow
|
||||
isTitle={true}
|
||||
isOpen={isOpen}
|
||||
project={currentProject}
|
||||
formatDate={formatDate}
|
||||
onSelect={toggleDropdown}
|
||||
/>
|
||||
|
||||
<View style={styles.dropdownOverlayContent}>
|
||||
<FlatList
|
||||
data={dropdownProjects}
|
||||
keyExtractor={(project, index) =>
|
||||
project?.id || project?.title || `project-${index}`
|
||||
}
|
||||
ItemSeparatorComponent={() => <View style={{ height: 10 }} />}
|
||||
renderItem={({ item: project }) => (
|
||||
<ProjectRow
|
||||
project={project}
|
||||
formatDate={formatDate}
|
||||
isSelected={currentProject?.id === project?.id}
|
||||
onSelect={handleSelect}
|
||||
onModify={handleModify}
|
||||
/>
|
||||
)}
|
||||
nestedScrollEnabled
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={styles.dropdownListContent}
|
||||
style={styles.dropdownList}
|
||||
/>
|
||||
<GradientButton
|
||||
containerStyle={styles.createButtonContainer}
|
||||
title="Commencer à créer"
|
||||
onPress={handleCreate}
|
||||
/>
|
||||
</View>
|
||||
</BlurView>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
{isOpen ? (
|
||||
<Pressable style={styles.backdrop} onPress={closeDropdown} />
|
||||
) : null}
|
||||
|
||||
<View
|
||||
ref={triggerRef}
|
||||
style={styles.triggerWrapper}
|
||||
onLayout={(event) => setTriggerLayout(event.nativeEvent.layout)}
|
||||
onLayout={(event) => {
|
||||
setTriggerLayout(event.nativeEvent.layout);
|
||||
measureTriggerPosition();
|
||||
}}
|
||||
>
|
||||
<Animated.View
|
||||
pointerEvents={isOpen ? "none" : "auto"}
|
||||
@@ -196,61 +291,29 @@ const ProjectDropDown = ({
|
||||
</BlurView>
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View
|
||||
pointerEvents={isOpen ? "auto" : "none"}
|
||||
style={[
|
||||
styles.dropdownOverlayContainer,
|
||||
{ width: dropdownWidth || "100%" },
|
||||
{
|
||||
opacity: dropdownAnimation,
|
||||
transform: [
|
||||
{ translateY: overlayTranslateY },
|
||||
{ scale: overlayScale },
|
||||
],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<BlurView
|
||||
intensity={BUTTON_BLUR_INTENSITY}
|
||||
tint="dark"
|
||||
style={styles.dropdownOverlay}
|
||||
>
|
||||
<ProjectRow
|
||||
isTitle={true}
|
||||
isOpen={isOpen}
|
||||
project={currentProject}
|
||||
formatDate={formatDate}
|
||||
onSelect={toggleDropdown}
|
||||
/>
|
||||
|
||||
<View style={styles.dropdownOverlayContent}>
|
||||
<FlatList
|
||||
data={dropdownProjects}
|
||||
keyExtractor={(project, index) =>
|
||||
project?.id || project?.title || `project-${index}`
|
||||
}
|
||||
ItemSeparatorComponent={() => <View style={{ height: 10 }} />}
|
||||
renderItem={({ item: project }) => (
|
||||
<ProjectRow
|
||||
project={project}
|
||||
formatDate={formatDate}
|
||||
isSelected={currentProject?.id === project?.id}
|
||||
onSelect={handleSelect}
|
||||
onModify={handleModify}
|
||||
/>
|
||||
)}
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={styles.dropdownListContent}
|
||||
style={styles.dropdownList}
|
||||
/>
|
||||
<GradientButton
|
||||
containerStyle={styles.createButtonContainer}
|
||||
title="Commencer à créer"
|
||||
onPress={handleCreate}
|
||||
/>
|
||||
{isOpen && triggerWindowLayout ? (
|
||||
<Portal>
|
||||
<View style={styles.portalContainer}>
|
||||
<Pressable style={styles.backdrop} onPress={closeDropdown} />
|
||||
<Animated.View
|
||||
pointerEvents="auto"
|
||||
style={[
|
||||
styles.dropdownOverlayContainer,
|
||||
overlayPositionStyle,
|
||||
{
|
||||
opacity: dropdownAnimation,
|
||||
transform: [
|
||||
{ translateY: overlayTranslateY },
|
||||
{ scale: overlayScale },
|
||||
],
|
||||
},
|
||||
]}
|
||||
>
|
||||
{dropdownContent}
|
||||
</Animated.View>
|
||||
</View>
|
||||
</BlurView>
|
||||
</Animated.View>
|
||||
</Portal>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -435,6 +498,11 @@ const styles = StyleSheet.create({
|
||||
chevronOpen: {
|
||||
transform: [{ rotate: "180deg" }],
|
||||
},
|
||||
portalContainer: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
zIndex: 999,
|
||||
elevation: 999,
|
||||
},
|
||||
backdrop: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
zIndex: 1,
|
||||
|
||||
Reference in New Issue
Block a user