Compare commits

..

7 Commits

Author SHA1 Message Date
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
46 changed files with 1693 additions and 112 deletions

View File

@@ -1,27 +1,29 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { import {
ClickableCustom, AlertDefaultSystem,
DrawerCustom, DrawerCustom,
GridComponentView,
MenuDrawerDynamicGrid,
StackCustom, StackCustom,
TextCustom, TextCustom,
} from "@/components"; } from "@/components";
import DrawerAdmin from "@/components/Drawer/DrawerAdmin"; import DrawerAdmin from "@/components/Drawer/DrawerAdmin";
import NavbarMenu from "@/components/Drawer/NavbarMenu"; import NavbarMenu from "@/components/Drawer/NavbarMenu";
import SidebarMenu from "@/components/Drawer/SidebarMenu";
import { AccentColor, MainColor } from "@/constants/color-palet"; import { AccentColor, MainColor } from "@/constants/color-palet";
import { ICON_SIZE_SMALL } from "@/constants/constans-value"; 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 { GStyles } from "@/styles/global-styles";
import { FontAwesome6, Ionicons } from "@expo/vector-icons"; import { FontAwesome6, Ionicons } from "@expo/vector-icons";
import { router, Stack } from "expo-router"; import { router, Stack } from "expo-router";
import { useState } from "react"; import { useState } from "react";
import { View } from "react-native";
export default function AdminLayout() { export default function AdminLayout() {
const [openDrawer, setOpenDrawer] = useState(false); const [openDrawerNavbar, setOpenDrawerNavbar] = useState(false);
const [openDrawerUser, setOpenDrawerUser] = useState(false);
return ( return (
<> <>
<Stack <Stack
screenOptions={{ screenOptions={{
title: "HIPMI DASHBOARD",
headerStyle: GStyles.headerStyle, headerStyle: GStyles.headerStyle,
headerTitleStyle: GStyles.headerTitleStyle, headerTitleStyle: GStyles.headerTitleStyle,
headerTitleAlign: "center", headerTitleAlign: "center",
@@ -31,64 +33,195 @@ export default function AdminLayout() {
headerLeft: () => ( headerLeft: () => (
<Ionicons <Ionicons
name="menu" name="menu"
size={ICON_SIZE_SMALL} size={ICON_SIZE_XLARGE}
color={MainColor.white} color={MainColor.white}
onPress={() => setOpenDrawer(true)} onPress={() => setOpenDrawerNavbar(true)}
/> />
), ),
headerRight: () => ( headerRight: () => (
<FontAwesome6 <FontAwesome6
name="circle-user" name="circle-user"
size={ICON_SIZE_SMALL} size={ICON_SIZE_MEDIUM}
color={MainColor.white} color={MainColor.white}
onPress={() => setOpenDrawerUser(true)}
/> />
), ),
}} }}
> >
<Stack.Screen name="dashboard" options={{ title: "Dashboard" }} /> <Stack.Screen name="dashboard"
<Stack.Screen name="maps" options={{ title: "Maps" }} /> // options={{ title: "Main Dashboard" }}
<Stack.Screen name="information" options={{ title: "Information" }} /> />
<Stack.Screen name="job/index" options={{ title: "Job" }} /> <Stack.Screen
<Stack.Screen name="job/publish" options={{ title: "Job Publish" }} /> name="investment/index"
<Stack.Screen name="job/review" options={{ title: "Job Review" }} /> // options={{ title: "Dashboard Investasi" }}
<Stack.Screen name="job/reject" options={{ title: "Job Reject" }} /> />
<Stack.Screen
name="investment/publish"
// options={{ title: "Investasi Publish" }}
/>
<Stack.Screen
name="investment/review"
// options={{ title: "Investasi Review" }}
/>
<Stack.Screen
name="investment/reject"
// options={{ title: "Investasi Reject" }}
/>
<Stack.Screen name="maps"
// options={{ title: "Maps" }}
/>
<Stack.Screen name="app-information/index"
// options={{ title: "Information" }}
/>
<Stack.Screen name="job/index"
// options={{ title: "Dashboard Job" }}
/>
<Stack.Screen name="job/publish"
// options={{ title: "Job Publish" }}
/>
<Stack.Screen name="job/review"
// options={{ title: "Job Review" }}
/>
<Stack.Screen name="job/reject"
// options={{ title: "Job Reject" }}
/>
<Stack.Screen
name="collaboration/index"
// options={{ title: "Dashboard Collaboration" }}
/>
<Stack.Screen
name="collaboration/publish"
// options={{ title: "Collaboration Publish" }}
/>
<Stack.Screen
name="collaboration/group"
// options={{ title: "Collaboration Group" }}
/>
<Stack.Screen
name="collaboration/reject"
// options={{ title: "Collaboration Reject" }}
/>
</Stack> </Stack>
<DrawerAdmin isVisible={openDrawer} onClose={() => setOpenDrawer(false)}> <DrawerAdmin
<StackCustom gap={"lg"}> isVisible={openDrawerNavbar}
onClose={() => setOpenDrawerNavbar(false)}
>
<StackCustom gap={"xs"}>
<Ionicons <Ionicons
name="close" name="close"
size={ICON_SIZE_SMALL} size={ICON_SIZE_SMALL}
color={MainColor.white} color={MainColor.white}
onPress={() => setOpenDrawer(false)} onPress={() => setOpenDrawerNavbar(false)}
style={{ alignSelf: "flex-end" }} style={{ alignSelf: "flex-end" }}
/> />
<NavbarMenu <NavbarMenu
items={[ items={adminListMenu}
{ label: "Dashboard", icon: "home", link: "/admin/dashboard" }, onClose={() => setOpenDrawerNavbar(false)}
{ label: "Maps", icon: "map", link: "/admin/maps" },
{
label: "Information",
icon: "information-circle",
link: "/admin/information",
},
{
label: "Job",
icon: "calendar",
links: [
{ label: "Summary", link: "/admin/job" },
{ label: "Publish", link: "/admin/job/publish" },
{ label: "Review", link: "/admin/job/review" },
{ label: "Reject", link: "/admin/job/reject" },
],
},
]}
onClose={() => setOpenDrawer(false)}
/> />
</StackCustom> </StackCustom>
</DrawerAdmin> </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,11 @@
import { TextCustom, ViewWrapper } from "@/components";
export default function AdminCollaborationGroup() {
return (
<>
<ViewWrapper>
<TextCustom>Admin Collaboration Group</TextCustom>
</ViewWrapper>
</>
);
}

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,40 @@
import { TextCustom, ViewWrapper } from "@/components"; 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() { export default function AdminDashboard() {
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
<TextCustom>Admin Dashboard</TextCustom> <StackCustom>
<TextCustom bold size={30}>
Main Dashboard
</TextCustom>
{listData.map((item, i) => (
<AdminComp_BoxDashboard key={i} item={item} />
))}
</StackCustom>
</ViewWrapper> </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

@@ -1,10 +1,10 @@
import { TextCustom, ViewWrapper } from "@/components"; import { TextCustom, ViewWrapper } from "@/components";
export default function AdminInformation() { export default function AdminInvestment() {
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
<TextCustom>Information</TextCustom> <TextCustom>Admin Investment</TextCustom>
</ViewWrapper> </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

@@ -1,10 +1,10 @@
import { TextCustom, ViewWrapper } from "@/components"; import { MapCustom, ViewWrapper } from "@/components";
export default function AdminMaps() { export default function AdminMaps() {
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
<TextCustom>Maps</TextCustom> <MapCustom height={"100%"} />
</ViewWrapper> </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

@@ -14,7 +14,10 @@ export default function RootLayout() {
headerTitleAlign: "center", 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="+not-found" options={{ title: "" }} />
<Stack.Screen <Stack.Screen
name="verification" name="verification"

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

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

View File

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

View File

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

View File

@@ -1,10 +1,10 @@
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { import {
Animated, Animated,
Dimensions, Dimensions,
InteractionManager, InteractionManager,
PanResponder, PanResponder,
StyleSheet StyleSheet,
} from "react-native"; } from "react-native";
import { AccentColor, MainColor } from "@/constants/color-palet"; import { AccentColor, MainColor } from "@/constants/color-palet";
@@ -107,9 +107,15 @@ export default function DrawerAdmin({
{...panResponder.panHandlers} {...panResponder.panHandlers}
> >
{/* Handle Bar (opsional) */} {/* Handle Bar (opsional) */}
{/* <View style={styles.handleBar} /> */} <SafeAreaView
edges={["top", "bottom"]}
<SafeAreaView>{children}</SafeAreaView> style={{
flex: 1,
}}
>
{children}
{/* <Spacing/> */}
</SafeAreaView>
</Animated.View> </Animated.View>
</> </>
); );

View File

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

View File

@@ -1,17 +1,17 @@
import { AccentColor, MainColor } from "@/constants/color-palet"; import { AccentColor, MainColor } from "@/constants/color-palet";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import { router, usePathname } from "expo-router"; import { router, usePathname } from "expo-router";
import React, { useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { import {
Animated, Animated,
ScrollView,
StyleSheet, StyleSheet,
Text, Text,
TouchableOpacity, TouchableOpacity,
View, View,
} from "react-native"; } from "react-native";
import TextCustom from "../Text/TextCustom";
interface NavbarItem { export interface NavbarItem {
label: string; label: string;
icon?: keyof typeof Ionicons.glyphMap; icon?: keyof typeof Ionicons.glyphMap;
color?: string; color?: string;
@@ -33,6 +33,17 @@ export default function NavbarMenu({ items, onClose }: NavbarMenuProps) {
const [activeLink, setActiveLink] = useState<string | null>(null); const [activeLink, setActiveLink] = useState<string | null>(null);
const [openKeys, setOpenKeys] = useState<string[]>([]); // Untuk kontrol dropdown 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 // Toggle dropdown
const toggleOpen = (label: string) => { const toggleOpen = (label: string) => {
setOpenKeys((prev) => setOpenKeys((prev) =>
@@ -41,18 +52,31 @@ export default function NavbarMenu({ items, onClose }: NavbarMenuProps) {
}; };
return ( return (
<View style={styles.container}> <View
{items.map((item) => ( style={{
<MenuItem // flex: 1,
key={item.label} // backgroundColor: MainColor.black,
item={item} marginBottom: 20,
onClose={onClose} }}
activeLink={activeLink} >
setActiveLink={setActiveLink} <ScrollView
isOpen={openKeys.includes(item.label)} contentContainerStyle={{
toggleOpen={() => toggleOpen(item.label)} 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> </View>
); );
} }
@@ -83,7 +107,7 @@ function MenuItem({
duration: 200, duration: 200,
useNativeDriver: false, useNativeDriver: false,
}).start(); }).start();
}, [isOpen, item.links]); }, [isOpen, item.links, animatedHeight]);
// Jika ada submenu // Jika ada submenu
if (item.links && item.links.length > 0) { if (item.links && item.links.length > 0) {
@@ -93,7 +117,7 @@ function MenuItem({
<TouchableOpacity style={styles.parentItem} onPress={toggleOpen}> <TouchableOpacity style={styles.parentItem} onPress={toggleOpen}>
<Ionicons <Ionicons
name={item.icon} name={item.icon}
size={20} size={16}
color={MainColor.white} color={MainColor.white}
style={styles.icon} style={styles.icon}
/> />
@@ -135,7 +159,7 @@ function MenuItem({
}} }}
> >
<Ionicons <Ionicons
name="caret-forward-sharp" name="radio-button-on-outline"
size={16} size={16}
color={isSubActive ? MainColor.yellow : MainColor.white} color={isSubActive ? MainColor.yellow : MainColor.white}
style={styles.icon} style={styles.icon}
@@ -168,7 +192,7 @@ function MenuItem({
> >
<Ionicons <Ionicons
name={item.icon} name={item.icon}
size={20} size={16}
color={isActive ? MainColor.yellow : MainColor.white} color={isActive ? MainColor.yellow : MainColor.white}
style={styles.icon} style={styles.icon}
/> />
@@ -186,14 +210,14 @@ function MenuItem({
// Styles // Styles
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
marginTop: 20, marginBottom: 5,
}, },
parentItem: { parentItem: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
paddingVertical: 12, paddingVertical: 12,
paddingHorizontal: 10, paddingHorizontal: 10,
backgroundColor: AccentColor.darkblue, // backgroundColor: AccentColor.darkblue,
borderRadius: 8, borderRadius: 8,
marginBottom: 5, marginBottom: 5,
justifyContent: "space-between", justifyContent: "space-between",
@@ -210,7 +234,7 @@ const styles = StyleSheet.create({
alignItems: "center", alignItems: "center",
paddingVertical: 12, paddingVertical: 12,
paddingHorizontal: 10, paddingHorizontal: 10,
backgroundColor: AccentColor.darkblue, // backgroundColor: AccentColor.darkblue,
borderRadius: 8, borderRadius: 8,
marginBottom: 5, marginBottom: 5,
}, },
@@ -246,6 +270,7 @@ const styles = StyleSheet.create({
}, },
subText: { subText: {
color: MainColor.white, color: MainColor.white,
fontSize: 14, fontSize: 16,
fontWeight: "500",
}, },
}); });

View File

@@ -1,4 +1,4 @@
import React, { useRef, useState, useEffect } from "react"; import React, { useEffect, useRef, useState } from "react";
import { import {
Animated, Animated,
Dimensions, Dimensions,

View File

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

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,31 @@
import Grid from "@/components/Grid/GridCustom";
import TextCustom from "@/components/Text/TextCustom";
import { View } from "react-native";
import AdminBackButton from "./BackButton";
export default function AdminBackButtonAntTitle({
title,
}: {
title: string;
}) {
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}>
<View />
</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 { 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 icon={item.icon} />
</Grid.Col>
</Grid>
</BaseBox>
</>
);
}

View File

@@ -0,0 +1,52 @@
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}
>
{/* <TextCustom
// style={{ alignSelf: "center" }}
bold
size={TEXT_SIZE_LARGE}
>
{title}
</TextCustom>
{rightComponent} */}
<Grid>
<Grid.Col span={6} style={{ justifyContent: "center" }}>
<TextCustom
// style={{ alignSelf: "center" }}
bold
size={TEXT_SIZE_LARGE}
>
{title}
</TextCustom>
</Grid.Col>
<Grid.Col
span={6}
style={{
justifyContent: "center",
alignItems: "flex-end",
}}
>
{rightComponent}
</Grid.Col>
</Grid>
</BaseBox>
</>
);
}

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

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

View File

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

@@ -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" },
{ label: "Review", link: "/admin/job/review" },
{ label: "Reject", link: "/admin/job/reject" },
],
},
{
label: "Forum",
icon: "chatbubble-ellipses-outline",
links: [
{ label: "Dashboard", link: "/admin/forum" },
{ label: "Posting", link: "/admin/forum/publish" },
{ label: "Report Posting", link: "/admin/forum/review" },
{ label: "Report Comment", link: "/admin/forum/reject" },
],
},
{
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

@@ -32,7 +32,7 @@ export default function LoginView() {
// router.navigate("/verification"); // router.navigate("/verification");
// router.navigate(`/(application)/(user)/profile/${id}`); // router.navigate(`/(application)/(user)/profile/${id}`);
// router.navigate("/(application)/(user)/home"); router.navigate("/(application)/(user)/home");
// router.navigate(`/(application)/profile/${id}/edit`); // router.navigate(`/(application)/profile/${id}/edit`);
// router.navigate(`/(application)/(user)/portofolio/${id}`) // router.navigate(`/(application)/(user)/portofolio/${id}`)
// router.navigate(`/(application)/(image)/preview-image/${id}`); // router.navigate(`/(application)/(image)/preview-image/${id}`);
@@ -40,7 +40,7 @@ export default function LoginView() {
// router.replace("/(application)/coba"); // router.replace("/(application)/coba");
// router.navigate("/investment/(tabs)")1 // router.navigate("/investment/(tabs)")1
// router.navigate("/crowdfunding") // router.navigate("/crowdfunding")
router.navigate("/admin/dashboard") // router.navigate("/admin/dashboard")
} }
return ( return (
@@ -78,9 +78,15 @@ export default function LoginView() {
placeholder="Masukkan nomor" placeholder="Masukkan nomor"
/> />
<Spacing height={20} /> <Spacing />
<ButtonCustom onPress={handleLogin}>Login</ButtonCustom> <ButtonCustom onPress={handleLogin}>Login</ButtonCustom>
<Spacing />
<ButtonCustom onPress={() => router.navigate("/admin/user-access")}>
Admin ( Delete Soon )
</ButtonCustom>
</View> </View>
</ViewWrapper> </ViewWrapper>
); );

View File

@@ -61,7 +61,7 @@ export const drawerItemsProfile = ({
/> />
), ),
label: "Dashboard Admin", label: "Dashboard Admin",
path: `/(application)/(admin)/dashboard`, path: `/(application)/admin/dashboard`,
}, },
{ {
icon: ( icon: (

View File

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

View File

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