eletrotupi / tcc/ frontend/components/ui/ScreenLayout.tsxc8d420616655908de46d541595ce6c2baba960fa
3.7 KB | 136 lines Raw
1
import {
2
  View,
3
  ScrollView,
4
  StyleSheet,
5
  Image,
6
  Pressable,
7
  StatusBar,
8
} from "react-native";
9

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

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

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

42
  return (
43
    <View style={[styles.container, { backgroundColor }]}>
44
      <StatusBar barStyle="dark-content" />
45
      <SafeAreaView
46
        style={[styles.safeAreaView, { backgroundColor }]}
47
        edges={["top", "left", "right"]}
48
      >
49
        <View style={[styles.header, { backgroundColor: surfaceColor, borderBottomColor: dividerColor }]}>
50
          <View style={styles.headerLeft}>
51
            {userAvatar ? (
52
              <Image source={{ uri: userAvatar }} style={[styles.avatar, { backgroundColor: accentBlue }]} />
53
            ) : (
54
              <View style={[styles.avatar, { backgroundColor: accentBlue }]} />
55
            )}
56
            <View>
57
              <Text style={[styles.userName, { color: textColor }]}>Olá, {userName}</Text>
58
            </View>
59
          </View>
60

61
          <Pressable
62
            style={styles.notificationButton}
63
            onPress={onNotificationPress ?? (() => router.push("/notifications"))}
64
            hitSlop={8}
65
          >
66
            <IconSymbol size={24} name="notifications" color={textColor} />
67
            {showNotificationBadge && (
68
              <View style={[styles.notificationBadge, { backgroundColor: tintColor }]} />
69
            )}
70
          </Pressable>
71
        </View>
72

73
        <ScrollView
74
          scrollEnabled={scrollEnabled}
75
          showsVerticalScrollIndicator={false}
76
          contentContainerStyle={scrollEnabled ? undefined : { flex: 1 }}
77
          scrollEventThrottle={16}
78
        >
79
          <View style={styles.scrollContent}>{children}</View>
80
        </ScrollView>
81
      </SafeAreaView>
82
    </View>
83
  );
84
};
85

86
const styles = StyleSheet.create({
87
  container: {
88
    flex: 1,
89
  },
90
  safeAreaView: {
91
    flex: 1,
92
  },
93
  header: {
94
    paddingHorizontal: Spacing.containerPadding,
95
    paddingVertical: 12,
96
    borderBottomWidth: 1,
97
    flexDirection: "row",
98
    justifyContent: "space-between",
99
    alignItems: "center",
100
  },
101
  headerLeft: {
102
    flexDirection: "row",
103
    alignItems: "center",
104
    gap: Spacing.inlineGapSm,
105
  },
106
  avatar: {
107
    width: 40,
108
    height: 40,
109
    borderRadius: 20,
110
  },
111
  userName: {
112
    fontSize: Typography.bodyLg.fontSize,
113
    fontWeight: "600",
114
  },
115
  notificationButton: {
116
    width: 40,
117
    height: 40,
118
    borderRadius: BorderRadius.md,
119
    justifyContent: "center",
120
    alignItems: "center",
121
  },
122
  notificationBadge: {
123
    position: "absolute",
124
    top: 4,
125
    right: 4,
126
    width: 8,
127
    height: 8,
128
    borderRadius: 4,
129
  },
130
  scrollContent: {
131
    paddingHorizontal: Spacing.containerPadding,
132
    paddingVertical: Spacing.sectionGap,
133
  },
134
});
135

136
export default ScreenLayout;