Skip to content

Commit fbd554c

Browse files
authored
Merge branch 'main' into settings_implementation
2 parents a280a47 + 1303710 commit fbd554c

3 files changed

Lines changed: 177 additions & 1 deletion

File tree

Auth/InsufficientPermissions.tsx

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import MaterialIcons from '@react-native-vector-icons/material-icons';
2+
import React, { useState } from 'react';
3+
import { Button, Modal, StyleSheet, Text, View } from 'react-native';
4+
import { useTheme } from '../Themes/ThemeContextProvider';
5+
6+
type InsufficientPermissionsProps = {
7+
featureName: string;
8+
onRetry: () => void;
9+
missingPermissions: string[];
10+
requiredPermissions: string[];
11+
};
12+
13+
function InsufficientPermissions({
14+
featureName,
15+
onRetry,
16+
missingPermissions,
17+
requiredPermissions,
18+
}: InsufficientPermissionsProps) {
19+
const { currentTheme } = useTheme();
20+
const [detailsVisible, setDetailsVisible] = useState(false);
21+
const satisfiedPermissions = requiredPermissions.filter(
22+
(item) => !missingPermissions.includes(item),
23+
);
24+
25+
type PermissionDetailsListProps = {
26+
permissions: string[];
27+
hasPermission: boolean;
28+
};
29+
const PermissionDetailsList = ({ permissions, hasPermission }: PermissionDetailsListProps) => {
30+
return permissions.map((permission, index) => (
31+
<View key={index} style={index === 0 ? styles.permissionItemFirst : styles.permissionItem}>
32+
{hasPermission ? (
33+
<MaterialIcons
34+
name={'check-circle-outline'}
35+
size={30}
36+
color={currentTheme.success}
37+
style={styles.icon}
38+
/>
39+
) : (
40+
<MaterialIcons
41+
name={'error-outline'}
42+
size={30}
43+
color={currentTheme.error}
44+
style={styles.icon}
45+
/>
46+
)}
47+
<Text style={styles.permissionItemText}>{permission}</Text>
48+
</View>
49+
));
50+
};
51+
52+
const PermissionDetailsDialog = () => {
53+
return (
54+
<Modal animationType="fade" transparent={true}>
55+
<View style={styles.viewContainer}>
56+
<View style={styles.modalView}>
57+
<Text style={styles.modalText}>Required Permissions</Text>
58+
<PermissionDetailsList permissions={missingPermissions} hasPermission={false} />
59+
<PermissionDetailsList permissions={satisfiedPermissions} hasPermission={true} />
60+
<View style={styles.modalButton}>
61+
<Button onPress={() => setDetailsVisible(false)} title="Close" />
62+
</View>
63+
</View>
64+
</View>
65+
</Modal>
66+
);
67+
};
68+
69+
return (
70+
<View style={styles.viewContainer}>
71+
{detailsVisible && <PermissionDetailsDialog></PermissionDetailsDialog>}
72+
<MaterialIcons
73+
name={'error-outline'}
74+
size={100}
75+
color={currentTheme.error}
76+
style={styles.icon}
77+
/>
78+
<Text style={styles.mainText}>{featureName} permissions required</Text>
79+
<View style={styles.buttonTopRow}>
80+
<View style={styles.button}>
81+
<Button onPress={() => {}} title="Go to #it-helpdesk" />
82+
</View>
83+
<View style={styles.button}>
84+
<Button onPress={onRetry} color={currentTheme.primary} title="Retry" />
85+
</View>
86+
</View>
87+
<View style={styles.buttonBottomRow}>
88+
<Button onPress={() => setDetailsVisible(true)} title="View details" />
89+
</View>
90+
</View>
91+
);
92+
}
93+
94+
const styles = StyleSheet.create({
95+
button: {
96+
marginHorizontal: 5,
97+
},
98+
buttonBottomRow: {
99+
marginTop: 10,
100+
},
101+
buttonTopRow: {
102+
display: 'flex',
103+
flexDirection: 'row',
104+
flexWrap: 'wrap',
105+
},
106+
icon: {
107+
margin: 10,
108+
},
109+
mainText: {
110+
fontSize: 30,
111+
marginBottom: 20,
112+
textAlign: 'center',
113+
},
114+
modalButton: {
115+
alignItems: 'flex-end',
116+
marginVertical: 20,
117+
},
118+
modalText: {
119+
fontSize: 20,
120+
marginVertical: 20,
121+
},
122+
modalView: {
123+
backgroundColor: 'white',
124+
borderRadius: 20,
125+
elevation: 5,
126+
margin: 20,
127+
padding: 20,
128+
shadowOffset: {
129+
width: 0,
130+
height: 2,
131+
},
132+
shadowOpacity: 0.25,
133+
shadowRadius: 4,
134+
width: '75%',
135+
},
136+
permissionItem: {
137+
alignItems: 'center',
138+
borderBlockColor: 'gray',
139+
borderBottomWidth: 1,
140+
borderTopWidth: 0,
141+
flexDirection: 'row',
142+
justifyContent: 'flex-start',
143+
},
144+
permissionItemFirst: {
145+
alignItems: 'center',
146+
borderBlockColor: 'gray',
147+
borderBottomWidth: 1,
148+
borderTopWidth: 1,
149+
flexDirection: 'row',
150+
justifyContent: 'flex-start',
151+
},
152+
permissionItemText: {
153+
fontSize: 15,
154+
},
155+
viewContainer: {
156+
alignItems: 'center',
157+
flex: 1,
158+
justifyContent: 'center',
159+
margin: 10,
160+
},
161+
});
162+
163+
export default InsufficientPermissions;

Navigation/RootStack.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import { AuthenticationState } from '../Auth/Authentication';
77
import AuthenticationScreen from '../Auth/AuthenticationScreen';
88
import LoadingScreen from '../Components/LoadingScreen';
99
import NfcEnabledScreen from '../Nfc/NfcEnabledScreen';
10+
import { useTheme } from '../Themes/ThemeContextProvider';
1011
import NavBar from './NavBar';
1112

1213
const Stack = createNativeStackNavigator();
1314
type NfcState = 'enabled' | 'disabled' | 'unsupported';
1415

1516
function RootStack() {
17+
const { currentTheme } = useTheme();
1618
const auth = useContext(AuthContext);
1719
const [nfcEnabled, setNfcEnabled] = useState<NfcState>('disabled');
1820

@@ -43,7 +45,15 @@ function RootStack() {
4345
return (
4446
<Stack.Navigator
4547
screenOptions={{
46-
headerShown: false,
48+
headerShown: true,
49+
title: 'MyRoboJackets',
50+
headerStyle: {
51+
backgroundColor: currentTheme.primary as string,
52+
},
53+
headerTitleStyle: {
54+
fontWeight: 'bold',
55+
fontSize: 24,
56+
},
4757
}}
4858
>
4959
{nfcEnabled !== 'enabled' ? (

Themes/Themes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type Theme = {
3636
surfaceContainer: ColorValue;
3737
surfaceContainerHigh: ColorValue;
3838
surfaceContainerHighest: ColorValue;
39+
success: ColorValue;
3940
};
4041

4142
export const LightMode: Theme = {
@@ -74,6 +75,7 @@ export const LightMode: Theme = {
7475
surfaceContainer: Colors.surfaceContainerLight,
7576
surfaceContainerHigh: Colors.surfaceContainerHighLight,
7677
surfaceContainerHighest: Colors.surfaceContainerHighestLight,
78+
success: Colors.success,
7779
};
7880

7981
export const DarkMode: Theme = {
@@ -112,4 +114,5 @@ export const DarkMode: Theme = {
112114
surfaceContainer: Colors.surfaceContainerDark,
113115
surfaceContainerHigh: Colors.surfaceContainerHighDark,
114116
surfaceContainerHighest: Colors.surfaceContainerHighestDark,
117+
success: Colors.success,
115118
};

0 commit comments

Comments
 (0)