theme
This commit is contained in:
@@ -1,36 +1,39 @@
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { StyleSheet, useColorScheme } from 'react-native';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { PaperProvider } from 'react-native-paper';
|
||||
import AppNavigator from './src/navigation/AppNavigator';
|
||||
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() {
|
||||
const isDarkMode = useColorScheme() === 'dark';
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// 🔹 Ask for permission
|
||||
requestPermission();
|
||||
|
||||
// 🔹 Handle background + quit state
|
||||
backgroundHandler();
|
||||
setupFirebaseHandlers()
|
||||
setupNotificationPressHandlers()
|
||||
setupFirebaseHandlers();
|
||||
setupNotificationPressHandlers();
|
||||
|
||||
// 🔹 Listen for foreground messages
|
||||
const unsubscribe = foregroundListener();
|
||||
|
||||
// 🔹 Listen for token refresh
|
||||
const unsubscribeRefresh = tokenRefreshHandler();
|
||||
|
||||
// 🔹 Create default notification channel (Android)
|
||||
notifee.createChannel({
|
||||
id: 'default',
|
||||
name: 'Default Channel',
|
||||
importance: 4, // HIGH
|
||||
importance: 4,
|
||||
});
|
||||
|
||||
return () => {
|
||||
@@ -39,19 +42,23 @@ function App() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<SafeAreaProvider>
|
||||
<PaperProvider>
|
||||
<ThemeProvider>
|
||||
<PaperProvider >
|
||||
<AppNavigator />
|
||||
</PaperProvider>
|
||||
</ThemeProvider>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
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 */; };
|
||||
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -24,6 +40,22 @@
|
||||
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>"; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -74,6 +106,7 @@
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
||||
20F28563BF834255BD7383AF /* Resources */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
@@ -97,6 +130,30 @@
|
||||
path = Pods;
|
||||
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 */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -159,6 +216,22 @@
|
||||
files = (
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard 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;
|
||||
};
|
||||
|
||||
@@ -26,14 +26,13 @@
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<false/>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<string/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
@@ -48,5 +47,24 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<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>
|
||||
</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-safe-area-context": "^5.6.1",
|
||||
"react-native-screens": "^4.16.0",
|
||||
"react-native-size-matters": "^0.0.3",
|
||||
"react-native-svg": "^15.13.0",
|
||||
"react-native-vector-icons": "^10.3.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 colors from "./colors";
|
||||
import { responsiveFontSize } from "react-native-responsive-dimensions";
|
||||
import { useTheme } from "../theme/ThemeProvider";
|
||||
import FontsFamily from "../constents/FontsFamily";
|
||||
|
||||
export interface AlertButton {
|
||||
text: string;
|
||||
@@ -29,7 +31,6 @@ export interface CustomAlertProps {
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
const BORDER_WIDTH = 6;
|
||||
const RADIUS = 24;
|
||||
|
||||
const CustomAlert: React.FC<CustomAlertProps> = ({
|
||||
@@ -40,6 +41,8 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
||||
alertType = 'info',
|
||||
onClose,
|
||||
}) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
const getIcon = () => {
|
||||
switch (alertType) {
|
||||
case 'error':
|
||||
@@ -47,7 +50,7 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
||||
case 'success':
|
||||
return { name: "checkmark-circle", color: colors.success };
|
||||
default:
|
||||
return { name: "information-circle", color: colors.primary };
|
||||
return { name: "information-circle", color: theme.colors.primary };
|
||||
}
|
||||
};
|
||||
const icon = getIcon();
|
||||
@@ -64,34 +67,30 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
||||
const getButtonStyle = (styleType: string | undefined) => {
|
||||
switch (styleType) {
|
||||
case "primary":
|
||||
return [styles.button, styles.primaryButton];
|
||||
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||
case "secondary":
|
||||
return [styles.button, styles.secondaryButton];
|
||||
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||
case "outline":
|
||||
return [styles.button, styles.outlineButton];
|
||||
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||
case "destructive":
|
||||
return [styles.button, styles.destructiveButton];
|
||||
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||
case "cancel":
|
||||
return [styles.button, styles.cancelButton];
|
||||
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||
default:
|
||||
return [styles.button, styles.defaultButton];
|
||||
return [styles.primaryButton,{ backgroundColor: theme.colors.textPrimary }];
|
||||
}
|
||||
};
|
||||
|
||||
const getButtonTextStyle = (styleType: string | undefined) => {
|
||||
switch (styleType) {
|
||||
case "primary":
|
||||
return [styles.buttonText, styles.primaryButtonText];
|
||||
case "secondary":
|
||||
return [styles.buttonText, styles.secondaryButtonText];
|
||||
case "outline":
|
||||
return [styles.buttonText, styles.outlineButtonText];
|
||||
case "destructive":
|
||||
return [styles.buttonText, styles.destructiveButtonText];
|
||||
return { color: theme.colors.reverseText };
|
||||
case "cancel":
|
||||
return [styles.buttonText, styles.cancelButtonText];
|
||||
return { color: colors.error };
|
||||
case "secondary":
|
||||
return { color: theme.colors.reverseText };
|
||||
default:
|
||||
return [styles.buttonText, styles.defaultButtonText];
|
||||
return { color: theme.colors.reverseText };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,35 +102,49 @@ const CustomAlert: React.FC<CustomAlertProps> = ({
|
||||
onRequestClose={handleRequestClose}
|
||||
>
|
||||
<View style={styles.centeredView}>
|
||||
{/* Background Overlay */}
|
||||
{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}>
|
||||
<View style={styles.faintOverlay} />
|
||||
{/* Alert Box */}
|
||||
<View style={[
|
||||
styles.box,
|
||||
{
|
||||
backgroundColor: theme.colors.card,
|
||||
borderColor: theme.colors.border,
|
||||
borderWidth: 1,
|
||||
}
|
||||
]}>
|
||||
|
||||
<View style={styles.contentContainer}>
|
||||
<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>
|
||||
<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 && (
|
||||
<View style={styles.buttonContainer}>
|
||||
{buttons.map((button, index) => (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
style={[
|
||||
...getButtonStyle(button.style),
|
||||
styles.button,
|
||||
getButtonStyle(button.style),
|
||||
// Custom overrides
|
||||
button.style !== "cancel" && button.buttonColor ? { backgroundColor: button.buttonColor } : null,
|
||||
button.style === "outline" && button.buttonColor ? { borderColor: button.buttonColor } : null,
|
||||
]}
|
||||
onPress={button.onPress}
|
||||
>
|
||||
<Text style={[
|
||||
...getButtonTextStyle(button.style),
|
||||
button.style !== "cancel" && button.textColor ? { color: button.textColor } : null,
|
||||
styles.buttonText,{color: theme.colors.reverseText},
|
||||
getButtonTextStyle(button.style),
|
||||
|
||||
]}>
|
||||
{button.text}
|
||||
</Text>
|
||||
@@ -153,112 +166,83 @@ const styles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
},
|
||||
absolute: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
...StyleSheet.absoluteFillObject,
|
||||
},
|
||||
box: {
|
||||
paddingHorizontal: 2, // reduce horizontal padding
|
||||
padding: BORDER_WIDTH + 2, // reduce overall padding
|
||||
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,
|
||||
width: '85%',
|
||||
maxWidth: 340,
|
||||
borderRadius: RADIUS,
|
||||
alignSelf: 'center',
|
||||
overflow: 'hidden',
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 10 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 10,
|
||||
elevation: 10,
|
||||
},
|
||||
contentContainer: {
|
||||
zIndex: 2,
|
||||
padding: 12, // reduce container padding
|
||||
padding: 20,
|
||||
alignItems: "center",
|
||||
},
|
||||
iconContainer: {
|
||||
marginBottom: 8, // reduce vertical space below icon
|
||||
marginBottom: 12,
|
||||
},
|
||||
alertTitle: {
|
||||
fontSize: responsiveFontSize(1.8), // smaller font size
|
||||
fontWeight: "bold",
|
||||
color: colors.textDark,
|
||||
marginBottom: 4, // less space below title
|
||||
fontSize: responsiveFontSize(2),
|
||||
fontFamily: FontsFamily.nunitoExtraBold,
|
||||
marginBottom: 8,
|
||||
textAlign: "center",
|
||||
|
||||
},
|
||||
alertMessage: {
|
||||
fontSize: responsiveFontSize(1.4), // smaller font size
|
||||
color: colors.textLight,
|
||||
fontFamily: FontsFamily.nunitoRegular,
|
||||
fontSize: responsiveFontSize(1.6),
|
||||
textAlign: "center",
|
||||
marginBottom: 12, // tighter spacing
|
||||
lineHeight: 18, // reduced line height
|
||||
marginBottom: 20,
|
||||
lineHeight: 20,
|
||||
},
|
||||
buttonContainer: {
|
||||
flexDirection: "row",
|
||||
justifyContent: 'flex-end',
|
||||
width: "100%",
|
||||
gap: 8, // reduce gap between buttons
|
||||
gap: 10,
|
||||
flexWrap: 'wrap', // Allow wrapping if many buttons
|
||||
},
|
||||
button: {
|
||||
paddingVertical: 8, // less vertical padding
|
||||
paddingHorizontal: 16, // less horizontal padding
|
||||
borderRadius: 16,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 20,
|
||||
borderRadius: 12,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minWidth: 72, // slightly smaller minimum width
|
||||
borderWidth: 0,
|
||||
minWidth: 80,
|
||||
},
|
||||
// === BUTTON STYLE VARIANTS ===
|
||||
buttonText: {
|
||||
fontSize: responsiveFontSize(1.6),
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
},
|
||||
|
||||
// === BUTTON STYLES ===
|
||||
defaultButton: {
|
||||
backgroundColor: colors.pastelPink,
|
||||
},
|
||||
destructiveButton: {
|
||||
backgroundColor: colors.error,
|
||||
backgroundColor: colors.pastelPink, // Or theme.colors.primary
|
||||
},
|
||||
primaryButton: {
|
||||
backgroundColor: colors.primary,
|
||||
},
|
||||
secondaryButton: {
|
||||
backgroundColor: colors.pastelBlue,
|
||||
backgroundColor: '#E0E0E0', // Neutral gray
|
||||
},
|
||||
destructiveButton: {
|
||||
backgroundColor: colors.error,
|
||||
},
|
||||
outlineButton: {
|
||||
borderColor: colors.primary,
|
||||
borderWidth: 2,
|
||||
backgroundColor: "transparent",
|
||||
borderWidth: 1.5,
|
||||
borderColor: colors.primary, // Will be overridden by theme in render if needed
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
cancelButton: {
|
||||
borderColor: colors.error,
|
||||
borderWidth: 1,
|
||||
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,
|
||||
borderColor: colors.error,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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 LinearGradient from "react-native-linear-gradient";
|
||||
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
||||
import colors from "../colors";
|
||||
import { responsiveFontSize } from "react-native-responsive-dimensions";
|
||||
import { useTheme } from "../../theme/ThemeProvider";
|
||||
import FontsFamily from "../../constents/FontsFamily";
|
||||
|
||||
type CardProps = {
|
||||
title: string;
|
||||
@@ -23,7 +25,7 @@ const AnimatedCard: React.FC<CardProps> = ({
|
||||
backTwo = colors.pastelPink,
|
||||
}) => {
|
||||
const scale = useRef(new Animated.Value(1)).current;
|
||||
|
||||
const{ theme } = useTheme()
|
||||
const handlePress = () => {
|
||||
Animated.sequence([
|
||||
Animated.spring(scale, { toValue: 0.95, useNativeDriver: true }),
|
||||
@@ -33,11 +35,11 @@ const AnimatedCard: React.FC<CardProps> = ({
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={handlePress}>
|
||||
<Animated.View style={[styles.card, { transform: [{ scale }] }]}>
|
||||
<LinearGradient colors={[backOne, backTwo]} style={styles.gradient}>
|
||||
<Ionicons name={iconName} size={38} color="#fff" style={styles.icon} />
|
||||
<Text style={styles.title}>{title}</Text>
|
||||
{subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
|
||||
</LinearGradient>
|
||||
<View style={[styles.gradient, { backgroundColor: theme.colors.reverseBackground }]}>
|
||||
<Ionicons name={iconName} size={38} color={theme.colors.reverseText} style={styles.icon} />
|
||||
<Text style={[styles.title, { color: theme.colors.reverseText }]}>{title}</Text>
|
||||
{subtitle && <Text style={[styles.subtitle, { color: theme.colors.reverseText }]}>{subtitle}</Text>}
|
||||
</View>
|
||||
</Animated.View>
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
@@ -58,8 +60,8 @@ const styles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
},
|
||||
icon: { marginBottom: 10 },
|
||||
title: { fontSize: responsiveFontSize(1.8), fontWeight: "bold", color: "#fff" },
|
||||
subtitle: { fontSize: responsiveFontSize(1.3), color: "#fff", opacity: 0.9 },
|
||||
title: { fontSize: responsiveFontSize(2.2), fontFamily: FontsFamily.nunitoExtraBold, color: "#fff" },
|
||||
subtitle: { fontSize: responsiveFontSize(1.5), fontFamily: FontsFamily.nunitoRegular, opacity: 0.9 },
|
||||
});
|
||||
|
||||
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 { BottomTabNavigationProp, createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
||||
import { View, Text, StyleSheet, Platform, AccessibilityInfo } from "react-native";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
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 GroupScreen from "../screens/GroupScreen";
|
||||
import Profile from "../screens/profile/Profile";
|
||||
@@ -8,8 +17,12 @@ import Home from "../screens/home/Home";
|
||||
import colors from "../components/colors";
|
||||
import Setting from "../screens/setting/Setting";
|
||||
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 = {
|
||||
activeColor: "#000",
|
||||
@@ -19,60 +32,72 @@ const TAB_CONFIG = {
|
||||
iconSize: 28,
|
||||
};
|
||||
|
||||
// Background (tab highlight) colors
|
||||
const activeTabColors: { [key: string]: string } = {
|
||||
Home: colors.pastelPink, // Soft pink
|
||||
Profile: colors.pastelBlue, // Light sky blue
|
||||
Group: colors.pastelGreen, // Gentle mint green
|
||||
Management: colors.pastelOrange, // Warm pastel yellow
|
||||
Home: colors.pastelPink,
|
||||
Profile: colors.pastelBlue,
|
||||
Group: colors.pastelGreen,
|
||||
Management: colors.pastelOrange,
|
||||
};
|
||||
|
||||
// Icon/Text colors on active tabs
|
||||
const activeIconColors: { [key: string]: string } = {
|
||||
Home: "#333",
|
||||
Profile: "#333",
|
||||
Group: "#333",
|
||||
Management: "#333",
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export type RootTabParamList = {
|
||||
Home: undefined;
|
||||
Profile: 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>;
|
||||
const Tab = createBottomTabNavigator<RootTabParamList>();
|
||||
|
||||
const BottomTabs: React.FC = () => {
|
||||
const { theme } = useTheme();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const [isReduceMotionEnabled, setIsReduceMotionEnabled] = React.useState<boolean>(false);
|
||||
const [isScreenReaderEnabled, setIsScreenReaderEnabled] = React.useState<boolean>(false);
|
||||
const [isReduceMotionEnabled, setIsReduceMotionEnabled] =
|
||||
useState<boolean>(false);
|
||||
const [isScreenReaderEnabled, setIsScreenReaderEnabled] =
|
||||
useState<boolean>(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
// Check for accessibility settings
|
||||
useEffect(() => {
|
||||
AccessibilityInfo.isScreenReaderEnabled().then(setIsScreenReaderEnabled);
|
||||
AccessibilityInfo.isReduceMotionEnabled().then(setIsReduceMotionEnabled);
|
||||
|
||||
const screenReaderSubscription = AccessibilityInfo.addEventListener(
|
||||
'screenReaderChanged',
|
||||
"screenReaderChanged",
|
||||
setIsScreenReaderEnabled
|
||||
);
|
||||
|
||||
return () => screenReaderSubscription.remove();
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
// console.log("isReduceMotionEnabled : ", isReduceMotionEnabled)
|
||||
// console.log("isScreenReaderEnabled : ", isScreenReaderEnabled)
|
||||
return (
|
||||
<Tab.Navigator
|
||||
screenOptions={({ route }) => ({
|
||||
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 }) =>
|
||||
!focused ? (
|
||||
@@ -82,32 +107,33 @@ const BottomTabs: React.FC = () => {
|
||||
tabBarIcon: ({ focused }) => {
|
||||
let iconName: IoniconsIconName = "home-outline";
|
||||
|
||||
// Determine icon based on route
|
||||
if (route.name === "Home") iconName = focused ? "home" : "home-outline";
|
||||
else if (route.name === "Profile") iconName = focused ? "person" : "person-outline";
|
||||
else if (route.name === "Management") iconName = focused ? "settings" : "settings-outline";
|
||||
else if (route.name === "Group") iconName = focused ? "people" : "people-outline";
|
||||
if (route.name === "Home")
|
||||
iconName = focused ? "home" : "home-outline";
|
||||
else if (route.name === "Profile")
|
||||
iconName = focused ? "person" : "person-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 = activeTabColors[route.name];
|
||||
const activeBackgroundColor = theme.colors.background;
|
||||
const activeIconColor = activeIconColors[route.name];
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.iconContainer,
|
||||
// 4. Apply the dynamic background color when focused
|
||||
focused && [
|
||||
styles.activeIconContainer,
|
||||
{ backgroundColor: activeBackgroundColor },
|
||||
],
|
||||
]}
|
||||
>
|
||||
(route.name === "Management"{<Ionicons
|
||||
<Ionicons
|
||||
name={iconName}
|
||||
size={TAB_CONFIG.iconSize}
|
||||
color={focused ? activeIconColor : TAB_CONFIG.inactiveColor}
|
||||
/>}:null)
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
@@ -119,7 +145,7 @@ const BottomTabs: React.FC = () => {
|
||||
<Tab.Screen name="Management" component={ManagementScreen} />
|
||||
</Tab.Navigator>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
screen: {
|
||||
@@ -135,19 +161,16 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
tabBar: {
|
||||
position: "absolute",
|
||||
bottom: 20,
|
||||
left: 20,
|
||||
right: 20,
|
||||
height: TAB_CONFIG.height,
|
||||
// backgroundColor: TAB_CONFIG.backgroundColor,
|
||||
borderRadius: 20,
|
||||
shadowColor: "#000",
|
||||
shadowOpacity: 0.1,
|
||||
shadowOffset: { width: 0, height: 5 },
|
||||
shadowRadius: 8,
|
||||
elevation: 10,
|
||||
paddingBottom: Platform.OS === "ios" ? 25 : 10,
|
||||
paddingTop: 10,
|
||||
paddingTop: 0,
|
||||
marginHorizontal: 10,
|
||||
},
|
||||
label: {
|
||||
@@ -155,19 +178,18 @@ const styles = StyleSheet.create({
|
||||
fontSize: responsiveFontSize(1.2),
|
||||
},
|
||||
iconContainer: {
|
||||
width: 60,
|
||||
height: 50,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: 80, // Reduced size for a sleeker look
|
||||
height: 60, // Reduced size
|
||||
marginTop: 10,
|
||||
borderRadius: 15,
|
||||
},
|
||||
activeIconContainer: {
|
||||
// The default active style, background color is now applied dynamically
|
||||
elevation: 2,
|
||||
shadowColor: '#000',
|
||||
shadowColor: "#000",
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 5,
|
||||
},
|
||||
});
|
||||
export default BottomTabs
|
||||
|
||||
export default BottomTabs;
|
||||
|
||||
+72
-59
@@ -22,14 +22,24 @@ import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
import MaterialRipple from 'react-native-material-ripple';
|
||||
import CustomAlert from '../components/CostomAlart';
|
||||
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 BLOCK_SIZE = width / 3;
|
||||
|
||||
|
||||
// Note: You will need to install react-native-material-ripple
|
||||
// npm install react-native-material-ripple
|
||||
|
||||
|
||||
export default function LoginScreen() {
|
||||
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
|
||||
const [mobile, setMobile] = useState('');
|
||||
@@ -42,9 +52,12 @@ export default function LoginScreen() {
|
||||
alertType: 'info' as 'info' | 'success' | 'error',
|
||||
});
|
||||
|
||||
|
||||
const fade = useRef(new Animated.Value(0)).current;
|
||||
const slide = useRef(new Animated.Value(30)).current;
|
||||
const ctaScale = useRef(new Animated.Value(1)).current;
|
||||
const { theme } = useTheme();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
Animated.parallel([
|
||||
@@ -53,6 +66,7 @@ export default function LoginScreen() {
|
||||
]).start();
|
||||
}, []);
|
||||
|
||||
|
||||
const showAlert = (
|
||||
title: string,
|
||||
message: string,
|
||||
@@ -62,10 +76,12 @@ export default function LoginScreen() {
|
||||
setAlertInfo({ visible: true, title, message, buttons, alertType });
|
||||
};
|
||||
|
||||
|
||||
const hideAlert = () => {
|
||||
setAlertInfo({ ...alertInfo, visible: false });
|
||||
};
|
||||
|
||||
|
||||
const handleContinue = async () => {
|
||||
if (mobile.length === 10) {
|
||||
setLoading(true);
|
||||
@@ -87,21 +103,24 @@ export default function LoginScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const colorsBlocks = [
|
||||
colors.pastelPink,
|
||||
colors.pastelBlue,
|
||||
colors.pastelGreen,
|
||||
colors.pastelOrange,
|
||||
colors.pastelBlue,
|
||||
colors.pastelPink,
|
||||
colors.pastelGreen,
|
||||
colors.pastelOrange,
|
||||
colors.pastelPink,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard,
|
||||
];
|
||||
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar barStyle="dark-content" backgroundColor={colors.pastelOrange} />
|
||||
<View style={[ styles.container, {backgroundColor: theme.colors.background }]}>
|
||||
<StatusBar barStyle={theme.mode === "dark" ? "light-content" : "dark-content"} backgroundColor={colors.pastelOrange} />
|
||||
|
||||
|
||||
{/* Funky grid blocks background (Unchanged) */}
|
||||
<View style={styles.gridContainer}>
|
||||
@@ -110,35 +129,38 @@ export default function LoginScreen() {
|
||||
key={index}
|
||||
style={[
|
||||
styles.gridBlock,
|
||||
{ backgroundColor: bgColor },
|
||||
{ backgroundColor: bgColor ,borderRadius:16 },
|
||||
index % 2 === 0 ? styles.elevatedBlock : {},
|
||||
]}
|
||||
/>
|
||||
|
||||
))}
|
||||
</View>
|
||||
|
||||
|
||||
<KeyboardAvoidingView
|
||||
style={styles.keyboardAvoidingContainer}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
>
|
||||
<View style={styles.contentContainer}>
|
||||
<View style={styles.topSection}>
|
||||
<View style={[ styles.topSection, {marginTop:60}]}>
|
||||
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] }}>
|
||||
<Text style={styles.brand}>CircleCollect</Text>
|
||||
<Text style={styles.title}>Welcome Back!</Text>
|
||||
<Text style={styles.subtitle}>
|
||||
<Text style={[styles.brand, { color: theme.colors.textPrimary }]}>CircleCollect</Text>
|
||||
<Text style={[styles.title, { color: theme.colors.textPrimary }]}>Welcome Back!</Text>
|
||||
<Text style={[styles.subtitle, { color: theme.colors.textSecondary }]}>
|
||||
Let's get you signed in to your community.
|
||||
</Text>
|
||||
</Animated.View>
|
||||
</View>
|
||||
|
||||
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] }}>
|
||||
<View style={styles.inputWrapper}>
|
||||
<Ionicons name="call-outline" size={24} color={colors.textLight} style={styles.inputIcon} />
|
||||
|
||||
<Animated.View style={{ opacity: fade, transform: [{ translateY: slide }] ,marginTop: 150}}>
|
||||
<View style={[styles.inputWrapper, { backgroundColor: theme.colors.reverseBackground }]}>
|
||||
<Ionicons name="call-outline" size={24} color={theme.colors.reverseText} style={styles.inputIcon} />
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
style={[ styles.input, { color: theme.colors.reverseText, fontFamily: FontsFamily.nunitoRegular }]}
|
||||
placeholder="Enter your mobile number"
|
||||
placeholderTextColor={colors.textLight}
|
||||
placeholderTextColor={theme.colors.reverseText}
|
||||
value={mobile}
|
||||
onChangeText={setMobile}
|
||||
keyboardType="phone-pad"
|
||||
@@ -148,6 +170,7 @@ export default function LoginScreen() {
|
||||
</View>
|
||||
</Animated.View>
|
||||
|
||||
|
||||
<Animated.View style={[styles.bottomSection, { transform: [{ scale: ctaScale }] }]}>
|
||||
<MaterialRipple
|
||||
onPress={handleContinue}
|
||||
@@ -157,21 +180,16 @@ export default function LoginScreen() {
|
||||
rippleCentered
|
||||
rippleContainerBorderRadius={30}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[colors.pastelPink, colors.pastelOrange]}
|
||||
style={styles.buttonGradient}
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
>
|
||||
<View style={[styles.buttonGradient, { backgroundColor: theme.colors.reverseBackground }]} >
|
||||
{loading ? (
|
||||
<ActivityIndicator color={colors.white} />
|
||||
<ActivityIndicator color={theme.colors.reverseText} />
|
||||
) : (
|
||||
<View style={styles.buttonContent}>
|
||||
<Text style={styles.buttonText}>Continue</Text>
|
||||
<Ionicons name="arrow-forward-circle-outline" size={22} color={colors.white} style={{marginLeft: 8}} />
|
||||
<Text style={[styles.buttonText, { color: theme.colors.reverseText }]}>Continue</Text>
|
||||
<Ionicons name="arrow-forward-circle-outline" size={22} color={theme.colors.reverseText} style={{marginLeft: 8}} />
|
||||
</View>
|
||||
)}
|
||||
</LinearGradient>
|
||||
</View>
|
||||
</MaterialRipple>
|
||||
<Text style={styles.footerText}>
|
||||
Your privacy is our priority. Your information is always secure.
|
||||
@@ -180,6 +198,7 @@ export default function LoginScreen() {
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
|
||||
|
||||
<CustomAlert
|
||||
visible={alertInfo.visible}
|
||||
title={alertInfo.title}
|
||||
@@ -191,6 +210,7 @@ export default function LoginScreen() {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
@@ -207,11 +227,11 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 16,
|
||||
},
|
||||
elevatedBlock: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 5 },
|
||||
shadowOpacity: 0.15,
|
||||
shadowRadius: 10,
|
||||
elevation: 7,
|
||||
shadowColor: '#ffffffff',
|
||||
shadowOffset: { width: 1, height: 5 },
|
||||
shadowOpacity: 1,
|
||||
shadowRadius: 15,
|
||||
elevation: 10,
|
||||
},
|
||||
keyboardAvoidingContainer: {
|
||||
flex: 1,
|
||||
@@ -227,8 +247,7 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
},
|
||||
brand: {
|
||||
fontSize: responsiveFontSize(2.8),
|
||||
fontWeight: '700',
|
||||
fontSize: responsiveFontSize(3),
|
||||
color: colors.primary,
|
||||
textAlign: 'center',
|
||||
letterSpacing: 2,
|
||||
@@ -236,33 +255,29 @@ const styles = StyleSheet.create({
|
||||
textShadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||
textShadowOffset: { width: 1, height: 1 },
|
||||
textShadowRadius: 2,
|
||||
fontFamily: FontsFamily.nunitoExtraBold,
|
||||
},
|
||||
title: {
|
||||
fontSize: responsiveFontSize(4),
|
||||
fontWeight: 'bold',
|
||||
color: colors.textDark,
|
||||
fontSize: responsiveFontSize(5),
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
|
||||
textAlign: 'center',
|
||||
marginBottom: 14,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: responsiveFontSize(1.6),
|
||||
color: colors.textDark,
|
||||
fontFamily: FontsFamily.nunitoRegular,
|
||||
textAlign: 'center',
|
||||
|
||||
lineHeight: 26,
|
||||
maxWidth: 320,
|
||||
},
|
||||
inputWrapper: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.85)',
|
||||
borderRadius: 36,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.pastelPink,
|
||||
paddingHorizontal: 20,
|
||||
shadowColor: colors.primary,
|
||||
shadowOffset: { width: 0, height: 6 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 14,
|
||||
paddingHorizontal: responsiveHeight(2),
|
||||
elevation: 8,
|
||||
},
|
||||
inputIcon: {
|
||||
@@ -271,9 +286,9 @@ const styles = StyleSheet.create({
|
||||
input: {
|
||||
flex: 1,
|
||||
fontSize: responsiveFontSize(1.8),
|
||||
fontWeight: '600',
|
||||
fontFamily: FontsFamily.nunitoSemiBold,
|
||||
color: colors.textLight,
|
||||
height: 58,
|
||||
height: responsiveHeight(5),
|
||||
},
|
||||
bottomSection: {
|
||||
alignItems: 'center',
|
||||
@@ -282,16 +297,13 @@ const styles = StyleSheet.create({
|
||||
button: {
|
||||
width: '100%',
|
||||
borderRadius: 30,
|
||||
shadowColor: colors.primary,
|
||||
shadowOffset: { width: 0, height: 10 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 20,
|
||||
elevation: 14,
|
||||
marginTop: 20,
|
||||
},
|
||||
buttonGradient: {
|
||||
borderRadius: 30,
|
||||
paddingVertical: 18,
|
||||
|
||||
borderRadius:42,
|
||||
paddingVertical: 14,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
@@ -302,8 +314,8 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
buttonText: {
|
||||
color: colors.white,
|
||||
fontWeight: '800',
|
||||
fontSize: responsiveFontSize(1.8),
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
},
|
||||
footerText: {
|
||||
fontSize: responsiveFontSize(1.4),
|
||||
@@ -311,5 +323,6 @@ const styles = StyleSheet.create({
|
||||
marginTop: 28,
|
||||
textAlign: 'center',
|
||||
maxWidth: 300,
|
||||
fontFamily: FontsFamily.nunitoRegular,
|
||||
},
|
||||
});
|
||||
@@ -21,6 +21,8 @@ import { LOGIN_URL, VARIFY_OTP_URL } from "../utils/ApiUrls";
|
||||
import colors from "../components/colors";
|
||||
import CustomAlert from "../components/CostomAlart";
|
||||
import { getFcmToken } from "../utils/firebase/firebaseServices";
|
||||
import { useTheme } from "../theme/ThemeProvider";
|
||||
import FontsFamily from "../constents/FontsFamily";
|
||||
|
||||
const CELL_COUNT = 6;
|
||||
const { width } = Dimensions.get('window');
|
||||
@@ -50,6 +52,7 @@ export default function OtpVerificationScreen() {
|
||||
buttons: [],
|
||||
alertType: "info",
|
||||
});
|
||||
const { theme } = useTheme();
|
||||
|
||||
const inputs = useRef<Array<TextInput | null>>([]);
|
||||
const route = useRoute<OtpVerifyRouteProp>();
|
||||
@@ -143,7 +146,7 @@ export default function OtpVerificationScreen() {
|
||||
routes: [{ name: 'Home' }],
|
||||
})
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
triggerAlert(
|
||||
'Success!',
|
||||
@@ -239,20 +242,20 @@ export default function OtpVerificationScreen() {
|
||||
};
|
||||
|
||||
const colorsBlocks = [
|
||||
colors.pastelPink,
|
||||
colors.pastelBlue,
|
||||
colors.pastelGreen,
|
||||
colors.pastelOrange,
|
||||
colors.pastelBlue,
|
||||
colors.pastelPink,
|
||||
colors.pastelGreen,
|
||||
colors.pastelOrange,
|
||||
colors.pastelPink,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard1,
|
||||
theme.colors.logincard,
|
||||
theme.colors.logincard,
|
||||
];
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar barStyle="dark-content" backgroundColor={colors.pastelOrange} />
|
||||
<View style={[styles.container, {backgroundColor: theme.colors.background }]}>
|
||||
<StatusBar barStyle={theme.mode === "dark" ? "light-content" : "dark-content"} backgroundColor={colors.pastelOrange} />
|
||||
|
||||
<View style={styles.gridContainer}>
|
||||
{colorsBlocks.map((bgColor, index) => (
|
||||
@@ -260,7 +263,7 @@ export default function OtpVerificationScreen() {
|
||||
key={index}
|
||||
style={[
|
||||
styles.gridBlock,
|
||||
{ backgroundColor: bgColor },
|
||||
{ backgroundColor: bgColor, borderRadius: 16 },
|
||||
index % 2 === 0 ? styles.elevatedBlock : {},
|
||||
]}
|
||||
/>
|
||||
@@ -268,26 +271,34 @@ export default function OtpVerificationScreen() {
|
||||
</View>
|
||||
|
||||
<KeyboardAvoidingView style={styles.keyboardAvoidingContainer} behavior={Platform.OS === "ios" ? "padding" : undefined}>
|
||||
|
||||
<CustomAlert {...alertConfig} />
|
||||
|
||||
<View style={styles.contentPanel}>
|
||||
<View style={[styles.contentPanel, { backgroundColor: theme.colors.reverseBackground }]}>
|
||||
<View style={styles.topSection}>
|
||||
<Text style={styles.title}>Verify Your Code</Text>
|
||||
<Text style={styles.subtitle}>We’ve sent a 6-digit verification code to +91 {mobile}.</Text>
|
||||
<Text style={[styles.title, { color: theme.colors.reverseText }]}>Verify Your Code</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) => (
|
||||
<TextInput
|
||||
key={`otp-${i}`}
|
||||
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"
|
||||
maxLength={i === 0 ? CELL_COUNT : 1}
|
||||
value={code[i]}
|
||||
onChangeText={(t) => (i === 0 ? handleFirstCellChange(t) : updateIndex(i, t))}
|
||||
onKeyPress={(e) => handleKeyPress(i, e)}
|
||||
placeholder="•"
|
||||
placeholder="*"
|
||||
placeholderTextColor="#BDBDBD"
|
||||
textContentType="oneTimeCode"
|
||||
/>
|
||||
@@ -300,16 +311,16 @@ export default function OtpVerificationScreen() {
|
||||
onPressIn={() => Animated.spring(ctaScale, { toValue: 0.97, useNativeDriver: true }).start()}
|
||||
onPressOut={() => Animated.spring(ctaScale, { toValue: 1, useNativeDriver: true }).start()}
|
||||
onPress={() => onSubmit(code.join(""), mobile)}
|
||||
style={styles.button}
|
||||
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>
|
||||
|
||||
{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}>
|
||||
<Text style={[styles.footerText, { color: colors.pastelPink, fontWeight: '600' }]}>
|
||||
<Text style={[styles.footerText, { color: theme.colors.reverseText, fontWeight: '600' }]}>
|
||||
{isResending ? "Resending..." : "Resend Code"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
@@ -335,16 +346,15 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 16,
|
||||
},
|
||||
elevatedBlock: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 5 },
|
||||
shadowOpacity: 0.15,
|
||||
shadowRadius: 10,
|
||||
elevation: 7,
|
||||
shadowColor: '#ffffffff',
|
||||
shadowOffset: { width: 1, height: 5 },
|
||||
shadowOpacity: 1,
|
||||
shadowRadius: 15,
|
||||
elevation: 10,
|
||||
},
|
||||
keyboardAvoidingContainer: { flex: 1, justifyContent: 'center' },
|
||||
contentPanel: {
|
||||
marginHorizontal: 24,
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||
borderRadius: 32,
|
||||
padding: 28,
|
||||
shadowColor: '#000',
|
||||
@@ -354,13 +364,33 @@ const styles = StyleSheet.create({
|
||||
elevation: 12,
|
||||
},
|
||||
topSection: { alignItems: 'center', marginBottom: 24 },
|
||||
title: { fontSize: 28, fontWeight: "bold", color: colors.textDark, textAlign: 'center', marginBottom: 12 },
|
||||
subtitle: { fontSize: 16, color: colors.textLight, textAlign: 'center', marginBottom: 32, lineHeight: 24, maxWidth: 300 },
|
||||
otpRow: { flexDirection: "row", justifyContent: "space-between", width: '100%', paddingHorizontal: 10 },
|
||||
cell: { width: 48, height: 56, borderRadius: 12, borderWidth: 1.5, borderColor: colors.inputBorder, backgroundColor: colors.white, textAlign: "center", fontSize: 22, fontWeight: '700', color: colors.textDark, shadowColor: "#000", shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.08, shadowRadius: 8, elevation: 3 },
|
||||
cellFilled: { borderColor: colors.primary, backgroundColor: '#F7F2FF' },
|
||||
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 ,fontFamily: FontsFamily.nunitoMedium},
|
||||
|
||||
otpRow: {
|
||||
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 },
|
||||
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},
|
||||
buttonText: { color: colors.white, fontWeight: "700", fontSize: 16 },
|
||||
footerText: { textAlign: "center", color: colors.textLight, fontSize: 14, marginTop: 20 },
|
||||
button: { backgroundColor: colors.pastelPink, paddingVertical: 18, borderRadius: 30, alignItems: "center", justifyContent: "center",},
|
||||
buttonText: { color: colors.white, fontSize: 16, fontFamily: FontsFamily.nunitoBold },
|
||||
footerText: { textAlign: "center", fontFamily: FontsFamily.nunitoBold, fontSize: 14, marginTop: 20 },
|
||||
});
|
||||
|
||||
+19
-11
@@ -10,6 +10,7 @@ import {
|
||||
ListRenderItem,
|
||||
Alert,
|
||||
RefreshControl,
|
||||
StatusBar,
|
||||
} from "react-native";
|
||||
import AppView from "../../components/AppView";
|
||||
import colors from "../../components/colors";
|
||||
@@ -23,6 +24,10 @@ import AnimatedCard from "../../components/common/AnimatedCard";
|
||||
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
||||
import { apiCall } from "../../utils/ApiHelper";
|
||||
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) {
|
||||
UIManager.setLayoutAnimationEnabledExperimental(true);
|
||||
@@ -80,6 +85,8 @@ const Home: React.FC = () => {
|
||||
const [userDashboard, setUserDashboard] = useState<any>(null);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [statusData, setStatusData] = useState<any>(null);
|
||||
const insets = useSafeAreaInsets();
|
||||
const {theme} = useTheme();
|
||||
const getDashboardData = async () => {
|
||||
try {
|
||||
const result = (await apiCall(DASHBOARD_URL, "GET")) as any;
|
||||
@@ -186,7 +193,8 @@ const Home: React.FC = () => {
|
||||
};
|
||||
|
||||
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
|
||||
data={actions}
|
||||
numColumns={2}
|
||||
@@ -195,18 +203,19 @@ const Home: React.FC = () => {
|
||||
ListHeaderComponent={
|
||||
<>
|
||||
<View style={styles.header}>
|
||||
<View>
|
||||
<Text style={styles.greeting}>
|
||||
Hello, <Text style={{ fontWeight: 'bold' }}>{user.firstName || apiUser?.firstName || "User"}</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 8 ,marginTop: responsiveHeight(2) }} >
|
||||
<Text style={[styles.greeting, { color: theme.colors.textPrimary }]}>
|
||||
Hello,
|
||||
</Text>
|
||||
<Text style={{ fontFamily:FontsFamily.nunitoExtraBold,color: theme.colors.textPrimary,fontSize:responsiveFontSize(2.5) }}>{user.firstName || apiUser?.firstName || "User"}</Text>
|
||||
</View>
|
||||
<TouchableOpacity onPress={() => navigation.navigate("Notification" as never)}>
|
||||
<TouchableOpacity onPress={() => navigation.navigate("Notification" as never)} style={{ marginTop: responsiveHeight(2) ,}}>
|
||||
{unreadCount > 0 && (
|
||||
<View style={styles.badge}>
|
||||
<Text style={styles.badgeText}>{unreadCount}</Text>
|
||||
</View>
|
||||
)}
|
||||
<Ionicons name="notifications-outline" size={30} color={colors.textDark} />
|
||||
<Ionicons name="notifications-outline" size={30} color={theme.colors.textPrimary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
@@ -217,7 +226,7 @@ const Home: React.FC = () => {
|
||||
/>
|
||||
|
||||
<View style={styles.actionHeader}>
|
||||
<Text style={styles.sectionTitle}>Quick Actions</Text>
|
||||
<Text style={[styles.sectionTitle,{ color: theme.colors.textPrimary }]}>Quick Actions </Text>
|
||||
|
||||
</View>
|
||||
</>
|
||||
@@ -243,7 +252,7 @@ const Home: React.FC = () => {
|
||||
onClose={() => setAlertVisible(false)}
|
||||
/>
|
||||
)}
|
||||
</AppView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -252,7 +261,6 @@ export default Home;
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.white,
|
||||
},
|
||||
header: {
|
||||
flexDirection: "row",
|
||||
@@ -262,8 +270,8 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 24,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
greeting: { fontSize: 22, color: colors.textDark },
|
||||
sectionTitle: { fontSize: 20, fontWeight: "600", color: colors.textDark, flex: 1 },
|
||||
greeting: { fontSize: 22,fontFamily: FontsFamily.nunitoLight },
|
||||
sectionTitle: { fontSize: 20, fontWeight: "600", color: colors.textDark, flex: 1 ,fontFamily: FontsFamily.nunitoSemiBold},
|
||||
actionHeader: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
responsiveWidth,
|
||||
responsiveFontSize
|
||||
} from "react-native-responsive-dimensions";
|
||||
import { useTheme } from "../../theme/ThemeProvider";
|
||||
import FontsFamily from "../../constents/FontsFamily";
|
||||
|
||||
type StatusData = {
|
||||
role?: string;
|
||||
@@ -73,7 +75,7 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
const [showPayDialog, setShowPayDialog] = useState(false);
|
||||
const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([]);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const {theme} = useTheme();
|
||||
// console.log("user me : ", userDashboard)
|
||||
// Preselect all due groups at mount and on change
|
||||
useEffect(() => {
|
||||
@@ -92,12 +94,12 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
// Top grid info items
|
||||
const infoItems = useMemo(
|
||||
() => [
|
||||
{ icon: <Ionicons name="person-outline" size={20} color={colors.primary} />, 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="book-outline" size={20} color={colors.primary} />, 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="document-text-outline" size={20} color={colors.primary} />, 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="person-outline" size={20} color={theme.colors.black} />, label: "Role", value: statusData?.role || "-" },
|
||||
{ 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={theme.colors.black} />, label: "Joined Groups", value: userDashboard?.myJoinedGroups?.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={theme.colors.black} />, label: "Total Due", value: `₹${userDashboard?.multiplePayAmount || 0}` },
|
||||
{ icon: <Ionicons name="checkmark-done-outline" size={20} color={theme.colors.black} />, label: "Completed", value: userDashboard?.completeStatusMyGroupCount?.toString() || "0" },
|
||||
],
|
||||
[userDashboard, statusData]
|
||||
);
|
||||
@@ -153,18 +155,18 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
|
||||
// Bottom bar
|
||||
const renderDueBar = () => (
|
||||
<View style={styles.dueBar}>
|
||||
<Text style={styles.dueBarText}>
|
||||
Total Due: <Text style={{ color: "#FFDE03", fontWeight: "bold" }}>₹{totalDue}</Text>
|
||||
<View style={[ styles.dueBar, { borderTopColor: theme.colors.border, backgroundColor: theme.colors.gray }]}>
|
||||
<Text style={[styles.dueBarText, { color: theme.colors.black }]}>
|
||||
Total Due: <Text style={{ color: theme.colors.black, fontWeight: "bold" }}>₹{totalDue}</Text>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.payAllButton}
|
||||
style={[styles.payAllButton, { backgroundColor: theme.colors.black }]}
|
||||
onPress={() => setShowPayDialog(true)}
|
||||
disabled={dueGroups.length === 0}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<Ionicons name="wallet-outline" size={20} color="#000000ff" />
|
||||
<Text style={styles.payAllButtonText}>Pay All</Text>
|
||||
<Ionicons name="wallet-outline" size={20} color={theme.colors.white} />
|
||||
<Text style={[styles.payAllButtonText, { color: theme.colors.white }]}>Pay All</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
@@ -173,17 +175,14 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
const renderPayDialog = () => (
|
||||
<Modal visible={showPayDialog} transparent animationType="fade" onRequestClose={() => setShowPayDialog(false)}>
|
||||
<View style={styles.payModalOverlay}>
|
||||
<LinearGradient
|
||||
colors={[colors.white, colors.white]}
|
||||
start={{ x: 0.2, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.payModalBox}
|
||||
<View
|
||||
style={[styles.payModalBox, { backgroundColor: theme.colors.reverseBackground }]}
|
||||
>
|
||||
<View style={styles.payDialogHeader}>
|
||||
<Ionicons name="card-outline" color="#000000ff" size={22} />
|
||||
<Text style={styles.payDialogTitle}>Select Groups to Pay</Text>
|
||||
<Ionicons name="card-outline" color={theme.colors.reverseText} size={22} />
|
||||
<Text style={[styles.payDialogTitle, { color: theme.colors.reverseText }]}>Select Groups to Pay</Text>
|
||||
<TouchableOpacity onPress={() => setShowPayDialog(false)}>
|
||||
<Ionicons name="close-circle" color="#000000ff" size={24} />
|
||||
<Ionicons name="close-circle" color={theme.colors.reverseText} size={24} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ScrollView
|
||||
@@ -193,70 +192,73 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
{dueGroups.map((group) => (
|
||||
<TouchableOpacity
|
||||
key={group.groupId}
|
||||
style={[
|
||||
style={[
|
||||
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)}
|
||||
activeOpacity={0.85}
|
||||
>
|
||||
<Ionicons
|
||||
name={selectedGroupIds.includes(group.groupId) ? "checkbox" : "square-outline"}
|
||||
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 }}>
|
||||
<Text style={[styles.payGroupName, { color: "#000000ff" }]}>{group.groupName}</Text>
|
||||
<Text style={styles.payDueText}>
|
||||
<Text style={[styles.payGroupName, {color: theme.colors.reverseText}]}>{group.groupName}</Text>
|
||||
<Text style={[styles.payDueText, {color: theme.colors.reverseText}]}>
|
||||
₹{group.baseAmount}
|
||||
{group.lateFee > 0 ? ` (Late: ₹${group.lateFee})` : ""}
|
||||
</Text>
|
||||
</View>
|
||||
<Text style={[styles.payAmount, { color: "#4CAF50" }]}>₹{group.totalDue}</Text>
|
||||
{/* <Text style={[styles.payAmount, { color: "#4CAF50" }]}>₹{group.totalDue}</Text> */}
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
<View style={styles.payDialogFooter}>
|
||||
<Text style={styles.payDialogTotal}>
|
||||
Total: <Text style={{ fontWeight: "bold", color: "#ff5f03ff" }}>₹{totalDueSelected}</Text>
|
||||
<Text style={[styles.payDialogTotal, { color: theme.colors.reverseText }]}>
|
||||
Total : <Text style={{ fontFamily: FontsFamily.nunitoBold, color: theme.colors.red }}>₹{totalDueSelected}</Text>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[styles.payConfirmButton, { opacity: submitting ? 0.7 : 1 }]}
|
||||
style={[styles.payConfirmButton, { opacity: submitting ? 0.7 : 1 , backgroundColor: theme.colors.background}]}
|
||||
onPress={handlePayAll}
|
||||
disabled={submitting || selectedGroupIds.length === 0}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
{submitting ? (
|
||||
<ActivityIndicator color="#fff" />
|
||||
<ActivityIndicator color={theme.colors.textPrimary} />
|
||||
) : (
|
||||
<>
|
||||
<Ionicons name="checkmark-circle" size={22} color="#ffffffff" />
|
||||
<Text style={styles.payButtonText}>Pay Selected</Text>
|
||||
<Ionicons name="checkmark-circle" size={22} color={theme.colors.textPrimary} />
|
||||
<Text style={[styles.payButtonText, { fontFamily: FontsFamily.nunitoSemiBold ,color: theme.colors.textPrimary}]}>Pay Selected</Text>
|
||||
</>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<LinearGradient
|
||||
colors={[colors.primary, colors.pastelPink]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.card}
|
||||
<View
|
||||
style={[styles.card, { backgroundColor: theme.colors.reverseBackground }]}
|
||||
>
|
||||
<View style={styles.headerSection}>
|
||||
<View style={styles.titleWithIcon}>
|
||||
<Ionicons name="stats-chart" size={24} color="#fff" style={styles.headerIcon} />
|
||||
<Text style={styles.header}>Profile Overview</Text>
|
||||
<Ionicons name="stats-chart" size={24} color={theme.colors.reverseText} style={styles.headerIcon} />
|
||||
<Text style={[styles.header, { color: theme.colors.reverseText} ]}>Profile Overview</Text>
|
||||
</View>
|
||||
<View style={styles.statusBadge}>
|
||||
<Ionicons name="shield-checkmark" size={16} color="#fff" />
|
||||
<Text style={styles.statusBadgeText}>
|
||||
<View style={[styles.statusBadge, { backgroundColor: theme.colors.background}]}>
|
||||
<Ionicons name="shield-checkmark" size={16} color={theme.colors.textPrimary} />
|
||||
<Text style={[styles.statusBadgeText, { color: theme.colors.textPrimary }]}>
|
||||
{statusData?.profileStatus ? "Verified" : "Pending"}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -265,16 +267,16 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
<View style={styles.leftSection}>
|
||||
<View style={styles.infoGrid}>
|
||||
{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.iconContainer}>
|
||||
<View style={[styles.iconContainer, {backgroundColor: theme.colors.optCard || theme.colors.card}]}>
|
||||
{item.icon}
|
||||
</View>
|
||||
<Text style={styles.infoLabel} >
|
||||
<Text style={[styles.infoLabel,{color: theme.colors.textPrimary}]} >
|
||||
{item.label}
|
||||
</Text>
|
||||
</View>
|
||||
<Text style={[styles.infoValue, { color: getValueColor(item.value) }]} numberOfLines={1}>
|
||||
<Text style={[styles.infoValue, { color: theme.colors.textPrimary }]} numberOfLines={1}>
|
||||
{item.value}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -296,16 +298,16 @@ const UserProfileStatus: React.FC<UserProfileStatusProps> = ({
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.infoCardOne}>
|
||||
<Text style={{ color: "#fff", fontSize: responsiveWidth(2.3)}}>Total Paid Amount <Text style={{ fontWeight: "900"}}>{userDashboard?.totalPaidAmountMonth}</Text></Text>
|
||||
{/* <Text style={{ color: "#fff", fontWeight: "400"}}>Total Paid Amount {userDashboard?.totalPaidAmountMonth}</Text> */}
|
||||
<View style={[styles.infoCardOne,{backgroundColor: theme.colors.background}]}>
|
||||
<Text style={{ color: theme.colors.textPrimary, fontSize: responsiveWidth(3), fontFamily: FontsFamily.nunitoSemiBold,}}>Total Paid Amount</Text>
|
||||
<Text style={{ color: theme.colors.textPrimary, fontWeight: "400", fontFamily: FontsFamily.nunitoRegular}}>{userDashboard?.totalPaidAmountMonth}</Text>
|
||||
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
{renderDueBar()}
|
||||
</LinearGradient>
|
||||
</View>
|
||||
|
||||
{renderPayDialog()}
|
||||
|
||||
@@ -377,8 +379,8 @@ const styles = StyleSheet.create({
|
||||
marginRight: 8
|
||||
},
|
||||
header: {
|
||||
fontSize: responsiveWidth(3.5),
|
||||
fontWeight: "700",
|
||||
fontSize: responsiveWidth(4.5),
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
color: "#fff"
|
||||
},
|
||||
statusBadge: {
|
||||
@@ -411,14 +413,11 @@ const styles = StyleSheet.create({
|
||||
gap: 10
|
||||
},
|
||||
infoCard: {
|
||||
backgroundColor: 'rgba(255,255,255,0.15)',
|
||||
borderRadius: 14,
|
||||
padding: 12,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255,255,255,0.2)',
|
||||
flex: 1,
|
||||
minWidth: '45%',
|
||||
marginBottom: 8,
|
||||
borderRadius:12
|
||||
},
|
||||
infoCardOne: {
|
||||
backgroundColor: 'rgba(255,255,255,0.15)',
|
||||
@@ -436,25 +435,22 @@ const styles = StyleSheet.create({
|
||||
marginBottom: 6
|
||||
},
|
||||
iconContainer: {
|
||||
width: 28,
|
||||
height: 28,
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 8,
|
||||
width: responsiveWidth(8),
|
||||
height: responsiveHeight(3.5),
|
||||
borderRadius: responsiveWidth(2),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 8,
|
||||
},
|
||||
infoLabel: {
|
||||
color: "rgba(255,255,255,0.9)",
|
||||
fontSize: responsiveWidth(2),
|
||||
fontWeight: '500',
|
||||
fontSize: responsiveWidth(3),
|
||||
fontFamily: FontsFamily.nunitoSemiBold,
|
||||
flexShrink: 1,
|
||||
},
|
||||
infoValue: {
|
||||
fontWeight: "700",
|
||||
fontSize: responsiveWidth(2.5),
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
fontSize: responsiveWidth(3),
|
||||
textAlign: 'left',
|
||||
color: "#fff"
|
||||
},
|
||||
profileSection: {
|
||||
width: 90,
|
||||
@@ -498,16 +494,13 @@ const styles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
padding: 16,
|
||||
borderTopWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.15)",
|
||||
backgroundColor: "rgba(0,0,0,0.15)",
|
||||
},
|
||||
dueBarText: {
|
||||
color: "#fff",
|
||||
fontSize: responsiveWidth(2.5),
|
||||
fontWeight: "600"
|
||||
fontFamily: FontsFamily.nunitoExtraBold,
|
||||
fontSize: responsiveWidth(4),
|
||||
|
||||
},
|
||||
payAllButton: {
|
||||
backgroundColor: "#ffffffff",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 16,
|
||||
@@ -516,8 +509,7 @@ const styles = StyleSheet.create({
|
||||
gap: 6,
|
||||
},
|
||||
payAllButtonText: {
|
||||
color: "#000000ff",
|
||||
fontWeight: "bold",
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
fontSize: responsiveWidth(2.5)
|
||||
},
|
||||
payModalOverlay: {
|
||||
@@ -527,7 +519,7 @@ const styles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
},
|
||||
payModalBox: {
|
||||
width: "92%",
|
||||
width: "90%",
|
||||
borderRadius: 24,
|
||||
overflow: "hidden",
|
||||
alignItems: "center",
|
||||
@@ -547,9 +539,10 @@ const styles = StyleSheet.create({
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
},
|
||||
payDialogTitle: {
|
||||
color: "#000000ff",
|
||||
fontSize: responsiveWidth(1.8),
|
||||
fontWeight: "700"
|
||||
|
||||
fontSize: responsiveWidth(4),
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
|
||||
},
|
||||
payGroupOption: {
|
||||
flexDirection: "row",
|
||||
@@ -557,24 +550,20 @@ const styles = StyleSheet.create({
|
||||
gap: 16,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 14,
|
||||
borderColor: colors.primary,
|
||||
borderWidth: 1,
|
||||
borderRadius: 12,
|
||||
marginBottom: 8,
|
||||
},
|
||||
payOptionSelected: {
|
||||
backgroundColor: "rgba(166, 49, 255, 0.2)",
|
||||
borderColor: colors.primary,
|
||||
|
||||
borderWidth: 1,
|
||||
},
|
||||
payGroupName: {
|
||||
color: "#000000ff",
|
||||
fontWeight: "700",
|
||||
fontSize: responsiveWidth(2.5)
|
||||
fontFamily: FontsFamily.nunitoSemiBold,
|
||||
fontSize: responsiveWidth(3)
|
||||
},
|
||||
payDueText: {
|
||||
color: "rgba(0, 0, 0, 0.8)",
|
||||
fontSize: responsiveWidth(1.3),
|
||||
fontSize: responsiveWidth(3),
|
||||
fontFamily: FontsFamily.nunitoRegular,
|
||||
marginTop: 2
|
||||
},
|
||||
payAmount: {
|
||||
@@ -591,26 +580,23 @@ const styles = StyleSheet.create({
|
||||
paddingHorizontal: 18,
|
||||
},
|
||||
payDialogTotal: {
|
||||
color: "#000000ff",
|
||||
fontWeight: "600",
|
||||
fontSize: responsiveWidth(1.7)
|
||||
fontFamily: FontsFamily.nunitoBold,
|
||||
fontSize: responsiveWidth(3.5)
|
||||
},
|
||||
payConfirmButton: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
backgroundColor: colors.primary,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 24,
|
||||
borderRadius: 20,
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 18,
|
||||
borderRadius: 12,
|
||||
elevation: 4,
|
||||
borderColor: colors.primary,
|
||||
borderWidth: 1,
|
||||
|
||||
gap: 8,
|
||||
},
|
||||
payButtonText: {
|
||||
color: "#ffffffff",
|
||||
fontWeight: "bold",
|
||||
fontSize: responsiveWidth(2.5)
|
||||
fontSize: responsiveWidth(3),
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/screens/ManagementScreen.tsx
|
||||
// src/screens/ManagementScreen.tsx
|
||||
import React, { useState, useCallback, FC, useEffect } from "react";
|
||||
import {
|
||||
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