Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"java.compile.nullAnalysis.mode": "automatic"
"java.compile.nullAnalysis.mode": "automatic",
"cSpell.words": ["Verticborder"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,5 @@
"typescript": "^5.3.3"
},
"private": true,
"packageManager": "pnpm@10.15.1+sha512.34e538c329b5553014ca8e8f4535997f96180a1d0f614339357449935350d924e22f8614682191264ec33d1462ac21561aff97f6bb18065351c162c7e8f6de67"
"packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a"
}
1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
packages:
- "src/*"
- "."

onlyBuiltDependencies:
Expand Down
9 changes: 6 additions & 3 deletions src/app/dashboard/banking/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -28,6 +29,9 @@ const Dashboard = () => {
/>

<ScrollView className="flex-1 p-8" showsVerticalScrollIndicator={false}>
{/* Header */}
<Header title={`${mockDashboardData.user.name} - Dashboard`} />

{/* Cards Section */}
{/* <SectionHeader title="Cards" delay={100} />
<SectionHeader title="Debitcard" size="medium" delay={150} />
Expand Down Expand Up @@ -79,7 +83,6 @@ const Dashboard = () => {
/>
))}

{/* Safe Accounts Section */}
<SectionHeader title={t("dashboardSafeAccounts")} delay={1000} />
{mockDashboardData.accounts.safe.map((account, index) => (
<AccountItem
Expand All @@ -92,15 +95,15 @@ const Dashboard = () => {
/>
))}

<SectionHeader title={t("sharedFunds")} delay={1000} />
<SectionHeader title={t("sharedFunds")} delay={1200} />
{mockDashboardData.sharedFunds && (
<AccountItem
key={mockDashboardData.sharedFunds.id}
icon={mockDashboardData.sharedFunds.icon}
name={mockDashboardData.sharedFunds.title}
arrow={mockDashboardData.sharedFunds.arrow}
iconWrapped
delay={1100}
delay={1300}
onPress={() =>
handleAccountPress(
mockDashboardData.sharedFunds.title,
Expand Down
47 changes: 47 additions & 0 deletions src/app/profile/index.tsx
Original file line number Diff line number Diff line change
@@ -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 <ProfileScreen onNavigate={handleNavigate} />;
case "Limits":
return <LimitsScreen onNavigate={handleNavigate} />;
case "Income":
return <IncomeScreen onNavigate={handleNavigate} />;
case "Notification":
return <NotificationScreen onNavigate={handleNavigate} />;
case "UserProfile":
return <UserProfileScreen onNavigate={handleNavigate} />;
case "BankAccounts":
return <BankAccountsScreen onNavigate={handleNavigate} />;
default:
return <ProfileScreen onNavigate={handleNavigate} />;
}
};

return renderScreen();
};

const ProfileApp: React.FC = () => {
return (
<ThemeProvider>
<ProfileAppContent />
</ThemeProvider>
);
};

export default ProfileApp;
Binary file added src/assets/Icons/Y.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/arrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/bank_account.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/banking.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/entertainment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/income.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/insights.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/key-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/key.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/limits.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/netflix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/plus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/profile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/rent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Icons/settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions src/components/AccountItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ export const AccountItem: React.FC<AccountItemProps> = ({

const Component = onPress ? TouchableOpacity : View;

const IconWrapper = ({
children,
H_size = 40,
W_size = 60,
}: {
children: React.ReactNode;
H_size?: number;
W_size?: number;
}) => (
<View
className="items-center justify-center rounded-2xl"
style={{
width: W_size,
height: H_size,
backgroundColor: colors.border,
}}
>
{children}
</View>
);

return (
<Animated.View
entering={FadeInDown.delay(delay).springify()}
Expand Down Expand Up @@ -64,6 +85,7 @@ export const AccountItem: React.FC<AccountItemProps> = ({
{amount}
</AppText>
)}

{arrow && (
<View className="ml-2">
{typeof arrow === "string" ? (
Expand Down
73 changes: 73 additions & 0 deletions src/components/BottomNavigation.tsx
Original file line number Diff line number Diff line change
@@ -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<BottomNavigationProps> = ({
activeTab,
onTabPress,
}) => {
const { colors } = useTheme();

const TabItem = ({
tab,
label,
iconSource,
}: {
tab: "Banking" | "Insights" | "Settings";
label: string;
iconSource: ImageSourcePropType;
}) => {
const isActive = activeTab === tab;
return (
<TouchableOpacity
className="flex-1 items-center py-3"
onPress={() => onTabPress(tab)}
>
<AppImage
source={iconSource}
className="h-5 w-5"
resizeMode="contain"
/>
<AppText
className="mt-1 text-xs"
style={{ color: isActive ? colors.primary : colors.text }}
>
{label}
</AppText>
</TouchableOpacity>
);
};

return (
<View
className="flex-row border-t pb-3"
style={{
borderTopColor: colors.border,
backgroundColor: colors.cardBackground,
}}
>
<TabItem
tab="Banking"
label="Banking"
iconSource={require("~/assets/Icons/banking.png")}
/>
<TabItem
tab="Insights"
label="Insights"
iconSource={require("~/assets/Icons/insights.png")}
/>
<TabItem
tab="Settings"
label="Settings"
iconSource={require("~/assets/Icons/settings.png")}
/>
</View>
);
};
39 changes: 39 additions & 0 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<TouchableOpacity
onPress={onPress}
disabled={disabled}
className={`items-center justify-center rounded-xl px-4 py-3 ${
disabled ? "bg-gray-400" : "bg-blue-600"
} ${className}`}
>
<AppText
semibold
className={`text-base ${
disabled ? "text-gray-200" : "text-white"
} ${textClassName}`}
style={{ color: undefined }}
>
{title}
</AppText>
</TouchableOpacity>
);
}
53 changes: 53 additions & 0 deletions src/components/FloatingActionButton.tsx
Original file line number Diff line number Diff line change
@@ -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<FloatingActionButtonProps> = ({
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 (
<Animated.View
className="absolute bottom-24 right-5 h-12 w-12 items-center justify-center rounded-full shadow-lg"
style={[{ backgroundColor: colors.primary }, animatedStyle]}
>
<TouchableOpacity
className="h-full w-full items-center justify-center"
onPress={onPress}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
activeOpacity={1}
>
<AppImage
source={require("~/assets/Icons/plus.png")}
className="h-3 w-3"
resizeMode="contain"
/>
</TouchableOpacity>
</Animated.View>
);
};
13 changes: 7 additions & 6 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<HeaderProps> = ({ name, type }) => {
export const Header: React.FC<HeaderProps> = ({ title, name, type }) => {
const { colors } = useTheme();
const headerOpacity = useSharedValue(0);
const { t } = useTranslation();
Expand All @@ -32,8 +33,8 @@ export const Header: React.FC<HeaderProps> = ({ name, type }) => {

return (
<AnimatedView
className="bg-black border-gray-800 w-full flex-row items-center justify-center gap-3 space-x-2 rounded-lg border-b px-4 py-3"
style={headerAnimatedStyle}
className="border-gray-800 absolute left-0 right-0 top-0 flex-row items-center justify-center gap-3 border-b px-4 py-4"
style={[headerAnimatedStyle, { backgroundColor: colors.cardBackground }]}
>
<AppImage
source={require("../assets/images/avatar.png")}
Expand All @@ -44,7 +45,7 @@ export const Header: React.FC<HeaderProps> = ({ name, type }) => {
className="text-center text-sm"
style={{ color: colors.text }}
>
{name} - {t(type)}
{title ?? `${name ?? ""}${type ? ` - ${t(type)}` : ""}`}
</AppText>
</AnimatedView>
);
Expand Down
Loading