Skip to content
Open
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"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@neondatabase/serverless": "^1.0.0",
"@react-native-community/datetimepicker": "8.4.1",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.1.17",
"@t3-oss/env-core": "^0.13.6",
"@tanstack/react-query": "^5.75.7",
"@trpc/client": "^11.1.2",
Expand Down
64 changes: 63 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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
75 changes: 75 additions & 0 deletions src/components/BottomNavigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type React from "react";
import { View, TouchableOpacity, Image } from "react-native";
import { useTheme } from "../contexts/ThemeContext";
import AppText from "./ui/AppText";

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: any;
}) => {
const isActive = activeTab === tab;
return (
<TouchableOpacity
className="flex-1 items-center py-3"
onPress={() => onTabPress(tab)}
>
<Image
source={iconSource}
style={{
width: 20,
height: 20,
}}
resizeMode="contain"
/>
<AppText
className="mt-1 text-xs"
style={{ color: isActive ? colors.text : 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>
);
}
52 changes: 52 additions & 0 deletions src/components/FloatingActionButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type React from "react";
import { TouchableOpacity, Image } from "react-native";
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from "react-native-reanimated";
import { useTheme } from "~/contexts/ThemeContext";

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}
>
<Image
source={require("~/assets/Icons/plus.png")}
style={{ width: 12, height: 12 }}
resizeMode="contain"
/>
</TouchableOpacity>
</Animated.View>
);
};
Loading
Loading