Compare commits
17 Commits
resourcing
...
event/22-j
| Author | SHA1 | Date | |
|---|---|---|---|
| aa4ea9fb0c | |||
| 81d86885f4 | |||
| 814f261881 | |||
| 7889d25a44 | |||
| ce0e82e627 | |||
| 08dfd62bfd | |||
| c8cc0f0232 | |||
| b844a8151d | |||
| f9e96aa077 | |||
| b8b1efc71e | |||
| eaf0ebfb0a | |||
| e68d366d49 | |||
| 9999f78ed4 | |||
| 2be5afe5ca | |||
| 24913a9f97 | |||
| 3376336c55 | |||
| a0dad5618a |
@@ -76,6 +76,13 @@ export default function UserLayout() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="event/create"
|
||||
options={{
|
||||
title: "Tambah Event",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Stack.Screen
|
||||
name="event/detail/[id]"
|
||||
@@ -85,6 +92,22 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
<Stack.Screen
|
||||
name="event/[id]/edit"
|
||||
options={{
|
||||
title: "Edit Event",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Stack.Screen
|
||||
name="event/[id]/list-of-participants"
|
||||
options={{
|
||||
title: "Daftar peserta",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ========== Forum Section ========= */}
|
||||
<Stack.Screen
|
||||
name="forum/create"
|
||||
@@ -114,6 +137,34 @@ export default function UserLayout() {
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="forum/[id]/report-commentar"
|
||||
options={{
|
||||
title: "Laporkan Komentar",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="forum/[id]/other-report-commentar"
|
||||
options={{
|
||||
title: "Laporkan Komentar",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="forum/[id]/report-posting"
|
||||
options={{
|
||||
title: "Laporkan Diskusi",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="forum/[id]/other-report-posting"
|
||||
options={{
|
||||
title: "Laporkan Diskusi",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ========== Maps Section ========= */}
|
||||
<Stack.Screen
|
||||
|
||||
@@ -1,32 +1,36 @@
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||
import { OS_IOS_HEIGHT, OS_ANDROID_HEIGHT } from "@/constants/constans-value";
|
||||
import { FontAwesome5, Ionicons } from "@expo/vector-icons";
|
||||
import { Tabs } from "expo-router";
|
||||
import { Platform, View } from "react-native";
|
||||
|
||||
export default function EventLayout() {
|
||||
export default function EventTabsLayout() {
|
||||
return (
|
||||
<Tabs
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
tabBarActiveTintColor: MainColor.yellow,
|
||||
tabBarInactiveTintColor: MainColor.white_gray,
|
||||
tabBarStyle: {
|
||||
backgroundColor: MainColor.darkblue,
|
||||
},
|
||||
// tabBarButton: HapticTab,
|
||||
// tabBarBackground: BlurTabBarBackground,
|
||||
// tabBarStyle: Platform.select({
|
||||
// ios: {
|
||||
// // Use a transparent background on iOS to show the blur effect
|
||||
// position: "absolute",
|
||||
// },
|
||||
// default: {},
|
||||
// }),
|
||||
tabBarBackground: CustomTabBarBackground,
|
||||
tabBarStyle: Platform.select({
|
||||
ios: {
|
||||
borderTopWidth: 0,
|
||||
paddingTop: 5,
|
||||
height: OS_IOS_HEIGHT,
|
||||
},
|
||||
android: {
|
||||
borderTopWidth: 0,
|
||||
paddingTop: 5,
|
||||
height: OS_ANDROID_HEIGHT,
|
||||
},
|
||||
default: {},
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: "Home",
|
||||
title: "Beranda",
|
||||
tabBarIcon: ({ color }) => (
|
||||
<Ionicons size={20} name="home" color={color} />
|
||||
),
|
||||
@@ -42,7 +46,7 @@ export default function EventLayout() {
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="kontribusi"
|
||||
name="contribution"
|
||||
options={{
|
||||
title: "Kontribusi",
|
||||
tabBarIcon: ({ color }) => (
|
||||
@@ -51,7 +55,7 @@ export default function EventLayout() {
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="riwayat"
|
||||
name="history"
|
||||
options={{
|
||||
title: "Riwayat",
|
||||
tabBarIcon: ({ color }) => (
|
||||
@@ -62,3 +66,16 @@ export default function EventLayout() {
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
function CustomTabBarBackground() {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: MainColor.darkblue,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: AccentColor.blue,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
43
app/(application)/(user)/event/(tabs)/contribution.tsx
Normal file
43
app/(application)/(user)/event/(tabs)/contribution.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
AvatarCustom,
|
||||
AvatarUsernameAndOtherComponent,
|
||||
BoxWithHeaderSection,
|
||||
Grid,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper
|
||||
} from "@/components";
|
||||
import React from "react";
|
||||
|
||||
export default function EventContribution() {
|
||||
return (
|
||||
<ViewWrapper hideFooter>
|
||||
{Array.from({ length: 10 }).map((_, index) => (
|
||||
<BoxWithHeaderSection key={index} href={`/event/${index}/contribution`}>
|
||||
<StackCustom>
|
||||
<AvatarUsernameAndOtherComponent
|
||||
avatarHref={`/profile/${index}`}
|
||||
rightComponent={
|
||||
<TextCustom truncate>
|
||||
{new Date().toLocaleDateString()}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
|
||||
<TextCustom bold align="center" size="xlarge">
|
||||
Judul Event Disini
|
||||
</TextCustom>
|
||||
|
||||
<Grid>
|
||||
{Array.from({ length: 4 }).map((_, index2) => (
|
||||
<Grid.Col span={3} key={index2}>
|
||||
<AvatarCustom size="sm" href={`/profile/${index2}`} />
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</StackCustom>
|
||||
</BoxWithHeaderSection>
|
||||
))}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
68
app/(application)/(user)/event/(tabs)/history.tsx
Normal file
68
app/(application)/(user)/event/(tabs)/history.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import { ButtonCustom, Spacing, TextCustom } from "@/components";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||
import Event_BoxPublishSection from "@/screens/Event/BoxPublishSection";
|
||||
import { useState } from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
export default function EventHistory() {
|
||||
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
||||
|
||||
const handlePress = (item: any) => {
|
||||
setActiveCategory(item);
|
||||
// tambahkan logika lain seperti filter dsb.
|
||||
};
|
||||
|
||||
const headerComponent = (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
padding: 5,
|
||||
backgroundColor: MainColor.soft_darkblue,
|
||||
borderRadius: 50,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<ButtonCustom
|
||||
backgroundColor={
|
||||
activeCategory === "all" ? MainColor.yellow : AccentColor.blue
|
||||
}
|
||||
textColor={activeCategory === "all" ? MainColor.black : MainColor.white}
|
||||
style={{ width: "49%" }}
|
||||
onPress={() => handlePress("all")}
|
||||
>
|
||||
Semua Riwayat
|
||||
</ButtonCustom>
|
||||
<Spacing width={"2%"} />
|
||||
<ButtonCustom
|
||||
backgroundColor={
|
||||
activeCategory === "main" ? MainColor.yellow : AccentColor.blue
|
||||
}
|
||||
textColor={
|
||||
activeCategory === "main" ? MainColor.black : MainColor.white
|
||||
}
|
||||
style={{ width: "49%" }}
|
||||
onPress={() => handlePress("main")}
|
||||
>
|
||||
Riwayat Saya
|
||||
</ButtonCustom>
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<ViewWrapper headerComponent={headerComponent} hideFooter>
|
||||
{Array.from({ length: 10 }).map((_, index) => (
|
||||
<Event_BoxPublishSection
|
||||
key={index.toString()}
|
||||
id={index.toString()}
|
||||
username={`Riwayat ${activeCategory === "main" ? "Saya" : "Semua"}`}
|
||||
rightComponentAvatar={
|
||||
<TextCustom>{new Date().toLocaleDateString()}</TextCustom>
|
||||
}
|
||||
href={`/event/${index}/history`}
|
||||
/>
|
||||
))}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,25 +1,23 @@
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import FloatingButton from "@/components/Button/FloatingButton";
|
||||
import Event_BoxPublishSection from "@/screens/Event/BoxPublishSection";
|
||||
import { router } from "expo-router";
|
||||
import { Text, TouchableHighlight, View } from "react-native";
|
||||
|
||||
export default function Event() {
|
||||
export default function EventBeranda() {
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<TouchableHighlight onPress={() => router.push("/event/detail/1")}>
|
||||
<View
|
||||
style={{
|
||||
padding: 20,
|
||||
backgroundColor: MainColor.darkblue,
|
||||
borderRadius: 10,
|
||||
borderColor: AccentColor.blue,
|
||||
borderWidth: 1,
|
||||
}}
|
||||
>
|
||||
<Text style={GStyles.textLabel}>Event</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<ViewWrapper
|
||||
hideFooter
|
||||
floatingButton={
|
||||
<FloatingButton onPress={() => router.push("/event/create")} />
|
||||
}
|
||||
>
|
||||
{Array.from({ length: 10 }).map((_, index) => (
|
||||
<Event_BoxPublishSection
|
||||
key={index}
|
||||
id={index.toString()}
|
||||
href={`/event/${index}/publish`}
|
||||
/>
|
||||
))}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Text } from "react-native";
|
||||
|
||||
export default function Kontribusi() {
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<Text style={GStyles.textLabel}>Kontribusi</Text>
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Text } from "react-native";
|
||||
|
||||
export default function Riwayat() {
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<Text style={GStyles.textLabel}>Riwayat</Text>
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,63 @@
|
||||
import {
|
||||
BoxWithHeaderSection,
|
||||
Grid,
|
||||
ScrollableCustom,
|
||||
StackCustom,
|
||||
TextCustom
|
||||
} from "@/components";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Text } from "react-native";
|
||||
import { masterStatus } from "@/lib/dummy-data/_master/status";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function EventStatus() {
|
||||
const id = "test-id-event";
|
||||
|
||||
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||
"publish"
|
||||
);
|
||||
|
||||
const handlePress = (item: any) => {
|
||||
setActiveCategory(item.value);
|
||||
// tambahkan logika lain seperti filter dsb.
|
||||
};
|
||||
|
||||
const scrollComponent = (
|
||||
<ScrollableCustom
|
||||
data={masterStatus.map((e, i) => ({
|
||||
id: i,
|
||||
label: e.label,
|
||||
value: e.value,
|
||||
}))}
|
||||
onButtonPress={handlePress}
|
||||
activeId={activeCategory as any}
|
||||
/>
|
||||
);
|
||||
|
||||
export default function Status() {
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<Text style={GStyles.textLabel}>Status</Text>
|
||||
<ViewWrapper headerComponent={scrollComponent}>
|
||||
<BoxWithHeaderSection href={`/event/${id}/${activeCategory}/detail-event`}>
|
||||
<StackCustom gap={"xs"}>
|
||||
<Grid>
|
||||
<Grid.Col span={8}>
|
||||
<TextCustom truncate bold>
|
||||
Lorem ipsum,{" "}
|
||||
<TextCustom color="green">{activeCategory}</TextCustom> dolor
|
||||
sit amet consectetur adipisicing elit.
|
||||
</TextCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
||||
<TextCustom>{new Date().toLocaleDateString()}</TextCustom>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<TextCustom truncate={2}>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur
|
||||
eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora,
|
||||
atque. Aperiam minima asperiores dicta perferendis quis adipisci,
|
||||
dolore optio porro!
|
||||
</TextCustom>
|
||||
</StackCustom>
|
||||
</BoxWithHeaderSection>
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
117
app/(application)/(user)/event/[id]/[status]/detail-event.tsx
Normal file
117
app/(application)/(user)/event/[id]/[status]/detail-event.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import {
|
||||
BaseBox,
|
||||
DotButton,
|
||||
DrawerCustom,
|
||||
Grid,
|
||||
MenuDrawerDynamicGrid,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import Event_AlertButtonStatusSection from "@/screens/Event/AlertButtonStatusSection";
|
||||
import Event_ButtonStatusSection from "@/screens/Event/ButtonStatusSection";
|
||||
import { menuDrawerDraftEvent } from "@/screens/Event/menuDrawerDraft";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function EventDetailStatus() {
|
||||
const { id, status } = useLocalSearchParams();
|
||||
const [openDrawer, setOpenDrawer] = useState(false);
|
||||
const [openAlert, setOpenAlert] = useState(false);
|
||||
const [openDeleteAlert, setOpenDeleteAlert] = useState(false);
|
||||
|
||||
const handlePress = (item: IMenuDrawerItem) => {
|
||||
console.log("PATH >> ", item.path);
|
||||
router.navigate(item.path as any);
|
||||
setOpenDrawer(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
title: `Detail ${status === "publish" ? "" : status}`,
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
headerRight: () =>
|
||||
status === "draft" ? (
|
||||
<DotButton onPress={() => setOpenDrawer(true)} />
|
||||
) : null,
|
||||
}}
|
||||
/>
|
||||
<ViewWrapper>
|
||||
<BaseBox>
|
||||
<StackCustom>
|
||||
<TextCustom bold align="center" size="xlarge">
|
||||
Judul event {status}
|
||||
</TextCustom>
|
||||
{listData.map((item, index) => (
|
||||
<Grid key={index}>
|
||||
<Grid.Col span={4}>
|
||||
<TextCustom bold>{item.title}</TextCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<TextCustom>{item.value}</TextCustom>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
))}
|
||||
</StackCustom>
|
||||
</BaseBox>
|
||||
<Event_ButtonStatusSection
|
||||
status={status as string}
|
||||
onOpenAlert={setOpenAlert}
|
||||
onOpenDeleteAlert={setOpenDeleteAlert}
|
||||
/>
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
|
||||
<DrawerCustom
|
||||
isVisible={openDrawer}
|
||||
closeDrawer={() => setOpenDrawer(false)}
|
||||
height={250}
|
||||
>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={menuDrawerDraftEvent({ id: id as string })}
|
||||
columns={4}
|
||||
onPressItem={handlePress}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
|
||||
<Event_AlertButtonStatusSection
|
||||
id={id as string}
|
||||
status={status as string}
|
||||
openAlert={openAlert}
|
||||
setOpenAlert={setOpenAlert}
|
||||
openDeleteAlert={openDeleteAlert}
|
||||
setOpenDeleteAlert={setOpenDeleteAlert}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const listData = [
|
||||
{
|
||||
title: "Lokasi",
|
||||
value:
|
||||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora, atque. Aperiam minima asperiores dicta perferendis quis adipisci, dolore optio porro!",
|
||||
},
|
||||
{
|
||||
title: "Tipe Acara",
|
||||
value: "Workshop",
|
||||
},
|
||||
{
|
||||
title: "Tanggal Mulai",
|
||||
value: "Senin, 18 Juli 2025, 10:00 WIB",
|
||||
},
|
||||
{
|
||||
title: "Tanggal Berakhir",
|
||||
value: "Selasa, 19 Juli 2025, 12:00 WIB",
|
||||
},
|
||||
{
|
||||
title: "Deskripsi",
|
||||
value:
|
||||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora, atque. Aperiam minima asperiores dicta perferendis quis adipisci, dolore optio porro!",
|
||||
},
|
||||
];
|
||||
51
app/(application)/(user)/event/[id]/contribution.tsx
Normal file
51
app/(application)/(user)/event/[id]/contribution.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import {
|
||||
DotButton,
|
||||
DrawerCustom,
|
||||
MenuDrawerDynamicGrid,
|
||||
ViewWrapper,
|
||||
Spacing,
|
||||
} from "@/components";
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function EventDetailContribution() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const [openDrawer, setOpenDrawer] = useState(false);
|
||||
|
||||
const handlePress = (item: IMenuDrawerItem) => {
|
||||
console.log("PATH ", item.path);
|
||||
router.navigate(item.path as any);
|
||||
setOpenDrawer(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
title: `Detail kontribusi`,
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||
}}
|
||||
/>
|
||||
<ViewWrapper>
|
||||
<Event_BoxDetailPublishSection />
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
<DrawerCustom
|
||||
isVisible={openDrawer}
|
||||
closeDrawer={() => setOpenDrawer(false)}
|
||||
height={250}
|
||||
>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={menuDrawerPublishEvent({ id: id as string })}
|
||||
columns={4}
|
||||
onPressItem={handlePress}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
107
app/(application)/(user)/event/[id]/edit.tsx
Normal file
107
app/(application)/(user)/event/[id]/edit.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
ButtonCustom,
|
||||
SelectCustom,
|
||||
StackCustom,
|
||||
TextAreaCustom,
|
||||
TextInputCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
|
||||
import { masterTypeEvent } from "@/lib/dummy-data/event/master-type-event";
|
||||
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
||||
import { router } from "expo-router";
|
||||
import React, { useState } from "react";
|
||||
import { Platform } from "react-native";
|
||||
|
||||
export default function EventEdit() {
|
||||
const [selectedDate, setSelectedDate] = useState<
|
||||
Date | DateTimePickerEvent | null
|
||||
>(null);
|
||||
|
||||
const [selectedEndDate, setSelectedEndDate] = useState<
|
||||
Date | DateTimePickerEvent | null
|
||||
>(null);
|
||||
|
||||
const handlerSubmit = () => {
|
||||
try {
|
||||
if (selectedDate) {
|
||||
console.log("Tanggal yang dipilih:", selectedDate);
|
||||
console.log(`ISO Format ${Platform.OS}:`, selectedDate.toString());
|
||||
// Kirim ke API atau proses lanjutan
|
||||
} else {
|
||||
console.log("Tanggal belum dipilih");
|
||||
}
|
||||
|
||||
if (selectedEndDate) {
|
||||
console.log("Tanggal yang dipilih:", selectedEndDate);
|
||||
console.log(`ISO Format ${Platform.OS}:`, selectedEndDate.toString());
|
||||
// Kirim ke API atau proses lanjutan
|
||||
} else {
|
||||
console.log("Tanggal berakhir belum dipilih");
|
||||
}
|
||||
|
||||
console.log("Data berhasil terupdate");
|
||||
router.back()
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
const buttonSubmit = (
|
||||
<ButtonCustom title="Update" onPress={handlerSubmit} />
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<StackCustom gap={"xs"}>
|
||||
<TextInputCustom
|
||||
placeholder="Masukkan nama event"
|
||||
label="Nama Event"
|
||||
required
|
||||
/>
|
||||
<SelectCustom
|
||||
label="Tipe Event"
|
||||
placeholder="Pilih tipe event"
|
||||
data={masterTypeEvent}
|
||||
onChange={(value) => console.log(value)}
|
||||
/>
|
||||
<TextInputCustom
|
||||
label="Lokasi"
|
||||
placeholder="Masukkan lokasi event"
|
||||
required
|
||||
/>
|
||||
|
||||
<DateTimePickerCustom
|
||||
label="Tanggal & Waktu Mulai"
|
||||
required
|
||||
onChange={(date: Date) => {
|
||||
setSelectedDate(date as any);
|
||||
}}
|
||||
value={selectedDate as any}
|
||||
minimumDate={new Date(Date.now())}
|
||||
/>
|
||||
|
||||
<DateTimePickerCustom
|
||||
label="Tanggal & Waktu Berakhir"
|
||||
required
|
||||
onChange={(date: Date) => {
|
||||
setSelectedEndDate(date as any);
|
||||
}}
|
||||
value={selectedEndDate as any}
|
||||
/>
|
||||
|
||||
<TextAreaCustom
|
||||
label="Deskripsi"
|
||||
placeholder="Masukkan deskripsi event"
|
||||
required
|
||||
showCount
|
||||
maxLength={100}
|
||||
/>
|
||||
|
||||
{buttonSubmit}
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
51
app/(application)/(user)/event/[id]/history.tsx
Normal file
51
app/(application)/(user)/event/[id]/history.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import {
|
||||
DotButton,
|
||||
DrawerCustom,
|
||||
MenuDrawerDynamicGrid,
|
||||
ViewWrapper,
|
||||
Spacing,
|
||||
} from "@/components";
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function EventDetailHistory() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const [openDrawer, setOpenDrawer] = useState(false);
|
||||
|
||||
const handlePress = (item: IMenuDrawerItem) => {
|
||||
console.log("PATH ", item.path);
|
||||
router.navigate(item.path as any);
|
||||
setOpenDrawer(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
title: `Detail riwayat`,
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||
}}
|
||||
/>
|
||||
<ViewWrapper>
|
||||
<Event_BoxDetailPublishSection />
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
<DrawerCustom
|
||||
isVisible={openDrawer}
|
||||
closeDrawer={() => setOpenDrawer(false)}
|
||||
height={250}
|
||||
>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={menuDrawerPublishEvent({ id: id as string })}
|
||||
columns={4}
|
||||
onPressItem={handlePress}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
17
app/(application)/(user)/event/[id]/list-of-participants.tsx
Normal file
17
app/(application)/(user)/event/[id]/list-of-participants.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import {
|
||||
AvatarUsernameAndOtherComponent,
|
||||
BaseBox,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
|
||||
export default function EventListOfParticipants() {
|
||||
return (
|
||||
<ViewWrapper>
|
||||
{Array.from({ length: 10 }).map((_, index) => (
|
||||
<BaseBox key={index} paddingBlock={0}>
|
||||
<AvatarUsernameAndOtherComponent avatarHref={`/profile/${index}`} />
|
||||
</BaseBox>
|
||||
))}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
64
app/(application)/(user)/event/[id]/publish.tsx
Normal file
64
app/(application)/(user)/event/[id]/publish.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
ButtonCustom,
|
||||
DotButton,
|
||||
DrawerCustom,
|
||||
MenuDrawerDynamicGrid,
|
||||
Spacing,
|
||||
ViewWrapper
|
||||
} from "@/components";
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { Alert } from "react-native";
|
||||
|
||||
export default function EventDetailPublish() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const [openDrawer, setOpenDrawer] = useState(false);
|
||||
|
||||
const handlePress = (item: IMenuDrawerItem) => {
|
||||
console.log("PATH ", item.path);
|
||||
router.navigate(item.path as any);
|
||||
setOpenDrawer(false);
|
||||
};
|
||||
|
||||
const footerButton = (
|
||||
<ButtonCustom
|
||||
backgroundColor="green"
|
||||
textColor="white"
|
||||
onPress={() => Alert.alert("Anda berhasil join event ini")}
|
||||
>
|
||||
Join
|
||||
</ButtonCustom>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
title: `Event publish`,
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||
}}
|
||||
/>
|
||||
<ViewWrapper>
|
||||
<Event_BoxDetailPublishSection footerButton={footerButton} />
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
|
||||
<DrawerCustom
|
||||
isVisible={openDrawer}
|
||||
closeDrawer={() => setOpenDrawer(false)}
|
||||
height={250}
|
||||
>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={menuDrawerPublishEvent({ id: id as string })}
|
||||
columns={4}
|
||||
onPressItem={handlePress}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
109
app/(application)/(user)/event/create.tsx
Normal file
109
app/(application)/(user)/event/create.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
ButtonCustom,
|
||||
SelectCustom,
|
||||
StackCustom,
|
||||
TextAreaCustom,
|
||||
TextInputCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
|
||||
import { masterTypeEvent } from "@/lib/dummy-data/event/master-type-event";
|
||||
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
||||
import { router } from "expo-router";
|
||||
import React, { useState } from "react";
|
||||
import { Platform } from "react-native";
|
||||
|
||||
export default function EventCreate() {
|
||||
const [selectedDate, setSelectedDate] = useState<
|
||||
Date | DateTimePickerEvent | null
|
||||
>(null);
|
||||
|
||||
const [selectedEndDate, setSelectedEndDate] = useState<
|
||||
Date | DateTimePickerEvent | null
|
||||
>(null);
|
||||
|
||||
const handlerSubmit = () => {
|
||||
try {
|
||||
if (selectedDate) {
|
||||
console.log("Tanggal yang dipilih:", selectedDate);
|
||||
console.log(`ISO Format ${Platform.OS}:`, selectedDate.toString());
|
||||
// Kirim ke API atau proses lanjutan
|
||||
} else {
|
||||
console.log("Tanggal belum dipilih");
|
||||
}
|
||||
|
||||
if (selectedEndDate) {
|
||||
console.log("Tanggal yang dipilih:", selectedEndDate);
|
||||
console.log(`ISO Format ${Platform.OS}:`, selectedEndDate.toString());
|
||||
// Kirim ke API atau proses lanjutan
|
||||
} else {
|
||||
console.log("Tanggal berakhir belum dipilih");
|
||||
}
|
||||
|
||||
console.log("Data berhasil disimpan");
|
||||
router.navigate("/event/status");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
const buttonSubmit = (
|
||||
<ButtonCustom title="Simpan" onPress={handlerSubmit} />
|
||||
// <BoxButtonOnFooter>
|
||||
// </BoxButtonOnFooter>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<StackCustom gap={"xs"}>
|
||||
<TextInputCustom
|
||||
placeholder="Masukkan nama event"
|
||||
label="Nama Event"
|
||||
required
|
||||
/>
|
||||
<SelectCustom
|
||||
label="Tipe Event"
|
||||
placeholder="Pilih tipe event"
|
||||
data={masterTypeEvent}
|
||||
onChange={(value) => console.log(value)}
|
||||
/>
|
||||
<TextInputCustom
|
||||
label="Lokasi"
|
||||
placeholder="Masukkan lokasi event"
|
||||
required
|
||||
/>
|
||||
|
||||
<DateTimePickerCustom
|
||||
label="Tanggal & Waktu Mulai"
|
||||
required
|
||||
onChange={(date: Date) => {
|
||||
setSelectedDate(date as any);
|
||||
}}
|
||||
value={selectedDate as any}
|
||||
minimumDate={new Date(Date.now())}
|
||||
/>
|
||||
|
||||
<DateTimePickerCustom
|
||||
label="Tanggal & Waktu Berakhir"
|
||||
required
|
||||
onChange={(date: Date) => {
|
||||
setSelectedEndDate(date as any);
|
||||
}}
|
||||
value={selectedEndDate as any}
|
||||
/>
|
||||
|
||||
<TextAreaCustom
|
||||
label="Deskripsi"
|
||||
placeholder="Masukkan deskripsi event"
|
||||
required
|
||||
showCount
|
||||
maxLength={100}
|
||||
/>
|
||||
|
||||
{buttonSubmit}
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
||||
import { listDataDummyCommentarForum } from "@/screens/Forum/list-data-dummy";
|
||||
import { listDummyDiscussionForum } from "@/screens/Forum/list-data-dummy";
|
||||
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
@@ -47,12 +47,14 @@ export default function Forumku() {
|
||||
</ButtonCustom>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
{listDataDummyCommentarForum.map((e, i) => (
|
||||
{listDummyDiscussionForum.map((e, i) => (
|
||||
<Forum_BoxDetailSection
|
||||
key={i}
|
||||
data={e}
|
||||
setOpenDrawer={setOpenDrawer}
|
||||
setStatus={setStatus}
|
||||
isTruncate={true}
|
||||
href={`/forum/${id}`}
|
||||
/>
|
||||
))}
|
||||
</StackCustom>
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
ButtonCustom,
|
||||
DrawerCustom,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
TextAreaCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
@@ -12,9 +11,9 @@ import Forum_CommentarBoxSection from "@/screens/Forum/CommentarBoxSection";
|
||||
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
||||
import { listDummyCommentarForum } from "@/screens/Forum/list-data-dummy";
|
||||
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
||||
import Forum_MenuDrawerCommentar from "@/screens/Forum/MenuDrawerSection.tsx/MenuCommentar";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { Divider } from "react-native-paper";
|
||||
|
||||
export default function ForumDetail() {
|
||||
const { id } = useLocalSearchParams();
|
||||
@@ -27,7 +26,7 @@ export default function ForumDetail() {
|
||||
|
||||
// Comentar
|
||||
const [openDrawerCommentar, setOpenDrawerCommentar] = useState(false);
|
||||
const [statusCommentar, setStatusCommentar] = useState("");
|
||||
const [alertDeleteCommentar, setAlertDeleteCommentar] = useState(false);
|
||||
|
||||
const dataDummy = {
|
||||
name: "Bagas",
|
||||
@@ -78,7 +77,6 @@ export default function ForumDetail() {
|
||||
key={i}
|
||||
data={e}
|
||||
setOpenDrawer={setOpenDrawerCommentar}
|
||||
setStatus={setStatusCommentar}
|
||||
/>
|
||||
))}
|
||||
</ViewWrapper>
|
||||
@@ -145,16 +143,34 @@ export default function ForumDetail() {
|
||||
isVisible={openDrawerCommentar}
|
||||
closeDrawer={() => setOpenDrawerCommentar(false)}
|
||||
>
|
||||
<Forum_MenuDrawerBerandaSection
|
||||
<Forum_MenuDrawerCommentar
|
||||
id={id as string}
|
||||
status={statusCommentar}
|
||||
setIsDrawerOpen={() => {
|
||||
setOpenDrawerCommentar(false);
|
||||
}}
|
||||
setShowDeleteAlert={setDeleteAlert}
|
||||
setShowAlertStatus={setAlertStatus}
|
||||
setShowDeleteAlert={setAlertDeleteCommentar}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
|
||||
{/* Alert Delete Commentar */}
|
||||
<AlertCustom
|
||||
isVisible={alertDeleteCommentar}
|
||||
title="Hapus Komentar"
|
||||
message="Apakah Anda yakin ingin menghapus komentar ini?"
|
||||
onLeftPress={() => {
|
||||
setOpenDrawerCommentar(false);
|
||||
setAlertDeleteCommentar(false);
|
||||
console.log("Batal");
|
||||
}}
|
||||
onRightPress={() => {
|
||||
setOpenDrawerCommentar(false);
|
||||
setAlertDeleteCommentar(false);
|
||||
console.log("Hapus commentar");
|
||||
}}
|
||||
textLeft="Batal"
|
||||
textRight="Hapus"
|
||||
colorRight={MainColor.red}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
BoxButtonOnFooter,
|
||||
ButtonCustom,
|
||||
TextAreaCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function ForumOtherReportCommentar() {
|
||||
const handleSubmit = (
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
backgroundColor={MainColor.red}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Report lainnya");
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Report
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper footerComponent={handleSubmit}>
|
||||
<TextAreaCustom placeholder="Laporkan Komentar" />
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
32
app/(application)/(user)/forum/[id]/other-report-posting.tsx
Normal file
32
app/(application)/(user)/forum/[id]/other-report-posting.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
BoxButtonOnFooter,
|
||||
ButtonCustom,
|
||||
TextAreaCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function ForumOtherReportPosting() {
|
||||
const handleSubmit = (
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
backgroundColor={MainColor.red}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Report lainnya");
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Report
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper footerComponent={handleSubmit}>
|
||||
<TextAreaCustom placeholder="Laporkan Diskusi" />
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
42
app/(application)/(user)/forum/[id]/report-commentar.tsx
Normal file
42
app/(application)/(user)/forum/[id]/report-commentar.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import {
|
||||
ButtonCustom,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
ViewWrapper
|
||||
} from "@/components";
|
||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function ForumReportCommentar() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<StackCustom>
|
||||
<Forum_ReportListSection />
|
||||
<ButtonCustom
|
||||
backgroundColor={MainColor.red}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Report");
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Report
|
||||
</ButtonCustom>
|
||||
<ButtonCustom
|
||||
backgroundColor={AccentColor.blue}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Lainnya");
|
||||
router.replace("/forum/[id]/other-report-commentar");
|
||||
}}
|
||||
>
|
||||
Lainnya
|
||||
</ButtonCustom>
|
||||
<Spacing/>
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
37
app/(application)/(user)/forum/[id]/report-posting.tsx
Normal file
37
app/(application)/(user)/forum/[id]/report-posting.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ViewWrapper, StackCustom, ButtonCustom, Spacing } from "@/components";
|
||||
import { MainColor, AccentColor } from "@/constants/color-palet";
|
||||
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function ForumReportPosting() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<StackCustom>
|
||||
<Forum_ReportListSection />
|
||||
<ButtonCustom
|
||||
backgroundColor={MainColor.red}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Report");
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Report
|
||||
</ButtonCustom>
|
||||
<ButtonCustom
|
||||
backgroundColor={AccentColor.blue}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Lainnya");
|
||||
router.replace("/forum/[id]/other-report-posting");
|
||||
}}
|
||||
>
|
||||
Lainnya
|
||||
</ButtonCustom>
|
||||
<Spacing />
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -11,18 +11,18 @@ import { useState } from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
const categories = [
|
||||
{ id: 1, label: "Semua" },
|
||||
{ id: 2, label: "Event" },
|
||||
{ id: 3, label: "Job" },
|
||||
{ id: 4, label: "Voting" },
|
||||
{ id: 5, label: "Donasi" },
|
||||
{ id: 6, label: "Investasi" },
|
||||
{ id: 7, label: "Forum" },
|
||||
{ id: 8, label: "Collaboration" },
|
||||
{ value: "all", label: "Semua" },
|
||||
{ value: "event", label: "Event" },
|
||||
{ value: "job", label: "Job" },
|
||||
{ value: "voting", label: "Voting" },
|
||||
{ value: "donasi", label: "Donasi" },
|
||||
{ value: "investasi", label: "Investasi" },
|
||||
{ value: "forum", label: "Forum" },
|
||||
{ value: "collaboration", label: "Collaboration" },
|
||||
];
|
||||
|
||||
const selectedCategory = (id: number) => {
|
||||
const category = categories.find((c) => c.id === id);
|
||||
const selectedCategory = (value: string) => {
|
||||
const category = categories.find((c) => c.value === value);
|
||||
return category?.label;
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ const BoxNotification = ({
|
||||
activeCategory,
|
||||
}: {
|
||||
index: number;
|
||||
activeCategory: number | null;
|
||||
activeCategory: string | null;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
@@ -39,13 +39,13 @@ const BoxNotification = ({
|
||||
onPress={() =>
|
||||
console.log(
|
||||
"Notification >",
|
||||
selectedCategory(activeCategory as number)
|
||||
selectedCategory(activeCategory as string)
|
||||
)
|
||||
}
|
||||
>
|
||||
<StackCustom>
|
||||
<TextCustom bold>
|
||||
# {selectedCategory(activeCategory as number)}
|
||||
# {selectedCategory(activeCategory as string)}
|
||||
</TextCustom>
|
||||
|
||||
<View
|
||||
@@ -81,38 +81,31 @@ const BoxNotification = ({
|
||||
};
|
||||
|
||||
export default function Notifications() {
|
||||
const [activeCategory, setActiveCategory] = useState<number | null>(1);
|
||||
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
||||
|
||||
const handlePress = (item: any) => {
|
||||
setActiveCategory(item.id);
|
||||
setActiveCategory(item.value);
|
||||
// tambahkan logika lain seperti filter dsb.
|
||||
};
|
||||
return (
|
||||
<ViewWrapper
|
||||
headerComponent={
|
||||
<ScrollableCustom
|
||||
data={categories}
|
||||
data={categories.map((e, i) => ({
|
||||
id: i,
|
||||
label: e.label,
|
||||
value: e.value,
|
||||
}))}
|
||||
onButtonPress={handlePress}
|
||||
activeId={activeCategory as any}
|
||||
activeId={activeCategory as string}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{Array.from({ length: 20 }).map((e, i) => (
|
||||
<View key={i}>
|
||||
<BoxNotification index={i} activeCategory={activeCategory} />
|
||||
<BoxNotification index={i} activeCategory={activeCategory as any} />
|
||||
</View>
|
||||
))}
|
||||
|
||||
{/* Konten utama di sini */}
|
||||
{/* <View style={{ flex: 1 }}>
|
||||
<Text style={{ color: "white" }}>
|
||||
{activeCategory
|
||||
? `Kategori Aktif: ${
|
||||
categories.find((c) => c.id === activeCategory)?.label
|
||||
}`
|
||||
: "Pilih kategori"}
|
||||
</Text>
|
||||
</View> */}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DrawerCustom } from "@/components";
|
||||
import { AlertCustom, DrawerCustom } from "@/components";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
@@ -7,13 +7,14 @@ import Portofolio_MenuDrawerSection from "@/screens/Portofolio/MenuDrawer";
|
||||
import PorfofolioSection from "@/screens/Portofolio/PorfofolioSection";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { Stack, useLocalSearchParams } from "expo-router";
|
||||
import { Stack, useLocalSearchParams, router } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { TouchableOpacity } from "react-native";
|
||||
|
||||
export default function Portofolio() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||
|
||||
const openDrawer = () => {
|
||||
setIsDrawerOpen(true);
|
||||
@@ -42,7 +43,7 @@ export default function Portofolio() {
|
||||
headerTitleStyle: GStyles.headerTitleStyle,
|
||||
}}
|
||||
/>
|
||||
<PorfofolioSection />
|
||||
<PorfofolioSection setShowDeleteAlert={setDeleteAlert} />
|
||||
</ViewWrapper>
|
||||
|
||||
{/* Drawer Komponen Eksternal */}
|
||||
@@ -56,6 +57,22 @@ export default function Portofolio() {
|
||||
setIsDrawerOpen={setIsDrawerOpen}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
|
||||
{/* Alert Delete */}
|
||||
<AlertCustom
|
||||
isVisible={deleteAlert}
|
||||
onLeftPress={() => setDeleteAlert(false)}
|
||||
onRightPress={() => {
|
||||
setDeleteAlert(false);
|
||||
console.log("Hapus portofolio");
|
||||
router.back();
|
||||
}}
|
||||
title="Hapus Portofolio"
|
||||
message="Apakah Anda yakin ingin menghapus portofolio ini?"
|
||||
textLeft="Batal"
|
||||
textRight="Hapus"
|
||||
colorRight={MainColor.red}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -103,14 +103,7 @@ export default function CreateProfile() {
|
||||
required
|
||||
onChange={(value) => setData({ ...(data as any), gender: value })}
|
||||
/>
|
||||
<TextInputCustom
|
||||
required
|
||||
label="Alamat"
|
||||
placeholder="Masukkan alamat"
|
||||
value={data.address}
|
||||
onChangeText={(text) => setData({ ...data, address: text })}
|
||||
/>
|
||||
{/* <Spacing /> */}
|
||||
<Spacing />
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
);
|
||||
|
||||
@@ -22,15 +22,8 @@ export default function ProfileEdit() {
|
||||
});
|
||||
|
||||
const options = [
|
||||
{ label: "React", value: "react" },
|
||||
{ label: "Vue", value: "vue" },
|
||||
{ label: "Angular", value: "angular" },
|
||||
{ label: "Svelte", value: "svelte" },
|
||||
{ label: "Next.js", value: "nextjs" },
|
||||
{ label: "Nuxt.js", value: "nuxtjs" },
|
||||
{ label: "Remix", value: "remix" },
|
||||
{ label: "Sapper", value: "sapper" },
|
||||
{ label: "SvelteKit", value: "sveltekit" },
|
||||
{ label: "Laki-laki", value: "laki-laki" },
|
||||
{ label: "Perempuan", value: "perempuan" },
|
||||
];
|
||||
|
||||
const handleSave = () => {
|
||||
@@ -59,16 +52,6 @@ export default function ProfileEdit() {
|
||||
}
|
||||
>
|
||||
<StackCustom gap={"xs"}>
|
||||
<SelectCustom
|
||||
label="Framework"
|
||||
placeholder="Pilih framework favoritmu"
|
||||
data={options}
|
||||
value={data.selectedValue}
|
||||
onChange={(value) => {
|
||||
setData({ ...(data as any), selectedValue: value });
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextInputCustom
|
||||
label="Nama"
|
||||
placeholder="Nama"
|
||||
@@ -96,6 +79,16 @@ export default function ProfileEdit() {
|
||||
}}
|
||||
required
|
||||
/>
|
||||
<SelectCustom
|
||||
required
|
||||
label="Jenis Kelamin"
|
||||
placeholder="Pilih jenis kelamin"
|
||||
data={options}
|
||||
value={data.selectedValue}
|
||||
onChange={(value) => {
|
||||
setData({ ...(data as any), selectedValue: value });
|
||||
}}
|
||||
/>
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
);
|
||||
|
||||
@@ -4,8 +4,8 @@ import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import DrawerCustom from "@/components/Drawer/DrawerCustom";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { drawerItemsProfile } from "@/screens/Profile/ListPage";
|
||||
import Profile_MenuDrawerSection from "@/screens/Profile/MenuDrawerSection";
|
||||
import ProfilSection from "@/screens/Profile/ProfilSection";
|
||||
import Profile_MenuDrawerSection from "@/screens/Profile/menuDrawerSection";
|
||||
import ProfileSection from "@/screens/Profile/ProfileSection";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
@@ -52,7 +52,7 @@ export default function Profile() {
|
||||
headerTitleStyle: GStyles.headerTitleStyle,
|
||||
}}
|
||||
/>
|
||||
<ProfilSection />
|
||||
<ProfileSection />
|
||||
</ViewWrapper>
|
||||
|
||||
{/* Drawer Komponen Eksternal */}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB |
BIN
assets/images/dummy/dummy-user.png
Normal file
BIN
assets/images/dummy/dummy-user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 395 KiB |
3
bun.lock
3
bun.lock
@@ -5,6 +5,7 @@
|
||||
"name": "hipmi-mobile",
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^14.1.0",
|
||||
"@react-native-community/datetimepicker": "8.4.1",
|
||||
"@react-navigation/bottom-tabs": "^7.4.2",
|
||||
"@react-navigation/drawer": "^7.5.2",
|
||||
"@react-navigation/elements": "^2.3.8",
|
||||
@@ -372,6 +373,8 @@
|
||||
|
||||
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="],
|
||||
|
||||
"@react-native-community/datetimepicker": ["@react-native-community/datetimepicker@8.4.1", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "expo": ">=52.0.0", "react": "*", "react-native": "*", "react-native-windows": "*" }, "optionalPeers": ["expo", "react-native-windows"] }, "sha512-DrK+CUS5fZnz8dhzBezirkzQTcNDdaXer3oDLh0z4nc2tbdIdnzwvXCvi8IEOIvleoc9L95xS5tKUl0/Xv71Mg=="],
|
||||
|
||||
"@react-native/assets-registry": ["@react-native/assets-registry@0.79.5", "", {}, "sha512-N4Kt1cKxO5zgM/BLiyzuuDNquZPiIgfktEQ6TqJ/4nKA8zr4e8KJgU6Tb2eleihDO4E24HmkvGc73naybKRz/w=="],
|
||||
|
||||
"@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.79.5", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.79.5" } }, "sha512-Rt/imdfqXihD/sn0xnV4flxxb1aLLjPtMF1QleQjEhJsTUPpH4TFlfOpoCvsrXoDl4OIcB1k4FVM24Ez92zf5w=="],
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
import { AccentColor } from "@/constants/color-palet";
|
||||
import { PADDING_EXTRA_SMALL, PADDING_MEDIUM, PADDING_SMALL } from "@/constants/constans-value";
|
||||
import { StyleProp, TouchableHighlight, View, ViewStyle } from "react-native";
|
||||
import {
|
||||
PADDING_MEDIUM,
|
||||
PADDING_SMALL
|
||||
} from "@/constants/constans-value";
|
||||
import { Href, router } from "expo-router";
|
||||
import {
|
||||
StyleProp,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
ViewStyle
|
||||
} from "react-native";
|
||||
|
||||
interface BaseBoxProps {
|
||||
children: React.ReactNode;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
href?: Href;
|
||||
onPress?: () => void;
|
||||
marginBottom?: number;
|
||||
padding?: number;
|
||||
paddingTop?: number;
|
||||
paddingBottom?: number;
|
||||
paddingInline?: number;
|
||||
paddingBlock?: number;
|
||||
}
|
||||
@@ -15,16 +27,21 @@ interface BaseBoxProps {
|
||||
export default function BaseBox({
|
||||
children,
|
||||
style,
|
||||
href,
|
||||
onPress,
|
||||
marginBottom = PADDING_MEDIUM,
|
||||
paddingBlock = PADDING_EXTRA_SMALL,
|
||||
paddingBlock = PADDING_MEDIUM,
|
||||
paddingInline = PADDING_SMALL,
|
||||
paddingTop = PADDING_MEDIUM,
|
||||
paddingBottom = PADDING_MEDIUM,
|
||||
}: BaseBoxProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{onPress ? (
|
||||
<TouchableHighlight
|
||||
onPress={onPress}
|
||||
{onPress || href ? (
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
onPress={href ? () => router.navigate(href) : onPress}
|
||||
style={[
|
||||
{
|
||||
backgroundColor: AccentColor.darkblue,
|
||||
@@ -34,13 +51,14 @@ export default function BaseBox({
|
||||
marginBottom,
|
||||
paddingBlock,
|
||||
paddingInline,
|
||||
paddingTop,
|
||||
paddingBottom,
|
||||
},
|
||||
style,
|
||||
]}
|
||||
// activeOpacity={0.7}
|
||||
>
|
||||
<View>{children}</View>
|
||||
</TouchableHighlight>
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<View
|
||||
style={[
|
||||
|
||||
20
components/Box/BoxWithHeaderInformation.tsx
Normal file
20
components/Box/BoxWithHeaderInformation.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Href } from "expo-router";
|
||||
import BaseBox from "./BaseBox";
|
||||
|
||||
export default function BoxWithHeaderSection({
|
||||
children,
|
||||
href,
|
||||
onPress,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
href?: Href;
|
||||
onPress?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<BaseBox href={href} onPress={onPress} paddingTop={5}>
|
||||
{children}
|
||||
</BaseBox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
13
components/Button/DotButton.tsx
Normal file
13
components/Button/DotButton.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
|
||||
export default function DotButton({ onPress }: { onPress: () => void }) {
|
||||
return (
|
||||
<Ionicons
|
||||
onPress={onPress}
|
||||
name="ellipsis-vertical"
|
||||
size={20}
|
||||
color={MainColor.yellow}
|
||||
/>
|
||||
);
|
||||
}
|
||||
205
components/DateInput/DataTimeAndroid.tsx
Normal file
205
components/DateInput/DataTimeAndroid.tsx
Normal file
@@ -0,0 +1,205 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
// DateTimeInput.tsx
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import DateTimePicker, {
|
||||
DateTimePickerEvent,
|
||||
} from "@react-native-community/datetimepicker";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { Pressable, StyleProp, Text, View, ViewStyle } from "react-native";
|
||||
import Grid from "../Grid/GridCustom";
|
||||
import TextCustom from "../Text/TextCustom";
|
||||
|
||||
interface DateTimeInputProps {
|
||||
// Main
|
||||
value?: DateTimePickerEvent;
|
||||
mode?: "date" | "time";
|
||||
onChange: (selectedDate: DateTimePickerEvent) => void;
|
||||
maximumDate?: Date;
|
||||
minimumDate?: Date;
|
||||
// Main
|
||||
label?: string;
|
||||
required?: boolean;
|
||||
disabled?: boolean;
|
||||
iconLeft?: React.ReactNode;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
borderRadius?: number;
|
||||
externalError?: string;
|
||||
internalError?: string;
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
const DateTimeInput_Android: React.FC<DateTimeInputProps> = ({
|
||||
// Main
|
||||
value,
|
||||
mode,
|
||||
onChange,
|
||||
maximumDate,
|
||||
minimumDate,
|
||||
// Main
|
||||
label,
|
||||
required,
|
||||
disabled,
|
||||
iconLeft,
|
||||
style,
|
||||
borderRadius = 8,
|
||||
externalError,
|
||||
internalError,
|
||||
containerStyle,
|
||||
}) => {
|
||||
const [showDate, setShowDate] = useState(false);
|
||||
const [showTime, setShowTime] = useState(false);
|
||||
const [selectedDate, setSelectedDate] = useState<Date>(value as any);
|
||||
const [selectedTime, setSelectedTime] = useState<Date>(value as any);
|
||||
|
||||
// Fungsi untuk menggabungkan tanggal dan waktu
|
||||
const combineDateAndTime = useCallback((date: Date, time: Date): Date => {
|
||||
const combined = new Date(date);
|
||||
combined.setHours(
|
||||
time.getHours(),
|
||||
time.getMinutes(),
|
||||
time.getSeconds(),
|
||||
time.getMilliseconds()
|
||||
);
|
||||
return combined;
|
||||
}, []);
|
||||
|
||||
// Handler untuk tanggal
|
||||
const handleConfirmDate = (event: DateTimePickerEvent, date?: Date) => {
|
||||
if (event.type === "set" && date) {
|
||||
setSelectedDate(date);
|
||||
if (selectedTime) {
|
||||
const combined = combineDateAndTime(date, selectedTime);
|
||||
onChange?.(combined as any);
|
||||
}
|
||||
}
|
||||
setShowDate(false);
|
||||
};
|
||||
|
||||
// Handler untuk waktu
|
||||
const handleConfirmTime = (event: DateTimePickerEvent, time?: Date) => {
|
||||
if (event.type === "set" && time) {
|
||||
setSelectedTime(time);
|
||||
if (selectedDate) {
|
||||
const combined = combineDateAndTime(selectedDate, time);
|
||||
onChange?.(combined as any);
|
||||
}
|
||||
}
|
||||
setShowTime(false);
|
||||
};
|
||||
|
||||
const toggleDatePicker = () => {
|
||||
setShowDate(!showDate);
|
||||
};
|
||||
|
||||
const toggleTimePicker = () => {
|
||||
setShowTime(!showTime);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={[GStyles.inputContainerArea, containerStyle]}>
|
||||
{label && (
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
{required && <Text style={GStyles.inputRequired}> *</Text>}
|
||||
</Text>
|
||||
)}
|
||||
<View
|
||||
style={[
|
||||
style,
|
||||
{ borderRadius },
|
||||
externalError || internalError ? GStyles.inputErrorBorder : null,
|
||||
GStyles.inputContainerInput,
|
||||
disabled && GStyles.disabledBox,
|
||||
]}
|
||||
>
|
||||
<View style={GStyles.inputIcon}>
|
||||
<Ionicons
|
||||
name="calendar-outline"
|
||||
size={20}
|
||||
color={MainColor.placeholder}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<Grid
|
||||
containerStyle={{
|
||||
borderRadius: 8,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Grid.Col span={6} style={{}}>
|
||||
<Pressable onPress={toggleDatePicker}>
|
||||
<TextCustom color="gray">
|
||||
{selectedDate ? (
|
||||
<TextCustom color="black">
|
||||
{selectedDate.toLocaleDateString()}
|
||||
</TextCustom>
|
||||
) : (
|
||||
"Pilih tanggal"
|
||||
)}
|
||||
</TextCustom>
|
||||
</Pressable>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={1} style={{ alignItems: "center" }}>
|
||||
<TextCustom color="gray">|</TextCustom>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={5} style={{}}>
|
||||
<Pressable onPress={toggleTimePicker}>
|
||||
<TextCustom color="gray">
|
||||
{selectedTime ? (
|
||||
<TextCustom color="black">
|
||||
{selectedTime.toLocaleTimeString("id-ID", {
|
||||
minute: "2-digit",
|
||||
hour: "2-digit",
|
||||
})}
|
||||
</TextCustom>
|
||||
) : (
|
||||
"Pilih waktu"
|
||||
)}
|
||||
</TextCustom>
|
||||
</Pressable>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</View>
|
||||
{externalError ||
|
||||
(internalError && (
|
||||
<Text style={GStyles.inputErrorMessage}>
|
||||
{externalError || internalError}
|
||||
</Text>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{showDate && (
|
||||
<DateTimePicker
|
||||
testID="dateTimePicker"
|
||||
value={selectedDate || new Date()}
|
||||
mode="date"
|
||||
is24Hour={true}
|
||||
display="default"
|
||||
onChange={handleConfirmDate}
|
||||
minimumDate={minimumDate}
|
||||
maximumDate={maximumDate}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showTime && (
|
||||
<DateTimePicker
|
||||
testID="dateTimePicker"
|
||||
value={selectedTime || new Date()}
|
||||
mode="time"
|
||||
is24Hour={true}
|
||||
display="default"
|
||||
onChange={handleConfirmTime}
|
||||
minimumDate={minimumDate}
|
||||
maximumDate={maximumDate}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateTimeInput_Android;
|
||||
161
components/DateInput/DateTimeIOS.tsx
Normal file
161
components/DateInput/DateTimeIOS.tsx
Normal file
@@ -0,0 +1,161 @@
|
||||
// DateTimeInput.tsx
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import DateTimePicker, {
|
||||
DateTimePickerEvent,
|
||||
} from "@react-native-community/datetimepicker";
|
||||
import dayjs from "dayjs";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
StyleProp,
|
||||
Text,
|
||||
View,
|
||||
ViewStyle
|
||||
} from "react-native";
|
||||
import ClickableCustom from "../Clickable/ClickableCustom";
|
||||
import TextCustom from "../Text/TextCustom";
|
||||
|
||||
interface DateTimeInputProps {
|
||||
// Main
|
||||
value?: DateTimePickerEvent;
|
||||
mode?: "date" | "time";
|
||||
onChange: (selectedDate: DateTimePickerEvent) => void;
|
||||
maximumDate?: Date;
|
||||
minimumDate?: Date;
|
||||
// Main
|
||||
label?: string;
|
||||
required?: boolean;
|
||||
disabled?: boolean;
|
||||
iconLeft?: React.ReactNode;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
borderRadius?: number;
|
||||
externalError?: string;
|
||||
internalError?: string;
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
const DateTimeInput_IOS: React.FC<DateTimeInputProps> = ({
|
||||
// Main
|
||||
value,
|
||||
mode,
|
||||
onChange,
|
||||
maximumDate,
|
||||
minimumDate,
|
||||
// Main
|
||||
label,
|
||||
required,
|
||||
disabled,
|
||||
iconLeft,
|
||||
style,
|
||||
borderRadius = 8,
|
||||
externalError,
|
||||
internalError,
|
||||
containerStyle,
|
||||
}) => {
|
||||
const [show, setShow] = useState(false);
|
||||
const [selectedDate, setSelectedDate] = useState<Date | undefined>(
|
||||
value as any
|
||||
);
|
||||
|
||||
const handleConfirm = (event: any, date?: Date) => {
|
||||
if (event.type === "set" && date !== undefined) {
|
||||
setSelectedDate(date);
|
||||
onChange(date as any);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePress = () => {
|
||||
setShow(!show);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ClickableCustom
|
||||
activeOpacity={0.8}
|
||||
style={[GStyles.inputContainerArea, containerStyle]}
|
||||
onPress={handlePress}
|
||||
>
|
||||
{label && (
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
{required && <Text style={GStyles.inputRequired}> *</Text>}
|
||||
</Text>
|
||||
)}
|
||||
<View
|
||||
style={[
|
||||
style,
|
||||
{ borderRadius },
|
||||
externalError || internalError ? GStyles.inputErrorBorder : null,
|
||||
GStyles.inputContainerInput,
|
||||
disabled && GStyles.disabledBox,
|
||||
]}
|
||||
>
|
||||
<View style={GStyles.inputIcon}>
|
||||
<Ionicons
|
||||
name="calendar-outline"
|
||||
size={20}
|
||||
color={MainColor.placeholder}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<TextCustom color="gray">
|
||||
{selectedDate ? (
|
||||
<TextCustom color="black">
|
||||
{dayjs(selectedDate).format("DD-MM-YYYY HH:mm")}
|
||||
</TextCustom>
|
||||
) : (
|
||||
"Pilih tanggal"
|
||||
)}
|
||||
</TextCustom>
|
||||
</View>
|
||||
{externalError ||
|
||||
(internalError && (
|
||||
<Text style={GStyles.inputErrorMessage}>
|
||||
{externalError || internalError}
|
||||
</Text>
|
||||
))}
|
||||
</ClickableCustom>
|
||||
|
||||
{show && (
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
zIndex: 15,
|
||||
backgroundColor: "white",
|
||||
borderRadius: 8,
|
||||
padding: 10,
|
||||
// top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
borderColor: "#ccc",
|
||||
borderWidth: 1,
|
||||
}}
|
||||
>
|
||||
<View style={{ alignItems: "flex-end" }}>
|
||||
<Ionicons
|
||||
name="close"
|
||||
size={20}
|
||||
color="black"
|
||||
onPress={() => setShow(false)}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<DateTimePicker
|
||||
value={selectedDate || new Date()}
|
||||
mode={"datetime"}
|
||||
display="inline"
|
||||
onChange={handleConfirm}
|
||||
minimumDate={minimumDate}
|
||||
maximumDate={maximumDate}
|
||||
/>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateTimeInput_IOS;
|
||||
54
components/DateInput/DateTimePickerCustom.tsx
Normal file
54
components/DateInput/DateTimePickerCustom.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
import {
|
||||
DateTimePickerEvent,
|
||||
} from "@react-native-community/datetimepicker";
|
||||
import React from "react";
|
||||
import { Platform } from "react-native";
|
||||
import DateTimeInput_Android from "./DataTimeAndroid";
|
||||
import DateTimeInput_IOS from "./DateTimeIOS";
|
||||
|
||||
type Props = {
|
||||
value?: Date;
|
||||
onChange?: (date: Date) => void;
|
||||
label?: string;
|
||||
required?: boolean;
|
||||
maximumDate?: Date;
|
||||
minimumDate?: Date;
|
||||
};
|
||||
|
||||
const DateTimePickerCustom: React.FC<Props> = ({
|
||||
value,
|
||||
onChange,
|
||||
label,
|
||||
required,
|
||||
maximumDate,
|
||||
minimumDate,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{Platform.OS === "ios" ? (
|
||||
<DateTimeInput_IOS
|
||||
label={label}
|
||||
onChange={(date: DateTimePickerEvent) => {
|
||||
onChange?.(date as any);
|
||||
}}
|
||||
required={required}
|
||||
maximumDate={maximumDate}
|
||||
minimumDate={minimumDate}
|
||||
/>
|
||||
) : (
|
||||
<DateTimeInput_Android
|
||||
label={label}
|
||||
onChange={(date: DateTimePickerEvent) => {
|
||||
onChange?.(date as any);
|
||||
}}
|
||||
required={required}
|
||||
maximumDate={maximumDate}
|
||||
minimumDate={minimumDate}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateTimePickerCustom;
|
||||
70
components/DateInput/DateTimeTry.tsx
Normal file
70
components/DateInput/DateTimeTry.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React, { useState } from "react";
|
||||
import { Pressable, Text, StyleSheet } from "react-native";
|
||||
import DateTimePicker, { Event } from "@react-native-community/datetimepicker";
|
||||
|
||||
type Props = {
|
||||
value?: Date;
|
||||
mode?: "date" | "time" | "datetime";
|
||||
onChange: (date: Date) => void;
|
||||
};
|
||||
|
||||
const DateTimePickerTry: React.FC<Props> = ({
|
||||
value = new Date(),
|
||||
mode = "date",
|
||||
onChange,
|
||||
}) => {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const toggleDatePicker = () => {
|
||||
setShow(!show);
|
||||
};
|
||||
|
||||
const handleConfirm = (event: Event, selectedDate?: Date) => {
|
||||
if (event.type === "set" && selectedDate !== undefined) {
|
||||
onChange(selectedDate);
|
||||
}
|
||||
setShow(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Pressable onPress={toggleDatePicker} style={styles.button}>
|
||||
<Text style={styles.buttonText}>
|
||||
{value ? value.toLocaleDateString() : "Pilih tanggal"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
{show && (
|
||||
<DateTimePicker
|
||||
// style={styles.button}
|
||||
textColor="white"
|
||||
testID="dateTimePicker"
|
||||
value={value}
|
||||
mode={mode}
|
||||
is24Hour={true}
|
||||
display="default"
|
||||
onChange={handleConfirm as any}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 20,
|
||||
backgroundColor: "white",
|
||||
borderRadius: 8,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginVertical: 10,
|
||||
},
|
||||
buttonText: {
|
||||
color: "white",
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
});
|
||||
|
||||
export default DateTimePickerTry;
|
||||
132
components/Radio/RadioCustom.tsx
Normal file
132
components/Radio/RadioCustom.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
// components/Radio.tsx
|
||||
import { GStyles } from '@/styles/global-styles';
|
||||
import React, { createContext, useCallback, useContext } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextStyle,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
ViewStyle
|
||||
} from 'react-native';
|
||||
|
||||
// ========================
|
||||
// Types
|
||||
// ========================
|
||||
|
||||
type RadioContextType = {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
|
||||
const RadioContext = createContext<RadioContextType | undefined>(undefined);
|
||||
|
||||
interface RadioGroupProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
children: React.ReactNode;
|
||||
style?: ViewStyle;
|
||||
}
|
||||
|
||||
interface RadioProps {
|
||||
label: string;
|
||||
value: string | number;
|
||||
disabled?: boolean;
|
||||
style?: ViewStyle;
|
||||
labelStyle?: TextStyle;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Components
|
||||
// ========================
|
||||
|
||||
export const RadioGroup: React.FC<RadioGroupProps> = ({ value, onChange, children, style }) => {
|
||||
const contextValue = {
|
||||
value,
|
||||
onChange,
|
||||
};
|
||||
|
||||
return <RadioContext.Provider value={contextValue}>{children}</RadioContext.Provider>;
|
||||
};
|
||||
|
||||
export const RadioCustom: React.FC<RadioProps> = ({ label, value, disabled = false, style, labelStyle }) => {
|
||||
const context = useContext(RadioContext);
|
||||
if (!context) {
|
||||
throw new Error('Radio must be used inside a RadioGroup');
|
||||
}
|
||||
|
||||
const { value: selectedValue, onChange } = context;
|
||||
|
||||
const handlePress = useCallback(() => {
|
||||
if (!disabled && selectedValue !== value) {
|
||||
onChange(value as any);
|
||||
}
|
||||
}, [disabled, selectedValue, value, onChange]);
|
||||
|
||||
const isSelected = selectedValue === value;
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.radioContainer, style]}
|
||||
onPress={handlePress}
|
||||
disabled={disabled}
|
||||
>
|
||||
{/* Circle */}
|
||||
<View
|
||||
style={[styles.outerCircle, isSelected && styles.outerCircleChecked]}
|
||||
>
|
||||
<View
|
||||
style={[styles.innerCircle, isSelected && styles.innerCircleChecked]}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Label */}
|
||||
<Text
|
||||
style={[
|
||||
GStyles.textLabelBold,
|
||||
labelStyle,
|
||||
disabled && GStyles.inputTextDisabled,
|
||||
]}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
// ========================
|
||||
// Styles
|
||||
// ========================
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
radioContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginVertical: 8,
|
||||
},
|
||||
outerCircle: {
|
||||
height: 24,
|
||||
width: 24,
|
||||
borderRadius: 12,
|
||||
borderWidth: 2,
|
||||
borderColor: '#3B82F6',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 10,
|
||||
},
|
||||
outerCircleChecked: {
|
||||
backgroundColor: '#3B82F6',
|
||||
},
|
||||
innerCircle: {
|
||||
height: 12,
|
||||
width: 12,
|
||||
borderRadius: 6,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
innerCircleChecked: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: 'white',
|
||||
borderRadius: 6,
|
||||
},
|
||||
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import ButtonCustom from "../Button/ButtonCustom";
|
||||
interface ButtonData {
|
||||
id: string | number;
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface ScrollableCustomProps {
|
||||
@@ -27,7 +28,7 @@ const ScrollableCustom = ({
|
||||
style={styles.scrollView}
|
||||
>
|
||||
{data.map((item) => {
|
||||
const isActive = activeId === item.id;
|
||||
const isActive = activeId === item.value;
|
||||
|
||||
return (
|
||||
<ButtonCustom
|
||||
@@ -48,6 +49,9 @@ export default ScrollableCustom;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scrollView: {
|
||||
backgroundColor: MainColor.soft_darkblue,
|
||||
borderRadius: 50,
|
||||
padding: 5,
|
||||
// maxHeight: 50,
|
||||
},
|
||||
buttonContainer: {
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
TEXT_SIZE_LARGE,
|
||||
TEXT_SIZE_MEDIUM,
|
||||
TEXT_SIZE_SMALL,
|
||||
TEXT_SIZE_XLARGE,
|
||||
} from "@/constants/constans-value";
|
||||
import React from "react";
|
||||
import {
|
||||
@@ -21,8 +22,8 @@ interface TextCustomProps {
|
||||
style?: StyleProp<TextStyle>;
|
||||
bold?: boolean;
|
||||
semiBold?: boolean;
|
||||
size?: "default" | "large" | "small";
|
||||
color?: "default" | "yellow" | "red" | "gray" | "green";
|
||||
size?: "default" | "large" | "small" | "xlarge";
|
||||
color?: "default" | "yellow" | "red" | "gray" | "green" | "black"
|
||||
align?: TextAlign; // Prop untuk alignment
|
||||
truncate?: boolean | number;
|
||||
onPress?: () => void;
|
||||
@@ -51,6 +52,7 @@ const TextCustom: React.FC<TextCustomProps> = ({
|
||||
|
||||
// Size
|
||||
if (size === "large") selectedStyles.push(styles.large);
|
||||
else if (size === "xlarge") selectedStyles.push(styles.xlarge);
|
||||
else if (size === "small") selectedStyles.push(styles.small);
|
||||
|
||||
// Color
|
||||
@@ -58,6 +60,7 @@ const TextCustom: React.FC<TextCustomProps> = ({
|
||||
else if (color === "red") selectedStyles.push(styles.red);
|
||||
else if (color === "gray") selectedStyles.push(styles.gray);
|
||||
else if (color === "green") selectedStyles.push(styles.green);
|
||||
else if (color === "black") selectedStyles.push(styles.black);
|
||||
|
||||
// Alignment
|
||||
if (align) {
|
||||
@@ -112,11 +115,14 @@ export const styles = StyleSheet.create({
|
||||
fontFamily: "Poppins-SemiBold",
|
||||
fontWeight: "500",
|
||||
},
|
||||
small: {
|
||||
fontSize: TEXT_SIZE_SMALL,
|
||||
},
|
||||
large: {
|
||||
fontSize: TEXT_SIZE_LARGE,
|
||||
},
|
||||
small: {
|
||||
fontSize: TEXT_SIZE_SMALL,
|
||||
xlarge: {
|
||||
fontSize: TEXT_SIZE_XLARGE,
|
||||
},
|
||||
yellow: {
|
||||
color: MainColor.yellow,
|
||||
@@ -130,4 +136,7 @@ export const styles = StyleSheet.create({
|
||||
green: {
|
||||
color: MainColor.green,
|
||||
},
|
||||
black: {
|
||||
color: MainColor.black,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
TextInput as RNTextInput,
|
||||
StyleProp,
|
||||
Text,
|
||||
View,
|
||||
ViewStyle,
|
||||
TextInput as RNTextInput,
|
||||
StyleProp,
|
||||
Text,
|
||||
View,
|
||||
ViewStyle,
|
||||
} from "react-native";
|
||||
|
||||
type IconType = React.ReactNode | string;
|
||||
@@ -79,7 +79,7 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={GStyles.inputContainerArea}>
|
||||
<View style={[GStyles.inputContainerArea]}>
|
||||
{label && (
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
@@ -105,7 +105,7 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
|
||||
multiline
|
||||
numberOfLines={numberOfLines}
|
||||
style={[
|
||||
GStyles.inputText,
|
||||
// GStyles.inputText,
|
||||
GStyles.textAreaInput,
|
||||
{ color: fontColor },
|
||||
]}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ImageSourcePropType, View } from "react-native";
|
||||
import Grid from "../Grid/GridCustom";
|
||||
import AvatarCustom from "../Image/AvatarCustom";
|
||||
import TextCustom from "../Text/TextCustom";
|
||||
|
||||
const AvatarUsernameAndOtherComponent = ({
|
||||
avatarHref,
|
||||
avatar,
|
||||
name,
|
||||
rightComponent,
|
||||
}: {
|
||||
avatarHref?: string;
|
||||
avatar?: ImageSourcePropType;
|
||||
name?: string;
|
||||
rightComponent?: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<View>
|
||||
<Grid containerStyle={{ zIndex: 10 }}>
|
||||
<Grid.Col span={2}>
|
||||
<AvatarCustom source={avatar} href={avatarHref as any} />
|
||||
</Grid.Col>
|
||||
<Grid.Col
|
||||
span={rightComponent ? 6 : 10}
|
||||
style={{ justifyContent: "center" }}
|
||||
>
|
||||
<TextCustom truncate bold>
|
||||
{name || "Username"}
|
||||
</TextCustom>
|
||||
</Grid.Col>
|
||||
{rightComponent && (
|
||||
<Grid.Col
|
||||
span={4}
|
||||
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
||||
>
|
||||
{rightComponent}
|
||||
</Grid.Col>
|
||||
)}
|
||||
</Grid>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AvatarUsernameAndOtherComponent;
|
||||
@@ -3,12 +3,12 @@ import React from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
interface SpacingProps {
|
||||
width?: number;
|
||||
height?: number;
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
}
|
||||
|
||||
const Spacing: React.FC<SpacingProps> = ({ width = 20, height = 20 }) => {
|
||||
return <View style={{ height, width }} />;
|
||||
return <View style={{ height: height as any, width: width as any }} />;
|
||||
};
|
||||
|
||||
export default Spacing;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { OS_HEIGHT } from "@/constants/constans-value";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import {
|
||||
ImageBackground,
|
||||
@@ -19,15 +20,23 @@ interface ViewWrapperProps {
|
||||
headerComponent?: React.ReactNode;
|
||||
footerComponent?: React.ReactNode;
|
||||
floatingButton?: React.ReactNode;
|
||||
hideFooter?: boolean;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param hideFooter
|
||||
* @returns meneyembunyikan footer ketika menggunakan tabs (misal: bottom tab)
|
||||
*/
|
||||
|
||||
const ViewWrapper = ({
|
||||
children,
|
||||
withBackground = false,
|
||||
headerComponent,
|
||||
footerComponent,
|
||||
floatingButton,
|
||||
hideFooter = false,
|
||||
style,
|
||||
}: ViewWrapperProps) => {
|
||||
const assetBackground = require("../../assets/images/main-background.png");
|
||||
@@ -71,15 +80,18 @@ const ViewWrapper = ({
|
||||
edges={["bottom"]}
|
||||
style={{
|
||||
backgroundColor: MainColor.darkblue,
|
||||
height: OS_HEIGHT
|
||||
}}
|
||||
>
|
||||
{footerComponent}
|
||||
</SafeAreaView>
|
||||
) : (
|
||||
<SafeAreaView
|
||||
edges={["bottom"]}
|
||||
style={{ backgroundColor: MainColor.darkblue }}
|
||||
/>
|
||||
hideFooter ? null : (
|
||||
<SafeAreaView
|
||||
edges={["bottom"]}
|
||||
style={{ backgroundColor: MainColor.darkblue }}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
||||
{/* Floating Component (misal: FAB) */}
|
||||
|
||||
@@ -4,12 +4,10 @@ import AlertCustom from "./Alert/AlertCustom";
|
||||
import LeftButtonCustom from "./Button/BackButton";
|
||||
import ButtonCenteredOnly from "./Button/ButtonCenteredOnly";
|
||||
import ButtonCustom from "./Button/ButtonCustom";
|
||||
import DotButton from "./Button/DotButton";
|
||||
// Drawer
|
||||
import DrawerCustom from "./Drawer/DrawerCustom";
|
||||
import MenuDrawerDynamicGrid from "./Drawer/MenuDrawerDynamicGird";
|
||||
// ShareComponent
|
||||
import Spacing from "./_ShareComponent/Spacing";
|
||||
import ViewWrapper from "./_ShareComponent/ViewWrapper";
|
||||
// Text
|
||||
import TextCustom from "./Text/TextCustom";
|
||||
// TextInput
|
||||
@@ -21,6 +19,7 @@ import Grid from "./Grid/GridCustom";
|
||||
// Box
|
||||
import BaseBox from "./Box/BaseBox";
|
||||
import BoxButtonOnFooter from "./Box/BoxButtonOnFooter";
|
||||
import BoxWithHeaderSection from "./Box/BoxWithHeaderInformation";
|
||||
import InformationBox from "./Box/InformationBox";
|
||||
// Stack
|
||||
import StackCustom from "./Stack/StackCustom";
|
||||
@@ -39,27 +38,36 @@ import CenterCustom from "./Center/CenterCustom";
|
||||
import ClickableCustom from "./Clickable/ClickableCustom";
|
||||
// Scroll
|
||||
import ScrollableCustom from "./Scroll/ScrollCustom";
|
||||
|
||||
// ShareComponent
|
||||
import AvatarUsernameAndOtherComponent from "./_ShareComponent/AvataraAndOtherHeaderComponent";
|
||||
import Spacing from "./_ShareComponent/Spacing";
|
||||
import ViewWrapper from "./_ShareComponent/ViewWrapper";
|
||||
export {
|
||||
AlertCustom,
|
||||
// Image
|
||||
AvatarCustom,
|
||||
LandscapeFrameUploaded,
|
||||
// ShareComponent
|
||||
AvatarUsernameAndOtherComponent, LeftButtonCustom as BackButton,
|
||||
// Box
|
||||
BaseBox,
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
InformationBox,
|
||||
LeftButtonCustom as BackButton,
|
||||
BoxButtonOnFooter, BoxWithHeaderSection,
|
||||
// Button
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
// Center
|
||||
CenterCustom,
|
||||
// Clickable
|
||||
ClickableCustom,
|
||||
// Divider
|
||||
DividerCustom, DotButton,
|
||||
// Drawer
|
||||
DrawerCustom,
|
||||
MenuDrawerDynamicGrid,
|
||||
// Grid
|
||||
Grid,
|
||||
Grid, InformationBox, LandscapeFrameUploaded,
|
||||
// Map
|
||||
MapCustom,
|
||||
MapCustom, MenuDrawerDynamicGrid,
|
||||
// Scroll
|
||||
ScrollableCustom,
|
||||
// Select
|
||||
SelectCustom,
|
||||
// ShareComponent
|
||||
@@ -73,13 +81,6 @@ export {
|
||||
// TextInput
|
||||
TextInputCustom,
|
||||
// ViewWrapper
|
||||
ViewWrapper,
|
||||
// Divider
|
||||
DividerCustom,
|
||||
// Center
|
||||
CenterCustom,
|
||||
// Clickable
|
||||
ClickableCustom,
|
||||
// Scroll
|
||||
ScrollableCustom,
|
||||
ViewWrapper
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { Platform } from "react-native";
|
||||
|
||||
export {
|
||||
OS_ANDROID_HEIGHT,
|
||||
OS_IOS_HEIGHT,
|
||||
OS_HEIGHT,
|
||||
TEXT_SIZE_SMALL,
|
||||
TEXT_SIZE_MEDIUM,
|
||||
TEXT_SIZE_LARGE,
|
||||
TEXT_SIZE_XLARGE,
|
||||
ICON_SIZE_SMALL,
|
||||
ICON_SIZE_MEDIUM,
|
||||
DRAWER_HEIGHT,
|
||||
@@ -13,10 +19,16 @@ export {
|
||||
PADDING_LARGE,
|
||||
};
|
||||
|
||||
// OS Height
|
||||
const OS_ANDROID_HEIGHT = 115
|
||||
const OS_IOS_HEIGHT = 65
|
||||
const OS_HEIGHT = Platform.OS === "ios" ? OS_IOS_HEIGHT : OS_ANDROID_HEIGHT
|
||||
|
||||
// Text Size
|
||||
const TEXT_SIZE_SMALL = 12;
|
||||
const TEXT_SIZE_MEDIUM = 14;
|
||||
const TEXT_SIZE_LARGE = 16;
|
||||
const TEXT_SIZE_XLARGE = 18;
|
||||
|
||||
// Icon Size
|
||||
const ICON_SIZE_BUTTON = 18
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const DUMMY_IMAGE = {
|
||||
avatar: require("@/assets/images/dummy/dummy-avatar.png"),
|
||||
avatar: require("@/assets/images/dummy/dummy-user.png"),
|
||||
background: require("@/assets/images/dummy/dummy-image-background.jpg"),
|
||||
};
|
||||
|
||||
|
||||
6
lib/dummy-data/_master/status.tsx
Normal file
6
lib/dummy-data/_master/status.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
export const masterStatus = [
|
||||
{ value: "publish", label: "Publish" },
|
||||
{ value: "review", label: "Review" },
|
||||
{ value: "draft", label: "Draft" },
|
||||
{ value: "reject", label: "Reject" },
|
||||
];
|
||||
8
lib/dummy-data/event/master-type-event.tsx
Normal file
8
lib/dummy-data/event/master-type-event.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export const masterTypeEvent = [
|
||||
{ label: "Seminar", value: "seminar" },
|
||||
{ label: "Workshop", value: "workshop" },
|
||||
{ label: "Lomba", value: "lomba" },
|
||||
{ label: "Pameran", value: "pameran" },
|
||||
{ label: "Kegiatan Sosial", value: "kegiatan_sosial" },
|
||||
{ label: "Musyawarah", value: "musyawarah" },
|
||||
];
|
||||
26
lib/dummy-data/forum/report-list.tsx
Normal file
26
lib/dummy-data/forum/report-list.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
export const listDummyReportForum = [
|
||||
{
|
||||
title: "Kebencian",
|
||||
desc: "Cercaan, Stereotip rasis atau seksis, Dehumanisasi, Menyulut ketakutan atau diskriminasi, Referensi kebencian, Simbol & logo kebencian",
|
||||
},
|
||||
{
|
||||
title: "Penghinaan & Pelecehan secara Online",
|
||||
desc: "Penghinaan, Konten Seksual yang Tidak Diinginkan, Penyangkalan Peristiwa Kekerasan, Pelecehan Bertarget dan Memprovokasi Pelecehan",
|
||||
},
|
||||
{
|
||||
title: "Tutur Kekerasan",
|
||||
desc: "Ancaman Kekerasan, Berharap Terjadinya Celaka, Mengagungkan Kekerasan, Penghasutan Kekerasan, Penghasutan Kekerasan dengan Kode",
|
||||
},
|
||||
{
|
||||
title: "Keselamatan Anak",
|
||||
desc: "Eksploitasi seks anak di bawah umur, grooming, kekerasan fisik terhadap anak, pengguna di bawah umur",
|
||||
},
|
||||
{
|
||||
title: "Privasi",
|
||||
desc: "Membagikan informasi pribadi, mengancam akan membagikan/menyebarkan informasi pribadi, membagikan gambar intim tanpa persetujuan, membagikan gambar saya yang tidak saya kehendaki di platform ini",
|
||||
},
|
||||
{
|
||||
title: "Spam",
|
||||
desc: "Akun palsu, penipuan keuangan, memposting tautan berbahaya, menyalahgunakan hashtag, keterlibatan palsu, balasan berulang, Posting Ulang, atau Direct Message",
|
||||
},
|
||||
];
|
||||
@@ -12,6 +12,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^14.1.0",
|
||||
"@react-native-community/datetimepicker": "8.4.1",
|
||||
"@react-navigation/bottom-tabs": "^7.4.2",
|
||||
"@react-navigation/drawer": "^7.5.2",
|
||||
"@react-navigation/elements": "^2.3.8",
|
||||
|
||||
@@ -30,12 +30,13 @@ 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)/(user)/home");
|
||||
// router.navigate(`/(application)/profile/${id}/edit`);
|
||||
// router.navigate(`/(application)/(user)/portofolio/${id}`)
|
||||
// router.navigate(`/(application)/(image)/preview-image/${id}`);
|
||||
// router.replace("/(application)/(user)/event/(tabs)");
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Spacing from "@/components/_ShareComponent/Spacing";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import ButtonCustom from "@/components/Button/ButtonCustom";
|
||||
import { TextInputCustom } from "@/components/TextInput/TextInputCustom";
|
||||
import TextInputCustom from "@/components/TextInput/TextInputCustom";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||
|
||||
115
screens/Event/AlertButtonStatusSection.tsx
Normal file
115
screens/Event/AlertButtonStatusSection.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import AlertCustom from "@/components/Alert/AlertCustom";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function Event_AlertButtonStatusSection({
|
||||
id,
|
||||
status,
|
||||
openAlert,
|
||||
setOpenAlert,
|
||||
openDeleteAlert,
|
||||
setOpenDeleteAlert,
|
||||
}: {
|
||||
id: string;
|
||||
status: string;
|
||||
openAlert: boolean;
|
||||
setOpenAlert: (value: boolean) => void;
|
||||
openDeleteAlert: boolean;
|
||||
setOpenDeleteAlert: (value: boolean) => void;
|
||||
}) {
|
||||
// --- Alert untuk aksi berdasarkan status ---
|
||||
const renderStatusAlert = () => {
|
||||
switch (status) {
|
||||
case "publish":
|
||||
return <></>;
|
||||
|
||||
case "review":
|
||||
return (
|
||||
<AlertCustom
|
||||
isVisible={openAlert}
|
||||
title="Batalkan Review"
|
||||
message="Apakah Anda yakin ingin membatalkan review?"
|
||||
textLeft="Batal"
|
||||
textRight="Ya"
|
||||
colorRight="green"
|
||||
onLeftPress={() => {
|
||||
setOpenAlert(false);
|
||||
}}
|
||||
onRightPress={() => {
|
||||
setOpenAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
case "draft":
|
||||
return (
|
||||
<AlertCustom
|
||||
isVisible={openAlert}
|
||||
title="Ajukan Review ?"
|
||||
message="Apakah Anda yakin ingin mengajukan review kembali?"
|
||||
textLeft="Batal"
|
||||
textRight="Ya"
|
||||
colorRight="green"
|
||||
onLeftPress={() => {
|
||||
setOpenAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
onRightPress={() => {
|
||||
setOpenAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
case "reject":
|
||||
return (
|
||||
<AlertCustom
|
||||
isVisible={openAlert}
|
||||
title="Edit Kembali"
|
||||
message="Apakah Anda yakin ingin mengedit kembali event ini?"
|
||||
textLeft="Batal"
|
||||
textRight="Ya"
|
||||
colorRight="green"
|
||||
onLeftPress={() => {
|
||||
setOpenAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
onRightPress={() => {
|
||||
setOpenAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Alert berdasarkan status */}
|
||||
{renderStatusAlert()}
|
||||
|
||||
{/* Alert untuk hapus - selalu muncul jika openDeleteAlert true */}
|
||||
<AlertCustom
|
||||
isVisible={openDeleteAlert}
|
||||
title="Hapus Event"
|
||||
message="Apakah Anda yakin ingin menghapus event ini?"
|
||||
textLeft="Batal"
|
||||
textRight="Ya, Hapus"
|
||||
colorRight="red"
|
||||
onLeftPress={() => {
|
||||
setOpenDeleteAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
onRightPress={() => {
|
||||
// Aksi hapus event
|
||||
console.log("Menghapus event dengan ID:", id);
|
||||
setOpenDeleteAlert(false);
|
||||
router.back();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
61
screens/Event/BoxDetailPublishSection.tsx
Normal file
61
screens/Event/BoxDetailPublishSection.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
BaseBox,
|
||||
Grid,
|
||||
StackCustom,
|
||||
TextCustom
|
||||
} from "@/components";
|
||||
|
||||
export default function Event_BoxDetailPublishSection({
|
||||
footerButton,
|
||||
}: {
|
||||
footerButton?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<BaseBox>
|
||||
<StackCustom>
|
||||
<TextCustom bold align="center" size="xlarge">
|
||||
Judul event publish
|
||||
</TextCustom>
|
||||
{listData.map((item, index) => (
|
||||
<Grid key={index}>
|
||||
<Grid.Col span={4}>
|
||||
<TextCustom bold>{item.title}</TextCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<TextCustom>{item.value}</TextCustom>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
))}
|
||||
</StackCustom>
|
||||
</BaseBox>
|
||||
|
||||
{footerButton}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const listData = [
|
||||
{
|
||||
title: "Lokasi",
|
||||
value:
|
||||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora, atque. Aperiam minima asperiores dicta perferendis quis adipisci, dolore optio porro!",
|
||||
},
|
||||
{
|
||||
title: "Tipe Acara",
|
||||
value: "Workshop",
|
||||
},
|
||||
{
|
||||
title: "Tanggal Mulai",
|
||||
value: "Senin, 18 Juli 2025, 10:00 WIB",
|
||||
},
|
||||
{
|
||||
title: "Tanggal Berakhir",
|
||||
value: "Selasa, 19 Juli 2025, 12:00 WIB",
|
||||
},
|
||||
{
|
||||
title: "Deskripsi",
|
||||
value:
|
||||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur eveniet ab eum ducimus tempore a quia deserunt quisquam. Tempora, atque. Aperiam minima asperiores dicta perferendis quis adipisci, dolore optio porro!",
|
||||
},
|
||||
];
|
||||
51
screens/Event/BoxPublishSection.tsx
Normal file
51
screens/Event/BoxPublishSection.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import {
|
||||
AvatarUsernameAndOtherComponent,
|
||||
BoxWithHeaderSection,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
} from "@/components";
|
||||
import { Href } from "expo-router";
|
||||
|
||||
export default function Event_BoxPublishSection({
|
||||
id,
|
||||
title,
|
||||
username,
|
||||
description,
|
||||
href,
|
||||
|
||||
// Avatar
|
||||
sourceAvatar,
|
||||
rightComponentAvatar,
|
||||
}: {
|
||||
id: string;
|
||||
title?: string;
|
||||
username?: string;
|
||||
description?: string;
|
||||
href: Href;
|
||||
|
||||
// Avatar
|
||||
sourceAvatar?: string;
|
||||
rightComponentAvatar?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<BoxWithHeaderSection href={href}>
|
||||
<StackCustom gap={"xs"}>
|
||||
<AvatarUsernameAndOtherComponent
|
||||
avatarHref={`/profile/${id}`}
|
||||
name={username || "Lorem ipsum dolor sit"}
|
||||
rightComponent={rightComponentAvatar}
|
||||
avatar={sourceAvatar as any}
|
||||
/>
|
||||
<TextCustom truncate bold>
|
||||
{title || "Lorem ipsum dolor sit"}
|
||||
</TextCustom>
|
||||
<TextCustom truncate={2}>
|
||||
{description ||
|
||||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro sed doloremque tempora soluta. Dolorem ex quidem ipsum tempora, ipsa, obcaecati quia suscipit numquam, voluptates commodi porro impedit natus quos doloremque!"}
|
||||
</TextCustom>
|
||||
</StackCustom>
|
||||
</BoxWithHeaderSection>
|
||||
</>
|
||||
);
|
||||
}
|
||||
76
screens/Event/ButtonStatusSection.tsx
Normal file
76
screens/Event/ButtonStatusSection.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { ButtonCustom, Grid } from "@/components";
|
||||
import { View } from "react-native";
|
||||
|
||||
export default function Event_ButtonStatusSection({
|
||||
status,
|
||||
onOpenAlert,
|
||||
onOpenDeleteAlert,
|
||||
}: {
|
||||
status: string;
|
||||
onOpenAlert: (value: boolean) => void;
|
||||
onOpenDeleteAlert: (value: boolean) => void;
|
||||
}) {
|
||||
|
||||
const handleOpenAlert = () => {
|
||||
onOpenAlert(true);
|
||||
};
|
||||
|
||||
const handleOpenDeleteAlert = () => {
|
||||
onOpenDeleteAlert(true);
|
||||
};
|
||||
|
||||
const DeleteButton = () => {
|
||||
return (
|
||||
<>
|
||||
<ButtonCustom backgroundColor="red" textColor="white" onPress={handleOpenDeleteAlert}>
|
||||
Hapus
|
||||
</ButtonCustom>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
switch (status) {
|
||||
case "publish":
|
||||
return <></>;
|
||||
|
||||
case "review":
|
||||
return (
|
||||
<ButtonCustom onPress={handleOpenAlert}>
|
||||
Batalkan Review
|
||||
</ButtonCustom>
|
||||
);
|
||||
|
||||
case "draft":
|
||||
return (
|
||||
<>
|
||||
<Grid>
|
||||
<Grid.Col span={5}>
|
||||
<ButtonCustom onPress={handleOpenAlert}>Ajukan Review</ButtonCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={2}>
|
||||
<View />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={5}>{DeleteButton()}</Grid.Col>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
|
||||
case "reject":
|
||||
return (
|
||||
<>
|
||||
<Grid>
|
||||
<Grid.Col span={5}>
|
||||
<ButtonCustom onPress={handleOpenAlert}>Edit Kembali</ButtonCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={2}>
|
||||
<View />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={5}>{DeleteButton()}</Grid.Col>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
|
||||
default:
|
||||
return <ButtonCustom disabled>Status Undifined</ButtonCustom>;
|
||||
}
|
||||
}
|
||||
17
screens/Event/menuDrawerDraft.tsx
Normal file
17
screens/Event/menuDrawerDraft.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { AccentColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
export const menuDrawerDraftEvent = ({ id }: { id: string }) => [
|
||||
{
|
||||
icon: (
|
||||
<Ionicons
|
||||
name="create"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Edit event",
|
||||
path: `/(application)/(user)/event/${id}/edit`,
|
||||
},
|
||||
];
|
||||
17
screens/Event/menuDrawerPublish.tsx
Normal file
17
screens/Event/menuDrawerPublish.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { AccentColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import { FontAwesome } from "@expo/vector-icons";
|
||||
|
||||
export const menuDrawerPublishEvent = ({ id }: { id: string }) => [
|
||||
{
|
||||
icon: (
|
||||
<FontAwesome
|
||||
name="users"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Daftar peserta",
|
||||
path: `/(application)/(user)/event/${id}/list-of-participants`,
|
||||
},
|
||||
];
|
||||
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
BaseBox,
|
||||
Grid,
|
||||
AvatarCustom,
|
||||
TextCustom,
|
||||
BaseBox,
|
||||
ClickableCustom,
|
||||
Grid,
|
||||
Spacing,
|
||||
TextCustom,
|
||||
} from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||
@@ -14,11 +14,9 @@ import { View } from "react-native";
|
||||
export default function Forum_CommentarBoxSection({
|
||||
data,
|
||||
setOpenDrawer,
|
||||
setStatus,
|
||||
}: {
|
||||
data: any;
|
||||
setOpenDrawer: (value: boolean) => void;
|
||||
setStatus: (value: string) => void;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
@@ -46,7 +44,6 @@ export default function Forum_CommentarBoxSection({
|
||||
<ClickableCustom
|
||||
onPress={() => {
|
||||
setOpenDrawer(true);
|
||||
setStatus(data.status);
|
||||
}}
|
||||
style={{
|
||||
alignItems: "flex-end",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { MainColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||
import { Feather, Ionicons } from "@expo/vector-icons";
|
||||
|
||||
export { drawerItemsForumBeranda };
|
||||
export { drawerItemsForumBeranda, drawerItemsForumComentar };
|
||||
|
||||
const drawerItemsForumBeranda = ({
|
||||
id,
|
||||
@@ -11,6 +11,15 @@ const drawerItemsForumBeranda = ({
|
||||
id: string;
|
||||
status: string;
|
||||
}) => [
|
||||
{
|
||||
icon: (
|
||||
<Ionicons name="flag" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
),
|
||||
label: "Laporkan diskusi",
|
||||
// color: MainColor.white,
|
||||
path: `/forum/${id}/report-posting`,
|
||||
},
|
||||
|
||||
{
|
||||
icon: (
|
||||
<Feather name="edit" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
@@ -21,14 +30,14 @@ const drawerItemsForumBeranda = ({
|
||||
{
|
||||
icon:
|
||||
status === "Open" ? (
|
||||
<Ionicons name="open" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
) : (
|
||||
<Ionicons name="close" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
) : (
|
||||
<Ionicons name="open" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
),
|
||||
|
||||
label: status === "Open" ? "Buka forum" : "Tutup forum",
|
||||
label: status === "Open" ? "Tutup forum" : "Buka forum",
|
||||
path: "",
|
||||
color: status === "Open" ? MainColor.green : MainColor.orange,
|
||||
color: status === "Open" ? MainColor.orange : MainColor.green,
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
@@ -39,3 +48,22 @@ const drawerItemsForumBeranda = ({
|
||||
color: MainColor.red,
|
||||
},
|
||||
];
|
||||
|
||||
const drawerItemsForumComentar = ({ id }: { id: string }) => [
|
||||
{
|
||||
icon: (
|
||||
<Ionicons name="flag" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
),
|
||||
label: "Laporkan",
|
||||
// color: MainColor.white,
|
||||
path: `/forum/${id}/report-commentar`,
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<Ionicons name="trash" size={ICON_SIZE_SMALL} color={MainColor.white} />
|
||||
),
|
||||
label: "Hapus",
|
||||
color: MainColor.red,
|
||||
path: "",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { MenuDrawerDynamicGrid } from "@/components";
|
||||
import { drawerItemsForumComentar } from "../ListPage";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function Forum_MenuDrawerCommentar({
|
||||
id,
|
||||
setShowDeleteAlert,
|
||||
setIsDrawerOpen,
|
||||
}: {
|
||||
id: string;
|
||||
setShowDeleteAlert: (value: boolean) => void;
|
||||
setIsDrawerOpen: (value: boolean) => void;
|
||||
}) {
|
||||
const handlePress = (item: any) => {
|
||||
if (item.label === "Hapus") {
|
||||
setShowDeleteAlert(true);
|
||||
} else {
|
||||
router.push(item.path as any);
|
||||
}
|
||||
|
||||
setIsDrawerOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={drawerItemsForumComentar({ id })}
|
||||
columns={4}
|
||||
onPressItem={handlePress}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
41
screens/Forum/ReportListSection.tsx
Normal file
41
screens/Forum/ReportListSection.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { BaseBox, ButtonCustom, StackCustom, TextCustom } from "@/components";
|
||||
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { listDummyReportForum } from "@/lib/dummy-data/forum/report-list";
|
||||
import { router } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
export default function Forum_ReportListSection() {
|
||||
const [value, setValue] = useState<any | number>("");
|
||||
return (
|
||||
<>
|
||||
<BaseBox>
|
||||
<StackCustom>
|
||||
<RadioGroup value={value} onChange={setValue}>
|
||||
{listDummyReportForum.map((e, i) => (
|
||||
<View key={i}>
|
||||
<RadioCustom
|
||||
label={e.title}
|
||||
// value={i}
|
||||
value={e.title}
|
||||
/>
|
||||
<TextCustom>{e.desc}</TextCustom>
|
||||
</View>
|
||||
))}
|
||||
</RadioGroup>
|
||||
|
||||
{/* <ButtonCustom
|
||||
backgroundColor={MainColor.red}
|
||||
textColor={MainColor.white}
|
||||
onPress={() => {
|
||||
console.log("Report", value);
|
||||
}}
|
||||
>
|
||||
Report
|
||||
</ButtonCustom> */}
|
||||
</StackCustom>
|
||||
</BaseBox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -2,9 +2,13 @@ import { ButtonCustom } from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
export default function Portofolio_ButtonDelete() {
|
||||
export default function Portofolio_ButtonDelete({
|
||||
setShowDeleteAlert,
|
||||
}: {
|
||||
setShowDeleteAlert: (value: boolean) => void;
|
||||
}) {
|
||||
const handleDelete = () => {
|
||||
console.log("Delete");
|
||||
setShowDeleteAlert(true);
|
||||
};
|
||||
return (
|
||||
<ButtonCustom textColor={MainColor.white} iconLeft={<Ionicons name="trash-outline" size={20} color="white" />} onPress={handleDelete} backgroundColor={MainColor.red}>
|
||||
|
||||
@@ -4,13 +4,17 @@ import Portofolio_Data from "./DataPortofolio";
|
||||
import Portofolio_SocialMediaSection from "./SocialMediaSection";
|
||||
import Portofolio_ButtonDelete from "./ButtonDelete";
|
||||
|
||||
export default function PorfofolioSection() {
|
||||
export default function PorfofolioSection({
|
||||
setShowDeleteAlert,
|
||||
}: {
|
||||
setShowDeleteAlert: (value: boolean) => void;
|
||||
}) {
|
||||
return (
|
||||
<StackCustom>
|
||||
<Portofolio_Data />
|
||||
<Portofolio_BusinessLocation />
|
||||
<Portofolio_SocialMediaSection />
|
||||
<Portofolio_ButtonDelete/>
|
||||
<Portofolio_ButtonDelete setShowDeleteAlert={setShowDeleteAlert}/>
|
||||
<Spacing/>
|
||||
</StackCustom>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { router, useLocalSearchParams } from "expo-router";
|
||||
import { View } from "react-native";
|
||||
import AvatarAndBackground from "./AvatarAndBackground";
|
||||
|
||||
export default function ProfilSection() {
|
||||
export default function ProfileSection() {
|
||||
const { id } = useLocalSearchParams();
|
||||
|
||||
const listData = [
|
||||
@@ -44,17 +44,16 @@ export const GStyles = StyleSheet.create({
|
||||
},
|
||||
floatingContainer: {
|
||||
position: "absolute",
|
||||
bottom: 80,
|
||||
bottom: 100,
|
||||
right: 20,
|
||||
zIndex: 8,
|
||||
},
|
||||
|
||||
// Style saat disabled
|
||||
// =============== Disabled Styles =============== //
|
||||
disabledBox: {
|
||||
backgroundColor: MainColor.disabled,
|
||||
borderColor: AccentColor.disabledBorder,
|
||||
},
|
||||
|
||||
inputDisabled: {
|
||||
backgroundColor: "#f0f0f0",
|
||||
borderColor: "#ddd",
|
||||
@@ -65,7 +64,7 @@ export const GStyles = StyleSheet.create({
|
||||
inputPlaceholderDisabled: {
|
||||
color: "#444",
|
||||
},
|
||||
// =============== Main Styles =============== //
|
||||
// =============== Disabled Styles =============== //
|
||||
|
||||
// =============== AUTHENTICATION =============== //
|
||||
authContainer: {
|
||||
@@ -94,6 +93,11 @@ export const GStyles = StyleSheet.create({
|
||||
color: MainColor.white_gray,
|
||||
fontWeight: "normal",
|
||||
},
|
||||
textLabelBold: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
color: MainColor.white_gray,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
// =============== TEXT & LABEL =============== //
|
||||
|
||||
// =============== STACK HEADER =============== //
|
||||
@@ -284,8 +288,10 @@ export const GStyles = StyleSheet.create({
|
||||
// TextArea untuk tambahan
|
||||
textAreaInput: {
|
||||
textAlignVertical: "top",
|
||||
padding: 5,
|
||||
height: undefined, // biar multiline bebas tinggi
|
||||
paddingTop: 10,
|
||||
// height: undefined, // biar multiline bebas tinggi
|
||||
height: 100,
|
||||
width: "100%",
|
||||
},
|
||||
|
||||
// Select
|
||||
|
||||
Reference in New Issue
Block a user