Fix:
- UI: status, detail status, delete button, detail utama, tampilan utama
- Semua terintergrasi ke API mobile

### No Issue
This commit is contained in:
2025-09-12 14:14:37 +08:00
parent b6d4c0e6a6
commit 005b798688
9 changed files with 180 additions and 81 deletions

View File

@@ -1,9 +1,36 @@
import { LoaderCustom, TextCustom } from "@/components";
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper"; import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
import FloatingButton from "@/components/Button/FloatingButton"; import FloatingButton from "@/components/Button/FloatingButton";
import Event_BoxPublishSection from "@/screens/Event/BoxPublishSection"; import Event_BoxPublishSection from "@/screens/Event/BoxPublishSection";
import { router } from "expo-router"; import { apiEventGetAll } from "@/service/api-client/api-event";
import { dateTimeView } from "@/utils/dateTimeView";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
export default function EventBeranda() { export default function EventBeranda() {
const [listData, setListData] = useState([]);
const [isLoadData, setIsLoadData] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [])
);
const onLoadData = async () => {
try {
setIsLoadData(true);
const response = await apiEventGetAll();
// console.log("Response", JSON.stringify(response.data, null, 2));
setListData(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setIsLoadData(false);
}
};
return ( return (
<ViewWrapper <ViewWrapper
hideFooter hideFooter
@@ -11,13 +38,24 @@ export default function EventBeranda() {
<FloatingButton onPress={() => router.push("/event/create")} /> <FloatingButton onPress={() => router.push("/event/create")} />
} }
> >
{Array.from({ length: 10 }).map((_, index) => ( {isLoadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Belum ada event</TextCustom>
) : (
listData.map((item: any, index) => (
<Event_BoxPublishSection <Event_BoxPublishSection
key={index} key={index}
id={index.toString()} href={`/event/${item.id}/publish`}
href={`/event/${index}/publish`} data={item}
rightComponentAvatar={
<TextCustom>
{dateTimeView({ date: item?.tanggal, withoutTime: true })}
</TextCustom>
}
/> />
))} ))
)}
</ViewWrapper> </ViewWrapper>
); );
} }

View File

@@ -80,7 +80,7 @@ export default function EventEdit() {
} }
}; };
const validateDate = () => { const validateDate = async () => {
if ( if (
data?.title === "" || data?.title === "" ||
data?.lokasi === "" || data?.lokasi === "" ||
@@ -92,7 +92,8 @@ export default function EventEdit() {
text1: "Info", text1: "Info",
text2: "Lengkapi semua data", text2: "Lengkapi semua data",
}); });
return;
return false;
} }
const startDate = new Date(selectedDate as any); const startDate = new Date(selectedDate as any);
@@ -104,12 +105,17 @@ export default function EventEdit() {
text1: "Info", text1: "Info",
text2: "Ubah tanggal berakhirnya event", text2: "Ubah tanggal berakhirnya event",
}); });
return;
return false;
} }
return true;
}; };
const handlerSubmit = async () => { const handlerSubmit = async () => {
validateDate(); const isValid = await validateDate();
if (!isValid) return;
try { try {
setIsLoading(true); setIsLoading(true);
const newData = { const newData = {

View File

@@ -1,23 +1,42 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
ButtonCustom, ButtonCustom,
DotButton, DotButton,
DrawerCustom, DrawerCustom,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
Spacing, Spacing,
ViewWrapper ViewWrapper,
} from "@/components"; } from "@/components";
import { IMenuDrawerItem } from "@/components/_Interface/types"; import { IMenuDrawerItem } from "@/components/_Interface/types";
import LeftButtonCustom from "@/components/Button/BackButton"; import LeftButtonCustom from "@/components/Button/BackButton";
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection"; import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish"; import { menuDrawerPublishEvent } from "@/screens/Event/menuDrawerPublish";
import { apiEventGetOne } from "@/service/api-client/api-event";
import { router, Stack, useLocalSearchParams } from "expo-router"; import { router, Stack, useLocalSearchParams } from "expo-router";
import { useState } from "react"; import { useEffect, useState } from "react";
import { Alert } from "react-native"; import { Alert } from "react-native";
export default function EventDetailPublish() { export default function EventDetailPublish() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const [openDrawer, setOpenDrawer] = useState(false); const [openDrawer, setOpenDrawer] = useState(false);
const [data, setData] = useState();
useEffect(() => {
onLoadData();
}, [id]);
async function onLoadData() {
try {
const response = await apiEventGetOne({ id: id as string });
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
}
}
const handlePress = (item: IMenuDrawerItem) => { const handlePress = (item: IMenuDrawerItem) => {
console.log("PATH ", item.path); console.log("PATH ", item.path);
router.navigate(item.path as any); router.navigate(item.path as any);
@@ -44,19 +63,19 @@ export default function EventDetailPublish() {
}} }}
/> />
<ViewWrapper> <ViewWrapper>
<Event_BoxDetailPublishSection footerButton={footerButton} /> <Event_BoxDetailPublishSection data={data} footerButton={footerButton} />
<Spacing /> <Spacing />
</ViewWrapper> </ViewWrapper>
<DrawerCustom <DrawerCustom
isVisible={openDrawer} isVisible={openDrawer}
closeDrawer={() => setOpenDrawer(false)} closeDrawer={() => setOpenDrawer(false)}
height={250} height={"auto"}
> >
<MenuDrawerDynamicGrid <MenuDrawerDynamicGrid
data={menuDrawerPublishEvent({ id: id as string })} data={menuDrawerPublishEvent({ id: id as string })}
columns={4} columns={4}
onPressItem={handlePress} // onPressItem={handlePress}
/> />
</DrawerCustom> </DrawerCustom>
</> </>

View File

@@ -1,7 +1,6 @@
import { ImageSourcePropType } from "react-native";
import Divider from "../Divider/Divider"; import Divider from "../Divider/Divider";
import Grid from "../Grid/GridCustom"; import Grid from "../Grid/GridCustom";
import AvatarCustom from "../Image/AvatarCustom"; import AvatarComp from "../Image/AvatarComp";
import TextCustom from "../Text/TextCustom"; import TextCustom from "../Text/TextCustom";
const AvatarUsernameAndOtherComponent = ({ const AvatarUsernameAndOtherComponent = ({
@@ -12,7 +11,7 @@ const AvatarUsernameAndOtherComponent = ({
withBottomLine = false, withBottomLine = false,
}: { }: {
avatarHref?: string; avatarHref?: string;
avatar?: ImageSourcePropType; avatar?: string;
name?: string; name?: string;
rightComponent?: React.ReactNode; rightComponent?: React.ReactNode;
withBottomLine?: boolean; withBottomLine?: boolean;
@@ -21,7 +20,7 @@ const AvatarUsernameAndOtherComponent = ({
<> <>
<Grid containerStyle={{ zIndex: 10 }}> <Grid containerStyle={{ zIndex: 10 }}>
<Grid.Col span={2}> <Grid.Col span={2}>
<AvatarCustom source={avatar} href={avatarHref as any} /> <AvatarComp fileId={avatar} href={avatarHref as any} size="base" />
</Grid.Col> </Grid.Col>
<Grid.Col <Grid.Col
span={rightComponent ? 6 : 10} span={rightComponent ? 6 : 10}

View File

@@ -1,21 +1,50 @@
import { import { AvatarUsernameAndOtherComponent, BaseBox, BoxWithHeaderSection, Grid, StackCustom, TextCustom } from "@/components";
BaseBox, import { dateTimeView } from "@/utils/dateTimeView";
Grid,
StackCustom,
TextCustom
} from "@/components";
export default function Event_BoxDetailPublishSection({ export default function Event_BoxDetailPublishSection({
data,
footerButton, footerButton,
}: { }: {
data?: any;
footerButton?: React.ReactNode; footerButton?: React.ReactNode;
}) { }) {
const listData = [
{
title: "Lokasi",
value: data?.lokasi || "-",
},
{
title: "Tipe Acara",
value: data?.EventMaster_TipeAcara?.name || "-",
},
{
title: "Tanggal Mulai",
value: dateTimeView({ date: data?.tanggal }) || "-",
},
{
title: "Tanggal Berakhir",
value: dateTimeView({ date: data?.tanggalSelesai }) || "-",
},
{
title: "Deskripsi",
value: data?.deskripsi || "-",
},
];
console.log("DATA >> ", JSON.stringify(data, null, 2));
return ( return (
<> <>
<BaseBox> <BoxWithHeaderSection>
<StackCustom> <StackCustom>
<AvatarUsernameAndOtherComponent
avatarHref={`/profile/${data?.Author?.Profile?.id}`}
name={data?.Author?.username || "-"}
avatar={data?.Author?.Profile?.imageId || ""}
/>
<TextCustom bold align="center" size="xlarge"> <TextCustom bold align="center" size="xlarge">
Judul event publish {data?.title || "-"}
</TextCustom> </TextCustom>
{listData.map((item, index) => ( {listData.map((item, index) => (
<Grid key={index}> <Grid key={index}>
@@ -28,34 +57,9 @@ export default function Event_BoxDetailPublishSection({
</Grid> </Grid>
))} ))}
</StackCustom> </StackCustom>
</BaseBox> </BoxWithHeaderSection>
{footerButton} {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!",
},
];

View File

@@ -7,21 +7,15 @@ import {
import { Href } from "expo-router"; import { Href } from "expo-router";
export default function Event_BoxPublishSection({ export default function Event_BoxPublishSection({
id,
title,
username,
description,
href, href,
data,
// Avatar // Avatar
sourceAvatar, sourceAvatar,
rightComponentAvatar, rightComponentAvatar,
}: { }: {
id: string;
title?: string;
username?: string;
description?: string;
href: Href; href: Href;
data?: any;
// Avatar // Avatar
sourceAvatar?: string; sourceAvatar?: string;
@@ -32,18 +26,15 @@ export default function Event_BoxPublishSection({
<BoxWithHeaderSection href={href}> <BoxWithHeaderSection href={href}>
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<AvatarUsernameAndOtherComponent <AvatarUsernameAndOtherComponent
avatarHref={`/profile/${id}`} avatarHref={`/profile/${data?.Author?.Profile?.id}`}
name={username || "Lorem ipsum dolor sit"} name={data?.Author?.username || "-"}
rightComponent={rightComponentAvatar} rightComponent={rightComponentAvatar}
avatar={sourceAvatar as any} avatar={data?.Author?.Profile?.imageId || ""}
/> />
<TextCustom truncate bold> <TextCustom truncate bold>
{title || "Lorem ipsum dolor sit"} {data?.title || "-"}
</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> </TextCustom>
<TextCustom truncate={2}>{data?.deskripsi || "-"}</TextCustom>
</StackCustom> </StackCustom>
</BoxWithHeaderSection> </BoxWithHeaderSection>
</> </>

View File

@@ -1,5 +1,8 @@
import { AlertDefaultSystem, ButtonCustom, Grid } from "@/components"; import { AlertDefaultSystem, ButtonCustom, Grid } from "@/components";
import { apiEventUpdateStatus } from "@/service/api-client/api-event"; import {
apiEventDelete,
apiEventUpdateStatus,
} from "@/service/api-client/api-event";
import { router } from "expo-router"; import { router } from "expo-router";
import Toast from "react-native-toast-message"; import Toast from "react-native-toast-message";
@@ -118,9 +121,26 @@ export default function Event_ButtonStatusSection({
message: "Apakah Anda yakin ingin menghapus data ini?", message: "Apakah Anda yakin ingin menghapus data ini?",
textLeft: "Batal", textLeft: "Batal",
textRight: "Hapus", textRight: "Hapus",
onPressRight: () => { onPressRight: async () => {
console.log("Hapus"); try {
const response = await apiEventDelete({ id: id });
if (response.success) {
Toast.show({
type: "success",
text1: response.message,
});
router.back(); router.back();
} else {
Toast.show({
type: "info",
text1: "Info",
text2: response.message,
});
router.back();
}
} catch (error) {
console.log("[ERROR]", error);
}
}, },
}); });
}; };

View File

@@ -62,3 +62,23 @@ export async function apiEventUpdateData({ id, data }: { id: string; data: any }
throw error; throw error;
} }
} }
export async function apiEventDelete({ id }: { id: string }) {
try {
const response = await apiConfig.delete(`/mobile/event/${id}`);
return response.data;
} catch (error) {
throw error;
}
}
export async function apiEventGetAll() {
try {
const response = await apiConfig.get(`/mobile/event`);
return response.data;
} catch (error) {
throw error;
}
}

View File

@@ -7,6 +7,8 @@ export const dateTimeView = ({
date: any; date: any;
withoutTime?: boolean; withoutTime?: boolean;
}) => { }) => {
const newDate = dayjs(date).format(`DD-MM-YYYY, ${withoutTime ? "" : "HH:mm"}`); const newDate = dayjs(date).format(
`DD-MM-YYYY ${withoutTime ? "" : ", HH:mm"}`
);
return newDate; return newDate;
}; };