Compare commits
20 Commits
voting/25-
...
donation/1
| Author | SHA1 | Date | |
|---|---|---|---|
| 25e495cdf1 | |||
| 0eebe64647 | |||
| db0f4246b6 | |||
| 16462c4214 | |||
| 8e31df660a | |||
| cc35bc6907 | |||
| 2931f6ba55 | |||
| 7205cb0736 | |||
| 54fc2a3d02 | |||
| 56d074260e | |||
| b3be6a7f53 | |||
| c863c04fb4 | |||
| a43ddaa9d6 | |||
| 927db87749 | |||
| 8a514d2670 | |||
| 554428b7b4 | |||
| befbd1a47d | |||
| c9a1ac1db5 | |||
| 4bcfcb5f5a | |||
| f21ff744d3 |
25
app/(application)/(file)/[id].tsx
Normal file
25
app/(application)/(file)/[id].tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { BackButton, ViewWrapper } from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { FontAwesome } from "@expo/vector-icons";
|
||||||
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
|
export default function FileScreen() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "File",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<FontAwesome
|
||||||
|
name="file-pdf-o"
|
||||||
|
size={300}
|
||||||
|
style={{ alignSelf: "center" }}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { BackButton } from "@/components";
|
import { BackButton } from "@/components";
|
||||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
import { HeaderStyles } from "@/styles/header-styles";
|
import { HeaderStyles } from "@/styles/header-styles";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { router, Stack } from "expo-router";
|
import { router, Stack } from "expo-router";
|
||||||
@@ -147,7 +148,6 @@ export default function UserLayout() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
{/* ========== End Collaboration Section ========= */}
|
{/* ========== End Collaboration Section ========= */}
|
||||||
|
|
||||||
{/* ========== Voting Section ========= */}
|
{/* ========== Voting Section ========= */}
|
||||||
@@ -165,17 +165,205 @@ export default function UserLayout() {
|
|||||||
headerLeft: () => <BackButton path="/home" />,
|
headerLeft: () => <BackButton path="/home" />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
{/* <Stack.Screen
|
|
||||||
name="voting/[id]/edit"
|
name="voting/[id]/edit"
|
||||||
options={{
|
options={{
|
||||||
title: "Edit Voting",
|
title: "Edit Voting",
|
||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
}}
|
}}
|
||||||
/> */}
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="voting/[id]/list-of-contributor"
|
||||||
|
options={{
|
||||||
|
title: "Daftar Kontributor",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* ========== End Voting Section ========= */}
|
{/* ========== 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 />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/index"
|
||||||
|
options={{
|
||||||
|
title: "Detail Investasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/edit"
|
||||||
|
options={{
|
||||||
|
title: "Edit Investasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/edit-prospectus"
|
||||||
|
options={{
|
||||||
|
title: "Edit Prospektus",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(document)/list-of-document"
|
||||||
|
options={{
|
||||||
|
title: "Daftar Dokumen",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(document)/add-document"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Dokumen",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(document)/edit-document"
|
||||||
|
options={{
|
||||||
|
title: "Edit Dokumen",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(news)/add-news"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Berita",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/investor"
|
||||||
|
options={{
|
||||||
|
title: "Investor",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(transaction-flow)/index"
|
||||||
|
options={{
|
||||||
|
title: "Pembelian Saham",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(transaction-flow)/select-bank"
|
||||||
|
options={{
|
||||||
|
title: "Pilih Bank",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(transaction-flow)/invoice"
|
||||||
|
options={{
|
||||||
|
title: "Invoice",
|
||||||
|
headerLeft: () => (
|
||||||
|
<Ionicons
|
||||||
|
name="close"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() =>
|
||||||
|
router.navigate(`/investment/(tabs)/transaction`)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(transaction-flow)/process"
|
||||||
|
options={{
|
||||||
|
title: "Proses",
|
||||||
|
headerLeft: () => (
|
||||||
|
<Ionicons
|
||||||
|
name="close"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() =>
|
||||||
|
router.navigate(`/investment/(tabs)/transaction`)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(transaction-flow)/success"
|
||||||
|
options={{
|
||||||
|
title: "Transaksi Berhasil",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(transaction-flow)/failed"
|
||||||
|
options={{
|
||||||
|
title: "Transaksi Gagal",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="investment/[id]/(my-holding)/[id]"
|
||||||
|
options={{
|
||||||
|
title: "Detail Saham Saya",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* ========== End Investment Section ========= */}
|
||||||
|
|
||||||
|
{/* ========== Donation Section ========= */}
|
||||||
|
<Stack.Screen
|
||||||
|
name="donation/(tabs)"
|
||||||
|
options={{
|
||||||
|
title: "Donasi",
|
||||||
|
headerLeft: () => <BackButton path="/home" />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="donation/create"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Donasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="donation/create-story"
|
||||||
|
options={{
|
||||||
|
title: "Tambah Donasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* ========== End Donation Section ========= */}
|
||||||
|
|
||||||
{/* ========== Job Section ========= */}
|
{/* ========== Job Section ========= */}
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="job/create"
|
name="job/create"
|
||||||
|
|||||||
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/(tabs)",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
37
app/(application)/(user)/donation/(tabs)/_layout.tsx
Normal file
37
app/(application)/(user)/donation/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { IconHome, IconStatus } from "@/components/_Icon";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
|
import {
|
||||||
|
FontAwesome5
|
||||||
|
} from "@expo/vector-icons";
|
||||||
|
import { Tabs } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentTabsLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs screenOptions={TabsStyles}>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: "Beranda",
|
||||||
|
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="status"
|
||||||
|
options={{
|
||||||
|
title: "Galang Dana",
|
||||||
|
tabBarIcon: ({ color }) => <IconStatus color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="my-donation"
|
||||||
|
options={{
|
||||||
|
title: "Donasi Saya",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<FontAwesome5 name="donate" color={color} size={ICON_SIZE_SMALL} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
56
app/(application)/(user)/donation/(tabs)/index.tsx
Normal file
56
app/(application)/(user)/donation/(tabs)/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
FloatingButton,
|
||||||
|
Grid,
|
||||||
|
ProgressCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function DonationBeranda() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper
|
||||||
|
hideFooter
|
||||||
|
floatingButton={
|
||||||
|
<FloatingButton onPress={() => router.push("/donation/create")} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingTop={7}
|
||||||
|
paddingBottom={7}
|
||||||
|
href={`/investment/${index}`}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<DummyLandscapeImage height={100} />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<StackCustom>
|
||||||
|
<View>
|
||||||
|
<TextCustom truncate>
|
||||||
|
Judul Donasi: Lorem ipsum dolor sit amet consectetur
|
||||||
|
adipisicing elit.
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom size="small">Sisa hari: 0</TextCustom>
|
||||||
|
</View>
|
||||||
|
<ProgressCustom value={(index % 5) * 20} size="lg" />
|
||||||
|
{/* <TextCustom>
|
||||||
|
Terkumpul : Rp 300.000
|
||||||
|
</TextCustom> */}
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
60
app/(application)/(user)/donation/(tabs)/my-donation.tsx
Normal file
60
app/(application)/(user)/donation/(tabs)/my-donation.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import {
|
||||||
|
BadgeCustom,
|
||||||
|
BaseBox,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function DonationMyDonation() {
|
||||||
|
const randomStatusData = Array.from({ length: 10 }, () => {
|
||||||
|
const randomIndex = Math.floor(
|
||||||
|
Math.random() * dummyMasterStatusTransaction.length
|
||||||
|
);
|
||||||
|
return dummyMasterStatusTransaction[randomIndex];
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{randomStatusData.map((item, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingTop={7}
|
||||||
|
paddingBottom={7}
|
||||||
|
href={`/investment/${index}`}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<DummyLandscapeImage height={100} />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<View>
|
||||||
|
<TextCustom truncate>
|
||||||
|
Judul Donasi: Lorem ipsum dolor sit amet consectetur
|
||||||
|
adipisicing elit.
|
||||||
|
</TextCustom>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<TextCustom>Donasi Saya</TextCustom>
|
||||||
|
<TextCustom bold color="yellow">
|
||||||
|
Rp. 7.500.000
|
||||||
|
</TextCustom>
|
||||||
|
</View>
|
||||||
|
<BadgeCustom variant="light" color={item.color} fullWidth>
|
||||||
|
{item.label}
|
||||||
|
</BadgeCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
74
app/(application)/(user)/donation/(tabs)/status.tsx
Normal file
74
app/(application)/(user)/donation/(tabs)/status.tsx
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import {
|
||||||
|
Grid,
|
||||||
|
BaseBox,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
ScrollableCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function DonationStatus() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
|
"publish"
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollComponent = (
|
||||||
|
<ScrollableCustom
|
||||||
|
data={dummyMasterStatus.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as any}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter headerComponent={scrollComponent}>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingTop={7}
|
||||||
|
paddingBottom={7}
|
||||||
|
href={`/investment/${index}`}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<DummyLandscapeImage height={100} />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom truncate>
|
||||||
|
Judul Donasi: {activeCategory} Lorem ipsum dolor sit amet
|
||||||
|
consectetur adipisicing elit.
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<TextCustom>Target Dana</TextCustom>
|
||||||
|
<TextCustom bold color="yellow">
|
||||||
|
Rp. 7.500.000
|
||||||
|
</TextCustom>
|
||||||
|
</View>
|
||||||
|
{/* <TextCustom>
|
||||||
|
Terkumpul : Rp 300.000
|
||||||
|
</TextCustom> */}
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
64
app/(application)/(user)/donation/create-story.tsx
Normal file
64
app/(application)/(user)/donation/create-story.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import {
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function DonationCreateStory() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="Cerita Anda adalah kunci untuk menginspirasi kebaikan. Jelaskan dengan jujur dan jelas tujuan penggalangan dana ini agar calon donatur memahami dampak positif yang dapat mereka wujudkan melalui kontribusi mereka." />
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Pembukaan Cerita"
|
||||||
|
placeholder="Masukkan pembukaan cerita"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Tujuan Donasi"
|
||||||
|
placeholder="Masukkan tujuan donasi"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly onPress={() => {}} icon="upload">
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
|
||||||
|
<Spacing height={40} />
|
||||||
|
<InformationBox text="Pastikan Anda mengisi nama bank dan nomor rekening dengan benar. Informasi ini akan membantu admin memverifikasi dan memproses penggalangan dana Anda dengan cepat dan tepat setelah penggalangan dana dipublikasikan." />
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nama Bank"
|
||||||
|
placeholder="Masukkan nama bank"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nomor Rekening"
|
||||||
|
placeholder="Masukkan nomor rekening"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
router.navigate(`/donation/(tabs)/status`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
70
app/(application)/(user)/donation/create.tsx
Normal file
70
app/(application)/(user)/donation/create.tsx
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
SelectCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { dummyDonasiDurasi } from "@/lib/dummy-data/donasi/durasi";
|
||||||
|
import { dummyDonasiKategori } from "@/lib/dummy-data/donasi/kategori";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function DonationCreate() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="Lengkapi semua data di bawah untuk selanjutnya mengisi cerita penggalangan dana." />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Donasi"
|
||||||
|
placeholder="Masukkan Judul Donasi"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextInputCustom
|
||||||
|
label="Target Donasi"
|
||||||
|
placeholder="Masukkan Target Donasi"
|
||||||
|
required
|
||||||
|
keyboardType="numeric"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectCustom
|
||||||
|
data={dummyDonasiKategori.map((item) => ({
|
||||||
|
label: item.label,
|
||||||
|
value: item.value,
|
||||||
|
}))}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
label="Pilih Kategori Donasi"
|
||||||
|
placeholder="Pilih Kategori Donasi"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectCustom
|
||||||
|
data={dummyDonasiDurasi.map((item) => ({
|
||||||
|
label: item.label,
|
||||||
|
value: item.value,
|
||||||
|
}))}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
label="Pilih Durasi Donasi"
|
||||||
|
placeholder="Pilih Durasi Donasi"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly onPress={() => {
|
||||||
|
router.push("/(application)/(image)/take-picture/123")
|
||||||
|
}} icon="upload">
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
<ButtonCustom onPress={() => {
|
||||||
|
router.push("/donation/create-story")
|
||||||
|
}}>Selanjutnya</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
BoxWithHeaderSection,
|
BoxWithHeaderSection,
|
||||||
Grid,
|
Grid,
|
||||||
ScrollableCustom,
|
ScrollableCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom
|
TextCustom
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function EventStatus() {
|
export default function EventStatus() {
|
||||||
@@ -23,7 +23,7 @@ export default function EventStatus() {
|
|||||||
|
|
||||||
const scrollComponent = (
|
const scrollComponent = (
|
||||||
<ScrollableCustom
|
<ScrollableCustom
|
||||||
data={masterStatus.map((e, i) => ({
|
data={dummyMasterStatus.map((e, i) => ({
|
||||||
id: i,
|
id: i,
|
||||||
label: e.label,
|
label: e.label,
|
||||||
value: e.value,
|
value: e.value,
|
||||||
|
|||||||
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} href={`/investment/${index}`}>
|
||||||
|
<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>;
|
||||||
50
app/(application)/(user)/investment/(tabs)/my-holding.tsx
Normal file
50
app/(application)/(user)/investment/(tabs)/my-holding.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
ProgressCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
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} onPress={() => router.push(`/investment/${index}/(my-holding)/holding-${index}`)}>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
||||||
39
app/(application)/(user)/investment/(tabs)/portofolio.tsx
Normal file
39
app/(application)/(user)/investment/(tabs)/portofolio.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { ScrollableCustom, ViewWrapper } from "@/components";
|
||||||
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
|
import Investment_StatusBox from "@/screens/Invesment/StatusBox";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
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={dummyMasterStatus.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) => (
|
||||||
|
<Investment_StatusBox
|
||||||
|
key={index}
|
||||||
|
id={index.toString()}
|
||||||
|
status={activeCategory as string}
|
||||||
|
href={`/investment/${index}/${activeCategory}/detail`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
81
app/(application)/(user)/investment/(tabs)/transaction.tsx
Normal file
81
app/(application)/(user)/investment/(tabs)/transaction.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
BadgeCustom,
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function InvestmentTransaction() {
|
||||||
|
const randomStatusData = Array.from({ length: 10 }, () => {
|
||||||
|
const randomIndex = Math.floor(
|
||||||
|
Math.random() * dummyMasterStatusTransaction.length
|
||||||
|
);
|
||||||
|
return dummyMasterStatusTransaction[randomIndex];
|
||||||
|
});
|
||||||
|
|
||||||
|
const handlePress = (value: string) => {
|
||||||
|
if (value === "menunggu") {
|
||||||
|
router.push(`/investment/${value}/(transaction-flow)/invoice`);
|
||||||
|
} else if (value === "proses") {
|
||||||
|
router.push(`/investment/${value}/(transaction-flow)/process`);
|
||||||
|
} else if (value === "berhasil") {
|
||||||
|
router.push(`/investment/${value}/(transaction-flow)/success`);
|
||||||
|
} else if (value === "gagal") {
|
||||||
|
router.push(`/investment/${value}/(transaction-flow)/failed`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper hideFooter>
|
||||||
|
{randomStatusData.map((item, i) => (
|
||||||
|
<BaseBox
|
||||||
|
key={i}
|
||||||
|
paddingTop={7}
|
||||||
|
paddingBottom={7}
|
||||||
|
onPress={() => {
|
||||||
|
handlePress(item.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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={item.color}
|
||||||
|
style={GStyles.alignSelfFlexEnd}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</BadgeCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
InformationBox,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { FontAwesome5 } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentAddDocument() {
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom onPress={() => router.back()}>Simpan</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="File dokumen bersifat opsional, jika memang ada file yang bisa membantu meyakinkan investor. Anda bisa mengupload nya." />
|
||||||
|
<Spacing />
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Dokumen"
|
||||||
|
placeholder="Masukan judul dokumen"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<CenterCustom>
|
||||||
|
<FontAwesome5
|
||||||
|
name="file-pdf"
|
||||||
|
size={30}
|
||||||
|
color={MainColor.disabled}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() =>
|
||||||
|
router.push("/(application)/(image)/take-picture/123")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
InformationBox,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { FontAwesome5 } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentEditDocument() {
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom onPress={() => router.back()}>Update</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="File dokumen bersifat opsional, jika memang ada file yang bisa membantu meyakinkan investor. Anda bisa mengupload nya." />
|
||||||
|
<Spacing />
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Dokumen"
|
||||||
|
placeholder="Masukan judul dokumen"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<CenterCustom>
|
||||||
|
<FontAwesome5
|
||||||
|
name="file-pdf"
|
||||||
|
size={30}
|
||||||
|
color={MainColor.disabled}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() =>
|
||||||
|
router.push("/(application)/(image)/take-picture/123")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { ViewWrapper } from "@/components";
|
||||||
|
import Investment_BoxDetailDocument from "@/screens/Invesment/Document/RecapBoxDetail";
|
||||||
|
|
||||||
|
export default function InvestmentListOfDocument() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Investment_BoxDetailDocument
|
||||||
|
key={index}
|
||||||
|
title={`Judul Dokumen ${index + 1}`}
|
||||||
|
href={`/(file)/${index + 1}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconEdit } from "@/components/_Icon";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import Investment_BoxDetailDocument from "@/screens/Invesment/Document/RecapBoxDetail";
|
||||||
|
import { AntDesign, Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentRecapOfDocument() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [openDrawerBox, setOpenDrawerBox] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Rekap Dokumen",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<DotButton
|
||||||
|
onPress={() => {
|
||||||
|
setOpenDrawer(true);
|
||||||
|
setOpenDrawerBox(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<Investment_BoxDetailDocument
|
||||||
|
key={index}
|
||||||
|
title={`Judul Dokumen ${index + 1}`}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="ellipsis-horizontal-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
style={{
|
||||||
|
zIndex: 10,
|
||||||
|
alignSelf: "flex-end",
|
||||||
|
}}
|
||||||
|
onPress={() => setOpenDrawerBox(true)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
href={`/(file)/${id}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* Drawer On Header */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<AntDesign
|
||||||
|
name="pluscircle"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Tambah Dokumen",
|
||||||
|
path: `/investment/${id}/(document)/add-document`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
router.push(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Drawer On Box */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerBox}
|
||||||
|
closeDrawer={() => setOpenDrawerBox(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconEdit />,
|
||||||
|
label: "Edit Dokumen",
|
||||||
|
path: `/investment/${id}/(document)/edit-document`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<Ionicons
|
||||||
|
name="trash-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Hapus Dokumen",
|
||||||
|
path: "" as any,
|
||||||
|
color: MainColor.red,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
if (item.path === ("" as any)) {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Hapus Dokumen",
|
||||||
|
message: "Apakah anda yakin ingin menghapus dokumen ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Hapus",
|
||||||
|
onPressRight: () => {
|
||||||
|
setOpenDrawerBox(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
router.push(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
154
app/(application)/(user)/investment/[id]/(my-holding)/[id].tsx
Normal file
154
app/(application)/(user)/investment/[id]/(my-holding)/[id].tsx
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import {
|
||||||
|
BackButton,
|
||||||
|
BaseBox,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
Grid,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
||||||
|
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
||||||
|
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentDetailHolding() {
|
||||||
|
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) => {
|
||||||
|
console.log("PATH >> ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bottomSection = (
|
||||||
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
|
id={id as string}
|
||||||
|
status={"publish"}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail ${_.startCase(status as string)}`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () =>
|
||||||
|
status === "draft" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerDraft(true)} />
|
||||||
|
) : status === "publish" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
) : null,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom bold>Nila Transaksi</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom bold>Rp. 7.500.000</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom bold>Saham Terbeli</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom bold>300 Lembar</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
<Invesment_DetailDataPublishSection
|
||||||
|
status={"publish"}
|
||||||
|
bottomSection={bottomSection}
|
||||||
|
/>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Draft Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerDraft}
|
||||||
|
closeDrawer={() => setOpenDrawerDraft(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconEdit />,
|
||||||
|
label: "Edit Data",
|
||||||
|
path: `/investment/${id}/edit`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<AntDesign
|
||||||
|
name="edit"
|
||||||
|
size={ICON_SIZE_MEDIUM}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Edit Prospektus",
|
||||||
|
path: `/investment/${id}/edit-prospectus`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<MaterialIcons
|
||||||
|
name="create"
|
||||||
|
size={ICON_SIZE_MEDIUM}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Update Dokumen",
|
||||||
|
path: `/investment/${id}/recap-of-document`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePressDraft as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconDocument />,
|
||||||
|
label: "Update Dokumen",
|
||||||
|
path: `/investment/${id}/recap-of-document`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <IconNews />,
|
||||||
|
label: "Update Berita",
|
||||||
|
path: `/investment/${id}/(news)/recap-of-news`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
BackButton,
|
||||||
|
BaseBox,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { IconTrash } from "@/components/_Icon/IconTrash";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentNews() {
|
||||||
|
const { id, news } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Detail Berita",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<DummyLandscapeImage />
|
||||||
|
<TextCustom bold align="center" size="large">
|
||||||
|
Judul Berita {news} Terbaru
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum
|
||||||
|
fuga mollitia laboriosam voluptatibus quos molestias, illo fugiat
|
||||||
|
esse repellat, ad officia earum numquam? Aliquid corrupti quam
|
||||||
|
tempora cum harum est!
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: "Hapus Berita",
|
||||||
|
path: `/investment/${id}/add-news`,
|
||||||
|
icon: <IconTrash />,
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Hapus Berita",
|
||||||
|
message: "Apakah Anda yakin ingin menghapus berita ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Hapus",
|
||||||
|
onPressRight: () => {
|
||||||
|
router.back();
|
||||||
|
setOpenDrawer(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
53
app/(application)/(user)/investment/[id]/(news)/add-news.tsx
Normal file
53
app/(application)/(user)/investment/[id]/(news)/add-news.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import {
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextAreaCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentAddNews() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="Pengunggahan foto ke aplikasi bersifat opsional dan tidak diwajibkan, Anda dapat menyimpan berita tanpa mengunggah foto." />
|
||||||
|
<LandscapeFrameUploaded />
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
onPress={() => {
|
||||||
|
router.push("/(application)/(image)/take-picture/123");
|
||||||
|
}}
|
||||||
|
icon="upload"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
<Spacing />
|
||||||
|
<TextInputCustom
|
||||||
|
label="Judul Berita"
|
||||||
|
placeholder="Masukan judul berita"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextAreaCustom
|
||||||
|
label="Deskripsi Berita"
|
||||||
|
placeholder="Masukan deskripsi berita"
|
||||||
|
required
|
||||||
|
showCount
|
||||||
|
maxLength={1000}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
BackButton,
|
||||||
|
BaseBox,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
import { IconPlus } from "@/components/_Icon";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentListOfNews() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Daftar Berita",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
// headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 15 }).map((_, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingBlock={5}
|
||||||
|
href={`/investment/${id}/(news)/${index + 1}`}
|
||||||
|
>
|
||||||
|
<TextCustom bold>Berita Terbaru {index + 1}</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: "Tambah Berita",
|
||||||
|
path: `/investment/${id}/add-news`,
|
||||||
|
icon: <IconPlus />,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
router.push(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
BackButton,
|
||||||
|
BaseBox,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconPlus } from "@/components/_Icon";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentRecapOfNews() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Rekap Berita",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 15 }).map((_, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingBlock={5}
|
||||||
|
href={`/investment/${id}/(news)/${index + 1}`}
|
||||||
|
>
|
||||||
|
<TextCustom bold>Berita Terbaru {index + 1}</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: "Tambah Berita",
|
||||||
|
path: `/investment/${id}/add-news`,
|
||||||
|
icon: <IconPlus />,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item) => {
|
||||||
|
router.push(item.path as any);
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { BaseBox, Grid, Spacing, StackCustom, TextCustom, ViewWrapper } from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export default function InvestmentFailed() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold align="center">
|
||||||
|
Transaksi anda gagal karena bukti transfer tidak sesuai dengan
|
||||||
|
data kami. Jika ini masalah khusus silahkan hubungi pada kontak
|
||||||
|
whatsapp kami.
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<FontAwesome6
|
||||||
|
name="whatsapp"
|
||||||
|
size={50}
|
||||||
|
color={MainColor.green}
|
||||||
|
style={GStyles.alignSelfCenter}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<TextCustom bold align="center" size="large">
|
||||||
|
Detail Transaksi
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<StackCustom>
|
||||||
|
{listData.map((item, i) => (
|
||||||
|
<Grid key={i}>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<TextCustom bold>{item.label}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={7}>
|
||||||
|
<TextCustom style={{ paddingLeft: 10 }}>
|
||||||
|
{item.value}
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Bank",
|
||||||
|
value: " BCA",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Rekening Penerima",
|
||||||
|
value: "Himpunan Pengusaha Muda Indonesia",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "No Rekening",
|
||||||
|
value: "2304235678854332",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jumlah",
|
||||||
|
value: "Rp. 1.000.000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tanggal",
|
||||||
|
value: "2022-01-01",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Lembar Terbeli",
|
||||||
|
value: "100",
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
Divider,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentInvest() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const buttonSubmit = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom onPress={() => router.push(`/investment/${id}/select-bank`)}>Beli</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit()}>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom>Sisa Lembar Saham</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom>3.000</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom>Harga Per Lembar</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom>Rp. 1.000</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col
|
||||||
|
span={6}
|
||||||
|
style={{
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Jumlah Pembelian</TextCustom>
|
||||||
|
<TextCustom bold color="yellow" size="small">
|
||||||
|
Minimum 10 lembar
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={6}
|
||||||
|
style={{
|
||||||
|
alignItems: "flex-end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextInputCustom
|
||||||
|
style={{
|
||||||
|
width: "80%",
|
||||||
|
}}
|
||||||
|
placeholder="0"
|
||||||
|
keyboardType="numeric"
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Divider />
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom>Total Harga</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom>Rp. 1.000</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
Grid,
|
||||||
|
InformationBox,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentInvoice() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<InformationBox text="Mohon transfer ke rekening dibawah" />
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom>Nama BANK</TextCustom>
|
||||||
|
<TextCustom>Nama Penerima</TextCustom>
|
||||||
|
<Spacing height={10} />
|
||||||
|
|
||||||
|
<BaseBox backgroundColor={MainColor.soft_darkblue}>
|
||||||
|
<Grid containerStyle={{ justifyContent: "center" }}>
|
||||||
|
<Grid.Col
|
||||||
|
span={8}
|
||||||
|
style={{
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom size="xlarge" bold color="yellow">
|
||||||
|
4567898765433567
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={4}
|
||||||
|
style={{
|
||||||
|
alignItems: "flex-end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonCustom>Salin</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom>Jumlah Transaksi</TextCustom>
|
||||||
|
|
||||||
|
<Spacing height={10} />
|
||||||
|
|
||||||
|
<BaseBox backgroundColor={MainColor.soft_darkblue}>
|
||||||
|
<Grid containerStyle={{ justifyContent: "center" }}>
|
||||||
|
<Grid.Col
|
||||||
|
span={8}
|
||||||
|
style={{
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom size="xlarge" bold color="yellow">
|
||||||
|
Rp. 1.000.000
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={4}
|
||||||
|
style={{
|
||||||
|
alignItems: "flex-end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonCustom>Salin</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom>Upload bukti transfer anda.</TextCustom>
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
onPress={() => {
|
||||||
|
router.push("/(application)/(image)/take-picture/123");
|
||||||
|
}}
|
||||||
|
icon="upload"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
router.push(`/investment/${id}/(transaction-flow)/process`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Saya Sudah Transfer
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing/>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { ActivityIndicator } from "react-native";
|
||||||
|
|
||||||
|
export default function InvestmentProcess() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center" bold>
|
||||||
|
Admin sedang memproses transaksimu
|
||||||
|
</TextCustom>
|
||||||
|
<ActivityIndicator size="large" color={MainColor.yellow} />
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={10} style={{justifyContent: 'center'}}>
|
||||||
|
<TextCustom size="small">
|
||||||
|
Hubungi admin jika tidak kunjung di proses! Klik pada logo
|
||||||
|
Whatsapp ini.
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={2} style={{alignItems: "flex-end"}}>
|
||||||
|
<Ionicons
|
||||||
|
name="logo-whatsapp"
|
||||||
|
size={50}
|
||||||
|
color={MainColor.green}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
|
||||||
|
import { dummyMasterBank } from "@/lib/dummy-data/_master/bank";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentSelectBank() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [value, setValue] = useState<any | number>("");
|
||||||
|
|
||||||
|
const buttonSubmit = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => router.replace(`/investment/${id}/invoice`)}
|
||||||
|
>
|
||||||
|
Pilih
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit()}>
|
||||||
|
<RadioGroup value={value} onChange={setValue}>
|
||||||
|
{dummyMasterBank.map((item) => (
|
||||||
|
<BaseBox key={item.name}>
|
||||||
|
<RadioCustom label={item.name} value={item.code} />
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export default function InvestmentSuccess() {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<FontAwesome6
|
||||||
|
name="money-bill-wave"
|
||||||
|
size={100}
|
||||||
|
color={MainColor.green}
|
||||||
|
style={GStyles.alignSelfCenter}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCustom bold align="center">
|
||||||
|
Terimakasih telah percaya pada kami untuk mengelola dana anda!
|
||||||
|
Info mengenai update Investasi ini bisa di lihat di kolom berita.
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<TextCustom bold align="center" size="large">
|
||||||
|
Detail Transaksi
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Spacing/>
|
||||||
|
|
||||||
|
|
||||||
|
<StackCustom>
|
||||||
|
{listData.map((item, i) => (
|
||||||
|
<Grid key={i}>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<TextCustom bold>{item.label}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={7}>
|
||||||
|
<TextCustom style={{paddingLeft: 10}}>{item.value}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Bank",
|
||||||
|
value: " BCA",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Rekening Penerima",
|
||||||
|
value: "Himpunan Pengusaha Muda Indonesia",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "No Rekening",
|
||||||
|
value: "2304235678854332",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jumlah",
|
||||||
|
value: "Rp. 1.000.000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tanggal",
|
||||||
|
value: "2022-01-01",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Lembar Terbeli",
|
||||||
|
value: "100",
|
||||||
|
},
|
||||||
|
];
|
||||||
136
app/(application)/(user)/investment/[id]/[status]/detail.tsx
Normal file
136
app/(application)/(user)/investment/[id]/[status]/detail.tsx
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import {
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvestasiSection";
|
||||||
|
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
||||||
|
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
||||||
|
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentDetailStatus() {
|
||||||
|
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) => {
|
||||||
|
console.log("PATH >> ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bottomSection = (
|
||||||
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
|
id={id as string}
|
||||||
|
status={status as string}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttonSection = (
|
||||||
|
<Investment_ButtonInvestasiSection id={id as string} isMine={false} />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail ${_.startCase(status as string)}`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () =>
|
||||||
|
status === "draft" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerDraft(true)} />
|
||||||
|
) : status === "publish" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
) : null,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
<Invesment_DetailDataPublishSection
|
||||||
|
status={status as string}
|
||||||
|
bottomSection={bottomSection}
|
||||||
|
buttonSection={buttonSection}
|
||||||
|
/>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Draft Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerDraft}
|
||||||
|
closeDrawer={() => setOpenDrawerDraft(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconEdit />,
|
||||||
|
label: "Edit Data",
|
||||||
|
path: `/investment/${id}/edit`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<AntDesign
|
||||||
|
name="edit"
|
||||||
|
size={ICON_SIZE_MEDIUM}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Edit Prospektus",
|
||||||
|
path: `/investment/${id}/edit-prospectus`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<MaterialIcons
|
||||||
|
name="create"
|
||||||
|
size={ICON_SIZE_MEDIUM}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Update Dokumen",
|
||||||
|
path: `/investment/${id}/(document)/recap-of-document`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePressDraft as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconDocument />,
|
||||||
|
label: "Update Dokumen",
|
||||||
|
path: `/investment/${id}/(document)/recap-of-document`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <IconNews />,
|
||||||
|
label: "Update Berita",
|
||||||
|
path: `/investment/${id}/(news)/recap-of-news`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
46
app/(application)/(user)/investment/[id]/edit-prospectus.tsx
Normal file
46
app/(application)/(user)/investment/[id]/edit-prospectus.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
InformationBox,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { FontAwesome5 } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function InvestmentEditProspectus() {
|
||||||
|
const buttonFooter = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom onPress={() => router.back()}>Update</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<InformationBox text="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan." />
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<CenterCustom>
|
||||||
|
<FontAwesome5
|
||||||
|
name="file-pdf"
|
||||||
|
size={30}
|
||||||
|
color={MainColor.disabled}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
</BaseBox>
|
||||||
|
<ButtonCenteredOnly
|
||||||
|
icon="upload"
|
||||||
|
onPress={() => router.push("/(application)/(image)/take-picture/123")}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</ButtonCenteredOnly>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
164
app/(application)/(user)/investment/[id]/edit.tsx
Normal file
164
app/(application)/(user)/investment/[id]/edit.tsx
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import {
|
||||||
|
ButtonCenteredOnly,
|
||||||
|
ButtonCustom,
|
||||||
|
InformationBox,
|
||||||
|
LandscapeFrameUploaded,
|
||||||
|
SelectCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper
|
||||||
|
} from "@/components";
|
||||||
|
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 { router } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentEdit() {
|
||||||
|
const [data, setData] = useState({
|
||||||
|
title: "",
|
||||||
|
targetDana: 0,
|
||||||
|
hargaPerLembar: 0,
|
||||||
|
totalLembar: 0,
|
||||||
|
rasioKeuntungan: 0,
|
||||||
|
pencarianInvestor: "",
|
||||||
|
periodeDeviden: "",
|
||||||
|
pembagianDeviden: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<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." />
|
||||||
|
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
||||||
134
app/(application)/(user)/investment/[id]/index.tsx
Normal file
134
app/(application)/(user)/investment/[id]/index.tsx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import {
|
||||||
|
BackButton,
|
||||||
|
DotButton,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
|
||||||
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvestasiSection";
|
||||||
|
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
||||||
|
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
||||||
|
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function InvestmentDetail() {
|
||||||
|
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) => {
|
||||||
|
console.log("PATH >> ", item.path);
|
||||||
|
router.navigate(item.path as any);
|
||||||
|
setOpenDrawerPublish(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bottomSection = (
|
||||||
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
|
id={id as string}
|
||||||
|
status={'publish'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttonSection = <Investment_ButtonInvestasiSection id={id as string} isMine={true} />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: `Detail ${_.startCase(status as string)}`,
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () =>
|
||||||
|
status === "draft" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerDraft(true)} />
|
||||||
|
) : status === "publish" ? (
|
||||||
|
<DotButton onPress={() => setOpenDrawerPublish(true)} />
|
||||||
|
) : null,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewWrapper>
|
||||||
|
<Invesment_DetailDataPublishSection
|
||||||
|
status={"publish"}
|
||||||
|
bottomSection={bottomSection}
|
||||||
|
buttonSection={buttonSection}
|
||||||
|
/>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
{/* ========= Draft Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerDraft}
|
||||||
|
closeDrawer={() => setOpenDrawerDraft(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconEdit />,
|
||||||
|
label: "Edit Data",
|
||||||
|
path: `/investment/${id}/edit`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<AntDesign
|
||||||
|
name="edit"
|
||||||
|
size={ICON_SIZE_MEDIUM}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Edit Prospektus",
|
||||||
|
path: `/investment/${id}/edit-prospectus`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<MaterialIcons
|
||||||
|
name="create"
|
||||||
|
size={ICON_SIZE_MEDIUM}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: "Update Dokumen",
|
||||||
|
path: `/investment/${id}/recap-of-document`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
columns={4}
|
||||||
|
onPressItem={handlePressDraft as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* ========= Publish Drawer ========= */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerPublish}
|
||||||
|
closeDrawer={() => setOpenDrawerPublish(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
icon: <IconDocument />,
|
||||||
|
label: "Update Dokumen",
|
||||||
|
path: `/investment/${id}/recap-of-document`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <IconNews />,
|
||||||
|
label: "Update Berita",
|
||||||
|
path: `/investment/${id}/(news)/recap-of-news`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={handlePressPublish as any}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
app/(application)/(user)/investment/[id]/investor.tsx
Normal file
21
app/(application)/(user)/investment/[id]/investor.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
|
||||||
|
export default function InvestmentInvestor() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
|
<BoxWithHeaderSection key={index}>
|
||||||
|
<AvatarUsernameAndOtherComponent />
|
||||||
|
<TextCustom bold>Rp. 7.000.000</TextCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
))}
|
||||||
|
</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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
ScrollableCustom,
|
ScrollableCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
import { jobDataDummy } from "@/screens/Job/listDataDummy";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export default function JobStatus() {
|
|||||||
|
|
||||||
const scrollComponent = (
|
const scrollComponent = (
|
||||||
<ScrollableCustom
|
<ScrollableCustom
|
||||||
data={masterStatus.map((e, i) => ({
|
data={dummyMasterStatus.map((e, i) => ({
|
||||||
id: i,
|
id: i,
|
||||||
label: e.label,
|
label: e.label,
|
||||||
value: e.value,
|
value: e.value,
|
||||||
|
|||||||
@@ -1,25 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
BadgeCustom,
|
ViewWrapper
|
||||||
StackCustom,
|
|
||||||
TextCustom,
|
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
|
||||||
|
|
||||||
export default function VotingContribution() {
|
export default function VotingContribution() {
|
||||||
const bottomComponent = (
|
|
||||||
<StackCustom>
|
|
||||||
<TextCustom align="center">Pilihan Anda:</TextCustom>
|
|
||||||
<BadgeCustom style={[GStyles.alignSelfCenter]}>Pilihan 1</BadgeCustom>
|
|
||||||
</StackCustom>
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper hideFooter>
|
<ViewWrapper hideFooter>
|
||||||
{Array.from({ length: 5 }).map((_, index) => (
|
{Array.from({ length: 5 }).map((_, index) => (
|
||||||
<Voting_BoxPublishSection
|
<Voting_BoxPublishSection
|
||||||
key={index}
|
key={index}
|
||||||
bottomComponent={bottomComponent}
|
href={`/voting/${index}/contribution`}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
|
|||||||
@@ -1,9 +1,37 @@
|
|||||||
import { TextCustom, ViewWrapper } from "@/components";
|
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() {
|
export default function VotingHistory() {
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper
|
||||||
<TextCustom>Voting History</TextCustom>
|
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>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default function VotingBeranda() {
|
|||||||
headerComponent={<SearchInput placeholder="Cari voting" />}
|
headerComponent={<SearchInput placeholder="Cari voting" />}
|
||||||
>
|
>
|
||||||
{Array.from({ length: 5 }).map((_, index) => (
|
{Array.from({ length: 5 }).map((_, index) => (
|
||||||
<Voting_BoxPublishSection key={index} />
|
<Voting_BoxPublishSection key={index} href={`/voting/${index}`} />
|
||||||
))}
|
))}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import {
|
|||||||
ScrollableCustom,
|
ScrollableCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export default function VotingStatus() {
|
|||||||
|
|
||||||
const scrollComponent = (
|
const scrollComponent = (
|
||||||
<ScrollableCustom
|
<ScrollableCustom
|
||||||
data={masterStatus.map((e, i) => ({
|
data={dummyMasterStatus.map((e, i) => ({
|
||||||
id: i,
|
id: i,
|
||||||
label: e.label,
|
label: e.label,
|
||||||
value: e.value,
|
value: e.value,
|
||||||
@@ -39,8 +39,7 @@ export default function VotingStatus() {
|
|||||||
key={i}
|
key={i}
|
||||||
paddingTop={20}
|
paddingTop={20}
|
||||||
paddingBottom={20}
|
paddingBottom={20}
|
||||||
// href={`/job/${e.id}/${activeCategory}/detail`}
|
href={`/voting/${i}/${activeCategory}/detail`}
|
||||||
// onPress={() => console.log("pressed")}
|
|
||||||
>
|
>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom align="center" bold truncate size="large">
|
<TextCustom align="center" bold truncate size="large">
|
||||||
|
|||||||
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ import { Ionicons } from "@expo/vector-icons";
|
|||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { TouchableOpacity } from "react-native";
|
import { TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
export default function CreateVoting() {
|
export default function VotingCreate() {
|
||||||
const buttonSubmit = () => {
|
const buttonSubmit = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
@@ -11,6 +12,8 @@ import { Ionicons } from "@expo/vector-icons";
|
|||||||
import { router, Stack } from "expo-router";
|
import { router, Stack } from "expo-router";
|
||||||
import EventDetailScreen from "./double-scroll";
|
import EventDetailScreen from "./double-scroll";
|
||||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
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");
|
||||||
|
|
||||||
@@ -117,14 +120,38 @@ const CustomTabNavigator = () => {
|
|||||||
|
|
||||||
const ActiveComponent = getActiveComponent();
|
const ActiveComponent = getActiveComponent();
|
||||||
|
|
||||||
|
const handleImageUpload = (file: any) => {
|
||||||
|
console.log("Gambar dipilih:", file);
|
||||||
|
// Upload ke server
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePdfOrPngUpload = (file: any) => {
|
||||||
|
console.log("PDF atau PNG dipilih:", file);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen
|
<SafeAreaView edges={["bottom"]} style={styles.container}>
|
||||||
options={{
|
<Stack.Screen
|
||||||
title: "Custom Tab Navigator",
|
options={{
|
||||||
}}
|
title: "Custom Tab Navigator",
|
||||||
/>
|
}}
|
||||||
<EventDetailScreen />
|
/>
|
||||||
|
<EventDetailScreen />
|
||||||
|
|
||||||
|
<CustomUploadButton
|
||||||
|
allowedExtensions={["jpeg", "png"]}
|
||||||
|
buttonTitle="Unggah Gambar (JPEG/PNG)"
|
||||||
|
onFileSelected={handleImageUpload}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hanya PDF atau PNG */}
|
||||||
|
<CustomUploadButton
|
||||||
|
allowedExtensions={["pdf"]}
|
||||||
|
buttonTitle="Unggah PDF atau PNG"
|
||||||
|
onFileSelected={handlePdfOrPngUpload}
|
||||||
|
/>
|
||||||
|
</SafeAreaView>
|
||||||
</>
|
</>
|
||||||
// <View style={styles.container}>
|
// <View style={styles.container}>
|
||||||
// {/* Content Area */}
|
// {/* Content Area */}
|
||||||
|
|||||||
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;
|
||||||
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 |
13
bun.lock
13
bun.lock
@@ -11,6 +11,7 @@
|
|||||||
"@react-navigation/elements": "^2.3.8",
|
"@react-navigation/elements": "^2.3.8",
|
||||||
"@react-navigation/native": "^7.1.6",
|
"@react-navigation/native": "^7.1.6",
|
||||||
"@react-navigation/native-stack": "^7.3.21",
|
"@react-navigation/native-stack": "^7.3.21",
|
||||||
|
"@types/lodash": "^4.17.20",
|
||||||
"@types/react-native-vector-icons": "^6.4.18",
|
"@types/react-native-vector-icons": "^6.4.18",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"expo": "53.0.17",
|
"expo": "53.0.17",
|
||||||
@@ -18,6 +19,8 @@
|
|||||||
"expo-camera": "~16.1.10",
|
"expo-camera": "~16.1.10",
|
||||||
"expo-clipboard": "~7.1.5",
|
"expo-clipboard": "~7.1.5",
|
||||||
"expo-constants": "~17.1.7",
|
"expo-constants": "~17.1.7",
|
||||||
|
"expo-document-picker": "~13.1.6",
|
||||||
|
"expo-file-system": "~18.1.11",
|
||||||
"expo-font": "~13.3.2",
|
"expo-font": "~13.3.2",
|
||||||
"expo-haptics": "~14.1.4",
|
"expo-haptics": "~14.1.4",
|
||||||
"expo-image": "~2.3.2",
|
"expo-image": "~2.3.2",
|
||||||
@@ -29,6 +32,7 @@
|
|||||||
"expo-symbols": "~0.4.5",
|
"expo-symbols": "~0.4.5",
|
||||||
"expo-system-ui": "~5.0.10",
|
"expo-system-ui": "~5.0.10",
|
||||||
"expo-web-browser": "~14.2.0",
|
"expo-web-browser": "~14.2.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-native": "0.79.5",
|
"react-native": "0.79.5",
|
||||||
@@ -36,6 +40,7 @@
|
|||||||
"react-native-international-phone-number": "^0.9.3",
|
"react-native-international-phone-number": "^0.9.3",
|
||||||
"react-native-maps": "1.20.1",
|
"react-native-maps": "1.20.1",
|
||||||
"react-native-otp-entry": "^1.8.5",
|
"react-native-otp-entry": "^1.8.5",
|
||||||
|
"react-native-pager-view": "6.7.1",
|
||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
"react-native-reanimated": "~3.17.4",
|
"react-native-reanimated": "~3.17.4",
|
||||||
"react-native-safe-area-context": "5.4.0",
|
"react-native-safe-area-context": "5.4.0",
|
||||||
@@ -448,6 +453,8 @@
|
|||||||
|
|
||||||
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
||||||
|
|
||||||
|
"@types/lodash": ["@types/lodash@4.17.20", "", {}, "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.0.3", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg=="],
|
"@types/node": ["@types/node@24.0.3", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.0.14", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-ixLZ7zG7j1fM0DijL9hDArwhwcCb4vqmePgwtV0GfnkHRSCUEv4LvzarcTdhoqgyMznUx/EhoTUv31CKZzkQlw=="],
|
"@types/react": ["@types/react@19.0.14", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-ixLZ7zG7j1fM0DijL9hDArwhwcCb4vqmePgwtV0GfnkHRSCUEv4LvzarcTdhoqgyMznUx/EhoTUv31CKZzkQlw=="],
|
||||||
@@ -832,6 +839,8 @@
|
|||||||
|
|
||||||
"expo-constants": ["expo-constants@17.1.7", "", { "dependencies": { "@expo/config": "~11.0.12", "@expo/env": "~1.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-byBjGsJ6T6FrLlhOBxw4EaiMXrZEn/MlUYIj/JAd+FS7ll5X/S4qVRbIimSJtdW47hXMq0zxPfJX6njtA56hHA=="],
|
"expo-constants": ["expo-constants@17.1.7", "", { "dependencies": { "@expo/config": "~11.0.12", "@expo/env": "~1.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-byBjGsJ6T6FrLlhOBxw4EaiMXrZEn/MlUYIj/JAd+FS7ll5X/S4qVRbIimSJtdW47hXMq0zxPfJX6njtA56hHA=="],
|
||||||
|
|
||||||
|
"expo-document-picker": ["expo-document-picker@13.1.6", "", { "peerDependencies": { "expo": "*" } }, "sha512-8FTQPDOkyCvFN/i4xyqzH7ELW4AsB6B3XBZQjn1FEdqpozo6rpNJRr7sWFU/93WrLgA9FJEKpKbyr6XxczK6BA=="],
|
||||||
|
|
||||||
"expo-file-system": ["expo-file-system@18.1.11", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-HJw/m0nVOKeqeRjPjGdvm+zBi5/NxcdPf8M8P3G2JFvH5Z8vBWqVDic2O58jnT1OFEy0XXzoH9UqFu7cHg9DTQ=="],
|
"expo-file-system": ["expo-file-system@18.1.11", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-HJw/m0nVOKeqeRjPjGdvm+zBi5/NxcdPf8M8P3G2JFvH5Z8vBWqVDic2O58jnT1OFEy0XXzoH9UqFu7cHg9DTQ=="],
|
||||||
|
|
||||||
"expo-font": ["expo-font@13.3.2", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-wUlMdpqURmQ/CNKK/+BIHkDA5nGjMqNlYmW0pJFXY/KE/OG80Qcavdu2sHsL4efAIiNGvYdBS10WztuQYU4X0A=="],
|
"expo-font": ["expo-font@13.3.2", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-wUlMdpqURmQ/CNKK/+BIHkDA5nGjMqNlYmW0pJFXY/KE/OG80Qcavdu2sHsL4efAIiNGvYdBS10WztuQYU4X0A=="],
|
||||||
@@ -1154,6 +1163,8 @@
|
|||||||
|
|
||||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||||
|
|
||||||
|
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||||
|
|
||||||
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
|
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
|
||||||
|
|
||||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||||
@@ -1392,6 +1403,8 @@
|
|||||||
|
|
||||||
"react-native-otp-entry": ["react-native-otp-entry@1.8.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-TZNkIuUzZKAAWrC8X/A22ZHJdycLysxUNysrGf0yTmDLRUyf4zLXwVFcDYUcRNe763Hjaf5qvtKGILb6lDGzoA=="],
|
"react-native-otp-entry": ["react-native-otp-entry@1.8.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-TZNkIuUzZKAAWrC8X/A22ZHJdycLysxUNysrGf0yTmDLRUyf4zLXwVFcDYUcRNe763Hjaf5qvtKGILb6lDGzoA=="],
|
||||||
|
|
||||||
|
"react-native-pager-view": ["react-native-pager-view@6.7.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-cBSr6xw4g5N7Kd3VGWcf+kmaH7iBWb0DXAf2bVo3bXkzBcBbTOmYSvc0LVLHhUPW8nEq5WjT9LCIYAzgF++EXw=="],
|
||||||
|
|
||||||
"react-native-paper": ["react-native-paper@5.14.5", "", { "dependencies": { "@callstack/react-theme-provider": "^3.0.9", "color": "^3.1.2", "use-latest-callback": "^0.2.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-safe-area-context": "*" } }, "sha512-eaIH5bUQjJ/mYm4AkI6caaiyc7BcHDwX6CqNDi6RIxfxfWxROsHpll1oBuwn/cFvknvA8uEAkqLk/vzVihI3AQ=="],
|
"react-native-paper": ["react-native-paper@5.14.5", "", { "dependencies": { "@callstack/react-theme-provider": "^3.0.9", "color": "^3.1.2", "use-latest-callback": "^0.2.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-safe-area-context": "*" } }, "sha512-eaIH5bUQjJ/mYm4AkI6caaiyc7BcHDwX6CqNDi6RIxfxfWxROsHpll1oBuwn/cFvknvA8uEAkqLk/vzVihI3AQ=="],
|
||||||
|
|
||||||
"react-native-reanimated": ["react-native-reanimated@3.17.5", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-classes": "^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-transform-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/plugin-transform-unicode-regex": "^7.0.0-0", "@babel/preset-typescript": "^7.16.7", "convert-source-map": "^2.0.0", "invariant": "^2.2.4", "react-native-is-edge-to-edge": "1.1.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0", "react": "*", "react-native": "*" } }, "sha512-SxBK7wQfJ4UoWoJqQnmIC7ZjuNgVb9rcY5Xc67upXAFKftWg0rnkknTw6vgwnjRcvYThrjzUVti66XoZdDJGtw=="],
|
"react-native-reanimated": ["react-native-reanimated@3.17.5", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-classes": "^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-transform-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/plugin-transform-unicode-regex": "^7.0.0-0", "@babel/preset-typescript": "^7.16.7", "convert-source-map": "^2.0.0", "invariant": "^2.2.4", "react-native-is-edge-to-edge": "1.1.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0", "react": "*", "react-native": "*" } }, "sha512-SxBK7wQfJ4UoWoJqQnmIC7ZjuNgVb9rcY5Xc67upXAFKftWg0rnkknTw6vgwnjRcvYThrjzUVti66XoZdDJGtw=="],
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type BadgeSize = "xs" | "sm" | "md" | "lg";
|
|||||||
interface BadgeProps extends ViewProps {
|
interface BadgeProps extends ViewProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
variant?: BadgeVariant;
|
variant?: BadgeVariant;
|
||||||
color?: BadgeColor;
|
color?: BadgeColor | string;
|
||||||
size?: BadgeSize;
|
size?: BadgeSize;
|
||||||
leftIcon?: React.ReactNode;
|
leftIcon?: React.ReactNode;
|
||||||
rightIcon?: React.ReactNode;
|
rightIcon?: React.ReactNode;
|
||||||
@@ -43,7 +43,8 @@ const BadgeCustom: React.FC<BadgeProps> = ({
|
|||||||
style,
|
style,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const colors = {
|
// Daftar warna bawaan
|
||||||
|
const defaultColors = {
|
||||||
primary: "#339AF0",
|
primary: "#339AF0",
|
||||||
success: "#40C057",
|
success: "#40C057",
|
||||||
warning: "#FAB005",
|
warning: "#FAB005",
|
||||||
@@ -52,8 +53,7 @@ const BadgeCustom: React.FC<BadgeProps> = ({
|
|||||||
dark: "#212529",
|
dark: "#212529",
|
||||||
};
|
};
|
||||||
|
|
||||||
const themeColor = colors[color];
|
const themeColor = color in defaultColors ? defaultColors[color as BadgeColor] : color;
|
||||||
|
|
||||||
// Ganti bagian sizeStyles dan styles.container
|
// Ganti bagian sizeStyles dan styles.container
|
||||||
const sizeStyles = {
|
const sizeStyles = {
|
||||||
xs: {
|
xs: {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import BaseBox from "./BaseBox";
|
|||||||
export default function InformationBox({ text }: { text: string }) {
|
export default function InformationBox({ text }: { text: string }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BaseBox>
|
<BaseBox paddingTop={5} paddingBottom={5}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col
|
<Grid.Col
|
||||||
span={2}
|
span={2}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const Col: React.FC<ColProps> = ({ children, span, style }) => {
|
|||||||
col: {
|
col: {
|
||||||
flexBasis: `${(100 / columns) * colSpan}%`,
|
flexBasis: `${(100 / columns) * colSpan}%`,
|
||||||
paddingVertical: margin,
|
paddingVertical: margin,
|
||||||
// marginBottom: gap,
|
// marginBottom: gap,
|
||||||
marginBlock: gap,
|
marginBlock: gap,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
193
components/Progress/ProgressCustom.tsx
Normal file
193
components/Progress/ProgressCustom.tsx
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
import { useTheme } from "@react-navigation/native";
|
||||||
|
import React from "react";
|
||||||
|
import { Animated, StyleSheet, Text, View, ViewStyle } from "react-native";
|
||||||
|
|
||||||
|
type ProgressColor =
|
||||||
|
| "primary"
|
||||||
|
| "success"
|
||||||
|
| "warning"
|
||||||
|
| "error"
|
||||||
|
| "info"
|
||||||
|
| "dark";
|
||||||
|
|
||||||
|
type ProgressSize = "xs" | "sm" | "md" | "lg" | "xl";
|
||||||
|
|
||||||
|
interface ProgressProps {
|
||||||
|
value?: number | null;
|
||||||
|
color?: ProgressColor;
|
||||||
|
size?: ProgressSize;
|
||||||
|
radius?: number;
|
||||||
|
style?: ViewStyle;
|
||||||
|
animated?: boolean;
|
||||||
|
label?: React.ReactNode; // Konten label (bisa string, number, atau elemen)
|
||||||
|
showLabel?: boolean; // Jika ingin mengontrol visibilitas
|
||||||
|
}
|
||||||
|
|
||||||
|
const getColor = (color: ProgressColor, isDark: boolean) => {
|
||||||
|
const palette: Record<ProgressColor, string> = {
|
||||||
|
primary: "#FFC107",
|
||||||
|
success: "#228B22",
|
||||||
|
warning: "#FFA500",
|
||||||
|
error: "#DC3545",
|
||||||
|
info: "#177DDC",
|
||||||
|
dark: isDark ? "#DADADA" : "#212121",
|
||||||
|
};
|
||||||
|
return palette[color];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSize = (size: ProgressSize): number => {
|
||||||
|
const sizes: Record<ProgressSize, number> = {
|
||||||
|
xs: 6,
|
||||||
|
sm: 8,
|
||||||
|
md: 12,
|
||||||
|
lg: 16,
|
||||||
|
xl: 20,
|
||||||
|
};
|
||||||
|
return sizes[size];
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProgressCustom: React.FC<ProgressProps> = ({
|
||||||
|
value = 0,
|
||||||
|
color = "primary",
|
||||||
|
size = "md",
|
||||||
|
radius = 999,
|
||||||
|
style,
|
||||||
|
animated = true,
|
||||||
|
label,
|
||||||
|
showLabel = true,
|
||||||
|
}) => {
|
||||||
|
const { dark } = useTheme();
|
||||||
|
const isDark = dark ?? false;
|
||||||
|
|
||||||
|
const barHeight = getSize(size);
|
||||||
|
const progressColor = getColor(color, isDark);
|
||||||
|
const displayValue =
|
||||||
|
typeof value === "number" ? Math.max(0, Math.min(100, value)) : 0;
|
||||||
|
|
||||||
|
// Animasi indeterminate
|
||||||
|
const translateX = React.useRef(new Animated.Value(-1)).current;
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (value === null && animated) {
|
||||||
|
const animation = Animated.loop(
|
||||||
|
Animated.timing(translateX, {
|
||||||
|
toValue: 1,
|
||||||
|
duration: 1200,
|
||||||
|
useNativeDriver: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
animation.start();
|
||||||
|
return () => animation.stop();
|
||||||
|
}
|
||||||
|
}, [value, animated, translateX]);
|
||||||
|
|
||||||
|
const isIndeterminate = value === null;
|
||||||
|
|
||||||
|
// Tentukan teks label
|
||||||
|
const labelText =
|
||||||
|
label !== undefined
|
||||||
|
? label
|
||||||
|
: typeof value === "number"
|
||||||
|
? `${Math.round(value)}%`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.container,
|
||||||
|
{
|
||||||
|
height: barHeight,
|
||||||
|
borderRadius: radius,
|
||||||
|
backgroundColor: isDark
|
||||||
|
? "rgb(255, 255, 255)"
|
||||||
|
: "rgba(255, 255, 255, 0.84)",
|
||||||
|
},
|
||||||
|
style,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{/* Progress Fill */}
|
||||||
|
{isIndeterminate ? (
|
||||||
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
styles.indeterminateBar,
|
||||||
|
{
|
||||||
|
width: "50%",
|
||||||
|
height: barHeight,
|
||||||
|
borderRadius: radius,
|
||||||
|
backgroundColor: progressColor,
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
translateX: translateX.interpolate({
|
||||||
|
inputRange: [-1, 1],
|
||||||
|
outputRange: [-100, 100],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.progressBar,
|
||||||
|
{
|
||||||
|
width: `${displayValue}%`,
|
||||||
|
height: barHeight,
|
||||||
|
borderRadius: radius,
|
||||||
|
backgroundColor: progressColor,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Label di tengah */}
|
||||||
|
{showLabel && labelText ? (
|
||||||
|
<View style={StyleSheet.absoluteFill}>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.label,
|
||||||
|
{
|
||||||
|
fontSize: barHeight * 0.7,
|
||||||
|
lineHeight: barHeight,
|
||||||
|
color: isDark ? "black" : "black", // Warna teks, bisa disesuaikan
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
numberOfLines={1}
|
||||||
|
adjustsFontSizeToFit
|
||||||
|
>
|
||||||
|
{labelText}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProgressCustom;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
overflow: "hidden",
|
||||||
|
backgroundColor: "rgba(0,0,0,0.1)",
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "center", // Pusatkan label secara vertikal
|
||||||
|
},
|
||||||
|
progressBar: {
|
||||||
|
backgroundColor: "#007BFF",
|
||||||
|
},
|
||||||
|
indeterminateBar: {
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
backgroundColor: "#007BFF",
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
textAlign: "center",
|
||||||
|
width: "100%",
|
||||||
|
// Hindari overlap dengan background — bisa tambahkan shadow atau background jika perlu
|
||||||
|
textShadowColor: "rgba(255,255,255,0.6)",
|
||||||
|
textShadowOffset: { width: 1, height: 1 },
|
||||||
|
textShadowRadius: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
13
components/_Icon/IconArchive.tsx
Normal file
13
components/_Icon/IconArchive.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export default function IconArchive({ color }: { color?: string }) {
|
||||||
|
return (
|
||||||
|
<Ionicons
|
||||||
|
name="archive"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ export default function IconContribution({ color }: { color?: string }) {
|
|||||||
<>
|
<>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
size={ICON_SIZE_SMALL}
|
size={ICON_SIZE_SMALL}
|
||||||
name="extension-puzzle"
|
name="people"
|
||||||
color={color || "white"}
|
color={color || "white"}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
25
components/_Icon/IconDocument.tsx
Normal file
25
components/_Icon/IconDocument.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { FontAwesome6, MaterialIcons } from "@expo/vector-icons";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
|
||||||
|
export { IconDocument, IconDocumentEdit };
|
||||||
|
|
||||||
|
function IconDocument({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<FontAwesome6
|
||||||
|
name="file-lines"
|
||||||
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IconDocumentEdit({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<MaterialIcons
|
||||||
|
name="edit-document"
|
||||||
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
15
components/_Icon/IconNews.tsx
Normal file
15
components/_Icon/IconNews.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import { MaterialIcons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export { IconNews };
|
||||||
|
|
||||||
|
function IconNews({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<MaterialIcons
|
||||||
|
name="newspaper"
|
||||||
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
15
components/_Icon/IconPlus.tsx
Normal file
15
components/_Icon/IconPlus.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import { Octicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export { IconPlus };
|
||||||
|
|
||||||
|
function IconPlus({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<Octicons
|
||||||
|
name="plus-circle"
|
||||||
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
components/_Icon/IconProspectus.tsx
Normal file
21
components/_Icon/IconProspectus.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import { FontAwesome6, MaterialIcons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export { IconProspectus , IconProspectusEdit};
|
||||||
|
|
||||||
|
function IconProspectus({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<FontAwesome6 name="file-contract" size={size || ICON_SIZE_MEDIUM} color={color || MainColor.white} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IconProspectusEdit({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<MaterialIcons
|
||||||
|
name="edit-note"
|
||||||
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
15
components/_Icon/IconTrash.tsx
Normal file
15
components/_Icon/IconTrash.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export { IconTrash };
|
||||||
|
|
||||||
|
function IconTrash({ color, size }: { color?: string; size?: number }) {
|
||||||
|
return (
|
||||||
|
<Ionicons
|
||||||
|
name="trash"
|
||||||
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
|
color={color || MainColor.white}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,5 +3,27 @@ import IconEdit from "./IconEdit";
|
|||||||
import IconHistory from "./IconHistory";
|
import IconHistory from "./IconHistory";
|
||||||
import IconHome from "./IconHome";
|
import IconHome from "./IconHome";
|
||||||
import IconStatus from "./IconStatus";
|
import IconStatus from "./IconStatus";
|
||||||
|
import IconArchive from "./IconArchive";
|
||||||
|
import { IconProspectus, IconProspectusEdit } from "./IconProspectus";
|
||||||
|
import { IconDocument, IconDocumentEdit } from "./IconDocument";
|
||||||
|
import { IconNews } from "./IconNews";
|
||||||
|
import { IconPlus } from "./IconPlus";
|
||||||
|
|
||||||
export { IconContribution, IconEdit, IconHistory, IconHome, IconStatus };
|
export {
|
||||||
|
IconContribution,
|
||||||
|
IconEdit,
|
||||||
|
IconHistory,
|
||||||
|
IconHome,
|
||||||
|
IconStatus,
|
||||||
|
IconArchive,
|
||||||
|
// Prospectus
|
||||||
|
IconProspectus,
|
||||||
|
IconProspectusEdit,
|
||||||
|
// Document
|
||||||
|
IconDocument,
|
||||||
|
IconDocumentEdit,
|
||||||
|
// News
|
||||||
|
IconNews,
|
||||||
|
// Plus
|
||||||
|
IconPlus,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ImageSourcePropType, View } from "react-native";
|
import { ImageSourcePropType } from "react-native";
|
||||||
|
import Divider from "../Divider/Divider";
|
||||||
import Grid from "../Grid/GridCustom";
|
import Grid from "../Grid/GridCustom";
|
||||||
import AvatarCustom from "../Image/AvatarCustom";
|
import AvatarCustom from "../Image/AvatarCustom";
|
||||||
import TextCustom from "../Text/TextCustom";
|
import TextCustom from "../Text/TextCustom";
|
||||||
import Divider from "../Divider/Divider"
|
|
||||||
|
|
||||||
const AvatarUsernameAndOtherComponent = ({
|
const AvatarUsernameAndOtherComponent = ({
|
||||||
avatarHref,
|
avatarHref,
|
||||||
@@ -19,30 +19,28 @@ const AvatarUsernameAndOtherComponent = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid containerStyle={{ zIndex: 10 }}>
|
<Grid containerStyle={{ zIndex: 10 }}>
|
||||||
<Grid.Col span={2}>
|
<Grid.Col span={2}>
|
||||||
<AvatarCustom source={avatar} href={avatarHref as any} />
|
<AvatarCustom source={avatar} href={avatarHref as any} />
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={rightComponent ? 6 : 10}
|
||||||
|
style={{ justifyContent: "center" }}
|
||||||
|
>
|
||||||
|
<TextCustom truncate bold>
|
||||||
|
{name || "Username"}
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
{rightComponent && (
|
||||||
<Grid.Col
|
<Grid.Col
|
||||||
span={rightComponent ? 6 : 10}
|
span={4}
|
||||||
style={{ justifyContent: "center" }}
|
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
||||||
>
|
>
|
||||||
<TextCustom truncate bold>
|
{rightComponent}
|
||||||
{name || "Username"}
|
|
||||||
</TextCustom>
|
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
{rightComponent && (
|
)}
|
||||||
<Grid.Col
|
</Grid>
|
||||||
span={4}
|
{withBottomLine && <Divider marginTop={0} />}
|
||||||
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
|
||||||
>
|
|
||||||
{rightComponent}
|
|
||||||
</Grid.Col>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
{withBottomLine && <Divider marginTop={0} />}
|
|
||||||
<View>
|
|
||||||
</View>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import { StyleSheet } from "react-native";
|
|||||||
import ClickableCustom from "../Clickable/ClickableCustom";
|
import ClickableCustom from "../Clickable/ClickableCustom";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
|
|
||||||
export default function DummyLandscapeImage() {
|
export default function DummyLandscapeImage({height}: {height?: number}) {
|
||||||
return (
|
return (
|
||||||
<ClickableCustom
|
<ClickableCustom
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push("/(application)/(image)/preview-image/1");
|
router.push("/(application)/(image)/preview-image/1");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image source={DUMMY_IMAGE.background} style={styles.backgroundImage} />
|
<Image source={DUMMY_IMAGE.background} style={[styles.backgroundImage, {height: height || 200}]} />
|
||||||
</ClickableCustom>
|
</ClickableCustom>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,6 @@ export default function DummyLandscapeImage() {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
backgroundImage: {
|
backgroundImage: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 200, // Tinggi background sesuai kebutuhan
|
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
|
|||||||
61
components/_ShareComponent/TabsTwoHeaderCustom.tsx
Normal file
61
components/_ShareComponent/TabsTwoHeaderCustom.tsx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { MainColor, AccentColor } from "@/constants/color-palet";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import ButtonCustom from "../Button/ButtonCustom";
|
||||||
|
import Spacing from "./Spacing";
|
||||||
|
|
||||||
|
export default function TabsTwoHeaderCustom ({
|
||||||
|
leftValue,
|
||||||
|
rightValue,
|
||||||
|
leftText,
|
||||||
|
rightText,
|
||||||
|
activeCategory,
|
||||||
|
handlePress,
|
||||||
|
}: {
|
||||||
|
leftValue: string;
|
||||||
|
rightValue: string;
|
||||||
|
leftText: string;
|
||||||
|
rightText: string;
|
||||||
|
activeCategory: string | null;
|
||||||
|
handlePress: (item: string) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: 5,
|
||||||
|
backgroundColor: MainColor.soft_darkblue,
|
||||||
|
borderRadius: 50,
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={
|
||||||
|
activeCategory === leftValue ? MainColor.yellow : AccentColor.blue
|
||||||
|
}
|
||||||
|
textColor={
|
||||||
|
activeCategory === leftValue ? MainColor.black : MainColor.white
|
||||||
|
}
|
||||||
|
style={{ width: "49%" }}
|
||||||
|
onPress={() => handlePress(leftValue)}
|
||||||
|
>
|
||||||
|
{leftText}
|
||||||
|
</ButtonCustom>
|
||||||
|
<Spacing width={"2%"} />
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor={
|
||||||
|
activeCategory === rightValue ? MainColor.yellow : AccentColor.blue
|
||||||
|
}
|
||||||
|
textColor={
|
||||||
|
activeCategory === rightValue ? MainColor.black : MainColor.white
|
||||||
|
}
|
||||||
|
style={{ width: "49%" }}
|
||||||
|
onPress={() => handlePress(rightValue)}
|
||||||
|
>
|
||||||
|
{rightText}
|
||||||
|
</ButtonCustom>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -55,6 +55,8 @@ import TabBarBackground from "./_ShareComponent/TabBarBackground";
|
|||||||
import ViewWrapper from "./_ShareComponent/ViewWrapper";
|
import ViewWrapper from "./_ShareComponent/ViewWrapper";
|
||||||
import SearchInput from "./_ShareComponent/SearchInput";
|
import SearchInput from "./_ShareComponent/SearchInput";
|
||||||
import DummyLandscapeImage from "./_ShareComponent/DummyLandscapeImage";
|
import DummyLandscapeImage from "./_ShareComponent/DummyLandscapeImage";
|
||||||
|
// Progress
|
||||||
|
import ProgressCustom from "./Progress/ProgressCustom";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AlertCustom,
|
AlertCustom,
|
||||||
@@ -96,6 +98,8 @@ export {
|
|||||||
// Map
|
// Map
|
||||||
MapCustom,
|
MapCustom,
|
||||||
MenuDrawerDynamicGrid,
|
MenuDrawerDynamicGrid,
|
||||||
|
// Progress
|
||||||
|
ProgressCustom,
|
||||||
// Scroll
|
// Scroll
|
||||||
ScrollableCustom,
|
ScrollableCustom,
|
||||||
// Select
|
// Select
|
||||||
|
|||||||
22
lib/dummy-data/_master/bank.ts
Normal file
22
lib/dummy-data/_master/bank.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
export const dummyMasterBank = [
|
||||||
|
{
|
||||||
|
name: "Bank BCA",
|
||||||
|
code: "BCA",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bank BNI",
|
||||||
|
code: "BNI",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bank BRI",
|
||||||
|
code: "BRI",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bank Mandiri",
|
||||||
|
code: "MANDIRI",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bank Permata",
|
||||||
|
code: "PERMATA",
|
||||||
|
},
|
||||||
|
]
|
||||||
8
lib/dummy-data/_master/status-transaction.ts
Normal file
8
lib/dummy-data/_master/status-transaction.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
|
||||||
|
export const dummyMasterStatusTransaction = [
|
||||||
|
{ value: "berhasil", label: "Berhasil", color: MainColor.green },
|
||||||
|
{ value: "proses", label: "Proses", color: AccentColor.skyblue },
|
||||||
|
{ value: "menunggu", label: "Menunggu", color: MainColor.yellow },
|
||||||
|
{ value: "gagal", label: "Gagal", color: MainColor.red },
|
||||||
|
];
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export const masterStatus = [
|
export const dummyMasterStatus = [
|
||||||
{ value: "publish", label: "Publish" },
|
{ value: "publish", label: "Publish" },
|
||||||
{ value: "review", label: "Review" },
|
{ value: "review", label: "Review" },
|
||||||
{ value: "draft", label: "Draft" },
|
{ value: "draft", label: "Draft" },
|
||||||
|
|||||||
18
lib/dummy-data/donasi/durasi.tsx
Normal file
18
lib/dummy-data/donasi/durasi.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export const dummyDonasiDurasi = [
|
||||||
|
{
|
||||||
|
label: "1 Bulan",
|
||||||
|
value: "1_bulan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "3 Bulan",
|
||||||
|
value: "3_bulan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "6 Bulan",
|
||||||
|
value: "6_bulan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "1 Tahun",
|
||||||
|
value: "1_tahun",
|
||||||
|
},
|
||||||
|
];
|
||||||
22
lib/dummy-data/donasi/kategori.tsx
Normal file
22
lib/dummy-data/donasi/kategori.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
export const dummyDonasiKategori = [
|
||||||
|
{
|
||||||
|
label: "Medis",
|
||||||
|
value: "medis",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pendidikan",
|
||||||
|
value: "pendidikan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kesehatan",
|
||||||
|
value: "kesehatan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Bantuan Sosial",
|
||||||
|
value: "bantuan_sosial",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Lainnya",
|
||||||
|
value: "lainnya",
|
||||||
|
},
|
||||||
|
];
|
||||||
71
lib/dummy-data/investment/dummy-data-not-publish.ts
Normal file
71
lib/dummy-data/investment/dummy-data-not-publish.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
export {listDataNotPublishInvesment, listDataPublishInvesment};
|
||||||
|
|
||||||
|
const listDataNotPublishInvesment = [
|
||||||
|
{
|
||||||
|
label: "Target Dana",
|
||||||
|
value: "Rp. 7.500.000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Harga Per Lembar",
|
||||||
|
value: "Rp. 2.400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Return Of Investment (ROI)",
|
||||||
|
value: "3 %",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Total Lembar",
|
||||||
|
value: "1.200",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jadwal Pembagian",
|
||||||
|
value: "Rp. 2.880.000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pembagian Deviden",
|
||||||
|
value: "Selamanya",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pencarian Investor",
|
||||||
|
value: "30 Hari",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const listDataPublishInvesment = [
|
||||||
|
{
|
||||||
|
label: "Investor",
|
||||||
|
value: "10",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Target Dana",
|
||||||
|
value: "Rp. 7.500.000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Harga Per Lembar",
|
||||||
|
value: "Rp. 2.400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Return Of Investment (ROI)",
|
||||||
|
value: "3 %",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Total Lembar",
|
||||||
|
value: "1.200",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Sisa Lembar",
|
||||||
|
value: "600",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jadwal Pembagian",
|
||||||
|
value: "Rp. 2.880.000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pembagian Deviden",
|
||||||
|
value: "Selamanya",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pencarian Investor",
|
||||||
|
value: "30 Hari",
|
||||||
|
},
|
||||||
|
];
|
||||||
20
lib/dummy-data/investment/pembagian-deviden.ts
Normal file
20
lib/dummy-data/investment/pembagian-deviden.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const dummyPembagianDeviden = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
name: "12",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default dummyPembagianDeviden;
|
||||||
20
lib/dummy-data/investment/pencarian-investor.ts
Normal file
20
lib/dummy-data/investment/pencarian-investor.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const dummyListPencarianInvestor = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "60",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "90",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
name: "120",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default dummyListPencarianInvestor;
|
||||||
12
lib/dummy-data/investment/periode-deviden.ts
Normal file
12
lib/dummy-data/investment/periode-deviden.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const dummyPeriodeDeviden = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "Selamanya",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "Satu tahun",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default dummyPeriodeDeviden;
|
||||||
65
package-lock.json
generated
65
package-lock.json
generated
@@ -9,16 +9,21 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^14.1.0",
|
"@expo/vector-icons": "^14.1.0",
|
||||||
|
"@react-native-community/datetimepicker": "8.4.1",
|
||||||
"@react-navigation/bottom-tabs": "^7.4.2",
|
"@react-navigation/bottom-tabs": "^7.4.2",
|
||||||
"@react-navigation/drawer": "^7.5.2",
|
"@react-navigation/drawer": "^7.5.2",
|
||||||
"@react-navigation/elements": "^2.3.8",
|
"@react-navigation/elements": "^2.3.8",
|
||||||
"@react-navigation/native": "^7.1.6",
|
"@react-navigation/native": "^7.1.6",
|
||||||
"@react-navigation/native-stack": "^7.3.21",
|
"@react-navigation/native-stack": "^7.3.21",
|
||||||
"@types/react-native-vector-icons": "^6.4.18",
|
"@types/react-native-vector-icons": "^6.4.18",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"expo": "53.0.17",
|
"expo": "53.0.17",
|
||||||
"expo-blur": "~14.1.5",
|
"expo-blur": "~14.1.5",
|
||||||
"expo-camera": "~16.1.10",
|
"expo-camera": "~16.1.10",
|
||||||
|
"expo-clipboard": "~7.1.5",
|
||||||
"expo-constants": "~17.1.7",
|
"expo-constants": "~17.1.7",
|
||||||
|
"expo-document-picker": "~13.1.6",
|
||||||
|
"expo-file-system": "~18.1.11",
|
||||||
"expo-font": "~13.3.2",
|
"expo-font": "~13.3.2",
|
||||||
"expo-haptics": "~14.1.4",
|
"expo-haptics": "~14.1.4",
|
||||||
"expo-image": "~2.3.2",
|
"expo-image": "~2.3.2",
|
||||||
@@ -37,6 +42,7 @@
|
|||||||
"react-native-international-phone-number": "^0.9.3",
|
"react-native-international-phone-number": "^0.9.3",
|
||||||
"react-native-maps": "1.20.1",
|
"react-native-maps": "1.20.1",
|
||||||
"react-native-otp-entry": "^1.8.5",
|
"react-native-otp-entry": "^1.8.5",
|
||||||
|
"react-native-pager-view": "6.7.1",
|
||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
"react-native-reanimated": "~3.17.4",
|
"react-native-reanimated": "~3.17.4",
|
||||||
"react-native-safe-area-context": "5.4.0",
|
"react-native-safe-area-context": "5.4.0",
|
||||||
@@ -2801,6 +2807,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native-community/datetimepicker": {
|
||||||
|
"version": "8.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-8.4.1.tgz",
|
||||||
|
"integrity": "sha512-DrK+CUS5fZnz8dhzBezirkzQTcNDdaXer3oDLh0z4nc2tbdIdnzwvXCvi8IEOIvleoc9L95xS5tKUl0/Xv71Mg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"invariant": "^2.2.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": ">=52.0.0",
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*",
|
||||||
|
"react-native-windows": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"expo": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native-windows": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@react-native/assets-registry": {
|
"node_modules/@react-native/assets-registry": {
|
||||||
"version": "0.79.5",
|
"version": "0.79.5",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.5.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.5.tgz",
|
||||||
@@ -5343,6 +5372,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dayjs": {
|
||||||
|
"version": "1.11.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||||
|
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
@@ -6331,6 +6366,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-clipboard": {
|
||||||
|
"version": "7.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-clipboard/-/expo-clipboard-7.1.5.tgz",
|
||||||
|
"integrity": "sha512-TCANUGOxouoJXxKBW5ASJl2WlmQLGpuZGemDCL2fO5ZMl57DGTypUmagb0CVUFxDl0yAtFIcESd78UsF9o64aw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*",
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-constants": {
|
"node_modules/expo-constants": {
|
||||||
"version": "17.1.7",
|
"version": "17.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.1.7.tgz",
|
||||||
@@ -6345,6 +6391,15 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-document-picker": {
|
||||||
|
"version": "13.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-document-picker/-/expo-document-picker-13.1.6.tgz",
|
||||||
|
"integrity": "sha512-8FTQPDOkyCvFN/i4xyqzH7ELW4AsB6B3XBZQjn1FEdqpozo6rpNJRr7sWFU/93WrLgA9FJEKpKbyr6XxczK6BA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-file-system": {
|
"node_modules/expo-file-system": {
|
||||||
"version": "18.1.11",
|
"version": "18.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.1.11.tgz",
|
||||||
@@ -10442,6 +10497,16 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-pager-view": {
|
||||||
|
"version": "6.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-6.7.1.tgz",
|
||||||
|
"integrity": "sha512-cBSr6xw4g5N7Kd3VGWcf+kmaH7iBWb0DXAf2bVo3bXkzBcBbTOmYSvc0LVLHhUPW8nEq5WjT9LCIYAzgF++EXw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-paper": {
|
"node_modules/react-native-paper": {
|
||||||
"version": "5.14.5",
|
"version": "5.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.14.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.14.5.tgz",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"@react-navigation/elements": "^2.3.8",
|
"@react-navigation/elements": "^2.3.8",
|
||||||
"@react-navigation/native": "^7.1.6",
|
"@react-navigation/native": "^7.1.6",
|
||||||
"@react-navigation/native-stack": "^7.3.21",
|
"@react-navigation/native-stack": "^7.3.21",
|
||||||
|
"@types/lodash": "^4.17.20",
|
||||||
"@types/react-native-vector-icons": "^6.4.18",
|
"@types/react-native-vector-icons": "^6.4.18",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"expo": "53.0.17",
|
"expo": "53.0.17",
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
"expo-camera": "~16.1.10",
|
"expo-camera": "~16.1.10",
|
||||||
"expo-clipboard": "~7.1.5",
|
"expo-clipboard": "~7.1.5",
|
||||||
"expo-constants": "~17.1.7",
|
"expo-constants": "~17.1.7",
|
||||||
|
"expo-document-picker": "~13.1.6",
|
||||||
|
"expo-file-system": "~18.1.11",
|
||||||
"expo-font": "~13.3.2",
|
"expo-font": "~13.3.2",
|
||||||
"expo-haptics": "~14.1.4",
|
"expo-haptics": "~14.1.4",
|
||||||
"expo-image": "~2.3.2",
|
"expo-image": "~2.3.2",
|
||||||
@@ -36,6 +39,7 @@
|
|||||||
"expo-symbols": "~0.4.5",
|
"expo-symbols": "~0.4.5",
|
||||||
"expo-system-ui": "~5.0.10",
|
"expo-system-ui": "~5.0.10",
|
||||||
"expo-web-browser": "~14.2.0",
|
"expo-web-browser": "~14.2.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-native": "0.79.5",
|
"react-native": "0.79.5",
|
||||||
@@ -43,6 +47,7 @@
|
|||||||
"react-native-international-phone-number": "^0.9.3",
|
"react-native-international-phone-number": "^0.9.3",
|
||||||
"react-native-maps": "1.20.1",
|
"react-native-maps": "1.20.1",
|
||||||
"react-native-otp-entry": "^1.8.5",
|
"react-native-otp-entry": "^1.8.5",
|
||||||
|
"react-native-pager-view": "6.7.1",
|
||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
"react-native-reanimated": "~3.17.4",
|
"react-native-reanimated": "~3.17.4",
|
||||||
"react-native-safe-area-context": "5.4.0",
|
"react-native-safe-area-context": "5.4.0",
|
||||||
|
|||||||
@@ -32,12 +32,14 @@ export default function LoginView() {
|
|||||||
|
|
||||||
// router.navigate("/verification");
|
// router.navigate("/verification");
|
||||||
// router.navigate(`/(application)/(user)/profile/${id}`);
|
// router.navigate(`/(application)/(user)/profile/${id}`);
|
||||||
router.navigate("/(application)/(user)/home");
|
// router.navigate("/(application)/(user)/home");
|
||||||
// router.navigate(`/(application)/profile/${id}/edit`);
|
// router.navigate(`/(application)/profile/${id}/edit`);
|
||||||
// router.navigate(`/(application)/(user)/portofolio/${id}`)
|
// router.navigate(`/(application)/(user)/portofolio/${id}`)
|
||||||
// router.navigate(`/(application)/(image)/preview-image/${id}`);
|
// router.navigate(`/(application)/(image)/preview-image/${id}`);
|
||||||
// router.replace("/(application)/(user)/event/(tabs)");
|
// router.replace("/(application)/(user)/event/(tabs)");
|
||||||
// router.replace("/(application)/coba");
|
// router.replace("/(application)/coba");
|
||||||
|
// router.navigate("/investment/(tabs)")
|
||||||
|
router.navigate("/crowdfunding")
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { BaseBox, ButtonCustom, StackCustom, TextCustom } from "@/components";
|
import { BaseBox, StackCustom, TextCustom } from "@/components";
|
||||||
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
|
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
|
||||||
import { listDummyReportForum } from "@/lib/dummy-data/forum/report-list";
|
import { listDummyReportForum } from "@/lib/dummy-data/forum/report-list";
|
||||||
import { router } from "expo-router";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
|||||||
@@ -30,33 +30,14 @@ export default function Home_FeatureSection() {
|
|||||||
<Ionicons name="cube" size={48} color="white" />
|
<Ionicons name="cube" size={48} color="white" />
|
||||||
<Text style={stylesHome.gridLabel}>Voting</Text>
|
<Text style={stylesHome.gridLabel}>Voting</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={stylesHome.gridItem}>
|
<TouchableOpacity
|
||||||
|
style={stylesHome.gridItem}
|
||||||
|
onPress={() => router.push("/(application)/(user)/crowdfunding")}
|
||||||
|
>
|
||||||
<Ionicons name="heart" size={48} color="white" />
|
<Ionicons name="heart" size={48} color="white" />
|
||||||
<Text style={stylesHome.gridLabel}>Crowdfunding</Text>
|
<Text style={stylesHome.gridLabel}>Crowdfunding</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* <View style={stylesHome.gridContainer}>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={stylesHome.gridItem}
|
|
||||||
onPress={() => router.push("/(application)/event")}
|
|
||||||
>
|
|
||||||
<Ionicons name="analytics" size={48} color="white" />
|
|
||||||
<Text style={stylesHome.gridLabel}>Event</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity style={stylesHome.gridItem}>
|
|
||||||
<Ionicons name="share" size={48} color="white" />
|
|
||||||
<Text style={stylesHome.gridLabel}>Collaboration</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity style={stylesHome.gridItem}>
|
|
||||||
<Ionicons name="cube" size={48} color="white" />
|
|
||||||
<Text style={stylesHome.gridLabel}>Voting</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity style={stylesHome.gridItem}>
|
|
||||||
<Ionicons name="heart" size={48} color="white" />
|
|
||||||
<Text style={stylesHome.gridLabel}>Crowdfunding</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View> */}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
50
screens/Invesment/BoxDetailDataSection.tsx
Normal file
50
screens/Invesment/BoxDetailDataSection.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function Invesment_BoxDetailDataSection({
|
||||||
|
title,
|
||||||
|
data,
|
||||||
|
bottomSection,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
data: any;
|
||||||
|
bottomSection?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BaseBox paddingBottom={0}>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<DummyLandscapeImage />
|
||||||
|
<Spacing />
|
||||||
|
<TextCustom align="center" size="xlarge" bold>
|
||||||
|
{title || "Judul Investasi"}
|
||||||
|
</TextCustom>
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
{data.map((item: any, index: any) => (
|
||||||
|
<Grid key={index}>
|
||||||
|
<Grid.Col span={4}>
|
||||||
|
<TextCustom bold>{item.label}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={7} style={{ justifyContent: "center" }}>
|
||||||
|
<TextCustom>{item.value}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
<Spacing />
|
||||||
|
{bottomSection}
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
16
screens/Invesment/BoxProgressSection.tsx
Normal file
16
screens/Invesment/BoxProgressSection.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { BaseBox, StackCustom, TextCustom, ProgressCustom } from "@/components";
|
||||||
|
|
||||||
|
export default function Invesment_BoxProgressSection({status}: {status: string}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{status === "publish" && (
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold>Progress Saham</TextCustom>
|
||||||
|
<ProgressCustom value={70} size="lg" />
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
26
screens/Invesment/ButtonInvestasiSection.tsx
Normal file
26
screens/Invesment/ButtonInvestasiSection.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { ButtonCustom } from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function Investment_ButtonInvestasiSection({
|
||||||
|
id,
|
||||||
|
isMine,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
isMine: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isMine ? (
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
router.navigate(`/investment/${id}/(transaction-flow)`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Beli Saham
|
||||||
|
</ButtonCustom>
|
||||||
|
) : (
|
||||||
|
<ButtonCustom disabled>Investasi Ini Milik Anda</ButtonCustom>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
125
screens/Invesment/ButtonStatusSection.tsx
Normal file
125
screens/Invesment/ButtonStatusSection.tsx
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { AlertDefaultSystem, ButtonCustom, Grid } from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
|
export default function Investment_ButtonStatusSection({
|
||||||
|
status,
|
||||||
|
buttonPublish
|
||||||
|
}: {
|
||||||
|
status: string;
|
||||||
|
buttonPublish?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const handleBatalkanReview = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Batalkan Review",
|
||||||
|
message: "Apakah Anda yakin ingin batalkan review ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAjukanReview = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Ajukan Review",
|
||||||
|
message: "Apakah Anda yakin ingin ajukan review ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditKembali = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Edit Kembali",
|
||||||
|
message: "Apakah Anda yakin ingin edit kembali ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenDeleteAlert = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Hapus",
|
||||||
|
message: "Apakah Anda yakin ingin menghapus data ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Hapus",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteButton = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor="red"
|
||||||
|
textColor="white"
|
||||||
|
onPress={handleOpenDeleteAlert}
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</ButtonCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case "publish":
|
||||||
|
return <>
|
||||||
|
{buttonPublish}
|
||||||
|
</>;
|
||||||
|
|
||||||
|
case "review":
|
||||||
|
return (
|
||||||
|
<ButtonCustom onPress={handleBatalkanReview}>
|
||||||
|
Batalkan Review
|
||||||
|
</ButtonCustom>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "draft":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ paddingRight: 10 }}>
|
||||||
|
<ButtonCustom onPress={handleAjukanReview}>
|
||||||
|
Ajukan Review
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ paddingLeft: 10 }}>
|
||||||
|
{DeleteButton()}
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "reject":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ paddingRight: 10 }}>
|
||||||
|
<ButtonCustom onPress={handleEditKembali}>
|
||||||
|
Edit Kembali
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ paddingLeft: 10 }}>
|
||||||
|
{DeleteButton()}
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return <ButtonCustom disabled>Status Undifined</ButtonCustom>;
|
||||||
|
}
|
||||||
|
}
|
||||||
126
screens/Invesment/ComponentBoxOnBottomDetail.tsx
Normal file
126
screens/Invesment/ComponentBoxOnBottomDetail.tsx
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
CenterCustom,
|
||||||
|
Grid,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconDocument, IconNews, IconProspectus } from "@/components/_Icon";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export default function Invesment_ComponentBoxOnBottomDetail({
|
||||||
|
id,
|
||||||
|
status,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
status: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{status === "publish" ? (
|
||||||
|
<>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ paddingInline: 5, marginBlock: 0 }}>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
|
||||||
|
href={`/(file)/${id}`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center">Prospektus</TextCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<IconProspectus size={50} color={MainColor.white} />
|
||||||
|
</CenterCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
|
<Grid.Col span={6} style={{ paddingInline: 5, marginBlock: 0 }}>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
|
||||||
|
href={`/investment/${id}/(document)/list-of-document`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center">Dokumen</TextCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<IconDocument size={50} color={MainColor.white} />
|
||||||
|
</CenterCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ paddingInline: 5, marginBlock: 0 }}>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
|
||||||
|
href={`/investment/${id}/investor`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center">Investor</TextCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<Ionicons
|
||||||
|
name="cash-outline"
|
||||||
|
size={50}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
|
<Grid.Col span={6} style={{ paddingInline: 5, marginBlock: 0 }}>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
|
||||||
|
href={`/investment/${id}/list-of-news`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center">Berita</TextCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<IconNews size={50} color={MainColor.white} />
|
||||||
|
</CenterCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ paddingRight: 10 }}>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
|
||||||
|
href={`/(file)/${id}`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center">Prospektus</TextCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<IconProspectus size={50} color={MainColor.white} />
|
||||||
|
</CenterCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
|
<Grid.Col span={6} style={{ paddingLeft: 10 }}>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={AccentColor.blue}
|
||||||
|
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
|
||||||
|
href={`/investment/${id}/(document)/list-of-document`}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom align="center">Dokumen</TextCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<IconDocument size={50} color={MainColor.white} />
|
||||||
|
</CenterCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
40
screens/Invesment/DetailDataPublishSection.tsx
Normal file
40
screens/Invesment/DetailDataPublishSection.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { Spacing, StackCustom } from "@/components";
|
||||||
|
import {
|
||||||
|
listDataNotPublishInvesment,
|
||||||
|
listDataPublishInvesment,
|
||||||
|
} from "@/lib/dummy-data/investment/dummy-data-not-publish";
|
||||||
|
import React from "react";
|
||||||
|
import Invesment_BoxDetailDataSection from "./BoxDetailDataSection";
|
||||||
|
import Invesment_BoxProgressSection from "./BoxProgressSection";
|
||||||
|
import Investment_ButtonStatusSection from "./ButtonStatusSection";
|
||||||
|
|
||||||
|
export default function Invesment_DetailDataPublishSection({
|
||||||
|
status,
|
||||||
|
bottomSection,
|
||||||
|
buttonSection,
|
||||||
|
}: {
|
||||||
|
status: string;
|
||||||
|
bottomSection?: React.ReactNode;
|
||||||
|
buttonSection?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<Invesment_BoxProgressSection status={status as string} />
|
||||||
|
<Invesment_BoxDetailDataSection
|
||||||
|
data={
|
||||||
|
status === "publish"
|
||||||
|
? listDataPublishInvesment
|
||||||
|
: listDataNotPublishInvesment
|
||||||
|
}
|
||||||
|
bottomSection={bottomSection}
|
||||||
|
/>
|
||||||
|
<Investment_ButtonStatusSection
|
||||||
|
status={status as string}
|
||||||
|
buttonPublish={buttonSection}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
<Spacing />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
28
screens/Invesment/Document/RecapBoxDetail.tsx
Normal file
28
screens/Invesment/Document/RecapBoxDetail.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { BaseBox, Grid, TextCustom } from "@/components";
|
||||||
|
import { Href } from "expo-router";
|
||||||
|
|
||||||
|
export default function Investment_BoxDetailDocument({
|
||||||
|
title,
|
||||||
|
leftIcon,
|
||||||
|
href,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
leftIcon?: React.ReactNode;
|
||||||
|
href?: Href;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BaseBox href={href}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={leftIcon ? 10 : 12}>
|
||||||
|
<TextCustom truncate>
|
||||||
|
{title ||
|
||||||
|
`Judul Dokumen: Lorem, ipsum dolor sit amet consectetur adipisicing elit.`}
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
{leftIcon && <Grid.Col span={2}>{leftIcon}</Grid.Col>}
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
48
screens/Invesment/StatusBox.tsx
Normal file
48
screens/Invesment/StatusBox.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { BaseBox, Grid, Spacing, TextCustom } from "@/components";
|
||||||
|
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { Href } from "expo-router";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
interface Investment_StatusBoxProps {
|
||||||
|
id: string;
|
||||||
|
status: string;
|
||||||
|
href?: Href
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Investment_StatusBox({
|
||||||
|
id,
|
||||||
|
status,
|
||||||
|
href
|
||||||
|
}: Investment_StatusBoxProps) {
|
||||||
|
return (
|
||||||
|
<BaseBox paddingTop={7} paddingBottom={7} href={href}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextCustom truncate={2}>
|
||||||
|
Title here : {status} 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. 7.500.000</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>
|
||||||
|
);
|
||||||
|
}
|
||||||
35
screens/Voting/BoxDetailContribution.tsx
Normal file
35
screens/Voting/BoxDetailContribution.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import {
|
||||||
|
BadgeCustom,
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
|
||||||
|
|
||||||
|
export function Voting_BoxDetailContributionSection({
|
||||||
|
headerAvatar,
|
||||||
|
}: {
|
||||||
|
headerAvatar?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
{headerAvatar ? headerAvatar : <Spacing />}
|
||||||
|
<StackCustom gap={"lg"}>
|
||||||
|
<Voting_ComponentDetailDataSection />
|
||||||
|
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom bold size="small" align="center">
|
||||||
|
Pilihan Anda
|
||||||
|
</TextCustom>
|
||||||
|
<BadgeCustom style={[GStyles.alignSelfCenter]}>
|
||||||
|
Pilihan 1
|
||||||
|
</BadgeCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
screens/Voting/BoxDetailHasilVotingSection.tsx
Normal file
30
screens/Voting/BoxDetailHasilVotingSection.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
Grid,
|
||||||
|
CircleContainer,
|
||||||
|
} from "@/components";
|
||||||
|
|
||||||
|
export default function Voting_BoxDetailHasilVotingSection() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom bold align="center">
|
||||||
|
Hasil Voting
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
|
<Grid.Col span={3} style={{ alignItems: "center" }} key={i}>
|
||||||
|
<CircleContainer value={9 % (i + 4)} />
|
||||||
|
<TextCustom size="small">Pilihan {i + 1}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
screens/Voting/BoxDetailHistorySection.tsx
Normal file
23
screens/Voting/BoxDetailHistorySection.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
Spacing,
|
||||||
|
StackCustom
|
||||||
|
} from "@/components";
|
||||||
|
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
|
||||||
|
|
||||||
|
export function Voting_BoxDetailHistorySection({
|
||||||
|
headerAvatar,
|
||||||
|
}: {
|
||||||
|
headerAvatar?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
{headerAvatar ? headerAvatar : <Spacing />}
|
||||||
|
<StackCustom>
|
||||||
|
<Voting_ComponentDetailDataSection />
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
47
screens/Voting/BoxDetailPublishSection.tsx
Normal file
47
screens/Voting/BoxDetailPublishSection.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
ButtonCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom
|
||||||
|
} from "@/components";
|
||||||
|
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
|
||||||
|
|
||||||
|
export function Voting_BoxDetailPublishSection({
|
||||||
|
headerAvatar,
|
||||||
|
}: {
|
||||||
|
headerAvatar?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const [value, setValue] = useState<any | number>("");
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
{headerAvatar ? headerAvatar : <Spacing />}
|
||||||
|
<StackCustom gap={"lg"}>
|
||||||
|
<Voting_ComponentDetailDataSection />
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<TextCustom bold size="small">
|
||||||
|
Pilihan :
|
||||||
|
</TextCustom>
|
||||||
|
<RadioGroup value={value} onChange={setValue}>
|
||||||
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
|
<View key={i}>
|
||||||
|
<RadioCustom
|
||||||
|
label={`Pilihan ${i + 1}`}
|
||||||
|
value={`Pilihan ${i + 1}`}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ButtonCustom onPress={() => console.log("vote")}>Vote</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
38
screens/Voting/BoxDetailSection.tsx
Normal file
38
screens/Voting/BoxDetailSection.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom
|
||||||
|
} from "@/components";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
|
||||||
|
|
||||||
|
export function Voting_BoxDetailSection({
|
||||||
|
headerAvatar,
|
||||||
|
}: {
|
||||||
|
headerAvatar?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
{headerAvatar ? headerAvatar : <Spacing />}
|
||||||
|
<StackCustom>
|
||||||
|
<Voting_ComponentDetailDataSection/>
|
||||||
|
<Spacing/>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<TextCustom bold size="small">
|
||||||
|
Pilihan :
|
||||||
|
</TextCustom>
|
||||||
|
{Array.from({ length: 3 }).map((_, i) => (
|
||||||
|
<View key={i}>
|
||||||
|
<TextCustom>Nama Pilihan {i + 1}</TextCustom>
|
||||||
|
<Spacing />
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -9,20 +9,25 @@ import {
|
|||||||
CircleContainer,
|
CircleContainer,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { Href } from "expo-router";
|
||||||
|
|
||||||
export default function Voting_BoxPublishSection({
|
export default function Voting_BoxPublishSection({
|
||||||
|
href,
|
||||||
|
id,
|
||||||
bottomComponent,
|
bottomComponent,
|
||||||
}: {
|
}: {
|
||||||
|
href?: Href
|
||||||
|
id?: string
|
||||||
bottomComponent?: React.ReactNode;
|
bottomComponent?: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BoxWithHeaderSection>
|
<BoxWithHeaderSection href={href}>
|
||||||
<AvatarUsernameAndOtherComponent avatarHref="/profile/1" />
|
<AvatarUsernameAndOtherComponent avatarHref="/profile/1" />
|
||||||
<Spacing />
|
<Spacing />
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom align="center" bold truncate size="large">
|
<TextCustom align="center" bold truncate size="large">
|
||||||
Voting Title Here
|
Voting Title {id}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<BadgeCustom
|
<BadgeCustom
|
||||||
@@ -34,18 +39,12 @@ export default function Voting_BoxPublishSection({
|
|||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={3} style={{ alignItems: "center" }}>
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
<CircleContainer value={"10"} />
|
<Grid.Col span={3} style={{ alignItems: "center" }} key={i}>
|
||||||
</Grid.Col>
|
<CircleContainer value={9 % (i + 4)} />
|
||||||
<Grid.Col span={3} style={{ alignItems: "center" }}>
|
<TextCustom size="small">Pilihan {i + 1}</TextCustom>
|
||||||
<CircleContainer value={"9"} />
|
</Grid.Col>
|
||||||
</Grid.Col>
|
))}
|
||||||
<Grid.Col span={3} style={{ alignItems: "center" }}>
|
|
||||||
<CircleContainer value={"10"} />
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={3} style={{ alignItems: "center" }}>
|
|
||||||
<CircleContainer value={"9"} />
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
{bottomComponent}
|
{bottomComponent}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|||||||
124
screens/Voting/ButtonStatusSection.tsx
Normal file
124
screens/Voting/ButtonStatusSection.tsx
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import { AlertDefaultSystem, ButtonCustom, Grid } from "@/components";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function Voting_ButtonStatusSection({
|
||||||
|
status,
|
||||||
|
}: {
|
||||||
|
status: string;
|
||||||
|
}) {
|
||||||
|
const handleBatalkanReview = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Batalkan Review",
|
||||||
|
message: "Apakah Anda yakin ingin batalkan review ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAjukanReview = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Ajukan Review",
|
||||||
|
message: "Apakah Anda yakin ingin ajukan review ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditKembali = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Edit Kembali",
|
||||||
|
message: "Apakah Anda yakin ingin edit kembali ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenDeleteAlert = () => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Hapus",
|
||||||
|
message: "Apakah Anda yakin ingin menghapus data ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Hapus",
|
||||||
|
onPressRight: () => {
|
||||||
|
console.log("Hapus");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteButton = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor="red"
|
||||||
|
textColor="white"
|
||||||
|
onPress={handleOpenDeleteAlert}
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</ButtonCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case "publish":
|
||||||
|
return <></>;
|
||||||
|
|
||||||
|
case "review":
|
||||||
|
return (
|
||||||
|
<ButtonCustom onPress={handleBatalkanReview}>
|
||||||
|
Batalkan Review
|
||||||
|
</ButtonCustom>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "draft":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<ButtonCustom onPress={handleAjukanReview}>
|
||||||
|
Ajukan Review
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={2}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={5}>{DeleteButton()}</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "reject":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<ButtonCustom onPress={handleEditKembali}>
|
||||||
|
Edit Kembali
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={2}>
|
||||||
|
<View />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={5}>{DeleteButton()}</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return <ButtonCustom disabled>Status Undifined</ButtonCustom>;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
screens/Voting/ComponentDetailDataSection.tsx
Normal file
32
screens/Voting/ComponentDetailDataSection.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { BadgeCustom, TextCustom } from "@/components";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export function Voting_ComponentDetailDataSection() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TextCustom align="center" bold size="large">
|
||||||
|
Title of Voting Here
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Perspiciatis
|
||||||
|
corporis blanditiis est provident corrupti facilis iste cum voluptate.
|
||||||
|
Natus eum aut quos consequatur doloribus fugiat sit ullam minima non
|
||||||
|
enim?
|
||||||
|
</TextCustom>
|
||||||
|
<View>
|
||||||
|
<TextCustom bold size="small" align="center">
|
||||||
|
Batas Voting
|
||||||
|
</TextCustom>
|
||||||
|
<BadgeCustom
|
||||||
|
style={[GStyles.alignSelfCenter, { width: "70%" }]}
|
||||||
|
variant="light"
|
||||||
|
>
|
||||||
|
{dayjs().format("DD/MM/YYYY")} -{" "}
|
||||||
|
{dayjs().add(1, "day").format("DD/MM/YYYY")}
|
||||||
|
</BadgeCustom>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -320,4 +320,7 @@ export const GStyles = StyleSheet.create({
|
|||||||
alignSelfCenter: {
|
alignSelfCenter: {
|
||||||
alignSelf: "center",
|
alignSelf: "center",
|
||||||
},
|
},
|
||||||
|
alignSelfFlexEnd: {
|
||||||
|
alignSelf: "flex-end",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
34
utils/fileValidation.ts
Normal file
34
utils/fileValidation.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// utils/fileValidation.ts
|
||||||
|
const ALLOWED_TYPES: Record<string, string[]> = {
|
||||||
|
image: ["jpeg", "jpg", "png"],
|
||||||
|
document: ["pdf", "png"],
|
||||||
|
pdf: ["pdf"],
|
||||||
|
png: ["png"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isValidFileType = (
|
||||||
|
fileName: string,
|
||||||
|
allowedExtensions: string[]
|
||||||
|
): boolean => {
|
||||||
|
const extension = fileName.split(".").pop()?.toLowerCase();
|
||||||
|
return !!extension && allowedExtensions.includes(extension);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper: Dapatkan MIME type berdasarkan ekstensi (opsional)
|
||||||
|
export const getMimeType = (fileName: string): string => {
|
||||||
|
const ext = fileName.split(".").pop()?.toLowerCase();
|
||||||
|
switch (ext) {
|
||||||
|
case "jpg":
|
||||||
|
return "image/jpg";
|
||||||
|
case "jpeg":
|
||||||
|
return "image/jpeg";
|
||||||
|
case "png":
|
||||||
|
return "image/png";
|
||||||
|
case "pdf":
|
||||||
|
return "application/pdf";
|
||||||
|
default:
|
||||||
|
return "application/octet-stream";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ALLOWED_TYPES;
|
||||||
Reference in New Issue
Block a user