theme
This commit is contained in:
@@ -1,36 +1,39 @@
|
|||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { StyleSheet, useColorScheme } from 'react-native';
|
import { StyleSheet, useColorScheme } from 'react-native';
|
||||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
import { PaperProvider } from 'react-native-paper';
|
import { PaperProvider } from 'react-native-paper';
|
||||||
import AppNavigator from './src/navigation/AppNavigator';
|
import AppNavigator from './src/navigation/AppNavigator';
|
||||||
import notifee from '@notifee/react-native';
|
import notifee from '@notifee/react-native';
|
||||||
import { backgroundHandler, foregroundListener, requestPermission, setupFirebaseHandlers, setupNotificationPressHandlers, tokenRefreshHandler } from './src/utils/firebase/firebaseServices';
|
|
||||||
|
import {
|
||||||
|
backgroundHandler,
|
||||||
|
foregroundListener,
|
||||||
|
requestPermission,
|
||||||
|
setupFirebaseHandlers,
|
||||||
|
setupNotificationPressHandlers,
|
||||||
|
tokenRefreshHandler,
|
||||||
|
} from './src/utils/firebase/firebaseServices';
|
||||||
|
|
||||||
|
|
||||||
|
import { dark, light } from './src/theme/theme';
|
||||||
|
import { ThemeProvider} from './src/theme/ThemeProvider';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const isDarkMode = useColorScheme() === 'dark';
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 🔹 Ask for permission
|
|
||||||
requestPermission();
|
requestPermission();
|
||||||
|
|
||||||
// 🔹 Handle background + quit state
|
|
||||||
backgroundHandler();
|
backgroundHandler();
|
||||||
setupFirebaseHandlers()
|
setupFirebaseHandlers();
|
||||||
setupNotificationPressHandlers()
|
setupNotificationPressHandlers();
|
||||||
|
|
||||||
// 🔹 Listen for foreground messages
|
|
||||||
const unsubscribe = foregroundListener();
|
const unsubscribe = foregroundListener();
|
||||||
|
|
||||||
// 🔹 Listen for token refresh
|
|
||||||
const unsubscribeRefresh = tokenRefreshHandler();
|
const unsubscribeRefresh = tokenRefreshHandler();
|
||||||
|
|
||||||
// 🔹 Create default notification channel (Android)
|
|
||||||
notifee.createChannel({
|
notifee.createChannel({
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'Default Channel',
|
name: 'Default Channel',
|
||||||
importance: 4, // HIGH
|
importance: 4,
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -39,19 +42,23 @@ function App() {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<PaperProvider>
|
<ThemeProvider>
|
||||||
<AppNavigator />
|
<PaperProvider >
|
||||||
</PaperProvider>
|
<AppNavigator />
|
||||||
|
</PaperProvider>
|
||||||
|
</ThemeProvider>
|
||||||
</SafeAreaProvider>
|
</SafeAreaProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"migIndex": 1,
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Black.ttf",
|
||||||
|
"sha1": "bede9c89e905ae0b91404768e1167e3e5d3c9c8e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-BlackItalic.ttf",
|
||||||
|
"sha1": "5b27538c43c1afcd5b4a8547854522a805f4c302"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Bold.ttf",
|
||||||
|
"sha1": "e50cf9134308e37008cbd39da1dc637aef022641"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-BoldItalic.ttf",
|
||||||
|
"sha1": "5ab6843366253b2e8009cf3384e6d275004ad5f3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraBold.ttf",
|
||||||
|
"sha1": "37ba2b2e9e7dd74a67b8b994a1aebe333af7fc39"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraBoldItalic.ttf",
|
||||||
|
"sha1": "fab683da6e0b9ff687a6ca683f96127e84919b24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraLight.ttf",
|
||||||
|
"sha1": "5473261207bdc8a16cf78d26e598becddeb8155e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraLightItalic.ttf",
|
||||||
|
"sha1": "fd4b64a944d4353f216df49c028cde717161dd24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Italic.ttf",
|
||||||
|
"sha1": "0c994f04c2bb328d87069d32e7422b559c05d5a7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Light.ttf",
|
||||||
|
"sha1": "e69e3dfdaf5baaa6fc6db1dd031ed18e1dca38f3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-LightItalic.ttf",
|
||||||
|
"sha1": "6855c33fb876932b819dc445eeb4ae3267c4ef7d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Medium.ttf",
|
||||||
|
"sha1": "75324fedc01df018cdf436bb5beba504bd82af0d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-MediumItalic.ttf",
|
||||||
|
"sha1": "e582f36e0b5d13c9e3ac827bd879593dec1a06d0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Regular.ttf",
|
||||||
|
"sha1": "929ddc840610489715952aaa10af50e9c1a6a4a6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-SemiBold.ttf",
|
||||||
|
"sha1": "c4a5281a3e088e1d2604635d4d09a1583d036db6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-SemiBoldItalic.ttf",
|
||||||
|
"sha1": "96d4f551a905d9dd509fec0ae085f35666d8f797"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -11,6 +11,22 @@
|
|||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||||
|
77E955B03ACA476189F41279 /* Nunito-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CD6281C4A8224BDC9C99061C /* Nunito-Black.ttf */; };
|
||||||
|
69272C3CFEEF44F4BB88C9BB /* Nunito-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8B63FD1EEF264E8E9FF335EC /* Nunito-BlackItalic.ttf */; };
|
||||||
|
84A9D5DED8094CB4A153268F /* Nunito-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AEAB2A7CD23248A9A542D0CA /* Nunito-Bold.ttf */; };
|
||||||
|
D67F05517BE4422F808A5EB3 /* Nunito-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4C5A03C0427D4F17A5988F0F /* Nunito-BoldItalic.ttf */; };
|
||||||
|
E007418A1C2740F79785A324 /* Nunito-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 60736DFE1D9549AEB020EE49 /* Nunito-ExtraBold.ttf */; };
|
||||||
|
CA97D53F7B8349D19F07E434 /* Nunito-ExtraBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D41A02AA33B74B74A5EA8D28 /* Nunito-ExtraBoldItalic.ttf */; };
|
||||||
|
FC3942C6BF94431DAF7D34CA /* Nunito-ExtraLight.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C2154C491E214E5B87CE0D6E /* Nunito-ExtraLight.ttf */; };
|
||||||
|
BF72BEDD2BEF41D5A740F6DB /* Nunito-ExtraLightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1BB241E150DC4271B6DB8035 /* Nunito-ExtraLightItalic.ttf */; };
|
||||||
|
C755B258B1CE4C7D9F669459 /* Nunito-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5E80FD17FB314B54B4070AE7 /* Nunito-Italic.ttf */; };
|
||||||
|
4432DD78D2D8420098273374 /* Nunito-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8654D08FDB97420F9054EC82 /* Nunito-Light.ttf */; };
|
||||||
|
7E3B3883C3FA414C9770A859 /* Nunito-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 50F514E360C2402797F5FB3B /* Nunito-LightItalic.ttf */; };
|
||||||
|
4B27568F87CA45C18D781B4E /* Nunito-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 13508BA55A1D4761A085FB3C /* Nunito-Medium.ttf */; };
|
||||||
|
0E89A7DC000347CCB92D18FA /* Nunito-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5744AD8D40A949D6B7F3C816 /* Nunito-MediumItalic.ttf */; };
|
||||||
|
609A14F1490B46E9966AD947 /* Nunito-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FAD14762400E476AA7B1075D /* Nunito-Regular.ttf */; };
|
||||||
|
430150A883E743E9A59596D5 /* Nunito-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 499363DC0EDB4DA4A3B87FA4 /* Nunito-SemiBold.ttf */; };
|
||||||
|
E3AC45B155004DE6BD7233A4 /* Nunito-SemiBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 62F0D71A41214365A475156B /* Nunito-SemiBoldItalic.ttf */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@@ -24,6 +40,22 @@
|
|||||||
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = CircleCollect/AppDelegate.swift; sourceTree = "<group>"; };
|
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = CircleCollect/AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = CircleCollect/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = CircleCollect/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
|
CD6281C4A8224BDC9C99061C /* Nunito-Black.ttf */ = {isa = PBXFileReference; name = "Nunito-Black.ttf"; path = "../src/assets/fonts/Nunito-Black.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
8B63FD1EEF264E8E9FF335EC /* Nunito-BlackItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-BlackItalic.ttf"; path = "../src/assets/fonts/Nunito-BlackItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
AEAB2A7CD23248A9A542D0CA /* Nunito-Bold.ttf */ = {isa = PBXFileReference; name = "Nunito-Bold.ttf"; path = "../src/assets/fonts/Nunito-Bold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
4C5A03C0427D4F17A5988F0F /* Nunito-BoldItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-BoldItalic.ttf"; path = "../src/assets/fonts/Nunito-BoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
60736DFE1D9549AEB020EE49 /* Nunito-ExtraBold.ttf */ = {isa = PBXFileReference; name = "Nunito-ExtraBold.ttf"; path = "../src/assets/fonts/Nunito-ExtraBold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
D41A02AA33B74B74A5EA8D28 /* Nunito-ExtraBoldItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-ExtraBoldItalic.ttf"; path = "../src/assets/fonts/Nunito-ExtraBoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
C2154C491E214E5B87CE0D6E /* Nunito-ExtraLight.ttf */ = {isa = PBXFileReference; name = "Nunito-ExtraLight.ttf"; path = "../src/assets/fonts/Nunito-ExtraLight.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
1BB241E150DC4271B6DB8035 /* Nunito-ExtraLightItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-ExtraLightItalic.ttf"; path = "../src/assets/fonts/Nunito-ExtraLightItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
5E80FD17FB314B54B4070AE7 /* Nunito-Italic.ttf */ = {isa = PBXFileReference; name = "Nunito-Italic.ttf"; path = "../src/assets/fonts/Nunito-Italic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
8654D08FDB97420F9054EC82 /* Nunito-Light.ttf */ = {isa = PBXFileReference; name = "Nunito-Light.ttf"; path = "../src/assets/fonts/Nunito-Light.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
50F514E360C2402797F5FB3B /* Nunito-LightItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-LightItalic.ttf"; path = "../src/assets/fonts/Nunito-LightItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
13508BA55A1D4761A085FB3C /* Nunito-Medium.ttf */ = {isa = PBXFileReference; name = "Nunito-Medium.ttf"; path = "../src/assets/fonts/Nunito-Medium.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
5744AD8D40A949D6B7F3C816 /* Nunito-MediumItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-MediumItalic.ttf"; path = "../src/assets/fonts/Nunito-MediumItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
FAD14762400E476AA7B1075D /* Nunito-Regular.ttf */ = {isa = PBXFileReference; name = "Nunito-Regular.ttf"; path = "../src/assets/fonts/Nunito-Regular.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
499363DC0EDB4DA4A3B87FA4 /* Nunito-SemiBold.ttf */ = {isa = PBXFileReference; name = "Nunito-SemiBold.ttf"; path = "../src/assets/fonts/Nunito-SemiBold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
|
62F0D71A41214365A475156B /* Nunito-SemiBoldItalic.ttf */ = {isa = PBXFileReference; name = "Nunito-SemiBoldItalic.ttf"; path = "../src/assets/fonts/Nunito-SemiBoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -74,6 +106,7 @@
|
|||||||
83CBBA001A601CBA00E9B192 /* Products */,
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||||
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
||||||
|
20F28563BF834255BD7383AF /* Resources */,
|
||||||
);
|
);
|
||||||
indentWidth = 2;
|
indentWidth = 2;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -97,6 +130,30 @@
|
|||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
20F28563BF834255BD7383AF /* Resources */ = {
|
||||||
|
isa = "PBXGroup";
|
||||||
|
children = (
|
||||||
|
CD6281C4A8224BDC9C99061C /* Nunito-Black.ttf */,
|
||||||
|
8B63FD1EEF264E8E9FF335EC /* Nunito-BlackItalic.ttf */,
|
||||||
|
AEAB2A7CD23248A9A542D0CA /* Nunito-Bold.ttf */,
|
||||||
|
4C5A03C0427D4F17A5988F0F /* Nunito-BoldItalic.ttf */,
|
||||||
|
60736DFE1D9549AEB020EE49 /* Nunito-ExtraBold.ttf */,
|
||||||
|
D41A02AA33B74B74A5EA8D28 /* Nunito-ExtraBoldItalic.ttf */,
|
||||||
|
C2154C491E214E5B87CE0D6E /* Nunito-ExtraLight.ttf */,
|
||||||
|
1BB241E150DC4271B6DB8035 /* Nunito-ExtraLightItalic.ttf */,
|
||||||
|
5E80FD17FB314B54B4070AE7 /* Nunito-Italic.ttf */,
|
||||||
|
8654D08FDB97420F9054EC82 /* Nunito-Light.ttf */,
|
||||||
|
50F514E360C2402797F5FB3B /* Nunito-LightItalic.ttf */,
|
||||||
|
13508BA55A1D4761A085FB3C /* Nunito-Medium.ttf */,
|
||||||
|
5744AD8D40A949D6B7F3C816 /* Nunito-MediumItalic.ttf */,
|
||||||
|
FAD14762400E476AA7B1075D /* Nunito-Regular.ttf */,
|
||||||
|
499363DC0EDB4DA4A3B87FA4 /* Nunito-SemiBold.ttf */,
|
||||||
|
62F0D71A41214365A475156B /* Nunito-SemiBoldItalic.ttf */,
|
||||||
|
);
|
||||||
|
name = Resources;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
path = "";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@@ -159,6 +216,22 @@
|
|||||||
files = (
|
files = (
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
|
77E955B03ACA476189F41279 /* Nunito-Black.ttf in Resources */,
|
||||||
|
69272C3CFEEF44F4BB88C9BB /* Nunito-BlackItalic.ttf in Resources */,
|
||||||
|
84A9D5DED8094CB4A153268F /* Nunito-Bold.ttf in Resources */,
|
||||||
|
D67F05517BE4422F808A5EB3 /* Nunito-BoldItalic.ttf in Resources */,
|
||||||
|
E007418A1C2740F79785A324 /* Nunito-ExtraBold.ttf in Resources */,
|
||||||
|
CA97D53F7B8349D19F07E434 /* Nunito-ExtraBoldItalic.ttf in Resources */,
|
||||||
|
FC3942C6BF94431DAF7D34CA /* Nunito-ExtraLight.ttf in Resources */,
|
||||||
|
BF72BEDD2BEF41D5A740F6DB /* Nunito-ExtraLightItalic.ttf in Resources */,
|
||||||
|
C755B258B1CE4C7D9F669459 /* Nunito-Italic.ttf in Resources */,
|
||||||
|
4432DD78D2D8420098273374 /* Nunito-Light.ttf in Resources */,
|
||||||
|
7E3B3883C3FA414C9770A859 /* Nunito-LightItalic.ttf in Resources */,
|
||||||
|
4B27568F87CA45C18D781B4E /* Nunito-Medium.ttf in Resources */,
|
||||||
|
0E89A7DC000347CCB92D18FA /* Nunito-MediumItalic.ttf in Resources */,
|
||||||
|
609A14F1490B46E9966AD947 /* Nunito-Regular.ttf in Resources */,
|
||||||
|
430150A883E743E9A59596D5 /* Nunito-SemiBold.ttf in Resources */,
|
||||||
|
E3AC45B155004DE6BD7233A4 /* Nunito-SemiBoldItalic.ttf in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,14 +26,13 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
|
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>NSAllowsLocalNetworking</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string></string>
|
<string/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
@@ -48,5 +47,24 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>UIAppFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>Nunito-Black.ttf</string>
|
||||||
|
<string>Nunito-BlackItalic.ttf</string>
|
||||||
|
<string>Nunito-Bold.ttf</string>
|
||||||
|
<string>Nunito-BoldItalic.ttf</string>
|
||||||
|
<string>Nunito-ExtraBold.ttf</string>
|
||||||
|
<string>Nunito-ExtraBoldItalic.ttf</string>
|
||||||
|
<string>Nunito-ExtraLight.ttf</string>
|
||||||
|
<string>Nunito-ExtraLightItalic.ttf</string>
|
||||||
|
<string>Nunito-Italic.ttf</string>
|
||||||
|
<string>Nunito-Light.ttf</string>
|
||||||
|
<string>Nunito-LightItalic.ttf</string>
|
||||||
|
<string>Nunito-Medium.ttf</string>
|
||||||
|
<string>Nunito-MediumItalic.ttf</string>
|
||||||
|
<string>Nunito-Regular.ttf</string>
|
||||||
|
<string>Nunito-SemiBold.ttf</string>
|
||||||
|
<string>Nunito-SemiBoldItalic.ttf</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"migIndex": 1,
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Black.ttf",
|
||||||
|
"sha1": "bede9c89e905ae0b91404768e1167e3e5d3c9c8e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-BlackItalic.ttf",
|
||||||
|
"sha1": "5b27538c43c1afcd5b4a8547854522a805f4c302"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Bold.ttf",
|
||||||
|
"sha1": "e50cf9134308e37008cbd39da1dc637aef022641"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-BoldItalic.ttf",
|
||||||
|
"sha1": "5ab6843366253b2e8009cf3384e6d275004ad5f3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraBold.ttf",
|
||||||
|
"sha1": "37ba2b2e9e7dd74a67b8b994a1aebe333af7fc39"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraBoldItalic.ttf",
|
||||||
|
"sha1": "fab683da6e0b9ff687a6ca683f96127e84919b24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraLight.ttf",
|
||||||
|
"sha1": "5473261207bdc8a16cf78d26e598becddeb8155e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-ExtraLightItalic.ttf",
|
||||||
|
"sha1": "fd4b64a944d4353f216df49c028cde717161dd24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Italic.ttf",
|
||||||
|
"sha1": "0c994f04c2bb328d87069d32e7422b559c05d5a7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Light.ttf",
|
||||||
|
"sha1": "e69e3dfdaf5baaa6fc6db1dd031ed18e1dca38f3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-LightItalic.ttf",
|
||||||
|
"sha1": "6855c33fb876932b819dc445eeb4ae3267c4ef7d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Medium.ttf",
|
||||||
|
"sha1": "75324fedc01df018cdf436bb5beba504bd82af0d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-MediumItalic.ttf",
|
||||||
|
"sha1": "e582f36e0b5d13c9e3ac827bd879593dec1a06d0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-Regular.ttf",
|
||||||
|
"sha1": "929ddc840610489715952aaa10af50e9c1a6a4a6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-SemiBold.ttf",
|
||||||
|
"sha1": "c4a5281a3e088e1d2604635d4d09a1583d036db6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "src/assets/fonts/Nunito-SemiBoldItalic.ttf",
|
||||||
|
"sha1": "96d4f551a905d9dd509fec0ae085f35666d8f797"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Generated
+296
-714
File diff suppressed because it is too large
Load Diff
@@ -49,6 +49,7 @@
|
|||||||
"react-native-responsive-dimensions": "^3.1.1",
|
"react-native-responsive-dimensions": "^3.1.1",
|
||||||
"react-native-safe-area-context": "^5.6.1",
|
"react-native-safe-area-context": "^5.6.1",
|
||||||
"react-native-screens": "^4.16.0",
|
"react-native-screens": "^4.16.0",
|
||||||
|
"react-native-size-matters": "^0.0.3",
|
||||||
"react-native-svg": "^15.13.0",
|
"react-native-svg": "^15.13.0",
|
||||||
"react-native-vector-icons": "^10.3.0",
|
"react-native-vector-icons": "^10.3.0",
|
||||||
"react-native-walkthrough-tooltip": "^1.6.0",
|
"react-native-walkthrough-tooltip": "^1.6.0",
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
project: {
|
||||||
|
ios: {},
|
||||||
|
android: {},
|
||||||
|
},
|
||||||
|
assets: ['./src/assets/fonts/'], // Path to your fonts
|
||||||
|
};
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -11,6 +11,8 @@ import { BlurView } from "@react-native-community/blur";
|
|||||||
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
||||||
import colors from "./colors";
|
import colors from "./colors";
|
||||||
import { responsiveFontSize } from "react-native-responsive-dimensions";
|
import { responsiveFontSize } from "react-native-responsive-dimensions";
|
||||||
|
import { useTheme } from "../theme/ThemeProvider";
|
||||||
|
import FontsFamily from "../constents/FontsFamily";
|
||||||
|
|
||||||
export interface AlertButton {
|
export interface AlertButton {
|
||||||
text: string;
|
text: string;
|
||||||
@@ -29,7 +31,6 @@ export interface CustomAlertProps {
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BORDER_WIDTH = 6;
|
|
||||||
const RADIUS = 24;
|
const RADIUS = 24;
|
||||||
|
|
||||||
const CustomAlert: React.FC<CustomAlertProps> = ({
|
const CustomAlert: React.FC<CustomAlertProps> = ({
|
||||||
@@ -40,6 +41,8 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
|||||||
alertType = 'info',
|
alertType = 'info',
|
||||||
onClose,
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
|
||||||
const getIcon = () => {
|
const getIcon = () => {
|
||||||
switch (alertType) {
|
switch (alertType) {
|
||||||
case 'error':
|
case 'error':
|
||||||
@@ -47,7 +50,7 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
|||||||
case 'success':
|
case 'success':
|
||||||
return { name: "checkmark-circle", color: colors.success };
|
return { name: "checkmark-circle", color: colors.success };
|
||||||
default:
|
default:
|
||||||
return { name: "information-circle", color: colors.primary };
|
return { name: "information-circle", color: theme.colors.primary };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const icon = getIcon();
|
const icon = getIcon();
|
||||||
@@ -64,34 +67,30 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
|||||||
const getButtonStyle = (styleType: string | undefined) => {
|
const getButtonStyle = (styleType: string | undefined) => {
|
||||||
switch (styleType) {
|
switch (styleType) {
|
||||||
case "primary":
|
case "primary":
|
||||||
return [styles.button, styles.primaryButton];
|
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||||
case "secondary":
|
case "secondary":
|
||||||
return [styles.button, styles.secondaryButton];
|
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||||
case "outline":
|
case "outline":
|
||||||
return [styles.button, styles.outlineButton];
|
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||||
case "destructive":
|
case "destructive":
|
||||||
return [styles.button, styles.destructiveButton];
|
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||||
case "cancel":
|
case "cancel":
|
||||||
return [styles.button, styles.cancelButton];
|
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||||
default:
|
default:
|
||||||
return [styles.button, styles.defaultButton];
|
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getButtonTextStyle = (styleType: string | undefined) => {
|
const getButtonTextStyle = (styleType: string | undefined) => {
|
||||||
switch (styleType) {
|
switch (styleType) {
|
||||||
case "primary":
|
|
||||||
return [styles.buttonText, styles.primaryButtonText];
|
|
||||||
case "secondary":
|
|
||||||
return [styles.buttonText, styles.secondaryButtonText];
|
|
||||||
case "outline":
|
case "outline":
|
||||||
return [styles.buttonText, styles.outlineButtonText];
|
return { color: theme.colors.reverseText };
|
||||||
case "destructive":
|
|
||||||
return [styles.buttonText, styles.destructiveButtonText];
|
|
||||||
case "cancel":
|
case "cancel":
|
||||||
return [styles.buttonText, styles.cancelButtonText];
|
return { color: colors.error };
|
||||||
|
case "secondary":
|
||||||
|
return { color: theme.colors.reverseText };
|
||||||
default:
|
default:
|
||||||
return [styles.buttonText, styles.defaultButtonText];
|
return { color: theme.colors.reverseText };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,35 +102,49 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
|||||||
onRequestClose={handleRequestClose}
|
onRequestClose={handleRequestClose}
|
||||||
>
|
>
|
||||||
<View style={styles.centeredView}>
|
<View style={styles.centeredView}>
|
||||||
|
{/* Background Overlay */}
|
||||||
{Platform.OS === 'ios' ? (
|
{Platform.OS === 'ios' ? (
|
||||||
<BlurView style={styles.absolute} blurType="light" blurAmount={5} />
|
<BlurView style={styles.absolute} blurType={theme.mode === 'dark' ? "dark" : "light"} blurAmount={5} />
|
||||||
) : (
|
) : (
|
||||||
<View style={[styles.absolute, { backgroundColor: colors.androidBackdrop }]} />
|
<View style={[styles.absolute, { backgroundColor: 'rgba(0,0,0,0.5)' }]} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={styles.box}>
|
{/* Alert Box */}
|
||||||
<View style={styles.faintOverlay} />
|
<View style={[
|
||||||
|
styles.box,
|
||||||
|
{
|
||||||
|
backgroundColor: theme.colors.card,
|
||||||
|
borderColor: theme.colors.border,
|
||||||
|
borderWidth: 1,
|
||||||
|
}
|
||||||
|
]}>
|
||||||
|
|
||||||
<View style={styles.contentContainer}>
|
<View style={styles.contentContainer}>
|
||||||
<View style={styles.iconContainer}>
|
<View style={styles.iconContainer}>
|
||||||
<Ionicons name={icon.name} size={36} color={icon.color} /> {/* smaller icon for vertical compression */}
|
<Ionicons name={icon.name} size={36} color={theme.colors.reverseBackground} />
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.alertTitle}>{title}</Text>
|
|
||||||
<Text style={styles.alertMessage}>{message}</Text>
|
<Text style={[styles.alertTitle, { color: theme.colors.textPrimary }]}>{title}</Text>
|
||||||
|
<Text style={[styles.alertMessage, { color: theme.colors.textSecondary }]}>{message}</Text>
|
||||||
|
|
||||||
{buttons.length > 0 && (
|
{buttons.length > 0 && (
|
||||||
<View style={styles.buttonContainer}>
|
<View style={styles.buttonContainer}>
|
||||||
{buttons.map((button, index) => (
|
{buttons.map((button, index) => (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
key={index}
|
key={index}
|
||||||
style={[
|
style={[
|
||||||
...getButtonStyle(button.style),
|
styles.button,
|
||||||
|
getButtonStyle(button.style),
|
||||||
|
// Custom overrides
|
||||||
button.style !== "cancel" && button.buttonColor ? { backgroundColor: button.buttonColor } : null,
|
button.style !== "cancel" && button.buttonColor ? { backgroundColor: button.buttonColor } : null,
|
||||||
button.style === "outline" && button.buttonColor ? { borderColor: button.buttonColor } : null,
|
button.style === "outline" && button.buttonColor ? { borderColor: button.buttonColor } : null,
|
||||||
]}
|
]}
|
||||||
onPress={button.onPress}
|
onPress={button.onPress}
|
||||||
>
|
>
|
||||||
<Text style={[
|
<Text style={[
|
||||||
...getButtonTextStyle(button.style),
|
styles.buttonText,{color: theme.colors.reverseText},
|
||||||
button.style !== "cancel" && button.textColor ? { color: button.textColor } : null,
|
getButtonTextStyle(button.style),
|
||||||
|
|
||||||
]}>
|
]}>
|
||||||
{button.text}
|
{button.text}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -153,112 +166,83 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
absolute: {
|
absolute: {
|
||||||
position: 'absolute',
|
...StyleSheet.absoluteFillObject,
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
bottom: 0,
|
|
||||||
right: 0,
|
|
||||||
},
|
},
|
||||||
box: {
|
box: {
|
||||||
paddingHorizontal: 2, // reduce horizontal padding
|
width: '85%',
|
||||||
padding: BORDER_WIDTH + 2, // reduce overall padding
|
maxWidth: 340,
|
||||||
borderRadius: RADIUS + BORDER_WIDTH,
|
|
||||||
width: '90%',
|
|
||||||
maxWidth: 400,
|
|
||||||
alignSelf: 'center',
|
|
||||||
margin: 10, // reduce margin for vertical compression
|
|
||||||
backgroundColor: colors.pastelPink,
|
|
||||||
position: 'relative',
|
|
||||||
overflow: 'hidden',
|
|
||||||
},
|
|
||||||
faintOverlay: {
|
|
||||||
...StyleSheet.absoluteFillObject,
|
|
||||||
backgroundColor: "rgba(255,255,255,0.77)",
|
|
||||||
zIndex: 1,
|
|
||||||
borderRadius: RADIUS,
|
borderRadius: RADIUS,
|
||||||
|
alignSelf: 'center',
|
||||||
|
overflow: 'hidden',
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: { width: 0, height: 10 },
|
||||||
|
shadowOpacity: 0.25,
|
||||||
|
shadowRadius: 10,
|
||||||
|
elevation: 10,
|
||||||
},
|
},
|
||||||
contentContainer: {
|
contentContainer: {
|
||||||
zIndex: 2,
|
padding: 20,
|
||||||
padding: 12, // reduce container padding
|
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
iconContainer: {
|
iconContainer: {
|
||||||
marginBottom: 8, // reduce vertical space below icon
|
marginBottom: 12,
|
||||||
},
|
},
|
||||||
alertTitle: {
|
alertTitle: {
|
||||||
fontSize: responsiveFontSize(1.8), // smaller font size
|
fontSize: responsiveFontSize(2),
|
||||||
fontWeight: "bold",
|
fontFamily: FontsFamily.nunitoExtraBold,
|
||||||
color: colors.textDark,
|
marginBottom: 8,
|
||||||
marginBottom: 4, // less space below title
|
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
|
|
||||||
},
|
},
|
||||||
alertMessage: {
|
alertMessage: {
|
||||||
fontSize: responsiveFontSize(1.4), // smaller font size
|
fontFamily: FontsFamily.nunitoRegular,
|
||||||
color: colors.textLight,
|
fontSize: responsiveFontSize(1.6),
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
marginBottom: 12, // tighter spacing
|
marginBottom: 20,
|
||||||
lineHeight: 18, // reduced line height
|
lineHeight: 20,
|
||||||
},
|
},
|
||||||
buttonContainer: {
|
buttonContainer: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
width: "100%",
|
width: "100%",
|
||||||
gap: 8, // reduce gap between buttons
|
gap: 10,
|
||||||
|
flexWrap: 'wrap', // Allow wrapping if many buttons
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
paddingVertical: 8, // less vertical padding
|
paddingVertical: 10,
|
||||||
paddingHorizontal: 16, // less horizontal padding
|
paddingHorizontal: 20,
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
minWidth: 72, // slightly smaller minimum width
|
minWidth: 80,
|
||||||
borderWidth: 0,
|
|
||||||
},
|
},
|
||||||
// === BUTTON STYLE VARIANTS ===
|
buttonText: {
|
||||||
|
fontSize: responsiveFontSize(1.6),
|
||||||
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
|
},
|
||||||
|
|
||||||
|
// === BUTTON STYLES ===
|
||||||
defaultButton: {
|
defaultButton: {
|
||||||
backgroundColor: colors.pastelPink,
|
backgroundColor: colors.pastelPink, // Or theme.colors.primary
|
||||||
},
|
|
||||||
destructiveButton: {
|
|
||||||
backgroundColor: colors.error,
|
|
||||||
},
|
},
|
||||||
primaryButton: {
|
primaryButton: {
|
||||||
backgroundColor: colors.primary,
|
backgroundColor: colors.primary,
|
||||||
},
|
},
|
||||||
secondaryButton: {
|
secondaryButton: {
|
||||||
backgroundColor: colors.pastelBlue,
|
backgroundColor: '#E0E0E0', // Neutral gray
|
||||||
|
},
|
||||||
|
destructiveButton: {
|
||||||
|
backgroundColor: colors.error,
|
||||||
},
|
},
|
||||||
outlineButton: {
|
outlineButton: {
|
||||||
borderColor: colors.primary,
|
borderWidth: 1.5,
|
||||||
borderWidth: 2,
|
borderColor: colors.primary, // Will be overridden by theme in render if needed
|
||||||
backgroundColor: "transparent",
|
backgroundColor: 'transparent',
|
||||||
},
|
},
|
||||||
cancelButton: {
|
cancelButton: {
|
||||||
borderColor: colors.error,
|
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
backgroundColor: "transparent",
|
borderColor: colors.error,
|
||||||
},
|
backgroundColor: 'transparent',
|
||||||
// === BUTTON TEXT COLOR VARIANTS ===
|
|
||||||
buttonText: {
|
|
||||||
fontSize: responsiveFontSize(1.4), // smaller text
|
|
||||||
fontWeight: "700",
|
|
||||||
},
|
|
||||||
defaultButtonText: {
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
destructiveButtonText: {
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
primaryButtonText: {
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
secondaryButtonText: {
|
|
||||||
color: colors.textDark,
|
|
||||||
},
|
|
||||||
outlineButtonText: {
|
|
||||||
color: colors.primary,
|
|
||||||
},
|
|
||||||
cancelButtonText: {
|
|
||||||
color: colors.error,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import React, { useRef } from "react";
|
import React, { use, useRef } from "react";
|
||||||
import { View, Text, StyleSheet, Animated, TouchableWithoutFeedback } from "react-native";
|
import { View, Text, StyleSheet, Animated, TouchableWithoutFeedback } from "react-native";
|
||||||
import LinearGradient from "react-native-linear-gradient";
|
import LinearGradient from "react-native-linear-gradient";
|
||||||
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
||||||
import colors from "../colors";
|
import colors from "../colors";
|
||||||
import { responsiveFontSize } from "react-native-responsive-dimensions";
|
import { responsiveFontSize } from "react-native-responsive-dimensions";
|
||||||
|
import { useTheme } from "../../theme/ThemeProvider";
|
||||||
|
import FontsFamily from "../../constents/FontsFamily";
|
||||||
|
|
||||||
type CardProps = {
|
type CardProps = {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -23,7 +25,7 @@ const AnimatedCard: React.FC<CardProps> = ({
|
|||||||
backTwo = colors.pastelPink,
|
backTwo = colors.pastelPink,
|
||||||
}) => {
|
}) => {
|
||||||
const scale = useRef(new Animated.Value(1)).current;
|
const scale = useRef(new Animated.Value(1)).current;
|
||||||
|
const{ theme } = useTheme()
|
||||||
const handlePress = () => {
|
const handlePress = () => {
|
||||||
Animated.sequence([
|
Animated.sequence([
|
||||||
Animated.spring(scale, { toValue: 0.95, useNativeDriver: true }),
|
Animated.spring(scale, { toValue: 0.95, useNativeDriver: true }),
|
||||||
@@ -33,11 +35,11 @@ const AnimatedCard: React.FC<CardProps> = ({
|
|||||||
return (
|
return (
|
||||||
<TouchableWithoutFeedback onPress={handlePress}>
|
<TouchableWithoutFeedback onPress={handlePress}>
|
||||||
<Animated.View style={[styles.card, { transform: [{ scale }] }]}>
|
<Animated.View style={[styles.card, { transform: [{ scale }] }]}>
|
||||||
<LinearGradient colors={[backOne, backTwo]} style={styles.gradient}>
|
<View style={[styles.gradient, { backgroundColor: theme.colors.reverseBackground }]}>
|
||||||
<Ionicons name={iconName} size={38} color="#fff" style={styles.icon} />
|
<Ionicons name={iconName} size={38} color={theme.colors.reverseText} style={styles.icon} />
|
||||||
<Text style={styles.title}>{title}</Text>
|
<Text style={[styles.title, { color: theme.colors.reverseText }]}>{title}</Text>
|
||||||
{subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
|
{subtitle && <Text style={[styles.subtitle, { color: theme.colors.reverseText }]}>{subtitle}</Text>}
|
||||||
</LinearGradient>
|
</View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
);
|
);
|
||||||
@@ -58,8 +60,8 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
icon: { marginBottom: 10 },
|
icon: { marginBottom: 10 },
|
||||||
title: { fontSize: responsiveFontSize(1.8), fontWeight: "bold", color: "#fff" },
|
title: { fontSize: responsiveFontSize(2.2), fontFamily: FontsFamily.nunitoExtraBold, color: "#fff" },
|
||||||
subtitle: { fontSize: responsiveFontSize(1.3), color: "#fff", opacity: 0.9 },
|
subtitle: { fontSize: responsiveFontSize(1.5), fontFamily: FontsFamily.nunitoRegular, opacity: 0.9 },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default AnimatedCard;
|
export default AnimatedCard;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
const FontsFamily = {
|
||||||
|
nunitoLight: 'Nunito-Light',
|
||||||
|
|
||||||
|
nunitoBlack: 'Nunito-Black',
|
||||||
|
nunitoBlackItalic: 'Nunito-BlackItalic',
|
||||||
|
|
||||||
|
nunitoBold: 'Nunito-Bold',
|
||||||
|
nunitoBoldItalic: 'Nunito-BoldItalic',
|
||||||
|
|
||||||
|
nunitoExtraBold: 'Nunito-ExtraBold',
|
||||||
|
nunitoExtraBoldItalic: 'Nunito-ExtraBoldItalic',
|
||||||
|
|
||||||
|
nunitoExtraLight: 'Nunito-ExtraLight',
|
||||||
|
nunitoExtraLightItalic: 'Nunito-ExtraLightItalic',
|
||||||
|
|
||||||
|
nunitoItalic: 'Nunito-Italic',
|
||||||
|
|
||||||
|
nunitoLightItalic: 'Nunito-LightItalic',
|
||||||
|
|
||||||
|
nunitoMedium: 'Nunito-Medium',
|
||||||
|
nunitoMediumItalic: 'Nunito-MediumItalic',
|
||||||
|
|
||||||
|
nunitoRegular: 'Nunito-Regular',
|
||||||
|
|
||||||
|
nunitoSemiBold: 'Nunito-SemiBold',
|
||||||
|
nunitoSemiBoldItalic: 'Nunito-SemiBoldItalic',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FontsFamily;
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
import React from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { BottomTabNavigationProp, createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
import {
|
||||||
import { View, Text, StyleSheet, Platform, AccessibilityInfo } from "react-native";
|
BottomTabNavigationProp,
|
||||||
|
createBottomTabNavigator,
|
||||||
|
} from "@react-navigation/bottom-tabs";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
Platform,
|
||||||
|
AccessibilityInfo,
|
||||||
|
} from "react-native";
|
||||||
import { Ionicons, IoniconsIconName } from "@react-native-vector-icons/ionicons";
|
import { Ionicons, IoniconsIconName } from "@react-native-vector-icons/ionicons";
|
||||||
import GroupScreen from "../screens/GroupScreen";
|
import GroupScreen from "../screens/GroupScreen";
|
||||||
import Profile from "../screens/profile/Profile";
|
import Profile from "../screens/profile/Profile";
|
||||||
@@ -8,8 +17,12 @@ import Home from "../screens/home/Home";
|
|||||||
import colors from "../components/colors";
|
import colors from "../components/colors";
|
||||||
import Setting from "../screens/setting/Setting";
|
import Setting from "../screens/setting/Setting";
|
||||||
import ManagementScreen from "../screens/management/ManagementScreen";
|
import ManagementScreen from "../screens/management/ManagementScreen";
|
||||||
import { responsiveFontSize, responsiveHeight } from "react-native-responsive-dimensions";
|
import {
|
||||||
|
responsiveFontSize,
|
||||||
|
responsiveHeight,
|
||||||
|
} from "react-native-responsive-dimensions";
|
||||||
|
import { useTheme } from "../theme/ThemeProvider";
|
||||||
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
|
|
||||||
const TAB_CONFIG = {
|
const TAB_CONFIG = {
|
||||||
activeColor: "#000",
|
activeColor: "#000",
|
||||||
@@ -19,60 +32,72 @@ const TAB_CONFIG = {
|
|||||||
iconSize: 28,
|
iconSize: 28,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Background (tab highlight) colors
|
|
||||||
const activeTabColors: { [key: string]: string } = {
|
const activeTabColors: { [key: string]: string } = {
|
||||||
Home: colors.pastelPink, // Soft pink
|
Home: colors.pastelPink,
|
||||||
Profile: colors.pastelBlue, // Light sky blue
|
Profile: colors.pastelBlue,
|
||||||
Group: colors.pastelGreen, // Gentle mint green
|
Group: colors.pastelGreen,
|
||||||
Management: colors.pastelOrange, // Warm pastel yellow
|
Management: colors.pastelOrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Icon/Text colors on active tabs
|
|
||||||
const activeIconColors: { [key: string]: string } = {
|
const activeIconColors: { [key: string]: string } = {
|
||||||
Home: "#333",
|
Home: "#333",
|
||||||
Profile: "#333",
|
Profile: "#333",
|
||||||
Group: "#333",
|
Group: "#333",
|
||||||
Management: "#333",
|
Management: "#333",
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootTabParamList = {
|
export type RootTabParamList = {
|
||||||
Home: undefined;
|
Home: undefined;
|
||||||
Profile: undefined;
|
Profile: undefined;
|
||||||
Group: undefined;
|
Group: undefined;
|
||||||
Management: { actionTab?: "My Groups" | "Joined Groups" | "Requests" | "Your Requests" };
|
Management: {
|
||||||
|
actionTab?: "My Groups" | "Joined Groups" | "Requests" | "Your Requests";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
// Define the navigation prop type for screens within the tab navigator
|
|
||||||
export type TabNavigationProp = BottomTabNavigationProp<RootTabParamList>;
|
export type TabNavigationProp = BottomTabNavigationProp<RootTabParamList>;
|
||||||
const Tab = createBottomTabNavigator<RootTabParamList>();
|
const Tab = createBottomTabNavigator<RootTabParamList>();
|
||||||
|
|
||||||
const BottomTabs: React.FC = () => {
|
const BottomTabs: React.FC = () => {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
const [isReduceMotionEnabled, setIsReduceMotionEnabled] = React.useState<boolean>(false);
|
const [isReduceMotionEnabled, setIsReduceMotionEnabled] =
|
||||||
const [isScreenReaderEnabled, setIsScreenReaderEnabled] = React.useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
|
const [isScreenReaderEnabled, setIsScreenReaderEnabled] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
// Check for accessibility settings
|
|
||||||
AccessibilityInfo.isScreenReaderEnabled().then(setIsScreenReaderEnabled);
|
AccessibilityInfo.isScreenReaderEnabled().then(setIsScreenReaderEnabled);
|
||||||
AccessibilityInfo.isReduceMotionEnabled().then(setIsReduceMotionEnabled);
|
AccessibilityInfo.isReduceMotionEnabled().then(setIsReduceMotionEnabled);
|
||||||
|
|
||||||
const screenReaderSubscription = AccessibilityInfo.addEventListener(
|
const screenReaderSubscription = AccessibilityInfo.addEventListener(
|
||||||
'screenReaderChanged',
|
"screenReaderChanged",
|
||||||
setIsScreenReaderEnabled
|
setIsScreenReaderEnabled
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => screenReaderSubscription.remove();
|
return () => screenReaderSubscription.remove();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// console.log("isReduceMotionEnabled : ", isReduceMotionEnabled)
|
|
||||||
// console.log("isScreenReaderEnabled : ", isScreenReaderEnabled)
|
|
||||||
return (
|
return (
|
||||||
<Tab.Navigator
|
<Tab.Navigator
|
||||||
screenOptions={({ route }) => ({
|
screenOptions={({ route }) => ({
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
tabBarStyle: [styles.tabBar, {marginVertical:isReduceMotionEnabled ? responsiveHeight(0.5) : responsiveHeight(3.5) || isScreenReaderEnabled ? responsiveHeight(0.5) : responsiveHeight(3.5)}],
|
tabBarStyle: [
|
||||||
|
[styles.tabBar,{ backgroundColor: theme.colors.reverseBackground }],
|
||||||
|
{
|
||||||
|
bottom: insets.bottom + 10
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
// Make each tab item occupy the full bar height and center its content
|
||||||
|
tabBarItemStyle: {
|
||||||
|
height: "100%",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
|
||||||
tabBarLabel: ({ focused, color }) =>
|
tabBarLabel: ({ focused, color }) =>
|
||||||
!focused ? (
|
!focused ? (
|
||||||
@@ -82,32 +107,33 @@ const BottomTabs: React.FC = () => {
|
|||||||
tabBarIcon: ({ focused }) => {
|
tabBarIcon: ({ focused }) => {
|
||||||
let iconName: IoniconsIconName = "home-outline";
|
let iconName: IoniconsIconName = "home-outline";
|
||||||
|
|
||||||
// Determine icon based on route
|
if (route.name === "Home")
|
||||||
if (route.name === "Home") iconName = focused ? "home" : "home-outline";
|
iconName = focused ? "home" : "home-outline";
|
||||||
else if (route.name === "Profile") iconName = focused ? "person" : "person-outline";
|
else if (route.name === "Profile")
|
||||||
else if (route.name === "Management") iconName = focused ? "settings" : "settings-outline";
|
iconName = focused ? "person" : "person-outline";
|
||||||
else if (route.name === "Group") iconName = focused ? "people" : "people-outline";
|
else if (route.name === "Management")
|
||||||
|
iconName = focused ? "settings" : "settings-outline";
|
||||||
|
else if (route.name === "Group")
|
||||||
|
iconName = focused ? "people" : "people-outline";
|
||||||
|
|
||||||
// 3. Get the active background color and icon color from the maps
|
const activeBackgroundColor = theme.colors.background;
|
||||||
const activeBackgroundColor = activeTabColors[route.name];
|
|
||||||
const activeIconColor = activeIconColors[route.name];
|
const activeIconColor = activeIconColors[route.name];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.iconContainer,
|
styles.iconContainer,
|
||||||
// 4. Apply the dynamic background color when focused
|
|
||||||
focused && [
|
focused && [
|
||||||
styles.activeIconContainer,
|
styles.activeIconContainer,
|
||||||
{ backgroundColor: activeBackgroundColor },
|
{ backgroundColor: activeBackgroundColor },
|
||||||
],
|
],
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
(route.name === "Management"{<Ionicons
|
<Ionicons
|
||||||
name={iconName}
|
name={iconName}
|
||||||
size={TAB_CONFIG.iconSize}
|
size={TAB_CONFIG.iconSize}
|
||||||
color={focused ? activeIconColor : TAB_CONFIG.inactiveColor}
|
color={focused ? activeIconColor : TAB_CONFIG.inactiveColor}
|
||||||
/>}:null)
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -119,7 +145,7 @@ const BottomTabs: React.FC = () => {
|
|||||||
<Tab.Screen name="Management" component={ManagementScreen} />
|
<Tab.Screen name="Management" component={ManagementScreen} />
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
screen: {
|
screen: {
|
||||||
@@ -135,19 +161,16 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
tabBar: {
|
tabBar: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
bottom: 20,
|
|
||||||
left: 20,
|
left: 20,
|
||||||
right: 20,
|
right: 20,
|
||||||
height: TAB_CONFIG.height,
|
height: TAB_CONFIG.height,
|
||||||
// backgroundColor: TAB_CONFIG.backgroundColor,
|
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
shadowColor: "#000",
|
shadowColor: "#000",
|
||||||
shadowOpacity: 0.1,
|
shadowOpacity: 0.1,
|
||||||
shadowOffset: { width: 0, height: 5 },
|
shadowOffset: { width: 0, height: 5 },
|
||||||
shadowRadius: 8,
|
shadowRadius: 8,
|
||||||
elevation: 10,
|
elevation: 10,
|
||||||
paddingBottom: Platform.OS === "ios" ? 25 : 10,
|
paddingTop: 0,
|
||||||
paddingTop: 10,
|
|
||||||
marginHorizontal: 10,
|
marginHorizontal: 10,
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
@@ -155,19 +178,18 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: responsiveFontSize(1.2),
|
fontSize: responsiveFontSize(1.2),
|
||||||
},
|
},
|
||||||
iconContainer: {
|
iconContainer: {
|
||||||
|
width: 60,
|
||||||
|
height: 50,
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
width: 80, // Reduced size for a sleeker look
|
|
||||||
height: 60, // Reduced size
|
|
||||||
marginTop: 10,
|
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
},
|
},
|
||||||
activeIconContainer: {
|
activeIconContainer: {
|
||||||
// The default active style, background color is now applied dynamically
|
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
shadowColor: '#000',
|
shadowColor: "#000",
|
||||||
shadowOpacity: 0.1,
|
shadowOpacity: 0.1,
|
||||||
shadowRadius: 5,
|
shadowRadius: 5,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default BottomTabs
|
|
||||||
|
export default BottomTabs;
|
||||||
|
|||||||
+87
-74
@@ -19,17 +19,27 @@ import type { StackNavigationProp } from '@react-navigation/stack';
|
|||||||
import { RootStackParamList } from '../navigation/AppNavigator';
|
import { RootStackParamList } from '../navigation/AppNavigator';
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||||
import MaterialRipple from 'react-native-material-ripple';
|
import MaterialRipple from 'react-native-material-ripple';
|
||||||
import CustomAlert from '../components/CostomAlart';
|
import CustomAlert from '../components/CostomAlart';
|
||||||
import colors from '../components/colors';
|
import colors from '../components/colors';
|
||||||
import { responsiveFontSize } from 'react-native-responsive-dimensions';
|
import {
|
||||||
|
responsiveHeight,
|
||||||
|
responsiveWidth,
|
||||||
|
responsiveFontSize
|
||||||
|
} from "react-native-responsive-dimensions";
|
||||||
|
import { useTheme } from '../theme/ThemeProvider';
|
||||||
|
import FontsFamily from '../constents/FontsFamily';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
const BLOCK_SIZE = width / 3;
|
const BLOCK_SIZE = width / 3;
|
||||||
|
|
||||||
|
|
||||||
// Note: You will need to install react-native-material-ripple
|
// Note: You will need to install react-native-material-ripple
|
||||||
// npm install react-native-material-ripple
|
// npm install react-native-material-ripple
|
||||||
|
|
||||||
|
|
||||||
export default function LoginScreen() {
|
export default function LoginScreen() {
|
||||||
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
|
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
|
||||||
const [mobile, setMobile] = useState('');
|
const [mobile, setMobile] = useState('');
|
||||||
@@ -42,9 +52,12 @@ export default function LoginScreen() {
|
|||||||
alertType: 'info' as 'info' | 'success' | 'error',
|
alertType: 'info' as 'info' | 'success' | 'error',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const fade = useRef(new Animated.Value(0)).current;
|
const fade = useRef(new Animated.Value(0)).current;
|
||||||
const slide = useRef(new Animated.Value(30)).current;
|
const slide = useRef(new Animated.Value(30)).current;
|
||||||
const ctaScale = useRef(new Animated.Value(1)).current;
|
const ctaScale = useRef(new Animated.Value(1)).current;
|
||||||
|
const { theme } = useTheme();
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Animated.parallel([
|
Animated.parallel([
|
||||||
@@ -53,6 +66,7 @@ export default function LoginScreen() {
|
|||||||
]).start();
|
]).start();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const showAlert = (
|
const showAlert = (
|
||||||
title: string,
|
title: string,
|
||||||
message: string,
|
message: string,
|
||||||
@@ -62,10 +76,12 @@ export default function LoginScreen() {
|
|||||||
setAlertInfo({ visible: true, title, message, buttons, alertType });
|
setAlertInfo({ visible: true, title, message, buttons, alertType });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const hideAlert = () => {
|
const hideAlert = () => {
|
||||||
setAlertInfo({ ...alertInfo, visible: false });
|
setAlertInfo({ ...alertInfo, visible: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleContinue = async () => {
|
const handleContinue = async () => {
|
||||||
if (mobile.length === 10) {
|
if (mobile.length === 10) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -87,58 +103,64 @@ export default function LoginScreen() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const colorsBlocks = [
|
const colorsBlocks = [
|
||||||
colors.pastelPink,
|
theme.colors.logincard,
|
||||||
colors.pastelBlue,
|
theme.colors.logincard1,
|
||||||
colors.pastelGreen,
|
theme.colors.logincard1,
|
||||||
colors.pastelOrange,
|
theme.colors.logincard,
|
||||||
colors.pastelBlue,
|
theme.colors.logincard,
|
||||||
colors.pastelPink,
|
theme.colors.logincard1,
|
||||||
colors.pastelGreen,
|
theme.colors.logincard1,
|
||||||
colors.pastelOrange,
|
theme.colors.logincard,
|
||||||
colors.pastelPink,
|
theme.colors.logincard,
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.container}>
|
|
||||||
<StatusBar barStyle="dark-content" backgroundColor={colors.pastelOrange} />
|
|
||||||
|
|
||||||
{/* Funky grid blocks background (Unchanged) */}
|
return (
|
||||||
<View style={styles.gridContainer}>
|
<View style={[ styles.container, {backgroundColor: theme.colors.background }]}>
|
||||||
{colorsBlocks.map((bgColor, index) => (
|
<StatusBar barStyle={theme.mode === "dark" ? "light-content" : "dark-content"} backgroundColor={colors.pastelOrange} />
|
||||||
<View
|
|
||||||
key={index}
|
|
||||||
style={[
|
{/* Funky grid blocks background (Unchanged) */}
|
||||||
styles.gridBlock,
|
<View style={styles.gridContainer}>
|
||||||
{ backgroundColor: bgColor },
|
{colorsBlocks.map((bgColor, index) => (
|
||||||
index % 2 === 0 ? styles.elevatedBlock : {},
|
<View
|
||||||
]}
|
key={index}
|
||||||
/>
|
style={[
|
||||||
))}
|
styles.gridBlock,
|
||||||
</View>
|
{ backgroundColor: bgColor ,borderRadius:16 },
|
||||||
|
index % 2 === 0 ? styles.elevatedBlock : {},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
|
||||||
<KeyboardAvoidingView
|
<KeyboardAvoidingView
|
||||||
style={styles.keyboardAvoidingContainer}
|
style={styles.keyboardAvoidingContainer}
|
||||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
>
|
>
|
||||||
<View style={styles.contentContainer}>
|
<View style={styles.contentContainer}>
|
||||||
<View style={styles.topSection}>
|
<View style={[ styles.topSection, {marginTop:60}]}>
|
||||||
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] }}>
|
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] }}>
|
||||||
<Text style={styles.brand}>CircleCollect</Text>
|
<Text style={[styles.brand, { color: theme.colors.textPrimary }]}>CircleCollect</Text>
|
||||||
<Text style={styles.title}>Welcome Back!</Text>
|
<Text style={[styles.title, { color: theme.colors.textPrimary }]}>Welcome Back!</Text>
|
||||||
<Text style={styles.subtitle}>
|
<Text style={[styles.subtitle, { color: theme.colors.textSecondary }]}>
|
||||||
Let's get you signed in to your community.
|
Let's get you signed in to your community.
|
||||||
</Text>
|
</Text>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] }}>
|
|
||||||
<View style={styles.inputWrapper}>
|
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] ,marginTop: 150}}>
|
||||||
<Ionicons name="call-outline" size={24} color={colors.textLight} style={styles.inputIcon} />
|
<View style={[styles.inputWrapper, { backgroundColor: theme.colors.reverseBackground }]}>
|
||||||
|
<Ionicons name="call-outline" size={24} color={theme.colors.reverseText} style={styles.inputIcon} />
|
||||||
<TextInput
|
<TextInput
|
||||||
style={styles.input}
|
style={[ styles.input, { color: theme.colors.reverseText, fontFamily: FontsFamily.nunitoRegular }]}
|
||||||
placeholder="Enter your mobile number"
|
placeholder="Enter your mobile number"
|
||||||
placeholderTextColor={colors.textLight}
|
placeholderTextColor={theme.colors.reverseText}
|
||||||
value={mobile}
|
value={mobile}
|
||||||
onChangeText={setMobile}
|
onChangeText={setMobile}
|
||||||
keyboardType="phone-pad"
|
keyboardType="phone-pad"
|
||||||
@@ -148,7 +170,8 @@ export default function LoginScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
|
||||||
<Animated.View style={[styles.bottomSection, { transform: [{ scale: ctaScale }] }]}>
|
|
||||||
|
<Animated.View style={[styles.bottomSection, { transform: [{ scale: ctaScale }] }]}>
|
||||||
<MaterialRipple
|
<MaterialRipple
|
||||||
onPress={handleContinue}
|
onPress={handleContinue}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
@@ -157,21 +180,16 @@ export default function LoginScreen() {
|
|||||||
rippleCentered
|
rippleCentered
|
||||||
rippleContainerBorderRadius={30}
|
rippleContainerBorderRadius={30}
|
||||||
>
|
>
|
||||||
<LinearGradient
|
<View style={[styles.buttonGradient, { backgroundColor: theme.colors.reverseBackground }]} >
|
||||||
colors={[colors.pastelPink, colors.pastelOrange]}
|
|
||||||
style={styles.buttonGradient}
|
|
||||||
start={{x: 0, y: 0}}
|
|
||||||
end={{x: 1, y: 1}}
|
|
||||||
>
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<ActivityIndicator color={colors.white} />
|
<ActivityIndicator color={theme.colors.reverseText} />
|
||||||
) : (
|
) : (
|
||||||
<View style={styles.buttonContent}>
|
<View style={styles.buttonContent}>
|
||||||
<Text style={styles.buttonText}>Continue</Text>
|
<Text style={[styles.buttonText, { color: theme.colors.reverseText }]}>Continue</Text>
|
||||||
<Ionicons name="arrow-forward-circle-outline" size={22} color={colors.white} style={{marginLeft: 8}} />
|
<Ionicons name="arrow-forward-circle-outline" size={22} color={theme.colors.reverseText} style={{marginLeft: 8}} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</LinearGradient>
|
</View>
|
||||||
</MaterialRipple>
|
</MaterialRipple>
|
||||||
<Text style={styles.footerText}>
|
<Text style={styles.footerText}>
|
||||||
Your privacy is our priority. Your information is always secure.
|
Your privacy is our priority. Your information is always secure.
|
||||||
@@ -180,6 +198,7 @@ export default function LoginScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
|
|
||||||
|
|
||||||
<CustomAlert
|
<CustomAlert
|
||||||
visible={alertInfo.visible}
|
visible={alertInfo.visible}
|
||||||
title={alertInfo.title}
|
title={alertInfo.title}
|
||||||
@@ -191,6 +210,7 @@ export default function LoginScreen() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -207,11 +227,11 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
},
|
},
|
||||||
elevatedBlock: {
|
elevatedBlock: {
|
||||||
shadowColor: '#000',
|
shadowColor: '#ffffffff',
|
||||||
shadowOffset: { width: 0, height: 5 },
|
shadowOffset: { width: 1, height: 5 },
|
||||||
shadowOpacity: 0.15,
|
shadowOpacity: 1,
|
||||||
shadowRadius: 10,
|
shadowRadius: 15,
|
||||||
elevation: 7,
|
elevation: 10,
|
||||||
},
|
},
|
||||||
keyboardAvoidingContainer: {
|
keyboardAvoidingContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -227,8 +247,7 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
brand: {
|
brand: {
|
||||||
fontSize: responsiveFontSize(2.8),
|
fontSize: responsiveFontSize(3),
|
||||||
fontWeight: '700',
|
|
||||||
color: colors.primary,
|
color: colors.primary,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
letterSpacing: 2,
|
letterSpacing: 2,
|
||||||
@@ -236,33 +255,29 @@ const styles = StyleSheet.create({
|
|||||||
textShadowColor: 'rgba(0, 0, 0, 0.1)',
|
textShadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||||
textShadowOffset: { width: 1, height: 1 },
|
textShadowOffset: { width: 1, height: 1 },
|
||||||
textShadowRadius: 2,
|
textShadowRadius: 2,
|
||||||
|
fontFamily: FontsFamily.nunitoExtraBold,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: responsiveFontSize(4),
|
fontSize: responsiveFontSize(5),
|
||||||
fontWeight: 'bold',
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
color: colors.textDark,
|
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginBottom: 14,
|
marginBottom: 14,
|
||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
fontSize: responsiveFontSize(1.6),
|
fontSize: responsiveFontSize(1.6),
|
||||||
color: colors.textDark,
|
fontFamily: FontsFamily.nunitoRegular,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
||||||
lineHeight: 26,
|
lineHeight: 26,
|
||||||
maxWidth: 320,
|
maxWidth: 320,
|
||||||
},
|
},
|
||||||
inputWrapper: {
|
inputWrapper: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.85)',
|
|
||||||
borderRadius: 36,
|
borderRadius: 36,
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderColor: colors.pastelPink,
|
paddingHorizontal: responsiveHeight(2),
|
||||||
paddingHorizontal: 20,
|
|
||||||
shadowColor: colors.primary,
|
|
||||||
shadowOffset: { width: 0, height: 6 },
|
|
||||||
shadowOpacity: 0.2,
|
|
||||||
shadowRadius: 14,
|
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
},
|
},
|
||||||
inputIcon: {
|
inputIcon: {
|
||||||
@@ -271,9 +286,9 @@ const styles = StyleSheet.create({
|
|||||||
input: {
|
input: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
fontSize: responsiveFontSize(1.8),
|
fontSize: responsiveFontSize(1.8),
|
||||||
fontWeight: '600',
|
fontFamily: FontsFamily.nunitoSemiBold,
|
||||||
color: colors.textLight,
|
color: colors.textLight,
|
||||||
height: 58,
|
height: responsiveHeight(5),
|
||||||
},
|
},
|
||||||
bottomSection: {
|
bottomSection: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -282,16 +297,13 @@ const styles = StyleSheet.create({
|
|||||||
button: {
|
button: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
borderRadius: 30,
|
borderRadius: 30,
|
||||||
shadowColor: colors.primary,
|
|
||||||
shadowOffset: { width: 0, height: 10 },
|
|
||||||
shadowOpacity: 0.4,
|
|
||||||
shadowRadius: 20,
|
|
||||||
elevation: 14,
|
elevation: 14,
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
},
|
},
|
||||||
buttonGradient: {
|
buttonGradient: {
|
||||||
borderRadius: 30,
|
|
||||||
paddingVertical: 18,
|
borderRadius:42,
|
||||||
|
paddingVertical: 14,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -302,8 +314,8 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
buttonText: {
|
buttonText: {
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
fontWeight: '800',
|
|
||||||
fontSize: responsiveFontSize(1.8),
|
fontSize: responsiveFontSize(1.8),
|
||||||
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
},
|
},
|
||||||
footerText: {
|
footerText: {
|
||||||
fontSize: responsiveFontSize(1.4),
|
fontSize: responsiveFontSize(1.4),
|
||||||
@@ -311,5 +323,6 @@ const styles = StyleSheet.create({
|
|||||||
marginTop: 28,
|
marginTop: 28,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
maxWidth: 300,
|
maxWidth: 300,
|
||||||
|
fontFamily: FontsFamily.nunitoRegular,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -21,6 +21,8 @@ import { LOGIN_URL, VARIFY_OTP_URL } from "../utils/ApiUrls";
|
|||||||
import colors from "../components/colors";
|
import colors from "../components/colors";
|
||||||
import CustomAlert from "../components/CostomAlart";
|
import CustomAlert from "../components/CostomAlart";
|
||||||
import { getFcmToken } from "../utils/firebase/firebaseServices";
|
import { getFcmToken } from "../utils/firebase/firebaseServices";
|
||||||
|
import { useTheme } from "../theme/ThemeProvider";
|
||||||
|
import FontsFamily from "../constents/FontsFamily";
|
||||||
|
|
||||||
const CELL_COUNT = 6;
|
const CELL_COUNT = 6;
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
@@ -50,6 +52,7 @@ export default function OtpVerificationScreen() {
|
|||||||
buttons: [],
|
buttons: [],
|
||||||
alertType: "info",
|
alertType: "info",
|
||||||
});
|
});
|
||||||
|
const { theme } = useTheme();
|
||||||
|
|
||||||
const inputs = useRef<Array<TextInput | null>>([]);
|
const inputs = useRef<Array<TextInput | null>>([]);
|
||||||
const route = useRoute<OtpVerifyRouteProp>();
|
const route = useRoute<OtpVerifyRouteProp>();
|
||||||
@@ -133,17 +136,17 @@ export default function OtpVerificationScreen() {
|
|||||||
await getFcmToken(res.data?.data?.userId);
|
await getFcmToken(res.data?.data?.userId);
|
||||||
|
|
||||||
let hasActionRun = false;
|
let hasActionRun = false;
|
||||||
const successAction = () => {
|
const successAction = () => {
|
||||||
if (hasActionRun) return;
|
if (hasActionRun) return;
|
||||||
hasActionRun = true;
|
hasActionRun = true;
|
||||||
hideAlert();
|
hideAlert();
|
||||||
navigation.dispatch(
|
navigation.dispatch(
|
||||||
CommonActions.reset({
|
CommonActions.reset({
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [{ name: 'Home' }],
|
routes: [{ name: 'Home' }],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
triggerAlert(
|
triggerAlert(
|
||||||
'Success!',
|
'Success!',
|
||||||
@@ -238,56 +241,64 @@ export default function OtpVerificationScreen() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const colorsBlocks = [
|
const colorsBlocks = [
|
||||||
colors.pastelPink,
|
theme.colors.logincard,
|
||||||
colors.pastelBlue,
|
theme.colors.logincard1,
|
||||||
colors.pastelGreen,
|
theme.colors.logincard1,
|
||||||
colors.pastelOrange,
|
theme.colors.logincard,
|
||||||
colors.pastelBlue,
|
theme.colors.logincard,
|
||||||
colors.pastelPink,
|
theme.colors.logincard1,
|
||||||
colors.pastelGreen,
|
theme.colors.logincard1,
|
||||||
colors.pastelOrange,
|
theme.colors.logincard,
|
||||||
colors.pastelPink,
|
theme.colors.logincard,
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={[styles.container, {backgroundColor: theme.colors.background }]}>
|
||||||
<StatusBar barStyle="dark-content" backgroundColor={colors.pastelOrange} />
|
<StatusBar barStyle={theme.mode === "dark" ? "light-content" : "dark-content"} backgroundColor={colors.pastelOrange} />
|
||||||
|
|
||||||
<View style={styles.gridContainer}>
|
<View style={styles.gridContainer}>
|
||||||
{colorsBlocks.map((bgColor, index) => (
|
{colorsBlocks.map((bgColor, index) => (
|
||||||
<View
|
<View
|
||||||
key={index}
|
key={index}
|
||||||
style={[
|
style={[
|
||||||
styles.gridBlock,
|
styles.gridBlock,
|
||||||
{ backgroundColor: bgColor },
|
{ backgroundColor: bgColor, borderRadius: 16 },
|
||||||
index % 2 === 0 ? styles.elevatedBlock : {},
|
index % 2 === 0 ? styles.elevatedBlock : {},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<KeyboardAvoidingView style={styles.keyboardAvoidingContainer} behavior={Platform.OS === "ios" ? "padding" : undefined}>
|
<KeyboardAvoidingView style={styles.keyboardAvoidingContainer} behavior={Platform.OS === "ios" ? "padding" : undefined}>
|
||||||
|
|
||||||
<CustomAlert {...alertConfig} />
|
<CustomAlert {...alertConfig} />
|
||||||
|
|
||||||
<View style={styles.contentPanel}>
|
<View style={[styles.contentPanel, { backgroundColor: theme.colors.reverseBackground }]}>
|
||||||
<View style={styles.topSection}>
|
<View style={styles.topSection}>
|
||||||
<Text style={styles.title}>Verify Your Code</Text>
|
<Text style={[styles.title, { color: theme.colors.reverseText }]}>Verify Your Code</Text>
|
||||||
<Text style={styles.subtitle}>We’ve sent a 6-digit verification code to +91 {mobile}.</Text>
|
<Text style={[styles.subtitle, { color: theme.colors.reverseText }]}>We’ve sent a 6-digit verification code to +91 {mobile}.</Text>
|
||||||
|
|
||||||
<Animated.View style={[styles.otpRow, { opacity: fade, transform: [{ translateY: slide }] }]}>
|
<Animated.View style={[styles.otpRow, { transform: [{ translateY: slide }] }]}>
|
||||||
{Array.from({ length: CELL_COUNT }).map((_, i) => (
|
{Array.from({ length: CELL_COUNT }).map((_, i) => (
|
||||||
<TextInput
|
<TextInput
|
||||||
key={`otp-${i}`}
|
key={`otp-${i}`}
|
||||||
ref={(r) => { inputs.current[i] = r; }}
|
ref={(r) => { inputs.current[i] = r; }}
|
||||||
style={[styles.cell, code[i] ? styles.cellFilled : null]}
|
// UPDATED CELL STYLE
|
||||||
|
style={[
|
||||||
|
styles.cell,
|
||||||
|
code[i] ? styles.cellFilled : null,
|
||||||
|
{
|
||||||
|
backgroundColor: theme.colors.optCard,
|
||||||
|
color: theme.colors.reverseText,
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
|
||||||
keyboardType="number-pad"
|
keyboardType="number-pad"
|
||||||
maxLength={i === 0 ? CELL_COUNT : 1}
|
maxLength={i === 0 ? CELL_COUNT : 1}
|
||||||
value={code[i]}
|
value={code[i]}
|
||||||
onChangeText={(t) => (i === 0 ? handleFirstCellChange(t) : updateIndex(i, t))}
|
onChangeText={(t) => (i === 0 ? handleFirstCellChange(t) : updateIndex(i, t))}
|
||||||
onKeyPress={(e) => handleKeyPress(i, e)}
|
onKeyPress={(e) => handleKeyPress(i, e)}
|
||||||
placeholder="•"
|
placeholder="*"
|
||||||
placeholderTextColor="#BDBDBD"
|
placeholderTextColor="#BDBDBD"
|
||||||
textContentType="oneTimeCode"
|
textContentType="oneTimeCode"
|
||||||
/>
|
/>
|
||||||
@@ -300,16 +311,16 @@ export default function OtpVerificationScreen() {
|
|||||||
onPressIn={() => Animated.spring(ctaScale, { toValue: 0.97, useNativeDriver: true }).start()}
|
onPressIn={() => Animated.spring(ctaScale, { toValue: 0.97, useNativeDriver: true }).start()}
|
||||||
onPressOut={() => Animated.spring(ctaScale, { toValue: 1, useNativeDriver: true }).start()}
|
onPressOut={() => Animated.spring(ctaScale, { toValue: 1, useNativeDriver: true }).start()}
|
||||||
onPress={() => onSubmit(code.join(""), mobile)}
|
onPress={() => onSubmit(code.join(""), mobile)}
|
||||||
style={styles.button}
|
style={[styles.button, { backgroundColor: theme.colors.background }]}
|
||||||
>
|
>
|
||||||
<Text style={styles.buttonText}>Verify & Continue</Text>
|
<Text style={[styles.buttonText, { color: theme.colors.textPrimary }]}>Verify & Continue</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|
||||||
{timer > 0 ? (
|
{timer > 0 ? (
|
||||||
<Text style={styles.footerText}>Resend code in 00:{timer.toString().padStart(2, "0")}</Text>
|
<Text style={[styles.footerText, { color: theme.colors.reverseText }]}>Resend code in 00:{timer.toString().padStart(2, "0")}</Text>
|
||||||
) : (
|
) : (
|
||||||
<Pressable onPress={resendOtp} disabled={isResending}>
|
<Pressable onPress={resendOtp} disabled={isResending}>
|
||||||
<Text style={[styles.footerText, { color: colors.pastelPink, fontWeight: '600' }]}>
|
<Text style={[styles.footerText, { color: theme.colors.reverseText, fontWeight: '600' }]}>
|
||||||
{isResending ? "Resending..." : "Resend Code"}
|
{isResending ? "Resending..." : "Resend Code"}
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
@@ -335,16 +346,15 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
},
|
},
|
||||||
elevatedBlock: {
|
elevatedBlock: {
|
||||||
shadowColor: '#000',
|
shadowColor: '#ffffffff',
|
||||||
shadowOffset: { width: 0, height: 5 },
|
shadowOffset: { width: 1, height: 5 },
|
||||||
shadowOpacity: 0.15,
|
shadowOpacity: 1,
|
||||||
shadowRadius: 10,
|
shadowRadius: 15,
|
||||||
elevation: 7,
|
elevation: 10,
|
||||||
},
|
},
|
||||||
keyboardAvoidingContainer: { flex: 1, justifyContent: 'center' },
|
keyboardAvoidingContainer: { flex: 1, justifyContent: 'center' },
|
||||||
contentPanel: {
|
contentPanel: {
|
||||||
marginHorizontal: 24,
|
marginHorizontal: 24,
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
|
||||||
borderRadius: 32,
|
borderRadius: 32,
|
||||||
padding: 28,
|
padding: 28,
|
||||||
shadowColor: '#000',
|
shadowColor: '#000',
|
||||||
@@ -354,13 +364,33 @@ const styles = StyleSheet.create({
|
|||||||
elevation: 12,
|
elevation: 12,
|
||||||
},
|
},
|
||||||
topSection: { alignItems: 'center', marginBottom: 24 },
|
topSection: { alignItems: 'center', marginBottom: 24 },
|
||||||
title: { fontSize: 28, fontWeight: "bold", color: colors.textDark, textAlign: 'center', marginBottom: 12 },
|
title: { fontSize: 28, color: colors.textDark, textAlign: 'center', marginBottom: 12 ,fontFamily: FontsFamily.nunitoExtraBold},
|
||||||
subtitle: { fontSize: 16, color: colors.textLight, textAlign: 'center', marginBottom: 32, lineHeight: 24, maxWidth: 300 },
|
subtitle: { fontSize: 16, color: colors.textLight, textAlign: 'center', marginBottom: 32, lineHeight: 24, maxWidth: 300 ,fontFamily: FontsFamily.nunitoMedium},
|
||||||
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 },
|
otpRow: {
|
||||||
cellFilled: { borderColor: colors.primary, backgroundColor: '#F7F2FF' },
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: '100%',
|
||||||
|
paddingHorizontal: 0, // Removed padding to use full width
|
||||||
|
},
|
||||||
|
|
||||||
|
// FIX: Updated Cell Styling for clean smooth radius
|
||||||
|
cell: {
|
||||||
|
width: 45,
|
||||||
|
height: 52,
|
||||||
|
borderRadius: 14, // Smoother radius
|
||||||
|
textAlign: "center",
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "600",
|
||||||
|
elevation: 0, // Removed elevation for flat look (or keep if you want shadow)
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
cellFilled: {
|
||||||
|
// Optional: Add specific style when filled if needed, handled inline above
|
||||||
|
},
|
||||||
|
|
||||||
bottomSection: { paddingBottom: Platform.OS === "ios" ? 20 : 10, paddingTop: 10 },
|
bottomSection: { paddingBottom: Platform.OS === "ios" ? 20 : 10, paddingTop: 10 },
|
||||||
button: { backgroundColor: colors.pastelPink, paddingVertical: 18, borderRadius: 30, alignItems: "center", justifyContent: "center", shadowColor: colors.primary, shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.3, shadowRadius: 15, elevation: 8 ,borderWidth:2, borderColor:colors.pastelPink},
|
button: { backgroundColor: colors.pastelPink, paddingVertical: 18, borderRadius: 30, alignItems: "center", justifyContent: "center",},
|
||||||
buttonText: { color: colors.white, fontWeight: "700", fontSize: 16 },
|
buttonText: { color: colors.white, fontSize: 16, fontFamily: FontsFamily.nunitoBold },
|
||||||
footerText: { textAlign: "center", color: colors.textLight, fontSize: 14, marginTop: 20 },
|
footerText: { textAlign: "center", fontFamily: FontsFamily.nunitoBold, fontSize: 14, marginTop: 20 },
|
||||||
});
|
});
|
||||||
|
|||||||
+19
-11
@@ -10,6 +10,7 @@ import {
|
|||||||
ListRenderItem,
|
ListRenderItem,
|
||||||
Alert,
|
Alert,
|
||||||
RefreshControl,
|
RefreshControl,
|
||||||
|
StatusBar,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import AppView from "../../components/AppView";
|
import AppView from "../../components/AppView";
|
||||||
import colors from "../../components/colors";
|
import colors from "../../components/colors";
|
||||||
@@ -23,6 +24,10 @@ import AnimatedCard from "../../components/common/AnimatedCard";
|
|||||||
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
||||||
import { apiCall } from "../../utils/ApiHelper";
|
import { apiCall } from "../../utils/ApiHelper";
|
||||||
import CustomAlert, { CustomAlertProps } from "../../components/CostomAlart";
|
import CustomAlert, { CustomAlertProps } from "../../components/CostomAlart";
|
||||||
|
import { useTheme } from "../../theme/ThemeProvider";
|
||||||
|
import FontsFamily from "../../constents/FontsFamily";
|
||||||
|
import { responsiveFontSize, responsiveHeight } from "react-native-responsive-dimensions";
|
||||||
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
|
|
||||||
if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
|
if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
|
||||||
UIManager.setLayoutAnimationEnabledExperimental(true);
|
UIManager.setLayoutAnimationEnabledExperimental(true);
|
||||||
@@ -80,6 +85,8 @@ const Home: React.FC = () => {
|
|||||||
const [userDashboard, setUserDashboard] = useState<any>(null);
|
const [userDashboard, setUserDashboard] = useState<any>(null);
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
const [statusData, setStatusData] = useState<any>(null);
|
const [statusData, setStatusData] = useState<any>(null);
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
const {theme} = useTheme();
|
||||||
const getDashboardData = async () => {
|
const getDashboardData = async () => {
|
||||||
try {
|
try {
|
||||||
const result = (await apiCall(DASHBOARD_URL, "GET")) as any;
|
const result = (await apiCall(DASHBOARD_URL, "GET")) as any;
|
||||||
@@ -186,7 +193,8 @@ const Home: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppView barStyle="dark-content" style={styles.container}>
|
<View style={[ styles.container, {backgroundColor: theme.colors.background, paddingBottom: insets.bottom + responsiveHeight(10) }]}>
|
||||||
|
<StatusBar barStyle={theme.mode === "dark" ? "light-content" : "dark-content"}/>
|
||||||
<FlatList
|
<FlatList
|
||||||
data={actions}
|
data={actions}
|
||||||
numColumns={2}
|
numColumns={2}
|
||||||
@@ -195,18 +203,19 @@ const Home: React.FC = () => {
|
|||||||
ListHeaderComponent={
|
ListHeaderComponent={
|
||||||
<>
|
<>
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
<View>
|
<View style={{ flexDirection: "row", alignItems: "center", gap: 8 ,marginTop: responsiveHeight(2) }} >
|
||||||
<Text style={styles.greeting}>
|
<Text style={[styles.greeting, { color: theme.colors.textPrimary }]}>
|
||||||
Hello, <Text style={{ fontWeight: 'bold' }}>{user.firstName || apiUser?.firstName || "User"}</Text>
|
Hello,
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text style={{ fontFamily:FontsFamily.nunitoExtraBold,color: theme.colors.textPrimary,fontSize:responsiveFontSize(2.5) }}>{user.firstName || apiUser?.firstName || "User"}</Text>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity onPress={() => navigation.navigate("Notification" as never)}>
|
<TouchableOpacity onPress={() => navigation.navigate("Notification" as never)} style={{ marginTop: responsiveHeight(2) ,}}>
|
||||||
{unreadCount > 0 && (
|
{unreadCount > 0 && (
|
||||||
<View style={styles.badge}>
|
<View style={styles.badge}>
|
||||||
<Text style={styles.badgeText}>{unreadCount}</Text>
|
<Text style={styles.badgeText}>{unreadCount}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<Ionicons name="notifications-outline" size={30} color={colors.textDark} />
|
<Ionicons name="notifications-outline" size={30} color={theme.colors.textPrimary} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -217,7 +226,7 @@ const Home: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<View style={styles.actionHeader}>
|
<View style={styles.actionHeader}>
|
||||||
<Text style={styles.sectionTitle}>Quick Actions</Text>
|
<Text style={[styles.sectionTitle,{ color: theme.colors.textPrimary }]}>Quick Actions </Text>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</>
|
</>
|
||||||
@@ -243,7 +252,7 @@ const Home: React.FC = () => {
|
|||||||
onClose={() => setAlertVisible(false)}
|
onClose={() => setAlertVisible(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</AppView>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -252,7 +261,6 @@ export default Home;
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: colors.white,
|
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
@@ -262,8 +270,8 @@ const styles = StyleSheet.create({
|
|||||||
paddingTop: 24,
|
paddingTop: 24,
|
||||||
paddingBottom: 16,
|
paddingBottom: 16,
|
||||||
},
|
},
|
||||||
greeting: { fontSize: 22, color: colors.textDark },
|
greeting: { fontSize: 22,fontFamily: FontsFamily.nunitoLight },
|
||||||
sectionTitle: { fontSize: 20, fontWeight: "600", color: colors.textDark, flex: 1 },
|
sectionTitle: { fontSize: 20, fontWeight: "600", color: colors.textDark, flex: 1 ,fontFamily: FontsFamily.nunitoSemiBold},
|
||||||
actionHeader: {
|
actionHeader: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import {
|
|||||||
responsiveWidth,
|
responsiveWidth,
|
||||||
responsiveFontSize
|
responsiveFontSize
|
||||||
} from "react-native-responsive-dimensions";
|
} from "react-native-responsive-dimensions";
|
||||||
|
import { useTheme } from "../../theme/ThemeProvider";
|
||||||
|
import FontsFamily from "../../constents/FontsFamily";
|
||||||
|
|
||||||
type StatusData = {
|
type StatusData = {
|
||||||
role?: string;
|
role?: string;
|
||||||
@@ -73,7 +75,7 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
const [showPayDialog, setShowPayDialog] = useState(false);
|
const [showPayDialog, setShowPayDialog] = useState(false);
|
||||||
const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([]);
|
const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([]);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
const {theme} = useTheme();
|
||||||
// console.log("user me : ", userDashboard)
|
// console.log("user me : ", userDashboard)
|
||||||
// Preselect all due groups at mount and on change
|
// Preselect all due groups at mount and on change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -92,12 +94,12 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
// Top grid info items
|
// Top grid info items
|
||||||
const infoItems = useMemo(
|
const infoItems = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ icon: <Ionicons name="person-outline" size={20} color={colors.primary} />, label: "Role", value: statusData?.role || "-" },
|
{ icon: <Ionicons name="person-outline" size={20} color={theme.colors.black} />, label: "Role", value: statusData?.role || "-" },
|
||||||
{ icon: <Ionicons name="pie-chart-outline" size={20} color={colors.primary} />, label: "Active Groups", value: userDashboard?.activeStatusMyGroupCount?.toString() || "0" },
|
{ icon: <Ionicons name="pie-chart-outline" size={20} color={theme.colors.black} />, label: "Active Groups", value: userDashboard?.activeStatusMyGroupCount?.toString() || "0" },
|
||||||
{ icon: <Ionicons name="book-outline" size={20} color={colors.primary} />, label: "Joined Groups", value: userDashboard?.myJoinedGroups?.length?.toString() || "0" },
|
{ icon: <Ionicons name="book-outline" size={20} color={theme.colors.black} />, label: "Joined Groups", value: userDashboard?.myJoinedGroups?.length?.toString() || "0" },
|
||||||
{ icon: <Ionicons name="people-outline" size={20} color={colors.primary} />, label: "My Groups", value: userDashboard?.myCreatedGroups?.length?.toString() || "0" },
|
{ icon: <Ionicons name="people-outline" size={20} color={theme.colors.black} />, label: "My Groups", value: userDashboard?.myCreatedGroups?.length?.toString() || "0" },
|
||||||
{ icon: <Ionicons name="document-text-outline" size={20} color={colors.primary} />, label: "Total Due", value: `₹${userDashboard?.multiplePayAmount || 0}` },
|
{ icon: <Ionicons name="document-text-outline" size={20} color={theme.colors.black} />, label: "Total Due", value: `₹${userDashboard?.multiplePayAmount || 0}` },
|
||||||
{ icon: <Ionicons name="checkmark-done-outline" size={20} color={colors.primary} />, label: "Completed", value: userDashboard?.completeStatusMyGroupCount?.toString() || "0" },
|
{ icon: <Ionicons name="checkmark-done-outline" size={20} color={theme.colors.black} />, label: "Completed", value: userDashboard?.completeStatusMyGroupCount?.toString() || "0" },
|
||||||
],
|
],
|
||||||
[userDashboard, statusData]
|
[userDashboard, statusData]
|
||||||
);
|
);
|
||||||
@@ -153,18 +155,18 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
|
|
||||||
// Bottom bar
|
// Bottom bar
|
||||||
const renderDueBar = () => (
|
const renderDueBar = () => (
|
||||||
<View style={styles.dueBar}>
|
<View style={[ styles.dueBar, { borderTopColor: theme.colors.border, backgroundColor: theme.colors.gray }]}>
|
||||||
<Text style={styles.dueBarText}>
|
<Text style={[styles.dueBarText, { color: theme.colors.black }]}>
|
||||||
Total Due: <Text style={{ color: "#FFDE03", fontWeight: "bold" }}>₹{totalDue}</Text>
|
Total Due: <Text style={{ color: theme.colors.black, fontWeight: "bold" }}>₹{totalDue}</Text>
|
||||||
</Text>
|
</Text>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.payAllButton}
|
style={[styles.payAllButton, { backgroundColor: theme.colors.black }]}
|
||||||
onPress={() => setShowPayDialog(true)}
|
onPress={() => setShowPayDialog(true)}
|
||||||
disabled={dueGroups.length === 0}
|
disabled={dueGroups.length === 0}
|
||||||
activeOpacity={0.8}
|
activeOpacity={0.8}
|
||||||
>
|
>
|
||||||
<Ionicons name="wallet-outline" size={20} color="#000000ff" />
|
<Ionicons name="wallet-outline" size={20} color={theme.colors.white} />
|
||||||
<Text style={styles.payAllButtonText}>Pay All</Text>
|
<Text style={[styles.payAllButtonText, { color: theme.colors.white }]}>Pay All</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -173,17 +175,14 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
const renderPayDialog = () => (
|
const renderPayDialog = () => (
|
||||||
<Modal visible={showPayDialog} transparent animationType="fade" onRequestClose={() => setShowPayDialog(false)}>
|
<Modal visible={showPayDialog} transparent animationType="fade" onRequestClose={() => setShowPayDialog(false)}>
|
||||||
<View style={styles.payModalOverlay}>
|
<View style={styles.payModalOverlay}>
|
||||||
<LinearGradient
|
<View
|
||||||
colors={[colors.white, colors.white]}
|
style={[styles.payModalBox, { backgroundColor: theme.colors.reverseBackground }]}
|
||||||
start={{ x: 0.2, y: 0 }}
|
|
||||||
end={{ x: 1, y: 1 }}
|
|
||||||
style={styles.payModalBox}
|
|
||||||
>
|
>
|
||||||
<View style={styles.payDialogHeader}>
|
<View style={styles.payDialogHeader}>
|
||||||
<Ionicons name="card-outline" color="#000000ff" size={22} />
|
<Ionicons name="card-outline" color={theme.colors.reverseText} size={22} />
|
||||||
<Text style={styles.payDialogTitle}>Select Groups to Pay</Text>
|
<Text style={[styles.payDialogTitle, { color: theme.colors.reverseText }]}>Select Groups to Pay</Text>
|
||||||
<TouchableOpacity onPress={() => setShowPayDialog(false)}>
|
<TouchableOpacity onPress={() => setShowPayDialog(false)}>
|
||||||
<Ionicons name="close-circle" color="#000000ff" size={24} />
|
<Ionicons name="close-circle" color={theme.colors.reverseText} size={24} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
@@ -193,70 +192,73 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
{dueGroups.map((group) => (
|
{dueGroups.map((group) => (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
key={group.groupId}
|
key={group.groupId}
|
||||||
style={[
|
style={[
|
||||||
styles.payGroupOption,
|
styles.payGroupOption,
|
||||||
selectedGroupIds.includes(group.groupId) && styles.payOptionSelected,
|
{ borderColor: theme.colors.background, borderWidth: 1 },
|
||||||
]}
|
|
||||||
|
selectedGroupIds.includes(group.groupId) && {
|
||||||
|
...styles.payOptionSelected,
|
||||||
|
borderColor: theme.colors.reverseBackground,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
|
||||||
onPress={() => handleToggleGroup(group.groupId)}
|
onPress={() => handleToggleGroup(group.groupId)}
|
||||||
activeOpacity={0.85}
|
activeOpacity={0.85}
|
||||||
>
|
>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name={selectedGroupIds.includes(group.groupId) ? "checkbox" : "square-outline"}
|
name={selectedGroupIds.includes(group.groupId) ? "checkbox" : "square-outline"}
|
||||||
size={22}
|
size={22}
|
||||||
color={selectedGroupIds.includes(group.groupId) ? colors.primary : "#000000ff"}
|
color={selectedGroupIds.includes(group.groupId) ? theme.colors.reverseText : theme.colors.reverseText}
|
||||||
/>
|
/>
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<Text style={[styles.payGroupName, { color: "#000000ff" }]}>{group.groupName}</Text>
|
<Text style={[styles.payGroupName, {color: theme.colors.reverseText}]}>{group.groupName}</Text>
|
||||||
<Text style={styles.payDueText}>
|
<Text style={[styles.payDueText, {color: theme.colors.reverseText}]}>
|
||||||
₹{group.baseAmount}
|
₹{group.baseAmount}
|
||||||
{group.lateFee > 0 ? ` (Late: ₹${group.lateFee})` : ""}
|
{group.lateFee > 0 ? ` (Late: ₹${group.lateFee})` : ""}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.payAmount, { color: "#4CAF50" }]}>₹{group.totalDue}</Text>
|
{/* <Text style={[styles.payAmount, { color: "#4CAF50" }]}>₹{group.totalDue}</Text> */}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
))}
|
))}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<View style={styles.payDialogFooter}>
|
<View style={styles.payDialogFooter}>
|
||||||
<Text style={styles.payDialogTotal}>
|
<Text style={[styles.payDialogTotal, { color: theme.colors.reverseText }]}>
|
||||||
Total: <Text style={{ fontWeight: "bold", color: "#ff5f03ff" }}>₹{totalDueSelected}</Text>
|
Total : <Text style={{ fontFamily: FontsFamily.nunitoBold, color: theme.colors.red }}>₹{totalDueSelected}</Text>
|
||||||
</Text>
|
</Text>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.payConfirmButton, { opacity: submitting ? 0.7 : 1 }]}
|
style={[styles.payConfirmButton, { opacity: submitting ? 0.7 : 1 , backgroundColor: theme.colors.background}]}
|
||||||
onPress={handlePayAll}
|
onPress={handlePayAll}
|
||||||
disabled={submitting || selectedGroupIds.length === 0}
|
disabled={submitting || selectedGroupIds.length === 0}
|
||||||
activeOpacity={0.8}
|
activeOpacity={0.8}
|
||||||
>
|
>
|
||||||
{submitting ? (
|
{submitting ? (
|
||||||
<ActivityIndicator color="#fff" />
|
<ActivityIndicator color={theme.colors.textPrimary} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Ionicons name="checkmark-circle" size={22} color="#ffffffff" />
|
<Ionicons name="checkmark-circle" size={22} color={theme.colors.textPrimary} />
|
||||||
<Text style={styles.payButtonText}>Pay Selected</Text>
|
<Text style={[styles.payButtonText, { fontFamily: FontsFamily.nunitoSemiBold ,color: theme.colors.textPrimary}]}>Pay Selected</Text>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</LinearGradient>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<LinearGradient
|
<View
|
||||||
colors={[colors.primary, colors.pastelPink]}
|
style={[styles.card, { backgroundColor: theme.colors.reverseBackground }]}
|
||||||
start={{ x: 0, y: 0 }}
|
|
||||||
end={{ x: 1, y: 1 }}
|
|
||||||
style={styles.card}
|
|
||||||
>
|
>
|
||||||
<View style={styles.headerSection}>
|
<View style={styles.headerSection}>
|
||||||
<View style={styles.titleWithIcon}>
|
<View style={styles.titleWithIcon}>
|
||||||
<Ionicons name="stats-chart" size={24} color="#fff" style={styles.headerIcon} />
|
<Ionicons name="stats-chart" size={24} color={theme.colors.reverseText} style={styles.headerIcon} />
|
||||||
<Text style={styles.header}>Profile Overview</Text>
|
<Text style={[styles.header, { color: theme.colors.reverseText} ]}>Profile Overview</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.statusBadge}>
|
<View style={[styles.statusBadge, { backgroundColor: theme.colors.background}]}>
|
||||||
<Ionicons name="shield-checkmark" size={16} color="#fff" />
|
<Ionicons name="shield-checkmark" size={16} color={theme.colors.textPrimary} />
|
||||||
<Text style={styles.statusBadgeText}>
|
<Text style={[styles.statusBadgeText, { color: theme.colors.textPrimary }]}>
|
||||||
{statusData?.profileStatus ? "Verified" : "Pending"}
|
{statusData?.profileStatus ? "Verified" : "Pending"}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -265,16 +267,16 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
<View style={styles.leftSection}>
|
<View style={styles.leftSection}>
|
||||||
<View style={styles.infoGrid}>
|
<View style={styles.infoGrid}>
|
||||||
{infoItems.map((item, idx) => (
|
{infoItems.map((item, idx) => (
|
||||||
<View key={item.label} style={styles.infoCard}>
|
<View key={item.label} style={[styles.infoCard,{backgroundColor: theme.colors.background}]}>
|
||||||
<View style={styles.infoCardHeader}>
|
<View style={styles.infoCardHeader}>
|
||||||
<View style={styles.iconContainer}>
|
<View style={[styles.iconContainer, {backgroundColor: theme.colors.optCard || theme.colors.card}]}>
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.infoLabel} >
|
<Text style={[styles.infoLabel,{color: theme.colors.textPrimary}]} >
|
||||||
{item.label}
|
{item.label}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.infoValue, { color: getValueColor(item.value) }]} numberOfLines={1}>
|
<Text style={[styles.infoValue, { color: theme.colors.textPrimary }]} numberOfLines={1}>
|
||||||
{item.value}
|
{item.value}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -296,16 +298,16 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.infoCardOne}>
|
<View style={[styles.infoCardOne,{backgroundColor: theme.colors.background}]}>
|
||||||
<Text style={{ color: "#fff", fontSize: responsiveWidth(2.3)}}>Total Paid Amount <Text style={{ fontWeight: "900"}}>{userDashboard?.totalPaidAmountMonth}</Text></Text>
|
<Text style={{ color: theme.colors.textPrimary, fontSize: responsiveWidth(3), fontFamily: FontsFamily.nunitoSemiBold,}}>Total Paid Amount</Text>
|
||||||
{/* <Text style={{ color: "#fff", fontWeight: "400"}}>Total Paid Amount {userDashboard?.totalPaidAmountMonth}</Text> */}
|
<Text style={{ color: theme.colors.textPrimary, fontWeight: "400", fontFamily: FontsFamily.nunitoRegular}}>{userDashboard?.totalPaidAmountMonth}</Text>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{renderDueBar()}
|
{renderDueBar()}
|
||||||
</LinearGradient>
|
</View>
|
||||||
|
|
||||||
{renderPayDialog()}
|
{renderPayDialog()}
|
||||||
|
|
||||||
@@ -377,8 +379,8 @@ const styles = StyleSheet.create({
|
|||||||
marginRight: 8
|
marginRight: 8
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
fontSize: responsiveWidth(3.5),
|
fontSize: responsiveWidth(4.5),
|
||||||
fontWeight: "700",
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
color: "#fff"
|
color: "#fff"
|
||||||
},
|
},
|
||||||
statusBadge: {
|
statusBadge: {
|
||||||
@@ -411,14 +413,11 @@ const styles = StyleSheet.create({
|
|||||||
gap: 10
|
gap: 10
|
||||||
},
|
},
|
||||||
infoCard: {
|
infoCard: {
|
||||||
backgroundColor: 'rgba(255,255,255,0.15)',
|
|
||||||
borderRadius: 14,
|
|
||||||
padding: 12,
|
padding: 12,
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: 'rgba(255,255,255,0.2)',
|
|
||||||
flex: 1,
|
flex: 1,
|
||||||
minWidth: '45%',
|
minWidth: '45%',
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
|
borderRadius:12
|
||||||
},
|
},
|
||||||
infoCardOne: {
|
infoCardOne: {
|
||||||
backgroundColor: 'rgba(255,255,255,0.15)',
|
backgroundColor: 'rgba(255,255,255,0.15)',
|
||||||
@@ -436,25 +435,22 @@ const styles = StyleSheet.create({
|
|||||||
marginBottom: 6
|
marginBottom: 6
|
||||||
},
|
},
|
||||||
iconContainer: {
|
iconContainer: {
|
||||||
width: 28,
|
width: responsiveWidth(8),
|
||||||
height: 28,
|
height: responsiveHeight(3.5),
|
||||||
backgroundColor: '#fff',
|
borderRadius: responsiveWidth(2),
|
||||||
borderRadius: 8,
|
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
infoLabel: {
|
infoLabel: {
|
||||||
color: "rgba(255,255,255,0.9)",
|
fontSize: responsiveWidth(3),
|
||||||
fontSize: responsiveWidth(2),
|
fontFamily: FontsFamily.nunitoSemiBold,
|
||||||
fontWeight: '500',
|
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
},
|
},
|
||||||
infoValue: {
|
infoValue: {
|
||||||
fontWeight: "700",
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
fontSize: responsiveWidth(2.5),
|
fontSize: responsiveWidth(3),
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
color: "#fff"
|
|
||||||
},
|
},
|
||||||
profileSection: {
|
profileSection: {
|
||||||
width: 90,
|
width: 90,
|
||||||
@@ -498,16 +494,13 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
padding: 16,
|
padding: 16,
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
borderColor: "rgba(255,255,255,0.15)",
|
|
||||||
backgroundColor: "rgba(0,0,0,0.15)",
|
|
||||||
},
|
},
|
||||||
dueBarText: {
|
dueBarText: {
|
||||||
color: "#fff",
|
fontFamily: FontsFamily.nunitoExtraBold,
|
||||||
fontSize: responsiveWidth(2.5),
|
fontSize: responsiveWidth(4),
|
||||||
fontWeight: "600"
|
|
||||||
},
|
},
|
||||||
payAllButton: {
|
payAllButton: {
|
||||||
backgroundColor: "#ffffffff",
|
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
@@ -516,8 +509,7 @@ const styles = StyleSheet.create({
|
|||||||
gap: 6,
|
gap: 6,
|
||||||
},
|
},
|
||||||
payAllButtonText: {
|
payAllButtonText: {
|
||||||
color: "#000000ff",
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
fontWeight: "bold",
|
|
||||||
fontSize: responsiveWidth(2.5)
|
fontSize: responsiveWidth(2.5)
|
||||||
},
|
},
|
||||||
payModalOverlay: {
|
payModalOverlay: {
|
||||||
@@ -527,7 +519,7 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
payModalBox: {
|
payModalBox: {
|
||||||
width: "92%",
|
width: "90%",
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -547,9 +539,10 @@ const styles = StyleSheet.create({
|
|||||||
borderColor: "rgba(255,255,255,0.1)",
|
borderColor: "rgba(255,255,255,0.1)",
|
||||||
},
|
},
|
||||||
payDialogTitle: {
|
payDialogTitle: {
|
||||||
color: "#000000ff",
|
|
||||||
fontSize: responsiveWidth(1.8),
|
fontSize: responsiveWidth(4),
|
||||||
fontWeight: "700"
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
|
|
||||||
},
|
},
|
||||||
payGroupOption: {
|
payGroupOption: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
@@ -557,24 +550,20 @@ const styles = StyleSheet.create({
|
|||||||
gap: 16,
|
gap: 16,
|
||||||
paddingVertical: 12,
|
paddingVertical: 12,
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
borderColor: colors.primary,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
payOptionSelected: {
|
payOptionSelected: {
|
||||||
backgroundColor: "rgba(166, 49, 255, 0.2)",
|
|
||||||
borderColor: colors.primary,
|
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
},
|
},
|
||||||
payGroupName: {
|
payGroupName: {
|
||||||
color: "#000000ff",
|
fontFamily: FontsFamily.nunitoSemiBold,
|
||||||
fontWeight: "700",
|
fontSize: responsiveWidth(3)
|
||||||
fontSize: responsiveWidth(2.5)
|
|
||||||
},
|
},
|
||||||
payDueText: {
|
payDueText: {
|
||||||
color: "rgba(0, 0, 0, 0.8)",
|
fontSize: responsiveWidth(3),
|
||||||
fontSize: responsiveWidth(1.3),
|
fontFamily: FontsFamily.nunitoRegular,
|
||||||
marginTop: 2
|
marginTop: 2
|
||||||
},
|
},
|
||||||
payAmount: {
|
payAmount: {
|
||||||
@@ -591,26 +580,23 @@ const styles = StyleSheet.create({
|
|||||||
paddingHorizontal: 18,
|
paddingHorizontal: 18,
|
||||||
},
|
},
|
||||||
payDialogTotal: {
|
payDialogTotal: {
|
||||||
color: "#000000ff",
|
fontFamily: FontsFamily.nunitoBold,
|
||||||
fontWeight: "600",
|
fontSize: responsiveWidth(3.5)
|
||||||
fontSize: responsiveWidth(1.7)
|
|
||||||
},
|
},
|
||||||
payConfirmButton: {
|
payConfirmButton: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
backgroundColor: colors.primary,
|
paddingVertical: 8,
|
||||||
paddingVertical: 12,
|
paddingHorizontal: 18,
|
||||||
paddingHorizontal: 24,
|
borderRadius: 12,
|
||||||
borderRadius: 20,
|
|
||||||
elevation: 4,
|
elevation: 4,
|
||||||
borderColor: colors.primary,
|
|
||||||
borderWidth: 1,
|
|
||||||
gap: 8,
|
gap: 8,
|
||||||
},
|
},
|
||||||
payButtonText: {
|
payButtonText: {
|
||||||
color: "#ffffffff",
|
color: "#ffffffff",
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
fontSize: responsiveWidth(2.5)
|
fontSize: responsiveWidth(3),
|
||||||
},
|
},
|
||||||
modalOverlay: {
|
modalOverlay: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// src/screens/ManagementScreen.tsx
|
// src/screens/ManagementScreen.tsx
|
||||||
import React, { useState, useCallback, FC, useEffect } from "react";
|
import React, { useState, useCallback, FC, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// ThemeProvider.tsx
|
||||||
|
|
||||||
|
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||||
|
import { Appearance } from 'react-native';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import { Theme, ThemeMode, light, dark } from './theme';
|
||||||
|
|
||||||
|
interface ThemeContextProps {
|
||||||
|
theme: Theme;
|
||||||
|
mode: ThemeMode;
|
||||||
|
setThemeMode: (mode: ThemeMode | 'system') => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeContext = createContext<ThemeContextProps | null>(null);
|
||||||
|
|
||||||
|
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const [mode, setMode] = useState<ThemeMode | 'system'>('system');
|
||||||
|
const [theme, setTheme] = useState<Theme>(light);
|
||||||
|
|
||||||
|
// Load saved theme mode
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const stored = await AsyncStorage.getItem('app_theme');
|
||||||
|
if (stored) setMode(stored as ThemeMode | 'system');
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Detect system theme + apply user choice
|
||||||
|
useEffect(() => {
|
||||||
|
const applyTheme = () => {
|
||||||
|
const system = Appearance.getColorScheme() === 'dark' ? 'dark' : 'light';
|
||||||
|
const finalMode = mode === 'system' ? system : mode;
|
||||||
|
|
||||||
|
setTheme(finalMode === 'dark' ? dark : light);
|
||||||
|
};
|
||||||
|
|
||||||
|
applyTheme();
|
||||||
|
|
||||||
|
const listener = Appearance.addChangeListener(applyTheme);
|
||||||
|
return () => listener.remove();
|
||||||
|
}, [mode]);
|
||||||
|
|
||||||
|
// Update & save theme mode
|
||||||
|
const setThemeMode = async (newMode: ThemeMode | 'system') => {
|
||||||
|
setMode(newMode);
|
||||||
|
await AsyncStorage.setItem('app_theme', newMode);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={{ theme, mode: theme.mode, setThemeMode }}>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Custom hook
|
||||||
|
export const useTheme = () => {
|
||||||
|
const context = useContext(ThemeContext);
|
||||||
|
if (!context) throw new Error("useTheme must be used inside ThemeProvider");
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
export type ThemeMode = 'light' | 'dark';
|
||||||
|
|
||||||
|
export interface ThemeColors {
|
||||||
|
primary: string;
|
||||||
|
secondary: string;
|
||||||
|
background: string;
|
||||||
|
card: string;
|
||||||
|
textPrimary: string;
|
||||||
|
textSecondary: string;
|
||||||
|
success: string;
|
||||||
|
border: string;
|
||||||
|
logincard?: string;
|
||||||
|
logincard1?: string;
|
||||||
|
reverseBackground: string;
|
||||||
|
reverseText?: string;
|
||||||
|
optCard?: string;
|
||||||
|
gray?: string;
|
||||||
|
black?: string;
|
||||||
|
white?: string;
|
||||||
|
red?: string;
|
||||||
|
green?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Theme {
|
||||||
|
mode: ThemeMode;
|
||||||
|
colors: ThemeColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const light: Theme = {
|
||||||
|
mode: 'light',
|
||||||
|
colors: {
|
||||||
|
primary: '#F4721E',
|
||||||
|
secondary: '#FF9A62',
|
||||||
|
reverseBackground: '#000000',
|
||||||
|
background: '#FFFFFF',
|
||||||
|
card: '#F3F4F6',
|
||||||
|
textPrimary: '#000000',
|
||||||
|
reverseText: '#FFFFFF',
|
||||||
|
textSecondary: '#666666',
|
||||||
|
success: '#008e02',
|
||||||
|
border: '#E5E7EB',
|
||||||
|
logincard: '#e0e0e0',
|
||||||
|
logincard1: '#66666eb3',
|
||||||
|
optCard: '#66666eb3',
|
||||||
|
gray:'#e0e0e0ff',
|
||||||
|
black:'#000000',
|
||||||
|
white:'#FFFFFF',
|
||||||
|
red:'#FF0000',
|
||||||
|
green:'#00C853'
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dark: Theme = {
|
||||||
|
mode: 'dark',
|
||||||
|
colors: {
|
||||||
|
primary: '#F4721E',
|
||||||
|
secondary: '#FF9A62',
|
||||||
|
reverseBackground: '#FFFFFF',
|
||||||
|
background: '#000000', // Fixed: Dark mode = Black bg
|
||||||
|
card: '#111214',
|
||||||
|
textPrimary: '#FFFFFF',
|
||||||
|
textSecondary: '#A1A1A1',
|
||||||
|
reverseText: '#000000',
|
||||||
|
success: '#00C853',
|
||||||
|
border: '#222427',
|
||||||
|
logincard: '#000000',
|
||||||
|
logincard1: '#8d8d8f',
|
||||||
|
optCard: '#e0e0e0',
|
||||||
|
gray:'#66666eb3',
|
||||||
|
black:'#000000',
|
||||||
|
white:'#FFFFFF',
|
||||||
|
red:'#FF0000',
|
||||||
|
green:'#00C853'
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user