Compare commits
86 Commits
resourcing
...
invesment/
| Author | SHA1 | Date | |
|---|---|---|---|
| a43ddaa9d6 | |||
| 927db87749 | |||
| 8a514d2670 | |||
| 554428b7b4 | |||
| befbd1a47d | |||
| c9a1ac1db5 | |||
| 4bcfcb5f5a | |||
| f21ff744d3 | |||
| b18044f53f | |||
| 20258d1fe5 | |||
| 51d696128e | |||
| 1b1732c7d8 | |||
| 7528c449eb | |||
| ed87d4a3f3 | |||
| 603003865b | |||
| e02ae8e35d | |||
| 4f8ae2d7e0 | |||
| 360ac5807c | |||
| 8cb0054580 | |||
| 64d5a4308c | |||
| 30d61c84aa | |||
| 70e324e76e | |||
| 4474b46ff3 | |||
| aa4ea9fb0c | |||
| 81d86885f4 | |||
| 814f261881 | |||
| 7889d25a44 | |||
| ce0e82e627 | |||
| 08dfd62bfd | |||
| c8cc0f0232 | |||
| b844a8151d | |||
| f9e96aa077 | |||
| b8b1efc71e | |||
| eaf0ebfb0a | |||
| e68d366d49 | |||
| 9999f78ed4 | |||
| 2be5afe5ca | |||
| 24913a9f97 | |||
| 3376336c55 | |||
| a0dad5618a | |||
| cce27c26f6 | |||
| 3211404397 | |||
| fbde2fd031 | |||
| ac9dae7c5b | |||
| 5183769a7c | |||
| 3301cf3d7a | |||
| 6913e9e4b5 | |||
| c5798b3127 | |||
| 2c94638e27 | |||
| b8ed577fea | |||
| e68a18bb89 | |||
| 862af44c03 | |||
| 71ea0ca5f2 | |||
| ee7efaef6a | |||
| bfb029058c | |||
| b7e774a556 | |||
| 2901d19db0 | |||
| 5c4dadbe7c | |||
| 6ac122c631 | |||
| 16559b94fe | |||
| 0698e14d36 | |||
| 3d9672154c | |||
| 55b4b1fa8d | |||
| b80968999e | |||
| 6bac89c536 | |||
| b9af7e0ca7 | |||
| 8abf23fd13 | |||
| 1a16b16f47 | |||
| 0b1fd05eec | |||
| b54693caa7 | |||
| 17e6208aae | |||
| f5cf9e1549 | |||
| 7b58e3315f | |||
| 101c9053d8 | |||
| 4a92385d6d | |||
| 7e39133c2f | |||
| e2744f0344 | |||
| 9667065bb3 | |||
| 23ae416f42 | |||
| 8fb37db0db | |||
| 258e20751e | |||
| 564ea68d29 | |||
| 4701fce07c | |||
| d58304a146 | |||
| 5577ef5d1e | |||
| c1bee77629 |
13
app.json
13
app.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "hipmi-mobile",
|
"name": "HIPMI BADUNG",
|
||||||
"slug": "hipmi-mobile",
|
"slug": "hipmi-mobile",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
@@ -38,7 +38,16 @@
|
|||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
[
|
||||||
|
"expo-camera",
|
||||||
|
{
|
||||||
|
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
|
||||||
|
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",
|
||||||
|
"recordAudioAndroid": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expo-font"
|
||||||
],
|
],
|
||||||
"experiments": {
|
"experiments": {
|
||||||
"typedRoutes": true
|
"typedRoutes": true
|
||||||
|
|||||||
9
app/(application)/(image)/preview-image/[id]/index.tsx
Normal file
9
app/(application)/(image)/preview-image/[id]/index.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { LandscapeFrameUploaded, ViewWrapper } from "@/components";
|
||||||
|
|
||||||
|
export default function PreviewImage() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
171
app/(application)/(image)/take-picture/[id]/index.tsx
Normal file
171
app/(application)/(image)/take-picture/[id]/index.tsx
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import AntDesign from "@expo/vector-icons/AntDesign";
|
||||||
|
import FontAwesome6 from "@expo/vector-icons/FontAwesome6";
|
||||||
|
import { CameraType, CameraView, useCameraPermissions } from "expo-camera";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import * as ImagePicker from "expo-image-picker";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { Pressable, StyleSheet, Text, View } from "react-native";
|
||||||
|
|
||||||
|
export default function TakePicture() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
// console.log("Take Picture ID >>", id);
|
||||||
|
|
||||||
|
const [permission, requestPermission] = useCameraPermissions();
|
||||||
|
const ref = useRef<CameraView>(null);
|
||||||
|
const [uri, setUri] = useState<string | null>(null);
|
||||||
|
const [facing, setFacing] = useState<CameraType>("back");
|
||||||
|
|
||||||
|
if (!permission?.granted) {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={{ textAlign: "center" }}>
|
||||||
|
We need your permission to use the camera
|
||||||
|
</Text>
|
||||||
|
<Pressable onPress={requestPermission}>
|
||||||
|
<Text style={{ color: "blue", marginTop: 10 }}>Grant permission</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const takePicture = async () => {
|
||||||
|
const photo = await ref.current?.takePictureAsync();
|
||||||
|
setUri(photo?.uri || null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const pickImage = async () => {
|
||||||
|
const result = await ImagePicker.launchImageLibraryAsync({
|
||||||
|
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
||||||
|
allowsEditing: true,
|
||||||
|
aspect: [1, 1],
|
||||||
|
quality: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.canceled) {
|
||||||
|
setUri(result.assets[0].uri);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleFacing = () => {
|
||||||
|
setFacing((prev) => (prev === "back" ? "front" : "back"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPicture = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Image
|
||||||
|
source={uri ? uri : null}
|
||||||
|
contentFit="contain"
|
||||||
|
style={{ width: 340, aspectRatio: 1 }}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<StackCustom >
|
||||||
|
<ButtonCustom onPress={() => setUri(null)} title="Foto ulang" />
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Upload picture >>", id);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
title="Upload Foto"
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderCameraUI = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.cameraOverlay}>
|
||||||
|
<View style={styles.shutterContainer}>
|
||||||
|
<Pressable onPress={toggleFacing}>
|
||||||
|
<FontAwesome6 name="rotate-left" size={32} color="white" />
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Pressable onPress={takePicture}>
|
||||||
|
{({ pressed }) => (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.shutterBtn,
|
||||||
|
{
|
||||||
|
opacity: pressed ? 0.5 : 1,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View style={styles.shutterBtnInner} />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Pressable onPress={pickImage}>
|
||||||
|
<AntDesign name="folderopen" size={32} color="white" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{uri ? (
|
||||||
|
<ViewWrapper>
|
||||||
|
<View style={styles.container}>{renderPicture()}</View>
|
||||||
|
</ViewWrapper>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<CameraView
|
||||||
|
style={styles.camera}
|
||||||
|
ref={ref}
|
||||||
|
facing={facing}
|
||||||
|
responsiveOrientationWhenOrientationLocked
|
||||||
|
/>
|
||||||
|
{renderCameraUI()}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
flex: 1,
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
cameraOverlay: {
|
||||||
|
...StyleSheet.absoluteFillObject,
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
padding: 44,
|
||||||
|
},
|
||||||
|
shutterContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
shutterBtn: {
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
borderWidth: 5,
|
||||||
|
borderColor: "white",
|
||||||
|
width: 85,
|
||||||
|
height: 85,
|
||||||
|
borderRadius: 45,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
shutterBtnInner: {
|
||||||
|
width: 70,
|
||||||
|
height: 70,
|
||||||
|
borderRadius: 50,
|
||||||
|
backgroundColor: "white",
|
||||||
|
},
|
||||||
|
});
|
||||||
355
app/(application)/(user)/_layout.tsx
Normal file
355
app/(application)/(user)/_layout.tsx
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
import { BackButton } from "@/components";
|
||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { HeaderStyles } from "@/styles/header-styles";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack } from "expo-router";
|
||||||
|
|
||||||
|
export default function UserLayout() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack screenOptions={HeaderStyles}>
|
||||||
|
<Stack.Screen
|
||||||
|
name="home"
|
||||||
|
options={{
|
||||||
|
title: "HIPMI",
|
||||||
|
headerLeft: () => (
|
||||||
|
<Ionicons
|
||||||
|
name="search"
|
||||||
|
size={20}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => router.push("/user-search")}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
headerRight: () => (
|
||||||
|
<Ionicons
|
||||||
|
name="notifications"
|
||||||
|
size={20}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => router.push("/notifications")}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== Profile Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="profile"
|
||||||
|
options={{
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== Portofolio Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="portofolio"
|
||||||
|
options={{
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== User Search Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="user-search/index"
|
||||||
|
options={{
|
||||||
|
title: "Pencarian Pengguna",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== Notification Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="notifications/index"
|
||||||
|
options={{
|
||||||
|
title: "Notifikasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== Event Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="event/(tabs)"
|
||||||
|
options={{
|
||||||
|
title: "Event",
|
||||||
|
headerLeft: () => (
|
||||||
|
<LeftButtonCustom path="/(application)/(user)/home" />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="event/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Event",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="event/detail/[id]"
|
||||||
|
options={{
|
||||||
|
title: "Event Detail",
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="event/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Event",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="event/[id]/list-of-participants"
|
||||||
|
options={{
|
||||||
|
title: "Daftar peserta",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* ========== End Event Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Collaboration Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="collaboration/(tabs)"
|
||||||
|
options={{
|
||||||
|
title: "Collaboration",
|
||||||
|
headerLeft: () => <BackButton path="/home" />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="collaboration/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Proyek",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="collaboration/[id]/list-of-participants"
|
||||||
|
options={{
|
||||||
|
title: "Daftar Partisipan",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="collaboration/[id]/detail-participant"
|
||||||
|
options={{
|
||||||
|
title: "Partisipasi Proyek",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="collaboration/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Proyek",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== End Collaboration Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Voting Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="voting/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Voting",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="voting/(tabs)"
|
||||||
|
options={{
|
||||||
|
title: "Voting",
|
||||||
|
headerLeft: () => <BackButton path="/home" />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="voting/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Voting",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="voting/[id]/list-of-contributor"
|
||||||
|
options={{
|
||||||
|
title: "Daftar Kontributor",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== End Voting Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Crowdfunding Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="crowdfunding/index"
|
||||||
|
options={{
|
||||||
|
title: "Crowdfunding",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== End Crowdfunding Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Investment Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/(tabs)"
|
||||||
|
options={{
|
||||||
|
title: "Investasi",
|
||||||
|
headerLeft: () => <BackButton path="/crowdfunding" />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Investasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== End Investment Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Donation Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="donation/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Donasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== End Donation Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Job Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="job/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Job",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="job/(tabs)"
|
||||||
|
options={{
|
||||||
|
title: "Job Vacancy",
|
||||||
|
headerLeft: () => <BackButton path="/home" />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="job/[id]/index"
|
||||||
|
options={{
|
||||||
|
title: "Detail Job",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="job/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Job",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== End Job Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Forum Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Diskusi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Diskusi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/forumku"
|
||||||
|
options={{
|
||||||
|
title: "Forumku",
|
||||||
|
headerLeft: () => <BackButton icon={"close"} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/index"
|
||||||
|
options={{
|
||||||
|
title: "Detail",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/report-commentar"
|
||||||
|
options={{
|
||||||
|
title: "Laporkan Komentar",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/other-report-commentar"
|
||||||
|
options={{
|
||||||
|
title: "Laporkan Komentar",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/report-posting"
|
||||||
|
options={{
|
||||||
|
title: "Laporkan Diskusi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/other-report-posting"
|
||||||
|
options={{
|
||||||
|
title: "Laporkan Diskusi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== Maps Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="maps/index"
|
||||||
|
options={{
|
||||||
|
title: "Maps",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="maps/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Maps",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="maps/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Maps",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="maps/[id]/custom-pin"
|
||||||
|
options={{
|
||||||
|
title: "Custom Pin Maps",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ========== Marketplace Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="marketplace/index"
|
||||||
|
options={{
|
||||||
|
title: "Market Place",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
36
app/(application)/(user)/collaboration/(tabs)/_layout.tsx
Normal file
36
app/(application)/(user)/collaboration/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { IconHome } from "@/components/_Icon";
|
||||||
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { Tabs } from "expo-router";
|
||||||
|
|
||||||
|
export default function CollaborationTabsLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs screenOptions={TabsStyles}>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: "Beranda",
|
||||||
|
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="participant"
|
||||||
|
options={{
|
||||||
|
title: "Partisipan",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Ionicons size={20} name="people" color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="group"
|
||||||
|
options={{
|
||||||
|
title: "Grup",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Ionicons size={20} name="chatbox-ellipses" color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
68
app/(application)/(user)/collaboration/(tabs)/group.tsx
Normal file
68
app/(application)/(user)/collaboration/(tabs)/group.tsx
Normal file
@@ -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 (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingBlock={5}
|
||||||
|
href={`/collaboration/${index}/${generateProjectName()}/room-chat`}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<TextCustom bold>{generateProjectName()}</TextCustom>
|
||||||
|
<TextCustom size="small">2 Anggota</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<Feather name="chevron-right" size={20} color={MainColor.white} />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
28
app/(application)/(user)/collaboration/(tabs)/index.tsx
Normal file
28
app/(application)/(user)/collaboration/(tabs)/index.tsx
Normal file
@@ -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 (
|
||||||
|
<>
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton
|
||||||
|
onPress={() => {
|
||||||
|
router.push("/collaboration/create");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Collaboration_BoxPublishSection
|
||||||
|
key={index}
|
||||||
|
id={index.toString()}
|
||||||
|
href={`/collaboration/${index}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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<string | null>(
|
||||||
|
"participant"
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerComponent = (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: 5,
|
||||||
|
backgroundColor: MainColor.soft_darkblue,
|
||||||
|
borderRadius: 50,
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={
|
||||||
|
activeCategory === "participant" ? MainColor.yellow : AccentColor.blue
|
||||||
|
}
|
||||||
|
textColor={
|
||||||
|
activeCategory === "participant" ? MainColor.black : MainColor.white
|
||||||
|
}
|
||||||
|
style={{ width: "49%" }}
|
||||||
|
onPress={() => handlePress("participant")}
|
||||||
|
>
|
||||||
|
Partisipasi Proyek
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing width={"2%"} />
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={
|
||||||
|
activeCategory === "main" ? MainColor.yellow : AccentColor.blue
|
||||||
|
}
|
||||||
|
textColor={
|
||||||
|
activeCategory === "main" ? MainColor.black : MainColor.white
|
||||||
|
}
|
||||||
|
style={{ width: "49%" }}
|
||||||
|
onPress={() => handlePress("main")}
|
||||||
|
>
|
||||||
|
Proyek Saya
|
||||||
|
</ButtonCustom>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter headerComponent={headerComponent}>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Collaboration_BoxPublishSection
|
||||||
|
key={index.toString()}
|
||||||
|
id={index.toString()}
|
||||||
|
username={` ${
|
||||||
|
activeCategory === "participant"
|
||||||
|
? "Partisipasi Proyek"
|
||||||
|
: "Proyek Saya"
|
||||||
|
}`}
|
||||||
|
href={
|
||||||
|
activeCategory === "participant"
|
||||||
|
? `/collaboration/${index}/detail-participant`
|
||||||
|
: `/collaboration/${index}/detail-project-main`
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Info`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
<StackCustom>
|
||||||
|
{listData.map((item, index) => (
|
||||||
|
<Grid key={index}>
|
||||||
|
<Grid.Col span={4}>
|
||||||
|
<TextCustom bold>{item.title}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<TextCustom>{item.value}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<AvatarUsernameAndOtherComponent key={index} avatarHref={`/profile/${index}`} />
|
||||||
|
))}
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.",
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -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 (
|
||||||
|
<>
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
{/* <View style={{flexDirection: 'row', alignItems: 'center'}}>
|
||||||
|
<TextInputCustom placeholder="Ketik pesan..." />
|
||||||
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.5}
|
||||||
|
onPress={() => console.log("Send")}
|
||||||
|
style={{
|
||||||
|
backgroundColor: AccentColor.blue,
|
||||||
|
padding: 10,
|
||||||
|
borderRadius: 50,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Feather name="send" size={30} color={MainColor.white} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View> */}
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={9}>
|
||||||
|
<TextInputCustom placeholder="Ketik pesan..." />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={2} style={{ alignItems: "center" }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.5}
|
||||||
|
onPress={() => console.log("Send")}
|
||||||
|
style={{
|
||||||
|
backgroundColor: AccentColor.blue,
|
||||||
|
padding: 10,
|
||||||
|
borderRadius: 50,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Feather
|
||||||
|
name="send"
|
||||||
|
size={30}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Proyek ${detail}`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<Feather
|
||||||
|
name="info"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => router.push(`/collaboration/${id}/${detail}/info`)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper footerComponent={inputChat()}>
|
||||||
|
{dummyData.map((item, index) => (
|
||||||
|
<View
|
||||||
|
key={index}
|
||||||
|
style={[
|
||||||
|
styles.messageRow,
|
||||||
|
item.role === 1 ? styles.rightAlign : styles.leftAlign,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.bubble,
|
||||||
|
item.role === 1 ? styles.bubbleRight : styles.bubbleLeft,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<TextCustom style={styles.sender}>{item.nama}</TextCustom>
|
||||||
|
<TextCustom style={styles.message}>{item.chat}</TextCustom>
|
||||||
|
<TextCustom style={styles.time}>
|
||||||
|
{new Date(item.time).toLocaleTimeString([], {
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
})}
|
||||||
|
</TextCustom>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
{/* <TextInputCustom placeholder="Ketik pesan..." />
|
||||||
|
<Spacing/> */}
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -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 (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Collaboration_BoxDetailSection id={id as string} />
|
||||||
|
<BaseBox style={{ height: 500 }}>
|
||||||
|
<TextCustom align="center" bold size="large">
|
||||||
|
Partisipan
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
{Array.from({ length: 5 }).map((_, index) => (
|
||||||
|
<AvatarUsernameAndOtherComponent
|
||||||
|
key={index}
|
||||||
|
avatarHref={`/profile/${index}`}
|
||||||
|
rightComponent={
|
||||||
|
<MaterialIcons
|
||||||
|
name="notes"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
onPress={() => setOpenDrawerParticipant(true)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</BaseBox>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerParticipant}
|
||||||
|
closeDrawer={() => setOpenDrawerParticipant(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold>Deskripsi Diri</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
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.
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Proyek Saya",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Collaboration_BoxDetailSection id={id as string} />
|
||||||
|
<Collaboration_MainParticipanSelectedSection
|
||||||
|
selected={selected}
|
||||||
|
setSelected={setSelected}
|
||||||
|
setOpenDrawerParticipant={setOpenDrawerParticipant}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
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
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: "Edit",
|
||||||
|
path: "/(application)/(user)/collaboration/(tabs)/group",
|
||||||
|
icon: <IconEdit />,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
handleEdit();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerParticipant}
|
||||||
|
closeDrawer={() => setOpenDrawerParticipant(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold>Deskripsi Diri</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
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.
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
53
app/(application)/(user)/collaboration/[id]/edit.tsx
Normal file
53
app/(application)/(user)/collaboration/[id]/edit.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
SelectCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function CollaborationEdit() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom label="Judul" placeholder="Masukan judul" required />
|
||||||
|
<TextInputCustom label="Lokasi" placeholder="Masukan lokasi" required />
|
||||||
|
<SelectCustom
|
||||||
|
label="Pilih Industri"
|
||||||
|
data={[
|
||||||
|
{ label: "Industri 1", value: "industri-1" },
|
||||||
|
{ label: "Industri 2", value: "industri-2" },
|
||||||
|
{ label: "Industri 3", value: "industri-3" },
|
||||||
|
]}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
required
|
||||||
|
label="Tujuan Proyek"
|
||||||
|
placeholder="Masukan tujuan proyek"
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
required
|
||||||
|
label="Keuntungan Proyek"
|
||||||
|
placeholder="Masukan keuntungan proyek"
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
title="Update"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Update proyek");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
91
app/(application)/(user)/collaboration/[id]/index.tsx
Normal file
91
app/(application)/(user)/collaboration/[id]/index.tsx
Normal file
@@ -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 (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Detail Proyek",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<DotButton onPress={() => setOpenDrawerMenu(true)} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Collaboration_BoxDetailSection id={id as string} />
|
||||||
|
|
||||||
|
<ButtonCustom onPress={() => setOpenDrawerPartisipasi(true)}>
|
||||||
|
Partisipasi
|
||||||
|
</ButtonCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* Drawer Partisipasi */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPartisipasi}
|
||||||
|
closeDrawer={() => setOpenDrawerPartisipasi(false)}
|
||||||
|
height={300}
|
||||||
|
>
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Dekripsi diri"
|
||||||
|
placeholder="Masukan dekripsi diri"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={500}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
style={{ alignSelf: "flex-end" }}
|
||||||
|
onPress={() => {
|
||||||
|
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
|
||||||
|
</ButtonCustom>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Drawer Menu */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerMenu}
|
||||||
|
closeDrawer={() => setOpenDrawerMenu(false)}
|
||||||
|
height={250}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <Ionicons name="people" size={24} color="white" />,
|
||||||
|
label: "Daftar Partisipan",
|
||||||
|
path: `/collaboration/${id}/list-of-participants`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
router.push(item.path as any);
|
||||||
|
setOpenDrawerMenu(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox key={index} paddingBlock={5}>
|
||||||
|
<AvatarUsernameAndOtherComponent
|
||||||
|
avatarHref={`/profile/${id}`}
|
||||||
|
rightComponent={
|
||||||
|
<Feather
|
||||||
|
name="chevron-right"
|
||||||
|
size={24}
|
||||||
|
color="white"
|
||||||
|
onPress={() => setOpenDrawer(true)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* Drawer */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold>Deskripsi diri</TextCustom>
|
||||||
|
<BaseBox>
|
||||||
|
<ScrollView style={{ height: "80%" }}>
|
||||||
|
<TextCustom>
|
||||||
|
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.
|
||||||
|
</TextCustom>
|
||||||
|
</ScrollView>
|
||||||
|
</BaseBox>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
53
app/(application)/(user)/collaboration/create.tsx
Normal file
53
app/(application)/(user)/collaboration/create.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
SelectCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function CollaborationCreate() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom label="Judul" placeholder="Masukan judul" required />
|
||||||
|
<TextInputCustom label="Lokasi" placeholder="Masukan lokasi" required />
|
||||||
|
<SelectCustom
|
||||||
|
label="Pilih Industri"
|
||||||
|
data={[
|
||||||
|
{ label: "Industri 1", value: "industri-1" },
|
||||||
|
{ label: "Industri 2", value: "industri-2" },
|
||||||
|
{ label: "Industri 3", value: "industri-3" },
|
||||||
|
]}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
required
|
||||||
|
label="Tujuan Proyek"
|
||||||
|
placeholder="Masukan tujuan proyek"
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
required
|
||||||
|
label="Keuntungan Proyek"
|
||||||
|
placeholder="Masukan keuntungan proyek"
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
title="Simpan"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Simpan proyek");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
68
app/(application)/(user)/crowdfunding/index.tsx
Normal file
68
app/(application)/(user)/crowdfunding/index.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { Feather } from "@expo/vector-icons";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
|
||||||
|
export default function Crowdfunding() {
|
||||||
|
const listPage = [
|
||||||
|
{
|
||||||
|
title: "Investasi",
|
||||||
|
desc: "Buat investasi dan jual beli saham lebih mudah dengan pengguna lain.",
|
||||||
|
path: "investment/(tabs)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Donasi",
|
||||||
|
desc: "Berbagi info untuk berdonasi lebih luas dan lebih efisien.",
|
||||||
|
path: "donation/create",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<Image
|
||||||
|
source={require("@/assets/images/constants/crowd-hipmi.png")}
|
||||||
|
contentFit="cover"
|
||||||
|
transition={1000}
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: 200,
|
||||||
|
borderRadius: 10,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{listPage.map((item, index) => (
|
||||||
|
<BaseBox key={index} paddingTop={10} paddingBottom={10} href={item.path as any} marginBottom={0}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom bold size="large">
|
||||||
|
{item.title}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>{item.desc}</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<Feather
|
||||||
|
name="chevron-right"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
11
app/(application)/(user)/donation/create.tsx
Normal file
11
app/(application)/(user)/donation/create.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { TextCustom, ViewWrapper } from "@/components";
|
||||||
|
|
||||||
|
export default function DonationCreate() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<TextCustom bold size="large">
|
||||||
|
Coming Soon !
|
||||||
|
</TextCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
43
app/(application)/(user)/event/(tabs)/_layout.tsx
Normal file
43
app/(application)/(user)/event/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
IconContribution,
|
||||||
|
IconHistory,
|
||||||
|
IconHome,
|
||||||
|
IconStatus,
|
||||||
|
} from "@/components/_Icon";
|
||||||
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
|
import { Tabs } from "expo-router";
|
||||||
|
|
||||||
|
export default function EventTabsLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs screenOptions={TabsStyles}>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: "Beranda",
|
||||||
|
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="status"
|
||||||
|
options={{
|
||||||
|
title: "Status",
|
||||||
|
tabBarIcon: ({ color }) => <IconStatus color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="contribution"
|
||||||
|
options={{
|
||||||
|
title: "Kontribusi",
|
||||||
|
tabBarIcon: ({ color }) => <IconContribution color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="history"
|
||||||
|
options={{
|
||||||
|
title: "Riwayat",
|
||||||
|
tabBarIcon: ({ color }) => <IconHistory color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
43
app/(application)/(user)/event/(tabs)/contribution.tsx
Normal file
43
app/(application)/(user)/event/(tabs)/contribution.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
AvatarCustom,
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function EventContribution() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BoxWithHeaderSection key={index} href={`/event/${index}/contribution`}>
|
||||||
|
<StackCustom>
|
||||||
|
<AvatarUsernameAndOtherComponent
|
||||||
|
avatarHref={`/profile/${index}`}
|
||||||
|
rightComponent={
|
||||||
|
<TextCustom truncate>
|
||||||
|
{new Date().toLocaleDateString()}
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCustom bold align="center" size="xlarge">
|
||||||
|
Judul Event Disini
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
{Array.from({ length: 4 }).map((_, index2) => (
|
||||||
|
<Grid.Col span={3} key={index2}>
|
||||||
|
<AvatarCustom size="sm" href={`/profile/${index2}`} />
|
||||||
|
</Grid.Col>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
68
app/(application)/(user)/event/(tabs)/history.tsx
Normal file
68
app/(application)/(user)/event/(tabs)/history.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { ButtonCustom, Spacing, TextCustom } from "@/components";
|
||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
import Event_BoxPublishSection from "@/screens/Event/BoxPublishSection";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function EventHistory() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerComponent = (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: 5,
|
||||||
|
backgroundColor: MainColor.soft_darkblue,
|
||||||
|
borderRadius: 50,
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={
|
||||||
|
activeCategory === "all" ? MainColor.yellow : AccentColor.blue
|
||||||
|
}
|
||||||
|
textColor={activeCategory === "all" ? MainColor.black : MainColor.white}
|
||||||
|
style={{ width: "49%" }}
|
||||||
|
onPress={() => handlePress("all")}
|
||||||
|
>
|
||||||
|
Semua Riwayat
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing width={"2%"} />
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={
|
||||||
|
activeCategory === "main" ? MainColor.yellow : AccentColor.blue
|
||||||
|
}
|
||||||
|
textColor={
|
||||||
|
activeCategory === "main" ? MainColor.black : MainColor.white
|
||||||
|
}
|
||||||
|
style={{ width: "49%" }}
|
||||||
|
onPress={() => handlePress("main")}
|
||||||
|
>
|
||||||
|
Riwayat Saya
|
||||||
|
</ButtonCustom>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper headerComponent={headerComponent} hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Event_BoxPublishSection
|
||||||
|
key={index.toString()}
|
||||||
|
id={index.toString()}
|
||||||
|
username={`Riwayat ${activeCategory === "main" ? "Saya" : "Semua"}`}
|
||||||
|
rightComponentAvatar={
|
||||||
|
<TextCustom>{new Date().toLocaleDateString()}</TextCustom>
|
||||||
|
}
|
||||||
|
href={`/event/${index}/history`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
app/(application)/(user)/event/(tabs)/index.tsx
Normal file
23
app/(application)/(user)/event/(tabs)/index.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import FloatingButton from "@/components/Button/FloatingButton";
|
||||||
|
import Event_BoxPublishSection from "@/screens/Event/BoxPublishSection";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function EventBeranda() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton onPress={() => router.push("/event/create")} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Event_BoxPublishSection
|
||||||
|
key={index}
|
||||||
|
id={index.toString()}
|
||||||
|
href={`/event/${index}/publish`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
63
app/(application)/(user)/event/(tabs)/status.tsx
Normal file
63
app/(application)/(user)/event/(tabs)/status.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import {
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
Grid,
|
||||||
|
ScrollableCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom
|
||||||
|
} from "@/components";
|
||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function EventStatus() {
|
||||||
|
const id = "test-id-event";
|
||||||
|
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
|
"publish"
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollComponent = (
|
||||||
|
<ScrollableCustom
|
||||||
|
data={masterStatus.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as any}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper headerComponent={scrollComponent}>
|
||||||
|
<BoxWithHeaderSection href={`/event/${id}/${activeCategory}/detail-event`}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<TextCustom truncate bold>
|
||||||
|
Lorem ipsum,{" "}
|
||||||
|
<TextCustom color="green">{activeCategory}</TextCustom> dolor
|
||||||
|
sit amet consectetur adipisicing elit.
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom>{new Date().toLocaleDateString()}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextCustom truncate={2}>
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur
|
||||||
|
eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora,
|
||||||
|
atque. Aperiam minima asperiores dicta perferendis quis adipisci,
|
||||||
|
dolore optio porro!
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
117
app/(application)/(user)/event/[id]/[status]/detail-event.tsx
Normal file
117
app/(application)/(user)/event/[id]/[status]/detail-event.tsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
Grid,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import Event_AlertButtonStatusSection from "@/screens/Event/AlertButtonStatusSection";
|
||||||
|
import Event_ButtonStatusSection from "@/screens/Event/ButtonStatusSection";
|
||||||
|
import { menuDrawerDraftEvent } from "@/screens/Event/menuDrawerDraft";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function EventDetailStatus() {
|
||||||
|
const { id, status } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [openAlert, setOpenAlert] = useState(false);
|
||||||
|
const [openDeleteAlert, setOpenDeleteAlert] = useState(false);
|
||||||
|
|
||||||
|
const handlePress = (item: IMenuDrawerItem) => {
|
||||||
|
console.log("PATH >> ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail ${status === "publish" ? "" : status}`,
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
headerRight: () =>
|
||||||
|
status === "draft" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawer(true)} />
|
||||||
|
) : null,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold align="center" size="xlarge">
|
||||||
|
Judul event {status}
|
||||||
|
</TextCustom>
|
||||||
|
{listData.map((item, index) => (
|
||||||
|
<Grid key={index}>
|
||||||
|
<Grid.Col span={4}>
|
||||||
|
<TextCustom bold>{item.title}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<TextCustom>{item.value}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
<Event_ButtonStatusSection
|
||||||
|
status={status as string}
|
||||||
|
onOpenAlert={setOpenAlert}
|
||||||
|
onOpenDeleteAlert={setOpenDeleteAlert}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={250}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={menuDrawerDraftEvent({ id: id as string }) as any}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePress as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
<Event_AlertButtonStatusSection
|
||||||
|
id={id as string}
|
||||||
|
status={status as string}
|
||||||
|
openAlert={openAlert}
|
||||||
|
setOpenAlert={setOpenAlert}
|
||||||
|
openDeleteAlert={openDeleteAlert}
|
||||||
|
setOpenDeleteAlert={setOpenDeleteAlert}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
title: "Lokasi",
|
||||||
|
value:
|
||||||
|
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora, atque. Aperiam minima asperiores dicta perferendis quis adipisci, dolore optio porro!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Tipe Acara",
|
||||||
|
value: "Workshop",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Tanggal Mulai",
|
||||||
|
value: "Senin, 18 Juli 2025, 10:00 WIB",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Tanggal Berakhir",
|
||||||
|
value: "Selasa, 19 Juli 2025, 12:00 WIB",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Deskripsi",
|
||||||
|
value:
|
||||||
|
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora, atque. Aperiam minima asperiores dicta perferendis quis adipisci, dolore optio porro!",
|
||||||
|
},
|
||||||
|
];
|
||||||
51
app/(application)/(user)/event/[id]/contribution.tsx
Normal file
51
app/(application)/(user)/event/[id]/contribution.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
ViewWrapper,
|
||||||
|
Spacing,
|
||||||
|
} from "@/components";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||||
|
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function EventDetailContribution() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
|
const handlePress = (item: IMenuDrawerItem) => {
|
||||||
|
console.log("PATH ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail kontribusi`,
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Event_BoxDetailPublishSection />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={250}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={menuDrawerPublishEvent({ id: id as string })}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePress}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
107
app/(application)/(user)/event/[id]/edit.tsx
Normal file
107
app/(application)/(user)/event/[id]/edit.tsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
SelectCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
|
||||||
|
import { masterTypeEvent } from "@/lib/dummy-data/event/master-type-event";
|
||||||
|
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Platform } from "react-native";
|
||||||
|
|
||||||
|
export default function EventEdit() {
|
||||||
|
const [selectedDate, setSelectedDate] = useState<
|
||||||
|
Date | DateTimePickerEvent | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const [selectedEndDate, setSelectedEndDate] = useState<
|
||||||
|
Date | DateTimePickerEvent | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const handlerSubmit = () => {
|
||||||
|
try {
|
||||||
|
if (selectedDate) {
|
||||||
|
console.log("Tanggal yang dipilih:", selectedDate);
|
||||||
|
console.log(`ISO Format ${Platform.OS}:`, selectedDate.toString());
|
||||||
|
// Kirim ke API atau proses lanjutan
|
||||||
|
} else {
|
||||||
|
console.log("Tanggal belum dipilih");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedEndDate) {
|
||||||
|
console.log("Tanggal yang dipilih:", selectedEndDate);
|
||||||
|
console.log(`ISO Format ${Platform.OS}:`, selectedEndDate.toString());
|
||||||
|
// Kirim ke API atau proses lanjutan
|
||||||
|
} else {
|
||||||
|
console.log("Tanggal berakhir belum dipilih");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Data berhasil terupdate");
|
||||||
|
router.back()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
|
<ButtonCustom title="Update" onPress={handlerSubmit} />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom
|
||||||
|
placeholder="Masukkan nama event"
|
||||||
|
label="Nama Event"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<SelectCustom
|
||||||
|
label="Tipe Event"
|
||||||
|
placeholder="Pilih tipe event"
|
||||||
|
data={masterTypeEvent}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Lokasi"
|
||||||
|
placeholder="Masukkan lokasi event"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DateTimePickerCustom
|
||||||
|
label="Tanggal & Waktu Mulai"
|
||||||
|
required
|
||||||
|
onChange={(date: Date) => {
|
||||||
|
setSelectedDate(date as any);
|
||||||
|
}}
|
||||||
|
value={selectedDate as any}
|
||||||
|
minimumDate={new Date(Date.now())}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DateTimePickerCustom
|
||||||
|
label="Tanggal & Waktu Berakhir"
|
||||||
|
required
|
||||||
|
onChange={(date: Date) => {
|
||||||
|
setSelectedEndDate(date as any);
|
||||||
|
}}
|
||||||
|
value={selectedEndDate as any}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi"
|
||||||
|
placeholder="Masukkan deskripsi event"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={100}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{buttonSubmit}
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
51
app/(application)/(user)/event/[id]/history.tsx
Normal file
51
app/(application)/(user)/event/[id]/history.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
ViewWrapper,
|
||||||
|
Spacing,
|
||||||
|
} from "@/components";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||||
|
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function EventDetailHistory() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
|
const handlePress = (item: IMenuDrawerItem) => {
|
||||||
|
console.log("PATH ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail riwayat`,
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Event_BoxDetailPublishSection />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={250}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={menuDrawerPublishEvent({ id: id as string })}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePress}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
17
app/(application)/(user)/event/[id]/list-of-participants.tsx
Normal file
17
app/(application)/(user)/event/[id]/list-of-participants.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BaseBox,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
|
||||||
|
export default function EventListOfParticipants() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox key={index} paddingBlock={0}>
|
||||||
|
<AvatarUsernameAndOtherComponent avatarHref={`/profile/${index}`} />
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
64
app/(application)/(user)/event/[id]/publish.tsx
Normal file
64
app/(application)/(user)/event/[id]/publish.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
Spacing,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||||
|
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Alert } from "react-native";
|
||||||
|
|
||||||
|
export default function EventDetailPublish() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
|
const handlePress = (item: IMenuDrawerItem) => {
|
||||||
|
console.log("PATH ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const footerButton = (
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor="green"
|
||||||
|
textColor="white"
|
||||||
|
onPress={() => Alert.alert("Anda berhasil join event ini")}
|
||||||
|
>
|
||||||
|
Join
|
||||||
|
</ButtonCustom>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Event publish`,
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Event_BoxDetailPublishSection footerButton={footerButton} />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={250}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={menuDrawerPublishEvent({ id: id as string })}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePress}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
109
app/(application)/(user)/event/create.tsx
Normal file
109
app/(application)/(user)/event/create.tsx
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
SelectCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
|
||||||
|
import { masterTypeEvent } from "@/lib/dummy-data/event/master-type-event";
|
||||||
|
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Platform } from "react-native";
|
||||||
|
|
||||||
|
export default function EventCreate() {
|
||||||
|
const [selectedDate, setSelectedDate] = useState<
|
||||||
|
Date | DateTimePickerEvent | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const [selectedEndDate, setSelectedEndDate] = useState<
|
||||||
|
Date | DateTimePickerEvent | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const handlerSubmit = () => {
|
||||||
|
try {
|
||||||
|
if (selectedDate) {
|
||||||
|
console.log("Tanggal yang dipilih:", selectedDate);
|
||||||
|
console.log(`ISO Format ${Platform.OS}:`, selectedDate.toString());
|
||||||
|
// Kirim ke API atau proses lanjutan
|
||||||
|
} else {
|
||||||
|
console.log("Tanggal belum dipilih");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedEndDate) {
|
||||||
|
console.log("Tanggal yang dipilih:", selectedEndDate);
|
||||||
|
console.log(`ISO Format ${Platform.OS}:`, selectedEndDate.toString());
|
||||||
|
// Kirim ke API atau proses lanjutan
|
||||||
|
} else {
|
||||||
|
console.log("Tanggal berakhir belum dipilih");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Data berhasil disimpan");
|
||||||
|
router.navigate("/event/status");
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
|
<ButtonCustom title="Simpan" onPress={handlerSubmit} />
|
||||||
|
// <BoxButtonOnFooter>
|
||||||
|
// </BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom
|
||||||
|
placeholder="Masukkan nama event"
|
||||||
|
label="Nama Event"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<SelectCustom
|
||||||
|
label="Tipe Event"
|
||||||
|
placeholder="Pilih tipe event"
|
||||||
|
data={masterTypeEvent}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Lokasi"
|
||||||
|
placeholder="Masukkan lokasi event"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DateTimePickerCustom
|
||||||
|
label="Tanggal & Waktu Mulai"
|
||||||
|
required
|
||||||
|
onChange={(date: Date) => {
|
||||||
|
setSelectedDate(date as any);
|
||||||
|
}}
|
||||||
|
value={selectedDate as any}
|
||||||
|
minimumDate={new Date(Date.now())}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DateTimePickerCustom
|
||||||
|
label="Tanggal & Waktu Berakhir"
|
||||||
|
required
|
||||||
|
onChange={(date: Date) => {
|
||||||
|
setSelectedEndDate(date as any);
|
||||||
|
}}
|
||||||
|
value={selectedEndDate as any}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi"
|
||||||
|
placeholder="Masukkan deskripsi event"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={100}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{buttonSubmit}
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
14
app/(application)/(user)/event/detail/[id].tsx
Normal file
14
app/(application)/(user)/event/detail/[id].tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { useLocalSearchParams } from "expo-router";
|
||||||
|
import { Text } from "react-native";
|
||||||
|
|
||||||
|
export default function DetailEvent() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
console.log("id event >", id);
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<Text style={GStyles.textLabel}>Detail Event {id}</Text>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
37
app/(application)/(user)/forum/[id]/edit.tsx
Normal file
37
app/(application)/(user)/forum/[id]/edit.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function ForumEdit() {
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Posting", text);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<TextAreaCustom
|
||||||
|
placeholder="Ketik diskusi anda..."
|
||||||
|
maxLength={1000}
|
||||||
|
showCount
|
||||||
|
value={text}
|
||||||
|
onChangeText={setText}
|
||||||
|
/>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
113
app/(application)/(user)/forum/[id]/forumku.tsx
Normal file
113
app/(application)/(user)/forum/[id]/forumku.tsx
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import {
|
||||||
|
AlertCustom,
|
||||||
|
AvatarCustom,
|
||||||
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
DrawerCustom,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
||||||
|
import { listDummyDiscussionForum } from "@/screens/Forum/list-data-dummy";
|
||||||
|
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
||||||
|
import { useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function Forumku() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [alertStatus, setAlertStatus] = useState(false);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<AvatarCustom
|
||||||
|
href={`/(application)/(image)/preview-image/${id}`}
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom bold truncate>
|
||||||
|
@bagas_banuna
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>1 postingan</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
|
<ButtonCustom href={`/profile/${id}`}>
|
||||||
|
Kunjungi Profile
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
{listDummyDiscussionForum.map((e, i) => (
|
||||||
|
<Forum_BoxDetailSection
|
||||||
|
key={i}
|
||||||
|
data={e}
|
||||||
|
setOpenDrawer={setOpenDrawer}
|
||||||
|
setStatus={setStatus}
|
||||||
|
isTruncate={true}
|
||||||
|
href={`/forum/${id}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* Drawer Komponen Eksternal */}
|
||||||
|
<DrawerCustom
|
||||||
|
height={350}
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
>
|
||||||
|
<Forum_MenuDrawerBerandaSection
|
||||||
|
id={id as string}
|
||||||
|
status={status}
|
||||||
|
setIsDrawerOpen={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
setShowDeleteAlert={setDeleteAlert}
|
||||||
|
setShowAlertStatus={setAlertStatus}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Alert Komponen Eksternal */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={alertStatus}
|
||||||
|
onLeftPress={() => setAlertStatus(false)}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setAlertStatus(false);
|
||||||
|
console.log("Ubah status forum");
|
||||||
|
}}
|
||||||
|
title="Ubah Status Forum"
|
||||||
|
message="Apakah Anda yakin ingin mengubah status forum ini?"
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Ubah"
|
||||||
|
colorRight={MainColor.green}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Alert Delete */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={deleteAlert}
|
||||||
|
onLeftPress={() => setDeleteAlert(false)}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
console.log("Hapus forum");
|
||||||
|
}}
|
||||||
|
title="Hapus Forum"
|
||||||
|
message="Apakah Anda yakin ingin menghapus forum ini?"
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Hapus"
|
||||||
|
colorRight={MainColor.red}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
176
app/(application)/(user)/forum/[id]/index.tsx
Normal file
176
app/(application)/(user)/forum/[id]/index.tsx
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
import {
|
||||||
|
AlertCustom,
|
||||||
|
ButtonCustom,
|
||||||
|
DrawerCustom,
|
||||||
|
Spacing,
|
||||||
|
TextAreaCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import Forum_CommentarBoxSection from "@/screens/Forum/CommentarBoxSection";
|
||||||
|
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
||||||
|
import { listDummyCommentarForum } from "@/screens/Forum/list-data-dummy";
|
||||||
|
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
||||||
|
import Forum_MenuDrawerCommentar from "@/screens/Forum/MenuDrawerSection.tsx/MenuCommentar";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function ForumDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
console.log(id);
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [alertStatus, setAlertStatus] = useState(false);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
|
||||||
|
// Comentar
|
||||||
|
const [openDrawerCommentar, setOpenDrawerCommentar] = useState(false);
|
||||||
|
const [alertDeleteCommentar, setAlertDeleteCommentar] = useState(false);
|
||||||
|
|
||||||
|
const dataDummy = {
|
||||||
|
name: "Bagas",
|
||||||
|
status: "Open",
|
||||||
|
date: "14/07/2025",
|
||||||
|
deskripsi:
|
||||||
|
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae inventore iure pariatur, libero omnis excepturi. Ullam ad officiis deleniti quos esse odit nesciunt, ipsam adipisci cumque aliquam corporis culpa fugit?",
|
||||||
|
jumlahBalas: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
{/* <StackCustom>
|
||||||
|
</StackCustom> */}
|
||||||
|
<Forum_BoxDetailSection
|
||||||
|
data={dataDummy}
|
||||||
|
setOpenDrawer={setOpenDrawer}
|
||||||
|
setStatus={setStatus}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
placeholder="Ketik diskusi anda..."
|
||||||
|
maxLength={1000}
|
||||||
|
showCount
|
||||||
|
value={text}
|
||||||
|
onChangeText={setText}
|
||||||
|
style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ButtonCustom
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-end",
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Posting", text);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Balas
|
||||||
|
</ButtonCustom>
|
||||||
|
|
||||||
|
<Spacing height={40} />
|
||||||
|
|
||||||
|
{listDummyCommentarForum.map((e, i) => (
|
||||||
|
<Forum_CommentarBoxSection
|
||||||
|
key={i}
|
||||||
|
data={e}
|
||||||
|
setOpenDrawer={setOpenDrawerCommentar}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
height={350}
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
>
|
||||||
|
<Forum_MenuDrawerBerandaSection
|
||||||
|
id={id as string}
|
||||||
|
status={status}
|
||||||
|
setIsDrawerOpen={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
setShowDeleteAlert={setDeleteAlert}
|
||||||
|
setShowAlertStatus={setAlertStatus}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Alert Status */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={alertStatus}
|
||||||
|
title="Ubah Status Forum"
|
||||||
|
message="Apakah Anda yakin ingin mengubah status forum ini?"
|
||||||
|
onLeftPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setAlertStatus(false);
|
||||||
|
console.log("Batal");
|
||||||
|
}}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setAlertStatus(false);
|
||||||
|
console.log("Ubah status forum");
|
||||||
|
}}
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Ubah"
|
||||||
|
colorRight={MainColor.green}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Alert Delete */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={deleteAlert}
|
||||||
|
title="Hapus Forum"
|
||||||
|
message="Apakah Anda yakin ingin menghapus forum ini?"
|
||||||
|
onLeftPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
console.log("Batal");
|
||||||
|
}}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
console.log("Hapus forum");
|
||||||
|
}}
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Hapus"
|
||||||
|
colorRight={MainColor.red}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Commentar */}
|
||||||
|
<DrawerCustom
|
||||||
|
height={350}
|
||||||
|
isVisible={openDrawerCommentar}
|
||||||
|
closeDrawer={() => setOpenDrawerCommentar(false)}
|
||||||
|
>
|
||||||
|
<Forum_MenuDrawerCommentar
|
||||||
|
id={id as string}
|
||||||
|
setIsDrawerOpen={() => {
|
||||||
|
setOpenDrawerCommentar(false);
|
||||||
|
}}
|
||||||
|
setShowDeleteAlert={setAlertDeleteCommentar}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Alert Delete Commentar */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={alertDeleteCommentar}
|
||||||
|
title="Hapus Komentar"
|
||||||
|
message="Apakah Anda yakin ingin menghapus komentar ini?"
|
||||||
|
onLeftPress={() => {
|
||||||
|
setOpenDrawerCommentar(false);
|
||||||
|
setAlertDeleteCommentar(false);
|
||||||
|
console.log("Batal");
|
||||||
|
}}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawerCommentar(false);
|
||||||
|
setAlertDeleteCommentar(false);
|
||||||
|
console.log("Hapus commentar");
|
||||||
|
}}
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Hapus"
|
||||||
|
colorRight={MainColor.red}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function ForumOtherReportCommentar() {
|
||||||
|
const handleSubmit = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={MainColor.red}
|
||||||
|
textColor={MainColor.white}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Report lainnya");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Report
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={handleSubmit}>
|
||||||
|
<TextAreaCustom placeholder="Laporkan Komentar" />
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
32
app/(application)/(user)/forum/[id]/other-report-posting.tsx
Normal file
32
app/(application)/(user)/forum/[id]/other-report-posting.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function ForumOtherReportPosting() {
|
||||||
|
const handleSubmit = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={MainColor.red}
|
||||||
|
textColor={MainColor.white}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Report lainnya");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Report
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={handleSubmit}>
|
||||||
|
<TextAreaCustom placeholder="Laporkan Diskusi" />
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
42
app/(application)/(user)/forum/[id]/report-commentar.tsx
Normal file
42
app/(application)/(user)/forum/[id]/report-commentar.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function ForumReportCommentar() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<Forum_ReportListSection />
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={MainColor.red}
|
||||||
|
textColor={MainColor.white}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Report");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Report
|
||||||
|
</ButtonCustom>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
textColor={MainColor.white}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Lainnya");
|
||||||
|
router.replace("/forum/[id]/other-report-commentar");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Lainnya
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing/>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
37
app/(application)/(user)/forum/[id]/report-posting.tsx
Normal file
37
app/(application)/(user)/forum/[id]/report-posting.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { ViewWrapper, StackCustom, ButtonCustom, Spacing } from "@/components";
|
||||||
|
import { MainColor, AccentColor } from "@/constants/color-palet";
|
||||||
|
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function ForumReportPosting() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<Forum_ReportListSection />
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={MainColor.red}
|
||||||
|
textColor={MainColor.white}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Report");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Report
|
||||||
|
</ButtonCustom>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
textColor={MainColor.white}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Lainnya");
|
||||||
|
router.replace("/forum/[id]/other-report-posting");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Lainnya
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
37
app/(application)/(user)/forum/create.tsx
Normal file
37
app/(application)/(user)/forum/create.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function ForumCreate() {
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Posting", text);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Posting
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<TextAreaCustom
|
||||||
|
placeholder="Ketik diskusi anda..."
|
||||||
|
maxLength={1000}
|
||||||
|
showCount
|
||||||
|
value={text}
|
||||||
|
onChangeText={setText}
|
||||||
|
/>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
113
app/(application)/(user)/forum/index.tsx
Normal file
113
app/(application)/(user)/forum/index.tsx
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import {
|
||||||
|
AlertCustom,
|
||||||
|
AvatarCustom,
|
||||||
|
BackButton,
|
||||||
|
DrawerCustom,
|
||||||
|
SearchInput,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import FloatingButton from "@/components/Button/FloatingButton";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
||||||
|
import { listDummyDiscussionForum } from "@/screens/Forum/list-data-dummy";
|
||||||
|
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
||||||
|
import { router, Stack } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function Forum() {
|
||||||
|
const id = "test-id-forum";
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [alertStatus, setAlertStatus] = useState(false);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Forum",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => <AvatarCustom href={`/forum/${id}/forumku`} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper
|
||||||
|
headerComponent={<SearchInput placeholder="Cari topik diskusi" />}
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton
|
||||||
|
onPress={() =>
|
||||||
|
router.navigate("/(application)/(user)/forum/create")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{listDummyDiscussionForum.map((e, i) => (
|
||||||
|
<Forum_BoxDetailSection
|
||||||
|
key={i}
|
||||||
|
data={e}
|
||||||
|
setOpenDrawer={setOpenDrawer}
|
||||||
|
setStatus={setStatus}
|
||||||
|
isTruncate={true}
|
||||||
|
href={`/forum/${id}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
height={350}
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
>
|
||||||
|
<Forum_MenuDrawerBerandaSection
|
||||||
|
id={id}
|
||||||
|
status={status}
|
||||||
|
setIsDrawerOpen={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
setShowDeleteAlert={setDeleteAlert}
|
||||||
|
setShowAlertStatus={setAlertStatus}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Alert Status */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={alertStatus}
|
||||||
|
title="Ubah Status Forum"
|
||||||
|
message="Apakah Anda yakin ingin mengubah status forum ini?"
|
||||||
|
onLeftPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setAlertStatus(false);
|
||||||
|
console.log("Batal");
|
||||||
|
}}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setAlertStatus(false);
|
||||||
|
console.log("Ubah status forum");
|
||||||
|
}}
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Ubah"
|
||||||
|
colorRight={MainColor.green}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Alert Delete */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={deleteAlert}
|
||||||
|
title="Hapus Forum"
|
||||||
|
message="Apakah Anda yakin ingin menghapus forum ini?"
|
||||||
|
onLeftPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
console.log("Batal");
|
||||||
|
}}
|
||||||
|
onRightPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
console.log("Hapus forum");
|
||||||
|
}}
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Hapus"
|
||||||
|
colorRight={MainColor.red}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import NewHomeView from "@/screens/Home/UiHome";
|
import UiHome from "@/screens/Home/UiHome";
|
||||||
|
|
||||||
export default function Application() {
|
export default function Application() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NewHomeView />
|
<UiHome />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
59
app/(application)/(user)/investment/(tabs)/_layout.tsx
Normal file
59
app/(application)/(user)/investment/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
|
import { Feather, FontAwesome6, Ionicons } from "@expo/vector-icons";
|
||||||
|
import { Tabs } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentTabsLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs screenOptions={TabsStyles}>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: "Bursa",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Ionicons
|
||||||
|
name="bar-chart-outline"
|
||||||
|
color={color}
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="portofolio"
|
||||||
|
options={{
|
||||||
|
title: "Portofolio",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Feather name="pie-chart" color={color} size={ICON_SIZE_SMALL} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="my-holding"
|
||||||
|
options={{
|
||||||
|
title: "Saham Saya",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<FontAwesome6
|
||||||
|
name="hand-holding-dollar"
|
||||||
|
color={color}
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="transaction"
|
||||||
|
options={{
|
||||||
|
title: "Transaksi",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<FontAwesome6
|
||||||
|
name="money-bill-transfer"
|
||||||
|
color={color}
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
81
app/(application)/(user)/investment/(tabs)/index.tsx
Normal file
81
app/(application)/(user)/investment/(tabs)/index.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
FloatingButton,
|
||||||
|
Grid,
|
||||||
|
ProgressCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function InvestmentBursa() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton onPress={() => router.push("/investment/create")} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox key={index} paddingTop={7} paddingBottom={7}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<Image
|
||||||
|
source={DUMMY_IMAGE.background}
|
||||||
|
style={{ width: "auto", height: 100, borderRadius: 10 }}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom truncate={2}>
|
||||||
|
Title here : Lorem ipsum dolor sit amet consectetur
|
||||||
|
adipisicing elit. Omnis, exercitationem, sequi enim quod
|
||||||
|
distinctio maiores laudantium amet, quidem atque repellat sit
|
||||||
|
vitae qui aliquam est veritatis laborum eum voluptatum totam!
|
||||||
|
</TextCustom>
|
||||||
|
<ProgressCustom value={index % 5 * 20} size="lg" />
|
||||||
|
<TextCustom>
|
||||||
|
Sisa waktu: {dayjs().diff(dayjs(), "day")} hari
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// <View style={{ padding: 20, gap: 16 }}>
|
||||||
|
// <TextCustom>Progress 70%</TextCustom>
|
||||||
|
// <ProgressCustom value={70} color="primary" size="md" />
|
||||||
|
|
||||||
|
// <TextCustom>Success Progress</TextCustom>
|
||||||
|
// <ProgressCustom value={40} color="success" size="lg" />
|
||||||
|
|
||||||
|
// <TextCustom>Warning Progress (small)</TextCustom>
|
||||||
|
// <ProgressCustom value={90} color="warning" size="sm" />
|
||||||
|
|
||||||
|
// <TextCustom>Error Indeterminate</TextCustom>
|
||||||
|
// <ProgressCustom value={null} color="error" size="md" />
|
||||||
|
|
||||||
|
// <TextCustom>Custom Radius</TextCustom>
|
||||||
|
// <ProgressCustom value={60} color="info" size="xl" radius={4} />
|
||||||
|
|
||||||
|
// <ProgressCustom value={70} color="primary" size="lg" />
|
||||||
|
|
||||||
|
// <ProgressCustom value={45} color="success" size="md" label="Halfway!" />
|
||||||
|
|
||||||
|
// <ProgressCustom value={90} color="warning" size="lg" showLabel={false} />
|
||||||
|
|
||||||
|
// <ProgressCustom value={null} color="error" size="sm" label="Loading..." />
|
||||||
|
// </View>;
|
||||||
49
app/(application)/(user)/investment/(tabs)/my-holding.tsx
Normal file
49
app/(application)/(user)/investment/(tabs)/my-holding.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
ProgressCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function InvestmentMyHolding() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox key={index} paddingTop={7} paddingBottom={7}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom truncate={2}>
|
||||||
|
Title here : Lorem ipsum dolor sit amet consectetur
|
||||||
|
adipisicing elit. Omnis, exercitationem, sequi enim quod
|
||||||
|
distinctio maiores laudantium amet, quidem atque repellat sit
|
||||||
|
vitae qui aliquam est veritatis laborum eum voluptatum totam!
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Spacing height={5} />
|
||||||
|
<TextCustom size="small">Rp. 7.500.000</TextCustom>
|
||||||
|
<TextCustom size="small">300 Lembar</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={5}
|
||||||
|
style={{
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProgressCustom value={(index % 5) * 20} size="lg" />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
70
app/(application)/(user)/investment/(tabs)/portofolio.tsx
Normal file
70
app/(application)/(user)/investment/(tabs)/portofolio.tsx
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
ScrollableCustom,
|
||||||
|
Spacing,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||||
|
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function InvestmentPortofolio() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
|
"publish"
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollComponent = (
|
||||||
|
<ScrollableCustom
|
||||||
|
data={masterStatus.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as any}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ViewWrapper headerComponent={scrollComponent} hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox key={index} paddingTop={7} paddingBottom={7}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom truncate={2}>
|
||||||
|
Title here : {activeCategory} Lorem ipsum dolor sit amet consectetur adipisicing
|
||||||
|
elit. Omnis, exercitationem, sequi enim quod distinctio maiores
|
||||||
|
laudantium amet, quidem atque repellat sit vitae qui aliquam est
|
||||||
|
veritatis laborum eum voluptatum totam!
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<TextCustom bold size="small">
|
||||||
|
Target Dana:
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>Rp. {index + 1 % 3/4 * 1004000}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<Image
|
||||||
|
source={DUMMY_IMAGE.background}
|
||||||
|
style={{ width: "auto", height: 100, borderRadius: 10 }}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
53
app/(application)/(user)/investment/(tabs)/transaction.tsx
Normal file
53
app/(application)/(user)/investment/(tabs)/transaction.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import {
|
||||||
|
BadgeCustom,
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function InvestmentTransaction() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, i) => (
|
||||||
|
<BaseBox key={i} paddingTop={7} paddingBottom={7}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom truncate>
|
||||||
|
Title Investment: Lorem ipsum dolor sit amet consectetur
|
||||||
|
adipisicing elit. Am culpa excepturi deleniti soluta animi
|
||||||
|
porro amet ducimus.
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom color="gray" size="small">
|
||||||
|
{dayjs().format("DD/MM/YYYY")}
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={5} style={{ alignItems: "flex-end" }}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom bold truncate>
|
||||||
|
Rp. 7.500.000
|
||||||
|
</TextCustom>
|
||||||
|
<BadgeCustom
|
||||||
|
variant="light"
|
||||||
|
color="success"
|
||||||
|
style={GStyles.alignSelfFlexEnd}
|
||||||
|
>
|
||||||
|
Berhasil
|
||||||
|
</BadgeCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
197
app/(application)/(user)/investment/create.tsx
Normal file
197
app/(application)/(user)/investment/create.tsx
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
SelectCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import dummyPembagianDeviden from "@/lib/dummy-data/investment/pembagian-deviden";
|
||||||
|
import dummyListPencarianInvestor from "@/lib/dummy-data/investment/pencarian-investor";
|
||||||
|
import dummyPeriodeDeviden from "@/lib/dummy-data/investment/periode-deviden";
|
||||||
|
import { FontAwesome5 } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentCreate() {
|
||||||
|
const [data, setData] = useState({
|
||||||
|
title: "",
|
||||||
|
targetDana: 0,
|
||||||
|
hargaPerLembar: 0,
|
||||||
|
totalLembar: 0,
|
||||||
|
rasioKeuntungan: 0,
|
||||||
|
pencarianInvestor: "",
|
||||||
|
periodeDeviden: "",
|
||||||
|
pembagianDeviden: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// const [coba, setCoba] = useState("");
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
{/* <View style={GStyles.inputContainerInput}>
|
||||||
|
<TextInput
|
||||||
|
style={{
|
||||||
|
...GStyles.inputText,
|
||||||
|
}}
|
||||||
|
onChangeText={(value) => setCoba(value)}
|
||||||
|
value={coba}
|
||||||
|
keyboardType="decimal-pad"
|
||||||
|
/>
|
||||||
|
</View> */}
|
||||||
|
|
||||||
|
<InformationBox text="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi." />
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.push("/take-picture/1")}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<InformationBox text="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepannya." />
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<CenterCustom>
|
||||||
|
<FontAwesome5
|
||||||
|
name="file-pdf"
|
||||||
|
size={30}
|
||||||
|
color={MainColor.disabled}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
</BaseBox>
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.push("/take-picture/1")}
|
||||||
|
>
|
||||||
|
Upload File
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
placeholder="Judul"
|
||||||
|
label="Judul"
|
||||||
|
value={data.title}
|
||||||
|
onChangeText={(value) => setData({ ...data, title: value })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
iconLeft="Rp."
|
||||||
|
placeholder="0"
|
||||||
|
label="Target Dana"
|
||||||
|
keyboardType="numeric"
|
||||||
|
onChangeText={(value) =>
|
||||||
|
setData({ ...data, targetDana: Number(value) })
|
||||||
|
}
|
||||||
|
value={data.targetDana === 0 ? "" : data.targetDana.toString()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
iconLeft="Rp."
|
||||||
|
placeholder="0"
|
||||||
|
label="Target Dana"
|
||||||
|
keyboardType="numeric"
|
||||||
|
onChangeText={(value) =>
|
||||||
|
setData({ ...data, targetDana: Number(value) })
|
||||||
|
}
|
||||||
|
value={data.targetDana === 0 ? "" : data.targetDana.toString()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
iconLeft="Rp."
|
||||||
|
placeholder="0"
|
||||||
|
label="Harga Per Lembar"
|
||||||
|
keyboardType="numeric"
|
||||||
|
onChangeText={(value) =>
|
||||||
|
setData({ ...data, targetDana: Number(value) })
|
||||||
|
}
|
||||||
|
value={data.targetDana === 0 ? "" : data.targetDana.toString()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
placeholder="0"
|
||||||
|
label="Total Lembar"
|
||||||
|
keyboardType="numeric"
|
||||||
|
onChangeText={(value) =>
|
||||||
|
setData({ ...data, totalLembar: Number(value) })
|
||||||
|
}
|
||||||
|
value={data.totalLembar === 0 ? "" : data.totalLembar.toString()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
iconRight="%"
|
||||||
|
label="Rasio Keuntungan / ROI %"
|
||||||
|
placeholder="0"
|
||||||
|
keyboardType="numeric"
|
||||||
|
onChangeText={(value) =>
|
||||||
|
setData({ ...data, rasioKeuntungan: Number(value) })
|
||||||
|
}
|
||||||
|
value={
|
||||||
|
data.rasioKeuntungan === 0 ? "" : data.rasioKeuntungan.toString()
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectCustom
|
||||||
|
required
|
||||||
|
placeholder="Pilih batas waktu"
|
||||||
|
label="Pencarian Investor"
|
||||||
|
data={dummyListPencarianInvestor.map((item) => ({
|
||||||
|
label: item.name + `${" "}hari`,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
onChange={(value) =>
|
||||||
|
setData({ ...data, pencarianInvestor: value as any })
|
||||||
|
}
|
||||||
|
value={data.pencarianInvestor}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectCustom
|
||||||
|
required
|
||||||
|
placeholder="Pilih batas waktu"
|
||||||
|
label="Pilih Periode Deviden"
|
||||||
|
data={dummyPeriodeDeviden.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
onChange={(value) =>
|
||||||
|
setData({ ...data, periodeDeviden: value as any })
|
||||||
|
}
|
||||||
|
value={data.periodeDeviden}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectCustom
|
||||||
|
required
|
||||||
|
placeholder="Pilih batas waktu"
|
||||||
|
label="Pilih Pembagian Deviden"
|
||||||
|
data={dummyPembagianDeviden.map((item) => ({
|
||||||
|
label: item.name + `${" "}bulan`,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
onChange={(value) =>
|
||||||
|
setData({ ...data, pembagianDeviden: value as any })
|
||||||
|
}
|
||||||
|
value={data.pembagianDeviden}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
<ButtonCustom onPress={() => router.replace("/investment/portofolio")}>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing height={50} />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
34
app/(application)/(user)/job/(tabs)/_layout.tsx
Normal file
34
app/(application)/(user)/job/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { IconHome, IconStatus } from "@/components/_Icon";
|
||||||
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { Tabs } from "expo-router";
|
||||||
|
|
||||||
|
export default function JobTabsLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs screenOptions={TabsStyles}>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: "Beranda",
|
||||||
|
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="status"
|
||||||
|
options={{
|
||||||
|
title: "Status",
|
||||||
|
tabBarIcon: ({ color }) => <IconStatus color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="archive"
|
||||||
|
options={{
|
||||||
|
title: "Arsip",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Ionicons size={20} name="archive" color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
16
app/(application)/(user)/job/(tabs)/archive.tsx
Normal file
16
app/(application)/(user)/job/(tabs)/archive.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { BaseBox, TextCustom, ViewWrapper } from "@/components";
|
||||||
|
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
||||||
|
|
||||||
|
export default function JobArchive() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{jobDataDummy.map((e, i) => (
|
||||||
|
<BaseBox key={i} paddingTop={20} paddingBottom={20}>
|
||||||
|
<TextCustom align="center" bold truncate size="large">
|
||||||
|
{e.posisi}
|
||||||
|
</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
34
app/(application)/(user)/job/(tabs)/index.tsx
Normal file
34
app/(application)/(user)/job/(tabs)/index.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
FloatingButton,
|
||||||
|
SearchInput,
|
||||||
|
Spacing,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function JobBeranda() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton onPress={() => router.push("/job/create")} />
|
||||||
|
}
|
||||||
|
headerComponent={<SearchInput placeholder="Cari pekerjaan" />}
|
||||||
|
>
|
||||||
|
{jobDataDummy.map((item, index) => (
|
||||||
|
<BoxWithHeaderSection key={index} onPress={() => router.push(`/job/${item.id}`)}>
|
||||||
|
<AvatarUsernameAndOtherComponent avatarHref={`/profile/${item.id}`} />
|
||||||
|
<Spacing />
|
||||||
|
<TextCustom truncate={2} align="center" bold size="large">
|
||||||
|
{item.posisi}
|
||||||
|
</TextCustom>
|
||||||
|
<Spacing />
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
50
app/(application)/(user)/job/(tabs)/status.tsx
Normal file
50
app/(application)/(user)/job/(tabs)/status.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
ScrollableCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
|
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function JobStatus() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
|
"publish"
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollComponent = (
|
||||||
|
<ScrollableCustom
|
||||||
|
data={masterStatus.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as any}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper headerComponent={scrollComponent} hideFooter>
|
||||||
|
{jobDataDummy.map((e, i) => (
|
||||||
|
<BaseBox
|
||||||
|
key={i}
|
||||||
|
paddingTop={20}
|
||||||
|
paddingBottom={20}
|
||||||
|
href={`/job/${e.id}/${activeCategory}/detail`}
|
||||||
|
// onPress={() => console.log("pressed")}
|
||||||
|
>
|
||||||
|
<TextCustom align="center" bold truncate size="large">
|
||||||
|
{e.posisi} {activeCategory?.toUpperCase()}
|
||||||
|
</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
65
app/(application)/(user)/job/[id]/[status]/detail.tsx
Normal file
65
app/(application)/(user)/job/[id]/[status]/detail.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import {
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
Spacing,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconEdit } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import Job_BoxDetailSection from "@/screens/Job/BoxDetailSection";
|
||||||
|
import Job_ButtonStatusSection from "@/screens/Job/ButtonStatusSection";
|
||||||
|
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function JobDetailStatus() {
|
||||||
|
const { id, status } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const jobDetail = jobDataDummy.find((e) => e.id === Number(id));
|
||||||
|
|
||||||
|
const handlePress = (item: IMenuDrawerItem) => {
|
||||||
|
console.log("PATH >> ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () =>
|
||||||
|
status === "draft" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawer(true)} />
|
||||||
|
) : null,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Job_BoxDetailSection data={jobDetail} />
|
||||||
|
<Job_ButtonStatusSection status={status as string} />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconEdit />,
|
||||||
|
label: "Edit",
|
||||||
|
path: `/job/${id}/edit`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePress as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
67
app/(application)/(user)/job/[id]/edit.tsx
Normal file
67
app/(application)/(user)/job/[id]/edit.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import {
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function JobEdit() {
|
||||||
|
const buttonSubmit = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonCustom onPress={() => router.back()}>Update</ButtonCustom>
|
||||||
|
<Spacing />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="Poster atau gambar lowongan kerja bersifat opsional, tidak wajib untuk dimasukkan dan upload lah gambar yang sesuai dengan deskripsi lowongan kerja." />
|
||||||
|
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
onPress={() => {
|
||||||
|
router.push("/(application)/(image)/take-picture/123");
|
||||||
|
}}
|
||||||
|
icon="upload"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Lowongan"
|
||||||
|
placeholder="Masukan Judul Lowongan Kerja"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Syarat & Kualifikasi"
|
||||||
|
placeholder="Masukan Syarat & Kualifikasi Lowongan Kerja"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi Lowongan"
|
||||||
|
placeholder="Masukan Deskripsi Lowongan Kerja"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{buttonSubmit()}
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
79
app/(application)/(user)/job/[id]/index.tsx
Normal file
79
app/(application)/(user)/job/[id]/index.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
Spacing,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import Job_BoxDetailSection from "@/screens/Job/BoxDetailSection";
|
||||||
|
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import * as Clipboard from "expo-clipboard";
|
||||||
|
import { useLocalSearchParams } from "expo-router";
|
||||||
|
import { Alert, Linking } from "react-native";
|
||||||
|
|
||||||
|
export default function JobDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const jobDetail = jobDataDummy.find((e) => e.id === Number(id));
|
||||||
|
|
||||||
|
const OpenLinkButton = () => {
|
||||||
|
const jobUrl =
|
||||||
|
"https://stg-hipmi.wibudev.com/job-vacancy/cm6ijt9w8005zucv4twsct657";
|
||||||
|
|
||||||
|
const openInBrowser = async () => {
|
||||||
|
const supported = await Linking.canOpenURL(jobUrl);
|
||||||
|
if (supported) {
|
||||||
|
await Linking.openURL(jobUrl);
|
||||||
|
} else {
|
||||||
|
Alert.alert("Gagal membuka link", "Browser tidak tersedia.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonCustom
|
||||||
|
iconLeft={
|
||||||
|
<Ionicons name="globe" size={ICON_SIZE_SMALL} color="white" />
|
||||||
|
}
|
||||||
|
onPress={openInBrowser}
|
||||||
|
backgroundColor="green"
|
||||||
|
textColor="white"
|
||||||
|
>
|
||||||
|
Buka Lowongan di Browser
|
||||||
|
</ButtonCustom>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CopyLinkButton = () => {
|
||||||
|
const jobUrl =
|
||||||
|
"https://stg-hipmi.wibudev.com/job-vacancy/cm6ijt9w8005zucv4twsct657";
|
||||||
|
|
||||||
|
const copyToClipboard = async () => {
|
||||||
|
await Clipboard.setStringAsync(jobUrl);
|
||||||
|
Alert.alert(
|
||||||
|
"Link disalin",
|
||||||
|
"Tautan lowongan telah disalin ke clipboard."
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonCustom
|
||||||
|
iconLeft={<Ionicons name="copy" size={ICON_SIZE_SMALL} color="white" />}
|
||||||
|
onPress={copyToClipboard}
|
||||||
|
backgroundColor={MainColor.orange}
|
||||||
|
textColor="white"
|
||||||
|
>
|
||||||
|
Salin Link
|
||||||
|
</ButtonCustom>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<Job_BoxDetailSection data={jobDetail}/>
|
||||||
|
<OpenLinkButton />
|
||||||
|
<Spacing />
|
||||||
|
<CopyLinkButton />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
73
app/(application)/(user)/job/create.tsx
Normal file
73
app/(application)/(user)/job/create.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import {
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function JobCreate() {
|
||||||
|
const buttonSubmit = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() =>
|
||||||
|
router.replace("/(application)/(user)/job/(tabs)/status")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="Poster atau gambar lowongan kerja bersifat opsional, tidak wajib untuk dimasukkan dan upload lah gambar yang sesuai dengan deskripsi lowongan kerja." />
|
||||||
|
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
onPress={() => {
|
||||||
|
router.push("/(application)/(image)/take-picture/123");
|
||||||
|
}}
|
||||||
|
icon="upload"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Lowongan"
|
||||||
|
placeholder="Masukan Judul Lowongan Kerja"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Syarat & Kualifikasi"
|
||||||
|
placeholder="Masukan Syarat & Kualifikasi Lowongan Kerja"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi Lowongan"
|
||||||
|
placeholder="Masukan Deskripsi Lowongan Kerja"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{buttonSubmit()}
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
55
app/(application)/(user)/maps/[id]/custom-pin.tsx
Normal file
55
app/(application)/(user)/maps/[id]/custom-pin.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
AvatarCustom,
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
MapCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import CenterCustom from "@/components/Center/CenterCustom";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function MapsCustomPin() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log(`Simpan maps ${id}`);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<StackCustom>
|
||||||
|
<InformationBox text="Pin map akan secara otomatis menampilkan logo pada porotofolio ini, jika anda ingin melakukan custom silahkan upload logo pin baru anda." />
|
||||||
|
<CenterCustom>
|
||||||
|
<AvatarCustom size="xl" />
|
||||||
|
</CenterCustom>
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
onPress={() => console.log("Upload")}
|
||||||
|
icon="upload"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<MapCustom />
|
||||||
|
</BaseBox>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
59
app/(application)/(user)/maps/[id]/edit.tsx
Normal file
59
app/(application)/(user)/maps/[id]/edit.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
MapCustom,
|
||||||
|
Spacing,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function MapsEdit() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log(`Simpan maps ${id}`);
|
||||||
|
router.back()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<MapCustom />
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Nama Pin"
|
||||||
|
placeholder="Masukkan nama pin maps"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Upload foto ");
|
||||||
|
router.navigate(`/take-picture/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing height={50} />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
59
app/(application)/(user)/maps/create.tsx
Normal file
59
app/(application)/(user)/maps/create.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
Spacing,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function MapsCreate() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log(`Simpan maps ${id}`);
|
||||||
|
router.replace(`/portofolio/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
||||||
|
|
||||||
|
<BaseBox style={{ height: 400 }}>
|
||||||
|
<TextCustom>Maps Her</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Nama Pin"
|
||||||
|
placeholder="Masukkan nama pin maps"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Spacing height={50} />
|
||||||
|
|
||||||
|
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Upload foto ");
|
||||||
|
router.navigate(`/take-picture/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing height={50} />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
9
app/(application)/(user)/maps/index.tsx
Normal file
9
app/(application)/(user)/maps/index.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { MapCustom, ViewWrapper } from "@/components";
|
||||||
|
|
||||||
|
export default function Maps() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper style={{ paddingInline: 0, paddingBlock: 0 }}>
|
||||||
|
<MapCustom height={"100%"} />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
9
app/(application)/(user)/marketplace/index.tsx
Normal file
9
app/(application)/(user)/marketplace/index.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { TextCustom, ViewWrapper } from "@/components";
|
||||||
|
|
||||||
|
export default function Marketplace() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<TextCustom>Marketplace</TextCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
111
app/(application)/(user)/notifications/index.tsx
Normal file
111
app/(application)/(user)/notifications/index.tsx
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
ScrollableCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
const categories = [
|
||||||
|
{ value: "all", label: "Semua" },
|
||||||
|
{ value: "event", label: "Event" },
|
||||||
|
{ value: "job", label: "Job" },
|
||||||
|
{ value: "voting", label: "Voting" },
|
||||||
|
{ value: "donasi", label: "Donasi" },
|
||||||
|
{ value: "investasi", label: "Investasi" },
|
||||||
|
{ value: "forum", label: "Forum" },
|
||||||
|
{ value: "collaboration", label: "Collaboration" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const selectedCategory = (value: string) => {
|
||||||
|
const category = categories.find((c) => c.value === value);
|
||||||
|
return category?.label;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoxNotification = ({
|
||||||
|
index,
|
||||||
|
activeCategory,
|
||||||
|
}: {
|
||||||
|
index: number;
|
||||||
|
activeCategory: string | null;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BaseBox
|
||||||
|
onPress={() =>
|
||||||
|
console.log(
|
||||||
|
"Notification >",
|
||||||
|
selectedCategory(activeCategory as string)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold>
|
||||||
|
# {selectedCategory(activeCategory as string)}
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderBottomColor: MainColor.white_gray,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCustom truncate={2}>
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint odio
|
||||||
|
unde quidem voluptate quam culpa sequi molestias ipsa corrupti id,
|
||||||
|
soluta, nostrum adipisci similique, et illo asperiores deleniti eum
|
||||||
|
labore.
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom size="small" color="gray">
|
||||||
|
{index + 1} Agustus 2025
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom size="small" color="gray">
|
||||||
|
Belum lihat
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Notifications() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
headerComponent={
|
||||||
|
<ScrollableCustom
|
||||||
|
data={categories.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as string}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 20 }).map((e, i) => (
|
||||||
|
<View key={i}>
|
||||||
|
<BoxNotification index={i} activeCategory={activeCategory as any} />
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
191
app/(application)/(user)/portofolio/[id]/create.tsx
Normal file
191
app/(application)/(user)/portofolio/[id]/create.tsx
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
Grid,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
SelectCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import dummyMasterBidangBisnis from "@/lib/dummy-data/master-bidang-bisnis";
|
||||||
|
import dummyMasterSubBidangBisnis from "@/lib/dummy-data/master-sub-bidang-bisnis";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
||||||
|
|
||||||
|
export default function PortofolioCreate() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [selectedCountry, setSelectedCountry] = useState<null | ICountry>(null);
|
||||||
|
const [inputValue, setInputValue] = useState<string>("");
|
||||||
|
const [data, setData] = useState({
|
||||||
|
name: "",
|
||||||
|
bidang_usaha: "",
|
||||||
|
sub_bidang_usaha: "",
|
||||||
|
alamat: "",
|
||||||
|
nomor_telepon: "",
|
||||||
|
deskripsi: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleInputValue(phoneNumber: string) {
|
||||||
|
setInputValue(phoneNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectedCountry(country: ICountry) {
|
||||||
|
setSelectedCountry(country);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSave() {
|
||||||
|
console.log("Selanjutnya");
|
||||||
|
router.replace(`/maps/create`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonSave = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom onPress={handleSave}>Selanjutnya</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonSave}>
|
||||||
|
{/* <TextCustom>Portofolio Create {id}</TextCustom> */}
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="Lengkapi data bisnis anda." />
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Nama Bisnis"
|
||||||
|
placeholder="Masukkan nama bisnis"
|
||||||
|
|
||||||
|
/>
|
||||||
|
<SelectCustom
|
||||||
|
label="Bidang Usaha"
|
||||||
|
required
|
||||||
|
data={dummyMasterBidangBisnis.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
value={data.bidang_usaha}
|
||||||
|
onChange={(value) => {
|
||||||
|
setData({ ...(data as any), bidang_usaha: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<SelectCustom
|
||||||
|
// disabled
|
||||||
|
label="Sub Bidang Usaha"
|
||||||
|
required
|
||||||
|
data={dummyMasterSubBidangBisnis.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
value={data.sub_bidang_usaha}
|
||||||
|
onChange={(value) => {
|
||||||
|
setData({ ...(data as any), sub_bidang_usaha: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "center", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<TouchableOpacity onPress={() => console.log("delete")}>
|
||||||
|
<Ionicons name="trash" size={24} color={MainColor.red} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly onPress={() => console.log("add")}>
|
||||||
|
Tambah Pilihan
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||||
|
<TextCustom semiBold style={{ color: MainColor.white_gray }}>
|
||||||
|
Nomor Telepon
|
||||||
|
</TextCustom>
|
||||||
|
<Text style={{ color: "red" }}> *</Text>
|
||||||
|
</View>
|
||||||
|
<Spacing height={5} />
|
||||||
|
<PhoneInput
|
||||||
|
value={inputValue}
|
||||||
|
onChangePhoneNumber={handleInputValue}
|
||||||
|
selectedCountry={selectedCountry}
|
||||||
|
onChangeSelectedCountry={handleSelectedCountry}
|
||||||
|
defaultCountry="ID"
|
||||||
|
placeholder="xxx-xxx-xxx"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Alamat Bisnis"
|
||||||
|
placeholder="Masukkan alamat bisnis"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi Bisnis"
|
||||||
|
placeholder="Masukkan deskripsi bisnis"
|
||||||
|
value={data.deskripsi}
|
||||||
|
onChangeText={(value: any) => setData({ ...data, deskripsi: value })}
|
||||||
|
autosize
|
||||||
|
minRows={2}
|
||||||
|
maxRows={5}
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={100}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
{/* Logo */}
|
||||||
|
<InformationBox text="Upload logo bisnis anda untuk di tampilaka pada portofolio." />
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Upload logo >>", id);
|
||||||
|
router.navigate(`/(application)/(image)/take-picture/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing height={40} />
|
||||||
|
|
||||||
|
{/* Social Media */}
|
||||||
|
<InformationBox text="Isi hanya pada sosial media yang anda miliki." />
|
||||||
|
<TextInputCustom
|
||||||
|
label="Tiktok"
|
||||||
|
placeholder="Masukkan username tiktok"
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Facebook"
|
||||||
|
placeholder="Masukkan username facebook"
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Instagram"
|
||||||
|
placeholder="Masukkan username instagram"
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Twitter"
|
||||||
|
placeholder="Masukkan username twitter"
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Youtube"
|
||||||
|
placeholder="Masukkan username youtube"
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
48
app/(application)/(user)/portofolio/[id]/edit-logo.tsx
Normal file
48
app/(application)/(user)/portofolio/[id]/edit-logo.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
AvatarCustom,
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function PortofolioEditLogo() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Simpan logo ");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<BaseBox
|
||||||
|
style={{
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
height: 250,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AvatarCustom size="xl" />
|
||||||
|
</BaseBox>
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.navigate(`/take-picture/${id}`)}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { useLocalSearchParams, router } from "expo-router";
|
||||||
|
|
||||||
|
export default function PortofolioEditSocialMedia() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log(`Simpan sosmed ${id}`);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<TextInputCustom label="Tiktok" placeholder="Masukkan tiktok" />
|
||||||
|
<TextInputCustom label="Instagram" placeholder="Masukkan instagram" />
|
||||||
|
<TextInputCustom label="Facebook" placeholder="Masukkan facebook" />
|
||||||
|
<TextInputCustom label="Twitter" placeholder="Masukkan twitter" />
|
||||||
|
<TextInputCustom label="Youtube" placeholder="Masukkan youtube" />
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
151
app/(application)/(user)/portofolio/[id]/edit.tsx
Normal file
151
app/(application)/(user)/portofolio/[id]/edit.tsx
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
Grid,
|
||||||
|
SelectCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import dummyMasterBidangBisnis from "@/lib/dummy-data/master-bidang-bisnis";
|
||||||
|
import dummyMasterSubBidangBisnis from "@/lib/dummy-data/master-sub-bidang-bisnis";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
||||||
|
|
||||||
|
export default function PortofolioEdit() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [selectedCountry, setSelectedCountry] = useState<null | ICountry>(null);
|
||||||
|
const [inputValue, setInputValue] = useState<string>("");
|
||||||
|
|
||||||
|
const [data, setData] = useState({
|
||||||
|
name: "",
|
||||||
|
bidang_usaha: "",
|
||||||
|
sub_bidang_usaha: "",
|
||||||
|
alamat: "",
|
||||||
|
nomor_telepon: "",
|
||||||
|
deskripsi: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleInputValue(phoneNumber: string) {
|
||||||
|
setInputValue(phoneNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectedCountry(country: ICountry) {
|
||||||
|
setSelectedCountry(country);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSave() {
|
||||||
|
console.log(`Update portofolio berhasil ${id}`);
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonUpdate = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom onPress={handleSave}>Simpan</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonUpdate}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Nama Bisnis"
|
||||||
|
placeholder="Masukkan nama bisnis"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectCustom
|
||||||
|
label="Bidang Usaha"
|
||||||
|
required
|
||||||
|
data={dummyMasterBidangBisnis.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
value={data.bidang_usaha}
|
||||||
|
onChange={(value) => {
|
||||||
|
setData({ ...(data as any), bidang_usaha: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<SelectCustom
|
||||||
|
// disabled
|
||||||
|
label="Sub Bidang Usaha"
|
||||||
|
required
|
||||||
|
data={dummyMasterSubBidangBisnis.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
value={data.sub_bidang_usaha}
|
||||||
|
onChange={(value) => {
|
||||||
|
setData({ ...(data as any), sub_bidang_usaha: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "center", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<TouchableOpacity onPress={() => console.log("delete")}>
|
||||||
|
<Ionicons name="trash" size={24} color={MainColor.red} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<ButtonCenteredOnly onPress={() => console.log("add")}>
|
||||||
|
Tambah Pilihan
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
<View>
|
||||||
|
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||||
|
<TextCustom semiBold style={{ color: MainColor.white_gray }}>
|
||||||
|
Nomor Telepon
|
||||||
|
</TextCustom>
|
||||||
|
<Text style={{ color: "red" }}> *</Text>
|
||||||
|
</View>
|
||||||
|
<Spacing height={5} />
|
||||||
|
<PhoneInput
|
||||||
|
value={inputValue}
|
||||||
|
onChangePhoneNumber={handleInputValue}
|
||||||
|
selectedCountry={selectedCountry}
|
||||||
|
onChangeSelectedCountry={handleSelectedCountry}
|
||||||
|
defaultCountry="ID"
|
||||||
|
placeholder="xxx-xxx-xxx"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Alamat Bisnis"
|
||||||
|
placeholder="Masukkan alamat bisnis"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi Bisnis"
|
||||||
|
placeholder="Masukkan deskripsi bisnis"
|
||||||
|
value={data.deskripsi}
|
||||||
|
onChangeText={(value: any) =>
|
||||||
|
setData({ ...data, deskripsi: value })
|
||||||
|
}
|
||||||
|
autosize
|
||||||
|
minRows={2}
|
||||||
|
maxRows={5}
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={100}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
78
app/(application)/(user)/portofolio/[id]/index.tsx
Normal file
78
app/(application)/(user)/portofolio/[id]/index.tsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { AlertCustom, DrawerCustom } from "@/components";
|
||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { drawerItemsPortofolio } from "@/screens/Portofolio/ListPage";
|
||||||
|
import Portofolio_MenuDrawerSection from "@/screens/Portofolio/MenuDrawer";
|
||||||
|
import PorfofolioSection from "@/screens/Portofolio/PorfofolioSection";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { Stack, useLocalSearchParams, router } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
export default function Portofolio() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
|
||||||
|
const openDrawer = () => {
|
||||||
|
setIsDrawerOpen(true);
|
||||||
|
};
|
||||||
|
const closeDrawer = () => {
|
||||||
|
setIsDrawerOpen(false);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
{/* Header */}
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Portofolio",
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
headerRight: () => (
|
||||||
|
<TouchableOpacity onPress={openDrawer}>
|
||||||
|
<Ionicons
|
||||||
|
name="ellipsis-vertical"
|
||||||
|
size={20}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
),
|
||||||
|
headerStyle: GStyles.headerStyle,
|
||||||
|
headerTitleStyle: GStyles.headerTitleStyle,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<PorfofolioSection setShowDeleteAlert={setDeleteAlert} />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* Drawer Komponen Eksternal */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={isDrawerOpen}
|
||||||
|
closeDrawer={closeDrawer}
|
||||||
|
height={350}
|
||||||
|
>
|
||||||
|
<Portofolio_MenuDrawerSection
|
||||||
|
drawerItems={drawerItemsPortofolio({ id: id as string })}
|
||||||
|
setIsDrawerOpen={setIsDrawerOpen}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Alert Delete */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={deleteAlert}
|
||||||
|
onLeftPress={() => setDeleteAlert(false)}
|
||||||
|
onRightPress={() => {
|
||||||
|
setDeleteAlert(false);
|
||||||
|
console.log("Hapus portofolio");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
title="Hapus Portofolio"
|
||||||
|
message="Apakah Anda yakin ingin menghapus portofolio ini?"
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Hapus"
|
||||||
|
colorRight={MainColor.red}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
47
app/(application)/(user)/portofolio/[id]/list.tsx
Normal file
47
app/(application)/(user)/portofolio/[id]/list.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { BaseBox, Grid, TextCustom, ViewWrapper } from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function ListPortofolio() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
style={{ backgroundColor: MainColor.darkblue }}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("press to Portofolio");
|
||||||
|
router.push(`/portofolio/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col
|
||||||
|
span={10}
|
||||||
|
style={{ justifyContent: "center", backgroundColor: "" }}
|
||||||
|
>
|
||||||
|
<TextCustom bold size="large" truncate={1}>
|
||||||
|
Nama usaha portofolio
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom size="small" color="yellow">
|
||||||
|
#id-porofolio12345
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name="caret-forward"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
32
app/(application)/(user)/portofolio/_layout.tsx
Normal file
32
app/(application)/(user)/portofolio/_layout.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import { HeaderStyles } from "@/styles/header-styles";
|
||||||
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
|
export default function PortofolioLayout() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack
|
||||||
|
screenOptions={{
|
||||||
|
...HeaderStyles,
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* <Stack.Screen name="[id]/index" options={{ title: "Portofolio" }} /> */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/create"
|
||||||
|
options={{ title: "Tambah Portofolio" }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/list"
|
||||||
|
options={{ title: "Daftar Portofolio" }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen name="[id]/edit" options={{ title: "Edit Portofolio" }} />
|
||||||
|
<Stack.Screen name="[id]/edit-logo" options={{ title: "Edit Logo " }} />
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/edit-social-media"
|
||||||
|
options={{ title: "Edit Social Media" }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
110
app/(application)/(user)/profile/[id]/create.tsx
Normal file
110
app/(application)/(user)/profile/[id]/create.tsx
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import {
|
||||||
|
AvatarCustom,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
SelectCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter";
|
||||||
|
import InformationBox from "@/components/Box/InformationBox";
|
||||||
|
import LandscapeFrameUploaded from "@/components/Image/LandscapeFrameUploaded";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function CreateProfile() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState({
|
||||||
|
name: "",
|
||||||
|
email: "",
|
||||||
|
address: "",
|
||||||
|
gender: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const handlerSave = () => {
|
||||||
|
console.log("data create profile >>", data);
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
|
||||||
|
const footerComponent = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={handlerSave}
|
||||||
|
// disabled={!data.name || !data.email || !data.address || !data.gender}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={footerComponent}>
|
||||||
|
<StackCustom>
|
||||||
|
<InformationBox text="Upload foto profile anda." />
|
||||||
|
<View style={{ alignItems: "center" }}>
|
||||||
|
<AvatarCustom size="xl" />
|
||||||
|
<Spacing />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.navigate(`/take-picture/${id}`)}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<InformationBox text="Upload foto latar belakang anda." />
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<Spacing />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.navigate(`/take-picture/${id}`)}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Nama"
|
||||||
|
placeholder="Masukkan nama"
|
||||||
|
value={data.name}
|
||||||
|
onChangeText={(text) => setData({ ...data, name: text })}
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
keyboardType="email-address"
|
||||||
|
required
|
||||||
|
label="Email"
|
||||||
|
placeholder="Masukkan email"
|
||||||
|
value={data.email}
|
||||||
|
onChangeText={(text) => setData({ ...data, email: text })}
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Alamat"
|
||||||
|
placeholder="Masukkan alamat"
|
||||||
|
value={data.address}
|
||||||
|
onChangeText={(text) => setData({ ...data, address: text })}
|
||||||
|
/>
|
||||||
|
<SelectCustom
|
||||||
|
label="Jenis Kelamin"
|
||||||
|
placeholder="Pilih jenis kelamin"
|
||||||
|
data={[
|
||||||
|
{ label: "Laki-laki", value: "laki-laki" },
|
||||||
|
{ label: "Perempuan", value: "perempuan" },
|
||||||
|
]}
|
||||||
|
value={data.gender}
|
||||||
|
required
|
||||||
|
onChange={(value) => setData({ ...(data as any), gender: value })}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
108
app/(application)/(user)/profile/[id]/edit.tsx
Normal file
108
app/(application)/(user)/profile/[id]/edit.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
SelectCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
|
export default function ProfileEdit() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const [data, setData] = useState({
|
||||||
|
nama: "Bagas Banuna",
|
||||||
|
email: "bagasbanuna@gmail.com",
|
||||||
|
alamat: "Jember",
|
||||||
|
selectedValue: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{ label: "Laki-laki", value: "laki-laki" },
|
||||||
|
{ label: "Perempuan", value: "perempuan" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
console.log({
|
||||||
|
nama: data.nama,
|
||||||
|
email: data.email,
|
||||||
|
alamat: data.alamat,
|
||||||
|
selectedValue: data.selectedValue,
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
footerComponent={
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
// disabled={
|
||||||
|
// !data.nama || !data.email || !data.alamat || !data.selectedValue
|
||||||
|
// }
|
||||||
|
onPress={handleSave}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nama"
|
||||||
|
placeholder="Nama"
|
||||||
|
value={data.nama}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setData({ ...data, nama: text });
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Email"
|
||||||
|
placeholder="Email"
|
||||||
|
value={data.email}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setData({ ...data, email: text });
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Alamat"
|
||||||
|
placeholder="Alamat"
|
||||||
|
value={data.alamat}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setData({ ...data, alamat: text });
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<SelectCustom
|
||||||
|
required
|
||||||
|
label="Jenis Kelamin"
|
||||||
|
placeholder="Pilih jenis kelamin"
|
||||||
|
data={options}
|
||||||
|
value={data.selectedValue}
|
||||||
|
onChange={(value) => {
|
||||||
|
setData({ ...(data as any), selectedValue: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
marginTop: 20,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
});
|
||||||
83
app/(application)/(user)/profile/[id]/index.tsx
Normal file
83
app/(application)/(user)/profile/[id]/index.tsx
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import AlertCustom from "@/components/Alert/AlertCustom";
|
||||||
|
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 ProfileSection from "@/screens/Profile/ProfileSection";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
export default function Profile() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
|
const [showLogoutAlert, setShowLogoutAlert] = useState(false);
|
||||||
|
|
||||||
|
const openDrawer = () => {
|
||||||
|
setIsDrawerOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDrawer = () => {
|
||||||
|
setIsDrawerOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
console.log("User logout");
|
||||||
|
router.replace("/");
|
||||||
|
setShowLogoutAlert(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
{/* Header */}
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Profile",
|
||||||
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
|
headerRight: () => (
|
||||||
|
<TouchableOpacity onPress={openDrawer}>
|
||||||
|
<Ionicons
|
||||||
|
name="ellipsis-vertical"
|
||||||
|
size={20}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
),
|
||||||
|
headerStyle: GStyles.headerStyle,
|
||||||
|
headerTitleStyle: GStyles.headerTitleStyle,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileSection />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* Drawer Komponen Eksternal */}
|
||||||
|
<DrawerCustom
|
||||||
|
height={350}
|
||||||
|
isVisible={isDrawerOpen}
|
||||||
|
closeDrawer={closeDrawer}
|
||||||
|
>
|
||||||
|
<Profile_MenuDrawerSection
|
||||||
|
drawerItems={drawerItemsProfile({ id: id as string })}
|
||||||
|
setShowLogoutAlert={setShowLogoutAlert}
|
||||||
|
setIsDrawerOpen={setIsDrawerOpen}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Alert Komponen Eksternal */}
|
||||||
|
<AlertCustom
|
||||||
|
isVisible={showLogoutAlert}
|
||||||
|
onLeftPress={() => setShowLogoutAlert(false)}
|
||||||
|
onRightPress={handleLogout}
|
||||||
|
title="Apakah anda yakin ingin keluar?"
|
||||||
|
textLeft="Batal"
|
||||||
|
textRight="Keluar"
|
||||||
|
colorRight={MainColor.red}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
190
app/(application)/(user)/profile/[id]/take-picture2.txt
Normal file
190
app/(application)/(user)/profile/[id]/take-picture2.txt
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
// COMPONENT : Jika ingin uoload gambar dan video gunakan component ini
|
||||||
|
|
||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import AntDesign from "@expo/vector-icons/AntDesign";
|
||||||
|
import Feather from "@expo/vector-icons/Feather";
|
||||||
|
import FontAwesome6 from "@expo/vector-icons/FontAwesome6";
|
||||||
|
import {
|
||||||
|
CameraMode,
|
||||||
|
CameraType,
|
||||||
|
CameraView,
|
||||||
|
useCameraPermissions,
|
||||||
|
} from "expo-camera";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { Button, Pressable, StyleSheet, Text, View } from "react-native";
|
||||||
|
|
||||||
|
export default function TakePictureProfile2() {
|
||||||
|
const [permission, requestPermission] = useCameraPermissions();
|
||||||
|
const ref = useRef<CameraView>(null);
|
||||||
|
const [uri, setUri] = useState<string | null>(null);
|
||||||
|
const [mode, setMode] = useState<CameraMode>("picture");
|
||||||
|
const [facing, setFacing] = useState<CameraType>("back");
|
||||||
|
const [recording, setRecording] = useState(false);
|
||||||
|
|
||||||
|
if (!permission?.granted) {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={{ textAlign: "center" }}>
|
||||||
|
We need your permission to use the camera
|
||||||
|
</Text>
|
||||||
|
<Button onPress={requestPermission} title="Grant permission" />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const takePicture = async () => {
|
||||||
|
const photo = await ref.current?.takePictureAsync();
|
||||||
|
setUri(photo?.uri || null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const recordVideo = async () => {
|
||||||
|
if (recording) {
|
||||||
|
setRecording(false);
|
||||||
|
ref.current?.stopRecording();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setRecording(true);
|
||||||
|
const video = await ref.current?.recordAsync();
|
||||||
|
console.log({ video });
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleMode = () => {
|
||||||
|
setMode((prev) => (prev === "picture" ? "video" : "picture"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleFacing = () => {
|
||||||
|
setFacing((prev) => (prev === "back" ? "front" : "back"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPicture = () => {
|
||||||
|
console.log("renderPicture", uri);
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Image
|
||||||
|
source={uri ? uri : null}
|
||||||
|
contentFit="contain"
|
||||||
|
style={{ width: 340, aspectRatio: 1 }}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<StackCustom>
|
||||||
|
<ButtonCustom onPress={() => setUri(null)} title="Foto ulang" />
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Update foto");
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
title="Update Foto"
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderCameraUI = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.cameraOverlay}>
|
||||||
|
<View style={styles.shutterContainer}>
|
||||||
|
<Pressable onPress={toggleMode}>
|
||||||
|
{mode === "picture" ? (
|
||||||
|
<AntDesign name="picture" size={32} color="white" />
|
||||||
|
) : (
|
||||||
|
<Feather name="video" size={32} color="white" />
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Pressable onPress={mode === "picture" ? takePicture : recordVideo}>
|
||||||
|
{({ pressed }) => (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.shutterBtn,
|
||||||
|
{
|
||||||
|
opacity: pressed ? 0.5 : 1,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.shutterBtnInner,
|
||||||
|
{
|
||||||
|
backgroundColor: mode === "picture" ? "white" : "red",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Pressable onPress={toggleFacing}>
|
||||||
|
<FontAwesome6 name="rotate-left" size={32} color="white" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{uri ? (
|
||||||
|
<ViewWrapper>
|
||||||
|
<View style={styles.container}>{renderPicture()}</View>
|
||||||
|
</ViewWrapper>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<CameraView
|
||||||
|
style={styles.camera}
|
||||||
|
ref={ref}
|
||||||
|
mode={mode}
|
||||||
|
facing={facing}
|
||||||
|
mute={false}
|
||||||
|
responsiveOrientationWhenOrientationLocked
|
||||||
|
/>
|
||||||
|
{renderCameraUI()}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
flex: 1,
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
cameraOverlay: {
|
||||||
|
...StyleSheet.absoluteFillObject,
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
padding: 44,
|
||||||
|
},
|
||||||
|
shutterContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
shutterBtn: {
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
borderWidth: 5,
|
||||||
|
borderColor: "white",
|
||||||
|
width: 85,
|
||||||
|
height: 85,
|
||||||
|
borderRadius: 45,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
shutterBtnInner: {
|
||||||
|
width: 70,
|
||||||
|
height: 70,
|
||||||
|
borderRadius: 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
47
app/(application)/(user)/profile/[id]/update-background.tsx
Normal file
47
app/(application)/(user)/profile/[id]/update-background.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { Image } from "react-native";
|
||||||
|
|
||||||
|
export default function UpdateBackgroundProfile() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Simpan foto background >>", id);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<BaseBox
|
||||||
|
style={{ alignItems: "center", justifyContent: "center", height: 250 }}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={DUMMY_IMAGE.background}
|
||||||
|
resizeMode="cover"
|
||||||
|
style={{ width: "100%", height: "100%", borderRadius: 10 }}
|
||||||
|
/>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.navigate(`/(application)/take-picture/${id}`)}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
47
app/(application)/(user)/profile/[id]/update-photo.tsx
Normal file
47
app/(application)/(user)/profile/[id]/update-photo.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
AvatarCustom,
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function UpdatePhotoProfile() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Simpan foto profile >>", id);
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<BaseBox
|
||||||
|
style={{ alignItems: "center", justifyContent: "center", height: 250 }}
|
||||||
|
>
|
||||||
|
<AvatarCustom size="xl" />
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Update photo >>", id);
|
||||||
|
router.navigate(`/(application)/take-picture/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
|
||||||
|
{/* <Spacing />
|
||||||
|
<ButtonCustom>Test</ButtonCustom> */}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
34
app/(application)/(user)/profile/_layout.tsx
Normal file
34
app/(application)/(user)/profile/_layout.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { BackButton } from "@/components";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
|
export default function ProfileLayout() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack
|
||||||
|
screenOptions={{
|
||||||
|
headerStyle: GStyles.headerStyle,
|
||||||
|
headerTitleStyle: GStyles.headerTitleStyle,
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerBackButtonDisplayMode: "minimal",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* <Stack.Screen name="[id]/index" options={{ headerShown: false }} /> */}
|
||||||
|
<Stack.Screen name="[id]/edit" options={{ title: "Edit Profile" }} />
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/update-photo"
|
||||||
|
options={{ title: "Update Foto" }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/update-background"
|
||||||
|
options={{ title: "Update Latar Belakang" }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/create"
|
||||||
|
options={{ title: "Buat Profile" }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
100
app/(application)/(user)/user-search/index.tsx
Normal file
100
app/(application)/(user)/user-search/index.tsx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import {
|
||||||
|
AvatarCustom,
|
||||||
|
ClickableCustom,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function UserSearch() {
|
||||||
|
function generateRandomPhoneNumber(index: number) {
|
||||||
|
let prefix;
|
||||||
|
|
||||||
|
// Menentukan prefix berdasarkan index genap atau ganjil
|
||||||
|
if (index % 2 === 0) {
|
||||||
|
const evenPrefixes = ["6288", "6289", "6281"];
|
||||||
|
prefix = evenPrefixes[Math.floor(Math.random() * evenPrefixes.length)];
|
||||||
|
} else {
|
||||||
|
const oddPrefixes = ["6285", "6283"];
|
||||||
|
prefix = oddPrefixes[Math.floor(Math.random() * oddPrefixes.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menghitung panjang sisa nomor acak (antara 10 - 12 digit)
|
||||||
|
const remainingLength = Math.floor(Math.random() * 3) + 10; // 10, 11, atau 12
|
||||||
|
|
||||||
|
// Membuat sisa nomor acak
|
||||||
|
let randomNumber = "";
|
||||||
|
for (let i = 0; i < remainingLength; i++) {
|
||||||
|
randomNumber += Math.floor(Math.random() * 10); // Digit acak antara 0-9
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menggabungkan prefix dan sisa nomor
|
||||||
|
return prefix + randomNumber;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper
|
||||||
|
headerComponent={
|
||||||
|
<TextInputCustom
|
||||||
|
iconLeft={
|
||||||
|
<Ionicons
|
||||||
|
name="search"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.placeholder}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
placeholder="Cari Pengguna"
|
||||||
|
borderRadius={50}
|
||||||
|
containerStyle={{ marginBottom: 0 }}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
{Array.from({ length: 20 }).map((e, index) => {
|
||||||
|
return (
|
||||||
|
<Grid key={index}>
|
||||||
|
<Grid.Col span={2}>
|
||||||
|
<AvatarCustom href={`/profile/${index}`}/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={9}>
|
||||||
|
<TextCustom size="large">Nama user {index}</TextCustom>
|
||||||
|
<TextCustom size="small">
|
||||||
|
+{generateRandomPhoneNumber(index)}
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={1}
|
||||||
|
style={{
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClickableCustom
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Ke Profile");
|
||||||
|
router.push(`/profile/${index}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name="chevron-forward"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
</ClickableCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing height={50} />
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
43
app/(application)/(user)/voting/(tabs)/_layout.tsx
Normal file
43
app/(application)/(user)/voting/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
IconContribution,
|
||||||
|
IconHistory,
|
||||||
|
IconHome,
|
||||||
|
IconStatus,
|
||||||
|
} from "@/components/_Icon";
|
||||||
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
|
import { Tabs } from "expo-router";
|
||||||
|
|
||||||
|
export default function VotingTabsLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs screenOptions={TabsStyles}>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: "Beranda",
|
||||||
|
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="status"
|
||||||
|
options={{
|
||||||
|
title: "Status",
|
||||||
|
tabBarIcon: ({ color }) => <IconStatus color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="contribution"
|
||||||
|
options={{
|
||||||
|
title: "Kontribusi",
|
||||||
|
tabBarIcon: ({ color }) => <IconContribution color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="history"
|
||||||
|
options={{
|
||||||
|
title: "Riwayat",
|
||||||
|
tabBarIcon: ({ color }) => <IconHistory color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
17
app/(application)/(user)/voting/(tabs)/contribution.tsx
Normal file
17
app/(application)/(user)/voting/(tabs)/contribution.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import {
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
||||||
|
|
||||||
|
export default function VotingContribution() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{Array.from({ length: 5 }).map((_, index) => (
|
||||||
|
<Voting_BoxPublishSection
|
||||||
|
key={index}
|
||||||
|
href={`/voting/${index}/contribution`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
37
app/(application)/(user)/voting/(tabs)/history.tsx
Normal file
37
app/(application)/(user)/voting/(tabs)/history.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { ViewWrapper } from "@/components";
|
||||||
|
import TabsTwoHeaderCustom from "@/components/_ShareComponent/TabsTwoHeaderCustom";
|
||||||
|
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function VotingHistory() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
headerComponent={
|
||||||
|
<TabsTwoHeaderCustom
|
||||||
|
leftValue="all"
|
||||||
|
rightValue="main"
|
||||||
|
leftText="Semua Riwayat"
|
||||||
|
rightText="Riwayat Saya"
|
||||||
|
activeCategory={activeCategory}
|
||||||
|
handlePress={handlePress}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Voting_BoxPublishSection
|
||||||
|
key={index}
|
||||||
|
id={activeCategory as any}
|
||||||
|
href={`/voting/${index}/history`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
app/(application)/(user)/voting/(tabs)/index.tsx
Normal file
23
app/(application)/(user)/voting/(tabs)/index.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
FloatingButton,
|
||||||
|
SearchInput,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function VotingBeranda() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton onPress={() => router.push("/voting/create")} />
|
||||||
|
}
|
||||||
|
headerComponent={<SearchInput placeholder="Cari voting" />}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 5 }).map((_, index) => (
|
||||||
|
<Voting_BoxPublishSection key={index} href={`/voting/${index}`} />
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
60
app/(application)/(user)/voting/(tabs)/status.tsx
Normal file
60
app/(application)/(user)/voting/(tabs)/status.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import {
|
||||||
|
BadgeCustom,
|
||||||
|
BaseBox,
|
||||||
|
ScrollableCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function VotingStatus() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
|
"publish"
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollComponent = (
|
||||||
|
<ScrollableCustom
|
||||||
|
data={masterStatus.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as any}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper headerComponent={scrollComponent} hideFooter>
|
||||||
|
{Array.from({ length: 10 }).map((_, i) => (
|
||||||
|
<BaseBox
|
||||||
|
key={i}
|
||||||
|
paddingTop={20}
|
||||||
|
paddingBottom={20}
|
||||||
|
href={`/voting/${i}/${activeCategory}/detail`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center" bold truncate size="large">
|
||||||
|
Lorem ipsum dolor sit {activeCategory}
|
||||||
|
</TextCustom>
|
||||||
|
<BadgeCustom
|
||||||
|
style={{ width: "70%", alignSelf: "center" }}
|
||||||
|
variant="light"
|
||||||
|
>
|
||||||
|
{dayjs().format("DD/MM/YYYY")} -{" "}
|
||||||
|
{dayjs().add(1, "day").format("DD/MM/YYYY")}
|
||||||
|
</BadgeCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
108
app/(application)/(user)/voting/[id]/[status]/detail.tsx
Normal file
108
app/(application)/(user)/voting/[id]/[status]/detail.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
Spacing,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconArchive, IconContribution, IconEdit } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import { Voting_BoxDetailSection } from "@/screens/Voting/BoxDetailSection";
|
||||||
|
import Voting_ButtonStatusSection from "@/screens/Voting/ButtonStatusSection";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function VotingDetailStatus() {
|
||||||
|
const { id, status } = useLocalSearchParams();
|
||||||
|
const [openDrawerDraft, setOpenDrawerDraft] = useState(false);
|
||||||
|
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
|
||||||
|
|
||||||
|
const handlePressDraft = (item: IMenuDrawerItem) => {
|
||||||
|
console.log("PATH >> ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerDraft(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePressPublish = (item: IMenuDrawerItem) => {
|
||||||
|
if (item.path === "") {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Update Arsip",
|
||||||
|
message: "Apakah Anda yakin ingin mengarsipkan voting ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail ${status}`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () =>
|
||||||
|
status === "draft" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerDraft(true)} />
|
||||||
|
) : status === "publish" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
) : null,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Voting_BoxDetailSection />
|
||||||
|
<Voting_ButtonStatusSection status={status as string} />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Draft Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerDraft}
|
||||||
|
closeDrawer={() => setOpenDrawerDraft(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconEdit />,
|
||||||
|
label: "Edit",
|
||||||
|
path: `/voting/${id}/edit`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePressDraft as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconContribution />,
|
||||||
|
label: "Daftar Kontributor",
|
||||||
|
path: `/voting/${id}/list-of-contributor`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <IconArchive />,
|
||||||
|
label: "Update Arsip",
|
||||||
|
path: "" as any,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
65
app/(application)/(user)/voting/[id]/contribution.tsx
Normal file
65
app/(application)/(user)/voting/[id]/contribution.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
Spacing,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconContribution } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import { Voting_BoxDetailContributionSection } from "@/screens/Voting/BoxDetailContribution";
|
||||||
|
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function VotingDetailContribution() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
|
||||||
|
|
||||||
|
const handlePressPublish = (item: IMenuDrawerItem) => {
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Detail Kontribusi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
<Voting_BoxDetailContributionSection
|
||||||
|
headerAvatar={<AvatarUsernameAndOtherComponent />}
|
||||||
|
/>
|
||||||
|
<Voting_BoxDetailHasilVotingSection />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconContribution />,
|
||||||
|
label: "Daftar Kontributor",
|
||||||
|
path: `/voting/${id}/list-of-contributor`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
78
app/(application)/(user)/voting/[id]/edit.tsx
Normal file
78
app/(application)/(user)/voting/[id]/edit.tsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
export default function VotingEdit() {
|
||||||
|
const buttonSubmit = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() =>
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit()}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Voting"
|
||||||
|
placeholder="MasukanJudul Voting"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi"
|
||||||
|
placeholder="Masukan Deskripsi"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
<DateTimePickerCustom label="Mulai Voting" required />
|
||||||
|
<DateTimePickerCustom label="Voting Berakhir" required />
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Pilihan"
|
||||||
|
placeholder="Masukan Pilihan"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "center", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<TouchableOpacity onPress={() => console.log("delete")}>
|
||||||
|
<Ionicons name="trash" size={24} color={MainColor.red} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly onPress={() => console.log("add")}>
|
||||||
|
Tambah Pilihan
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
64
app/(application)/(user)/voting/[id]/history.tsx
Normal file
64
app/(application)/(user)/voting/[id]/history.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
Spacing,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconContribution } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
|
||||||
|
import { Voting_BoxDetailHistorySection } from "@/screens/Voting/BoxDetailHistorySection";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function VotingDetailHistory() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
|
||||||
|
|
||||||
|
const handlePressPublish = (item: IMenuDrawerItem) => {
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Riwayat Voting",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<Voting_BoxDetailHistorySection
|
||||||
|
headerAvatar={<AvatarUsernameAndOtherComponent />}
|
||||||
|
/>
|
||||||
|
<Voting_BoxDetailHasilVotingSection />
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconContribution />,
|
||||||
|
label: "Daftar Kontributor",
|
||||||
|
path: `/voting/${id}/list-of-contributor`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
87
app/(application)/(user)/voting/[id]/index.tsx
Normal file
87
app/(application)/(user)/voting/[id]/index.tsx
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
InformationBox,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
StackCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconArchive, IconContribution } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
|
||||||
|
import { Voting_BoxDetailPublishSection } from "@/screens/Voting/BoxDetailPublishSection";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
export default function VotingDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
|
||||||
|
const handlePressPublish = (item: IMenuDrawerItem) => {
|
||||||
|
if (item.path === "") {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Update Arsip",
|
||||||
|
message: "Apakah Anda yakin ingin mengarsipkan voting ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail Voting`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<InformationBox text="Untuk sementara voting ini belum di buka. Voting akan dimulai sesuai dengan tanggal awal pemilihan, dan akan ditutup sesuai dengan tanggal akhir pemilihan." />
|
||||||
|
|
||||||
|
<Voting_BoxDetailPublishSection
|
||||||
|
headerAvatar={<AvatarUsernameAndOtherComponent />}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Voting_BoxDetailHasilVotingSection />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconContribution />,
|
||||||
|
label: "Daftar Kontributor",
|
||||||
|
path: `/voting/${id}/list-of-contributor`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <IconArchive />,
|
||||||
|
label: "Update Arsip",
|
||||||
|
path: "" as any,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
26
app/(application)/(user)/voting/[id]/list-of-contributor.tsx
Normal file
26
app/(application)/(user)/voting/[id]/list-of-contributor.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BadgeCustom,
|
||||||
|
BaseBox,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
|
||||||
|
export default function Voting_ListOfContributor() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox paddingTop={5} paddingBottom={5} key={index.toString()}>
|
||||||
|
<AvatarUsernameAndOtherComponent
|
||||||
|
rightComponent={
|
||||||
|
<BadgeCustom
|
||||||
|
style={{alignSelf: "flex-end" }}
|
||||||
|
>
|
||||||
|
Pilihan {index + 1}
|
||||||
|
</BadgeCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
78
app/(application)/(user)/voting/create.tsx
Normal file
78
app/(application)/(user)/voting/create.tsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
export default function VotingCreate() {
|
||||||
|
const buttonSubmit = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() =>
|
||||||
|
router.replace("/(application)/(user)/voting/(tabs)/status")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit()}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Voting"
|
||||||
|
placeholder="MasukanJudul Voting"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi"
|
||||||
|
placeholder="Masukan Deskripsi"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
<DateTimePickerCustom label="Mulai Voting" required />
|
||||||
|
<DateTimePickerCustom label="Voting Berakhir" required />
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Pilihan"
|
||||||
|
placeholder="Masukan Pilihan"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={2}
|
||||||
|
style={{ alignItems: "center", justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<TouchableOpacity onPress={() => console.log("delete")}>
|
||||||
|
<Ionicons name="trash" size={24} color={MainColor.red} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly onPress={() => console.log("add")}>
|
||||||
|
Tambah Pilihan
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,104 +1,28 @@
|
|||||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
import { BackButton } from "@/components";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { HeaderStyles } from "@/styles/header-styles";
|
||||||
import { router, Stack } from "expo-router";
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
export default function ApplicationLayout() {
|
export default function ApplicationLayout() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack
|
<Stack screenOptions={HeaderStyles}>
|
||||||
screenOptions={{
|
<Stack.Screen name="(user)" options={{ headerShown: false }} />
|
||||||
headerStyle: { backgroundColor: MainColor.darkblue },
|
|
||||||
headerTitleStyle: { color: MainColor.yellow, fontWeight: "bold" },
|
{/* Take Picture */}
|
||||||
headerTitleAlign: "center",
|
|
||||||
contentStyle: {
|
|
||||||
borderBottomColor: AccentColor.blue,
|
|
||||||
borderBottomWidth: 2,
|
|
||||||
},
|
|
||||||
headerLargeStyle: {
|
|
||||||
backgroundColor: MainColor.darkblue,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="home"
|
name="(image)/take-picture/[id]/index"
|
||||||
options={{
|
options={{
|
||||||
title: "HIPMI",
|
title: "Ambil Gambar",
|
||||||
headerLeft: () => (
|
headerLeft: () => <BackButton />,
|
||||||
<Ionicons
|
|
||||||
name="search"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
headerRight: () => (
|
|
||||||
<Ionicons
|
|
||||||
name="notifications"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Preview Image */}
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="forum/index"
|
name="(image)/preview-image/[id]/index"
|
||||||
options={{
|
options={{
|
||||||
title: "Forum",
|
title: "Preview Gambar",
|
||||||
headerLeft: () => (
|
headerLeft: () => <BackButton />,
|
||||||
<Ionicons
|
|
||||||
name="arrow-back"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack.Screen
|
|
||||||
name="maps/index"
|
|
||||||
options={{
|
|
||||||
title: "Maps",
|
|
||||||
headerLeft: () => (
|
|
||||||
<Ionicons
|
|
||||||
name="arrow-back"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack.Screen
|
|
||||||
name="market-place/index"
|
|
||||||
options={{
|
|
||||||
title: "Market Place",
|
|
||||||
headerLeft: () => (
|
|
||||||
<Ionicons
|
|
||||||
name="arrow-back"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack.Screen
|
|
||||||
name="profile/index"
|
|
||||||
options={{
|
|
||||||
title: "Profile",
|
|
||||||
headerLeft: () => (
|
|
||||||
<Ionicons
|
|
||||||
name="arrow-back"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
258
app/(application)/coba/double-scroll.tsx
Normal file
258
app/(application)/coba/double-scroll.tsx
Normal file
@@ -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<Participant[]>([]);
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
const [loadingMore, setLoadingMore] = useState<boolean>(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 (
|
||||||
|
<View style={styles.footer}>
|
||||||
|
<ActivityIndicator size="small" color="#007AFF" />
|
||||||
|
<Text style={styles.loadingText}> Memuat peserta berikutnya...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render header: detail event + info jumlah peserta
|
||||||
|
const renderHeader = () => (
|
||||||
|
<>
|
||||||
|
<View style={styles.headerContainer}>
|
||||||
|
<LeftButtonCustom path={"/"} />
|
||||||
|
<Text style={styles.title}>{event.title}</Text>
|
||||||
|
<Text style={styles.info}>📅 {event.date}</Text>
|
||||||
|
<Text style={styles.info}>📍 {event.location}</Text>
|
||||||
|
<Text style={styles.info}>👤 {event.organizer}</Text>
|
||||||
|
<Text style={styles.description}>{event.description}</Text>
|
||||||
|
|
||||||
|
<View style={styles.divider} />
|
||||||
|
|
||||||
|
<Text style={styles.sectionTitle}>
|
||||||
|
Daftar Peserta ({participants.length})
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Sub-header tambahan jika perlu */}
|
||||||
|
{participants.length === 0 ? (
|
||||||
|
<Text style={styles.empty}>Belum ada peserta yang terdaftar.</Text>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Loading awal
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ActivityIndicator size="large" color="#007AFF" style={styles.loader} />
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FlatList
|
||||||
|
data={participants}
|
||||||
|
keyExtractor={(item) => item.id.toString()}
|
||||||
|
ListHeaderComponent={renderHeader}
|
||||||
|
ListFooterComponent={renderFooter}
|
||||||
|
onEndReached={loadMore}
|
||||||
|
onEndReachedThreshold={0.5}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<View style={styles.participantItem}>
|
||||||
|
<Image source={{ uri: item.avatar }} style={styles.avatar} />
|
||||||
|
<Text style={styles.participantName}>{item.name}</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
initialNumToRender={10}
|
||||||
|
maxToRenderPerBatch={5}
|
||||||
|
windowSize={7}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
ListEmptyComponent={
|
||||||
|
<Text style={styles.empty}>Tidak ada peserta.</Text>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SafeAreaView
|
||||||
|
edges={["bottom"]}
|
||||||
|
style={{ backgroundColor: MainColor.darkblue }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -9,7 +9,11 @@ import {
|
|||||||
ScrollView,
|
ScrollView,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
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";
|
||||||
|
import CustomUploadButton from "./upload-button";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
const { width } = Dimensions.get("window");
|
const { width } = Dimensions.get("window");
|
||||||
|
|
||||||
@@ -17,7 +21,9 @@ const { width } = Dimensions.get("window");
|
|||||||
const HomeScreen = () => (
|
const HomeScreen = () => (
|
||||||
<View style={styles.screen}>
|
<View style={styles.screen}>
|
||||||
<Text style={styles.screenTitle}>Selamat Datang!</Text>
|
<Text style={styles.screenTitle}>Selamat Datang!</Text>
|
||||||
<Text style={styles.screenText}>Ini adalah halaman utama aplikasi Anda</Text>
|
<Text style={styles.screenText}>
|
||||||
|
Ini adalah halaman utama aplikasi Anda
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
const SearchScreen = () => (
|
const SearchScreen = () => (
|
||||||
@@ -66,9 +72,7 @@ const CustomTab = ({ icon, label, isActive, onPress }: any) => (
|
|||||||
|
|
||||||
// Main Custom Tab Navigator
|
// Main Custom Tab Navigator
|
||||||
const CustomTabNavigator = () => {
|
const CustomTabNavigator = () => {
|
||||||
const [activeTab, setActiveTab] = React.useState(
|
const [activeTab, setActiveTab] = React.useState("home");
|
||||||
'home'
|
|
||||||
);
|
|
||||||
const [showHome, setShowHome] = React.useState(true);
|
const [showHome, setShowHome] = React.useState(true);
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
@@ -86,7 +90,7 @@ const CustomTabNavigator = () => {
|
|||||||
activeIcon: "notifications",
|
activeIcon: "notifications",
|
||||||
label: "Forum",
|
label: "Forum",
|
||||||
component: NotificationScreen,
|
component: NotificationScreen,
|
||||||
path: "/(application)/(home-tabs)/forum",
|
path: "/forum",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "profile",
|
id: "profile",
|
||||||
@@ -94,55 +98,87 @@ const CustomTabNavigator = () => {
|
|||||||
activeIcon: "person",
|
activeIcon: "person",
|
||||||
label: "Katalog",
|
label: "Katalog",
|
||||||
component: ProfileScreen,
|
component: ProfileScreen,
|
||||||
path: "/(application)/(home-tabs)/katalog",
|
path: "/profile",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// Function untuk handle tab press
|
// Function untuk handle tab press
|
||||||
const handleTabPress = (tabId: string) => {
|
const handleTabPress = (tabId: string) => {
|
||||||
setActiveTab(tabId);
|
setActiveTab(tabId);
|
||||||
// setShowHome(false); // Hide home when any tab is pressed
|
setShowHome(false); // Hide home when any tab is pressed
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine which component to show
|
// Determine which component to show
|
||||||
const getActiveComponent = () => {
|
const getActiveComponent = () => {
|
||||||
if (showHome || activeTab === "home") {
|
if (showHome || activeTab === "home") {
|
||||||
return HomeScreen;
|
return HomeScreen;
|
||||||
}
|
}
|
||||||
const selectedTab = tabs.find((tab) => tab.id === activeTab);
|
// const selectedTab = tabs.find((tab) => tab.id === activeTab);
|
||||||
return selectedTab ? selectedTab.component : HomeScreen;
|
// return selectedTab ? selectedTab.component : HomeScreen;
|
||||||
|
return HomeScreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ActiveComponent = getActiveComponent();
|
const ActiveComponent = getActiveComponent();
|
||||||
|
|
||||||
return (
|
const handleImageUpload = (file: any) => {
|
||||||
<View style={styles.container}>
|
console.log("Gambar dipilih:", file);
|
||||||
{/* Content Area */}
|
// Upload ke server
|
||||||
<ScrollView>
|
};
|
||||||
<View style={styles.content}>
|
|
||||||
<ActiveComponent />
|
|
||||||
</View>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
{/* Custom Tab Bar */}
|
const handlePdfOrPngUpload = (file: any) => {
|
||||||
<View style={styles.tabBar}>
|
console.log("PDF atau PNG dipilih:", file);
|
||||||
<View style={styles.tabContainer}>
|
};
|
||||||
{tabs.map((e) => (
|
|
||||||
<CustomTab
|
return (
|
||||||
key={e.id}
|
<>
|
||||||
icon={activeTab === e.id ? e.activeIcon : e.icon}
|
<SafeAreaView edges={["bottom"]} style={styles.container}>
|
||||||
label={e.label}
|
<Stack.Screen
|
||||||
isActive={activeTab === e.id && !showHome}
|
options={{
|
||||||
onPress={() => {
|
title: "Custom Tab Navigator",
|
||||||
// handleTabPress(e.id);
|
}}
|
||||||
router.push(e.path as any);
|
/>
|
||||||
}}
|
<EventDetailScreen />
|
||||||
/>
|
|
||||||
))}
|
<CustomUploadButton
|
||||||
</View>
|
allowedExtensions={["jpeg", "png"]}
|
||||||
</View>
|
buttonTitle="Unggah Gambar (JPEG/PNG)"
|
||||||
</View>
|
onFileSelected={handleImageUpload}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hanya PDF atau PNG */}
|
||||||
|
<CustomUploadButton
|
||||||
|
allowedExtensions={["pdf"]}
|
||||||
|
buttonTitle="Unggah PDF atau PNG"
|
||||||
|
onFileSelected={handlePdfOrPngUpload}
|
||||||
|
/>
|
||||||
|
</SafeAreaView>
|
||||||
|
</>
|
||||||
|
// <View style={styles.container}>
|
||||||
|
// {/* Content Area */}
|
||||||
|
// <ScrollView>
|
||||||
|
// <View style={styles.content}>
|
||||||
|
// <ActiveComponent />
|
||||||
|
// </View>
|
||||||
|
// </ScrollView>
|
||||||
|
|
||||||
|
// {/* Custom Tab Bar */}
|
||||||
|
// <View style={styles.tabBar}>
|
||||||
|
// <View style={styles.tabContainer}>
|
||||||
|
// {tabs.map((e) => (
|
||||||
|
// <CustomTab
|
||||||
|
// key={e.id}
|
||||||
|
// icon={activeTab === e.id ? e.activeIcon : e.icon}
|
||||||
|
// label={e.label}
|
||||||
|
// isActive={activeTab === e.id && !showHome}
|
||||||
|
// onPress={() => {
|
||||||
|
// handleTabPress(e.id);
|
||||||
|
// router.push(e.path as any);
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// ))}
|
||||||
|
// </View>
|
||||||
|
// </View>
|
||||||
|
// </View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
99
app/(application)/coba/upload-button.tsx
Normal file
99
app/(application)/coba/upload-button.tsx
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// components/CustomUploadButton.tsx
|
||||||
|
import React from 'react';
|
||||||
|
import { Button, Alert, View, StyleSheet } from 'react-native';
|
||||||
|
import * as DocumentPicker from 'expo-document-picker';
|
||||||
|
import { isValidFileType, getMimeType } from '../../../utils/fileValidation';
|
||||||
|
|
||||||
|
interface UploadButtonProps {
|
||||||
|
allowedExtensions: string[];
|
||||||
|
buttonTitle?: string;
|
||||||
|
onFileSelected?: (file: {
|
||||||
|
uri: string;
|
||||||
|
name: string;
|
||||||
|
size: number | null;
|
||||||
|
mimeType: string;
|
||||||
|
}) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomUploadButton: React.FC<UploadButtonProps> = ({
|
||||||
|
allowedExtensions,
|
||||||
|
buttonTitle = 'Pilih File',
|
||||||
|
onFileSelected,
|
||||||
|
}) => {
|
||||||
|
const handlePickFile = async () => {
|
||||||
|
try {
|
||||||
|
// Coba filter dengan MIME type jika memungkinkan
|
||||||
|
const typeFilter = getMimeTypeFilter(allowedExtensions);
|
||||||
|
|
||||||
|
const result = await DocumentPicker.getDocumentAsync({
|
||||||
|
type: typeFilter, // Ini membantu memfilter di UI pemilih
|
||||||
|
copyToCacheDirectory: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.canceled) {
|
||||||
|
Alert.alert('Dibatalkan', 'Tidak ada file yang dipilih.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = result.assets[0];
|
||||||
|
const { uri, name, size } = file;
|
||||||
|
|
||||||
|
// Validasi ekstensi secara manual (cadangan jika MIME tidak akurat)
|
||||||
|
if (!isValidFileType(name, allowedExtensions)) {
|
||||||
|
Alert.alert(
|
||||||
|
'Format Tidak Didukung',
|
||||||
|
`Hanya file dengan ekstensi berikut yang diperbolehkan: ${allowedExtensions.join(', ')}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mimeType = getMimeType(name);
|
||||||
|
|
||||||
|
// Kirim data file ke komponen induk
|
||||||
|
if (onFileSelected) {
|
||||||
|
onFileSelected({ uri, name, size: size || null, mimeType });
|
||||||
|
}
|
||||||
|
|
||||||
|
Alert.alert('Berhasil', `File ${name} berhasil dipilih!`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error picking file:', error);
|
||||||
|
Alert.alert('Error', 'Terjadi kesalahan saat memilih file.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Button title={buttonTitle} onPress={handlePickFile} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fungsi bantu untuk menghasilkan MIME type filter dari ekstensi
|
||||||
|
const getMimeTypeFilter = (extensions: string[]): string => {
|
||||||
|
const mimeTypes: string[] = [];
|
||||||
|
extensions.forEach((ext) => {
|
||||||
|
switch (ext.toLowerCase()) {
|
||||||
|
case 'jpg':
|
||||||
|
case 'jpeg':
|
||||||
|
if (!mimeTypes.includes('image/jpeg')) mimeTypes.push('image/jpeg');
|
||||||
|
break;
|
||||||
|
case 'png':
|
||||||
|
if (!mimeTypes.includes('image/png')) mimeTypes.push('image/png');
|
||||||
|
break;
|
||||||
|
case 'pdf':
|
||||||
|
if (!mimeTypes.includes('application/pdf')) mimeTypes.push('application/pdf');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mimeTypes.push('*/*'); // fallback
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mimeTypes.length > 0 ? mimeTypes.join(',') : '*/*';
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
marginVertical: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CustomUploadButton;
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function Event() {
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<Text>Event</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function Forum() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<View>
|
|
||||||
<Text>Forum</Text>
|
|
||||||
</View>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function Maps() {
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<Text>Maps</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function MarketPlace() {
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<Text>Market Place</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function Profile() {
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<Text>Profile</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,16 @@
|
|||||||
import { Text, View } from "react-native";
|
import { StackCustom, TextCustom, ViewWrapper } from "@/components";
|
||||||
|
|
||||||
export default function NotFoundScreen() {
|
export default function NotFoundScreen() {
|
||||||
return (
|
return (
|
||||||
<View>
|
<ViewWrapper>
|
||||||
<Text>Not Found</Text>
|
<StackCustom align="center" gap={0} style={{justifyContent: "center", alignItems: "center", flex: 1}}>
|
||||||
</View>
|
<TextCustom size="large" bold style={{fontSize: 100}}>
|
||||||
)
|
404
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom size="large" bold>
|
||||||
|
Sorry, File Not Found
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,32 @@
|
|||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { Stack } from "expo-router";
|
import { Stack } from "expo-router";
|
||||||
|
import "react-native-gesture-handler";
|
||||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
return (
|
return (
|
||||||
<SafeAreaProvider
|
<>
|
||||||
style={{
|
<SafeAreaProvider>
|
||||||
backgroundColor: MainColor.darkblue,
|
<Stack
|
||||||
}}
|
screenOptions={{
|
||||||
>
|
headerStyle: { backgroundColor: MainColor.darkblue },
|
||||||
<Stack
|
headerTitleStyle: { color: MainColor.yellow, fontWeight: "bold" },
|
||||||
screenOptions={{
|
headerTitleAlign: "center",
|
||||||
headerStyle: { backgroundColor: MainColor.darkblue },
|
}}
|
||||||
headerTitleStyle: { color: MainColor.yellow, fontWeight: "bold" },
|
>
|
||||||
headerTitleAlign: "center",
|
<Stack.Screen name="index" options={{ title: "" }} />
|
||||||
// contentStyle: {
|
<Stack.Screen name="+not-found" options={{ title: "" }} />
|
||||||
// borderBottomColor: AccentColor.blue,
|
<Stack.Screen
|
||||||
// borderBottomWidth: 2,
|
name="verification"
|
||||||
// },
|
options={{ title: "", headerBackVisible: false }}
|
||||||
// headerLargeStyle: {
|
/>
|
||||||
// backgroundColor: MainColor.darkblue,
|
<Stack.Screen
|
||||||
// },
|
name="register"
|
||||||
// headerShadowVisible: false,
|
options={{ title: "", headerBackVisible: false }}
|
||||||
}}
|
/>
|
||||||
>
|
<Stack.Screen name="(application)" options={{ headerShown: false }} />
|
||||||
<Stack.Screen name="index" options={{ headerShown: false }} />
|
</Stack>
|
||||||
<Stack.Screen name="verification" options={{ headerShown: false }} />
|
</SafeAreaProvider>
|
||||||
<Stack.Screen name="register" options={{ headerShown: false }} />
|
</>
|
||||||
<Stack.Screen name="(application)" options={{ headerShown: false }} />
|
|
||||||
</Stack>
|
|
||||||
</SafeAreaProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/images/constants/crowd-hipmi.png
Normal file
BIN
assets/images/constants/crowd-hipmi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 331 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user