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, +};