Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 5 additions & 54 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,94 +1,48 @@
/**
* App.js
* The main entry point of the Audacity Sign Up app.
* - Initializes user authentication state from AsyncStorage
* - Displays a loading indicator until auth status is resolved
* - Sets up React Navigation stack with screens for Sign In, Home, Account, and volunteer flows
* - Sets up React Navigation stack with screens for Home and volunteer flows
*/

import "@expo/metro-runtime";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { StatusBar } from "expo-status-bar";
import React, { useEffect, useState } from "react";
import { ActivityIndicator, View } from "react-native";
import React from "react";
import { View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";

import AccountScreen from "./src/screens/AccountScreen";
import EmbeddedFormScreen from "./src/screens/EmbeddedFormScreen";
import EndScreen from "./src/screens/EndScreen";
import HomeScreen from "./src/screens/HomeScreen";
import SignInScreen from "./src/screens/SignInScreen";
import VolunteerFormScreen from "./src/screens/VolunteerFormScreen";
import VolunteerOpportunityScreen from "./src/screens/VolunteerOpportunityScreen";

import HomeHeader from "./src/components/HomeHeader";
import NoInternetBanner from "./src/components/NoInternetBanner";
import colors from "./src/constants/colors";
import { alertError, navigationRef } from "./src/utils";
import { navigationRef } from "./src/utils";

const Stack = createNativeStackNavigator();

export default function App() {
// Local state: loading indicator and logged-in status
const [loading, setLoading] = useState(true);
const [isLoggedIn, setIsLoggedIn] = useState(false);

useEffect(() => {
// On mount, retrieve user info to determine if already signed in
(async () => {
try {
const userString = await AsyncStorage.getItem("user");
setIsLoggedIn(userString != null);
} catch (error) {
// Alert on any errors retrieving user data
alertError(`While getting user in App: ${error}`);
} finally {
// Hide loading spinner after check
setLoading(false);
}
})();
}, []);

// Show a full-screen spinner while initializing app state
if (loading) {
return <ActivityIndicator size="large" />;
}

// Once ready, render the navigation container with all screens
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<NavigationContainer ref={navigationRef}>
{/* Light-content status bar to match header styling */}
<StatusBar style="light" />
<Stack.Navigator
initialRouteName={isLoggedIn ? "Home" : "Sign In"}
initialRouteName="Home"
screenOptions={{
headerStyle: { backgroundColor: colors.primary },
headerTintColor: colors.white,
}}
>
{/* Sign In screen for authentication */}
<Stack.Screen
name="Sign In"
component={SignInScreen}
options={{ headerBackVisible: false }}
/>
{/* Main Home screen with custom header */}
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ header: (props) => <HomeHeader {...props} /> }}
/>
{/* Account management screen */}
<Stack.Screen
name="Account"
component={AccountScreen}
options={{ animation: "slide_from_bottom" }}
/>
{/* Detailed volunteer opportunity view */}
<Stack.Screen
name="Volunteer Opportunity"
component={VolunteerOpportunityScreen}
Expand All @@ -97,11 +51,8 @@ export default function App() {
headerStyle: { backgroundColor: colors.black },
}}
/>
{/* Form submission screen for events */}
<Stack.Screen name="Sign Up Form" component={VolunteerFormScreen} />
{/* Embedded Google Forms web view */}
<Stack.Screen name="Google Forms" component={EmbeddedFormScreen} />
{/* End screen showing submission success/failure */}
<Stack.Screen
name="End"
component={EndScreen}
Expand Down
17 changes: 2 additions & 15 deletions app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default {
ios: {
supportsTablet: true,
bundleIdentifier: "org.eternityband.signup",
usesAppleSignIn: true,
},
android: {
adaptiveIcon: {
Expand All @@ -27,7 +26,7 @@ export default {
favicon: "./src/assets/eternity-band.png",
},
extra: {
email: "it@eternityband.org",
email: process.env.EXPO_PUBLIC_EMAIL,
eas: {
projectId: "56bb99cb-9cbe-423d-9a88-3f82a0cf3aa0",
},
Expand All @@ -36,18 +35,6 @@ export default {
url: "https://u.expo.dev/56bb99cb-9cbe-423d-9a88-3f82a0cf3aa0",
},
runtimeVersion: "1.0.0",
plugins: [
[
"@react-native-google-signin/google-signin",
{
iosUrlScheme:
process.env.EXPO_PUBLIC_GOOGLE_OAUTH_IOS_SCHEME ??
console.error(
"Error: Undefined EXPO_PUBLIC_GOOGLE_OAUTH_IOS_SCHEME env variable",
),
},
],
"expo-apple-authentication",
],
plugins: [],
owner: "audacitymusic",
};
45 changes: 11 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@
"dependencies": {
"@emailjs/react-native": "^5.1.0",
"@expo/metro-runtime": "~6.1.2",
"@react-native-async-storage/async-storage": "2.2.0",
"@react-native-community/cli-server-api": "^13.6.9",
"@react-native-community/netinfo": "^11.4.1",
"@react-native-google-signin/google-signin": "^12.2.1",
"@react-native-picker/picker": "2.11.1",
"@react-navigation/core": "^7.12.4",
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.10.0",
"@robinbobin/react-native-google-drive-api-wrapper": "^1.2.4",
"expo": "^54.0.10",
"expo-apple-authentication": "~8.0.8",
"expo-checkbox": "~5.0.8",
"expo-constants": "~18.0.12",
"expo-dev-client": "~6.0.20",
Expand Down Expand Up @@ -53,7 +50,8 @@
"react-native-screens": "~4.16.0",
"react-native-super-grid": "^6.0.1",
"react-native-webview": "13.15.0",
"react-native-worklets": "0.5.1"
"react-native-worklets": "0.5.1",
"validator": "^13.15.35"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down
1 change: 0 additions & 1 deletion src/components/CarouselSection.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ function CarouselSection({ navigation, data, onRefresh }) {
.filter((str) => str.length > 0)
}
formURL={event["Form Link"] ?? null}
isSubmitted={event.isSubmitted}
max={event.Max}
signedUp={event["Signed Up"]}
key={index}
Expand Down
42 changes: 3 additions & 39 deletions src/components/HomeHeader.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,23 @@
/**
* HomeHeader.js
* Custom app header with gradient background, title, and user profile action.
* Props:
* - navigation: React Navigation prop for screen navigation
* - route: React Navigation route prop to detect focus changes
* Custom app header with gradient background and title
*/

import FontAwesome from "@expo/vector-icons/FontAwesome";
import { LinearGradient } from "expo-linear-gradient";
import { useEffect, useState } from "react";
import { Image, Pressable, SafeAreaView, StyleSheet, Text } from "react-native";
import { SafeAreaView, StyleSheet, Text } from "react-native";

import colors from "../constants/colors";
import { getUser } from "../utils";

export default function HomeHeader({ navigation, route }) {
// Local state for current user info
const [user, setUser] = useState(null);

// Fetch user from AsyncStorage whenever screen focus changes
useEffect(() => {
getUser(true).then(setUser);
}, [route]);

export default function HomeHeader() {
return (
<LinearGradient
colors={[colors.primaryLight, colors.primaryDark]}
style={styles.container}
>
<SafeAreaView style={styles.subcontainer}>
Comment thread
Pramad712 marked this conversation as resolved.
{/* App title */}
<Text style={styles.headerText} selectable>
Audacity Sign Up
</Text>
{/* Profile icon or user photo navigates to Account screen */}
<Pressable onPress={() => navigation.navigate("Account")}>
{user?.photo ? (
<Image
style={styles.profile}
source={{ uri: user.photo, width: 40, height: 40 }}
/>
) : (
<FontAwesome
name="user-circle"
size={40}
color="white"
style={styles.profile}
/>
)}
</Pressable>
</SafeAreaView>
</LinearGradient>
);
Expand All @@ -70,9 +39,4 @@ const styles = StyleSheet.create({
color: colors.white,
fontSize: 23,
},
profile: {
width: 40,
height: 40,
borderRadius: 100,
},
});
Loading
Loading