From 7a9ce601cbf16f463566879efe45def1d8be1258 Mon Sep 17 00:00:00 2001 From: Abin Toppo Date: Mon, 29 Sep 2025 16:32:39 +0530 Subject: [PATCH] ui fix --- package-lock.json | 16 +- package.json | 2 + src/assets/images/placeholder.png | Bin 0 -> 58847 bytes src/components/CostomAlart.tsx | 177 ++++++++++ src/components/colors.ts | 35 +- src/components/common/AnimatedCard.tsx | 153 ++++----- src/components/common/Custom.tsx | 11 +- src/screens/LoginScreen.tsx | 348 ++++++++++++-------- src/screens/OtpVarificationScreen.tsx | 357 +++++++++++---------- src/screens/home/Home.tsx | 276 +++++----------- src/screens/management/EditGroupScreen.tsx | 4 +- src/screens/profile/Profile.tsx | 11 +- 12 files changed, 773 insertions(+), 617 deletions(-) create mode 100644 src/assets/images/placeholder.png create mode 100644 src/components/CostomAlart.tsx diff --git a/package-lock.json b/package-lock.json index ef44305..76b3c80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "dependencies": { "@react-native-clipboard/clipboard": "^1.16.3", + "@react-native-community/blur": "^4.4.1", "@react-native-community/slider": "^5.0.1", "@react-native-picker/picker": "^2.11.2", "@react-native-vector-icons/ionicons": "^12.3.0", @@ -36,6 +37,7 @@ "react-native-safe-area-context": "^5.6.1", "react-native-screens": "^4.16.0", "react-native-svg": "^15.13.0", + "react-native-vector-icons": "^10.3.0", "react-native-walkthrough-tooltip": "^1.6.0", "react-redux": "^9.2.0" }, @@ -2766,6 +2768,16 @@ } } }, + "node_modules/@react-native-community/blur": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@react-native-community/blur/-/blur-4.4.1.tgz", + "integrity": "sha512-XBSsRiYxE/MOEln2ayunShfJtWztHwUxLFcSL20o+HNNRnuUDv+GXkF6FmM2zE8ZUfrnhQ/zeTqvnuDPGw6O8A==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@react-native-community/cli": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-20.0.0.tgz", @@ -13578,7 +13590,6 @@ "integrity": "sha512-IFQ0RE57819hOUdFvgK4FowM5aMXg7C7XKsuGLevqXkkIJatc3QopN0wYrb2IrzUgmdpfP+QVIbI3S6h7M0btw==", "deprecated": "react-native-vector-icons package has moved to a new model of per-icon-family packages. See the https://github.com/oblador/react-native-vector-icons/blob/master/MIGRATION.md on how to migrate", "license": "MIT", - "peer": true, "dependencies": { "prop-types": "^15.7.2", "yargs": "^16.1.1" @@ -13595,7 +13606,6 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -13607,7 +13617,6 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "license": "MIT", - "peer": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -13626,7 +13635,6 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "license": "ISC", - "peer": true, "engines": { "node": ">=10" } diff --git a/package.json b/package.json index 8774c41..86868e2 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@react-native-clipboard/clipboard": "^1.16.3", + "@react-native-community/blur": "^4.4.1", "@react-native-community/slider": "^5.0.1", "@react-native-picker/picker": "^2.11.2", "@react-native-vector-icons/ionicons": "^12.3.0", @@ -38,6 +39,7 @@ "react-native-safe-area-context": "^5.6.1", "react-native-screens": "^4.16.0", "react-native-svg": "^15.13.0", + "react-native-vector-icons": "^10.3.0", "react-native-walkthrough-tooltip": "^1.6.0", "react-redux": "^9.2.0" }, diff --git a/src/assets/images/placeholder.png b/src/assets/images/placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..c7645dd59dad7f09cdde9e17bd456c9036a2408b GIT binary patch literal 58847 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 literal 0 HcmV?d00001 diff --git a/src/components/CostomAlart.tsx b/src/components/CostomAlart.tsx new file mode 100644 index 0000000..25cb593 --- /dev/null +++ b/src/components/CostomAlart.tsx @@ -0,0 +1,177 @@ +// src/components/CustomAlert.tsx + +import React from "react"; +import { + Modal, + View, + Text, + TouchableOpacity, + StyleSheet, + Platform, +} from "react-native"; +import { BlurView } from "@react-native-community/blur"; +import Ionicons from '@react-native-vector-icons/ionicons'; +import colors from "./colors"; // Import centralized colors + +interface AlertButton { + text: string; + onPress: () => void; + style?: "cancel" | "destructive" | "default"; +} + +interface CustomAlertProps { + visible: boolean; + title: string; + message: string; + buttons: AlertButton[]; + alertType?: 'error' | 'success' | 'info'; +} + +const CustomAlert: React.FC = ({ + visible, + title, + message, + buttons, + alertType = 'info', +}) => { + + const getIcon = () => { + switch (alertType) { + case 'error': + return { name: "close-circle", color: colors.error }; + case 'success': + return { name: "checkmark-circle", color: colors.success }; + default: + return { name: "information-circle", color: colors.primary }; + } + }; + + const icon = getIcon(); + + return ( + { + const closeButton = buttons.find(b => b.style === 'cancel') || buttons[0]; + closeButton?.onPress(); + }} + > + + {Platform.OS === 'ios' ? ( + + ) : ( + + )} + + + + + + {title} + {message} + + + {buttons.map((button, index) => ( + + + {button.text} + + + ))} + + + + + ); +}; + +const styles = StyleSheet.create({ + centeredView: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + absolute: { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, + }, + alertBox: { + backgroundColor: colors.alertBackground, + borderRadius: 24, + padding: 24, + alignItems: "center", + margin: 24, + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.5)', + shadowColor: colors.black, + shadowOffset: { width: 0, height: 10 }, + shadowOpacity: 0.1, + shadowRadius: 30, + elevation: 20, + width: '90%', + maxWidth: 400, + }, + iconContainer: { + marginBottom: 16, + }, + alertTitle: { + fontSize: 22, + fontWeight: "bold", + color: colors.textDark, + marginBottom: 8, + textAlign: "center", + }, + alertMessage: { + fontSize: 16, + color: colors.textLight, + textAlign: "center", + marginBottom: 24, + lineHeight: 22, + }, + buttonContainer: { + flexDirection: "row", + justifyContent: 'flex-end', + width: "100%", + gap: 12, + }, + button: { + paddingVertical: 14, + paddingHorizontal: 24, + borderRadius: 16, + justifyContent: 'center', + alignItems: 'center', + }, + defaultButton: { + backgroundColor: colors.primary, + }, + destructiveButton: { + backgroundColor: colors.error, + }, + buttonText: { + fontSize: 16, + fontWeight: "700", + }, + defaultButtonText: { + color: colors.white, + }, + destructiveButtonText: { + color: colors.white, + }, +}); + +export default CustomAlert; diff --git a/src/components/colors.ts b/src/components/colors.ts index 0abc115..a318f82 100644 --- a/src/components/colors.ts +++ b/src/components/colors.ts @@ -1,22 +1,27 @@ -// colors.ts -const colors = { - pastelPink: "#decbfcff", // darker pink - pastelBlue: "#D7E9F7", // darker blue - pastelGreen: "#DFF6DD", // darker green - pastelOrange: "#FFF4D2", // darker orange +// src/components/colors.ts - // darker accent colors - Home: "#995dfaff", // Rose red for contrast - Profile: "#2D9CDB", // Deep sky blue - Group: "#27AE60", // Green for freshness - Settings: "#F39C12", // Amber for warmth +const colors = { + // Pastel palette + pastelPink: "#decbfc", + pastelBlue: "#D7E9F7", + pastelGreen: "#DFF6DD", + pastelOrange: "#FFF4D2", - // common text + UI colors - textDark: "#212121", - textLight: "#555555", + // Primary and status colors + primary: "#711ff7", + error: "#EF4444", + success: "#22C55E", + + // Common UI colors + textDark: "#1F2937", + textLight: "#6B7280", white: "#FFFFFF", black: "#000000", - primary: "#711ff7ff", + inputBorder: "#E5E7EB", + + // Special background colors with transparency + alertBackground: "rgba(255, 255, 255, 0.8)", + androidBackdrop: "rgba(0, 0, 0, 0.4)", }; export default colors; diff --git a/src/components/common/AnimatedCard.tsx b/src/components/common/AnimatedCard.tsx index c4296a9..b1fa10c 100644 --- a/src/components/common/AnimatedCard.tsx +++ b/src/components/common/AnimatedCard.tsx @@ -5,10 +5,12 @@ import { StyleSheet, TouchableWithoutFeedback, Animated, + ViewStyle, } from "react-native"; import LinearGradient from "react-native-linear-gradient"; -import { Ionicons, IoniconsIconName } from "@react-native-vector-icons/ionicons"; -import colors from "../colors"; +import Ionicons from "react-native-vector-icons/Ionicons"; +import { IoniconsIconName } from "react-native-vector-icons/Ionicons"; +import colors from "../colors"; // Assuming your pastel colors are defined here type CardProps = { title: string; @@ -16,7 +18,8 @@ type CardProps = { iconName?: IoniconsIconName; onPress?: () => void; backOne?: string; - backTwo?: string + backTwo?: string; + style?: ViewStyle; }; const AnimatedCard: React.FC = ({ @@ -24,33 +27,27 @@ const AnimatedCard: React.FC = ({ subtitle, iconName = "ellipse", onPress, - backOne = '#4facfe', - backTwo = '#00f2fe' + backOne = colors.pastelPink, // Defaulting to pastelPink + backTwo = colors.primary, + style, }) => { const scale = useRef(new Animated.Value(1)).current; const handlePressIn = () => { - Animated.spring(scale, { - toValue: 0.96, - useNativeDriver: true, - friction: 4, - }).start(); + Animated.spring(scale, { toValue: 0.96, useNativeDriver: true, friction: 4 }).start(); }; const handlePressOut = () => { - Animated.spring(scale, { - toValue: 1, - useNativeDriver: true, - friction: 4, - }).start(() => onPress && onPress()); + Animated.spring(scale, { toValue: 1, useNativeDriver: true, friction: 4 }).start(() => { + if (onPress) { + onPress(); + } + }); }; return ( - - + + = ({ > {/* Decorative Graphics */} - - - {/* Content */} - {iconName && ( - - )} + {iconName && } {title} {subtitle && {subtitle}} @@ -87,102 +74,70 @@ const AnimatedCard: React.FC = ({ const styles = StyleSheet.create({ card: { - // marginHorizontal: 16, marginVertical: 10, - borderRadius: 20, + borderRadius: 24, overflow: "hidden", shadowColor: "#000", - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.25, - shadowRadius: 8, - elevation: 8, + shadowOffset: { width: 0, height: 5 }, + shadowOpacity: 0.15, + shadowRadius: 12, + elevation: 5, + backgroundColor: colors.white, }, gradient: { - minHeight: 120, + minHeight: 150, // Increased height for better spacing position: "relative", + flex: 1, + justifyContent: "center", + alignItems: "center", }, - // Graphics graphicCircleLarge: { position: "absolute", - top: -20, - right: -20, - width: 80, - height: 80, - borderRadius: 40, - backgroundColor: "rgba(124, 80, 80, 0.42)", - }, - graphicCircleMedium: { - position: "absolute", - bottom: 30, - left: -15, - width: 60, - height: 60, - borderRadius: 30, - backgroundColor: "rgba(122, 41, 41, 0.39)", + top: -30, + right: -40, + width: 100, + height: 100, + borderRadius: 50, + backgroundColor: "rgba(255, 255, 255, 0.1)", }, graphicCircleSmall: { position: "absolute", - bottom: -10, - right: 40, - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: "rgba(207, 110, 80, 0.25)", - }, - graphicTriangleTop: { - position: "absolute", - top: 0, - left: 0, - width: 0, - height: 0, - borderStyle: "solid", - borderRightWidth: 60, - borderTopWidth: 60, - borderRightColor: "transparent", - borderTopColor: "rgba(143, 62, 62, 0.31)", - }, - graphicTriangleBottom: { - position: "absolute", - bottom: 0, - right: 0, - width: 0, - height: 0, - borderStyle: "solid", - borderLeftWidth: 40, - borderBottomWidth: 40, - borderLeftColor: "transparent", - borderBottomColor: "rgba(172, 51, 51, 0.27)", + bottom: -20, + left: -25, + width: 70, + height: 70, + borderRadius: 35, + backgroundColor: "rgba(255, 255, 255, 0.08)", }, content: { - flexDirection: "row", // stack vertically - alignItems: "center", // center horizontally - justifyContent: "center", // center vertically padding: 20, position: "relative", zIndex: 1, - alignSelf: "center", - flex:1 - } - , + flex: 1, + justifyContent: "center", + alignItems: "center", + }, icon: { - marginRight: 12, + marginBottom: 12, }, textContainer: { - // alignItems: "center", // centers title and subtitle + alignItems: 'center', }, title: { fontSize: 18, - fontWeight: "700", + fontWeight: "bold", color: "#fff", - marginBottom: 4, - textTransform:'uppercase' - // textAlign: "center", + textTransform: 'uppercase', + letterSpacing: 1, + textAlign: 'center', }, subtitle: { - fontSize: 14, - color: colors.primary, + fontSize: 13, + color: colors.white, + opacity: 0.9, fontWeight: "500", textAlign: "center", + marginTop: 4, }, }); diff --git a/src/components/common/Custom.tsx b/src/components/common/Custom.tsx index 5855ceb..3585eb7 100644 --- a/src/components/common/Custom.tsx +++ b/src/components/common/Custom.tsx @@ -15,10 +15,12 @@ type CustomInputProps = TextInputProps & { label?: string; icon?: IoniconsIconName; error?:string + value?: string | number; }; const CustomInput: React.FC = ({ label, + value, icon, style, error, @@ -28,7 +30,7 @@ const CustomInput: React.FC = ({ {label ? {label} : null} - {icon && } + {icon && } = ({ // --- Styles --- const styles = StyleSheet.create({ - inputContainer: { marginBottom: 12 }, + inputContainer: { marginBottom: 12,elevation:5 }, inputLabel: { fontSize: 14, fontWeight: "500", color: colors.textDark, marginBottom: 6 }, inputWrapper: { flexDirection: "row", @@ -97,9 +99,7 @@ const styles = StyleSheet.create({ }, input: { flex: 1, - borderWidth: 1, - borderColor: colors.textLight, - borderRadius: 10, + borderRadius: 15, padding: 12, paddingLeft: 12, backgroundColor: colors.white, @@ -107,6 +107,7 @@ const styles = StyleSheet.create({ fontSize: 15, }, button: { + elevation:5, paddingVertical: 12, borderRadius: 12, alignItems: "center", diff --git a/src/screens/LoginScreen.tsx b/src/screens/LoginScreen.tsx index 5b37f77..3a44f1b 100644 --- a/src/screens/LoginScreen.tsx +++ b/src/screens/LoginScreen.tsx @@ -1,3 +1,5 @@ +// src/screens/LoginScreen.tsx + import React, { useState, useRef, useEffect } from "react"; import { View, @@ -5,7 +7,6 @@ import { TextInput, StyleSheet, TouchableOpacity, - Alert, KeyboardAvoidingView, Platform, Animated, @@ -17,175 +18,268 @@ import axios from "axios"; import { useNavigation } from "@react-navigation/native"; import type { StackNavigationProp } from "@react-navigation/stack"; import { RootStackParamList } from "../navigation/AppNavigator"; -import { CustomButton, CustomInput } from "../components/common/Custom"; -import colors from "../components/colors"; - -const theme = { - primary: "#111111", - accent: colors.primary, - background: "#F9F9F9", - surface: "#FFFFFF", - text: "#1A1A1A", - subText: "#6B6B6B", - outline: "#E5E5E5", - error: "#E53935", - success: "#2E7D32", -}; +import LinearGradient from "react-native-linear-gradient"; +import Ionicons from '@react-native-vector-icons/ionicons'; +import CustomAlert from "../components/CostomAlart"; +import colors from "../components/colors"; // Centralized colors from your file export default function LoginScreen() { const navigation = useNavigation>(); const [mobile, setMobile] = useState(""); const [loading, setLoading] = useState(false); - // animations + const [alertInfo, setAlertInfo] = useState({ + visible: false, + title: "", + message: "", + buttons: [] as { text: string; onPress: () => void; style?: "cancel" | "destructive" | "default" }[], + alertType: 'info' as 'info' | 'success' | 'error', + }); + const fade = useRef(new Animated.Value(0)).current; - const slide = useRef(new Animated.Value(24)).current; + const slide = useRef(new Animated.Value(30)).current; const ctaScale = useRef(new Animated.Value(1)).current; useEffect(() => { Animated.parallel([ - Animated.timing(fade, { toValue: 1, duration: 600, useNativeDriver: true }), - Animated.timing(slide, { toValue: 0, duration: 600, useNativeDriver: true }), + Animated.timing(fade, { toValue: 1, duration: 800, useNativeDriver: true }), + Animated.spring(slide, { toValue: 0, friction: 5, tension: 40, useNativeDriver: true }), ]).start(); }, []); - const handleContinue = async () => { - if (mobile.length === 10) { - setLoading(true); - try { - const res = await axios.get(LOGIN_URL, { - params: { mobile }, - }); + const showAlert = ( + title: string, + message: string, + buttons: { text: string; onPress: () => void; style?: "cancel" | "destructive" | "default" }[], + alertType: 'info' | 'success' | 'error' = 'info' + ) => { + setAlertInfo({ visible: true, title, message, buttons, alertType }); + }; + + const hideAlert = () => { + setAlertInfo({ ...alertInfo, visible: false }); + }; - console.log("OTP sent response:", res.data); - - if (res.data.statusCode === 200) { - navigation.navigate("OtpVarify", { mobile }); - } else { - Alert.alert("Error", res.data.message || "Failed to send OTP"); + const handleContinue = async () => { + if (mobile.length === 10) { + setLoading(true); + try { + // FIX: Used the imported LOGIN_URL constant instead of a string literal + const res = await axios.get(LOGIN_URL, { params: { mobile } }); + console.log("Login response:", res.data); + if (res.data.statusCode === 200) { + navigation.navigate("OtpVarify", { mobile }); + } else { + showAlert( + "Login Failed", + res.data.message || "Could not send OTP.", + [{ text: "Try Again", onPress: hideAlert }], + 'error' + ); + } + } catch (error: any) { + console.error("Login error:", error); + showAlert( + "An Error Occurred", + "Failed to send OTP. Please check your connection and try again.", + [{ text: "OK", onPress: hideAlert }], + 'error' + ); + } finally { + setLoading(false); } - } catch (error: any) { - console.error("Login error:", error); - - if (axios.isAxiosError(error)) { - console.log("Error message:", error.message); - console.log("Error response:", error.response?.data); - console.log("Error status:", error.response?.status); - console.log("Error headers:", error.response?.headers); - } else { - console.log("Unexpected error:", error); - } - - Alert.alert("Error", "Failed to send OTP. Please try again."); - } finally { - setLoading(false); + } else { + showAlert( + "Invalid Number", + "Please enter a valid 10-digit mobile number.", + [{ text: "Got it", onPress: hideAlert }], + 'info' + ); } - } else { - Alert.alert("Please enter a valid 10-digit mobile number"); - } -}; + }; -return ( - - - - {/* Top content */} - - CircleCollect - Welcome Back 👋 - - Enter your mobile number to sign in and continue. - - - + - - - + + + + + - {/* Bottom Button */} - - + + + CircleCollect + Welcome! + + Glad to see you again. Let's get you signed in to your community. + + + - - By continuing, you agree to our{" "} - - Terms & Privacy - - - - -); + + + + + + + + + + + + {loading ? ( + + ) : ( + Continue with Mobile + )} + + + Your privacy is our priority. Your information is always secure. + + + + + + + + ); } const styles = StyleSheet.create({ - container: { flex: 1, backgroundColor: theme.background, padding: 20 }, - topSection: { flex: 1, justifyContent: "center" }, + gradientContainer: { + flex: 1, + }, + container: { + flex: 1, + padding: 24, + justifyContent: "space-between", + }, + shape: { + position: 'absolute', + borderRadius: 1000, + opacity: 0.6, + }, + shape1: { + width: 400, + height: 400, + backgroundColor: colors.pastelPink, + top: -150, + left: -100, + }, + shape2: { + width: 300, + height: 300, + backgroundColor: colors.pastelBlue, + bottom: -100, + right: -120, + }, + shape3: { + width: 200, + height: 200, + backgroundColor: colors.pastelGreen, + bottom: '40%', + left: -80, + opacity: 0.5 + }, + topSection: { + flex: 0.8, + justifyContent: "center", + alignItems: 'center' + }, + formSection: { + flex: 1, + justifyContent: 'flex-start' + }, brand: { - fontSize: 30, - fontWeight: "700", - color: theme.accent, - marginBottom: 24, + fontSize: 24, + fontWeight: "600", + color: colors.primary, + textAlign: "center", + letterSpacing: 1.5, + marginBottom: 16, }, title: { - fontSize: 26, - fontWeight: "800", - color: theme.text, - marginBottom: 6, + fontSize: 38, + fontWeight: "bold", + color: colors.textDark, + textAlign: "center", + marginBottom: 12, }, subtitle: { - fontSize: 15, - color: theme.subText, - marginBottom: 30, - lineHeight: 22, + fontSize: 16, + color: colors.textLight, + textAlign: "center", + lineHeight: 24, + maxWidth: 320, }, - inputWrapper: { gap: 8 }, - inputLabel: { - fontSize: 14, - fontWeight: "600", - color: theme.text, + inputContainer: { + flexDirection: "row", + alignItems: "center", + backgroundColor: colors.white, + borderRadius: 16, + borderWidth: 1, + borderColor: colors.inputBorder, + paddingHorizontal: 16, + marginTop: 32, + shadowColor: colors.black, + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.05, + shadowRadius: 10, + elevation: 3, + }, + inputIcon: { + marginRight: 12, }, input: { - backgroundColor: theme.surface, - borderRadius: 14, - padding: 14, + flex: 1, + height: 58, fontSize: 16, - color: theme.text, - borderWidth: 1, - borderColor: theme.outline, + color: colors.textDark, }, bottomSection: { - marginBottom: 30, + paddingBottom: Platform.OS === "ios" ? 20 : 10, + paddingHorizontal: 10 }, button: { - backgroundColor: theme.primary, + backgroundColor: colors.primary, paddingVertical: 18, - borderRadius: 14, + borderRadius: 30, alignItems: "center", justifyContent: "center", + flexDirection: "row", + shadowColor: colors.primary, + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.3, + shadowRadius: 15, + elevation: 8, + }, + buttonText: { + color: colors.white, + fontWeight: "700", + fontSize: 16, }, - buttonText: { color: "#fff", fontWeight: "700", fontSize: 16 }, footerText: { textAlign: "center", - color: theme.subText, + color: colors.textLight, fontSize: 12, - marginTop: 14, + marginTop: 20, }, }); diff --git a/src/screens/OtpVarificationScreen.tsx b/src/screens/OtpVarificationScreen.tsx index 0bd381c..61fabff 100644 --- a/src/screens/OtpVarificationScreen.tsx +++ b/src/screens/OtpVarificationScreen.tsx @@ -13,41 +13,54 @@ import { TextInputKeyPressEventData, KeyboardAvoidingView, StatusBar, - Alert, - ToastAndroid, } from "react-native"; import { RootStackParamList } from "../navigation/AppNavigator"; import * as Keychain from "react-native-keychain"; -import { BASE_URL, LOGIN_URL, VARIFY_OTP_URL } from "../utils/ApiUrls"; +import { LOGIN_URL, VARIFY_OTP_URL } from "../utils/ApiUrls"; import colors from "../components/colors"; -import { fetchUserProfile } from "../utils/HelperFunction"; - -const theme = { - primary: "#111111", - accent: colors.primary, - background: "#F9F9F9", - text: "#1A1A1A", - subText: "#6B6B6B", - outline: "#E5E5E5", -}; +import LinearGradient from "react-native-linear-gradient"; +import CustomAlert from "../components/CostomAlart"; const CELL_COUNT = 6; type OtpVerifyRouteProp = RouteProp; +interface AlertButton { + text: string; + onPress: () => void; + style?: "cancel" | "destructive" | "default"; +} + export default function OtpVerificationScreen() { const [code, setCode] = useState(Array(CELL_COUNT).fill("")); const [timer, setTimer] = useState(30); const [isResending, setIsResending] = useState(false); + const [alertConfig, setAlertConfig] = useState<{ + visible: boolean; + title: string; + message: string; + buttons: AlertButton[]; + alertType: 'error' | 'success' | 'info'; + }>({ + visible: false, + title: "", + message: "", + buttons: [], + alertType: "info", + }); + const inputs = useRef>([]); const route = useRoute(); const { mobile } = route.params; const navigation = useNavigation(); - // animations + + // Refs for auto-closing logic + const successActionRef = useRef<(() => void) | null>(null); + const successTimerRef = useRef(null); + const fade = useRef(new Animated.Value(0)).current; const slide = useRef(new Animated.Value(24)).current; const ctaScale = useRef(new Animated.Value(1)).current; - useEffect(() => { Animated.parallel([ Animated.timing(fade, { toValue: 1, duration: 600, useNativeDriver: true }), @@ -55,88 +68,133 @@ export default function OtpVerificationScreen() { ]).start(); }, [fade, slide]); - // Countdown useEffect(() => { if (timer <= 0) return; - const interval = setInterval(() => { - setTimer((prev) => prev - 1); - }, 1000); + const interval = setInterval(() => setTimer((prev) => prev - 1), 1000); return () => clearInterval(interval); }, [timer]); + const hideAlert = () => { + if (successTimerRef.current) { + clearTimeout(successTimerRef.current); + successTimerRef.current = null; + } + setAlertConfig(prev => ({ ...prev, visible: false })); + }; + + const triggerAlert = ( + title: string, + message: string, + buttons: AlertButton[], + alertType: 'error' | 'success' | 'info' = 'info', + autoCloseAction?: () => void + ) => { + setAlertConfig({ visible: true, title, message, buttons, alertType }); + + if (alertType === 'success' && autoCloseAction) { + successActionRef.current = autoCloseAction; + successTimerRef.current = setTimeout(() => { + successActionRef.current?.(); + }, 2000); // Auto-close after 2 seconds + } + }; + const saveToken = async (token: string) => { try { - await Keychain.setGenericPassword("auth", token, { - accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED, - }); + await Keychain.setGenericPassword("auth", token, { accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED }); console.log("✅ Token saved securely"); } catch (error) { console.error("❌ Error saving token:", error); } }; - const onSubmit = async (otp: string, mobile: string) => { - try { - const payload = { mobile, otp }; - const res = await axios.post( - VARIFY_OTP_URL, - payload, - { - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - } - ); - - console.log("✅ OTP Verified:", res.data); - - if (res.data?.statusCode === 200) { - const { jwt, role } = res.data?.data || {}; - - saveToken(jwt); - - navigation.navigate("Home"); - - ToastAndroid.show("OTP Verified Successfully!", ToastAndroid.SHORT); + if (otp.length !== CELL_COUNT) { + triggerAlert( + 'Incomplete Code', + 'Please enter all 6 digits of the OTP.', + [{ text: 'OK', onPress: hideAlert }], + 'error' + ); + return; } - } catch (err: any) { - console.error("❌ OTP Verification Error:", err?.response?.data || err.message); - ToastAndroid.show( - err?.response?.data?.message || "Invalid OTP. Please try again.", - ToastAndroid.SHORT - ); - } -}; + try { + const res = await axios.post(VARIFY_OTP_URL, { mobile, otp }, { + headers: { "Content-Type": "application/json", Accept: "application/json" }, + }); + if (res.data?.statusCode === 200) { + const { jwt } = res.data?.data || {}; + await saveToken(jwt); + + let hasActionRun = false; + const successAction = () => { + if (hasActionRun) return; + hasActionRun = true; + hideAlert(); + navigation.navigate("Home"); + }; + + triggerAlert( + 'Success!', + 'OTP verified successfully. Redirecting...', + [{ text: 'OK', onPress: successAction }], + 'success', + successAction + ); + } + } catch (err: any) { + console.error("❌ OTP Verification Error:", err?.response?.data || err.message); + triggerAlert( + 'Verification Failed', + err?.response?.data?.message || "Invalid OTP. Please try again.", + [{ text: 'Try Again', onPress: hideAlert, style: 'cancel' }], + 'error' + ); + } + }; const resendOtp = async () => { try { setIsResending(true); - setTimer(30); // reset timer - - const res = await axios.get( - LOGIN_URL + mobile, - { headers: { "Content-Type": "application/json", Accept: "*/*" } } - ); - - console.log("📩 OTP Resent:", res); + setTimer(30); + await axios.get(`${LOGIN_URL}?mobile=${mobile}`, { + headers: { "Content-Type": "application/json", Accept: "*/*" }, + }); + setCode(Array(CELL_COUNT).fill("")); inputs.current[0]?.focus(); - ToastAndroid.show("OTP Sent", ToastAndroid.SHORT); + + let hasActionRun = false; + const successAction = () => { + if (hasActionRun) return; + hasActionRun = true; + hideAlert(); + }; + + triggerAlert( + 'OTP Sent', + 'A new code has been sent to your mobile number.', + [{ text: 'OK', onPress: successAction }], + 'success', + successAction + ); } catch (err: any) { console.error("❌ Resend OTP Error:", err?.response?.data || err.message); - ToastAndroid.show("Failed to resend OTP. Try again later.", ToastAndroid.SHORT); + triggerAlert( + 'Error', + 'Failed to resend OTP. Try again later.', + [{ text: 'OK', onPress: hideAlert, style: 'cancel' }], + 'error' + ); } finally { setIsResending(false); } }; const submitIfComplete = (arr: string[]) => { - const joined = arr.join(""); - if (joined.length === CELL_COUNT) { - onSubmit(joined, mobile); + if (arr.join("").length === CELL_COUNT) { + onSubmit(arr.join(""), mobile); } }; @@ -155,13 +213,14 @@ export default function OtpVerificationScreen() { updateIndex(0, digits); return; } - const next = Array(CELL_COUNT) - .fill("") - .map((_, i) => digits[i] ?? ""); + const next = Array(CELL_COUNT).fill("").map((_, i) => digits[i] ?? ""); setCode(next); const firstEmpty = next.findIndex((c) => !c); - if (firstEmpty >= 0) inputs.current[firstEmpty]?.focus(); - else inputs.current[CELL_COUNT - 1]?.blur(); + if (firstEmpty >= 0) { + inputs.current[firstEmpty]?.focus(); + } else { + inputs.current[CELL_COUNT - 1]?.blur(); + } submitIfComplete(next); }; @@ -172,107 +231,71 @@ export default function OtpVerificationScreen() { }; return ( - - + + + + + - {/* Top Section */} - - Verify Code 🔒 - - We’ve sent a 6-digit verification code to {mobile}. - + + Verify Your Code 🔒 + We’ve sent a 6-digit verification code to +91 {mobile}. - - {Array.from({ length: CELL_COUNT }).map((_, i) => ( - { - inputs.current[i] = r; - }} - style={[styles.cell, code[i] ? styles.cellFilled : null]} - keyboardType="number-pad" - maxLength={1} - value={code[i]} - onChangeText={(t) => (i === 0 ? handleFirstCellChange(t) : updateIndex(i, t))} - onKeyPress={(e) => handleKeyPress(i, e)} - placeholder="•" - placeholderTextColor="#BDBDBD" - textContentType="oneTimeCode" - /> - ))} - - + + {Array.from({ length: CELL_COUNT }).map((_, i) => ( + { inputs.current[i] = r; }} + style={[styles.cell, code[i] ? styles.cellFilled : null]} + keyboardType="number-pad" + maxLength={i === 0 ? CELL_COUNT : 1} + value={code[i]} + onChangeText={(t) => (i === 0 ? handleFirstCellChange(t) : updateIndex(i, t))} + onKeyPress={(e) => handleKeyPress(i, e)} + placeholder="•" + placeholderTextColor="#BDBDBD" + textContentType="oneTimeCode" + /> + ))} + + - {/* Bottom Section */} - - - Animated.spring(ctaScale, { toValue: 0.97, useNativeDriver: true }).start() - } - onPressOut={() => - Animated.spring(ctaScale, { toValue: 1, useNativeDriver: true }).start() - } - onPress={() => onSubmit(code.join(""), mobile)} - style={styles.button} - > - Continue - - - {timer > 0 ? ( - Resend code in 00:{timer.toString().padStart(2, "0")} - ) : ( - - - {isResending ? "Resending..." : "Resend Code"} - + + Animated.spring(ctaScale, { toValue: 0.97, useNativeDriver: true }).start()} + onPressOut={() => Animated.spring(ctaScale, { toValue: 1, useNativeDriver: true }).start()} + onPress={() => onSubmit(code.join(""), mobile)} + style={styles.button} + > + Verify & Continue - )} - - + + {timer > 0 ? ( + Resend code in 00:{timer.toString().padStart(2, "0")} + ) : ( + + + {isResending ? "Resending..." : "Resend Code"} + + + )} + + + ); } const styles = StyleSheet.create({ - container: { flex: 1, backgroundColor: theme.background, padding: 20 }, - topSection: { flex: 1, justifyContent: "center" }, - title: { fontSize: 26, fontWeight: "800", color: theme.text, marginBottom: 8 }, - subtitle: { - fontSize: 15, - color: theme.subText, - marginBottom: 24, - lineHeight: 22, - }, - otpRow: { flexDirection: "row", justifyContent: "space-between" }, - cell: { - width: 50, - height: 58, - borderRadius: 12, - borderWidth: 1, - borderColor: theme.outline, - backgroundColor: "#fff", - textAlign: "center", - fontSize: 20, - color: theme.text, - }, - cellFilled: { borderColor: "#D1D1D1" }, - bottomSection: { marginBottom: 30 }, - button: { - backgroundColor: colors.primary, - paddingVertical: 18, - borderRadius: 14, - alignItems: "center", - justifyContent: "center", - }, - buttonText: { color: "#000", fontWeight: "700", fontSize: 16 }, - footerText: { - textAlign: "center", - color: theme.subText, - fontSize: 13, - marginTop: 14, - }, + gradientContainer: { flex: 1 }, + container: { flex: 1, padding: 24, justifyContent: "space-between" }, + topSection: { flex: 1, justifyContent: "center", alignItems: 'center' }, + title: { fontSize: 28, fontWeight: "bold", color: colors.textDark, textAlign: 'center', marginBottom: 12 }, + subtitle: { fontSize: 16, color: colors.textLight, textAlign: 'center', marginBottom: 32, lineHeight: 24, maxWidth: 300 }, + otpRow: { flexDirection: "row", justifyContent: "space-between", width: '100%', paddingHorizontal: 10 }, + cell: { width: 48, height: 56, borderRadius: 12, borderWidth: 1.5, borderColor: colors.inputBorder, backgroundColor: colors.white, textAlign: "center", fontSize: 22, fontWeight: '700', color: colors.textDark, shadowColor: "#000", shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.08, shadowRadius: 8, elevation: 3 }, + cellFilled: { borderColor: colors.primary, backgroundColor: '#F7F2FF' }, + bottomSection: { paddingBottom: Platform.OS === "ios" ? 20 : 10 }, + button: { backgroundColor: colors.primary, paddingVertical: 18, borderRadius: 30, alignItems: "center", justifyContent: "center", shadowColor: colors.primary, shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.3, shadowRadius: 15, elevation: 8 }, + buttonText: { color: colors.white, fontWeight: "700", fontSize: 16 }, + footerText: { textAlign: "center", color: colors.textLight, fontSize: 14, marginTop: 20 }, }); diff --git a/src/screens/home/Home.tsx b/src/screens/home/Home.tsx index 25cef32..58ca3a6 100644 --- a/src/screens/home/Home.tsx +++ b/src/screens/home/Home.tsx @@ -9,23 +9,20 @@ import { Image, Alert, FlatList, - ListRenderItem, // Import ListRenderItem for better typing + ListRenderItem, } from "react-native"; import AppView from "../../components/AppView"; import colors from "../../components/colors"; import { useDispatch, useSelector } from "react-redux"; import { useNavigation } from "@react-navigation/native"; import { PROFILE_URL } from "../../utils/ApiUrls"; -import * as Keychain from "react-native-keychain"; import { setUserData } from "../../redux/userSlice"; import { TabNavigationProp } from "../../navigation/BottomTabs"; -import GroupsTabs from "./GroupsTabs"; import UserProfileStatus from "./UserProfileStatus"; -import UserHome from "./user-home/UserHome"; import AnimatedCard from "../../components/common/AnimatedCard"; import { IoniconsIconName } from "@react-native-vector-icons/ionicons"; +import { apiCall } from "../../utils/ApiHelper"; -// Enable layout animation for Android if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) { UIManager.setLayoutAnimationEnabledExperimental(true); } @@ -37,212 +34,108 @@ type UserProfile = { lastName: string | null; imageBlob: string | null; role?: string; -} -// --- TYPE DEFINITIONS --- +}; + interface ActionItem { id: string; title: string; action: string; tab?: "My Groups" | "Joined Groups" | "Requests" | "Your Requests"; - iconName?: IoniconsIconName; backOne?: string; backTwo?: string; - subtitle?: string + subtitle?: string; } - - -// Organizer Actions +// Updated action items with a prettier pastel palette const organizerActions: ActionItem[] = [ - { - id: "1", - title: "My Groups", - subtitle: "Manage your own groups", - action: "NAVIGATE_MANAGEMENT", - tab: "My Groups", - iconName: "people-outline", - backOne: "#4facfe", - backTwo: "#00f2fe", - }, - { - id: "2", - title: "Joined Groups", - subtitle: "View groups you’ve joined", - action: "NAVIGATE_MANAGEMENT", - tab: "Joined Groups", - iconName: "person-outline", - backOne: "#43e97b", - backTwo: "#38f9d7", - }, - { - id: "3", - title: "Requests", - subtitle: "Check group requests", - action: "NAVIGATE_MANAGEMENT", - tab: "Requests", - iconName: "notifications-outline", - backOne: "#fa709a", - backTwo: "#fee140", - }, + { id: "1", title: "My Groups", subtitle: "Manage your groups", action: "NAVIGATE_MANAGEMENT", tab: "My Groups", iconName: "people-circle-outline", backOne: '#decbfcff', backTwo: '#B799FF' }, + { id: "2", title: "Joined Groups", subtitle: "View member groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "people-outline", backOne: '#D7E9F7', backTwo: '#82AAE3' }, + { id: "3", title: "Requests", subtitle: "Check new requests", action: "NAVIGATE_MANAGEMENT", tab: "Requests", iconName: "notifications-outline", backOne: '#DFF6DD', backTwo: '#88D18A' }, ]; -// User Actions const userActions: ActionItem[] = [ - { - id: "1", - title: "Joined Groups", - subtitle: "See your joined groups", - action: "NAVIGATE_MANAGEMENT", - tab: "Joined Groups", - iconName: "person-outline", - backOne: "#43e97b", - backTwo: "#38f9d7", - }, - { - id: "2", - title: "Your Requests", - subtitle: "Track your group requests", - action: "NAVIGATE_MANAGEMENT", - tab: "Your Requests", - iconName: "mail-outline", - backOne: "#ff9a9e", - backTwo: "#fad0c4", - }, - { - id: "3", - title: "Transaction", - subtitle: "View your transaction history", - action: "TRANSACTION", - iconName: "calculator-outline", - backOne: "#4facfe", - backTwo: "#00f2fe", - }, + { id: "1", title: "Joined Groups", subtitle: "See your groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "person-outline", backOne: '#D7E9F7', backTwo: '#82AAE3' }, + { id: "2", title: "Your Requests", subtitle: "Track your requests", action: "NAVIGATE_MANAGEMENT", tab: "Your Requests", iconName: "mail-open-outline", backOne: '#FFF4D2', backTwo: '#FFB344' }, + { id: "3", title: "Transactions", subtitle: "View your history", action: "TRANSACTION", iconName: "receipt-outline", backOne: '#decbfcff', backTwo: '#B799FF' }, ]; - const Home: React.FC = () => { const user = useSelector((state: any) => state.user); const navigation = useNavigation(); const dispatch = useDispatch(); - // --- FIXED: Conditional logic moved inside the component --- const actions = user.role === 'ORGANIZER' ? organizerActions : userActions; - const [apiUser, setApiUser] = useState(null) + const [apiUser, setApiUser] = useState(null); - const fetchUserProfile = async () => { - try { - const credentials = await Keychain.getGenericPassword(); - if (!credentials) { - return; - } - const token = credentials.password; - - console.log("token : ", token) - const response = await fetch( - PROFILE_URL, - { - method: "GET", - headers: { - Accept: "*/*", - Authorization: `Bearer ${token}`, - }, + useEffect(() => { + const fetchUserProfile = async () => { + try { + const result = await apiCall(PROFILE_URL, "GET") as any; + if (result.status === "success") { + setApiUser(result.data); + dispatch(setUserData({ ...result.data, profileStatus: true })); } - ); - - const result = await response.json(); - console.log("👤 Profile Response:", result); - if (result.status === "success") { - setApiUser(result.data); - dispatch( - setUserData({ - id: result.data.id, - userId: result.data.userId, - username: result.data.username, - firstName: result.data.firstName, - lastName: result.data.lastName, - gender: result.data.gender, - mobile: result.data.mobile, - email: result.data.email, - address: result.data.address, - bankAccountNumber: result.data.bankAccountNumber, - bankName: result.data.bankName, - branchCode: result.data.branchCode, - profilePicture: result.data.filePath, - filePath: result.data.filePath, - imageBlob: result.data.imageBlob, - role: result.data.role, - organizerId: result.data.organizerId, - organizerStatus: result.data.organizerStatus, - profileStatus: true, - }) - ); + } catch (error) { + console.error("❌ Error fetching profile:", error); } - } catch (error) { - console.error("❌ Error fetching profile:", error); - } - }; - - useEffect(() => { + }; + const unsubscribe = navigation.addListener('focus', fetchUserProfile); fetchUserProfile(); - }, []); + return unsubscribe; + }, [navigation, dispatch]); - - useEffect(() => { - fetchUserProfile(); - }, []); - - // --- REFACTORED: Simplified action handler --- const handleActionPress = (item: ActionItem) => { if (item.action === "NAVIGATE_MANAGEMENT" && item.tab) { navigation.navigate('Management', { actionTab: item.tab }); } else if (item.action === "TRANSACTION") { - navigation.navigate("TransactionList" as never) - } else if (item.action === "ACTION_4") { - Alert.alert("Action 4 pressed"); + navigation.navigate("TransactionList" as never); } else { Alert.alert("Unknown action", item.title); } }; - // Render function for each grid item const renderGridItem: ListRenderItem = ({ item }) => ( - - handleActionPress(item)} - /> + + handleActionPress(item)} + /> + ); + const getProfileImageUri = () => { + const blob = user.imageBlob || apiUser?.imageBlob; + return blob ? { uri: `data:image/jpeg;base64,${blob}` } : require('../../assets/images/placeholder.png'); + }; + return ( - Hello, {user.firstName || apiUser?.firstName} {user.lastName || apiUser?.lastName} + + Hello, + {user.firstName || apiUser?.firstName || 'User'} + navigation.navigate("Profile" as never)}> - + - {/* Status */} + - {/* {user?.role === "USER" || apiUser?.role === "USER" ? : - } */} + + Quick Actions + item.id} - // columnWrapperStyle={styles.row} - // contentContainerStyle={{ paddingHorizontal: 8 }} + numColumns={2} + contentContainerStyle={{ paddingHorizontal: 8 }} /> ); @@ -253,48 +146,41 @@ export default Home; const styles = StyleSheet.create({ container: { flex: 1, - backgroundColor: '#F4F6F8' + backgroundColor: colors.white, // Set background to white }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", - marginBottom: 12, + paddingHorizontal: 20, + paddingTop: 24, + paddingBottom: 16, }, - headerTitle: { + greeting: { fontSize: 22, - fontWeight: "600", - color: colors.Home, + color: colors.textSecondary, }, - row: { + userName: { + fontSize: 28, + fontWeight: 'bold', + color: colors.textDark, + }, + profileImage: { + width: 50, + height: 50, + borderRadius: 25, + borderColor: colors.pastelPink, // Using pastelPink for border + borderWidth: 2, + }, + sectionTitle: { + fontSize: 20, + fontWeight: '600', + color: colors.textDark, + paddingHorizontal: 20, + marginBottom: 8, + }, + cardWrapper: { flex: 1, - justifyContent: "space-around", - }, - greeting: { fontSize: 22, fontWeight: "600", color: colors.pastelPink }, - gridButton: { - flex: 1, - margin: 8, - backgroundColor: "#FFFFFF", - borderRadius: 12, - padding: 16, - alignItems: "center", - shadowColor: "#000", - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.1, - shadowRadius: 5, - elevation: 4, - }, - gridIcon: { - width: 60, - height: 60, - marginBottom: 12, - borderRadius: 8, - backgroundColor: '#E0E0E0', - }, - gridLabel: { - fontSize: 16, - fontWeight: "500", - color: colors.Home, - textAlign: "center", + marginHorizontal: 8, }, }); diff --git a/src/screens/management/EditGroupScreen.tsx b/src/screens/management/EditGroupScreen.tsx index cf0e5f4..b2894bf 100644 --- a/src/screens/management/EditGroupScreen.tsx +++ b/src/screens/management/EditGroupScreen.tsx @@ -154,10 +154,10 @@ const EditGroupScreen: React.FC = ({ route }) => { } }, [groupId]); const getPaymentStatus = async()=>{ - const response = await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/payments/group/${groupId}/payment/paid`, 'GET') as { status: string; data?: { currentCycle: number ,status: boolean }; message?: string }; + const response = await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/payments/group/${groupId}/payment/paid`, 'GET') as { status: string; data?: { currentCycle: number ,allPaid: boolean }; message?: string }; console.log("paymentStatus",response) if (response.status === 'success') { - setPaymentStatus(response.data?.status || false); + setPaymentStatus(response.data?.allPaid || false); setCurrentCycle(response.data?.currentCycle || null); } } diff --git a/src/screens/profile/Profile.tsx b/src/screens/profile/Profile.tsx index 0400b69..c0d23e2 100644 --- a/src/screens/profile/Profile.tsx +++ b/src/screens/profile/Profile.tsx @@ -660,7 +660,7 @@ const Profile = () => { onPress={() => setEditing(false)} icon="close" style={styles.cancelButton} - buttonBackground="" + buttonBackground={colors.white } /> @@ -756,12 +756,14 @@ const styles = StyleSheet.create({ width: "80%", paddingHorizontal: 10, borderRadius: 25, + elevation: 5, + }, detailsSection: { marginBottom: "40%", }, sectionTitle: { - fontSize: 18, + fontSize: 18, fontWeight: "700", color: "#1e293b", // marginBottom: 16, @@ -777,6 +779,7 @@ const styles = StyleSheet.create({ }, detailIcon: { marginRight: 12, + elevation:5 }, detailLabel: { fontSize: 12, @@ -789,7 +792,9 @@ const styles = StyleSheet.create({ fontWeight: "500", }, editButton: { - paddingHorizontal: 8, + elevation:5, + paddingHorizontal: 10, + borderRadius: 15, }, editSection: { marginBottom: '100%',