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/RegisterUserScreen.tsx b/frontend/src/screens/RegisterUserScreen.tsx index 9014d98..9ccb32d 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 RegisterationStyles from "../styles/RegisterationStyles"; 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 = RegisterationStyles; 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/styles/RegisterationStyles.tsx b/frontend/src/styles/RegisterationStyles.tsx new file mode 100644 index 0000000..0a7cebe --- /dev/null +++ b/frontend/src/styles/RegisterationStyles.tsx @@ -0,0 +1,149 @@ +import { StyleSheet } from "react-native"; + +const RegisterationStyles = 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 RegisterationStyles; 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" ] }