eletrotupi / tcc/ frontend/components/ui/ScreenLayout.tsx88238be34dd62f1819ca47962a700d505097311f
4.0 KB | 151 lines Raw
1
import React from "react";
2

3
import {
4
  View,
5
  ScrollView,
6
  StyleSheet,
7
  Image,
8
  Pressable,
9
  StatusBar,
10
} from "react-native";
11

12
import { SafeAreaView } from "react-native-safe-area-context";
13
import { useRouter } from "expo-router";
14
import { IconSymbol } from "@/components/ui/icon-symbol";
15
import { useThemeColor } from "@/hooks/use-theme-color";
16
import { Typography, Spacing, BorderRadius } from "@/constants/theme";
17
import { Text } from "@/components/ui/Text";
18

19
interface ScreenLayoutProps {
20
  children: React.ReactNode;
21
  userName?: string;
22
  userAvatar?: string;
23
  onNotificationPress?: () => void;
24
  showNotificationBadge?: boolean;
25
  scrollEnabled?: boolean;
26
}
27

28
export const ScreenLayout: React.FC<ScreenLayoutProps> = ({
29
  children,
30
  userName = "Usuário",
31
  userAvatar,
32
  onNotificationPress,
33
  showNotificationBadge = false,
34
  scrollEnabled = true,
35
}) => {
36
  const router = useRouter();
37
  const textColor = useThemeColor({}, "text");
38
  const backgroundColor = useThemeColor({}, "background");
39
  const surfaceColor = useThemeColor({}, "surface");
40
  const dividerColor = useThemeColor({}, "divider");
41
  const accentBlue = useThemeColor({}, "accentBlue");
42
  const tintColor = useThemeColor({}, "tint");
43

44
  const styles = StyleSheet.create({
45
    container: {
46
      flex: 1,
47
      backgroundColor: backgroundColor,
48
    },
49
    safeAreaView: {
50
      flex: 1,
51
      backgroundColor: backgroundColor,
52
    },
53
    header: {
54
      paddingHorizontal: Spacing.containerPadding,
55
      paddingVertical: 12,
56
      backgroundColor: surfaceColor,
57
      borderBottomWidth: 1,
58
      borderBottomColor: dividerColor,
59
      flexDirection: "row",
60
      justifyContent: "space-between",
61
      alignItems: "center",
62
    },
63
    headerLeft: {
64
      flexDirection: "row",
65
      alignItems: "center",
66
      gap: Spacing.inlineGapSm,
67
    },
68
    avatar: {
69
      width: 40,
70
      height: 40,
71
      borderRadius: 20,
72
      backgroundColor: accentBlue,
73
    },
74
    userName: {
75
      fontSize: Typography.bodyLg.fontSize,
76
      fontWeight: "600",
77
      color: textColor,
78
    },
79
    notificationButton: {
80
      width: 40,
81
      height: 40,
82
      borderRadius: BorderRadius.md,
83
      justifyContent: "center",
84
      alignItems: "center",
85
      activeOpacity: 0.7,
86
    },
87
    notificationBadge: {
88
      position: "absolute",
89
      top: 4,
90
      right: 4,
91
      width: 8,
92
      height: 8,
93
      borderRadius: 4,
94
      backgroundColor: tintColor,
95
    },
96
    scrollContent: {
97
      paddingHorizontal: Spacing.containerPadding,
98
      paddingVertical: Spacing.sectionGap,
99
    },
100
  });
101

102
  return (
103
    <View style={styles.container}>
104
      <StatusBar barStyle="dark-content" />
105
      <SafeAreaView
106
        style={styles.safeAreaView}
107
        edges={["top", "left", "right"]}
108
      >
109
        <View style={styles.header}>
110
          <View style={styles.headerLeft}>
111
            {userAvatar ? (
112
              <Image source={{ uri: userAvatar }} style={styles.avatar} />
113
            ) : (
114
              <View style={styles.avatar} />
115
            )}
116
            <View>
117
              <Text style={styles.userName}>Olá, {userName}</Text>
118
            </View>
119
          </View>
120

121
          <Pressable
122
            style={styles.notificationButton}
123
            onPress={onNotificationPress ?? (() => router.push("/notifications"))}
124
            hitSlop={8}
125
          >
126
            <View
127
              style={{
128
                fontSize: 24,
129
                color: textColor,
130
              }}
131
            >
132
              <IconSymbol size={24} name="notifications" color={textColor} />
133
            </View>
134
            {showNotificationBadge && <View style={styles.notificationBadge} />}
135
          </Pressable>
136
        </View>
137

138
        <ScrollView
139
          scrollEnabled={scrollEnabled}
140
          showsVerticalScrollIndicator={false}
141
          contentContainerStyle={scrollEnabled ? undefined : { flex: 1 }}
142
          scrollEventThrottle={16}
143
        >
144
          <View style={styles.scrollContent}>{children}</View>
145
        </ScrollView>
146
      </SafeAreaView>
147
    </View>
148
  );
149
};
150

151
export default ScreenLayout;