diff --git a/frontend/.env.example b/frontend/.env.example index 63e09ed..8fd2f31 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1 +1,2 @@ EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your_key_here +EXPO_PUBLIC_API_BASE_URL=https://localhost:5000/ diff --git a/frontend/app.config.ts b/frontend/app.config.ts new file mode 100644 index 0000000..eb73656 --- /dev/null +++ b/frontend/app.config.ts @@ -0,0 +1,16 @@ +import { ExpoConfig } from "@expo/config"; +import getLocalIPAddress from "./getLocalIPAddress"; + +const LOCAL_IP = getLocalIPAddress(); + +const config: ExpoConfig = { + name: "Snap Map", + slug: "snap-map", + version: "1.0.0", + + extra: { + API_BASE_URL: `http://${LOCAL_IP}:5000` + } +}; + +export default config; \ No newline at end of file diff --git a/frontend/env.d.ts b/frontend/env.d.ts index 7aeac06..f0265e6 100644 --- a/frontend/env.d.ts +++ b/frontend/env.d.ts @@ -4,5 +4,6 @@ declare namespace NodeJS { interface ProcessEnv { EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY?: string; + EXPO_PUBLIC_API_BASE_URL?: string; } } diff --git a/frontend/getLocalIPAddress.js b/frontend/getLocalIPAddress.js new file mode 100644 index 0000000..7d62121 --- /dev/null +++ b/frontend/getLocalIPAddress.js @@ -0,0 +1,17 @@ +import { networkInterfaces } from "os"; + +function getLocalIPAddress() { + const interfaces = networkInterfaces(); + + for (const name in interfaces) { + for (const iface of interfaces[name] || []) { + if (iface.family === "IPv4" && !iface.internal) { + return iface.address; + } + } + } + + return "localhost"; +} + +export default getLocalIPAddress; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f21ae1e..d45100d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -27,6 +27,7 @@ "react-native": "0.81.5", "react-native-gesture-handler": "~2.28.0", "react-native-keyboard-controller": "1.18.5", + "react-native-maps": "1.20.1", "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "~5.6.0", "react-native-screens": "~4.16.0", @@ -3033,6 +3034,12 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -7488,6 +7495,28 @@ "react-native-reanimated": ">=3.0.0" } }, + "node_modules/react-native-maps": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.20.1.tgz", + "integrity": "sha512-NZI3B5Z6kxAb8gzb2Wxzu/+P2SlFIg1waHGIpQmazDSCRkNoHNY4g96g+xS0QPSaG/9xRBbDNnd2f2/OW6t6LQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.13" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": ">= 17.0.1", + "react-native": ">= 0.64.3", + "react-native-web": ">= 0.11" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, "node_modules/react-native-reanimated": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.6.tgz", @@ -8492,9 +8521,9 @@ } }, "node_modules/tabbable": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.3.0.tgz", - "integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "license": "MIT" }, "node_modules/tar": { diff --git a/frontend/package.json b/frontend/package.json index aca0646..50cefcc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,6 +28,7 @@ "react-native": "0.81.5", "react-native-gesture-handler": "~2.28.0", "react-native-keyboard-controller": "1.18.5", + "react-native-maps": "1.20.1", "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "~5.6.0", "react-native-screens": "~4.16.0", diff --git a/frontend/src/screens/BubbleDetailsScreen.tsx b/frontend/src/screens/BubbleDetailsScreen.tsx index 82bbd00..3b34460 100644 --- a/frontend/src/screens/BubbleDetailsScreen.tsx +++ b/frontend/src/screens/BubbleDetailsScreen.tsx @@ -1,7 +1,9 @@ import React from "react"; import { View, Text, Button, StyleSheet } from "react-native"; import type { ScreenProps } from "../types"; +import BubbleDetailsStyle from "../styles/BubbleDetailsStyle"; +const styles = BubbleDetailsStyle; const BubbleDetailsScreen = ({ navigation, }: ScreenProps<"BubbleDetailsScreen">) => { @@ -17,17 +19,3 @@ const BubbleDetailsScreen = ({ }; export default BubbleDetailsScreen; - -const styles = StyleSheet.create({ - root: { - textAlign: "center", - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - flex: 1, - }, - text: { - fontSize: 18, - marginBottom: 10, - }, -}); diff --git a/frontend/src/screens/CameraScreen.tsx b/frontend/src/screens/CameraScreen.tsx index c6e4235..9b615fe 100644 --- a/frontend/src/screens/CameraScreen.tsx +++ b/frontend/src/screens/CameraScreen.tsx @@ -11,7 +11,9 @@ import { View, } from "react-native"; import type { ScreenProps } from "../types"; +import CameraStyle from "../styles/CameraStyle"; +const styles = CameraStyle; export default function CameraScreen({ navigation, }: ScreenProps<"CameraScreen">) { @@ -146,68 +148,3 @@ export default function CameraScreen({ ); } - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: "#000000ff", - }, - permissionContainer: { - flex: 1, - alignItems: "center", - justifyContent: "center", - padding: 4, - backgroundColor: "#000000ff", - }, - permissionText: { - color: "#fff", - fontSize: 16, - textAlign: "center", - marginBottom: 16, - }, - camera: { - flex: 1, - }, - controls: { - position: "absolute", - bottom: 40, - width: "100%", - alignItems: "center", - gap: 16, - }, - controlsRow: { - flexDirection: "row", - justifyContent: "space-between", - width: "80%", - }, - controlButton: { - backgroundColor: "rgba(0,0,0,0.5)", - paddingVertical: 8, - paddingHorizontal: 16, - borderRadius: 20, - }, - controlText: { - color: "#fff", - fontSize: 14, - fontWeight: "600", - }, - shutterOuter: { - width: 72, - height: 72, - borderRadius: 36, - borderWidth: 4, - borderColor: "#0e0d0dff", - alignItems: "center", - justifyContent: "center", - }, - shutterInnerButton: { - width: 56, - height: 56, - borderRadius: 28, - backgroundColor: "#ffffffff", - - fontSize: 24, - fontWeight: "bold", - color: "white", - }, -}); diff --git a/frontend/src/screens/ErrorScreen.tsx b/frontend/src/screens/ErrorScreen.tsx index d4bd4de..ec55081 100644 --- a/frontend/src/screens/ErrorScreen.tsx +++ b/frontend/src/screens/ErrorScreen.tsx @@ -2,7 +2,9 @@ import React from "react"; import { View, Text, StyleSheet } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; import type { ScreenProps } from "../types"; +import ErrorStyle from "../styles/ErrorStyle"; +const styles = ErrorStyle; const ErrorScreen = ({ navigation }: ScreenProps<"ErrorScreen">) => { return ( @@ -17,30 +19,3 @@ const ErrorScreen = ({ navigation }: ScreenProps<"ErrorScreen">) => { }; export default ErrorScreen; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: "#FFF5F5", - }, - content: { - flex: 1, - justifyContent: "center", - alignItems: "center", - paddingHorizontal: 20, - }, - errorText: { - fontSize: 48, - fontWeight: "bold", - color: "#000", - marginBottom: 20, - textAlign: "center", - }, - messageText: { - fontSize: 18, - fontWeight: "normal", - color: "#000", - textAlign: "center", - lineHeight: 24, - }, -}); diff --git a/frontend/src/screens/EventGalleryScreen.tsx b/frontend/src/screens/EventGalleryScreen.tsx index 3cf2420..5bdcd2c 100644 --- a/frontend/src/screens/EventGalleryScreen.tsx +++ b/frontend/src/screens/EventGalleryScreen.tsx @@ -1,6 +1,9 @@ import React from "react"; import { View, Text, Button, StyleSheet } from "react-native"; import type { ScreenProps } from "../types"; +import EventGalleryStyle from "../styles/EventGalleryStyle"; + +const styles = EventGalleryStyle; const EventGalleryScreen = ({ navigation, @@ -17,17 +20,3 @@ const EventGalleryScreen = ({ }; export default EventGalleryScreen; - -const styles = StyleSheet.create({ - root: { - textAlign: "center", - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - flex: 1, - }, - text: { - fontSize: 18, - marginBottom: 10, - }, -}); diff --git a/frontend/src/screens/HomeScreen.tsx b/frontend/src/screens/HomeScreen.tsx index 44977a0..57a0634 100644 --- a/frontend/src/screens/HomeScreen.tsx +++ b/frontend/src/screens/HomeScreen.tsx @@ -4,6 +4,9 @@ import { Ionicons } from "@expo/vector-icons"; import { SafeAreaView } from "react-native-safe-area-context"; import type { ScreenProps } from "../types"; import { useUser } from "@clerk/clerk-expo"; +import HomeStyle from "../styles/HomeStyle"; + +const styles = HomeStyle; const HomeScreen = ({ navigation }: ScreenProps<"HomeScreen">) => { const { user } = useUser(); @@ -62,62 +65,3 @@ const HomeScreen = ({ navigation }: ScreenProps<"HomeScreen">) => { }; export default HomeScreen; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: "#FFF5F5", - }, - logoContainer: { - alignItems: "center", - paddingTop: 10, - paddingBottom: 10, - }, - logo: { - width: 100, - height: 100, - }, - mapContainer: { - flex: 1, - justifyContent: "center", - alignItems: "center", - margin: 20, - overflow: "hidden", - }, - mapImage: { - width: "125%", - height: "125%", - }, - buttonContainer: { - padding: 20, - paddingBottom: 40, - gap: 16, - }, - button: { - backgroundColor: "#FF4444", - borderRadius: 16, - paddingVertical: 18, - paddingHorizontal: 24, - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.1, - shadowRadius: 4, - elevation: 3, - }, - buttonText: { - color: "#FFFFFF", - fontSize: 18, - fontWeight: "bold", - letterSpacing: 1, - textTransform: "uppercase", - }, - cameraIcon: { - marginRight: 12, - }, -}); diff --git a/frontend/src/screens/MapScreen.tsx b/frontend/src/screens/MapScreen.tsx index 230ee9d..44794d1 100644 --- a/frontend/src/screens/MapScreen.tsx +++ b/frontend/src/screens/MapScreen.tsx @@ -4,6 +4,9 @@ import React, { useState, useEffect } from "react"; import * as Location from "expo-location"; import type { ScreenProps } from "../types"; import { FontAwesome } from "@expo/vector-icons"; +import MapStyle from "../styles/MapStyle"; + +const styles = MapStyle; const MapScreen = ({ navigation }: ScreenProps<"MapScreen">) => { const [location, setLocation] = useState<{ @@ -71,40 +74,3 @@ const MapScreen = ({ navigation }: ScreenProps<"MapScreen">) => { }; export default MapScreen; - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - map: { - width: "100%", - height: "100%", - }, - loading: { - flex: 1, - justifyContent: "center", - alignItems: "center", - }, - CameraButton: { - position: "absolute", - bottom: 100, - right: 20, - width: 60, - height: 60, - borderRadius: 10, - backgroundColor: "#DB001A", - justifyContent: "center", - alignItems: "center", - }, - HomeButton: { - position: "absolute", - top: 50, - left: 20, - width: 60, - height: 60, - borderRadius: 10, - backgroundColor: "#DB001A", - justifyContent: "center", - alignItems: "center", - }, -}); diff --git a/frontend/src/screens/MyUploadsScreen.tsx b/frontend/src/screens/MyUploadsScreen.tsx index 3b19d8c..b4e8378 100644 --- a/frontend/src/screens/MyUploadsScreen.tsx +++ b/frontend/src/screens/MyUploadsScreen.tsx @@ -1,6 +1,9 @@ import React from "react"; import { View, Text, Button, StyleSheet } from "react-native"; import type { ScreenProps } from "../types"; +import MyUploadsStyle from "../styles/MyUploadsStyle"; + +const styles = MyUploadsStyle; const MyUploadsScreen = ({ navigation }: ScreenProps<"MyUploadsScreen">) => { return ( @@ -14,18 +17,4 @@ const MyUploadsScreen = ({ navigation }: ScreenProps<"MyUploadsScreen">) => { ); }; -export default MyUploadsScreen; - -const styles = StyleSheet.create({ - root: { - textAlign: "center", - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - flex: 1, - }, - text: { - fontSize: 18, - marginBottom: 10, - }, -}); +export default MyUploadsScreen; \ No newline at end of file diff --git a/frontend/src/screens/ProfileScreen.tsx b/frontend/src/screens/ProfileScreen.tsx index b13b629..3ead5b3 100644 --- a/frontend/src/screens/ProfileScreen.tsx +++ b/frontend/src/screens/ProfileScreen.tsx @@ -1,6 +1,9 @@ import React from "react"; import { View, Text, Button, StyleSheet } from "react-native"; import type { ScreenProps } from "../types"; +import ProfileStyle from "../styles/ProfileStyle"; + +const styles = ProfileStyle; const ProfileScreen = ({ navigation }: ScreenProps<"ProfileScreen">) => { return ( @@ -15,17 +18,3 @@ const ProfileScreen = ({ navigation }: ScreenProps<"ProfileScreen">) => { }; export default ProfileScreen; - -const styles = StyleSheet.create({ - root: { - textAlign: "center", - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - flex: 1, - }, - text: { - fontSize: 18, - marginBottom: 10, - }, -}); diff --git a/frontend/src/screens/RegisterUserScreen.tsx b/frontend/src/screens/RegisterUserScreen.tsx index 9014d98..9063aec 100644 --- a/frontend/src/screens/RegisterUserScreen.tsx +++ b/frontend/src/screens/RegisterUserScreen.tsx @@ -4,16 +4,17 @@ import { Text, TextInput, TouchableOpacity, - StyleSheet, ScrollView, Alert, ActivityIndicator, Platform, Modal, } from "react-native"; +import RegisterUserStyle from "../styles/RegisterUserStyle"; import { useUser, useAuth } from "@clerk/clerk-expo"; import { Ionicons } from "@expo/vector-icons"; import { ScreenProps } from "../types"; +import Constants from "expo-constants"; // Enum values - Gender from backend model const GENDER_OPTIONS = ["male", "female", "others"]; @@ -21,15 +22,10 @@ const GENDER_OPTIONS = ["male", "female", "others"]; // Year options - frontend enum const YEAR_OPTIONS = ["1st", "2nd", "3rd", "4th", "5th", "Graduate", "Other"]; -// For Android emulator, use 10.0.2.2 instead of localhost -// For iOS simulator, localhost works fine -// For physical devices, use your computer's IP address -const API_BASE_URL = __DEV__ - ? Platform.OS === "android" - ? "http://10.0.2.2:5000" - : "http://192.168.29.11:5000" - : "https://your-production-url.com"; +// Use API base URL from environment variable +export const API_BASE_URL = Constants.expoConfig?.extra?.API_BASE_URL ?? "http://localhost:5000"; +const styles = RegisterUserStyle; const RegisterUserScreen = ({ navigation }: ScreenProps<"RegisterUserScreen">) => { const { user } = useUser(); const { getToken } = useAuth(); @@ -388,149 +384,3 @@ const RegisterUserScreen = ({ navigation }: ScreenProps<"RegisterUserScreen">) = }; export default RegisterUserScreen; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: "#FFF5F5", - }, - contentContainer: { - padding: 20, - paddingTop: 40, - }, - header: { - marginTop: 20, - marginBottom: 30, - alignItems: "center", - }, - title: { - fontSize: 24, - fontWeight: "bold", - color: "#333", - marginBottom: 8, - }, - subtitle: { - fontSize: 14, - color: "#666", - textAlign: "center", - }, - form: { - gap: 20, - }, - inputGroup: { - marginBottom: 4, - }, - label: { - fontSize: 14, - fontWeight: "600", - color: "#333", - marginBottom: 8, - }, - required: { - color: "#FF4444", - }, - input: { - backgroundColor: "#FFFFFF", - borderRadius: 12, - paddingHorizontal: 16, - paddingVertical: 14, - fontSize: 16, - color: "#333", - borderWidth: 1, - borderColor: "#E0E0E0", - }, - inputError: { - borderColor: "#FF4444", - }, - errorText: { - color: "#FF4444", - fontSize: 12, - marginTop: 4, - marginLeft: 4, - }, - submitButton: { - backgroundColor: "#FF4444", - borderRadius: 12, - paddingVertical: 16, - alignItems: "center", - justifyContent: "center", - marginTop: 10, - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.1, - shadowRadius: 4, - elevation: 3, - }, - submitButtonDisabled: { - opacity: 0.6, - }, - submitButtonText: { - color: "#FFFFFF", - fontSize: 16, - fontWeight: "bold", - letterSpacing: 0.5, - }, - dropdown: { - backgroundColor: "#FFFFFF", - borderRadius: 12, - paddingHorizontal: 16, - paddingVertical: 14, - fontSize: 16, - borderWidth: 1, - borderColor: "#E0E0E0", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - }, - dropdownText: { - fontSize: 16, - color: "#333", - }, - dropdownPlaceholder: { - color: "#999", - }, - modalOverlay: { - flex: 1, - backgroundColor: "rgba(0, 0, 0, 0.5)", - justifyContent: "center", - alignItems: "center", - }, - dropdownModal: { - backgroundColor: "#FFFFFF", - borderRadius: 12, - width: "80%", - maxWidth: 400, - maxHeight: "60%", - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.25, - shadowRadius: 4, - elevation: 5, - }, - dropdownOption: { - paddingHorizontal: 20, - paddingVertical: 16, - borderBottomWidth: 1, - borderBottomColor: "#F0F0F0", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - }, - dropdownOptionSelected: { - backgroundColor: "#FFF5F5", - }, - dropdownOptionText: { - fontSize: 16, - color: "#333", - }, - dropdownOptionTextSelected: { - color: "#FF4444", - fontWeight: "600", - }, -}); \ No newline at end of file diff --git a/frontend/src/screens/SettingsScreen.tsx b/frontend/src/screens/SettingsScreen.tsx index 1a7f58e..e810138 100644 --- a/frontend/src/screens/SettingsScreen.tsx +++ b/frontend/src/screens/SettingsScreen.tsx @@ -1,6 +1,9 @@ import React from "react"; import { View, Text, Button, StyleSheet } from "react-native"; import type { ScreenProps } from "../types"; +import SettingsStyle from "../styles/SettingsStyle"; + +const styles = SettingsStyle; const SettingsScreen = ({ navigation }: ScreenProps<"SettingsScreen">) => { return ( @@ -15,17 +18,3 @@ const SettingsScreen = ({ navigation }: ScreenProps<"SettingsScreen">) => { }; export default SettingsScreen; - -const styles = StyleSheet.create({ - root: { - textAlign: "center", - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - flex: 1, - }, - text: { - fontSize: 18, - marginBottom: 10, - }, -}); diff --git a/frontend/src/screens/SignInScreen.tsx b/frontend/src/screens/SignInScreen.tsx index 67c2878..a75d65c 100644 --- a/frontend/src/screens/SignInScreen.tsx +++ b/frontend/src/screens/SignInScreen.tsx @@ -3,6 +3,9 @@ import { StyleSheet, View, Text, TouchableOpacity } from "react-native"; import { useSignIn, useOAuth, useAuth } from "@clerk/clerk-expo"; import * as WebBrowser from "expo-web-browser"; import type { ScreenProps } from "../types"; +import SignInStyle from "../styles/SignInStyle"; + +const styles = SignInStyle; WebBrowser.maybeCompleteAuthSession(); @@ -52,46 +55,4 @@ const SignInScreen = ({ navigation }: ScreenProps<"SignInScreen">) => { ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - padding: 20, - }, - title: { - fontSize: 28, - fontWeight: "bold", - marginBottom: 10, - color: "#333", - }, - subtitle: { - fontSize: 16, - color: "#666", - marginBottom: 40, - }, - button: { - backgroundColor: "#4285F4", - paddingVertical: 15, - paddingHorizontal: 40, - borderRadius: 8, - marginBottom: 20, - width: "100%", - alignItems: "center", - }, - buttonText: { - color: "#fff", - fontSize: 16, - fontWeight: "600", - }, - linkButton: { - marginTop: 10, - }, - linkText: { - color: "#4285F4", - fontSize: 14, - }, -}); - -export default SignInScreen; +export default SignInScreen; \ No newline at end of file diff --git a/frontend/src/screens/SignUpScreen.tsx b/frontend/src/screens/SignUpScreen.tsx index fd91939..d1f75a5 100644 --- a/frontend/src/screens/SignUpScreen.tsx +++ b/frontend/src/screens/SignUpScreen.tsx @@ -3,6 +3,9 @@ import { StyleSheet, View, Text, TouchableOpacity } from "react-native"; import { useSignUp, useOAuth } from "@clerk/clerk-expo"; import * as WebBrowser from "expo-web-browser"; import type { ScreenProps } from "../types"; +import SignUpStyle from "../styles/SignUpStyle"; + +const styles = SignUpStyle; WebBrowser.maybeCompleteAuthSession(); @@ -44,46 +47,4 @@ const SignUpScreen = ({ navigation }: ScreenProps<"SignUpScreen">) => { ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - padding: 20, - }, - title: { - fontSize: 28, - fontWeight: "bold", - marginBottom: 10, - color: "#333", - }, - subtitle: { - fontSize: 16, - color: "#666", - marginBottom: 40, - }, - button: { - backgroundColor: "#4285F4", - paddingVertical: 15, - paddingHorizontal: 40, - borderRadius: 8, - marginBottom: 20, - width: "100%", - alignItems: "center", - }, - buttonText: { - color: "#fff", - fontSize: 16, - fontWeight: "600", - }, - linkButton: { - marginTop: 10, - }, - linkText: { - color: "#4285F4", - fontSize: 14, - }, -}); - export default SignUpScreen; diff --git a/frontend/src/screens/SplashScreen.tsx b/frontend/src/screens/SplashScreen.tsx index 78a299d..3d18a7d 100644 --- a/frontend/src/screens/SplashScreen.tsx +++ b/frontend/src/screens/SplashScreen.tsx @@ -2,6 +2,9 @@ import React, { useEffect } from "react"; import { View, Text, StyleSheet, Image } from "react-native"; import { useAuth } from "@clerk/clerk-expo"; import type { ScreenProps } from "../types"; +import SplashStyle from "../styles/SplashStyle"; + +const styles = SplashStyle; const SplashScreen = ({ navigation }: ScreenProps<"SplashScreen">) => { const { isSignedIn, isLoaded } = useAuth(); @@ -33,23 +36,3 @@ const SplashScreen = ({ navigation }: ScreenProps<"SplashScreen">) => { }; export default SplashScreen; - -const styles = StyleSheet.create({ - root: { - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - flex: 1, - }, - icon: { - width: 120, - height: 120, - marginBottom: 24, - }, - text: { - fontSize: 28, - fontWeight: "bold", - color: "#000", - letterSpacing: 2, - }, -}); diff --git a/frontend/src/screens/UploadConfirmationScreen.tsx b/frontend/src/screens/UploadConfirmationScreen.tsx index b418621..3a4fc7e 100644 --- a/frontend/src/screens/UploadConfirmationScreen.tsx +++ b/frontend/src/screens/UploadConfirmationScreen.tsx @@ -1,6 +1,9 @@ import React from "react"; import { Alert, Button, Image, StyleSheet, View } from "react-native"; import type { ScreenProps } from "../types"; +import UploadConfirmationStyle from "../styles/UploadConfirmationStyle"; + +const styles = UploadConfirmationStyle; const UploadConfirmationScreen = ({ navigation, @@ -47,31 +50,3 @@ const UploadConfirmationScreen = ({ }; export default UploadConfirmationScreen; - -const styles = StyleSheet.create({ - root: { - flex: 1, - backgroundColor: "#000", - justifyContent: "center", - alignItems: "center", - padding: 16, - gap: 16, - }, - text: { - fontSize: 18, - marginBottom: 10, - color: "#fff", - textAlign: "center", - }, - preview: { - width: "100%", - flex: 1, - borderRadius: 12, - }, - actions: { - width: "100%", - gap: 12, - - marginBottom: 10, - }, -}); diff --git a/frontend/src/styles/BubbleDetailsStyle.tsx b/frontend/src/styles/BubbleDetailsStyle.tsx new file mode 100644 index 0000000..51e4037 --- /dev/null +++ b/frontend/src/styles/BubbleDetailsStyle.tsx @@ -0,0 +1,17 @@ +import { StyleSheet } from "react-native"; + +const BubbleDetailsStyle = StyleSheet.create({ + root: { + textAlign: "center", + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + flex: 1, + }, + text: { + fontSize: 18, + marginBottom: 10, + }, +}); + +export default BubbleDetailsStyle; diff --git a/frontend/src/styles/CameraStyle.tsx b/frontend/src/styles/CameraStyle.tsx new file mode 100644 index 0000000..9dbe5d0 --- /dev/null +++ b/frontend/src/styles/CameraStyle.tsx @@ -0,0 +1,68 @@ +import { StyleSheet } from "react-native"; + +const CameraStyle = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#000000ff", + }, + permissionContainer: { + flex: 1, + alignItems: "center", + justifyContent: "center", + padding: 4, + backgroundColor: "#000000ff", + }, + permissionText: { + color: "#fff", + fontSize: 16, + textAlign: "center", + marginBottom: 16, + }, + camera: { + flex: 1, + }, + controls: { + position: "absolute", + bottom: 40, + width: "100%", + alignItems: "center", + gap: 16, + }, + controlsRow: { + flexDirection: "row", + justifyContent: "space-between", + width: "80%", + }, + controlButton: { + backgroundColor: "rgba(0,0,0,0.5)", + paddingVertical: 8, + paddingHorizontal: 16, + borderRadius: 20, + }, + controlText: { + color: "#fff", + fontSize: 14, + fontWeight: "600", + }, + shutterOuter: { + width: 72, + height: 72, + borderRadius: 36, + borderWidth: 4, + borderColor: "#0e0d0dff", + alignItems: "center", + justifyContent: "center", + }, + shutterInnerButton: { + width: 56, + height: 56, + borderRadius: 28, + backgroundColor: "#ffffffff", + + fontSize: 24, + fontWeight: "bold", + color: "white", + }, +}); + +export default CameraStyle; \ No newline at end of file diff --git a/frontend/src/styles/ErrorStyle.tsx b/frontend/src/styles/ErrorStyle.tsx new file mode 100644 index 0000000..eb96c81 --- /dev/null +++ b/frontend/src/styles/ErrorStyle.tsx @@ -0,0 +1,30 @@ +import { StyleSheet } from "react-native"; + +const ErrorStyle = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#FFF5F5", + }, + content: { + flex: 1, + justifyContent: "center", + alignItems: "center", + paddingHorizontal: 20, + }, + errorText: { + fontSize: 48, + fontWeight: "bold", + color: "#000", + marginBottom: 20, + textAlign: "center", + }, + messageText: { + fontSize: 18, + fontWeight: "normal", + color: "#000", + textAlign: "center", + lineHeight: 24, + }, +}); + +export default ErrorStyle; diff --git a/frontend/src/styles/EventGalleryStyle.tsx b/frontend/src/styles/EventGalleryStyle.tsx new file mode 100644 index 0000000..e7501ad --- /dev/null +++ b/frontend/src/styles/EventGalleryStyle.tsx @@ -0,0 +1,17 @@ +import { StyleSheet } from "react-native"; + +const EventGalleryStyle = StyleSheet.create({ + root: { + textAlign: "center", + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + flex: 1, + }, + text: { + fontSize: 18, + marginBottom: 10, + }, +}); + +export default EventGalleryStyle; diff --git a/frontend/src/styles/HomeStyle.tsx b/frontend/src/styles/HomeStyle.tsx new file mode 100644 index 0000000..d878a17 --- /dev/null +++ b/frontend/src/styles/HomeStyle.tsx @@ -0,0 +1,62 @@ +import { StyleSheet } from "react-native"; + +const HomeStyle = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#FFF5F5", + }, + logoContainer: { + alignItems: "center", + paddingTop: 10, + paddingBottom: 10, + }, + logo: { + width: 100, + height: 100, + }, + mapContainer: { + flex: 1, + justifyContent: "center", + alignItems: "center", + margin: 20, + overflow: "hidden", + }, + mapImage: { + width: "125%", + height: "125%", + }, + buttonContainer: { + padding: 20, + paddingBottom: 40, + gap: 16, + }, + button: { + backgroundColor: "#FF4444", + borderRadius: 16, + paddingVertical: 18, + paddingHorizontal: 24, + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + shadowColor: "#000", + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 3, + }, + buttonText: { + color: "#FFFFFF", + fontSize: 18, + fontWeight: "bold", + letterSpacing: 1, + textTransform: "uppercase", + }, + cameraIcon: { + marginRight: 12, + }, +}); + +export default HomeStyle; \ No newline at end of file diff --git a/frontend/src/styles/MapStyle.tsx b/frontend/src/styles/MapStyle.tsx new file mode 100644 index 0000000..d4cb24b --- /dev/null +++ b/frontend/src/styles/MapStyle.tsx @@ -0,0 +1,40 @@ +import { StyleSheet } from "react-native"; + +const MapStyle = StyleSheet.create({ + container: { + flex: 1, + }, + map: { + width: "100%", + height: "100%", + }, + loading: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + CameraButton: { + position: "absolute", + bottom: 100, + right: 20, + width: 60, + height: 60, + borderRadius: 10, + backgroundColor: "#DB001A", + justifyContent: "center", + alignItems: "center", + }, + HomeButton: { + position: "absolute", + top: 50, + left: 20, + width: 60, + height: 60, + borderRadius: 10, + backgroundColor: "#DB001A", + justifyContent: "center", + alignItems: "center", + }, +}); + +export default MapStyle; \ No newline at end of file diff --git a/frontend/src/styles/MyUploadsStyle.tsx b/frontend/src/styles/MyUploadsStyle.tsx new file mode 100644 index 0000000..065058f --- /dev/null +++ b/frontend/src/styles/MyUploadsStyle.tsx @@ -0,0 +1,17 @@ +import { StyleSheet } from "react-native"; + +const MyUploadsStyle = StyleSheet.create({ + root: { + textAlign: "center", + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + flex: 1, + }, + text: { + fontSize: 18, + marginBottom: 10, + }, +}); + +export default MyUploadsStyle; \ No newline at end of file diff --git a/frontend/src/styles/ProfileStyle.tsx b/frontend/src/styles/ProfileStyle.tsx new file mode 100644 index 0000000..5c1d929 --- /dev/null +++ b/frontend/src/styles/ProfileStyle.tsx @@ -0,0 +1,17 @@ +import { StyleSheet } from "react-native"; + +const ProfileStyle = StyleSheet.create({ + root: { + textAlign: "center", + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + flex: 1, + }, + text: { + fontSize: 18, + marginBottom: 10, + }, +}); + +export default ProfileStyle; \ No newline at end of file diff --git a/frontend/src/styles/RegisterUserStyle.tsx b/frontend/src/styles/RegisterUserStyle.tsx new file mode 100644 index 0000000..3a1cc8c --- /dev/null +++ b/frontend/src/styles/RegisterUserStyle.tsx @@ -0,0 +1,149 @@ +import { StyleSheet } from "react-native"; + +const RegisterUserStyles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#FFF5F5", + }, + contentContainer: { + padding: 20, + paddingTop: 40, + }, + header: { + marginTop: 20, + marginBottom: 30, + alignItems: "center", + }, + title: { + fontSize: 24, + fontWeight: "bold", + color: "#333", + marginBottom: 8, + }, + subtitle: { + fontSize: 14, + color: "#666", + textAlign: "center", + }, + form: { + gap: 20, + }, + inputGroup: { + marginBottom: 4, + }, + label: { + fontSize: 14, + fontWeight: "600", + color: "#333", + marginBottom: 8, + }, + required: { + color: "#FF4444", + }, + input: { + backgroundColor: "#FFFFFF", + borderRadius: 12, + paddingHorizontal: 16, + paddingVertical: 14, + fontSize: 16, + color: "#333", + borderWidth: 1, + borderColor: "#E0E0E0", + }, + inputError: { + borderColor: "#FF4444", + }, + errorText: { + color: "#FF4444", + fontSize: 12, + marginTop: 4, + marginLeft: 4, + }, + submitButton: { + backgroundColor: "#FF4444", + borderRadius: 12, + paddingVertical: 16, + alignItems: "center", + justifyContent: "center", + marginTop: 10, + shadowColor: "#000", + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 3, + }, + submitButtonDisabled: { + opacity: 0.6, + }, + submitButtonText: { + color: "#FFFFFF", + fontSize: 16, + fontWeight: "bold", + letterSpacing: 0.5, + }, + dropdown: { + backgroundColor: "#FFFFFF", + borderRadius: 12, + paddingHorizontal: 16, + paddingVertical: 14, + fontSize: 16, + borderWidth: 1, + borderColor: "#E0E0E0", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + }, + dropdownText: { + fontSize: 16, + color: "#333", + }, + dropdownPlaceholder: { + color: "#999", + }, + modalOverlay: { + flex: 1, + backgroundColor: "rgba(0, 0, 0, 0.5)", + justifyContent: "center", + alignItems: "center", + }, + dropdownModal: { + backgroundColor: "#FFFFFF", + borderRadius: 12, + width: "80%", + maxWidth: 400, + maxHeight: "60%", + shadowColor: "#000", + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.25, + shadowRadius: 4, + elevation: 5, + }, + dropdownOption: { + paddingHorizontal: 20, + paddingVertical: 16, + borderBottomWidth: 1, + borderBottomColor: "#F0F0F0", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + }, + dropdownOptionSelected: { + backgroundColor: "#FFF5F5", + }, + dropdownOptionText: { + fontSize: 16, + color: "#333", + }, + dropdownOptionTextSelected: { + color: "#FF4444", + fontWeight: "600", + }, +}); + +export default RegisterUserStyles; \ No newline at end of file diff --git a/frontend/src/styles/SettingsStyle.tsx b/frontend/src/styles/SettingsStyle.tsx new file mode 100644 index 0000000..09e3ac1 --- /dev/null +++ b/frontend/src/styles/SettingsStyle.tsx @@ -0,0 +1,17 @@ +import { StyleSheet } from "react-native"; + +const SettingsStyle = StyleSheet.create({ + root: { + textAlign: "center", + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + flex: 1, + }, + text: { + fontSize: 18, + marginBottom: 10, + }, +}); + +export default SettingsStyle; \ No newline at end of file diff --git a/frontend/src/styles/SignInStyle.tsx b/frontend/src/styles/SignInStyle.tsx new file mode 100644 index 0000000..a2b7d84 --- /dev/null +++ b/frontend/src/styles/SignInStyle.tsx @@ -0,0 +1,45 @@ +import { StyleSheet } from "react-native"; + +const SignInStyle = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + padding: 20, + }, + title: { + fontSize: 28, + fontWeight: "bold", + marginBottom: 10, + color: "#333", + }, + subtitle: { + fontSize: 16, + color: "#666", + marginBottom: 40, + }, + button: { + backgroundColor: "#4285F4", + paddingVertical: 15, + paddingHorizontal: 40, + borderRadius: 8, + marginBottom: 20, + width: "100%", + alignItems: "center", + }, + buttonText: { + color: "#fff", + fontSize: 16, + fontWeight: "600", + }, + linkButton: { + marginTop: 10, + }, + linkText: { + color: "#4285F4", + fontSize: 14, + }, +}); + +export default SignInStyle; diff --git a/frontend/src/styles/SignUpStyle.tsx b/frontend/src/styles/SignUpStyle.tsx new file mode 100644 index 0000000..2ec4016 --- /dev/null +++ b/frontend/src/styles/SignUpStyle.tsx @@ -0,0 +1,45 @@ +import { StyleSheet } from "react-native"; + +const SignUpStyle = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + padding: 20, + }, + title: { + fontSize: 28, + fontWeight: "bold", + marginBottom: 10, + color: "#333", + }, + subtitle: { + fontSize: 16, + color: "#666", + marginBottom: 40, + }, + button: { + backgroundColor: "#4285F4", + paddingVertical: 15, + paddingHorizontal: 40, + borderRadius: 8, + marginBottom: 20, + width: "100%", + alignItems: "center", + }, + buttonText: { + color: "#fff", + fontSize: 16, + fontWeight: "600", + }, + linkButton: { + marginTop: 10, + }, + linkText: { + color: "#4285F4", + fontSize: 14, + }, +}); + +export default SignUpStyle; diff --git a/frontend/src/styles/SplashStyle.tsx b/frontend/src/styles/SplashStyle.tsx new file mode 100644 index 0000000..e1fac75 --- /dev/null +++ b/frontend/src/styles/SplashStyle.tsx @@ -0,0 +1,23 @@ +import { StyleSheet } from "react-native"; + +const SplashStyle = StyleSheet.create({ + root: { + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + flex: 1, + }, + icon: { + width: 120, + height: 120, + marginBottom: 24, + }, + text: { + fontSize: 28, + fontWeight: "bold", + color: "#000", + letterSpacing: 2, + }, +}); + +export default SplashStyle; diff --git a/frontend/src/styles/UploadConfirmationStyle.tsx b/frontend/src/styles/UploadConfirmationStyle.tsx new file mode 100644 index 0000000..bfc695e --- /dev/null +++ b/frontend/src/styles/UploadConfirmationStyle.tsx @@ -0,0 +1,31 @@ +import { StyleSheet } from "react-native"; + +const UploadConfirmationStyle = StyleSheet.create({ + root: { + flex: 1, + backgroundColor: "#000", + justifyContent: "center", + alignItems: "center", + padding: 16, + gap: 16, + }, + text: { + fontSize: 18, + marginBottom: 10, + color: "#fff", + textAlign: "center", + }, + preview: { + width: "100%", + flex: 1, + borderRadius: 12, + }, + actions: { + width: "100%", + gap: 12, + + marginBottom: 10, + }, +}); + +export default UploadConfirmationStyle; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index e84e707..7bc2d57 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "expo/tsconfig.base", + "extends": "./node_modules/expo/tsconfig.base", "compilerOptions": { "strict": false }, @@ -7,5 +7,5 @@ "**/*.ts", "**/*.tsx", "env.d.ts" - ] +, "getLocalIPAddress.js" ] }