diff --git a/.vscode/settings.json b/.vscode/settings.json index 849f79e..d4f60e7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "java.compile.nullAnalysis.mode": "automatic" + "java.compile.nullAnalysis.mode": "automatic", + "cSpell.words": ["Verticborder"] } diff --git a/package.json b/package.json index f2fedd7..709c452 100644 --- a/package.json +++ b/package.json @@ -94,5 +94,5 @@ "typescript": "^5.3.3" }, "private": true, - "packageManager": "pnpm@10.15.1+sha512.34e538c329b5553014ca8e8f4535997f96180a1d0f614339357449935350d924e22f8614682191264ec33d1462ac21561aff97f6bb18065351c162c7e8f6de67" + "packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a" } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0d110a0..e6ee4c6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: + - "src/*" - "." onlyBuiltDependencies: diff --git a/src/app/dashboard/banking/index.tsx b/src/app/dashboard/banking/index.tsx index 5b2df18..e352983 100644 --- a/src/app/dashboard/banking/index.tsx +++ b/src/app/dashboard/banking/index.tsx @@ -5,6 +5,7 @@ import { mockDashboardData } from "~/data/mockData"; import { SectionHeader } from "~/components/SectionHeader"; import { AccountItem } from "~/components/AccountItem"; import { useTranslation } from "react-i18next"; +import { Header } from "~/components/Header"; // ✅ keep header const Dashboard = () => { const { colors, isDark } = useTheme(); @@ -28,6 +29,9 @@ const Dashboard = () => { /> + {/* Header */} +
+ {/* Cards Section */} {/* @@ -79,7 +83,6 @@ const Dashboard = () => { /> ))} - {/* Safe Accounts Section */} {mockDashboardData.accounts.safe.map((account, index) => ( { /> ))} - + {mockDashboardData.sharedFunds && ( { name={mockDashboardData.sharedFunds.title} arrow={mockDashboardData.sharedFunds.arrow} iconWrapped - delay={1100} + delay={1300} onPress={() => handleAccountPress( mockDashboardData.sharedFunds.title, diff --git a/src/app/profile/index.tsx b/src/app/profile/index.tsx new file mode 100644 index 0000000..8149d4f --- /dev/null +++ b/src/app/profile/index.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import { ThemeProvider } from "~/contexts/ThemeContext"; +import { ProfileScreen } from "~/components/profile/ProfileScreen"; +import { LimitsScreen } from "~/components/profile/Limits"; +import { IncomeScreen } from "~/components/profile/Income"; +import { NotificationScreen } from "~/components/profile/Notification"; +import { UserProfileScreen } from "~/components/profile/UserProfile"; +import { BankAccountsScreen } from "~/components/profile/BankAccounts"; + +const ProfileAppContent: React.FC = () => { + const [currentScreen, setCurrentScreen] = React.useState("Profile"); + + const handleNavigate = (screen: string) => { + setCurrentScreen(screen); + }; + + const renderScreen = () => { + switch (currentScreen) { + case "Profile": + return ; + case "Limits": + return ; + case "Income": + return ; + case "Notification": + return ; + case "UserProfile": + return ; + case "BankAccounts": + return ; + default: + return ; + } + }; + + return renderScreen(); +}; + +const ProfileApp: React.FC = () => { + return ( + + + + ); +}; + +export default ProfileApp; diff --git a/src/assets/Icons/Y.png b/src/assets/Icons/Y.png new file mode 100644 index 0000000..728e7f8 Binary files /dev/null and b/src/assets/Icons/Y.png differ diff --git a/src/assets/Icons/arrow.png b/src/assets/Icons/arrow.png new file mode 100644 index 0000000..c1f8894 Binary files /dev/null and b/src/assets/Icons/arrow.png differ diff --git a/src/assets/Icons/bank_account.png b/src/assets/Icons/bank_account.png new file mode 100644 index 0000000..8a21385 Binary files /dev/null and b/src/assets/Icons/bank_account.png differ diff --git a/src/assets/Icons/banking.png b/src/assets/Icons/banking.png new file mode 100644 index 0000000..9366b88 Binary files /dev/null and b/src/assets/Icons/banking.png differ diff --git a/src/assets/Icons/entertainment.png b/src/assets/Icons/entertainment.png new file mode 100644 index 0000000..d5e55d3 Binary files /dev/null and b/src/assets/Icons/entertainment.png differ diff --git a/src/assets/Icons/income.png b/src/assets/Icons/income.png new file mode 100644 index 0000000..3eb9119 Binary files /dev/null and b/src/assets/Icons/income.png differ diff --git a/src/assets/Icons/insights.png b/src/assets/Icons/insights.png new file mode 100644 index 0000000..9c8a2ad Binary files /dev/null and b/src/assets/Icons/insights.png differ diff --git a/src/assets/Icons/key-2.png b/src/assets/Icons/key-2.png new file mode 100644 index 0000000..ca22828 Binary files /dev/null and b/src/assets/Icons/key-2.png differ diff --git a/src/assets/Icons/key.png b/src/assets/Icons/key.png new file mode 100644 index 0000000..ffb6961 Binary files /dev/null and b/src/assets/Icons/key.png differ diff --git a/src/assets/Icons/limits.png b/src/assets/Icons/limits.png new file mode 100644 index 0000000..67ed3d4 Binary files /dev/null and b/src/assets/Icons/limits.png differ diff --git a/src/assets/Icons/netflix.png b/src/assets/Icons/netflix.png new file mode 100644 index 0000000..78fafa6 Binary files /dev/null and b/src/assets/Icons/netflix.png differ diff --git a/src/assets/Icons/notification.png b/src/assets/Icons/notification.png new file mode 100644 index 0000000..8d44e53 Binary files /dev/null and b/src/assets/Icons/notification.png differ diff --git a/src/assets/Icons/plus.png b/src/assets/Icons/plus.png new file mode 100644 index 0000000..eeec7d2 Binary files /dev/null and b/src/assets/Icons/plus.png differ diff --git a/src/assets/Icons/profile.png b/src/assets/Icons/profile.png new file mode 100644 index 0000000..b9c086c Binary files /dev/null and b/src/assets/Icons/profile.png differ diff --git a/src/assets/Icons/rent.png b/src/assets/Icons/rent.png new file mode 100644 index 0000000..35e4467 Binary files /dev/null and b/src/assets/Icons/rent.png differ diff --git a/src/assets/Icons/settings.png b/src/assets/Icons/settings.png new file mode 100644 index 0000000..c4ca66d Binary files /dev/null and b/src/assets/Icons/settings.png differ diff --git a/src/components/AccountItem.tsx b/src/components/AccountItem.tsx index 85f038b..9dfa137 100644 --- a/src/components/AccountItem.tsx +++ b/src/components/AccountItem.tsx @@ -27,6 +27,27 @@ export const AccountItem: React.FC = ({ const Component = onPress ? TouchableOpacity : View; + const IconWrapper = ({ + children, + H_size = 40, + W_size = 60, + }: { + children: React.ReactNode; + H_size?: number; + W_size?: number; + }) => ( + + {children} + + ); + return ( = ({ {amount} )} + {arrow && ( {typeof arrow === "string" ? ( diff --git a/src/components/BottomNavigation.tsx b/src/components/BottomNavigation.tsx new file mode 100644 index 0000000..38d7c68 --- /dev/null +++ b/src/components/BottomNavigation.tsx @@ -0,0 +1,73 @@ +import type React from "react"; +import { View, TouchableOpacity, ImageSourcePropType } from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import AppText from "./ui/AppText"; +import AppImage from "~/components/ui/AppImage"; + +interface BottomNavigationProps { + activeTab: "Banking" | "Insights" | "Settings"; + onTabPress: (tab: "Banking" | "Insights" | "Settings") => void; +} + +export const BottomNavigation: React.FC = ({ + activeTab, + onTabPress, +}) => { + const { colors } = useTheme(); + + const TabItem = ({ + tab, + label, + iconSource, + }: { + tab: "Banking" | "Insights" | "Settings"; + label: string; + iconSource: ImageSourcePropType; + }) => { + const isActive = activeTab === tab; + return ( + onTabPress(tab)} + > + + + {label} + + + ); + }; + + return ( + + + + + + ); +}; diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..dffb668 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import { TouchableOpacity } from "react-native"; +import AppText from "./ui/AppText"; + +type ButtonProps = { + title: string; + onPress: () => void; + className?: string; + textClassName?: string; + disabled?: boolean; +}; + +export default function Button({ + title, + onPress, + className = "", + textClassName = "", + disabled = false, +}: ButtonProps) { + return ( + + + {title} + + + ); +} diff --git a/src/components/FloatingActionButton.tsx b/src/components/FloatingActionButton.tsx new file mode 100644 index 0000000..cbc04bd --- /dev/null +++ b/src/components/FloatingActionButton.tsx @@ -0,0 +1,53 @@ +import type React from "react"; +import { TouchableOpacity } from "react-native"; +import Animated, { + useSharedValue, + useAnimatedStyle, + withSpring, +} from "react-native-reanimated"; +import { useTheme } from "~/contexts/ThemeContext"; +import AppImage from "~/components/ui/AppImage"; + +interface FloatingActionButtonProps { + onPress: () => void; +} + +export const FloatingActionButton: React.FC = ({ + onPress, +}) => { + const { colors } = useTheme(); + const scale = useSharedValue(1); + + const animatedStyle = useAnimatedStyle(() => ({ + transform: [{ scale: scale.value }], + })); + + const handlePressIn = () => { + scale.value = withSpring(0.95); + }; + + const handlePressOut = () => { + scale.value = withSpring(1); + }; + + return ( + + + + + + ); +}; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 1cbe28d..6069467 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -13,11 +13,12 @@ import { ProfileSectionType } from "~/types"; const AnimatedView = Animated.createAnimatedComponent(Animated.View); interface HeaderProps { - name: string; - type: ProfileSectionType; // enum key, not a translated string + title?: string; // keep backward compatibility + name?: string; + type?: ProfileSectionType; // enum key for translation } -export const Header: React.FC = ({ name, type }) => { +export const Header: React.FC = ({ title, name, type }) => { const { colors } = useTheme(); const headerOpacity = useSharedValue(0); const { t } = useTranslation(); @@ -32,8 +33,8 @@ export const Header: React.FC = ({ name, type }) => { return ( = ({ name, type }) => { className="text-center text-sm" style={{ color: colors.text }} > - {name} - {t(type)} + {title ?? `${name ?? ""}${type ? ` - ${t(type)}` : ""}`} ); diff --git a/src/components/ProfileMenuItem.tsx b/src/components/ProfileMenuItem.tsx new file mode 100644 index 0000000..5205d1e --- /dev/null +++ b/src/components/ProfileMenuItem.tsx @@ -0,0 +1,59 @@ +import type React from "react"; +import { View, TouchableOpacity } from "react-native"; +import Animated, { FadeInDown } from "react-native-reanimated"; +import { useTheme } from "~/contexts/ThemeContext"; +import AppText from "./ui/AppText"; +import AppImage from "~/components/ui/AppImage"; + +interface ProfileMenuItemProps { + icon: React.ReactNode; + title: string; + onPress: () => void; + delay?: number; +} + +export const ProfileMenuItem: React.FC = ({ + icon, + title, + onPress, + delay = 0, +}) => { + const { colors } = useTheme(); + + return ( + + + + {icon} + + + + {title} + + + + + + + + ); +}; diff --git a/src/components/Toggle.tsx b/src/components/Toggle.tsx new file mode 100644 index 0000000..7f9d2bc --- /dev/null +++ b/src/components/Toggle.tsx @@ -0,0 +1,51 @@ +import type React from "react"; +import { TouchableOpacity } from "react-native"; +import Animated, { + useSharedValue, + useAnimatedStyle, + withSpring, +} from "react-native-reanimated"; +import { useTheme } from "~/contexts/ThemeContext"; + +interface ToggleProps { + value: boolean; + onValueChange: (value: boolean) => void; +} + +export const Toggle: React.FC = ({ value, onValueChange }) => { + const { colors } = useTheme(); + + const translateX = useSharedValue(value ? 16 : 0); + + const trackStyle = useAnimatedStyle(() => ({ + backgroundColor: value ? colors.good : colors.textSecondary, + })); + + const thumbStyle = useAnimatedStyle(() => ({ + transform: [{ translateX: translateX.value }], + backgroundColor: colors.text, + })); + + const handlePress = () => { + const newValue = !value; + translateX.value = withSpring(newValue ? 16 : 0, { + damping: 15, + stiffness: 150, + }); + onValueChange(newValue); + }; + + return ( + + + + + + ); +}; diff --git a/src/components/profile/BankAccounts.tsx b/src/components/profile/BankAccounts.tsx new file mode 100644 index 0000000..5848821 --- /dev/null +++ b/src/components/profile/BankAccounts.tsx @@ -0,0 +1,94 @@ +import type React from "react"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + ImageSourcePropType, +} from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import { Header } from "~/components/Header"; +import { ProfileMenuItem } from "~/components/ProfileMenuItem"; +import { BottomNavigation } from "~/components/BottomNavigation"; +import AppImage from "~/components/ui/AppImage"; + +interface BankAccountsScreenProps { + onNavigate: (screen: string) => void; +} + +export const BankAccountsScreen: React.FC = ({ + onNavigate, +}) => { + const { colors, isDark } = useTheme(); + + const IconWrapper = ({ + source, + iconW = 18, + iconH = 18, + }: { + source: ImageSourcePropType; + iconW?: number; + iconH?: number; + }) => ( + + + + ); + + return ( + + + + +
+ + + } + title="PayPal" + onPress={() => onNavigate("PayPal")} + delay={100} + /> + + } + title="DebitCard" + onPress={() => onNavigate("DebitCard")} + delay={200} + /> + + + } + title="Safe Account" + onPress={() => onNavigate("SafeAccount")} + delay={300} + /> + + + + + ); +}; diff --git a/src/components/profile/Income.tsx b/src/components/profile/Income.tsx new file mode 100644 index 0000000..718698d --- /dev/null +++ b/src/components/profile/Income.tsx @@ -0,0 +1,110 @@ +import type React from "react"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + ImageSourcePropType, +} from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import { Header } from "~/components/Header"; +import { SectionHeader } from "~/components/SectionHeader"; +import { AccountItem } from "~/components/AccountItem"; +import { BottomNavigation } from "~/components/BottomNavigation"; +import { FloatingActionButton } from "~/components/FloatingActionButton"; +import AppText from "~/components/ui/AppText"; +import AppImage from "~/components/ui/AppImage"; + +interface IncomeScreenProps { + onNavigate: (screen: string) => void; +} + +export const IncomeScreen: React.FC = ({ onNavigate }) => { + const { colors, isDark } = useTheme(); + const IconWrapper = ({ + source, + iconW = 18, + iconH = 18, + }: { + source: ImageSourcePropType; + iconW?: number; + iconH?: number; + }) => ( + + + + ); + + return ( + + + + +
+ + + + + Every Month + + + } + name="Company" + amount="2000€" + delay={200} + /> + + + + + Every Month + + + } + name="Rent" + amount="1000€" + delay={400} + /> + + } + name="Netflix" + amount="10,99€" + delay={500} + /> + + + console.log("Add income/expense")} /> + onNavigate(tab)} + /> + + ); +}; diff --git a/src/components/profile/Limits.tsx b/src/components/profile/Limits.tsx new file mode 100644 index 0000000..1f035ff --- /dev/null +++ b/src/components/profile/Limits.tsx @@ -0,0 +1,86 @@ +import type React from "react"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + ImageSourcePropType, +} from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import { Header } from "~/components/Header"; +import { SectionHeader } from "~/components/SectionHeader"; +import { AccountItem } from "~/components/AccountItem"; +import { BottomNavigation } from "~/components/BottomNavigation"; +import { FloatingActionButton } from "~/components/FloatingActionButton"; +import AppImage from "~/components/ui/AppImage"; + +interface LimitsScreenProps { + onNavigate: (screen: string) => void; +} + +export const LimitsScreen: React.FC = ({ onNavigate }) => { + const { colors, isDark } = useTheme(); + const IconWrapper = ({ + source, + iconW = 18, + iconH = 18, + }: { + source: ImageSourcePropType; + iconW?: number; + iconH?: number; + }) => ( + + + + ); + + return ( + + + + +
+ + + + + + } + name="Entertainment" + amount="200€" + delay={200} + /> + } + name="Rent" + amount="1000€" + delay={300} + /> + + + + onNavigate("AddLimit")} /> + onNavigate(tab)} + /> + + ); +}; diff --git a/src/components/profile/Notification.tsx b/src/components/profile/Notification.tsx new file mode 100644 index 0000000..a027296 --- /dev/null +++ b/src/components/profile/Notification.tsx @@ -0,0 +1,90 @@ +import React from "react"; +import { ScrollView, StatusBar, SafeAreaView, View } from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import { Header } from "~/components/Header"; +import { BottomNavigation } from "~/components/BottomNavigation"; +import { Toggle } from "~/components/Toggle"; +import AppText from "~/components/ui/AppText"; +import AppImage from "~/components/ui/AppImage"; + +interface NotificationScreenProps { + onNavigate: (screen: string) => void; +} + +export const NotificationScreen: React.FC = ({ + onNavigate, +}) => { + const { colors, isDark } = useTheme(); + const [notificationEnabled, setNotificationEnabled] = React.useState(true); + + const IconWrapper = ({ + source, + iconW = 18, + iconH = 18, + }: { + source: any; + iconW?: number; + iconH?: number; + }) => ( + + + + ); + + return ( + + + + +
+ + + + + + + + Notification + + + + + + + console.log(tab)} + /> + + ); +}; diff --git a/src/components/profile/ProfileScreen.tsx b/src/components/profile/ProfileScreen.tsx new file mode 100644 index 0000000..42f351c --- /dev/null +++ b/src/components/profile/ProfileScreen.tsx @@ -0,0 +1,102 @@ +import type React from "react"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + ImageSourcePropType, +} from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import { Header } from "~/components/Header"; +import { SectionHeader } from "~/components/SectionHeader"; +import { ProfileMenuItem } from "~/components/ProfileMenuItem"; +import { BottomNavigation } from "~/components/BottomNavigation"; +import AppImage from "~/components/ui/AppImage"; + +interface ProfileScreenProps { + onNavigate: (screen: string) => void; +} + +export const ProfileScreen: React.FC = ({ onNavigate }) => { + const { colors, isDark } = useTheme(); + + const IconWrapper = ({ + source, + iconW = 18, + iconH = 18, + }: { + source: ImageSourcePropType; + iconW?: number; + iconH?: number; + }) => ( + + + + ); + + return ( + + + + +
+ + + } + title="Profile" + onPress={() => onNavigate("UserProfile")} + delay={200} + /> + + } + title="Notification" + onPress={() => onNavigate("Notification")} + delay={300} + /> + + + } + title="Limits" + onPress={() => onNavigate("Limits")} + delay={500} + /> + } + title="Income" + onPress={() => onNavigate("Income")} + delay={600} + /> + + } + title="Bank Accounts" + onPress={() => onNavigate("BankAccounts")} + delay={700} + /> + + + console.log(tab)} + /> + + ); +}; diff --git a/src/components/profile/UserProfile.tsx b/src/components/profile/UserProfile.tsx new file mode 100644 index 0000000..97abda0 --- /dev/null +++ b/src/components/profile/UserProfile.tsx @@ -0,0 +1,228 @@ +import React, { useState } from "react"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + TouchableOpacity, + TextInput, +} from "react-native"; +import { useTheme } from "~/contexts/ThemeContext"; +import { Header } from "~/components/Header"; +import { BottomNavigation } from "~/components/BottomNavigation"; +import AppText from "~/components/ui/AppText"; +import AppImage from "~/components/ui/AppImage"; + +interface UserProfileScreenProps { + onNavigate: (screen: string) => void; +} + +const InputField = ({ + label, + value, + onChangeText, + placeholder, + validate, +}: { + label: string; + value: string; + onChangeText: (text: string) => void; + placeholder?: string; + validate?: (text: string) => string | null; +}) => { + const { colors } = useTheme(); + const [touched, setTouched] = useState(false); + + const error = validate ? validate(value) : null; + const isValid = touched && !error; + + return ( + + {/* Label */} + + {label} + + + {/* Input container */} + + { + if (!touched) setTouched(true); + onChangeText(text); + }} + placeholder={placeholder} + placeholderTextColor={colors.textSecondary} + selectionColor={colors.primary} + value={value} + style={{ + color: "white", + backgroundColor: colors.cardBackground, // add background color + outlineStyle: "none" as any, // remove browser yellow outline + }} + /> + + {/* Validation Icon */} + {touched && ( + + + {error ? "✕" : "✓"} + + + )} + + + {/* Error Text */} + {touched && error && ( + + {error} + + )} + + ); +}; + +export const UserProfileScreen: React.FC = ({ + onNavigate, +}) => { + const { colors, isDark } = useTheme(); + + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [email, setEmail] = useState(""); + + // Validation functions + const validateRequired = (text: string) => + text.trim().length === 0 ? "This field is required" : null; + + const validateEmail = (text: string) => { + const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (text.trim().length === 0) return "Email is required"; + if (!regex.test(text)) return "Sorry, this email format is invalid!"; + return null; + }; + + const allValid = + !validateRequired(firstName) && + !validateRequired(lastName) && + !validateEmail(email); + + const handleSave = () => { + console.log("Saving profile:", { firstName, lastName, email }); + // Replace with API call + }; + + return ( + + + + +
+ + {/* Avatar */} + + + + Change Picture + + + + {/* Fields */} + + + + + {/* Change Password */} + + + + Change Password + + + + {/* Save Button */} + + + Save Changes + + + + + console.log(tab)} + /> + + ); +}; diff --git a/src/components/ui/AppText.tsx b/src/components/ui/AppText.tsx index 9e6fbaf..9ef15ce 100644 --- a/src/components/ui/AppText.tsx +++ b/src/components/ui/AppText.tsx @@ -20,7 +20,6 @@ export default function AppText({ style, ...rest }: AppTextProps & Omit, keyof AppTextProps>) { - // This is a Component that we use to render text with custom fonts const [fontsLoaded] = useFonts({ Raleway: require("~/assets/fonts/Raleway-Regular.ttf"), RalewayMedium: require("~/assets/fonts/Raleway-Medium.ttf"), diff --git a/src/contexts/ThemeContext.tsx b/src/contexts/ThemeContext.tsx index 2717639..5ce04c4 100644 --- a/src/contexts/ThemeContext.tsx +++ b/src/contexts/ThemeContext.tsx @@ -3,16 +3,23 @@ import { createContext, useContext, type ReactNode } from "react"; import { useColorScheme } from "react-native"; interface ThemeColors { - primary: string; background: string; - secondary: string; - accent: string; text: string; - stroke: string; - backgroundText: string; - danger: string; - warn: string; - good: string; + accent: string; + border?: string; + stroke?: string; + good?: string; + primary: string; + + cardBackground?: string; + textSecondary?: string; + success?: string; + error?: string; + + secondary?: string; + backgroundText?: string; + danger?: string; + warn?: string; } interface ThemeContextType { @@ -20,31 +27,40 @@ interface ThemeContextType { isDark: boolean; } -// Keep these colours with the Tailwind config in sync! const lightColors: ThemeColors = { - primary: "#E1E0F2", background: "#FBFBFE", - secondary: "#EEEEF6", - accent: "#3C73E9", + cardBackground: "#ffffff", text: "#050315", + textSecondary: "#666666", + accent: "#3C73E9", + border: "#e0e0e0", + success: "#00ff88", + primary: "#E1E0F2", stroke: "#D1DEEB", + good: "#63B37E", + error: "#ea2b19", + secondary: "#EEEEF6", backgroundText: "#606067", danger: "#9C2E2E", warn: "#9C7E2E", - good: "#63B37E", }; const darkColors: ThemeColors = { - primary: "#212121", background: "#0B0B0B", - secondary: "#121111", - accent: "#3C73E9", + cardBackground: "#1a1a1a", text: "#DFDFDF", + textSecondary: "#a0a0a0", + accent: "#3C73E9", + border: "#2a2a2a", + success: "#4CAF50", + primary: "#212121", stroke: "#1C1C1C", + good: "#63B37E", + error: "#ea2b19", + secondary: "#121111", backgroundText: "#C0BFD5", danger: "#9C2E2E", warn: "#9C7E2E", - good: "#63B37E", }; const ThemeContext = createContext(undefined); diff --git a/src/i18n.ts b/src/i18n.ts index 870ebc8..66e52cc 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -60,13 +60,13 @@ const getDeviceLanguage = (): string => { } }; -// Start with device language but prepare to update it immediately after initialization +// Start with the device language but prepare to update it immediately after initialization const deviceLanguage = getDeviceLanguage(); -// Initialize i18next with device language as starting point +// Initialize i18next with device language as a starting point i18n.use(initReactI18next).init({ resources, - lng: deviceLanguage, // Start with device language + lng: deviceLanguage, // Start with the device language fallbackLng: "en", interpolation: { escapeValue: false, diff --git a/src/types/index.ts b/src/types/index.ts index c1e5504..1411170 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,5 +1,6 @@ import type React from "react"; import { ImageSourcePropType } from "react-native"; + export interface Account { id: string; name: string; @@ -22,6 +23,7 @@ export interface SharedFundsData { icon: React.ReactNode; arrow: React.ReactNode; } + export interface DashboardData { user: { name: string; @@ -52,3 +54,9 @@ export enum ProfileSectionType { BANK_ACCOUNTS = "navigationBankAccounts", NOTIFICATIONS = "navigationNotifications", } + +export interface ProfileData { + profile: { + name: string; + }; +}