diff --git a/app/(application)/(home-tabs)/_layout.tsx b/app/(application)/(home-tabs)/_layout.tsx deleted file mode 100644 index d66f4af..0000000 --- a/app/(application)/(home-tabs)/_layout.tsx +++ /dev/null @@ -1,52 +0,0 @@ - -//app/(application)/(tabs)/_layout.tsx -import { MainColor } from "@/constants/color-palet"; -import { Entypo } from "@expo/vector-icons"; -import { Tabs } from "expo-router"; - -export default function TabsLayout() { - return ( - <> - - - - ( - - ), - }} - /> - ( - - ), - }} - /> - - ( - - ), - }} - /> - - - ); -} diff --git a/app/(application)/(home-tabs)/index.tsx b/app/(application)/(home-tabs)/index.tsx deleted file mode 100644 index 28523eb..0000000 --- a/app/(application)/(home-tabs)/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import HomeView from "@/screens/Home/HomeView"; -import { Styles } from "@/styles/global-styles"; -import { Stack } from "expo-router"; -import React from "react"; -import { View } from "react-native"; - -export default function Tabs() { - // const router = useRouter(); - // const navigation = useNavigation(); - // useEffect(() => { - // navigation.setOptions({ - - // }); - // }, [navigation]); - - return ( - <> - - - - - - ); -} diff --git a/app/(application)/_layout.tsx b/app/(application)/_layout.tsx index 32c104d..e9f1c06 100644 --- a/app/(application)/_layout.tsx +++ b/app/(application)/_layout.tsx @@ -20,16 +20,77 @@ export default function ApplicationLayout() { }} > ( + router.back()} + /> + ), + headerRight: () => ( + router.back()} + /> + ), }} /> ( + router.back()} + /> + ), + }} + /> + + ( + router.back()} + /> + ), + }} + /> + + ( + router.back()} + /> + ), + }} + /> + + ( ( + + Selamat Datang! + Ini adalah halaman utama aplikasi Anda + +); +const SearchScreen = () => ( + + Search Screen + Cari apa yang Anda butuhkan + +); + +const ProfileScreen = () => ( + + Profile Screen + Informasi profil pengguna + +); + +const NotificationScreen = () => ( + + {Array.from({ length: 10 }).map((_, index) => ( + + Notifications + Notifikasi terbaru Anda + + ))} + +); + +// Custom Tab Component +const CustomTab = ({ icon, label, isActive, onPress }: any) => ( + + + + + + {label} + + {isActive && } + +); + +// Main Custom Tab Navigator +const CustomTabNavigator = () => { + const [activeTab, setActiveTab] = React.useState( + 'home' + ); + const [showHome, setShowHome] = React.useState(true); + + const tabs = [ + { + id: "search", + icon: "search-outline", + activeIcon: "search", + label: "Event", + component: SearchScreen, + path: "/event", + }, + { + id: "notifications", + icon: "notifications-outline", + activeIcon: "notifications", + label: "Forum", + component: NotificationScreen, + path: "/(application)/(home-tabs)/forum", + }, + { + id: "profile", + icon: "person-outline", + activeIcon: "person", + label: "Katalog", + component: ProfileScreen, + path: "/(application)/(home-tabs)/katalog", + }, + ]; + + + // Function untuk handle tab press + const handleTabPress = (tabId: string) => { + setActiveTab(tabId); + // setShowHome(false); // Hide home when any tab is pressed + }; + + // Determine which component to show + const getActiveComponent = () => { + if (showHome || activeTab === "home") { + return HomeScreen; + } + const selectedTab = tabs.find((tab) => tab.id === activeTab); + return selectedTab ? selectedTab.component : HomeScreen; + }; + + const ActiveComponent = getActiveComponent(); + + return ( + + {/* Content Area */} + + + + + + + {/* Custom Tab Bar */} + + + {tabs.map((e) => ( + { + // handleTabPress(e.id); + router.push(e.path as any); + }} + /> + ))} + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#f5f5f5", + }, + content: { + flex: 1, + }, + screen: { + flex: 1, + justifyContent: "center", + alignItems: "center", + padding: 20, + }, + screenTitle: { + fontSize: 28, + fontWeight: "bold", + color: "#333", + marginBottom: 10, + }, + screenText: { + fontSize: 16, + color: "#666", + textAlign: "center", + }, + tabBar: { + backgroundColor: "#fff", + paddingBottom: 20, + paddingTop: 10, + shadowColor: "#000", + shadowOffset: { + width: 0, + height: -2, + }, + shadowOpacity: 0.1, + shadowRadius: 3, + elevation: 5, + }, + tabContainer: { + flexDirection: "row", + justifyContent: "space-around", + alignItems: "center", + paddingHorizontal: 20, + }, + tabItem: { + alignItems: "center", + justifyContent: "center", + paddingVertical: 8, + paddingHorizontal: 12, + minWidth: width / 5, + position: "relative", + }, + activeTab: { + transform: [{ scale: 1.05 }], + }, + iconContainer: { + padding: 8, + borderRadius: 20, + marginBottom: 4, + }, + activeIconContainer: { + backgroundColor: "#007AFF", + shadowColor: "#007AFF", + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.3, + shadowRadius: 4, + elevation: 4, + }, + tabLabel: { + fontSize: 12, + color: "#666", + fontWeight: "500", + }, + activeTabLabel: { + color: "#007AFF", + fontWeight: "600", + }, + activeIndicator: { + position: "absolute", + bottom: -2, + width: 4, + height: 4, + borderRadius: 2, + backgroundColor: "#007AFF", + }, +}); + +export default CustomTabNavigator; diff --git a/app/(application)/(home-tabs)/forum/index.tsx b/app/(application)/forum/index.tsx similarity index 100% rename from app/(application)/(home-tabs)/forum/index.tsx rename to app/(application)/forum/index.tsx diff --git a/app/(application)/home.tsx b/app/(application)/home.tsx index 1fa68dd..1a69aac 100644 --- a/app/(application)/home.tsx +++ b/app/(application)/home.tsx @@ -1,16 +1,9 @@ -import ViewWrapper from "@/components/_ShareComponent/ViewWrapper"; -import HomeView from "@/screens/Home/HomeView"; -import { Styles } from "@/styles/global-styles"; -import { View } from "react-native"; +import NewHomeView from "@/screens/Home/UiHome"; export default function Application() { return ( <> - - - - - + ); } diff --git a/app/(application)/(home-tabs)/maps.tsx b/app/(application)/maps/index.tsx similarity index 95% rename from app/(application)/(home-tabs)/maps.tsx rename to app/(application)/maps/index.tsx index 0d51bc5..9f57a7e 100644 --- a/app/(application)/(home-tabs)/maps.tsx +++ b/app/(application)/maps/index.tsx @@ -5,5 +5,5 @@ export default function Maps() { Maps - ); + ) } \ No newline at end of file diff --git a/app/(application)/market-place/index.tsx b/app/(application)/market-place/index.tsx new file mode 100644 index 0000000..2db5901 --- /dev/null +++ b/app/(application)/market-place/index.tsx @@ -0,0 +1,9 @@ +import { Text, View } from "react-native"; + +export default function MarketPlace() { + return ( + + Market Place + + ); +} \ No newline at end of file diff --git a/app/(application)/(home-tabs)/katalog.tsx b/app/(application)/profile/index.tsx similarity index 58% rename from app/(application)/(home-tabs)/katalog.tsx rename to app/(application)/profile/index.tsx index 5182a18..657677d 100644 --- a/app/(application)/(home-tabs)/katalog.tsx +++ b/app/(application)/profile/index.tsx @@ -1,9 +1,9 @@ import { Text, View } from "react-native"; -export default function Katalog() { +export default function Profile() { return ( - Katalog + Profile ); } \ No newline at end of file diff --git a/app/_layout.tsx b/app/_layout.tsx index 1a2f7e1..58bcc64 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,9 +1,6 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { AccentColor, MainColor } from "@/constants/color-palet"; -import { Feather, Ionicons, MaterialIcons } from "@expo/vector-icons"; +import { MainColor } from "@/constants/color-palet"; import { Stack } from "expo-router"; -import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"; -import Icon from "react-native-vector-icons/FontAwesome"; +import { SafeAreaProvider } from "react-native-safe-area-context"; export default function RootLayout() { return ( @@ -17,32 +14,17 @@ export default function RootLayout() { headerStyle: { backgroundColor: MainColor.darkblue }, headerTitleStyle: { color: MainColor.yellow, fontWeight: "bold" }, headerTitleAlign: "center", - contentStyle: { - borderBottomColor: AccentColor.blue, - borderBottomWidth: 2, - }, + // contentStyle: { + // borderBottomColor: AccentColor.blue, + // borderBottomWidth: 2, + // }, // headerLargeStyle: { // backgroundColor: MainColor.darkblue, // }, // headerShadowVisible: false, }} > - ( - // - // ), - // headerLeft: () => ( - // - // ), - // }} - options={{ headerShown: false }} - /> + diff --git a/components/Button/ButtonCustom.tsx b/components/Button/ButtonCustom.tsx index b50ee40..9dedd2e 100644 --- a/components/Button/ButtonCustom.tsx +++ b/components/Button/ButtonCustom.tsx @@ -5,6 +5,7 @@ import { Text, TouchableOpacity } from "react-native"; import buttonStyles from "./buttonStyles"; // Definisi props dengan TypeScript + interface ButtonProps { onPress: () => void; title?: string; @@ -15,6 +16,17 @@ interface ButtonProps { iconLeft?: React.ReactNode; } +/** + * Props untuk ButtonCustom + * @param onPress: () => void + * @param title?: string + * @param backgroundColor?: string + * @param textColor?: string + * @param radius?: number + * @param disabled?: boolean + * @param iconLeft?: React.ReactNode + * @example iconLeft={ + */ const ButtonCustom: React.FC = ({ onPress, title = "Button", diff --git a/components/_ShareComponent/ViewWrapper.tsx b/components/_ShareComponent/ViewWrapper.tsx index c409f76..c132330 100644 --- a/components/_ShareComponent/ViewWrapper.tsx +++ b/components/_ShareComponent/ViewWrapper.tsx @@ -5,19 +5,23 @@ import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"; interface ViewWrapperProps { children: React.ReactNode; withBackground?: boolean; + tabBarComponent?: React.ReactNode; } const ViewWrapper = ({ children, withBackground = false, + tabBarComponent, }: ViewWrapperProps) => { - const assetBackground = require("../../assets/images/main-background.png"); return ( {children} )} + {tabBarComponent} ); diff --git a/screens/Authentication/RegisterView.tsx b/screens/Authentication/RegisterView.tsx index 49ca539..f7db88d 100644 --- a/screens/Authentication/RegisterView.tsx +++ b/screens/Authentication/RegisterView.tsx @@ -40,7 +40,7 @@ export default function RegisterView() { radius={10} onPress={() => ( console.log("Success register"), - router.push("/(application)/(home-tabs)") + router.push("/(application)/home") )} /> diff --git a/screens/Home/UiHome.tsx b/screens/Home/UiHome.tsx new file mode 100644 index 0000000..572a876 --- /dev/null +++ b/screens/Home/UiHome.tsx @@ -0,0 +1,194 @@ +/* eslint-disable no-unused-expressions */ +import Spacing from "@/components/_ShareComponent/Spacing"; +import ViewWrapper from "@/components/_ShareComponent/ViewWrapper"; +import { AccentColor, MainColor } from "@/constants/color-palet"; +import { Ionicons } from "@expo/vector-icons"; +import { Href, router } from "expo-router"; +import React from "react"; +import { + Dimensions, + StyleSheet, + Text, + TouchableOpacity, + View, +} from "react-native"; +import Home_BottomFeatureSection from "./bottomFeatureSection"; +import Home_ImageSection from "./imageSection"; +import Home_FeatureSection from "./topFeatureSection"; + +interface Tabs { + id: string; + icon: string; + activeIcon: string; + label: string; + path: Href; + isActive: boolean; + disabled: boolean; +} + +const { width } = Dimensions.get("window"); + +export default function NewHomeView() { + const tabs: Tabs[] = [ + { + id: "forum", + icon: "chatbubble-ellipses-outline", + activeIcon: "chatbubble-ellipses", + label: "Forum", + path: "/forum", + isActive: true, + disabled: false, + }, + { + id: "marketplace", + icon: "cart-outline", + activeIcon: "cart", + label: "Marketplace", + path: "/market-place", + isActive: false, + disabled: true, + }, + { + id: "maps", + icon: "map-outline", + activeIcon: "map", + label: "Maps", + path: "/maps", + isActive: true, + disabled: false, + }, + { + id: "profile", + icon: "person-outline", + activeIcon: "person", + label: "Profile", + path: "/profile", + isActive: true, + disabled: false, + }, + ]; + + const CustomTab = ({ icon, label, isActive, onPress, disabled }: any) => ( + + + + + + {label} + + {isActive && } + + ); + + return ( + <> + + + {tabs.map((e) => ( + { + e.disabled ? console.log("disabled") : router.push(e.path); + }} + /> + ))} + + + } + > + + + + {/* Grid Section */} + + + + {/* Job Vacancy Section */} + + + + + ); +} + +const styles = StyleSheet.create({ + tabBar: { + backgroundColor: MainColor.darkblue, + borderTopColor: AccentColor.blue, + borderTopWidth: 1, + // borderTopEndRadius: 10, + // borderTopStartRadius: 10, + // tintColor: MainColor.yellow + // paddingBottom: 20, + // paddingTop: 10, + // shadowColor: AccentColor.blue, + // shadowOffset: { + // width: 0, + // height: -2, + // }, + // shadowOpacity: 0.9, + // shadowRadius: 3, + // elevation: 5, + }, + tabContainer: { + flexDirection: "row", + justifyContent: "space-around", + alignItems: "center", + paddingHorizontal: 0, + }, + tabItem: { + alignItems: "center", + justifyContent: "center", + paddingVertical: 8, + paddingHorizontal: 12, + minWidth: width / 5, + position: "relative", + }, + activeTab: { + transform: [{ scale: 1.05 }], + }, + iconContainer: { + padding: 8, + borderRadius: 20, + // marginBottom: 4, + }, + activeIconContainer: { + // backgroundColor: "#007AFF", + // shadowColor: "#007AFF", + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.3, + // shadowRadius: 4, + // elevation: 4, + }, + tabLabel: { + fontSize: 10, + color: "#666", + fontWeight: "500", + }, + activeTabLabel: { + color: MainColor.white, + fontWeight: "600", + }, + activeIndicator: { + position: "absolute", + bottom: -2, + width: 4, + height: 4, + borderRadius: 2, + backgroundColor: "#007AFF", + }, +}); diff --git a/screens/Home/bottomFeatureSection.tsx b/screens/Home/bottomFeatureSection.tsx new file mode 100644 index 0000000..e2fde4d --- /dev/null +++ b/screens/Home/bottomFeatureSection.tsx @@ -0,0 +1,60 @@ +import Spacing from "@/components/_ShareComponent/Spacing"; +import DynamicTruncatedText from "@/components/_ShareComponent/TruncatedText"; +import { Text, View } from "react-native"; +import Icon from "react-native-vector-icons/FontAwesome"; +import { stylesHome } from "./homeViewStyle"; + +export default function Home_BottomFeatureSection() { + return ( + <> + + + + Job Vacancy + + + + {/* Vacancy Item 1 */} + + {/* */} + + + + + + + + {/* Vacancy Item 2 */} + + {/* */} + + + + + + + + + + ); +} diff --git a/screens/Home/imageSection.tsx b/screens/Home/imageSection.tsx new file mode 100644 index 0000000..b38076b --- /dev/null +++ b/screens/Home/imageSection.tsx @@ -0,0 +1,26 @@ +import { Image } from "expo-image"; +import { View } from "react-native"; + +export default function Home_ImageSection() { + return ( + + + + ); +} diff --git a/screens/Home/topFeatureSection.tsx b/screens/Home/topFeatureSection.tsx new file mode 100644 index 0000000..c029935 --- /dev/null +++ b/screens/Home/topFeatureSection.tsx @@ -0,0 +1,54 @@ +import { Ionicons } from "@expo/vector-icons"; +import { router } from "expo-router"; +import { Text, TouchableOpacity, View } from "react-native"; +import { stylesHome } from "./homeViewStyle"; + +export default function Home_FeatureSection() { + return ( + <> + + router.push("/(application)/event")} + > + + Event + + + + Collaboration + + + + Voting + + + + Crowdfunding + + + + + router.push("/(application)/event")} + > + + Event + + + + Collaboration + + + + Voting + + + + Crowdfunding + + + + ); +}