Compare commits

...

14 Commits

Author SHA1 Message Date
72f760c6a9 Admin Forum
Add:
- admin/forum/report-posting
- admin/forum/report-comment
- admin/forum/posting
- admin/forum/[id]

Component
Fix:
- screens/Admin/listPageAdmin
- app/(application)/admin/_layout
- Admin/TitlePage
- Admin/BackButtonAntTitle
- Admin/BoxTitlePage

Package Install
Add:
- react-native-toast-message: untuk menampilkan toast

### No Issue
2025-08-11 17:18:14 +08:00
8750660fc7 Admin Forum
Add:
- admin/forum/

Admin Job
Fix: Delete page & fix delete
- admin/_layout.
- admin/job : publish, reject, review

### No Issue
2025-08-11 10:47:20 +08:00
d0b64f8109 Admin Job:
Add:
- admin/job/[status]/
- dmin/job/[id]/

### No issue
2025-08-08 17:42:44 +08:00
25f600e8c2 Admin Collaboration
Add:
- collaboration/[id]

Fix: tampilan UI
- admin/collaboration: publish, group, reject

### No Issue
2025-08-08 14:21:37 +08:00
72e8d7aabd Admin User Access
Add:
- admin/user-access.tsx

### No Issue
2025-08-07 17:15:02 +08:00
29377c0bb0 Admin App Infromation
Add:
- admin/app-information/sticker/

#### No Issue
2025-08-07 15:44:22 +08:00
88cf3321e1 Admin App Information
Add:
- app-information/information-bank

### No Issue
2025-08-07 14:09:56 +08:00
9ad1ccfd5f Admin App Information
Add:
- app-information/information-bank/

Component
Fix:
- constans-value: Icon size re name

### No Issue
2025-08-07 12:05:16 +08:00
d47fff469b Admin
App-Information
Add:
- screens/Admin/App-Information
- _ShareComponent/Admin
- app/(application)/admin/app-information

### No Issue
2025-08-06 17:35:30 +08:00
bcc0e02581 Admin
Add:
- screens/Admin/
- admin/notification/

Component
Add:
-  components/_ShareComponent/GridSectionView.tsx

### No Issue
2025-08-06 15:02:47 +08:00
caf250c5ca Admin
Add:
- Menambahkan folder : /admin/collaboration , /admin/investmen
- NavbarMenu

### No Issue
2025-08-06 11:53:33 +08:00
c4c16f19c1 Admin
Add:"
- app/(application)/admin/

## NO Issue
2025-08-05 17:40:46 +08:00
48c34aa26c Admin
Add:
- app/(application)/(admin)/

## No Issue
2025-08-05 12:11:25 +08:00
e16b0c2fce Donation
Add:
- [transaction]/success.tsx
- [transaction]/failed.tsx

Fix:
- InformationBox : props type di tambah React.ReactNode
- /donation/create && /donation/create-story : fix route

### No Issue
2025-08-05 11:01:41 +08:00
79 changed files with 4280 additions and 65 deletions

View File

@@ -477,6 +477,20 @@ export default function UserLayout() {
),
}}
/>
<Stack.Screen
name="donation/[id]/(transaction-flow)/[transaction]/success"
options={{
title: "Donasi Berhasil",
headerLeft: () => <BackButton />,
}}
/>
<Stack.Screen
name="donation/[id]/(transaction-flow)/[transaction]/failed"
options={{
title: "Donasi Gagal",
headerLeft: () => <BackButton />,
}}
/>
{/* ========== End Donation Section ========= */}

View File

@@ -1,13 +1,14 @@
import {
BadgeCustom,
BaseBox,
DummyLandscapeImage,
Grid,
StackCustom,
TextCustom,
ViewWrapper
BadgeCustom,
BaseBox,
DummyLandscapeImage,
Grid,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction";
import { router } from "expo-router";
import { View } from "react-native";
export default function DonationMyDonation() {
@@ -17,6 +18,19 @@ export default function DonationMyDonation() {
);
return dummyMasterStatusTransaction[randomIndex];
});
const handlePress = (value: string) => {
if (value === "menunggu") {
router.push(`/donation/${value}/(transaction-flow)/123/invoice`);
} else if (value === "proses") {
router.push(`/donation/${value}/(transaction-flow)/123/process`);
} else if (value === "berhasil") {
router.push(`/donation/${value}/(transaction-flow)/123/success`);
} else if (value === "gagal") {
router.push(`/donation/${value}/(transaction-flow)/123/failed`);
}
};
return (
<ViewWrapper hideFooter>
{randomStatusData.map((item, index) => (
@@ -24,11 +38,13 @@ export default function DonationMyDonation() {
key={index}
paddingTop={7}
paddingBottom={7}
href={`/investment/${index}`}
onPress={() => {
handlePress(item.value);
}}
>
<Grid>
<Grid.Col span={5}>
<DummyLandscapeImage height={100} />
<DummyLandscapeImage height={100} unClickPath />
</Grid.Col>
<Grid.Col span={1}>
<View />

View File

@@ -0,0 +1,83 @@
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";
import dayjs from "dayjs";
export default function DonasiFailed() {
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 Donasi",
value: "Rp. 750.000",
},
{
label: "Tanggal",
value: `${dayjs(new Date()).format("DD/MM/YYYY")}`,
},
];

View File

@@ -13,12 +13,12 @@ import { MainColor } from "@/constants/color-palet";
import { router, useLocalSearchParams } from "expo-router";
export default function DonationInvoice() {
const { id } = useLocalSearchParams();
const { id, transaction } = useLocalSearchParams();
return (
<>
<ViewWrapper>
<StackCustom>
<InformationBox text="Mohon transfer ke rekening dibawah" />
<InformationBox text={`Mohon transfer donasi anda ke rekening dibawah dengan Id: ${transaction}`} />
<BaseBox>
<StackCustom gap={"xs"}>
<TextCustom>Nama BANK</TextCustom>

View File

@@ -0,0 +1,83 @@
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";
import dayjs from "dayjs";
export default function DonationSuccess() {
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 Penggalian Dana 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 Donasi",
value: "Rp. 750.000",
},
{
label: "Tanggal",
value: `${dayjs(new Date()).format("DD/MM/YYYY")}`,
},
];

View File

@@ -57,7 +57,7 @@ export default function DonationCreateStory() {
<Spacing />
<ButtonCustom
onPress={() => {
router.navigate(`/donation/(tabs)/status`);
router.replace(`/donation/(tabs)/status`);
}}
>
Simpan

View File

@@ -66,7 +66,7 @@ export default function DonationCreate() {
<Spacing />
<ButtonCustom
onPress={() => {
router.push("/donation/create-story");
router.replace("/donation/create-story");
}}
>
Selanjutnya

View File

@@ -1,5 +1,5 @@
import { ViewWrapper } from "@/components";
import TabsTwoHeaderCustom from "@/components/_ShareComponent/TabsTwoHeaderCustom";
import TabsTwoButtonCustom from "@/components/_ShareComponent/TabsTwoHeaderCustom";
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
import { useState } from "react";
@@ -15,7 +15,7 @@ export default function VotingHistory() {
<ViewWrapper
hideFooter
headerComponent={
<TabsTwoHeaderCustom
<TabsTwoButtonCustom
leftValue="all"
rightValue="main"
leftText="Semua Riwayat"

View File

@@ -7,6 +7,8 @@ export default function ApplicationLayout() {
<>
<Stack screenOptions={HeaderStyles}>
<Stack.Screen name="(user)" options={{ headerShown: false }} />
<Stack.Screen name="admin" options={{ headerShown: false }} />
{/* Take Picture */}
<Stack.Screen

View File

@@ -0,0 +1,216 @@
import {
AlertDefaultSystem,
DrawerCustom,
GridComponentView,
MenuDrawerDynamicGrid,
StackCustom,
TextCustom,
} from "@/components";
import DrawerAdmin from "@/components/Drawer/DrawerAdmin";
import NavbarMenu from "@/components/Drawer/NavbarMenu";
import { AccentColor, MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM, ICON_SIZE_SMALL, ICON_SIZE_XLARGE } from "@/constants/constans-value";
import { adminListMenu } from "@/screens/Admin/listPageAdmin";
import { GStyles } from "@/styles/global-styles";
import { FontAwesome6, Ionicons } from "@expo/vector-icons";
import { router, Stack } from "expo-router";
import { useState } from "react";
export default function AdminLayout() {
const [openDrawerNavbar, setOpenDrawerNavbar] = useState(false);
const [openDrawerUser, setOpenDrawerUser] = useState(false);
return (
<>
<Stack
screenOptions={{
title: "HIPMI DASHBOARD",
headerStyle: GStyles.headerStyle,
headerTitleStyle: GStyles.headerTitleStyle,
headerTitleAlign: "center",
contentStyle: {
borderBottomColor: AccentColor.blue,
},
headerLeft: () => (
<Ionicons
name="menu"
size={ICON_SIZE_XLARGE}
color={MainColor.white}
onPress={() => setOpenDrawerNavbar(true)}
/>
),
headerRight: () => (
<FontAwesome6
name="circle-user"
size={ICON_SIZE_MEDIUM}
color={MainColor.white}
onPress={() => setOpenDrawerUser(true)}
/>
),
}}
>
<Stack.Screen name="dashboard" />
{/* ================== Investment Start ================== */}
<Stack.Screen name="investment/index" />
<Stack.Screen name="investment/publish" />
<Stack.Screen name="investment/review" />
<Stack.Screen name="investment/reject" />
{/* ================== Investment End ================== */}
{/* ================== Maps Start ================== */}
<Stack.Screen name="maps" />
{/* ================== Maps End ================== */}
{/* ================== App Information Start ================== */}
<Stack.Screen name="app-information/index" />
{/* ================== App Information End ================== */}
{/* ================== Job Start ================== */}
<Stack.Screen name="job/index" />
{/* <Stack.Screen name="job/publish" />
<Stack.Screen name="job/review" />
<Stack.Screen name="job/reject" /> */}
<Stack.Screen name="job/[status]/status" />
<Stack.Screen name="job/[id]/[status]/index" />
{/* ================== Collaboration Start ================== */}
<Stack.Screen name="collaboration/index" />
<Stack.Screen name="collaboration/publish" />
<Stack.Screen name="collaboration/group" />
<Stack.Screen name="collaboration/reject" />
<Stack.Screen name="collaboration/[id]/[status]"/>
<Stack.Screen name="collaboration/[id]/group"/>
{/* ================== Collaboration End ================== */}
{/* ================== Forum Start ================== */}
<Stack.Screen name="forum/index" />
<Stack.Screen name="forum/[id]/index" />
<Stack.Screen name="forum/report-comment"/>
<Stack.Screen name="forum/report-posting"/>
<Stack.Screen name="forum/[id]/list-report-posting" />
<Stack.Screen name="forum/[id]/list-report-comment"/>
{/* ================== Forum End ================== */}
</Stack>
<DrawerAdmin
isVisible={openDrawerNavbar}
onClose={() => setOpenDrawerNavbar(false)}
>
<StackCustom gap={"xs"}>
<Ionicons
name="close"
size={ICON_SIZE_SMALL}
color={MainColor.white}
onPress={() => setOpenDrawerNavbar(false)}
style={{ alignSelf: "flex-end" }}
/>
<NavbarMenu
items={adminListMenu}
onClose={() => setOpenDrawerNavbar(false)}
/>
</StackCustom>
</DrawerAdmin>
<DrawerCustom
isVisible={openDrawerUser}
closeDrawer={() => setOpenDrawerUser(false)}
height={"auto"}
>
<StackCustom>
<GridComponentView
leftIcon={
<Ionicons
name="person"
size={ICON_SIZE_SMALL}
color={MainColor.white}
/>
}
>
<TextCustom>Username</TextCustom>
</GridComponentView>
<GridComponentView
leftIcon={
<Ionicons
name="ribbon-outline"
size={ICON_SIZE_SMALL}
color={MainColor.white}
/>
}
>
<TextCustom>User Role</TextCustom>
</GridComponentView>
<MenuDrawerDynamicGrid
columns={3}
data={[
{
label: "Notifikasi",
value: "notification",
icon: (
<Ionicons
name="notifications"
size={ICON_SIZE_SMALL}
color={MainColor.white}
/>
),
path: "/admin/notification",
},
{
label: "Kembali ke User",
value: "back-to-user",
icon: (
<Ionicons
name="git-compare"
size={ICON_SIZE_SMALL}
color={MainColor.white}
/>
),
path: "" as any,
},
{
label: "Keluar",
value: "logout",
icon: (
<Ionicons
name="log-out"
size={ICON_SIZE_SMALL}
color={MainColor.white}
/>
),
path: "" as any,
color: MainColor.red,
},
]}
onPressItem={(item) => {
if (item.value === "notification") {
router.push("/admin/notification");
setOpenDrawerUser(false);
} else if (item.value === "back-to-user") {
AlertDefaultSystem({
title: "Kembali ke User",
message: "Apakah Anda yakin ingin kembali ke user?",
textLeft: "Batal",
textRight: "Ya",
onPressRight: () => {
router.replace(`/(application)/(user)/profile/${123}`);
},
});
} else if (item.value === "logout") {
AlertDefaultSystem({
title: "Keluar",
message: "Apakah Anda yakin ingin keluar?",
textLeft: "Batal",
textRight: "Keluar",
onPressRight: () => {
router.replace("/");
},
});
}
}}
/>
</StackCustom>
</DrawerCustom>
</>
);
}

View File

@@ -0,0 +1,36 @@
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { router } from "expo-router";
export default function AdminAppInformation_BusinessFieldDetail() {
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
onPress={() => router.back()}
>
Update
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
<TextInputCustom
label="Nama Bidang Bisnis"
placeholder="Masukan Nama Bidang Bisnis"
required
/>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,36 @@
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { router } from "expo-router";
export default function AdminAppInformation_BusinessFieldCreate() {
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
onPress={() => router.back()}
>
Tambah
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Tambah Bidang Bisnis" />
<TextInputCustom
label="Nama Bidang Bisnis"
placeholder="Masukan Nama Bidang Bisnis"
required
/>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,96 @@
import {
ActionIcon,
ScrollableCustom,
StackCustom,
ViewWrapper,
} from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
import AdminAppInformation_BusinessFieldSection from "@/screens/Admin/App-Information/BusinessFieldSection";
import AdminAppInformation_Bank from "@/screens/Admin/App-Information/InformationBankSection";
import AdminAppInformation_StickerSection from "@/screens/Admin/App-Information/StickerSection";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
export default function AdminInformation() {
const [activeCategory, setActiveCategory] = useState<string | null>("bank");
const [activePage, setActivePage] = useState<string>("Informasi Bank");
const handlePress = (item: any) => {
setActiveCategory(item.value);
setActivePage(item.label);
// tambahkan logika lain seperti filter dsb.
};
const scrollComponent = (
<StackCustom>
<ScrollableCustom
data={listPage}
onButtonPress={handlePress}
activeId={activeCategory as any}
/>
</StackCustom>
);
const renderContent = () => {
switch (activeCategory) {
case "bank":
return <AdminAppInformation_Bank />;
case "business":
return <AdminAppInformation_BusinessFieldSection />;
case "sticker":
return <AdminAppInformation_StickerSection />;
default:
return <AdminAppInformation_Bank />;
}
};
return (
<>
<ViewWrapper headerComponent={scrollComponent}>
<AdminComp_BoxTitle
title={activePage}
rightComponent={
<View style={{ flexDirection: "row" }}>
<ActionIcon
icon={
<Ionicons name="add" size={ICON_SIZE_SMALL} color="black" />
}
onPress={() => {
if (activeCategory === "bank") {
router.push("/admin/app-information/information-bank/create");
} else if (activeCategory === "business") {
router.push("/admin/app-information/business-field/create");
} else if (activeCategory === "sticker") {
router.push("/admin/app-information/sticker/create");
}
}}
/>
</View>
}
/>
{renderContent()}
</ViewWrapper>
</>
);
}
const listPage = [
{
id: "1",
label: "Informasi Bank",
value: "bank",
},
{
id: "2",
label: "Bidang Bisnis",
value: "business",
},
{
id: "3",
label: "Stiker",
value: "sticker",
},
];

View File

@@ -0,0 +1,50 @@
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { router } from "expo-router";
export default function AdminAppInformation_BankDetail() {
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
onPress={() => router.back()}
>
Update
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Update Bank" />
<StackCustom>
<TextInputCustom
label="Nama Bank"
placeholder="Masukan Nama Bank"
required
/>
<TextInputCustom
label="Nama Rekening"
placeholder="Masukan Nama Rekening"
required
/>
<TextInputCustom
label="Nomor Rekening"
placeholder="Masukan Nomor Rekening"
required
/>
</StackCustom>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,50 @@
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextInputCustom,
ViewWrapper
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { router } from "expo-router";
export default function AdminAppInformation_BankCreate() {
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
onPress={() => router.back()}
>
Tambah
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Tambah Daftar Bank" />
<StackCustom>
<TextInputCustom
label="Nama Bank"
placeholder="Masukan Nama Bank"
required
/>
<TextInputCustom
label="Nama Rekening"
placeholder="Masukan Nama Rekening"
required
/>
<TextInputCustom
label="Nomor Rekening"
placeholder="Masukan Nomor Rekening"
required
/>
</StackCustom>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,80 @@
import {
BoxButtonOnFooter,
ButtonCenteredOnly,
ButtonCustom,
CheckboxCustom,
CheckboxGroup,
LandscapeFrameUploaded,
SelectCustom,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { dummyMasterEmotions } from "@/lib/dummy-data/_master/emotions";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
export default function AdminAppInformation_StickerCreate() {
const [value, setValue] = useState<string | null>(null);
const [selectedEmotions, setSelectedEmotions] = useState<string[]>([]);
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom onPress={() => router.back()}>Update</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Edit Stiker" />
<StackCustom gap={"xs"}>
<LandscapeFrameUploaded />
<ButtonCenteredOnly icon="upload" onPress={() => {}}>
Upload
</ButtonCenteredOnly>
<Spacing />
<SelectCustom
required
label="Jenis Kelamin"
data={[
{ label: "Laki-laki", value: "laki-laki" },
{ label: "Perempuan", value: "perempuan" },
]}
value={value}
onChange={(value) => setValue(value as string)}
/>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<TextCustom>Pilih Emosi Stiker</TextCustom>
<TextCustom color="red">*</TextCustom>
</View>
<Spacing height={10} />
<CheckboxGroup
value={selectedEmotions}
onChange={(value) => setSelectedEmotions(value as string[])}
>
<StackCustom>
{dummyMasterEmotions.map((e) => (
<CheckboxCustom
size={25}
key={e.id}
label={<TextCustom>{e.label}</TextCustom>}
valueKey={e.id}
/>
))}
</StackCustom>
</CheckboxGroup>
</StackCustom>
</StackCustom>
<Spacing />
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,84 @@
import {
BoxButtonOnFooter,
ButtonCenteredOnly,
ButtonCustom,
CheckboxCustom,
CheckboxGroup,
LandscapeFrameUploaded,
SelectCustom,
Spacing,
StackCustom,
TextCustom,
ViewWrapper
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { dummyMasterEmotions } from "@/lib/dummy-data/_master/emotions";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
export default function AdminAppInformation_StickerCreate() {
const [value, setValue] = useState<string | null>(null);
const [selectedEmotions, setSelectedEmotions] = useState<string[]>([]);
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
onPress={() => router.back()}
>
Tambah
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Tambah Stiker" />
<StackCustom gap={"xs"}>
<LandscapeFrameUploaded />
<ButtonCenteredOnly icon="upload" onPress={() => {}}>
Upload
</ButtonCenteredOnly>
<Spacing />
<SelectCustom
required
label="Jenis Kelamin"
data={[
{ label: "Laki-laki", value: "laki-laki" },
{ label: "Perempuan", value: "perempuan" },
]}
value={value}
onChange={(value) => setValue(value as string)}
/>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<TextCustom>Pilih Emosi Stiker</TextCustom>
<TextCustom color="red">*</TextCustom>
</View>
<Spacing height={10} />
<CheckboxGroup
value={selectedEmotions}
onChange={(value) => setSelectedEmotions(value as string[])}
>
<StackCustom>
{dummyMasterEmotions.map((e) => (
<CheckboxCustom
size={25}
key={e.id}
label={<TextCustom>{e.label}</TextCustom>}
valueKey={e.id}
/>
))}
</StackCustom>
</CheckboxGroup>
</StackCustom>
</StackCustom>
<Spacing/>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,89 @@
import {
BaseBox,
BoxButtonOnFooter,
ButtonCustom,
Grid,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { MainColor } from "@/constants/color-palet";
import { useLocalSearchParams } from "expo-router";
export default function AdminCollaborationPublish() {
const { id, status } = useLocalSearchParams();
console.log("params:", id, status);
const bottomFooter = (
<BoxButtonOnFooter>
<ButtonCustom
backgroundColor={MainColor.red}
textColor="white"
onPress={() => {}}
>
Reject
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper
headerComponent={<AdminBackButtonAntTitle title={`Detail ${status}`} />}
footerComponent={bottomFooter}
>
<BaseBox>
<StackCustom>
{listData.map((item, i) => (
<Grid key={i}>
<Grid.Col
span={4}
style={{ justifyContent: "center", paddingRight: 10 }}
>
<TextCustom bold>{item.label}</TextCustom>
</Grid.Col>
<Grid.Col span={8} style={{ justifyContent: "center" }}>
<TextCustom>{item.value}</TextCustom>
</Grid.Col>
</Grid>
))}
</StackCustom>
</BaseBox>
</ViewWrapper>
</>
);
}
const listData = [
{
label: "Username",
value: "Bagas Banuna",
},
{
label: "Judul Proyek",
value:
"Judul Proyek: Lorem ipsum dolor sit amet consectetur adipisicing elit.",
},
{
label: "Industri",
value: "Kesehatan",
},
{
label: "Jumlah Partisipan ",
value: "0",
},
{
label: "Lokasi",
value: "Kuta Selatan, Bali",
},
{
label: "Tujuan Proyek",
value:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
},
{
label: "Keuntungan",
value:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
},
];

View File

@@ -0,0 +1,97 @@
import {
BaseBox,
Grid,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { useLocalSearchParams } from "expo-router";
export default function AdminCollaborationGroup() {
const { id } = useLocalSearchParams();
console.log("params:", id);
return (
<>
<ViewWrapper
headerComponent={
<AdminBackButtonAntTitle title={`Detail Group ${id}`} />
}
>
<StackCustom gap={"xs"}>
<BaseBox>
<StackCustom>
{listData.map((item, i) => (
<Grid key={i}>
<Grid.Col
span={4}
style={{ justifyContent: "center", paddingRight: 10 }}
>
<TextCustom bold>{item.label}</TextCustom>
</Grid.Col>
<Grid.Col span={8} style={{ justifyContent: "center" }}>
<TextCustom>{item.value}</TextCustom>
</Grid.Col>
</Grid>
))}
</StackCustom>
</BaseBox>
<BaseBox>
<StackCustom>
<TextCustom align="center">Anggota</TextCustom>
{Array.from({ length: 10 }).map((_, i) => (
<Grid key={i}>
<Grid.Col
span={4}
style={{ justifyContent: "center", paddingRight: 10 }}
>
<TextCustom bold>Username</TextCustom>
</Grid.Col>
<Grid.Col span={8} style={{ justifyContent: "center" }}>
<TextCustom>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
</TextCustom>
</Grid.Col>
</Grid>
))}
</StackCustom>
</BaseBox>
</StackCustom>
</ViewWrapper>
</>
);
}
const listData = [
{
label: "Admin Group",
value: "Bagas Banuna",
},
{
label: "Nama Group",
value: "Lorem ipsum dolor sit amet consectetur adipisicing elit.",
},
{
label: "Industri",
value: "Kesehatan",
},
{
label: "Jumlah Partisipan ",
value: "0",
},
{
label: "Lokasi",
value: "Kuta Selatan, Bali",
},
{
label: "Tujuan Proyek",
value:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
},
{
label: "Keuntungan",
value:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
},
];

View File

@@ -0,0 +1,69 @@
import {
ActionIcon,
BaseBox,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { Octicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { Divider } from "react-native-paper";
export default function AdminCollaborationGroup() {
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Collaboration" />}>
<StackCustom gap={"xs"}>
<AdminComp_BoxTitle title="Group" />
<BaseBox>
<AdminTitleTable
title1="Aksi"
title2="Admin Group"
title3="Nama Group"
/>
<Spacing height={10} />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<Octicons
name="eye"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(`/admin/collaboration/${index}/group`);
}}
/>
}
value2={
<TextCustom truncate={1}>Username username </TextCustom>
}
value3={
<TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae
mollitia.
</TextCustom>
}
/>
))}
</BaseBox>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,37 @@
import { StackCustom, ViewWrapper } from "@/components";
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { MainColor } from "@/constants/color-palet";
import { Entypo, FontAwesome } from "@expo/vector-icons";
export default function AdminCollaboration() {
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Collaboration" />}>
<StackCustom gap={"xs"}>
{listData.map((item, i) => (
<AdminComp_BoxDashboard key={i} item={item} />
))}
</StackCustom>
</ViewWrapper>
</>
);
}
const listData = [
{
label: "Publish",
value: 4,
icon: <Entypo name="publish" size={25} color={MainColor.green} />,
},
{
label: "Group",
value: 7,
icon: <FontAwesome name="group" size={25} color={MainColor.yellow} />,
},
{
label: "Reject",
value: 7,
icon: <FontAwesome name="warning" size={25} color={MainColor.red} />,
},
];

View File

@@ -0,0 +1,70 @@
import {
ActionIcon,
BaseBox,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { Octicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { Divider } from "react-native-paper";
export default function AdminCollaborationPublish() {
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Collaboration" />}>
<StackCustom gap={"xs"}>
<AdminComp_BoxTitle title="Publish" />
<BaseBox>
<AdminTitleTable
title1="Aksi"
title2="Username"
title3="Judul Proyek"
/>
<Spacing height={10} />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<Octicons
name="eye"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(`/admin/collaboration/${index}/publish`);
}}
/>
}
value2={
<TextCustom truncate={1}>Username username </TextCustom>
}
value3={
<TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae
mollitia.
</TextCustom>
}
/>
))}
</BaseBox>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,69 @@
import {
ActionIcon,
BaseBox,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { Octicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { Divider } from "react-native-paper";
export default function AdminCollaborationReject() {
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Collaboration" />}>
<StackCustom gap={"xs"}>
<AdminComp_BoxTitle title="Reject" />
<BaseBox>
<AdminTitleTable
title1="Aksi"
title2="Username"
title3="Judul Proyek"
/>
<Spacing height={10} />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<Octicons
name="eye"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(`/admin/collaboration/${index}/reject`);
}}
/>
}
value2={
<TextCustom truncate={1}>Username username </TextCustom>
}
value3={
<TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae
mollitia.
</TextCustom>
}
/>
))}
</BaseBox>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,40 @@
import {
StackCustom,
TextCustom,
ViewWrapper
} from "@/components";
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
import { MainColor } from "@/constants/color-palet";
import { Ionicons } from "@expo/vector-icons";
export default function AdminDashboard() {
return (
<>
<ViewWrapper>
<StackCustom>
<TextCustom bold size={30}>
Main Dashboard
</TextCustom>
{listData.map((item, i) => (
<AdminComp_BoxDashboard key={i} item={item} />
))}
</StackCustom>
</ViewWrapper>
</>
);
}
const listData = [
{
label: "User",
value: 4,
icon: <Ionicons name="people" size={30} color={MainColor.yellow} />,
},
{
label: "Portofolio",
value: 7,
icon: (
<Ionicons name="id-card-outline" size={30} color={MainColor.yellow} />
),
},
];

View File

@@ -0,0 +1,203 @@
import {
ActionIcon,
AlertDefaultSystem,
BadgeCustom,
BaseBox,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconDot, IconView } from "@/components/_Icon/IconComponent";
import { IconTrash } from "@/components/_Icon/IconTrash";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
import { MainColor } from "@/constants/color-palet";
import {
ICON_SIZE_BUTTON,
ICON_SIZE_MEDIUM,
ICON_SIZE_XLARGE,
} from "@/constants/constans-value";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { useState } from "react";
import { Divider } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function AdminForumDetailPosting() {
const [openDrawerPage, setOpenDrawerPage] = useState(false);
const [openDrawerAction, setOpenDrawerAction] = useState(false);
const [id, setId] = useState<any>();
const handlerAction = (item: { value: string; path: string }) => {
if (item.value === "delete") {
AlertDefaultSystem({
title: "Hapus Posting",
message: "Apakah Anda yakin ingin menghapus posting ini?",
textLeft: "Batal",
textRight: "Hapus",
onPressRight: () => {
Toast.show({
type: "success",
text1: "Posting berhasil dihapus",
});
},
});
} else {
router.navigate(item.path as any);
}
setOpenDrawerAction(false);
};
return (
<>
<ViewWrapper
headerComponent={
<AdminBackButtonAntTitle
title="Detail Posting"
rightComponent={
<ActionIcon
icon={<IconDot size={16} color={MainColor.darkblue} />}
onPress={() => setOpenDrawerPage(true)}
/>
}
/>
}
>
<BaseBox>
<StackCustom gap={"sm"}>
{listDataAction.map((item, i) => (
<GridDetail_4_8
key={i}
label={<TextCustom bold>{item.label}</TextCustom>}
value={<TextCustom>{item.value}</TextCustom>}
/>
))}
<TextCustom bold>Posting</TextCustom>
<TextCustom>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Asperiores cupiditate nobis dignissimos explicabo quo unde dolorum
numquam eos ab laborum fugiat illo nam velit quibusdam, maxime
assumenda aut vero provident!
</TextCustom>
</StackCustom>
</BaseBox>
{/* <AdminComp_BoxTitle title="Komentar" rightComponent={rightComponent} /> */}
<BaseBox>
<AdminTitleTable title1="Aksi" title2="Username" title3="Komentar" />
<Spacing />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<Ionicons
name="ellipsis-vertical-outline"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
setOpenDrawerAction(true);
setId(index + 1);
}}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae mollitia.
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
<DrawerCustom
isVisible={openDrawerPage}
closeDrawer={() => setOpenDrawerPage(false)}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: (
<Ionicons
name="list"
size={ICON_SIZE_XLARGE}
color={MainColor.white}
/>
),
label: "Daftar Report Posting",
value: "detail",
path: `/admin/forum/${id}/list-report-posting`,
},
]}
onPressItem={(item) => {
router.navigate(item.path as any);
setOpenDrawerPage(false);
}}
/>
</DrawerCustom>
<DrawerCustom
isVisible={openDrawerAction}
closeDrawer={() => setOpenDrawerAction(false)}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: <IconView />,
label: "Detail Komentar",
value: "detail",
path: `admin/forum/${id}/list-report-comment`,
},
{
icon: (
<IconTrash size={ICON_SIZE_MEDIUM} color={MainColor.white} />
),
label: "Hapus Komentar",
value: "delete",
path: "",
color: MainColor.red,
},
]}
onPressItem={(item) => {
handlerAction(item as any);
}}
/>
</DrawerCustom>
</>
);
}
const listDataAction = [
{
label: "Username",
value: "Username",
},
{
label: "Status",
value: <BadgeCustom color={MainColor.green}>Open</BadgeCustom>,
},
{
label: "Komentar",
value: "10",
},
{
label: "Total Report",
value: "1",
},
];

View File

@@ -0,0 +1,168 @@
import {
ActionIcon,
AlertDefaultSystem,
BaseBox,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconDot, IconView } from "@/components/_Icon/IconComponent";
import { IconTrash } from "@/components/_Icon/IconTrash";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { router } from "expo-router";
import { useState } from "react";
import { Divider } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function AdminForumReportComment() {
const [openDrawer, setOpenDrawer] = useState(false);
const [openDrawerAction, setOpenDrawerAction] = useState(false);
return (
<>
<ViewWrapper
headerComponent={
<AdminBackButtonAntTitle
title="Report Komentar"
rightComponent={
<ActionIcon
icon={<IconDot size={16} color={MainColor.darkblue} />}
onPress={() => setOpenDrawer(true)}
/>
}
/>
}
>
<BaseBox>
<StackCustom gap={"sm"}>
{listData.map((item, i) => (
<GridDetail_4_8
key={i}
label={<TextCustom bold>{item.label}</TextCustom>}
value={<TextCustom>{item.value}</TextCustom>}
/>
))}
<TextCustom bold>Posting</TextCustom>
<TextCustom>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Asperiores cupiditate nobis dignissimos explicabo quo unde dolorum
numquam eos ab laborum fugiat illo nam velit quibusdam, maxime
assumenda aut vero provident!
</TextCustom>
</StackCustom>
</BaseBox>
<AdminComp_BoxTitle title="Daftar Report Komentar" />
<BaseBox>
<AdminTitleTable
title1="Aksi"
title2="Username"
title3="Kategori Report"
/>
<Spacing />
<Divider />
{Array.from({ length: 5 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
onPress={() => {
setOpenDrawerAction(true);
}}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2} align="center">
SPAM
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
<DrawerCustom
isVisible={openDrawer}
closeDrawer={() => setOpenDrawer(false)}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: <IconTrash />,
label: "Hapus Komentar",
value: "delete",
path: "",
color: MainColor.red,
},
]}
onPressItem={(item) => {
AlertDefaultSystem({
title: "Hapus Komentar",
message: "Apakah Anda yakin ingin menghapus komentar ini?",
textLeft: "Batal",
textRight: "Hapus",
onPressRight: () => {
setOpenDrawer(false);
Toast.show({
type: "success",
text1: "Komentar berhasil dihapus",
});
router.back();
},
});
}}
/>
</DrawerCustom>
<DrawerCustom
isVisible={openDrawerAction}
closeDrawer={() => setOpenDrawerAction(false)}
height={"auto"}
>
{listDataAction.map((item, i) => (
<GridDetail_4_8
key={i}
label={<TextCustom bold>{item.label}</TextCustom>}
value={<TextCustom>{item.value}</TextCustom>}
/>
))}
</DrawerCustom>
</>
);
}
const listData = [
{
label: "Username",
value: "Username",
},
];
const listDataAction = [
{
label: "Username",
value: "Riyusa",
},
{
label: "Kategori Report",
value: "SPAM",
},
{
label: "Deskripsi",
value:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Blanditiis asperiores quidem deleniti architecto eaque et nostrum, ad consequuntur eveniet quisquam quae voluptatum ducimus! Dolorem nobis modi officia debitis, beatae mollitia.",
},
];

View File

@@ -0,0 +1,170 @@
import {
ActionIcon,
AlertDefaultSystem,
BadgeCustom,
BaseBox,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconDot, IconView } from "@/components/_Icon/IconComponent";
import { IconTrash } from "@/components/_Icon/IconTrash";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { router } from "expo-router";
import { useState } from "react";
import { Divider } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function AdminForumReportPosting() {
const [openDrawerPage, setOpenDrawerPage] = useState(false);
const [openDrawerAction, setOpenDrawerAction] = useState(false);
return (
<>
<ViewWrapper
headerComponent={
<AdminBackButtonAntTitle
title="Report Posting"
rightComponent={
<ActionIcon
icon={<IconDot size={16} color={MainColor.darkblue} />}
onPress={() => setOpenDrawerPage(true)}
/>
}
/>
}
>
<BaseBox>
<StackCustom gap={"sm"}>
{listData.map((item, i) => (
<GridDetail_4_8
key={i}
label={<TextCustom bold>{item.label}</TextCustom>}
value={<TextCustom>{item.value}</TextCustom>}
/>
))}
<TextCustom bold>Posting</TextCustom>
<TextCustom>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Asperiores cupiditate nobis dignissimos explicabo quo unde dolorum
numquam eos ab laborum fugiat illo nam velit quibusdam, maxime
assumenda aut vero provident!
</TextCustom>
</StackCustom>
</BaseBox>
<AdminComp_BoxTitle title="Daftar Report Posting" />
<BaseBox>
<AdminTitleTable
title1="Aksi"
title2="Username"
title3="Kategori Report"
/>
<Spacing />
<Divider />
{Array.from({ length: 5 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
onPress={() => setOpenDrawerAction(true)}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2} align="center">
SPAM
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
<DrawerCustom
isVisible={openDrawerPage}
closeDrawer={() => setOpenDrawerPage(false)}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: <IconTrash />,
label: "Hapus Posting",
value: "delete",
path: "",
color: MainColor.red,
},
]}
onPressItem={(item) => {
AlertDefaultSystem({
title: "Hapus Posting",
message: "Apakah Anda yakin ingin menghapus posting ini?",
textLeft: "Batal",
textRight: "Hapus",
onPressRight: () => {
setOpenDrawerPage(false);
Toast.show({
type: "success",
text1: "Posting berhasil dihapus",
});
router.back()
},
});
}}
/>
</DrawerCustom>
<DrawerCustom
isVisible={openDrawerAction}
closeDrawer={() => setOpenDrawerAction(false)}
height={"auto"}
>
{listDataAction.map((item, i) => (
<GridDetail_4_8
key={i}
label={<TextCustom bold>{item.label}</TextCustom>}
value={<TextCustom>{item.value}</TextCustom>}
/>
))}
</DrawerCustom>
</>
);
}
const listData = [
{
label: "Username",
value: "Username",
},
{
label: "Status",
value: <BadgeCustom color={MainColor.green}>Open</BadgeCustom>,
},
];
const listDataAction = [
{
label: "Username",
value: "Firman Nusantara",
},
{
label: "Kategori Report",
value: "SPAM",
},
{
label: "Deskripsi",
value:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Blanditiis asperiores quidem deleniti architecto eaque et nostrum, ad consequuntur eveniet quisquam quae voluptatum ducimus! Dolorem nobis modi officia debitis, beatae mollitia.",
},
];

View File

@@ -0,0 +1,42 @@
import { Spacing, StackCustom, ViewWrapper } from "@/components";
import {
IconPublish,
IconReport,
} from "@/components/_Icon/IconComponent";
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { MainColor } from "@/constants/color-palet";
export default function AdminForum() {
return (
<>
<ViewWrapper>
<AdminTitlePage title="Forum" />
<Spacing />
<StackCustom gap={"xs"}>
{listData.map((item, i) => (
<AdminComp_BoxDashboard key={i} item={item} />
))}
</StackCustom>
</ViewWrapper>
</>
);
}
const listData = [
{
label: "Posting",
value: 4,
icon: <IconPublish size={25} color={MainColor.green} />,
},
{
label: "Report Posting",
value: 7,
icon: <IconReport size={25} color={MainColor.orange} />,
},
{
label: "Report Comment",
value: 5,
icon: <IconReport size={25} color={MainColor.red} />,
},
];

View File

@@ -0,0 +1,61 @@
import {
ActionIcon,
BaseBox,
SearchInput,
Spacing,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconView } from "@/components/_Icon/IconComponent";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { router } from "expo-router";
import React from "react";
import { Divider } from "react-native-paper";
export default function AdminForumPosting() {
const rightComponent = (
<SearchInput
containerStyle={{ width: "100%", marginBottom: 0 }}
placeholder="Cari"
/>
);
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Forum" />}>
<AdminComp_BoxTitle title={"Posting"} rightComponent={rightComponent} />
<BaseBox>
<AdminTitleTable title1="Aksi" title2="Username" title3="Postingan" />
<Spacing />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
onPress={() => {
router.push(`/admin/forum/${index + 1}`);
}}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae mollitia.
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,65 @@
import {
ActionIcon,
BaseBox,
Divider,
SearchInput,
Spacing,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconView } from "@/components/_Icon/IconComponent";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { router } from "expo-router";
export default function AdminForumReportComment() {
const rightComponent = (
<SearchInput
containerStyle={{ width: "100%", marginBottom: 0 }}
placeholder="Cari Komentar"
/>
);
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Forum" />}>
<AdminComp_BoxTitle
title="Report Comment"
rightComponent={rightComponent}
/>
<BaseBox>
<AdminTitleTable title1="Aksi" title2="Pelapor" title3="Jenis Laporan" />
<Spacing />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<IconView size={ICON_SIZE_BUTTON} color={MainColor.black} />
}
onPress={() => {
router.push(`/admin/forum/${index + 1}/list-report-comment`);
}}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2} align="center">
SPAM
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,73 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
ActionIcon,
BaseBox,
Divider,
SearchInput,
Spacing,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconView } from "@/components/_Icon/IconComponent";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { router } from "expo-router";
import { useState } from "react";
export default function AdminForumReportPosting() {
const [openDrawer, setOpenDrawer] = useState(false);
const [id, setId] = useState<any>();
const rightComponent = (
<SearchInput
containerStyle={{ width: "100%", marginBottom: 0 }}
placeholder="Cari"
/>
);
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Forum" />}>
<AdminComp_BoxTitle
title="Report Posting"
rightComponent={rightComponent}
/>
<BaseBox>
<AdminTitleTable title1="Aksi" title2="Pelapor" title3="Postingan" />
<Spacing />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<IconView size={ICON_SIZE_BUTTON} color={MainColor.black} />
}
onPress={() => {
router.push(`/admin/forum/${id}/list-report-posting`);
}}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2} align="center">
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Omnis laborum doloremque eius velit voluptate corrupti vel,
provident quaerat tempore animi sed accusamus amet.
Temporibus, praesentium? Rem voluptatum nesciunt voluptas
repellat.
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,11 @@
import { TextCustom, ViewWrapper } from "@/components";
export default function AdminInvestment() {
return (
<>
<ViewWrapper>
<TextCustom>Admin Investment</TextCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,11 @@
import { TextCustom, ViewWrapper } from "@/components";
export default function AdminInvestmentPublish() {
return (
<>
<ViewWrapper>
<TextCustom>Admin Investment Publish</TextCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,11 @@
import { TextCustom, ViewWrapper } from "@/components";
export default function AdminInvestmentReject() {
return (
<>
<ViewWrapper>
<TextCustom>Admin Investment Reject</TextCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,11 @@
import { TextCustom, ViewWrapper } from "@/components";
export default function AdminInvestmentReview() {
return (
<>
<ViewWrapper>
<TextCustom>Admin Investment Review</TextCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,110 @@
import {
BadgeCustom,
BaseBox,
ButtonCustom,
DummyLandscapeImage,
Grid,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { MainColor } from "@/constants/color-palet";
import { useLocalSearchParams } from "expo-router";
import _ from "lodash";
export default function AdminJobDetailStatus() {
const { id, status } = useLocalSearchParams();
const colorBadge = () => {
if (status === "publish") {
return MainColor.green;
} else if (status === "review") {
return MainColor.orange;
} else if (status === "reject") {
return MainColor.red;
}
};
const listData = [
{
label: "Username",
value: "Bagas Banuna",
},
{
label: "Judul",
value: `Judul Proyek: ${id}Lorem ipsum dolor sit amet consectetur adipisicing elit.`,
},
{
label: "Status",
value: (
<BadgeCustom color={colorBadge()}>
{_.startCase(status as string)}
</BadgeCustom>
),
},
{
label: "Konten",
value: "Lorem ipsum dolor sit amet consectetur adipisicing elit.",
},
{
label: "Deskripsi",
value: "Lorem ipsum dolor sit amet consectetur adipisicing elit.",
},
// {
// label: "Poster",
// value: (
// <ButtonCustom
// href={`/(application)/()/${id}`}
// >
// Lihat Poster
// </ButtonCustom>
// ),
// },
];
return (
<>
<ViewWrapper
headerComponent={<AdminBackButtonAntTitle title={`Detail Data`} />}
>
<BaseBox>
<StackCustom>
{listData.map((item, i) => (
<Grid key={i}>
<Grid.Col
span={4}
style={{ justifyContent: "center", paddingRight: 10 }}
>
<TextCustom bold>{item.label}</TextCustom>
</Grid.Col>
<Grid.Col span={8} style={{ justifyContent: "center" }}>
<TextCustom>{item.value}</TextCustom>
</Grid.Col>
</Grid>
))}
<TextCustom bold>Poster</TextCustom>
<DummyLandscapeImage />
</StackCustom>
</BaseBox>
{status === "review" && (
<Grid>
<Grid.Col span={6} style={{ paddingRight: 10 }}>
<ButtonCustom backgroundColor={MainColor.green} textColor="white">
Publish
</ButtonCustom>
</Grid.Col>
<Grid.Col span={6} style={{ paddingLeft: 10 }}>
<ButtonCustom backgroundColor={MainColor.red} textColor="white">
Reject
</ButtonCustom>
</Grid.Col>
</Grid>
)}
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,76 @@
import {
ActionIcon,
BaseBox,
SearchInput,
Spacing,
TextCustom,
ViewWrapper
} from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { Octicons } from "@expo/vector-icons";
import { router, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { Divider } from "react-native-paper";
export default function AdminJobStatus() {
const { status } = useLocalSearchParams();
const rightComponent = (
<SearchInput
containerStyle={{ width: "100%", marginBottom: 0 }}
placeholder="Cari"
/>
);
return (
<>
<ViewWrapper headerComponent={<AdminTitlePage title="Job Vacancy" />}>
<AdminComp_BoxTitle
title={`${_.startCase(status as string)}`}
rightComponent={rightComponent}
/>
<BaseBox>
<AdminTitleTable
title1="Aksi"
title2="Username"
title3="Judul Pekerjaan"
/>
<Spacing />
<Divider />
{Array.from({ length: 10 }).map((_, index) => (
<AdminTableValue
key={index}
value1={
<ActionIcon
icon={
<Octicons
name="eye"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(`/admin/job/${index}/${status}`);
}}
/>
}
value2={<TextCustom truncate={1}>Username username</TextCustom>}
value3={
<TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae mollitia.
</TextCustom>
}
/>
))}
</BaseBox>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,43 @@
import { Spacing, StackCustom, ViewWrapper } from "@/components";
import {
IconPublish,
IconReject,
IconReview,
} from "@/components/_Icon/IconComponent";
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { MainColor } from "@/constants/color-palet";
export default function AdminJob() {
return (
<>
<ViewWrapper>
<AdminTitlePage title="Job Vacancy" />
<Spacing />
<StackCustom gap={"xs"}>
{listData.map((item, i) => (
<AdminComp_BoxDashboard key={i} item={item} />
))}
</StackCustom>
</ViewWrapper>
</>
);
}
const listData = [
{
label: "Publish",
value: 4,
icon: <IconPublish size={25} color={MainColor.green} />,
},
{
label: "Review",
value: 7,
icon: <IconReview size={25} color={MainColor.orange} />,
},
{
label: "Reject",
value: 5,
icon: <IconReject size={25} color={MainColor.red} />,
},
];

View File

@@ -0,0 +1,11 @@
import { MapCustom, ViewWrapper } from "@/components";
export default function AdminMaps() {
return (
<>
<ViewWrapper>
<MapCustom height={"100%"} />
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,20 @@
import { BackButton, TextCustom, ViewWrapper } from "@/components";
import { Stack } from "expo-router";
export default function AdminNotification() {
return (
<>
<Stack.Screen
options={{
title: "Admin Notifikasi",
headerLeft: () => <BackButton />,
headerRight: () => <></>,
}}
/>
<ViewWrapper>
<TextCustom>Notification</TextCustom>
</ViewWrapper>
</>
);
}

View File

@@ -0,0 +1,117 @@
import {
ButtonCustom,
Divider,
Grid,
SearchInput,
StackCustom,
TextCustom,
ViewWrapper
} from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
import { Ionicons } from "@expo/vector-icons";
export default function AdminUserAccess() {
const rightComponent = () => {
return (
<>
<SearchInput
containerStyle={{ width: "100%", marginBottom: 0 }}
placeholder="Cari User"
/>
</>
);
};
return (
<>
<ViewWrapper
headerComponent={
<AdminComp_BoxTitle
title="User Access"
rightComponent={rightComponent()}
/>
}
>
<Grid>
<Grid.Col span={4} style={{ alignItems: "center" }}>
<TextCustom bold>Aksi</TextCustom>
</Grid.Col>
<Grid.Col span={4} style={{ alignItems: "center" }}>
<TextCustom bold>Username</TextCustom>
</Grid.Col>
<Grid.Col span={4} style={{ alignItems: "center" }}>
<TextCustom bold>Nomor</TextCustom>
</Grid.Col>
</Grid>
<Divider />
<StackCustom>
{Array.from({ length: 10 }).map((_, index) => (
<Grid key={index}>
<Grid.Col
span={4}
style={{
alignItems: "center",
paddingLeft: 5,
paddingRight: 5,
}}
>
<TextCustom bold>
<ButtonCustom
iconLeft={
<Ionicons
name={
index % 2 === 0
? "checkmark-outline"
: "close-circle-outline"
}
size={ICON_SIZE_MEDIUM}
color="black"
/>
}
onPress={() => {}}
backgroundColor={
index % 2 === 0 ? MainColor.green : MainColor.red
}
>
<TextCustom size={"small"} color={"black"}>
{index % 2 === 0 ? "Berikan Akses" : "Hapus Akses"}
</TextCustom>
</ButtonCustom>
</TextCustom>
</Grid.Col>
<Grid.Col
span={4}
style={{
alignItems: "center",
justifyContent: "center",
paddingLeft: 5,
paddingRight: 5,
}}
>
<TextCustom bold truncate>
Useraname
</TextCustom>
</Grid.Col>
<Grid.Col
span={4}
style={{
alignItems: "center",
justifyContent: "center",
paddingLeft: 5,
paddingRight: 5,
}}
>
<TextCustom bold truncate>
08123456789
</TextCustom>
</Grid.Col>
</Grid>
))}
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -2,6 +2,7 @@ import { MainColor } from "@/constants/color-palet";
import { Stack } from "expo-router";
import "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";
import Toast from "react-native-toast-message";
export default function RootLayout() {
return (
@@ -14,7 +15,10 @@ export default function RootLayout() {
headerTitleAlign: "center",
}}
>
<Stack.Screen name="index" options={{ title: "" }} />
<Stack.Screen
name="index"
options={{ title: "", headerBackVisible: false }}
/>
<Stack.Screen name="+not-found" options={{ title: "" }} />
<Stack.Screen
name="verification"
@@ -27,6 +31,7 @@ export default function RootLayout() {
<Stack.Screen name="(application)" options={{ headerShown: false }} />
</Stack>
</SafeAreaProvider>
<Toast />
</>
);
}

View File

@@ -45,6 +45,7 @@
"react-native-reanimated": "~3.17.4",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
"react-native-toast-message": "^2.3.3",
"react-native-vector-icons": "^10.2.0",
"react-native-web": "~0.20.0",
"react-native-webview": "13.13.5",
@@ -1413,6 +1414,8 @@
"react-native-screens": ["react-native-screens@4.11.1", "", { "dependencies": { "react-freeze": "^1.0.0", "react-native-is-edge-to-edge": "^1.1.7", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-F0zOzRVa3ptZfLpD0J8ROdo+y1fEPw+VBFq1MTY/iyDu08al7qFUO5hLMd+EYMda5VXGaTFCa8q7bOppUszhJw=="],
"react-native-toast-message": ["react-native-toast-message@2.3.3", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4IIUHwUPvKHu4gjD0Vj2aGQzqPATiblL1ey8tOqsxOWRPGGu52iIbL8M/mCz4uyqecvPdIcMY38AfwRuUADfQQ=="],
"react-native-vector-icons": ["react-native-vector-icons@10.2.0", "", { "dependencies": { "prop-types": "^15.7.2", "yargs": "^16.1.1" }, "bin": { "fa-upgrade.sh": "bin/fa-upgrade.sh", "fa5-upgrade": "bin/fa5-upgrade.sh", "fa6-upgrade": "bin/fa6-upgrade.sh", "generate-icon": "bin/generate-icon.js" } }, "sha512-n5HGcxUuVaTf9QJPs/W22xQpC2Z9u0nb0KgLPnVltP8vdUvOp6+R26gF55kilP/fV4eL4vsAHUqUjewppJMBOQ=="],
"react-native-web": ["react-native-web@0.20.0", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-OOSgrw+aON6R3hRosCau/xVxdLzbjEcsLysYedka0ZON4ZZe6n9xgeN9ZkoejhARM36oTlUgHIQqxGutEJ9Wxg=="],

View File

@@ -0,0 +1,59 @@
import { MainColor } from "@/constants/color-palet";
import { Href, router } from "expo-router";
import { DimensionValue, TouchableOpacity } from "react-native";
type SizeType = "xs" | "sm" | "md" | "lg" | "xl" | number | string | undefined;
export default function ActionIcon({
href,
onPress,
icon,
size = "md",
}: {
href?: Href;
onPress?: () => void;
icon: React.ReactNode;
size?: SizeType;
}) {
const sizeMap = {
xs: 22,
sm: 26,
md: 30,
lg: 34,
xl: 38,
};
const getSize = (size: SizeType): DimensionValue => {
if (!size) return sizeMap.md; // Default to 'md' if size is undefined
if (typeof size === 'string' && size in sizeMap) {
return sizeMap[size as keyof typeof sizeMap];
}
return size as DimensionValue;
};
const iconSize = getSize(size);
return (
<TouchableOpacity
activeOpacity={0.7}
style={{
backgroundColor: MainColor.yellow,
padding: 5,
borderRadius: 50,
alignItems: "center",
justifyContent: "center",
width: iconSize,
height: iconSize,
}}
onPress={() => {
if (href) {
router.push(href);
} else {
onPress?.();
}
}}
>
{icon}
</TouchableOpacity>
);
}

View File

@@ -3,8 +3,9 @@ import { Ionicons } from "@expo/vector-icons";
import Grid from "../Grid/GridCustom";
import TextCustom from "../Text/TextCustom";
import BaseBox from "./BaseBox";
import React from "react";
export default function InformationBox({ text }: { text: string }) {
export default function InformationBox({ text }: { text: React.ReactNode | string }) {
return (
<>
<BaseBox paddingTop={5} paddingBottom={5}>

View File

@@ -1,4 +1,4 @@
import { AccentColor } from "@/constants/color-palet";
import { AccentColor, MainColor } from "@/constants/color-palet";
import { MaterialIcons } from "@expo/vector-icons"; // Bisa diganti dengan ikon lain
import React, { useContext } from "react";
import { Animated, Text, TouchableOpacity, View } from "react-native";
@@ -17,7 +17,7 @@ const CheckboxGroupContext =
// Tipe props
// Tambahkan prop baru: groupValueKey
interface CheckboxProps {
label?: string;
label?: string | React.ReactNode;
description?: string;
error?: string;
value?: boolean; // controlled value (untuk standalone)
@@ -39,7 +39,7 @@ const CheckboxCustom: React.FC<CheckboxProps> = ({
onChange,
disabled: propDisabled,
size = 20,
color = AccentColor.softblue,
color = MainColor.yellow,
style,
component,
valueKey,

View File

@@ -1,22 +1,28 @@
import { MainColor } from "@/constants/color-palet";
import React from "react";
import { StyleSheet, TextInput, View } from "react-native";
import { StyleProp, StyleSheet, TextInput, View, ViewStyle } from "react-native";
interface CircularInputProps {
value: string | number;
onChange?: (value: string) => void;
value?: string | number
onChange?: (value: string | number) => void;
icon?: React.ReactNode;
style?: StyleProp<ViewStyle>
}
const CircularInput: React.FC<CircularInputProps> = ({ value, onChange }) => {
const CircularInput: React.FC<CircularInputProps> = ({ value, onChange, icon, style }) => {
return (
<View style={styles.circleContainer}>
<TextInput
value={String(value)}
onChangeText={onChange}
style={styles.input}
keyboardType="numeric"
maxLength={2} // Batasan maksimal karakter
/>
<View style={[styles.circleContainer, style]}>
{icon ? (
icon
) : (
<TextInput
value={String(value)}
onChangeText={onChange}
style={styles.input}
keyboardType="numeric"
maxLength={2} // Batasan maksimal karakter
/>
)}
</View>
);
};

View File

@@ -2,8 +2,8 @@ import { AccentColor } from "@/constants/color-palet";
import { View } from "react-native";
export default function Divider({
color = AccentColor.blue,
size = 1,
color = AccentColor.white,
size = 0.5,
marginTop= 12,
marginBottom= 12,
}: {

View File

@@ -0,0 +1,157 @@
import React, { useEffect, useRef } from "react";
import {
Animated,
Dimensions,
InteractionManager,
PanResponder,
StyleSheet,
} from "react-native";
import { AccentColor, MainColor } from "@/constants/color-palet";
import { SafeAreaView } from "react-native-safe-area-context";
// Lebar drawer (bisa di-pass sebagai prop)
const DRAWER_WIDTH = Dimensions.get("window").width * 0.8; // 80% lebar layar
interface DrawerAdminProps {
children?: React.ReactNode;
width?: number; // lebar drawer
isVisible: boolean;
onClose: () => void; // ganti nama dari closeDrawer agar lebih jelas
}
export default function DrawerAdmin({
children,
width = DRAWER_WIDTH,
isVisible,
onClose,
}: DrawerAdminProps) {
const drawerAnim = useRef(new Animated.Value(-width)).current; // mulai dari kiri (tersembunyi)
// Efek untuk handle animasi saat isVisible berubah
useEffect(() => {
if (isVisible) {
Animated.timing(drawerAnim, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start();
} else {
Animated.timing(drawerAnim, {
toValue: -width,
duration: 300,
useNativeDriver: true,
}).start();
}
}, [isVisible, width, onClose, drawerAnim]);
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: (_, gestureState) => {
return Math.abs(gestureState.dx) > 10; // deteksi gesek horizontal
},
onPanResponderMove: (_, gestureState) => {
let newAnim = gestureState.dx; // geser ke kanan = dx positif → drawerAnim negatif
newAnim = Math.max(-width, Math.min(0, newAnim)); // batas antara -width dan 0
drawerAnim.setValue(newAnim);
},
onPanResponderRelease: (_, gestureState) => {
if (gestureState.dx > 100) {
// gesek kencang ke kiri → tutup
InteractionManager.runAfterInteractions(() => {
onClose();
});
} else {
// kembali ke posisi terbuka penuh
Animated.spring(drawerAnim, {
toValue: 0,
useNativeDriver: true,
}).start();
}
},
})
).current;
if (!isVisible) return null;
return (
<>
{/* Overlay Gelap */}
<Animated.View
style={[
styles.overlay,
{
opacity: drawerAnim.interpolate({
inputRange: [-width, 0],
outputRange: [0, 0.6],
extrapolate: "clamp",
}),
},
]}
onTouchStart={() => {
InteractionManager.runAfterInteractions(() => {
onClose();
});
}}
/>
{/* Left Drawer */}
<Animated.View
style={[
styles.drawer,
{
width,
transform: [{ translateX: drawerAnim }],
},
]}
{...panResponder.panHandlers}
>
{/* Handle Bar (opsional) */}
<SafeAreaView
edges={["top", "bottom"]}
style={{
flex: 1,
}}
>
{children}
{/* <Spacing/> */}
</SafeAreaView>
</Animated.View>
</>
);
}
const styles = StyleSheet.create({
overlay: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "black",
zIndex: 998,
},
drawer: {
position: "absolute",
top: 0,
bottom: 0,
left: 0,
backgroundColor: AccentColor.darkblue,
// borderRadius: 20, // opsional
shadowColor: "#000",
shadowOffset: { width: 2, height: 0 },
shadowOpacity: 0.2,
shadowRadius: 5,
elevation: 5,
zIndex: 999,
padding: 20,
},
handleBar: {
width: 10,
height: 5,
backgroundColor: MainColor.yellow,
borderRadius: 5,
alignSelf: "flex-start",
marginBottom: 20,
},
});

View File

@@ -7,7 +7,8 @@ import { Href } from "expo-router";
type IMenuDrawerItemProps = {
icon: React.ReactNode;
label: string;
path?: Href;
value?: string;
path?: Href | string;
color?: string;
}

View File

@@ -0,0 +1,276 @@
import { AccentColor, MainColor } from "@/constants/color-palet";
import { Ionicons } from "@expo/vector-icons";
import { router, usePathname } from "expo-router";
import React, { useEffect, useRef, useState } from "react";
import {
Animated,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
export interface NavbarItem {
label: string;
icon?: keyof typeof Ionicons.glyphMap;
color?: string;
link?: string;
links?: {
label: string;
link: string;
}[];
initiallyOpened?: boolean;
}
interface NavbarMenuProps {
items: NavbarItem[];
onClose?: () => void;
}
export default function NavbarMenu({ items, onClose }: NavbarMenuProps) {
const pathname = usePathname();
const [activeLink, setActiveLink] = useState<string | null>(null);
const [openKeys, setOpenKeys] = useState<string[]>([]); // Untuk kontrol dropdown
// Normalisasi path: hapus trailing slash
const normalizePath = (path: string) => path.replace(/\/+$/, "");
const normalizedPathname = pathname ? normalizePath(pathname) : "";
// Set activeLink saat pathname berubah
useEffect(() => {
if (normalizedPathname) {
setActiveLink(normalizedPathname);
}
}, [normalizedPathname]);
// Toggle dropdown
const toggleOpen = (label: string) => {
setOpenKeys((prev) =>
prev.includes(label) ? prev.filter((key) => key !== label) : [label]
);
};
return (
<View
style={{
// flex: 1,
// backgroundColor: MainColor.black,
marginBottom: 20,
}}
>
<ScrollView
contentContainerStyle={{
paddingVertical: 10, // Opsional: tambahkan padding
}}
// showsVerticalScrollIndicator={false} // Opsional: sembunyikan indikator scroll
>
{items.map((item) => (
<MenuItem
key={item.label}
item={item}
onClose={onClose}
activeLink={activeLink}
setActiveLink={setActiveLink}
isOpen={openKeys.includes(item.label)}
toggleOpen={() => toggleOpen(item.label)}
/>
))}
</ScrollView>
</View>
);
}
// Komponen Item Menu
function MenuItem({
item,
onClose,
activeLink,
setActiveLink,
isOpen,
toggleOpen,
}: {
item: NavbarItem;
onClose?: () => void;
activeLink: string | null;
setActiveLink: (link: string | null) => void;
isOpen: boolean;
toggleOpen: () => void;
}) {
const isActive = activeLink === item.link;
const animatedHeight = useRef(new Animated.Value(0)).current;
// Animasi saat isOpen berubah
React.useEffect(() => {
Animated.timing(animatedHeight, {
toValue: isOpen ? (item.links ? item.links.length * 40 : 0) : 0,
duration: 200,
useNativeDriver: false,
}).start();
}, [isOpen, item.links, animatedHeight]);
// Jika ada submenu
if (item.links && item.links.length > 0) {
return (
<View>
{/* Parent Item */}
<TouchableOpacity style={styles.parentItem} onPress={toggleOpen}>
<Ionicons
name={item.icon}
size={16}
color={MainColor.white}
style={styles.icon}
/>
<Text style={styles.parentText}>{item.label}</Text>
<Ionicons
name={isOpen ? "chevron-up" : "chevron-down"}
size={16}
color={MainColor.white}
/>
</TouchableOpacity>
{/* Submenu (Animated) */}
<Animated.View
style={[
styles.submenu,
// {
// backgroundColor: "red",
// },
{
height: animatedHeight,
opacity: animatedHeight.interpolate({
inputRange: [0, item.links.length * 40],
outputRange: [0, 1],
extrapolate: "clamp",
}),
},
]}
>
{item.links.map((subItem, index) => {
const isSubActive = activeLink === subItem.link;
return (
<TouchableOpacity
key={index}
style={[styles.subItem, isSubActive && styles.subItemActive]}
onPress={() => {
setActiveLink(subItem.link);
onClose?.();
router.push(subItem.link as any);
}}
>
<Ionicons
name="radio-button-on-outline"
size={16}
color={isSubActive ? MainColor.yellow : MainColor.white}
style={styles.icon}
/>
<Text
style={[
styles.subText,
isSubActive && { color: MainColor.yellow },
]}
>
{subItem.label}
</Text>
</TouchableOpacity>
);
})}
</Animated.View>
</View>
);
}
// Menu tanpa submenu
return (
<TouchableOpacity
style={[styles.singleItem, isActive && styles.singleItemActive]}
onPress={() => {
setActiveLink(item.link || null);
onClose?.();
router.push(item.link as any);
}}
>
<Ionicons
name={item.icon}
size={16}
color={isActive ? MainColor.yellow : MainColor.white}
style={styles.icon}
/>
<Text
style={[
styles.singleText,
{ color: isActive ? MainColor.yellow : MainColor.white },
]}
>
{item.label}
</Text>
</TouchableOpacity>
);
}
// Styles
const styles = StyleSheet.create({
container: {
marginBottom: 5,
},
parentItem: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 12,
paddingHorizontal: 10,
// backgroundColor: AccentColor.darkblue,
borderRadius: 8,
marginBottom: 5,
justifyContent: "space-between",
},
parentText: {
flex: 1,
fontSize: 16,
fontWeight: "500",
marginLeft: 10,
color: MainColor.white,
},
singleItem: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 12,
paddingHorizontal: 10,
// backgroundColor: AccentColor.darkblue,
borderRadius: 8,
marginBottom: 5,
},
singleItemActive: {
backgroundColor: AccentColor.blue,
},
singleText: {
fontSize: 16,
fontWeight: "500",
marginLeft: 10,
color: MainColor.white,
},
icon: {
width: 24,
textAlign: "center",
paddingRight: 10,
},
submenu: {
overflow: "hidden",
marginLeft: 30,
marginTop: 5,
},
subItem: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 6,
marginBottom: 4,
},
subItemActive: {
backgroundColor: AccentColor.blue,
},
subText: {
color: MainColor.white,
fontSize: 16,
fontWeight: "500",
},
});

View File

@@ -0,0 +1,279 @@
import React, { useEffect, useRef, useState } from "react";
import {
Animated,
Dimensions,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
import { AccentColor, MainColor } from "@/constants/color-palet";
import { Ionicons } from "@expo/vector-icons";
import { router, usePathname } from "expo-router";
// Lebar sidebar
const SIDEBAR_WIDTH = Dimensions.get("window").width * 0.8;
interface SidebarItem {
label: string;
icon?: keyof typeof Ionicons.glyphMap;
color?: string;
link?: string;
links?: {
label: string;
link: string;
}[];
initiallyOpened?: boolean;
}
interface SidebarMenuProps {
items: SidebarItem[];
onClose?: () => void;
}
export default function SidebarMenu({ items, onClose }: SidebarMenuProps) {
const pathname = usePathname();
const [activeLink, setActiveLink] = useState<string | null>(null);
const [openKeys, setOpenKeys] = useState<string[]>([]); // Untuk kontrol dropdown
// Normalisasi path: hapus trailing slash
const normalizePath = (path: string) => path.replace(/\/+$/, "");
const normalizedPathname = pathname ? normalizePath(pathname) : "";
// Set activeLink saat pathname berubah
useEffect(() => {
if (normalizedPathname) {
setActiveLink(normalizedPathname);
}
}, [normalizedPathname]);
// Auto-buka dropdown jika submenu aktif
useEffect(() => {
const activeItem = items.find((item) =>
item.links?.some((sub) => sub.link === normalizedPathname)
);
if (activeItem && !openKeys.includes(activeItem.label)) {
setOpenKeys([activeItem.label]);
}
}, [normalizedPathname, items, openKeys]);
// Toggle dropdown
const toggleOpen = (label: string) => {
setOpenKeys((prev) =>
prev.includes(label) ? prev.filter((key) => key !== label) : [label]
);
};
return (
<View style={styles.container}>
{items.map((item) => (
<MenuItem
key={item.label}
item={item}
onClose={onClose}
activeLink={activeLink}
setActiveLink={setActiveLink}
isOpen={openKeys.includes(item.label)}
toggleOpen={() => toggleOpen(item.label)}
/>
))}
</View>
);
}
// Komponen Item Menu
function MenuItem({
item,
onClose,
activeLink,
setActiveLink,
isOpen,
toggleOpen,
}: {
item: SidebarItem;
onClose?: () => void;
activeLink: string | null;
setActiveLink: (link: string | null) => void;
isOpen: boolean;
toggleOpen: () => void;
}) {
const animatedHeight = useRef(new Animated.Value(0)).current;
// Animasi saat isOpen berubah
React.useEffect(() => {
Animated.timing(animatedHeight, {
toValue: isOpen ? (item.links ? item.links.length * 40 : 0) : 0,
duration: 200,
useNativeDriver: false,
}).start();
}, [isOpen, item.links]);
// Cek apakah menu ini aktif
const isActive = activeLink === item.link;
// Cek apakah ada submenu aktif
const hasActiveSubItem = item.links?.some((sub) => sub.link === activeLink);
// Jika ada submenu
if (item.links && item.links.length > 0) {
return (
<View>
{/* Parent Item */}
<TouchableOpacity style={styles.parentItem} onPress={toggleOpen}>
<Ionicons
name={item.icon}
size={20}
color={MainColor.white}
style={styles.icon}
/>
<Text style={styles.parentText}>{item.label}</Text>
<Ionicons
name={isOpen ? "chevron-up" : "chevron-down"}
size={16}
color={MainColor.white}
/>
</TouchableOpacity>
{/* Submenu (Animated) */}
<Animated.View
style={[
styles.submenu,
{
height: animatedHeight,
opacity: animatedHeight.interpolate({
inputRange: [0, item.links.length * 40],
outputRange: [0, 1],
extrapolate: "clamp",
}),
},
]}
>
{item.links.map((subItem, index) => {
const isSubActive = activeLink === subItem.link;
return (
<TouchableOpacity
key={index}
style={[styles.subItem, isSubActive && styles.subItemActive]}
onPress={() => {
setActiveLink(subItem.link);
onClose?.();
router.push(subItem.link as any);
}}
>
<Ionicons
name="caret-forward-sharp"
size={16}
color={isSubActive ? MainColor.yellow : MainColor.white}
style={styles.icon}
/>
<Text
style={[
styles.subText,
isSubActive && { color: MainColor.yellow },
]}
>
{subItem.label}
</Text>
</TouchableOpacity>
);
})}
</Animated.View>
</View>
);
}
// Menu tanpa submenu
return (
<TouchableOpacity
style={[styles.singleItem, isActive && styles.singleItemActive]}
onPress={() => {
setActiveLink(item.link || null);
onClose?.();
router.push(item.link as any);
}}
>
<Ionicons
name={item.icon}
size={20}
color={isActive ? MainColor.yellow : MainColor.white}
style={styles.icon}
/>
<Text
style={[
styles.singleText,
{ color: isActive ? MainColor.yellow : MainColor.white },
]}
>
{item.label}
</Text>
</TouchableOpacity>
);
}
// Styles
const styles = StyleSheet.create({
container: {
marginTop: 20,
},
parentItem: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 12,
paddingHorizontal: 10,
backgroundColor: AccentColor.darkblue,
borderRadius: 8,
marginBottom: 5,
justifyContent: "space-between",
},
parentText: {
flex: 1,
fontSize: 16,
fontWeight: "500",
marginLeft: 10,
color: MainColor.white,
},
singleItem: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 12,
paddingHorizontal: 10,
backgroundColor: AccentColor.darkblue,
borderRadius: 8,
marginBottom: 5,
},
singleItemActive: {
backgroundColor: AccentColor.blue,
},
singleText: {
fontSize: 16,
fontWeight: "500",
marginLeft: 10,
color: MainColor.white,
},
icon: {
width: 24,
textAlign: "center",
paddingRight: 10,
},
submenu: {
overflow: "hidden",
marginLeft: 30,
marginTop: 5,
},
subItem: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 6,
marginBottom: 4,
},
subItemActive: {
backgroundColor: AccentColor.blue,
},
subText: {
color: MainColor.white,
fontSize: 14,
},
});

View File

@@ -22,7 +22,7 @@ interface TextCustomProps {
style?: StyleProp<TextStyle>;
bold?: boolean;
semiBold?: boolean;
size?: "default" | "large" | "small" | "xlarge";
size?: "default" | "large" | "small" | "xlarge" | number
color?: "default" | "yellow" | "red" | "gray" | "green" | "black"
align?: TextAlign; // Prop untuk alignment
truncate?: boolean | number;
@@ -54,6 +54,7 @@ const TextCustom: React.FC<TextCustomProps> = ({
if (size === "large") selectedStyles.push(styles.large);
else if (size === "xlarge") selectedStyles.push(styles.xlarge);
else if (size === "small") selectedStyles.push(styles.small);
else if (typeof size === "number") selectedStyles.push({ fontSize: size });
// Color
if (color === "yellow") selectedStyles.push(styles.yellow);
@@ -105,7 +106,7 @@ export const styles = StyleSheet.create({
fontSize: TEXT_SIZE_MEDIUM,
color: MainColor.white,
fontFamily: "Poppins-Regular",
lineHeight: 20,
// lineHeight: 20,
},
bold: {
fontFamily: "Poppins-Bold",

View File

@@ -2,11 +2,11 @@ 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 }) {
export default function IconArchive({ color, size }: { color?: string; size?: number }) {
return (
<Ionicons
name="archive"
size={ICON_SIZE_SMALL}
size={size || ICON_SIZE_SMALL}
color={color || MainColor.white}
/>
);

View File

@@ -0,0 +1,111 @@
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
import {
Entypo,
FontAwesome,
FontAwesome6,
Ionicons,
Octicons,
} from "@expo/vector-icons";
export const IconPublish = ({
size,
color,
}: {
size?: number;
color?: string;
}) => {
return (
<>
<Entypo
name="publish"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.white}
/>
</>
);
};
export const IconReview = ({
size,
color,
}: {
size?: number;
color?: string;
}) => {
return (
<>
<FontAwesome6
name="person-circle-check"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.white}
/>
</>
);
};
export const IconReject = ({
size,
color,
}: {
size?: number;
color?: string;
}) => {
return (
<>
<FontAwesome
name="warning"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.white}
/>
</>
);
};
export const IconReport = ({
size,
color,
}: {
size?: number;
color?: string;
}) => {
return (
<>
<Octicons
name="report"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.white}
/>
</>
);
};
export const IconView = ({
size,
color,
}: {
size?: number;
color?: string;
}) => {
return (
<>
<Octicons
name="eye"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.white}
/>
</>
);
};
export const IconDot = ({ size, color }: { size?: number; color?: string }) => {
return (
<>
<Ionicons
name="ellipsis-vertical"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.darkblue}
/>
</>
);
};

View File

@@ -0,0 +1,13 @@
import ActionIcon from "@/components/ActionIcon/ActionIcon";
import { MainColor } from "@/constants/color-palet";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
export default function AdminBackButton() {
return (
<ActionIcon
icon={<Ionicons name="arrow-back" size={16} color={MainColor.darkblue} />}
onPress={() => router.back()}
/>
);
}

View File

@@ -0,0 +1,32 @@
import Grid from "@/components/Grid/GridCustom";
import TextCustom from "@/components/Text/TextCustom";
import AdminBackButton from "./BackButton";
export default function AdminBackButtonAntTitle({
title,
rightComponent,
}: {
title: string;
rightComponent?: React.ReactNode;
}) {
return (
<>
<Grid>
<Grid.Col span={2}>
<AdminBackButton />
</Grid.Col>
<Grid.Col
span={8}
style={{ alignItems: "center", justifyContent: "center" }}
>
<TextCustom bold size={"large"} align="center">
{title}
</TextCustom>
</Grid.Col>
<Grid.Col span={2} style={{ alignItems: "flex-end" }}>
{rightComponent}
</Grid.Col>
</Grid>
</>
);
}

View File

@@ -0,0 +1,46 @@
import BaseBox from "@/components/Box/BaseBox";
import CircleContainer from "@/components/Container/CircleContainer";
import Grid from "@/components/Grid/GridCustom";
import StackCustom from "@/components/Stack/StackCustom";
import TextCustom from "@/components/Text/TextCustom";
import { AccentColor, MainColor } from "@/constants/color-palet";
interface BoxDashboardProps {
item: {
label: string;
value: string | number;
icon: React.ReactNode;
};
}
export default function AdminComp_BoxDashboard({ item }: BoxDashboardProps) {
return (
<>
<BaseBox
backgroundColor={MainColor.soft_darkblue}
paddingTop={5}
paddingBottom={5}
>
<Grid containerStyle={{ marginBlock: 0 }}>
<Grid.Col
span={9}
style={{
paddingLeft: 10,
}}
>
<StackCustom gap={"xs"}>
<TextCustom bold>{item.label}</TextCustom>
<TextCustom size={50}>{item.value}</TextCustom>
</StackCustom>
</Grid.Col>
<Grid.Col
span={3}
style={{ alignItems: "flex-start", justifyContent: "center" }}
>
<CircleContainer style={{ backgroundColor: MainColor.white, borderColor: AccentColor.blue }} icon={item.icon} />
</Grid.Col>
</Grid>
</BaseBox>
</>
);
}

View File

@@ -0,0 +1,45 @@
import BaseBox from "@/components/Box/BaseBox";
import Grid from "@/components/Grid/GridCustom";
import TextCustom from "@/components/Text/TextCustom";
import { TEXT_SIZE_LARGE } from "@/constants/constans-value";
export default function AdminComp_BoxTitle({
title,
rightComponent,
}: {
title: string;
rightComponent?: React.ReactNode;
}) {
return (
<>
<BaseBox
style={{ flexDirection: "row", justifyContent: "space-between" }}
paddingTop={5}
paddingBottom={5}
>
<Grid>
<Grid.Col span={rightComponent ? 6 : 12} style={{ justifyContent: "center" }}>
<TextCustom
// style={{ alignSelf: "center" }}
bold
size={TEXT_SIZE_LARGE}
>
{title}
</TextCustom>
</Grid.Col>
{rightComponent && (
<Grid.Col
span={6}
style={{
justifyContent: "center",
alignItems: "flex-end",
}}
>
{rightComponent}
</Grid.Col>
)}
</Grid>
</BaseBox>
</>
);
}

View File

@@ -0,0 +1,28 @@
import Grid from "@/components/Grid/GridCustom";
import TextCustom from "@/components/Text/TextCustom";
export default function AdminTitleTable({
title1,
title2,
title3,
}: {
title1: string;
title2: string;
title3: string;
}) {
return (
<>
<Grid>
<Grid.Col span={3} style={{ alignItems: "center", justifyContent: "center" }}>
<TextCustom bold align="center">{title1}</TextCustom>
</Grid.Col>
<Grid.Col span={3} style={{ alignItems: "center", justifyContent: "center" }}>
<TextCustom bold align="center">{title2}</TextCustom>
</Grid.Col>
<Grid.Col span={6} style={{ alignItems: "center", justifyContent: "center" }}>
<TextCustom bold align="center">{title3}</TextCustom>
</Grid.Col>
</Grid>
</>
);
}

View File

@@ -0,0 +1,56 @@
import Grid from "@/components/Grid/GridCustom";
import React from "react";
import { View } from "react-native";
import { Divider } from "react-native-paper";
export default function AdminTableValue({
value1,
value2,
value3,
}: {
value1: React.ReactNode;
value2: React.ReactNode;
value3: React.ReactNode;
}) {
return (
<>
<View style={{ paddingVertical: 5 }}>
<Grid>
<Grid.Col
span={3}
style={{
alignItems: "center",
justifyContent: "center",
paddingLeft: 5,
paddingRight: 5,
}}
>
{value1}
</Grid.Col>
<Grid.Col
span={3}
style={{
alignItems: "center",
justifyContent: "center",
paddingLeft: 5,
paddingRight: 5,
}}
>
{value2}
</Grid.Col>
<Grid.Col
span={6}
style={{
justifyContent: "center",
paddingLeft: 5,
paddingRight: 5,
}}
>
{value3}
</Grid.Col>
</Grid>
<Divider />
</View>
</>
);
}

View File

@@ -0,0 +1,11 @@
import TextCustom from "@/components/Text/TextCustom";
export default function AdminTitlePage({ title }: { title: string }) {
return (
<>
<TextCustom bold size={25}>
{title}
</TextCustom>
</>
);
}

View File

@@ -0,0 +1,20 @@
import { Grid } from "@/components";
export const GridDetail_4_8 = ({
label,
value,
}: {
label: React.ReactNode;
value: React.ReactNode;
}) => {
return (
<Grid>
<Grid.Col span={4} style={{ justifyContent: "center", paddingRight: 10 }}>
{label}
</Grid.Col>
<Grid.Col span={8} style={{ justifyContent: "center" }}>
{value}
</Grid.Col>
</Grid>
);
};

View File

@@ -0,0 +1,25 @@
import Grid from "../Grid/GridCustom";
export default function GridComponentView({
leftIcon,
children,
rightIcon,
}: {
leftIcon?: React.ReactNode;
children: React.ReactNode;
rightIcon?: React.ReactNode;
}) {
return (
<Grid containerStyle={{ marginBottom: 0 }}>
<Grid.Col span={1} style={{ justifyContent: "center" }}>
{leftIcon}
</Grid.Col>
<Grid.Col span={10} style={{ justifyContent: "center" }}>
{children}
</Grid.Col>
<Grid.Col span={1} style={{ justifyContent: "center" }}>
{rightIcon}
</Grid.Col>
</Grid>
);
}

View File

@@ -17,7 +17,7 @@ export default function SearchInput({
onPress,
iconLeft,
iconRight,
containerStyle = { marginBottom: 0 },
containerStyle,
style,
...props
}: SearchInputProps) {
@@ -32,7 +32,7 @@ export default function SearchInput({
}
placeholder={placeholder}
borderRadius={50}
containerStyle={containerStyle}
containerStyle={[containerStyle, { marginBottom: 0 }]}
{...props}
/>
);

View File

@@ -1,15 +1,16 @@
import { MainColor, AccentColor } from "@/constants/color-palet";
import { AccentColor, MainColor } from "@/constants/color-palet";
import { View } from "react-native";
import ButtonCustom from "../Button/ButtonCustom";
import Spacing from "./Spacing";
export default function TabsTwoHeaderCustom ({
export default function TabsTwoButtonCustom ({
leftValue,
rightValue,
leftText,
rightText,
activeCategory,
handlePress,
hideBackground,
}: {
leftValue: string;
rightValue: string;
@@ -17,6 +18,7 @@ export default function TabsTwoHeaderCustom ({
rightText: string;
activeCategory: string | null;
handlePress: (item: string) => void;
hideBackground?: boolean;
}) {
return (
<>
@@ -25,7 +27,7 @@ export default function TabsTwoHeaderCustom ({
flexDirection: "row",
alignItems: "center",
padding: 5,
backgroundColor: MainColor.soft_darkblue,
backgroundColor: hideBackground ? "transparent" : MainColor.soft_darkblue,
borderRadius: 50,
width: "100%",
}}

View File

@@ -1,6 +1,8 @@
// Alert
import AlertCustom from "./Alert/AlertCustom";
import AlertDefaultSystem from "./Alert/AlertDefaultSystem";
// ActionIcon
import ActionIcon from "./ActionIcon/ActionIcon";
// Button
import LeftButtonCustom from "./Button/BackButton";
import ButtonCenteredOnly from "./Button/ButtonCenteredOnly";
@@ -55,10 +57,14 @@ import TabBarBackground from "./_ShareComponent/TabBarBackground";
import ViewWrapper from "./_ShareComponent/ViewWrapper";
import SearchInput from "./_ShareComponent/SearchInput";
import DummyLandscapeImage from "./_ShareComponent/DummyLandscapeImage";
import GridComponentView from "./_ShareComponent/GridSectionView";
// Progress
import ProgressCustom from "./Progress/ProgressCustom";
export {
// ActionIcon
ActionIcon,
// Alert
AlertCustom,
AlertDefaultSystem,
// Image
@@ -107,6 +113,7 @@ export {
// ShareComponent
SearchInput,
DummyLandscapeImage,
GridComponentView,
Spacing,
// Stack
StackCustom,

View File

@@ -8,11 +8,13 @@ export {
TEXT_SIZE_MEDIUM,
TEXT_SIZE_LARGE,
TEXT_SIZE_XLARGE,
ICON_SIZE_SMALL,
ICON_SIZE_MEDIUM,
ICON_SIZE_XLARGE as ICON_SIZE_XLARGE,
ICON_SIZE_LARGE as ICON_SIZE_MEDIUM,
ICON_SIZE_MEDIUM as ICON_SIZE_SMALL,
ICON_SIZE_XSMALL as ICON_SIZE_XSMALL,
ICON_SIZE_SMALLL as ICON_SIZE_BUTTON,
DRAWER_HEIGHT,
RADIUS_BUTTON,
ICON_SIZE_BUTTON,
PADDING_EXTRA_SMALL,
PADDING_SMALL,
PADDING_MEDIUM,
@@ -31,9 +33,11 @@ const TEXT_SIZE_LARGE = 16;
const TEXT_SIZE_XLARGE = 18;
// Icon Size
const ICON_SIZE_BUTTON = 18
const ICON_SIZE_SMALL = 20;
const ICON_SIZE_MEDIUM = 24;
const ICON_SIZE_XSMALL = 10
const ICON_SIZE_SMALLL = 14
const ICON_SIZE_MEDIUM = 18;
const ICON_SIZE_LARGE = 22;
const ICON_SIZE_XLARGE = 26;
// Drawer Height
const DRAWER_HEIGHT = 500; // tinggi drawer5

View File

@@ -0,0 +1,123 @@
export const dummyMasterEmotions = [
{
id: 1,
label: "Senang",
value: "senang",
isActive: true,
createdAt: "2025-06-16T09:57:16.726Z",
updatedAt: "2025-06-16T09:57:16.726Z",
},
{
id: 2,
label: "Sedih",
value: "sedih",
isActive: true,
createdAt: "2025-06-16T09:57:16.730Z",
updatedAt: "2025-06-16T09:57:16.730Z",
},
{
id: 15,
label: "Takut",
value: "takut",
isActive: true,
createdAt: "2025-06-16T09:57:16.730Z",
updatedAt: "2025-06-16T09:57:16.730Z",
},
{
id: 6,
label: "Marah",
value: "marah",
isActive: true,
createdAt: "2025-06-16T09:57:16.730Z",
updatedAt: "2025-06-16T09:57:16.730Z",
},
{
id: 8,
label: "Terkejut",
value: "terkejut",
isActive: true,
createdAt: "2025-06-16T09:57:16.730Z",
updatedAt: "2025-06-16T09:57:16.730Z",
},
{
id: 14,
label: "Malas",
value: "malas",
isActive: true,
createdAt: "2025-06-16T09:57:16.730Z",
updatedAt: "2025-06-16T09:57:16.730Z",
},
{
id: 7,
label: "Penasaran",
value: "penasaran",
isActive: true,
createdAt: "2025-06-16T09:57:16.731Z",
updatedAt: "2025-06-16T09:57:16.731Z",
},
{
id: 3,
label: "Cinta",
value: "cinta",
isActive: true,
createdAt: "2025-06-16T09:57:16.731Z",
updatedAt: "2025-06-16T09:57:16.731Z",
},
{
id: 4,
label: "Bangga",
value: "bangga",
isActive: true,
createdAt: "2025-06-16T09:57:16.731Z",
updatedAt: "2025-06-16T09:57:16.731Z",
},
{
id: 5,
label: "Malu",
value: "malu",
isActive: true,
createdAt: "2025-06-16T09:57:16.731Z",
updatedAt: "2025-06-16T09:57:16.731Z",
},
{
id: 11,
label: "Kesal",
value: "kesal",
isActive: true,
createdAt: "2025-06-16T09:57:16.732Z",
updatedAt: "2025-06-16T09:57:16.732Z",
},
{
id: 9,
label: "Bingung",
value: "bingung",
isActive: true,
createdAt: "2025-06-16T09:57:16.732Z",
updatedAt: "2025-06-16T09:57:16.732Z",
},
{
id: 10,
label: "Kaget",
value: "kaget",
isActive: true,
createdAt: "2025-06-16T09:57:16.732Z",
updatedAt: "2025-06-16T09:57:16.732Z",
},
{
id: 12,
label: "Iri",
value: "iri",
isActive: true,
createdAt: "2025-06-16T09:57:16.732Z",
updatedAt: "2025-06-16T09:57:16.732Z",
},
{
id: 13,
label: "Lega",
value: "lega",
isActive: true,
createdAt: "2025-06-16T09:57:16.733Z",
updatedAt: "2025-06-16T09:57:16.733Z",
},
];

View File

@@ -52,6 +52,7 @@
"react-native-reanimated": "~3.17.4",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
"react-native-toast-message": "^2.3.3",
"react-native-vector-icons": "^10.2.0",
"react-native-web": "~0.20.0",
"react-native-webview": "13.13.5"

View File

@@ -0,0 +1,83 @@
import {
ActionIcon,
Grid,
StackCustom,
TextCustom
} from "@/components";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import dummyMasterBidangBisnis from "@/lib/dummy-data/master-bidang-bisnis";
import { FontAwesome5 } from "@expo/vector-icons";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
import { Divider, Switch } from "react-native-paper";
export default function AdminAppInformation_BusinessFieldSection() {
const [value, setValue] = useState(false);
const [selectedBusinessField, setSelectedBusinessField] = useState<any>(null);
return (
<>
<>
<Grid>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<TextCustom bold>Aksi</TextCustom>
</Grid.Col>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<TextCustom bold>Status</TextCustom>
</Grid.Col>
<Grid.Col span={6}>
<TextCustom bold>Nama Bidang Bisnis</TextCustom>
</Grid.Col>
</Grid>
<Divider />
<StackCustom>
{dummyMasterBidangBisnis.map((e, i) => (
<View key={i}>
<Grid>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<ActionIcon
icon={
<FontAwesome5
name="edit"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(`/admin/app-information/business-field/${i}`);
}}
/>
</Grid.Col>
<Grid.Col
span={3}
style={{ alignItems: "center", justifyContent: "center" }}
>
<Switch
value={i === selectedBusinessField}
onValueChange={() => {
setValue(!value);
setSelectedBusinessField(i);
}}
theme={{
colors: {
primary: MainColor.yellow,
},
}}
/>
</Grid.Col>
<Grid.Col span={6} style={{ justifyContent: "center" }}>
<TextCustom>{e.name}</TextCustom>
</Grid.Col>
</Grid>
<Divider />
</View>
))}
</StackCustom>
</>
</>
);
}

View File

@@ -0,0 +1,77 @@
import { ActionIcon, Grid, StackCustom, TextCustom } from "@/components";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { dummyMasterBank } from "@/lib/dummy-data/_master/bank";
import { FontAwesome5 } from "@expo/vector-icons";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
import { Divider, Switch } from "react-native-paper";
export default function AdminAppInformation_Bank() {
const [value, setValue] = useState(false);
return (
<>
<>
<Grid>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<TextCustom bold>Aksi</TextCustom>
</Grid.Col>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<TextCustom bold>Status</TextCustom>
</Grid.Col>
<Grid.Col span={6}>
<TextCustom bold>Nama Bank</TextCustom>
</Grid.Col>
</Grid>
<Divider />
<StackCustom>
{dummyMasterBank.map((e, i) => (
<View key={i}>
<Grid>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<ActionIcon
icon={
<FontAwesome5
name="edit"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(
`/admin/app-information/information-bank/${i}`
);
}}
/>
</Grid.Col>
<Grid.Col
span={3}
style={{ alignItems: "center", justifyContent: "center" }}
>
<Switch
value={value}
onValueChange={() => {
setValue(!value);
}}
theme={{
colors: {
primary: MainColor.yellow,
},
}}
/>
</Grid.Col>
<Grid.Col span={6} style={{ justifyContent: "center" }}>
<TextCustom>{e.code}</TextCustom>
</Grid.Col>
</Grid>
<Divider />
</View>
))}
</StackCustom>
</>
</>
);
}

View File

@@ -0,0 +1,109 @@
import { ActionIcon, Grid, StackCustom, TextCustom } from "@/components";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { FontAwesome5 } from "@expo/vector-icons";
import { Image } from "expo-image";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
import { Divider, Switch } from "react-native-paper";
export default function AdminAppInformation_StickerSection() {
const [value, setValue] = useState(false);
return (
<>
<Grid>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<TextCustom bold>Aksi</TextCustom>
</Grid.Col>
<Grid.Col span={3} style={{ alignItems: "center" }}>
<TextCustom bold>Status</TextCustom>
</Grid.Col>
<Grid.Col span={6}>
<TextCustom bold align="center" >Stiker</TextCustom>
</Grid.Col>
</Grid>
<Divider />
<StackCustom>
{listSticker.map((e, i) => (
<View key={i}>
<Grid>
<Grid.Col
span={3}
style={{ alignItems: "center", justifyContent: "center" }}
>
<ActionIcon
icon={
<FontAwesome5
name="edit"
size={ICON_SIZE_BUTTON}
color="black"
/>
}
onPress={() => {
router.push(`/admin/app-information/sticker/${i}`);
}}
/>
</Grid.Col>
<Grid.Col
span={3}
style={{ alignItems: "center", justifyContent: "center" }}
>
<Switch
value={value}
onValueChange={() => {
setValue(!value);
}}
theme={{
colors: {
primary: MainColor.yellow,
},
}}
/>
</Grid.Col>
<Grid.Col span={6} style={{ justifyContent: "center", alignItems: "center" }}>
<Image source={e.path} style={{ width: 100, height: 100 }} />
</Grid.Col>
</Grid>
<Divider />
</View>
))}
</StackCustom>
</>
);
}
const listSticker = [
{
id: "1",
label: "Stiker 1",
value: "sticker 1",
path: "https://wibu-storage.wibudev.com/api/files/cmb0dkn5700bjbpnnwcfpzxpz",
},
{
id: "2",
label: "Stiker 2",
value: "sticker 2",
path: "https://wibu-storage.wibudev.com/api/files/cmb0djnya00bhbpnn8b2sfpg3",
},
{
id: "3",
label: "Stiker 3",
value: "sticker 3",
path: "https://wibu-storage.wibudev.com/api/files/cmb0dj0o400bfbpnn6hrfa71y",
},
{
id: "4",
label: "Stiker 4",
value: "sticker 4",
path: "https://wibu-storage.wibudev.com/api/files/cmb0d5rdb00abbpnnrbhxrxjz",
},
{
id: "5",
label: "Stiker 5",
value: "sticker 5",
path: "https://wibu-storage.wibudev.com/api/files/cmb0d4j5q00a9bpnn0qpxa0k4",
},
];

View File

@@ -0,0 +1,96 @@
import { NavbarItem } from "@/components/Drawer/NavbarMenu";
export { adminListMenu }
const adminListMenu: NavbarItem[] = [
{
label: "Main Dashboard",
icon: "home",
link: "/admin/dashboard",
},
{
label: "Investasi",
icon: "wallet",
links: [
{ label: "Dashboard", link: "/admin/investment" },
{ label: "Publish", link: "/admin/investment/publish" },
{ label: "Review", link: "/admin/investment/review" },
{ label: "Reject", link: "/admin/investment/reject" },
],
},
{
label: "Donasi",
icon: "hand-right",
links: [
{ label: "Dashboard", link: "/admin/donasi" },
{ label: "Publish", link: "/admin/donasi/publish" },
{ label: "Review", link: "/admin/donasi/review" },
{ label: "Reject", link: "/admin/donasi/reject" },
{ label: "Kategori", link: "/admin/donasi/kategori" },
],
},
{
label: "Event",
icon: "calendar-clear",
links: [
{ label: "Dashboard", link: "/admin/event" },
{ label: "Publish", link: "/admin/event/publish" },
{ label: "Review", link: "/admin/event/review" },
{ label: "Reject", link: "/admin/event/reject" },
{ label: "Tipe Acara", link: "/admin/event/tipe-acara" },
{ label: "Riwayat", link: "/admin/event/riwayat" },
],
},
{
label: "Voting",
icon: "accessibility-outline",
links: [
{ label: "Dashboard", link: "/admin/voting" },
{ label: "Publish", link: "/admin/voting/publish" },
{ label: "Review", link: "/admin/voting/review" },
{ label: "Reject", link: "/admin/voting/reject" },
{ label: "Riwayat", link: "/admin/voting/riwayat" },
],
},
{
label: "Job",
icon: "desktop-outline",
links: [
{ label: "Dashboard", link: "/admin/job" },
{ label: "Publish", link: "/admin/job/publish/status" },
{ label: "Review", link: "/admin/job/review/status" },
{ label: "Reject", link: "/admin/job/reject/status" },
],
},
{
label: "Forum",
icon: "chatbubble-ellipses-outline",
links: [
{ label: "Dashboard", link: "/admin/forum" },
{ label: "Posting", link: "/admin/forum/posting" },
{ label: "Report Posting", link: "/admin/forum/report-posting" },
{ label: "Report Comment", link: "/admin/forum/report-comment" },
],
},
{
label: "Collaboration",
icon: "people",
links: [
{ label: "Dashboard", link: "/admin/collaboration" },
{ label: "Publish", link: "/admin/collaboration/publish" },
{ label: "Group", link: "/admin/collaboration/group" },
{ label: "Reject", link: "/admin/collaboration/reject" },
],
},
{ label: "Maps", icon: "map", link: "/admin/maps" },
{
label: "App Information",
icon: "information-circle",
link: "/admin/app-information",
},
{
label: "User Access",
icon: "people",
link: "/admin/user-access",
},
];

View File

@@ -30,7 +30,7 @@ export default function LoginView() {
const id = randomAlfabet + randomNumber + fixNumber;
console.log("login user id :", id);
// router.navigate("/verification");
router.navigate("/verification");
// router.navigate(`/(application)/(user)/profile/${id}`);
// router.navigate("/(application)/(user)/home");
// router.navigate(`/(application)/profile/${id}/edit`);
@@ -38,8 +38,9 @@ export default function LoginView() {
// router.navigate(`/(application)/(image)/preview-image/${id}`);
// router.replace("/(application)/(user)/event/(tabs)");
// router.replace("/(application)/coba");
// router.navigate("/investment/(tabs)")
router.navigate("/crowdfunding")
// router.navigate("/investment/(tabs)")1
// router.navigate("/crowdfunding")
// router.navigate("/admin/dashboard")
}
return (
@@ -77,9 +78,15 @@ export default function LoginView() {
placeholder="Masukkan nomor"
/>
<Spacing height={20} />
<Spacing />
<ButtonCustom onPress={handleLogin}>Login</ButtonCustom>
<Spacing />
<ButtonCustom onPress={() => router.navigate("/admin/forum")}>
Admin ( Delete Soon )
</ButtonCustom>
</View>
</ViewWrapper>
);

View File

@@ -52,11 +52,17 @@ export const drawerItemsProfile = ({
label: "Tambah portofolio",
path: `/(application)/portofolio/${id}/create`,
},
// {
// icon: "settings",
// label: "Dashboard Admin",
// path: `/(application)/profile/dashboard-admin`,
// },
{
icon: (
<Ionicons
name="settings"
size={ICON_SIZE_MEDIUM}
color={AccentColor.white}
/>
),
label: "Dashboard Admin",
path: `/(application)/admin/dashboard`,
},
{
icon: (
<Ionicons

View File

@@ -26,9 +26,14 @@ export default function Profile_MenuDrawerSection({
<>
{/* Menu Items */}
<MenuDrawerDynamicGrid
data={drawerItems}
data={drawerItems.map((item) => ({
icon: item.icon,
label: item.label,
path: item.path as any,
color: item.color,
}))}
columns={4} // Ubah ke 2 jika ingin 2 kolom per baris
onPressItem={handlePress}
onPressItem={(item) => handlePress(item as any)}
/>
</>
);

View File

@@ -36,11 +36,11 @@ export const GStyles = StyleSheet.create({
right: 0,
zIndex: 10,
backgroundColor: "transparent",
paddingBlock: PADDING_SMALL,
// paddingBlock: PADDING_EXTRA_SMALL,
paddingInline: PADDING_MEDIUM,
// padding: 16,
// paddingTop: 8,
// paddingBottom: 8,
paddingTop: 8,
paddingBottom: 8,
},
floatingContainer: {
position: "absolute",

View File

@@ -13,5 +13,5 @@
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts"
]
, "app/(application)/admin/app-information/business-field/[id]" ]
}