Skip to content
Merged
2 changes: 1 addition & 1 deletion shatter-mobile/app/(tabs)/EventsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import AnimatedTab from "../../src/components/AnimatedTab";
import EventCard from "../../src/components/events/EventCard";
import AnimatedTab from "../../src/components/general/AnimatedTab";
import EventIB from "../../src/interfaces/Event";
import { getUserEvents } from "../../src/services/event.service";
import { EventPageStyling as styles } from "../../src/styling/EventPage.styles";
Expand Down
14 changes: 7 additions & 7 deletions shatter-mobile/app/(tabs)/JoinEventPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { useState } from "react";
import {
ActivityIndicator,
ImageBackground,
Text,
TextInput,
TouchableOpacity,
View,
ActivityIndicator,
ImageBackground,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import AnimatedTab from "../../src/components/AnimatedTab";
import { useAuth } from "../../src/components/context/AuthContext";
import AnimatedTab from "../../src/components/general/AnimatedTab";
import QRScannerBox from "../../src/components/new-events/QRScannerBox";
import { JoinEventStyling as styles } from "../../src/styling/JoinEventPage.styles";

Expand Down
14 changes: 7 additions & 7 deletions shatter-mobile/app/(tabs)/ProfilePage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { useFocusEffect, useRouter } from "expo-router";
import { useCallback, useEffect, useState } from "react";
import {
Image,
ImageBackground,
ScrollView,
Text,
TouchableOpacity,
View,
Image,
ImageBackground,
ScrollView,
Text,
TouchableOpacity,
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { SvgUri } from "react-native-svg";
import AnimatedTab from "../../src/components/AnimatedTab";
import { useAuth } from "../../src/components/context/AuthContext";
import AnimatedTab from "../../src/components/general/AnimatedTab";
import { ProfilePageStyling as styles } from "../../src/styling/ProfilePage.styles";

export default function Profile() {
Expand Down
1 change: 1 addition & 0 deletions shatter-mobile/app/EventPages/EventLobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function EventLobby() {

router.replace({
pathname: "/GamePages/Game",
params: { eventId: event._id },
});
}
}, POLL_INTERVAL);
Expand Down
4 changes: 2 additions & 2 deletions shatter-mobile/app/GamePages/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import { ImageBackground, Text, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import FullPageLoader from "../../src/components/FullPageLoader";
import IcebreakerGame from "../../src/components/games/IcebreakerGame";
import FullPageLoader from "../../src/components/general/FullPageLoader";
import { getEventById } from "../../src/services/event.service";
import { GamePageStyling as styles } from "../../src/styling/GamePage.styles";

Expand Down Expand Up @@ -60,7 +60,7 @@ const GamePage = () => {
</View>

<View style={styles.gameContainer}>
<IcebreakerGame event={event}/>
<IcebreakerGame event={event} />
</View>
</View>
</SafeAreaView>
Expand Down
186 changes: 129 additions & 57 deletions shatter-mobile/app/UserPages/Guest.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import SocialSpinner from "@/src/components/login-signup/SocialSpinner";
import { SocialLink } from "@/src/interfaces/User";
import { colors } from "@/src/styling/constants";
import { GuestStyling as styles } from "@/src/styling/Guest.styles";
import { useRouter } from "expo-router";
import { Stack, useRouter } from "expo-router";
import { useState } from "react";
import {
ImageBackground,
Modal,
Text,
TextInput,
TouchableOpacity,
Expand All @@ -17,12 +19,13 @@ export default function GuestPage() {
const { continueAsGuest } = useAuth();
const [name, setName] = useState("");
const [contactLink, setContactLink] = useState("");
const [showConfirmModal, setShowConfirmModal] = useState(false);
const [error, setError] = useState("");
const router = useRouter();

const handleContinue = async () => {
//need name and social link
if (!name.trim() || !contactLink) {
if (!name.trim() || !contactLink.trim()) {
setError("Name and Social Link Cannot Be Empty");
return;
}
Expand All @@ -39,64 +42,133 @@ export default function GuestPage() {
}

setError("");
await continueAsGuest(name.trim(), socialLink);
await continueAsGuest(name.trim(), socialLink, ""); //no organization on this page, handled on GuestConfirm
router.replace("/JoinEventPage");
};

return (
<ImageBackground
source={require("../../src/images/getStartedImage.png")}
style={styles.background}
resizeMode="cover"
>
<SafeAreaView style={styles.safe}>
<View style={styles.header}>
<Text style={styles.pageTitle}>Guest Access</Text>
<Text style={styles.subtitle}>Enter your details to continue</Text>
</View>

<View style={styles.container}>
<Text style={styles.label}>Your Name</Text>
<TextInput
style={styles.input}
placeholder="Your Name"
placeholderTextColor={colors.lightGrey2}
value={name}
onChangeText={setName}
/>

<Text style={styles.label}>Contact Link</Text>
<TextInput
style={styles.input}
placeholder="LinkedIn, portfolio, etc."
placeholderTextColor={colors.lightGrey2}
value={contactLink}
onChangeText={setContactLink}
autoCapitalize="none"
keyboardType="url"
/>
<Text style={styles.inputInfo}>
Your contact link can be your LinkedIn profile URL, a portfolio
link, or another relevant personal link.
</Text>

{error ? <Text style={styles.error}>{error}</Text> : null}

<TouchableOpacity
style={styles.primaryButton}
onPress={handleContinue}
>
<Text style={styles.buttonText}>Continue</Text>
</TouchableOpacity>

<TouchableOpacity
style={styles.secondaryButton}
onPress={() => router.push("/UserPages/Signup")}
>
<Text style={styles.buttonText}>Back</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</ImageBackground>
<>
<Stack.Screen options={{ animation: "slide_from_left" }} />
<ImageBackground
source={require("../../src/images/getStartedImage.png")}
style={styles.background}
resizeMode="cover"
>
<SafeAreaView style={styles.safe}>
<View style={styles.header}>
<Text style={styles.pageTitle}>Guest Access</Text>
<Text style={styles.subtitle}>Enter your details to continue</Text>
</View>

<View style={styles.container}>
<Text style={styles.label}>Your Name</Text>
<TextInput
style={styles.input}
placeholder="Your Name"
placeholderTextColor={colors.lightGrey2}
value={name}
onChangeText={setName}
/>

<Text style={styles.label}>Contact Link</Text>
<TextInput
style={styles.input}
placeholder="LinkedIn, portfolio, etc."
placeholderTextColor={colors.lightGrey2}
value={contactLink}
onChangeText={setContactLink}
autoCapitalize="none"
keyboardType="url"
/>
<Text style={styles.inputInfo}>
Your contact link can be your LinkedIn profile URL, a portfolio
link, or another relevant personal link.
</Text>

{error ? <Text style={styles.error}>{error}</Text> : null}

<TouchableOpacity
style={styles.primaryButton}
onPress={handleContinue}
>
<Text style={styles.buttonText}>Continue</Text>
</TouchableOpacity>

<TouchableOpacity
style={styles.secondaryButton}
onPress={() => router.push("/UserPages/Signup")}
>
<Text style={styles.buttonText}>Back</Text>
</TouchableOpacity>

<TouchableOpacity
style={styles.secondaryButtonNoBack}
onPress={() => {
setShowConfirmModal(true);
}}
>
<Text style={styles.buttonTextWarning}>No Contact Link?</Text>
</TouchableOpacity>
</View>

<Modal visible={showConfirmModal} transparent animationType="slide">
<View
style={{
flex: 1,
backgroundColor: "rgba(0,0,0,0.6)",
justifyContent: "center",
alignItems: "center",
}}
>
<View
style={{
width: "85%",
backgroundColor: colors.lightGrey,
borderRadius: 16,
padding: 20,
}}
>
<Text style={styles.confirmTitle}>
Continue Without a Contact Link?
</Text>

<SocialSpinner />

<Text style={styles.confirmSubtitle}>
Users tend to connect better when you include a contact link
like LinkedIn or a portfolio.
</Text>

<Text style={styles.inputInfo}>
Adding a contact link helps others learn more about you and
improves networking during events.
</Text>

{/* Add link */}
<TouchableOpacity
style={styles.primaryButton}
onPress={() => setShowConfirmModal(false)}
>
<Text style={styles.buttonText}>Add Contact Link</Text>
</TouchableOpacity>

{/* Continue anyway */}
<TouchableOpacity
style={styles.secondaryButtonNoBack}
onPress={() => {
setShowConfirmModal(false);
router.push("/UserPages/GuestNoLink");
}}
>
<Text style={styles.buttonTextWarning}>
Continue Without Link
</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</SafeAreaView>
</ImageBackground>
</>
);
}
92 changes: 92 additions & 0 deletions shatter-mobile/app/UserPages/GuestNoLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { colors } from "@/src/styling/constants";
import { GuestStyling as styles } from "@/src/styling/Guest.styles";
import { Stack, useRouter } from "expo-router";
import { useState } from "react";
import {
ImageBackground,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { useAuth } from "../../src/components/context/AuthContext";

export default function GuestConfirm() {
const { continueAsGuest } = useAuth();
const [name, setName] = useState("");
const [organization, setOrganization] = useState("");
const [error, setError] = useState("");
const router = useRouter();

const handleContinue = async () => {
if (!name.trim() || !organization.trim()) {
setError("Name and Organization cannot be empty");
return;
}

setError("");

await continueAsGuest(
name.trim(),
{ label: "", url: "" },
organization.trim(),
);

router.replace("/JoinEventPage");
};

return (
<>
<Stack.Screen options={{ animation: "fade" }} />
<ImageBackground
source={require("../../src/images/getStartedImage.png")}
style={styles.background}
resizeMode="cover"
>
<SafeAreaView style={styles.safe}>
<View style={styles.header}>
<Text style={styles.pageTitle}>Guest Access</Text>
<Text style={styles.subtitle}>Continue without a contact link</Text>
</View>

<View style={styles.container}>
<Text style={styles.label}>Your Name</Text>
<TextInput
style={styles.input}
placeholder="Your Name"
placeholderTextColor={colors.lightGrey2}
value={name}
onChangeText={setName}
/>

<Text style={styles.label}>Organization</Text>
<TextInput
style={styles.input}
placeholder="Your Organization"
placeholderTextColor={colors.lightGrey2}
value={organization}
onChangeText={setOrganization}
/>

{error ? <Text style={styles.error}>{error}</Text> : null}

<TouchableOpacity
style={styles.primaryButton}
onPress={handleContinue}
>
<Text style={styles.buttonText}>Continue</Text>
</TouchableOpacity>

<TouchableOpacity
style={styles.secondaryButton}
onPress={() => router.back()}
>
<Text style={styles.buttonText}>Back</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</ImageBackground>
</>
);
}
Loading
Loading