diff --git a/app/(application)/(user)/_layout.tsx b/app/(application)/(user)/_layout.tsx
index 1ef2af6..5c87b0a 100644
--- a/app/(application)/(user)/_layout.tsx
+++ b/app/(application)/(user)/_layout.tsx
@@ -107,6 +107,48 @@ export default function UserLayout() {
headerLeft: () => ,
}}
/>
+ {/* ========== End Event Section ========= */}
+
+ {/* ========== Collaboration Section ========= */}
+ ,
+ }}
+ />
+ ,
+ }}
+ />
+ ,
+ }}
+ />
+ ,
+ }}
+ />
+
+ ,
+ }}
+ />
+
+
+ {/* ========== End Collaboration Section ========= */}
{/* ========== Forum Section ========= */}
,
+ headerLeft: () => ,
}}
/>
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+
+ );
+}
diff --git a/app/(application)/(user)/collaboration/(tabs)/group.tsx b/app/(application)/(user)/collaboration/(tabs)/group.tsx
new file mode 100644
index 0000000..5144f93
--- /dev/null
+++ b/app/(application)/(user)/collaboration/(tabs)/group.tsx
@@ -0,0 +1,68 @@
+import { BaseBox, Grid, TextCustom } from "@/components";
+import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
+import { MainColor } from "@/constants/color-palet";
+import { Feather } from "@expo/vector-icons";
+
+export default function CollaborationGroup() {
+
+
+ return (
+
+ {Array.from({ length: 10 }).map((_, index) => (
+
+
+
+ {generateProjectName()}
+ 2 Anggota
+
+
+
+
+
+
+ ))}
+
+ );
+}
+
+
+function generateProjectName() {
+ const adjectives = [
+ "Blue",
+ "Dark",
+ "Bright",
+ "Quantum",
+ "Silent",
+ "Cyber",
+ "Epic",
+ "Golden",
+ "Shadow",
+ "Rapid",
+ ];
+
+ const nouns = [
+ "Spark",
+ "Core",
+ "Orbit",
+ "Nest",
+ "Drive",
+ "Nova",
+ "Cloud",
+ "Blade",
+ "Matrix",
+ "Link",
+ ];
+
+ const randomAdjective =
+ adjectives[Math.floor(Math.random() * adjectives.length)];
+ const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
+
+ return randomAdjective + randomNoun;
+}
\ No newline at end of file
diff --git a/app/(application)/(user)/collaboration/(tabs)/index.tsx b/app/(application)/(user)/collaboration/(tabs)/index.tsx
new file mode 100644
index 0000000..037bf40
--- /dev/null
+++ b/app/(application)/(user)/collaboration/(tabs)/index.tsx
@@ -0,0 +1,28 @@
+import { FloatingButton, ViewWrapper } from "@/components";
+import Collaboration_BoxPublishSection from "@/screens/Collaboration/BoxPublishSection";
+import { router } from "expo-router";
+
+export default function CollaborationBeranda() {
+ return (
+ <>
+ {
+ router.push("/collaboration/create");
+ }}
+ />
+ }
+ >
+ {Array.from({ length: 10 }).map((_, index) => (
+
+ ))}
+
+ >
+ );
+}
diff --git a/app/(application)/(user)/collaboration/(tabs)/participant.tsx b/app/(application)/(user)/collaboration/(tabs)/participant.tsx
new file mode 100644
index 0000000..082792c
--- /dev/null
+++ b/app/(application)/(user)/collaboration/(tabs)/participant.tsx
@@ -0,0 +1,77 @@
+import { ButtonCustom, Spacing } from "@/components";
+import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
+import { AccentColor, MainColor } from "@/constants/color-palet";
+import Collaboration_BoxPublishSection from "@/screens/Collaboration/BoxPublishSection";
+import { useState } from "react";
+import { View } from "react-native";
+
+export default function CollaborationParticipans() {
+ const [activeCategory, setActiveCategory] = useState(
+ "participant"
+ );
+
+ const handlePress = (item: any) => {
+ setActiveCategory(item);
+ // tambahkan logika lain seperti filter dsb.
+ };
+
+ const headerComponent = (
+
+ handlePress("participant")}
+ >
+ Partisipasi Proyek
+
+
+ handlePress("main")}
+ >
+ Proyek Saya
+
+
+ );
+
+ return (
+
+ {Array.from({ length: 10 }).map((_, index) => (
+
+ ))}
+
+ );
+}
diff --git a/app/(application)/(user)/collaboration/[id]/[detail]/info.tsx b/app/(application)/(user)/collaboration/[id]/[detail]/info.tsx
new file mode 100644
index 0000000..8362799
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/[detail]/info.tsx
@@ -0,0 +1,73 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import {
+ AvatarUsernameAndOtherComponent,
+ BackButton,
+ BoxWithHeaderSection,
+ Grid,
+ StackCustom,
+ TextCustom,
+ ViewWrapper,
+} from "@/components";
+import { Stack, useLocalSearchParams } from "expo-router";
+
+export default function CollaborationRoomInfo() {
+ const { id, detail } = useLocalSearchParams();
+ return (
+ <>
+ ,
+ }}
+ />
+
+
+
+
+ {listData.map((item, index) => (
+
+
+ {item.title}
+
+
+ {item.value}
+
+
+ ))}
+
+
+
+
+ {Array.from({ length: 10 }).map((_, index) => (
+
+ ))}
+
+
+ >
+ );
+}
+
+const listData = [
+ {
+ title: "Judul Proyek",
+ value: "Judul Proyek",
+ },
+ {
+ title: "Industri",
+ value: "Pilihan Industri",
+ },
+ {
+ title: "Deskripsi",
+ value: "Deskripsi Proyek",
+ },
+ {
+ title: "Tujuan Proyek",
+ value:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+ },
+ {
+ title: "Keuntungan Proyek",
+ value:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+ },
+];
diff --git a/app/(application)/(user)/collaboration/[id]/[detail]/room-chat.tsx b/app/(application)/(user)/collaboration/[id]/[detail]/room-chat.tsx
new file mode 100644
index 0000000..542d58f
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/[detail]/room-chat.tsx
@@ -0,0 +1,192 @@
+import {
+ BackButton,
+ BoxButtonOnFooter,
+ Grid,
+ TextCustom,
+ TextInputCustom,
+ ViewWrapper,
+} from "@/components";
+import { AccentColor, MainColor } from "@/constants/color-palet";
+import { ICON_SIZE_SMALL } from "@/constants/constans-value";
+import { Feather } from "@expo/vector-icons";
+import { router, Stack, useLocalSearchParams } from "expo-router";
+import { StyleSheet, TouchableOpacity, View } from "react-native";
+
+export default function CollaborationRoomChat() {
+ const { id, detail } = useLocalSearchParams();
+
+ const inputChat = () => {
+ return (
+ <>
+
+ {/*
+
+ console.log("Send")}
+ style={{
+ backgroundColor: AccentColor.blue,
+ padding: 10,
+ borderRadius: 50,
+ }}
+ >
+
+
+ */}
+
+
+
+
+
+
+
+
+ console.log("Send")}
+ style={{
+ backgroundColor: AccentColor.blue,
+ padding: 10,
+ borderRadius: 50,
+ }}
+ >
+
+
+
+
+
+ >
+ );
+ };
+
+ return (
+ <>
+ ,
+ headerRight: () => (
+ router.push(`/collaboration/${id}/${detail}/info`)}
+ />
+ ),
+ }}
+ />
+
+ {dummyData.map((item, index) => (
+
+
+ {item.nama}
+ {item.chat}
+
+ {new Date(item.time).toLocaleTimeString([], {
+ hour: "2-digit",
+ minute: "2-digit",
+ })}
+
+
+
+ ))}
+ {/*
+ */}
+
+ >
+ );
+}
+
+const dummyData = [
+ {
+ nama: "Dina",
+ role: 1,
+ chat: "Hai! Kamu udah lihat dokumen proyek yang baru?",
+ time: "2025-07-24T09:01:15Z",
+ },
+ {
+ nama: "Rafi",
+ role: 2,
+ chat: "Halo! Iya, aku baru aja baca. Kayaknya kita harus revisi bagian akhir deh.",
+ time: "2025-07-24T09:02:03Z",
+ },
+ {
+ nama: "Dina",
+ role: 1,
+ chat: "Setuju. Aku juga kurang sreg sama penutupnya.",
+ time: "2025-07-24T09:02:45Z",
+ },
+ {
+ nama: "Rafi",
+ role: 2,
+ chat: "Oke, aku coba edit malam ini ya. Nanti aku share ulang versinya.",
+ time: "2025-07-24T09:03:10Z",
+ },
+ {
+ nama: "Dina",
+ role: 1,
+ chat: "Siap, makasih ya. Jangan begadang!",
+ time: "2025-07-24T09:03:30Z",
+ },
+];
+
+const styles = StyleSheet.create({
+ container: {
+ paddingVertical: 10,
+ paddingHorizontal: 12,
+ },
+ messageRow: {
+ flexDirection: "row",
+ marginBottom: 12,
+ },
+ rightAlign: {
+ justifyContent: "flex-end",
+ },
+ leftAlign: {
+ justifyContent: "flex-start",
+ },
+ bubble: {
+ maxWidth: "75%",
+ padding: 10,
+ borderRadius: 12,
+ },
+ bubbleRight: {
+ backgroundColor: "#DCF8C6", // hijau muda
+ borderTopRightRadius: 0,
+ },
+ bubbleLeft: {
+ backgroundColor: "#F0F0F0", // abu-abu terang
+ borderTopLeftRadius: 0,
+ },
+ sender: {
+ fontSize: 12,
+ fontWeight: "bold",
+ marginBottom: 2,
+ color: "#555",
+ },
+ message: {
+ fontSize: 15,
+ color: "#000",
+ },
+ time: {
+ fontSize: 10,
+ color: "#888",
+ textAlign: "right",
+ marginTop: 4,
+ },
+});
diff --git a/app/(application)/(user)/collaboration/[id]/detail-participant.tsx b/app/(application)/(user)/collaboration/[id]/detail-participant.tsx
new file mode 100644
index 0000000..5a11ddd
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/detail-participant.tsx
@@ -0,0 +1,62 @@
+import {
+ AvatarUsernameAndOtherComponent,
+ BaseBox,
+ DrawerCustom,
+ StackCustom,
+ TextCustom,
+ ViewWrapper,
+} from "@/components";
+import { ICON_SIZE_SMALL } from "@/constants/constans-value";
+import Collaboration_BoxDetailSection from "@/screens/Collaboration/BoxDetailSection";
+import { MaterialIcons } from "@expo/vector-icons";
+import { useLocalSearchParams } from "expo-router";
+import { useState } from "react";
+
+export default function CollaborationDetailParticipant() {
+ const { id } = useLocalSearchParams();
+ const [openDrawerParticipant, setOpenDrawerParticipant] = useState(false);
+
+ return (
+ <>
+
+
+
+
+ Partisipan
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+ setOpenDrawerParticipant(true)}
+ />
+ }
+ />
+ ))}
+
+
+
+ setOpenDrawerParticipant(false)}
+ height={"auto"}
+ >
+
+ Deskripsi Diri
+
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit. Commodi,
+ itaque adipisci. Voluptas, sed quod! Ad facere labore voluptates,
+ neque quidem aut reprehenderit ducimus mollitia quisquam temporibus!
+ Temporibus iusto soluta necessitatibus.
+
+
+
+ >
+ );
+}
diff --git a/app/(application)/(user)/collaboration/[id]/detail-project-main.tsx b/app/(application)/(user)/collaboration/[id]/detail-project-main.tsx
new file mode 100644
index 0000000..32af517
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/detail-project-main.tsx
@@ -0,0 +1,106 @@
+import {
+ AlertDefaultSystem,
+ BackButton,
+ ButtonCustom,
+ DotButton,
+ DrawerCustom,
+ MenuDrawerDynamicGrid,
+ Spacing,
+ StackCustom,
+ TextCustom,
+ ViewWrapper
+} from "@/components";
+import { IconEdit } from "@/components/_Icon";
+import Collaboration_BoxDetailSection from "@/screens/Collaboration/BoxDetailSection";
+import Collaboration_MainParticipanSelectedSection from "@/screens/Collaboration/ProjectMainSelectedSection";
+import { router, Stack, useLocalSearchParams } from "expo-router";
+import { useState } from "react";
+
+export default function CollaborationDetailProjectMain() {
+ const { id } = useLocalSearchParams();
+ const [openDrawer, setOpenDrawer] = useState(false);
+ const [openDrawerParticipant, setOpenDrawerParticipant] = useState(false);
+ const [selected, setSelected] = useState<(string | number)[]>([]);
+
+ const handleEdit = () => {
+ console.log("Edit collaboration");
+ router.push("/(application)/(user)/collaboration/(id)/edit");
+ };
+
+ return (
+ <>
+ ,
+ headerRight: () => setOpenDrawer(true)} />,
+ }}
+ />
+
+
+
+
+ {
+ AlertDefaultSystem({
+ title: "Buat Grup",
+ message:
+ "Apakah anda yakin ingin membuat grup untuk proyek ini ?",
+ textLeft: "Tidak",
+ textRight: "Ya",
+ onPressLeft: () => {},
+ onPressRight: () => {
+ router.navigate(
+ "/(application)/(user)/collaboration/(tabs)/group"
+ );
+ console.log("selected :", selected);
+ },
+ });
+ }}
+ >
+ Buat Grup
+
+
+
+
+ setOpenDrawer(false)}
+ height={"auto"}
+ >
+ ,
+ },
+ ]}
+ onPressItem={(item) => {
+ handleEdit();
+ }}
+ />
+
+
+ setOpenDrawerParticipant(false)}
+ height={"auto"}
+ >
+
+ Deskripsi Diri
+
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit. Commodi,
+ itaque adipisci. Voluptas, sed quod! Ad facere labore voluptates,
+ neque quidem aut reprehenderit ducimus mollitia quisquam temporibus!
+ Temporibus iusto soluta necessitatibus.
+
+
+
+ >
+ );
+}
diff --git a/app/(application)/(user)/collaboration/[id]/edit.tsx b/app/(application)/(user)/collaboration/[id]/edit.tsx
new file mode 100644
index 0000000..233bfe8
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/edit.tsx
@@ -0,0 +1,53 @@
+import {
+ ButtonCustom,
+ SelectCustom,
+ StackCustom,
+ TextAreaCustom,
+ TextInputCustom,
+ ViewWrapper,
+} from "@/components";
+import { router } from "expo-router";
+
+export default function CollaborationEdit() {
+ return (
+
+
+
+
+ console.log(value)}
+ />
+
+
+
+
+
+ {
+ console.log("Update proyek");
+ router.back();
+ }}
+ />
+
+
+ );
+}
diff --git a/app/(application)/(user)/collaboration/[id]/index.tsx b/app/(application)/(user)/collaboration/[id]/index.tsx
new file mode 100644
index 0000000..8a1082b
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/index.tsx
@@ -0,0 +1,91 @@
+import {
+ AlertDefaultSystem,
+ BackButton,
+ ButtonCustom,
+ DotButton,
+ DrawerCustom,
+ MenuDrawerDynamicGrid,
+ TextAreaCustom,
+ ViewWrapper,
+} from "@/components";
+import Collaboration_BoxDetailSection from "@/screens/Collaboration/BoxDetailSection";
+import { Ionicons } from "@expo/vector-icons";
+import { router, Stack, useLocalSearchParams } from "expo-router";
+import { useState } from "react";
+
+export default function CollaborationDetail() {
+ const { id } = useLocalSearchParams();
+ const [openDrawerPartisipasi, setOpenDrawerPartisipasi] = useState(false);
+ const [openDrawerMenu, setOpenDrawerMenu] = useState(false);
+ return (
+ <>
+ ,
+ headerRight: () => (
+ setOpenDrawerMenu(true)} />
+ ),
+ }}
+ />
+
+
+
+ setOpenDrawerPartisipasi(true)}>
+ Partisipasi
+
+
+
+ {/* Drawer Partisipasi */}
+ setOpenDrawerPartisipasi(false)}
+ height={300}
+ >
+
+
+ {
+ AlertDefaultSystem({
+ title: "Simpan data deskripsi",
+ message: "Apakah anda sudah yakin ingin menyimpan data ini ?",
+ textLeft: "Batal",
+ textRight: "Simpan",
+ onPressRight: () => router.replace(`/collaboration/(tabs)/group`),
+ });
+ }}
+ >
+ Simpan
+
+
+
+ {/* Drawer Menu */}
+ setOpenDrawerMenu(false)}
+ height={250}
+ >
+ ,
+ label: "Daftar Partisipan",
+ path: `/collaboration/${id}/list-of-participants`,
+ },
+ ]}
+ onPressItem={(item) => {
+ router.push(item.path as any);
+ setOpenDrawerMenu(false);
+ }}
+ />
+
+ >
+ );
+}
diff --git a/app/(application)/(user)/collaboration/[id]/list-of-participants.tsx b/app/(application)/(user)/collaboration/[id]/list-of-participants.tsx
new file mode 100644
index 0000000..91e064d
--- /dev/null
+++ b/app/(application)/(user)/collaboration/[id]/list-of-participants.tsx
@@ -0,0 +1,82 @@
+import {
+ AvatarUsernameAndOtherComponent,
+ BaseBox,
+ DrawerCustom,
+ Spacing,
+ StackCustom,
+ TextCustom,
+ ViewWrapper
+} from "@/components";
+import { Feather } from "@expo/vector-icons";
+import { useLocalSearchParams } from "expo-router";
+import { useState } from "react";
+import { ScrollView } from "react-native";
+
+export default function CollaborationListOfParticipants() {
+ const { id } = useLocalSearchParams();
+ const [openDrawer, setOpenDrawer] = useState(false);
+ return (
+ <>
+
+ {Array.from({ length: 10 }).map((_, index) => (
+
+ setOpenDrawer(true)}
+ />
+ }
+ />
+
+ ))}
+
+
+ {/* Drawer */}
+ setOpenDrawer(false)}
+ >
+
+ Deskripsi diri
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.Lorem
+ ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.Lorem
+ ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.Lorem
+ ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut iqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+ labore et dolore magna aliqua.
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/app/(application)/(user)/collaboration/create.tsx b/app/(application)/(user)/collaboration/create.tsx
new file mode 100644
index 0000000..3670778
--- /dev/null
+++ b/app/(application)/(user)/collaboration/create.tsx
@@ -0,0 +1,53 @@
+import {
+ ButtonCustom,
+ SelectCustom,
+ StackCustom,
+ TextAreaCustom,
+ TextInputCustom,
+ ViewWrapper
+} from "@/components";
+import { router } from "expo-router";
+
+export default function CollaborationCreate() {
+ return (
+
+
+
+
+ console.log(value)}
+ />
+
+
+
+
+
+ {
+ console.log("Simpan proyek");
+ router.back();
+ }}
+ />
+
+
+ );
+}
diff --git a/app/(application)/(user)/event/(tabs)/_layout.tsx b/app/(application)/(user)/event/(tabs)/_layout.tsx
index 41fc6ed..9f04143 100644
--- a/app/(application)/(user)/event/(tabs)/_layout.tsx
+++ b/app/(application)/(user)/event/(tabs)/_layout.tsx
@@ -1,31 +1,11 @@
-import { AccentColor, MainColor } from "@/constants/color-palet";
-import { OS_IOS_HEIGHT, OS_ANDROID_HEIGHT } from "@/constants/constans-value";
+import { TabsStyles } from "@/styles/tabs-styles";
import { FontAwesome5, Ionicons } from "@expo/vector-icons";
import { Tabs } from "expo-router";
-import { Platform, View } from "react-native";
export default function EventTabsLayout() {
return (
- );
-}
diff --git a/app/(application)/(user)/event/(tabs)/history.tsx b/app/(application)/(user)/event/(tabs)/history.tsx
index 31ae386..c590df3 100644
--- a/app/(application)/(user)/event/(tabs)/history.tsx
+++ b/app/(application)/(user)/event/(tabs)/history.tsx
@@ -56,10 +56,11 @@ export default function EventHistory() {
{new Date().toLocaleDateString()}
}
+ href={`/event/${index}/history`}
/>
))}
diff --git a/app/(application)/(user)/event/(tabs)/index.tsx b/app/(application)/(user)/event/(tabs)/index.tsx
index 0cc395a..d54f026 100644
--- a/app/(application)/(user)/event/(tabs)/index.tsx
+++ b/app/(application)/(user)/event/(tabs)/index.tsx
@@ -12,7 +12,11 @@ export default function EventBeranda() {
}
>
{Array.from({ length: 10 }).map((_, index) => (
-
+
))}
);
diff --git a/app/(application)/(user)/profile/[id]/index.tsx b/app/(application)/(user)/profile/[id]/index.tsx
index b8aad97..ba375dc 100644
--- a/app/(application)/(user)/profile/[id]/index.tsx
+++ b/app/(application)/(user)/profile/[id]/index.tsx
@@ -4,8 +4,8 @@ import LeftButtonCustom from "@/components/Button/BackButton";
import DrawerCustom from "@/components/Drawer/DrawerCustom";
import { MainColor } from "@/constants/color-palet";
import { drawerItemsProfile } from "@/screens/Profile/ListPage";
-import Profile_MenuDrawerSection from "@/screens/Profile/MenuDrawerSection";
-import ProfilSection from "@/screens/Profile/ProfilSection";
+import Profile_MenuDrawerSection from "@/screens/Profile/menuDrawerSection";
+import ProfileSection from "@/screens/Profile/ProfileSection";
import { GStyles } from "@/styles/global-styles";
import { Ionicons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
@@ -52,7 +52,7 @@ export default function Profile() {
headerTitleStyle: GStyles.headerTitleStyle,
}}
/>
-
+
{/* Drawer Komponen Eksternal */}
diff --git a/app/(application)/coba/double-scroll.tsx b/app/(application)/coba/double-scroll.tsx
new file mode 100644
index 0000000..3600384
--- /dev/null
+++ b/app/(application)/coba/double-scroll.tsx
@@ -0,0 +1,258 @@
+// File: src/screens/EventDetailScreen.tsx
+
+import LeftButtonCustom from "@/components/Button/BackButton";
+import { MainColor } from "@/constants/color-palet";
+import React, { useState, useEffect } from "react";
+import {
+ FlatList,
+ View,
+ Text,
+ Image,
+ StyleSheet,
+ ActivityIndicator,
+} from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+// === TYPES ===
+type Participant = {
+ id: number;
+ name: string;
+ avatar: string;
+};
+
+type EventDetail = {
+ id: number;
+ title: string;
+ description: string;
+ date: string;
+ location: string;
+ organizer: string;
+};
+
+// === KOMPONEN UTAMA ===
+const EventDetailScreen: React.FC = () => {
+ const [participants, setParticipants] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [loadingMore, setLoadingMore] = useState(false);
+
+ // Data event
+ const event: EventDetail = {
+ id: 1,
+ title: "Workshop React Native & Expo",
+ description:
+ "Pelatihan intensif pengembangan aplikasi mobile menggunakan React Native, Expo, dan TypeScript. Cocok untuk developer tingkat menengah.",
+ date: "Sabtu, 5 April 2025 | 09:00 - 16:00",
+ location: "Gedung Teknologi, Jakarta Selatan",
+ organizer: "DevCommunity Indonesia",
+ };
+
+ // Simulasi API: generate data dummy
+ const generateParticipants = (
+ startId: number,
+ count: number
+ ): Participant[] => {
+ return Array.from({ length: count }, (_, i) => {
+ const id = startId + i;
+ return {
+ id,
+ name: `Peserta ${id}`,
+ avatar: `https://i.pravatar.cc/150?img=${(id % 70) + 1}`, // 70 gambar unik
+ };
+ });
+ };
+
+ // Load data awal
+ useEffect(() => {
+ const loadInitial = () => {
+ setTimeout(() => {
+ const initialData = generateParticipants(1, 20); // 20 peserta pertama
+ setParticipants(initialData);
+ setLoading(false);
+ }, 800);
+ };
+
+ loadInitial();
+ }, []);
+
+ // Load lebih banyak peserta saat scroll ke bawah
+ const loadMore = () => {
+ if (loadingMore || participants.length >= 200) return; // Batas 200 peserta
+
+ setLoadingMore(true);
+ setTimeout(() => {
+ const nextId = participants.length + 1;
+ const newData = generateParticipants(nextId, 10); // Tambah 10 peserta
+ setParticipants((prev) => [...prev, ...newData]);
+ setLoadingMore(false);
+ }, 1000);
+ };
+
+ // Render footer: loading indicator
+ const renderFooter = () => {
+ if (!loadingMore) return null;
+ return (
+
+
+ Memuat peserta berikutnya...
+
+ );
+ };
+
+ // Render header: detail event + info jumlah peserta
+ const renderHeader = () => (
+ <>
+
+
+ {event.title}
+ 📅 {event.date}
+ 📍 {event.location}
+ 👤 {event.organizer}
+ {event.description}
+
+
+
+
+ Daftar Peserta ({participants.length})
+
+
+
+ {/* Sub-header tambahan jika perlu */}
+ {participants.length === 0 ? (
+ Belum ada peserta yang terdaftar.
+ ) : null}
+ >
+ );
+
+ // Loading awal
+ if (loading) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+ <>
+ item.id.toString()}
+ ListHeaderComponent={renderHeader}
+ ListFooterComponent={renderFooter}
+ onEndReached={loadMore}
+ onEndReachedThreshold={0.5}
+ renderItem={({ item }) => (
+
+
+ {item.name}
+
+ )}
+ initialNumToRender={10}
+ maxToRenderPerBatch={5}
+ windowSize={7}
+ showsVerticalScrollIndicator={false}
+ ListEmptyComponent={
+ Tidak ada peserta.
+ }
+ />
+
+
+ >
+ );
+};
+
+export default EventDetailScreen;
+
+// === STYLES ===
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: "#f8f9fa",
+ },
+ loader: {
+ marginTop: 20,
+ },
+ headerContainer: {
+ padding: 16,
+ backgroundColor: "#ffffff",
+ borderBottomWidth: 1,
+ borderBottomColor: "#e0e0e0",
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: "bold",
+ color: "#1d1d1d",
+ marginBottom: 8,
+ },
+ info: {
+ fontSize: 16,
+ color: "#444",
+ marginBottom: 4,
+ },
+ description: {
+ fontSize: 14,
+ color: "#666",
+ lineHeight: 20,
+ marginTop: 12,
+ },
+ divider: {
+ height: 1,
+ backgroundColor: "#e0e0e0",
+ marginVertical: 16,
+ },
+ sectionTitle: {
+ fontSize: 18,
+ fontWeight: "600",
+ color: "#1d1d1d",
+ marginBottom: 12,
+ },
+ participantItem: {
+ flexDirection: "row",
+ alignItems: "center",
+ paddingHorizontal: 16,
+ paddingVertical: 12,
+ backgroundColor: "#fff",
+ borderBottomWidth: 1,
+ borderBottomColor: "#f0f0f0",
+ },
+ avatar: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ marginRight: 12,
+ },
+ participantName: {
+ fontSize: 16,
+ color: "#333",
+ },
+ footer: {
+ flexDirection: "row",
+ justifyContent: "center",
+ alignItems: "center",
+ padding: 16,
+ backgroundColor: "#f8f9fa",
+ },
+ loadingText: {
+ color: "#555",
+ fontSize: 14,
+ },
+ empty: {
+ textAlign: "center",
+ color: "#999",
+ fontStyle: "italic",
+ padding: 16,
+ backgroundColor: "#fff",
+ fontSize: 14,
+ },
+ subHeader: {
+ paddingHorizontal: 16,
+ paddingVertical: 8,
+ backgroundColor: "#f1f1f1",
+ fontSize: 14,
+ color: "#666",
+ fontStyle: "italic",
+ },
+});
diff --git a/app/(application)/coba/index.tsx b/app/(application)/coba/index.tsx
index 7e1b43b..65e2c9e 100644
--- a/app/(application)/coba/index.tsx
+++ b/app/(application)/coba/index.tsx
@@ -8,7 +8,9 @@ import {
ScrollView,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
-import { router } from "expo-router";
+import { router, Stack } from "expo-router";
+import EventDetailScreen from "./double-scroll";
+import LeftButtonCustom from "@/components/Button/BackButton";
const { width } = Dimensions.get("window");
@@ -16,7 +18,9 @@ const { width } = Dimensions.get("window");
const HomeScreen = () => (
Selamat Datang!
- Ini adalah halaman utama aplikasi Anda
+
+ Ini adalah halaman utama aplikasi Anda
+
);
const SearchScreen = () => (
@@ -65,9 +69,7 @@ const CustomTab = ({ icon, label, isActive, onPress }: any) => (
// Main Custom Tab Navigator
const CustomTabNavigator = () => {
- const [activeTab, setActiveTab] = React.useState(
- 'home'
- );
+ const [activeTab, setActiveTab] = React.useState("home");
const [showHome, setShowHome] = React.useState(true);
const tabs = [
@@ -97,13 +99,12 @@ const CustomTabNavigator = () => {
},
];
-
// 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") {
@@ -111,38 +112,46 @@ const CustomTabNavigator = () => {
}
// const selectedTab = tabs.find((tab) => tab.id === activeTab);
// return selectedTab ? selectedTab.component : HomeScreen;
- return HomeScreen
+ return HomeScreen;
};
const ActiveComponent = getActiveComponent();
return (
-
- {/* Content Area */}
-
-
-
-
-
+ <>
+
+
+ >
+ //
+ // {/* Content Area */}
+ //
+ //
+ //
+ //
+ //
- {/* Custom Tab Bar */}
-
-
- {tabs.map((e) => (
- {
- handleTabPress(e.id);
- router.push(e.path as any);
- }}
- />
- ))}
-
-
-
+ // {/* Custom Tab Bar */}
+ //
+ //
+ // {tabs.map((e) => (
+ // {
+ // handleTabPress(e.id);
+ // router.push(e.path as any);
+ // }}
+ // />
+ // ))}
+ //
+ //
+ //
);
};
diff --git a/assets/images/dummy/dummy-avatar.png b/assets/images/dummy/dummy-avatar.png
deleted file mode 100644
index 20e377a..0000000
Binary files a/assets/images/dummy/dummy-avatar.png and /dev/null differ
diff --git a/assets/images/dummy/dummy-user.png b/assets/images/dummy/dummy-user.png
new file mode 100644
index 0000000..7bfc6f9
Binary files /dev/null and b/assets/images/dummy/dummy-user.png differ
diff --git a/components/Alert/AlertDefaultSystem.ts b/components/Alert/AlertDefaultSystem.ts
new file mode 100644
index 0000000..f705f19
--- /dev/null
+++ b/components/Alert/AlertDefaultSystem.ts
@@ -0,0 +1,31 @@
+import { Alert } from "react-native";
+
+export default function AlertDefaultSystem({
+ title,
+ message,
+ textLeft,
+ textRight,
+ onPressLeft,
+ onPressRight,
+}: {
+ title: string;
+ message: string;
+ textLeft: string;
+ textRight: string;
+ onPressLeft?: () => void;
+ onPressRight?: () => void;
+}) {
+ return Alert.alert(title, message, [
+ {
+ style: "cancel",
+ text: textLeft,
+ onPress: () => onPressLeft?.(),
+ },
+ {
+ style: "default",
+ text: textRight,
+ isPreferred: true,
+ onPress: () => onPressRight?.(),
+ },
+ ]);
+}
diff --git a/components/Box/BaseBox.tsx b/components/Box/BaseBox.tsx
index a9cf39c..799ebdf 100644
--- a/components/Box/BaseBox.tsx
+++ b/components/Box/BaseBox.tsx
@@ -22,6 +22,7 @@ interface BaseBoxProps {
paddingBottom?: number;
paddingInline?: number;
paddingBlock?: number;
+ backgroundColor?: string;
}
export default function BaseBox({
@@ -34,6 +35,7 @@ export default function BaseBox({
paddingInline = PADDING_SMALL,
paddingTop = PADDING_MEDIUM,
paddingBottom = PADDING_MEDIUM,
+ backgroundColor = AccentColor.darkblue,
}: BaseBoxProps) {
return (
@@ -44,7 +46,7 @@ export default function BaseBox({
onPress={href ? () => router.navigate(href) : onPress}
style={[
{
- backgroundColor: AccentColor.darkblue,
+ backgroundColor,
borderColor: AccentColor.blue,
borderWidth: 1,
borderRadius: 10,
@@ -63,7 +65,7 @@ export default function BaseBox({
-
+
{children}
>
diff --git a/components/Checkbox/CheckboxCustom.tsx b/components/Checkbox/CheckboxCustom.tsx
new file mode 100644
index 0000000..1c9a2f4
--- /dev/null
+++ b/components/Checkbox/CheckboxCustom.tsx
@@ -0,0 +1,133 @@
+import { AccentColor } from "@/constants/color-palet";
+import { MaterialIcons } from "@expo/vector-icons"; // Bisa diganti dengan ikon lain
+import React, { useContext } from "react";
+import { Animated, Text, TouchableOpacity, View } from "react-native";
+import { checkboxStyles } from "./checkbox-styles";
+
+// Context untuk Group
+interface CheckboxGroupContextType {
+ value: (string | number)[];
+ onChange: (value: (string | number)[]) => void;
+ disabled?: boolean;
+}
+
+const CheckboxGroupContext =
+ React.createContext(null);
+
+// Tipe props
+// Tambahkan prop baru: groupValueKey
+interface CheckboxProps {
+ label?: string;
+ description?: string;
+ error?: string;
+ value?: boolean; // controlled value (untuk standalone)
+ onChange?: (checked: boolean) => void;
+ disabled?: boolean;
+ size?: number;
+ color?: string;
+ style?: object;
+ component?: React.ReactNode;
+ // Prop tambahan untuk Group
+ valueKey?: string | number; // nilai unik untuk identifikasi di group
+}
+
+const CheckboxCustom: React.FC = ({
+ label,
+ description,
+ error,
+ value: controlledValue,
+ onChange,
+ disabled: propDisabled,
+ size = 20,
+ color = AccentColor.softblue,
+ style,
+ component,
+ valueKey,
+}) => {
+ // const [uncontrolledChecked, setUncontrolledChecked] = useState(false);
+ // const isChecked = controlledValue ?? uncontrolledChecked;
+ // const scaleValue = new Animated.Value(isChecked ? 1 : 0);
+
+ const group = useContext(CheckboxGroupContext);
+ const isInsideGroup = !!group && valueKey !== undefined;
+
+ // Jika di dalam group, gunakan logika group
+ const isChecked = isInsideGroup
+ ? group.value.includes(valueKey!)
+ : controlledValue ?? false;
+
+ const disabled = propDisabled || (isInsideGroup && group.disabled);
+
+ const scaleValue = new Animated.Value(isChecked ? 1 : 0);
+
+ const toggle = () => {
+ if (disabled) return;
+
+ if (isInsideGroup) {
+ const newValue = isChecked
+ ? group.value.filter((v) => v !== valueKey)
+ : [...group.value, valueKey!];
+ group.onChange(newValue);
+ } else if (onChange) {
+ onChange(!controlledValue);
+ }
+ };
+
+ const styles = checkboxStyles({
+ size,
+ color,
+ disabled: disabled as boolean,
+ error: !!error,
+ });
+
+ return (
+
+
+
+ {isChecked && (
+
+
+
+ )}
+
+ {component}
+ {(label || description) && (
+
+ {label ? (
+
+ {label}
+
+ ) : null}
+ {description ? (
+
+ {description}
+
+ ) : null}
+ {error ? {error} : null}
+
+ )}
+
+
+ );
+};
+
+export default CheckboxCustom;
+
+// Export context agar bisa digunakan
+export { CheckboxGroupContext };
diff --git a/components/Checkbox/CheckboxGroup.tsx b/components/Checkbox/CheckboxGroup.tsx
new file mode 100644
index 0000000..3af0a64
--- /dev/null
+++ b/components/Checkbox/CheckboxGroup.tsx
@@ -0,0 +1,75 @@
+import React, { useState, useMemo } from "react";
+import { View, Text, StyleSheet } from "react-native";
+import { CheckboxGroupContext } from "./CheckboxCustom";
+
+interface CheckboxGroupProps {
+ value?: (string | number)[];
+ onChange?: (values: (string | number)[]) => void;
+ defaultValue?: (string | number)[];
+ label?: string;
+ description?: string;
+ error?: string;
+ disabled?: boolean;
+ children: React.ReactNode;
+ style?: object;
+}
+const CheckboxGroup: React.FC = ({
+ value: controlledValue,
+ onChange,
+ defaultValue = [],
+ label,
+ description,
+ error,
+ disabled = false,
+ children,
+ style,
+}) => {
+ const [uncontrolledValue, setUncontrolledValue] =
+ useState<(string | number)[]>(defaultValue);
+
+ const value = controlledValue ?? uncontrolledValue;
+ const handleChange = onChange ?? setUncontrolledValue;
+
+ const contextValue = useMemo(
+ () => ({ value, onChange: handleChange, disabled }),
+ [value, handleChange, disabled]
+ );
+
+ return (
+
+
+ {label ? {label} : null}
+ {description ? (
+ {description}
+ ) : null}
+ {children}
+ {error ? {error} : null}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ gap: 8,
+ },
+ label: {
+ fontSize: 16,
+ fontWeight: "600",
+ color: "#f8f9fa",
+ marginBottom: 4,
+ },
+ description: {
+ fontSize: 14,
+ color: "#ced4da",
+ marginBottom: 8,
+ },
+ errorText: {
+ color: "#e03131",
+ fontSize: 14,
+ marginTop: 4,
+ },
+});
+
+export default CheckboxGroup;
+
diff --git a/components/Checkbox/checkbox-styles.tsx b/components/Checkbox/checkbox-styles.tsx
new file mode 100644
index 0000000..7cc7afd
--- /dev/null
+++ b/components/Checkbox/checkbox-styles.tsx
@@ -0,0 +1,61 @@
+import { MainColor } from "@/constants/color-palet";
+import { StyleSheet } from "react-native";
+
+export const checkboxStyles = (props: {
+ size: number;
+ color: string;
+ disabled: boolean;
+ error: boolean;
+}) =>
+ StyleSheet.create({
+ container: {
+ flexDirection: "row",
+ alignItems: "flex-start",
+ // marginBottom: 12,
+ },
+ innerContainer: {
+ flexDirection: "row",
+ alignItems: "center",
+ },
+ box: {
+ width: props.size,
+ height: props.size,
+ borderRadius: 6,
+ borderWidth: 2,
+ borderColor: props.error
+ ? "#fff"
+ : props.disabled
+ ? "#ced4da"
+ : props.color,
+ justifyContent: "center",
+ alignItems: "center",
+ marginRight: 10,
+ },
+ checked: {
+ backgroundColor: props.color,
+ borderColor: props.color,
+ },
+ checkIcon: {
+ color: MainColor.white,
+ fontWeight: "bold",
+ fontSize: props.size * 0.6,
+ },
+ labelWrapper: {
+ flex: 1,
+ },
+ label: {
+ fontSize: props.size * 0.6,
+ color: props.disabled ? MainColor.disabled : MainColor.white,
+ fontWeight: "500",
+ },
+ description: {
+ fontSize: props.size * 0.5,
+ color: props.disabled ? MainColor.disabled : MainColor.white,
+ marginTop: 2,
+ },
+ errorText: {
+ color: MainColor.red,
+ fontSize: props.size * 0.5,
+ marginTop: 2,
+ },
+ });
diff --git a/components/Divider/Divider.tsx b/components/Divider/Divider.tsx
new file mode 100644
index 0000000..810ab6e
--- /dev/null
+++ b/components/Divider/Divider.tsx
@@ -0,0 +1,25 @@
+import { AccentColor } from "@/constants/color-palet";
+import { View } from "react-native";
+
+export default function Divider({
+ color = AccentColor.blue,
+ size = 1,
+ marginTop= 12,
+ marginBottom= 12,
+}: {
+ color?: string;
+ size?: number;
+ marginTop?: number;
+ marginBottom?: number;
+}) {
+ return (
+
+ );
+}
diff --git a/components/Drawer/DrawerCustom.tsx b/components/Drawer/DrawerCustom.tsx
index c871f84..b4617a0 100644
--- a/components/Drawer/DrawerCustom.tsx
+++ b/components/Drawer/DrawerCustom.tsx
@@ -9,20 +9,20 @@ import {
import { AccentColor, MainColor } from "@/constants/color-palet";
import { DRAWER_HEIGHT } from "@/constants/constans-value";
+import { SafeAreaView } from "react-native-safe-area-context";
interface DrawerCustomProps {
children?: React.ReactNode;
- height?: number;
+ height?: number | "auto";
isVisible: boolean;
drawerAnim?: Animated.Value;
closeDrawer: () => void;
// openLogoutAlert: () => void;
}
-
/**
- *
- * @param drawerAnim
+ *
+ * @param drawerAnim
* @example const drawerAnim = useRef(new Animated.Value(DRAWER_HEIGHT)).current; // mulai di luar bawah layar
*/
export default function DrawerCustom({
@@ -34,7 +34,9 @@ export default function DrawerCustom({
}: // openLogoutAlert,
DrawerCustomProps) {
const drawerAnima = useRef(
- new Animated.Value(height || DRAWER_HEIGHT)
+ new Animated.Value(
+ height === "auto" ? DRAWER_HEIGHT : height || DRAWER_HEIGHT
+ )
).current;
// Efek untuk handle open/close drawer
useEffect(() => {
@@ -46,7 +48,7 @@ DrawerCustomProps) {
}).start();
} else {
Animated.timing(drawerAnima, {
- toValue: height || DRAWER_HEIGHT,
+ toValue: height === "auto" ? DRAWER_HEIGHT : height || DRAWER_HEIGHT,
duration: 300,
useNativeDriver: true,
}).start();
@@ -99,7 +101,7 @@ DrawerCustomProps) {
style={[
styles.drawer,
{
- height: height || DRAWER_HEIGHT,
+ height: height === "auto" ? "auto" : height || DRAWER_HEIGHT,
transform: [{ translateY: drawerAnima }],
},
]}
@@ -110,34 +112,7 @@ DrawerCustomProps) {
/>
{children}
-
- {/* {
- alert("Pilihan 1 diklik");
- closeDrawer();
- }}
- >
- Menu Item 1
-
-
- {
- alert("Pilihan 2 diklik");
- closeDrawer();
- }}
- >
- Menu Item 2
-
-
-
- alert("Logout via Alert bawaan")}
- >
- Keluar
- */}
+ {height === "auto" && }
>
);
diff --git a/components/Drawer/MenuDrawerDynamicGird.tsx b/components/Drawer/MenuDrawerDynamicGird.tsx
index db54a10..eba1007 100644
--- a/components/Drawer/MenuDrawerDynamicGird.tsx
+++ b/components/Drawer/MenuDrawerDynamicGird.tsx
@@ -2,13 +2,26 @@ import { AccentColor, MainColor } from "@/constants/color-palet";
import { TEXT_SIZE_SMALL } from "@/constants/constans-value";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import { IMenuDrawerItem } from "../_Interface/types";
+import { Href } from "expo-router";
-const MenuDrawerDynamicGrid = ({ data, columns = 3, onPressItem }: any) => {
+type IMenuDrawerItemProps = {
+ icon: React.ReactNode;
+ label: string;
+ path?: Href;
+ color?: string;
+}
+
+interface MenuDrawerDynamicGridProps {
+ data: IMenuDrawerItemProps[];
+ columns?: number;
+ onPressItem?: (item: IMenuDrawerItemProps) => void;
+}
+const MenuDrawerDynamicGrid = ({ data, columns = 4, onPressItem }: MenuDrawerDynamicGridProps) => {
const numColumns = columns;
return (
- {data.map((item: IMenuDrawerItem, index: any) => (
+ {data.map((item: IMenuDrawerItemProps, index: any) => (
+
+ >
+ );
+}
diff --git a/components/_Icon/index.ts b/components/_Icon/index.ts
new file mode 100644
index 0000000..728531e
--- /dev/null
+++ b/components/_Icon/index.ts
@@ -0,0 +1,3 @@
+import IconEdit from "./IconEdit";
+
+export { IconEdit };
diff --git a/components/_ShareComponent/AvataraAndOtherHeaderComponent.tsx b/components/_ShareComponent/AvataraAndOtherHeaderComponent.tsx
index 9a3f317..42380ba 100644
--- a/components/_ShareComponent/AvataraAndOtherHeaderComponent.tsx
+++ b/components/_ShareComponent/AvataraAndOtherHeaderComponent.tsx
@@ -2,21 +2,23 @@ import { ImageSourcePropType, View } from "react-native";
import Grid from "../Grid/GridCustom";
import AvatarCustom from "../Image/AvatarCustom";
import TextCustom from "../Text/TextCustom";
+import Divider from "../Divider/Divider"
const AvatarUsernameAndOtherComponent = ({
avatarHref,
avatar,
name,
rightComponent,
+ withBottomLine = false,
}: {
avatarHref?: string;
avatar?: ImageSourcePropType;
name?: string;
rightComponent?: React.ReactNode;
+ withBottomLine?: boolean;
}) => {
return (
<>
-
@@ -38,6 +40,8 @@ const AvatarUsernameAndOtherComponent = ({
)}
+ {withBottomLine && }
+
>
);
diff --git a/components/_ShareComponent/TabBarBackground.tsx b/components/_ShareComponent/TabBarBackground.tsx
new file mode 100644
index 0000000..d71ee70
--- /dev/null
+++ b/components/_ShareComponent/TabBarBackground.tsx
@@ -0,0 +1,15 @@
+import { AccentColor, MainColor } from "@/constants/color-palet";
+import { View } from "react-native";
+
+export default function TabBarBackground() {
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/components/index.ts b/components/index.ts
index b064049..42c5a40 100644
--- a/components/index.ts
+++ b/components/index.ts
@@ -1,10 +1,15 @@
// Alert
import AlertCustom from "./Alert/AlertCustom";
+import AlertDefaultSystem from "./Alert/AlertDefaultSystem";
// Button
import LeftButtonCustom from "./Button/BackButton";
import ButtonCenteredOnly from "./Button/ButtonCenteredOnly";
import ButtonCustom from "./Button/ButtonCustom";
import DotButton from "./Button/DotButton";
+import FloatingButton from "./Button/FloatingButton";
+// Checkbox
+import CheckboxCustom from "./Checkbox/CheckboxCustom";
+import CheckboxGroup from "./Checkbox/CheckboxGroup";
// Drawer
import DrawerCustom from "./Drawer/DrawerCustom";
import MenuDrawerDynamicGrid from "./Drawer/MenuDrawerDynamicGird";
@@ -29,6 +34,7 @@ import SelectCustom from "./Select/SelectCustom";
import AvatarCustom from "./Image/AvatarCustom";
import LandscapeFrameUploaded from "./Image/LandscapeFrameUploaded";
// Divider
+import Divider from "./Divider/Divider";
import DividerCustom from "./Divider/DividerCustom";
// Map
import MapCustom from "./Map/MapCustom";
@@ -41,31 +47,45 @@ import ScrollableCustom from "./Scroll/ScrollCustom";
// ShareComponent
import AvatarUsernameAndOtherComponent from "./_ShareComponent/AvataraAndOtherHeaderComponent";
import Spacing from "./_ShareComponent/Spacing";
+import TabBarBackground from "./_ShareComponent/TabBarBackground";
import ViewWrapper from "./_ShareComponent/ViewWrapper";
+
export {
AlertCustom,
+ AlertDefaultSystem,
// Image
AvatarCustom,
// ShareComponent
- AvatarUsernameAndOtherComponent, LeftButtonCustom as BackButton,
+ AvatarUsernameAndOtherComponent,
+ // Button
+ LeftButtonCustom as BackButton,
// Box
BaseBox,
- BoxButtonOnFooter, BoxWithHeaderSection,
- // Button
+ BoxButtonOnFooter,
+ BoxWithHeaderSection,
ButtonCenteredOnly,
ButtonCustom,
+ DotButton,
// Center
CenterCustom,
+ // Checkbox
+ CheckboxCustom,
+ CheckboxGroup,
// Clickable
ClickableCustom,
// Divider
- DividerCustom, DotButton,
+ Divider,
+ DividerCustom,
// Drawer
DrawerCustom,
+ FloatingButton,
// Grid
- Grid, InformationBox, LandscapeFrameUploaded,
+ Grid,
+ InformationBox,
+ LandscapeFrameUploaded,
// Map
- MapCustom, MenuDrawerDynamicGrid,
+ MapCustom,
+ MenuDrawerDynamicGrid,
// Scroll
ScrollableCustom,
// Select
@@ -74,6 +94,7 @@ export {
Spacing,
// Stack
StackCustom,
+ TabBarBackground,
// TextArea
TextAreaCustom,
// Text
@@ -81,6 +102,5 @@ export {
// TextInput
TextInputCustom,
// ViewWrapper
- ViewWrapper
+ ViewWrapper,
};
-
diff --git a/constants/dummy-image-value.ts b/constants/dummy-image-value.ts
index 530df88..4a76281 100644
--- a/constants/dummy-image-value.ts
+++ b/constants/dummy-image-value.ts
@@ -1,5 +1,5 @@
const DUMMY_IMAGE = {
- avatar: require("@/assets/images/dummy/dummy-avatar.png"),
+ avatar: require("@/assets/images/dummy/dummy-user.png"),
background: require("@/assets/images/dummy/dummy-image-background.jpg"),
};
diff --git a/screens/Authentication/LoginView.tsx b/screens/Authentication/LoginView.tsx
index aac55c3..641006d 100644
--- a/screens/Authentication/LoginView.tsx
+++ b/screens/Authentication/LoginView.tsx
@@ -37,6 +37,7 @@ export default function LoginView() {
// router.navigate(`/(application)/(user)/portofolio/${id}`)
// router.navigate(`/(application)/(image)/preview-image/${id}`);
// router.replace("/(application)/(user)/event/(tabs)");
+ // router.replace("/(application)/coba");
}
return (
diff --git a/screens/Collaboration/BoxDetailSection.tsx b/screens/Collaboration/BoxDetailSection.tsx
new file mode 100644
index 0000000..7840f11
--- /dev/null
+++ b/screens/Collaboration/BoxDetailSection.tsx
@@ -0,0 +1,54 @@
+import {
+ AvatarUsernameAndOtherComponent,
+ BoxWithHeaderSection,
+ Grid,
+ StackCustom,
+ TextCustom
+} from "@/components";
+
+export default function Collaboration_BoxDetailSection({ id }: { id: string }) {
+ return (
+ <>
+
+
+
+
+ Judul Proyek {id}
+
+
+ {listData.map((item, index) => (
+
+
+ {item.title}
+
+
+ {item.value}
+
+
+ ))}
+
+
+ >
+ );
+}
+
+const listData = [
+ {
+ title: "Industri",
+ value: "Pilihan Industri",
+ },
+ {
+ title: "Deskripsi",
+ value: "Deskripsi Proyek",
+ },
+ {
+ title: "Tujuan Proyek",
+ value:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+ },
+ {
+ title: "Keuntungan Proyek",
+ value:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+ },
+];
diff --git a/screens/Collaboration/BoxPublishSection.tsx b/screens/Collaboration/BoxPublishSection.tsx
new file mode 100644
index 0000000..7694b18
--- /dev/null
+++ b/screens/Collaboration/BoxPublishSection.tsx
@@ -0,0 +1,60 @@
+import {
+ AvatarUsernameAndOtherComponent,
+ BoxWithHeaderSection,
+ StackCustom,
+ TextCustom
+} from "@/components";
+import { Href } from "expo-router";
+
+function Collaboration_BoxPublishSection({
+ id,
+ title,
+ username,
+ description,
+ href,
+
+ // Avatar
+ sourceAvatar,
+ rightComponentAvatar,
+}: {
+ id: string;
+ title?: string;
+ username?: string;
+ description?: string;
+ href: Href;
+
+ // Avatar
+ sourceAvatar?: string;
+ rightComponentAvatar?: React.ReactNode;
+}) {
+ return (
+ <>
+
+
+
+
+
+
+ {title || "Lorem ipsum dolor sit"}
+
+
+ {description ||
+ "Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro sed doloremque tempora soluta. Dolorem ex quidem ipsum tempora, ipsa, obcaecati quia suscipit numquam, voluptates commodi porro impedit natus quos doloremque!"}
+
+ {/*
+ 2 Partisipan
+ */}
+
+
+
+ >
+ );
+}
+
+export default Collaboration_BoxPublishSection;
diff --git a/screens/Collaboration/ProjectMainSelectedSection.tsx b/screens/Collaboration/ProjectMainSelectedSection.tsx
new file mode 100644
index 0000000..3dba588
--- /dev/null
+++ b/screens/Collaboration/ProjectMainSelectedSection.tsx
@@ -0,0 +1,69 @@
+import {
+ AvatarCustom,
+ BaseBox,
+ CheckboxCustom,
+ CheckboxGroup,
+ Grid,
+ StackCustom,
+ TextCustom
+} from "@/components";
+import { ICON_SIZE_SMALL } from "@/constants/constans-value";
+import { MaterialIcons } from "@expo/vector-icons";
+import { View } from "react-native";
+
+export default function Collaboration_ProjectMainSelectedSection({
+ selected,
+ setSelected,
+ setOpenDrawerParticipant,
+}: {
+ selected: (string | number)[];
+ setSelected: (value: (string | number)[]) => void;
+ setOpenDrawerParticipant: (value: boolean) => void;
+}) {
+ return (
+
+
+
+ *{" "}
+
+ Pilih user yang akan menjadi tim proyek anda
+
+
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+
+
+
+
+
+
+
+ Username
+
+
+
+ setOpenDrawerParticipant(true)}
+ />
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/screens/Event/BoxPublishSection.tsx b/screens/Event/BoxPublishSection.tsx
index 288dd5d..7440e41 100644
--- a/screens/Event/BoxPublishSection.tsx
+++ b/screens/Event/BoxPublishSection.tsx
@@ -4,12 +4,14 @@ import {
StackCustom,
TextCustom,
} from "@/components";
+import { Href } from "expo-router";
export default function Event_BoxPublishSection({
id,
title,
username,
description,
+ href,
// Avatar
sourceAvatar,
@@ -19,6 +21,7 @@ export default function Event_BoxPublishSection({
title?: string;
username?: string;
description?: string;
+ href: Href;
// Avatar
sourceAvatar?: string;
@@ -26,7 +29,7 @@ export default function Event_BoxPublishSection({
}) {
return (
<>
-
+
Event
-
+ router.push("/(application)/(user)/collaboration/(tabs)")}
+ >
Collaboration
diff --git a/screens/Profile/profilSection.tsx b/screens/Profile/ProfileSection.tsx
similarity index 98%
rename from screens/Profile/profilSection.tsx
rename to screens/Profile/ProfileSection.tsx
index 131ce03..945f5c1 100644
--- a/screens/Profile/profilSection.tsx
+++ b/screens/Profile/ProfileSection.tsx
@@ -6,7 +6,7 @@ import { router, useLocalSearchParams } from "expo-router";
import { View } from "react-native";
import AvatarAndBackground from "./AvatarAndBackground";
-export default function ProfilSection() {
+export default function ProfileSection() {
const { id } = useLocalSearchParams();
const listData = [
diff --git a/styles/tabs-styles.ts b/styles/tabs-styles.ts
new file mode 100644
index 0000000..70fe42b
--- /dev/null
+++ b/styles/tabs-styles.ts
@@ -0,0 +1,25 @@
+import { TabBarBackground } from "@/components";
+import { MainColor } from "@/constants/color-palet";
+import { OS_IOS_HEIGHT, OS_ANDROID_HEIGHT } from "@/constants/constans-value";
+import { BottomTabNavigationOptions } from "@react-navigation/bottom-tabs";
+import { Platform } from "react-native";
+
+export const TabsStyles: BottomTabNavigationOptions = {
+ headerShown: false,
+ tabBarActiveTintColor: MainColor.yellow,
+ tabBarInactiveTintColor: MainColor.white_gray,
+ tabBarStyle: Platform.select({
+ ios: {
+ borderTopWidth: 0,
+ paddingTop: 5,
+ height: OS_IOS_HEIGHT,
+ },
+ android: {
+ borderTopWidth: 0,
+ paddingTop: 5,
+ height: OS_ANDROID_HEIGHT,
+ },
+ default: {},
+ }),
+ tabBarBackground: TabBarBackground,
+};