Compare commits

..

2 Commits

Author SHA1 Message Date
821a211f58 Collaboration
Fix:
- Integrasi API: Beranda, create, list partisipan, check sudah berpartisipasi ?

### No Issue
2025-09-22 17:31:40 +08:00
333b1d2512 Voting
Fix: Semua tampilan sudah terintegrasi API

### No Issue
2025-09-19 17:51:08 +08:00
26 changed files with 1075 additions and 275 deletions

View File

@@ -125,7 +125,6 @@ export default function UserLayout() {
headerLeft: () => <BackButton />,
}}
/>
<Stack.Screen
name="collaboration/[id]/edit"
options={{
@@ -133,6 +132,13 @@ export default function UserLayout() {
headerLeft: () => <BackButton />,
}}
/>
<Stack.Screen
name="collaboration/[id]/create-pacticipants"
options={{
title: "Ajukan Partisipasi",
headerLeft: () => <BackButton />,
}}
/>
{/* ========== End Collaboration Section ========= */}

View File

@@ -1,8 +1,37 @@
import { FloatingButton, ViewWrapper } from "@/components";
import {
FloatingButton,
LoaderCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import Collaboration_BoxPublishSection from "@/screens/Collaboration/BoxPublishSection";
import { router } from "expo-router";
import { apiCollaborationGetAll } from "@/service/api-client/api-collaboration";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
export default function CollaborationBeranda() {
const [listData, setListData] = useState<any[]>();
const [loadingGetData, setLoadingGetData] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [])
);
const onLoadData = async () => {
try {
setLoadingGetData(true);
const response = await apiCollaborationGetAll();
setListData(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
};
return (
<>
<ViewWrapper
@@ -15,13 +44,19 @@ export default function CollaborationBeranda() {
/>
}
>
{Array.from({ length: 10 }).map((_, index) => (
<Collaboration_BoxPublishSection
key={index}
id={index.toString()}
href={`/collaboration/${index}`}
/>
))}
{loadingGetData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Tidak ada data</TextCustom>
) : (
listData?.map((item: any, index: number) => (
<Collaboration_BoxPublishSection
key={index}
href={`/collaboration/${item.id}`}
data={item}
/>
))
)}
</ViewWrapper>
</>
);

View File

@@ -0,0 +1,80 @@
import {
AlertDefaultSystem,
ButtonCustom,
TextAreaCustom,
ViewWrapper,
} from "@/components";
import { useAuth } from "@/hooks/use-auth";
import { apiCollaborationCreatePartisipasi } from "@/service/api-client/api-collaboration";
import { router, useLocalSearchParams } from "expo-router";
import { useState } from "react";
import Toast from "react-native-toast-message";
export default function CollaborationCreatePartisipans() {
const { user } = useAuth();
const { id } = useLocalSearchParams();
const [description, setDescription] = useState("");
const [isLoading, setLoading] = useState(false);
const handlerSubmitParticipans = async () => {
try {
setLoading(true);
const response = await apiCollaborationCreatePartisipasi({
id: id as string,
data: {
authorId: user?.id,
description,
},
});
if (response.success) {
Toast.show({
type: "success",
text1: "Data berhasil disimpan",
});
router.replace(`/collaboration/${id}/list-of-participants`);
} else {
Toast.show({
type: "error",
text1: "Gagal menyimpan data",
});
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoading(false);
}
};
return (
<ViewWrapper>
<TextAreaCustom
// label="Deskripsi"
placeholder="Masukan deskripsi diri anda .."
value={description}
onChangeText={setDescription}
required
showCount
maxLength={1000}
/>
<ButtonCustom
disabled={description.length === 0}
isLoading={isLoading}
onPress={() => {
AlertDefaultSystem({
title: "Simpan data deskripsi",
message: "Apakah anda sudah yakin ingin menyimpan data ini ?",
textLeft: "Batal",
textRight: "Simpan",
onPressRight: () => {
handlerSubmitParticipans();
},
});
}}
>
Simpan
</ButtonCustom>
</ViewWrapper>
);
}

View File

@@ -1,22 +1,73 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AlertDefaultSystem,
BackButton,
ButtonCustom,
DotButton,
DrawerCustom,
LoaderCustom,
MenuDrawerDynamicGrid,
TextAreaCustom,
ViewWrapper,
} from "@/components";
import { useAuth } from "@/hooks/use-auth";
import Collaboration_BoxDetailSection from "@/screens/Collaboration/BoxDetailSection";
import {
apiCollaborationGetOne,
apiCollaborationGetParticipants,
} from "@/service/api-client/api-collaboration";
import { Ionicons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useState } from "react";
import {
router,
Stack,
useFocusEffect,
useLocalSearchParams,
} from "expo-router";
import { useCallback, useState } from "react";
export default function CollaborationDetail() {
const { user } = useAuth();
const { id } = useLocalSearchParams();
const [openDrawerPartisipasi, setOpenDrawerPartisipasi] = useState(false);
const [data, setData] = useState();
const [openDrawerMenu, setOpenDrawerMenu] = useState(false);
const [isParticipant, setIsParticipant] = useState(false);
const [loadingIsParticipant, setLoadingIsParticipant] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
onLoadParticipants();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiCollaborationGetOne({ id: id as string });
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const onLoadParticipants = async () => {
try {
setLoadingIsParticipant(true);
const response = await apiCollaborationGetParticipants({
category: "check-participant",
id: id as string,
authorId: user?.id,
});
if (response.success) {
setIsParticipant(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingIsParticipant(false);
}
};
return (
<>
<Stack.Screen
@@ -29,15 +80,27 @@ export default function CollaborationDetail() {
}}
/>
<ViewWrapper>
<Collaboration_BoxDetailSection id={id as string} />
{!data && !isParticipant ? (
<LoaderCustom />
) : (
<>
<Collaboration_BoxDetailSection data={data} />
<ButtonCustom onPress={() => setOpenDrawerPartisipasi(true)}>
Partisipasi
</ButtonCustom>
<ButtonCustom
disabled={isParticipant || loadingIsParticipant}
onPress={() => {
router.push(`/collaboration/${id}/create-pacticipants`);
// setOpenDrawerPartisipasi(true);
}}
>
{isParticipant ? "Anda telah berpartisipasi" : "Partisipasi"}
</ButtonCustom>
</>
)}
</ViewWrapper>
{/* Drawer Partisipasi */}
<DrawerCustom
{/* <DrawerCustom
isVisible={openDrawerPartisipasi}
closeDrawer={() => setOpenDrawerPartisipasi(false)}
height={300}
@@ -48,6 +111,8 @@ export default function CollaborationDetail() {
required
showCount
maxLength={500}
value={description}
onChangeText={setDescription}
/>
<ButtonCustom
@@ -58,19 +123,21 @@ export default function CollaborationDetail() {
message: "Apakah anda sudah yakin ingin menyimpan data ini ?",
textLeft: "Batal",
textRight: "Simpan",
onPressRight: () => router.replace(`/collaboration/(tabs)/group`),
onPressRight: () => {
handlerSubmitParticipans();
},
});
}}
>
Simpan
</ButtonCustom>
</DrawerCustom>
</DrawerCustom> */}
{/* Drawer Menu */}
<DrawerCustom
isVisible={openDrawerMenu}
closeDrawer={() => setOpenDrawerMenu(false)}
height={250}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[

View File

@@ -1,38 +1,79 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AvatarUsernameAndOtherComponent,
BaseBox,
DrawerCustom,
Spacing,
StackCustom,
TextCustom,
ViewWrapper
AvatarUsernameAndOtherComponent,
BaseBox,
DrawerCustom,
LoaderCustom,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { apiCollaborationGetParticipants } from "@/service/api-client/api-collaboration";
import { Feather } from "@expo/vector-icons";
import { useLocalSearchParams } from "expo-router";
import { useState } from "react";
import _ from "lodash";
import { useEffect, useState } from "react";
import { ScrollView } from "react-native";
export default function CollaborationListOfParticipants() {
const { id } = useLocalSearchParams();
const [listData, setListData] = useState<any[]>();
const [loadingGetData, setLoadingGetData] = useState(false);
const [description, setDescription] = useState("");
useEffect(() => {
onLoadData();
}, [id]);
const onLoadData = async () => {
try {
setLoadingGetData(true);
const response = await apiCollaborationGetParticipants({
category: "list",
id: id as string,
});
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
};
const [openDrawer, setOpenDrawer] = useState(false);
return (
<>
<ViewWrapper>
{Array.from({ length: 10 }).map((_, index) => (
<BaseBox key={index} paddingBlock={5}>
<AvatarUsernameAndOtherComponent
avatarHref={`/profile/${id}`}
rightComponent={
<Feather
name="chevron-right"
size={24}
color="white"
onPress={() => setOpenDrawer(true)}
/>
}
/>
</BaseBox>
))}
{loadingGetData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Tidak ada data</TextCustom>
) : (
listData?.map((item: any, index: number) => (
<BaseBox key={index} paddingBlock={5}>
<AvatarUsernameAndOtherComponent
avatar={item?.User?.Profile?.imageId}
avatarHref={`/profile/${item?.User?.Profile?.id}`}
name={item?.User?.username}
rightComponent={
<Feather
name="chevron-right"
size={24}
color="white"
onPress={() => {
setDescription(item?.deskripsi_diri);
setOpenDrawer(true);
}}
/>
}
/>
</BaseBox>
))
)}
</ViewWrapper>
{/* Drawer */}
@@ -44,34 +85,7 @@ export default function CollaborationListOfParticipants() {
<TextCustom bold>Deskripsi diri</TextCustom>
<BaseBox>
<ScrollView style={{ height: "80%" }}>
<TextCustom>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.Lorem
ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.Lorem
ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.Lorem
ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut iqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.Lorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.
</TextCustom>
<TextCustom>{description}</TextCustom>
</ScrollView>
</BaseBox>
<Spacing />

View File

@@ -1,53 +1,175 @@
import {
ButtonCustom,
SelectCustom,
StackCustom,
TextAreaCustom,
TextInputCustom,
ViewWrapper
ButtonCustom,
LoaderCustom,
SelectCustom,
StackCustom,
TextAreaCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import { useAuth } from "@/hooks/use-auth";
import { apiCollaborationCreate } from "@/service/api-client/api-collaboration";
import { apiMasterCollaborationType } from "@/service/api-client/api-master";
import { router } from "expo-router";
import React, { useEffect, useState } from "react";
import Toast from "react-native-toast-message";
interface CollaborationCreateProps {
title?: string;
lokasi?: string;
purpose?: string;
benefit?: string;
projectCollaborationMaster_IndustriId?: string;
userId?: string;
}
export default function CollaborationCreate() {
const { user } = useAuth();
const [listMaster, setListMaster] = useState<any>([]);
const [loadingMaster, setLoadingMaster] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = React.useState<CollaborationCreateProps>({
title: "",
lokasi: "",
purpose: "",
benefit: "",
projectCollaborationMaster_IndustriId: "",
userId: "",
});
useEffect(() => {
onLoadMaster();
}, []);
async function onLoadMaster() {
try {
setLoadingMaster(true);
const response = await apiMasterCollaborationType();
setListMaster(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingMaster(false);
}
}
const handlerSubmit = async () => {
if (
!data?.title ||
!data?.lokasi ||
!data?.purpose ||
!data?.benefit ||
!data?.projectCollaborationMaster_IndustriId
) {
Toast.show({
type: "error",
text1: "Gagal",
text2: "Harap isi semua data",
});
return;
}
const newData: CollaborationCreateProps = {
title: data?.title,
lokasi: data?.lokasi,
purpose: data?.purpose,
benefit: data?.benefit,
projectCollaborationMaster_IndustriId:
data?.projectCollaborationMaster_IndustriId,
userId: user?.id,
};
try {
setIsLoading(true);
console.log("[DATA]>>", newData);
const response = await apiCollaborationCreate({ data: newData });
if (response.success) {
Toast.show({
type: "success",
text1: "Berhasil",
text2: response.message,
});
router.back();
} else {
Toast.show({
type: "error",
text1: "Gagal",
text2: response.message,
});
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setIsLoading(false);
}
};
return (
<ViewWrapper>
<StackCustom gap={"xs"}>
<TextInputCustom label="Judul" placeholder="Masukan judul" required />
<TextInputCustom label="Lokasi" placeholder="Masukan lokasi" required />
<SelectCustom
label="Pilih Industri"
data={[
{ label: "Industri 1", value: "industri-1" },
{ label: "Industri 2", value: "industri-2" },
{ label: "Industri 3", value: "industri-3" },
]}
onChange={(value) => console.log(value)}
/>
{loadingMaster ? (
<LoaderCustom />
) : (
<StackCustom gap={"xs"}>
<TextInputCustom
label="Judul"
placeholder="Masukan judul"
required
value={data?.title}
onChangeText={(value: any) => setData({ ...data, title: value })}
/>
<TextAreaCustom
required
label="Tujuan Proyek"
placeholder="Masukan tujuan proyek"
showCount
maxLength={1000}
/>
<TextInputCustom
label="Lokasi"
placeholder="Masukan lokasi"
required
value={data?.lokasi}
onChangeText={(value: any) => setData({ ...data, lokasi: value })}
/>
<TextAreaCustom
required
label="Keuntungan Proyek"
placeholder="Masukan keuntungan proyek"
showCount
maxLength={1000}
/>
<SelectCustom
label="Pilih Industri"
data={listMaster?.map((item: any) => ({
label: item.name,
value: item.id,
}))}
value={data?.projectCollaborationMaster_IndustriId}
onChange={(value: any) => {
console.log(value);
setData({
...data,
projectCollaborationMaster_IndustriId: value,
});
}}
/>
<ButtonCustom
title="Simpan"
onPress={() => {
console.log("Simpan proyek");
router.back();
}}
/>
</StackCustom>
<TextAreaCustom
required
label="Tujuan Proyek"
placeholder="Masukan tujuan proyek"
showCount
maxLength={1000}
value={data?.purpose}
onChangeText={(value: any) => setData({ ...data, purpose: value })}
/>
<TextAreaCustom
required
label="Keuntungan Proyek"
placeholder="Masukan keuntungan proyek"
showCount
maxLength={1000}
value={data?.benefit}
onChangeText={(value: any) => setData({ ...data, benefit: value })}
/>
<ButtonCustom
isLoading={isLoading}
title="Simpan"
onPress={() => handlerSubmit()}
/>
</StackCustom>
)}
</ViewWrapper>
);
}

View File

@@ -1,15 +1,57 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
LoaderCustom,
TextCustom,
ViewWrapper
} from "@/components";
import { useAuth } from "@/hooks/use-auth";
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
import { apiVotingGetAll } from "@/service/api-client/api-voting";
import { useFocusEffect } from "expo-router";
import _ from "lodash";
import { useState, useCallback } from "react";
export default function VotingContribution() {
const { user } = useAuth();
const [listData, setListData] = useState<any>([]);
const [loadingGetData, setLoadingGetData] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [])
);
const onLoadData = async () => {
try {
setLoadingGetData(true);
const response = await apiVotingGetAll({
category: "contribution",
authorId: user?.id as string,
});
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
};
return (
<ViewWrapper hideFooter>
{Array.from({ length: 5 }).map((_, index) => (
{loadingGetData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Tidak ada kontribusi</TextCustom>
) : listData.map((item: any, index: number) => (
<Voting_BoxPublishSection
data={item}
key={index}
href={`/voting/${index}/contribution`}
href={`/voting/${item.id}/contribution`}
/>
))}
</ViewWrapper>

View File

@@ -1,11 +1,44 @@
import { ViewWrapper } from "@/components";
/* eslint-disable react-hooks/exhaustive-deps */
import { LoaderCustom, TextCustom, ViewWrapper } from "@/components";
import TabsTwoButtonCustom from "@/components/_ShareComponent/TabsTwoHeaderCustom";
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
import { useState } from "react";
import { useAuth } from "@/hooks/use-auth";
import { useCallback, useState } from "react";
import { apiVotingGetAll } from "@/service/api-client/api-voting";
import { useFocusEffect } from "expo-router";
import _ from "lodash";
export default function VotingHistory() {
const { user } = useAuth();
const [activeCategory, setActiveCategory] = useState<string | null>("all");
const [listData, setListData] = useState<any>([]);
const [loadingGetData, setLoadingGetData] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [activeCategory])
);
const onLoadData = async () => {
try {
setLoadingGetData(true);
const response = await apiVotingGetAll({
category: activeCategory === "all" ? "all-history" : "my-history",
authorId: user?.id as string,
});
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
};
const handlePress = (item: any) => {
setActiveCategory(item);
// tambahkan logika lain seperti filter dsb.
@@ -25,13 +58,20 @@ export default function VotingHistory() {
/>
}
>
{Array.from({ length: 10 }).map((_, index) => (
<Voting_BoxPublishSection
key={index}
id={activeCategory as any}
href={`/voting/${index}/history`}
/>
))}
{loadingGetData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Tidak ada riwayat</TextCustom>
) : (
listData.map((item: any, index: number) => (
<Voting_BoxPublishSection
key={index}
id={item.id}
data={item}
href={`/voting/${item.id}/history`}
/>
))
)}
</ViewWrapper>
);
}

View File

@@ -8,23 +8,28 @@ import {
} from "@/components";
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
import { apiVotingGetAll } from "@/service/api-client/api-voting";
import { router } from "expo-router";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import { useEffect, useState } from "react";
import { useCallback, useState } from "react";
export default function VotingBeranda() {
const [listData, setListData] = useState<any>([]);
const [loadingGetData, setLoadingGetData] = useState(false);
const [search, setSearch] = useState("");
useEffect(() => {
onLoadData();
}, [search]);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [search])
);
const onLoadData = async () => {
try {
setLoadingGetData(true);
const response = await apiVotingGetAll({ search });
const response = await apiVotingGetAll({
search,
category: "beranda",
});
if (response.success) {
setListData(response.data);
}

View File

@@ -2,17 +2,24 @@
import {
AlertDefaultSystem,
BackButton,
BaseBox,
DotButton,
DrawerCustom,
LoaderCustom,
MenuDrawerDynamicGrid,
Spacing,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconArchive, IconContribution, IconEdit } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
import { Voting_BoxDetailSection } from "@/screens/Voting/BoxDetailSection";
import Voting_ButtonStatusSection from "@/screens/Voting/ButtonStatusSection";
import { apiVotingGetOne } from "@/service/api-client/api-voting";
import {
apiVotingGetOne,
apiVotingUpdateData,
} from "@/service/api-client/api-voting";
import {
router,
Stack,
@@ -20,12 +27,14 @@ import {
useLocalSearchParams,
} from "expo-router";
import { useCallback, useState } from "react";
import Toast from "react-native-toast-message";
export default function VotingDetailStatus() {
const { id, status } = useLocalSearchParams();
const [openDrawerDraft, setOpenDrawerDraft] = useState(false);
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [loadingGetData, setLoadingGetData] = useState(false);
const [data, setData] = useState<any>(null);
@@ -37,12 +46,16 @@ export default function VotingDetailStatus() {
const onLoadData = async () => {
try {
setLoadingGetData(true);
const response = await apiVotingGetOne({ id: id as string });
if(response.success){
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
};
@@ -59,9 +72,24 @@ export default function VotingDetailStatus() {
message: "Apakah Anda yakin ingin mengarsipkan voting ini?",
textLeft: "Batal",
textRight: "Ya",
onPressRight: () => {
console.log("Arsip voting");
router.back();
onPressRight: async () => {
try {
const response = await apiVotingUpdateData({
id: id as string,
data: data.isArsip ? false : true,
category: "archive",
});
if (response.success) {
Toast.show({
type: "success",
text1: response.message,
});
router.back();
}
} catch (error) {
console.log("[ERROR]", error);
}
},
});
}
@@ -73,7 +101,7 @@ export default function VotingDetailStatus() {
<>
<Stack.Screen
options={{
title: `Detail ${status}`,
title: `Detail`,
headerLeft: () => <BackButton />,
headerRight: () =>
status === "draft" ? (
@@ -84,14 +112,37 @@ export default function VotingDetailStatus() {
}}
/>
<ViewWrapper>
<Voting_BoxDetailSection data={data as any} />
<Voting_ButtonStatusSection
isLoading={isLoading}
onSetLoading={setIsLoading}
id={id as string}
status={status as string}
/>
<Spacing />
{loadingGetData ? (
<LoaderCustom />
) : (
<>
{status === "publish" && (
<BaseBox>
<TextCustom bold>
Status:{" "}
<TextCustom color={data?.isArsip ? "red" : "green"}>
{data?.isArsip ? "Arsip" : "Publish"}
</TextCustom>
</TextCustom>
</BaseBox>
)}
<Spacing height={0} />
<Voting_BoxDetailSection data={data as any} />
{status === "publish" ? (
<Voting_BoxDetailHasilVotingSection
listData={data?.Voting_DaftarNamaVote}
/>
) : (
<Voting_ButtonStatusSection
isLoading={isLoading}
onSetLoading={setIsLoading}
id={id as string}
status={status as string}
/>
)}
<Spacing />
</>
)}
</ViewWrapper>
{/* ========= Draft Drawer ========= */}

View File

@@ -1,22 +1,76 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AvatarUsernameAndOtherComponent,
BackButton,
DotButton,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
AvatarUsernameAndOtherComponent,
BackButton,
DotButton,
DrawerCustom,
LoaderCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
} from "@/components";
import { IconContribution } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { useAuth } from "@/hooks/use-auth";
import { Voting_BoxDetailContributionSection } from "@/screens/Voting/BoxDetailContribution";
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
import {
apiVotingContribution,
apiVotingGetOne,
} from "@/service/api-client/api-voting";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useState } from "react";
import { useEffect, useState } from "react";
export default function VotingDetailContribution() {
const { user } = useAuth();
const { id } = useLocalSearchParams();
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const [data, setData] = useState<any>(null);
const [loadingGetData, setLoadingGetData] = useState(false);
const [nameChoice, setNameChoice] = useState("");
useEffect(() => {
handlerLoadData();
}, [id, user?.id]);
async function handlerLoadData() {
try {
setLoadingGetData(true);
await onLoadData();
await onLoadCheckContribution();
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
}
const onLoadData = async () => {
try {
const response = await apiVotingGetOne({ id: id as string });
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const onLoadCheckContribution = async () => {
try {
const response = await apiVotingContribution({
id: id as string,
authorId: user?.id as string,
category: "checked",
});
if (response.success) {
setNameChoice(response.data.nameChoice);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const handlePressPublish = (item: IMenuDrawerItem) => {
router.navigate(item.path as any);
@@ -36,11 +90,27 @@ export default function VotingDetailContribution() {
/>
<ViewWrapper>
<Voting_BoxDetailContributionSection
headerAvatar={<AvatarUsernameAndOtherComponent />}
/>
<Voting_BoxDetailHasilVotingSection />
<Spacing />
{loadingGetData ? (
<LoaderCustom />
) : (
<>
<Voting_BoxDetailContributionSection
data={data}
nameChoice={nameChoice}
headerAvatar={
<AvatarUsernameAndOtherComponent
avatar={data?.Author?.Profile?.imageId || ""}
name={data?.Author?.username || "Username"}
avatarHref={`/profile/${data?.Author?.Profile?.id}`}
/>
}
/>
<Voting_BoxDetailHasilVotingSection
listData={data?.Voting_DaftarNamaVote}
/>
<Spacing />
</>
)}
</ViewWrapper>
{/* ========= Publish Drawer ========= */}

View File

@@ -150,6 +150,7 @@ export default function VotingEdit() {
const response = await apiVotingUpdateData({
id: id as string,
data: newData,
category: "edit",
});
if (response.success) {

View File

@@ -1,23 +1,78 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AvatarUsernameAndOtherComponent,
BackButton,
DotButton,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
AvatarUsernameAndOtherComponent,
BackButton,
DotButton,
DrawerCustom,
LoaderCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
} from "@/components";
import { IconContribution } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { useAuth } from "@/hooks/use-auth";
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
import { Voting_BoxDetailHistorySection } from "@/screens/Voting/BoxDetailHistorySection";
import {
apiVotingContribution,
apiVotingGetOne,
} from "@/service/api-client/api-voting";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useState } from "react";
import { useEffect, useState } from "react";
export default function VotingDetailHistory() {
const { id } = useLocalSearchParams();
const { user } = useAuth();
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const [data, setData] = useState<any>(null);
const [loadingGetData, setLoadingGetData] = useState(false);
const [nameChoice, setNameChoice] = useState("");
useEffect(() => {
handlerLoadData();
}, [id, user?.id]);
async function handlerLoadData() {
try {
setLoadingGetData(true);
await onLoadData();
await onLoadCheckContribution();
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingGetData(false);
}
}
const onLoadData = async () => {
try {
const response = await apiVotingGetOne({ id: id as string });
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const onLoadCheckContribution = async () => {
try {
const response = await apiVotingContribution({
id: id as string,
authorId: user?.id as string,
category: "checked",
});
if (response.success) {
setNameChoice(response.data.nameChoice);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const handlePressPublish = (item: IMenuDrawerItem) => {
router.navigate(item.path as any);
setOpenDrawerPublish(false);
@@ -35,11 +90,27 @@ export default function VotingDetailHistory() {
}}
/>
<ViewWrapper>
<Voting_BoxDetailHistorySection
headerAvatar={<AvatarUsernameAndOtherComponent />}
/>
<Voting_BoxDetailHasilVotingSection />
<Spacing />
{loadingGetData ? (
<LoaderCustom />
) : (
<>
<Voting_BoxDetailHistorySection
data={data}
nameChoice={nameChoice}
headerAvatar={
<AvatarUsernameAndOtherComponent
avatar={data?.Author?.Profile?.imageId || ""}
name={data?.Author?.username || "Username"}
avatarHref={`/profile/${data?.Author?.Profile?.id}`}
/>
}
/>
<Voting_BoxDetailHasilVotingSection
listData={data?.Voting_DaftarNamaVote}
/>
<Spacing />
</>
)}
</ViewWrapper>
{/* ========= Publish Drawer ========= */}

View File

@@ -9,17 +9,19 @@ import {
LoaderCustom,
MenuDrawerDynamicGrid,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconArchive, IconContribution } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { useAuth } from "@/hooks/use-auth";
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
import { Voting_BoxDetailPublishSection } from "@/screens/Voting/BoxDetailPublishSection";
import {
apiVotingCheckContribution,
apiVotingContribution,
apiVotingGetOne,
apiVotingUpdateData,
} from "@/service/api-client/api-voting";
import { today } from "@/utils/dateTimeView";
import {
router,
Stack,
@@ -27,14 +29,11 @@ import {
useLocalSearchParams,
} from "expo-router";
import React, { useCallback, useState } from "react";
import { useAuth } from "@/hooks/use-auth";
import Toast from "react-native-toast-message";
export default function VotingDetail() {
const { id } = useLocalSearchParams();
const { user } = useAuth();
console.log("[ID]", id);
const dateNow = new Date();
console.log("[DATE NOW]", dateNow);
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const [data, setData] = useState<any>(null);
@@ -42,8 +41,6 @@ export default function VotingDetail() {
const [isContribution, setIsContribution] = useState(false);
const [nameChoice, setNameChoice] = useState("");
console.log("[DATA AWAL]", data?.awalVote);
useFocusEffect(
useCallback(() => {
handlerLoadData();
@@ -65,7 +62,6 @@ export default function VotingDetail() {
const onLoadData = async () => {
try {
const response = await apiVotingGetOne({ id: id as string });
// console.log("[DATA]", JSON.stringify(response.data, null, 2));
if (response.success) {
setData(response.data);
}
@@ -76,11 +72,12 @@ export default function VotingDetail() {
const onLoadCheckContribution = async () => {
try {
const response = await apiVotingCheckContribution({
const response = await apiVotingContribution({
id: id as string,
authorId: user?.id as string,
category: "checked",
});
console.log("[DATA CONTRIBUION]", response.data);
if (response.success) {
setIsContribution(response.data.isContribution);
setNameChoice(response.data.nameChoice);
@@ -97,9 +94,24 @@ export default function VotingDetail() {
message: "Apakah Anda yakin ingin mengarsipkan voting ini?",
textLeft: "Batal",
textRight: "Ya",
onPressRight: () => {
console.log("Hapus");
router.back();
onPressRight: async () => {
try {
const response = await apiVotingUpdateData({
id: id as string,
data: data.isArsip ? false : true,
category: "archive",
});
if (response.success) {
Toast.show({
type: "success",
text1: response.message,
});
router.back();
}
} catch (error) {
console.log("[ERROR]", error);
}
},
});
}
@@ -124,8 +136,8 @@ export default function VotingDetail() {
<LoaderCustom />
) : (
<StackCustom gap={"xs"}>
{dateNow < new Date(data?.awalVote) && (
<InformationBox text="Untuk sementara voting ini belum di buka. Voting akan dimulai sesuai dengan tanggal awal pemilihan, dan akan ditutup sesuai dengan tanggal akhir pemilihan." />
{today.getDate() < new Date(data?.awalVote).getDate() && (
<InformationBox text="Untuk sementara voting tidak dapat dilakukan. Voting dapat dimulai sesuai dengan tanggal awal pemilihan, dan akan ditutup sesuai dengan tanggal akhir pemilihan." />
)}
<Voting_BoxDetailPublishSection
data={data}
@@ -155,18 +167,28 @@ export default function VotingDetail() {
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: <IconContribution />,
label: "Daftar Kontributor",
path: `/voting/${id}/list-of-contributor`,
},
{
icon: <IconArchive />,
label: "Update Arsip",
path: "" as any,
},
]}
data={
user?.id === data?.Author?.id
? [
{
icon: <IconContribution />,
label: "Daftar Kontributor",
path: `/voting/${id}/list-of-contributor`,
},
{
icon: <IconArchive />,
label: "Update Arsip",
path: "" as any,
},
]
: [
{
icon: <IconContribution />,
label: "Daftar Kontributor",
path: `/voting/${id}/list-of-contributor`,
},
]
}
onPressItem={handlePressPublish as any}
/>
</DrawerCustom>

View File

@@ -1,26 +1,69 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AvatarUsernameAndOtherComponent,
BadgeCustom,
BaseBox,
LoaderCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { apiVotingContribution } from "@/service/api-client/api-voting";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
export default function Voting_ListOfContributor() {
const { id } = useLocalSearchParams();
const [listData, setListData] = useState<any>([]);
const [isLoadData, setIsLoadData] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadList();
}, [id])
);
const onLoadList = async () => {
try {
setIsLoadData(true);
const response = await apiVotingContribution({
id: id as string,
authorId: "",
category: "list",
});
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setIsLoadData(false);
}
};
return (
<ViewWrapper>
{Array.from({ length: 10 }).map((_, index) => (
<BaseBox paddingTop={5} paddingBottom={5} key={index.toString()}>
<AvatarUsernameAndOtherComponent
rightComponent={
<BadgeCustom
style={{alignSelf: "flex-end" }}
>
Pilihan {index + 1}
</BadgeCustom>
}
/>
</BaseBox>
))}
{isLoadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Tidak ada kontributor</TextCustom>
) : (
listData.map((item: any, index: number) => (
<BaseBox paddingTop={5} paddingBottom={5} key={index.toString()}>
<AvatarUsernameAndOtherComponent
avatar={item?.Author?.Profile?.imageId || ""}
name={item?.Author?.username || "Username"}
avatarHref={`/profile/${item?.Author?.Profile?.id}`}
rightComponent={
<BadgeCustom style={{ alignSelf: "flex-end" }}>
{item?.Voting_DaftarNamaVote?.value}
</BadgeCustom>
}
/>
</BaseBox>
))
)}
</ViewWrapper>
);
}

View File

@@ -1,3 +1,4 @@
import { AccentColor } from "@/constants/color-palet";
import Divider from "../Divider/Divider";
import Grid from "../Grid/GridCustom";
import AvatarComp from "../Image/AvatarComp";
@@ -39,7 +40,7 @@ const AvatarUsernameAndOtherComponent = ({
</Grid.Col>
)}
</Grid>
{withBottomLine && <Divider marginTop={0} />}
{withBottomLine && <Divider color={AccentColor.blue} marginTop={0} />}
</>
);
};

View File

@@ -1,22 +1,33 @@
import {
AvatarUsernameAndOtherComponent,
BoxWithHeaderSection,
Grid,
StackCustom,
TextCustom
AvatarUsernameAndOtherComponent,
BoxWithHeaderSection,
Grid,
Spacing,
StackCustom,
TextCustom,
} from "@/components";
export default function Collaboration_BoxDetailSection({ id }: { id: string }) {
export default function Collaboration_BoxDetailSection({
data,
}: {
data: any;
}) {
return (
<>
<BoxWithHeaderSection>
<AvatarUsernameAndOtherComponent
avatar={data?.Author?.Profile?.imageId}
name={data?.Author?.username}
avatarHref={`/profile/${data?.Author?.Profile?.id}`}
withBottomLine
/>
<Spacing height={10}/>
<StackCustom>
<AvatarUsernameAndOtherComponent />
<TextCustom align="center" bold size="large">
Judul Proyek {id}
{data?.title || ""}
</TextCustom>
{listData.map((item, index) => (
{listData(data).map((item, index) => (
<Grid key={index}>
<Grid.Col span={4}>
<TextCustom bold>{item.title}</TextCustom>
@@ -32,23 +43,21 @@ export default function Collaboration_BoxDetailSection({ id }: { id: string }) {
);
}
const listData = [
const listData = (data: any) => [
{
title: "Industri",
value: "Pilihan Industri",
value: data?.ProjectCollaborationMaster_Industri?.name || "-",
},
{
title: "Deskripsi",
value: "Deskripsi Proyek",
title: "Lokasi",
value: data?.lokasi || "-",
},
{
title: "Tujuan Proyek",
value:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
value: data?.purpose || "-",
},
{
title: "Keuntungan Proyek",
value:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
value: data?.benefit || "-",
},
];

View File

@@ -7,24 +7,12 @@ import {
import { Href } from "expo-router";
function Collaboration_BoxPublishSection({
id,
title,
username,
description,
href,
// Avatar
sourceAvatar,
data,
rightComponentAvatar,
}: {
id: string;
title?: string;
username?: string;
description?: string;
href: Href;
// Avatar
sourceAvatar?: string;
data: any;
rightComponentAvatar?: React.ReactNode;
}) {
return (
@@ -32,21 +20,18 @@ function Collaboration_BoxPublishSection({
<BoxWithHeaderSection href={href}>
<StackCustom gap={0}>
<AvatarUsernameAndOtherComponent
avatarHref={`/profile/${id}`}
name={username || "Username"}
avatarHref={`/profile/${data?.Author?.id}`}
name={data?.Author?.username || "Username"}
rightComponent={rightComponentAvatar}
avatar={sourceAvatar as any}
avatar={data?.Author?.Profile?.imageId}
withBottomLine
/>
<StackCustom>
<TextCustom truncate={2} size="large" bold align="center">
{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!"}
{data?.title || "-"}
</TextCustom>
<TextCustom truncate={2}>{data?.purpose || "-"}</TextCustom>
{/* <TextCustom bold size="small" >
2 Partisipan
</TextCustom> */}

View File

@@ -9,23 +9,32 @@ import { GStyles } from "@/styles/global-styles";
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
export function Voting_BoxDetailContributionSection({
data,
headerAvatar,
nameChoice,
}: {
data: any;
headerAvatar?: React.ReactNode;
nameChoice?: string;
}) {
return (
<>
<BoxWithHeaderSection>
{headerAvatar ? headerAvatar : <Spacing />}
{headerAvatar && (
<>
{headerAvatar}
<Spacing />
</>
)}
<StackCustom gap={"lg"}>
<Voting_ComponentDetailDataSection />
<Voting_ComponentDetailDataSection data={data} />
<StackCustom gap={"xs"}>
<StackCustom gap={"sm"}>
<TextCustom bold size="small" align="center">
Pilihan Anda
</TextCustom>
<BadgeCustom style={[GStyles.alignSelfCenter]}>
Pilihan 1
<BadgeCustom variant="light" size="lg" style={[GStyles.alignSelfCenter]}>
{nameChoice || "-"}
</BadgeCustom>
</StackCustom>
</StackCustom>

View File

@@ -9,7 +9,7 @@ import {
export default function Voting_BoxDetailHasilVotingSection({
listData,
}: {
listData?: any[];
listData: any[];
}) {
return (
<>

View File

@@ -1,21 +1,36 @@
import {
BadgeCustom,
BoxWithHeaderSection,
Spacing,
StackCustom
StackCustom,
TextCustom
} from "@/components";
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
import { GStyles } from "@/styles/global-styles";
export function Voting_BoxDetailHistorySection({
headerAvatar,
data,
nameChoice,
}: {
headerAvatar?: React.ReactNode;
data: any;
nameChoice: string;
}) {
return (
<>
<BoxWithHeaderSection>
{headerAvatar ? headerAvatar : <Spacing />}
<StackCustom>
<Voting_ComponentDetailDataSection />
<Voting_ComponentDetailDataSection data={data} />
<StackCustom gap={"sm"}>
<TextCustom bold size="small" align="center">
Pilihan Anda
</TextCustom>
<BadgeCustom variant="light" size="lg" style={[GStyles.alignSelfCenter]}>
{nameChoice || "-"}
</BadgeCustom>
</StackCustom>
</StackCustom>
</BoxWithHeaderSection>
</>

View File

@@ -1,18 +1,19 @@
import {
AlertDefaultSystem,
BadgeCustom,
BoxWithHeaderSection,
ButtonCustom,
CenterCustom,
Spacing,
StackCustom,
TextCustom,
TextCustom
} from "@/components";
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
import { apiVotingVote } from "@/service/api-client/api-voting";
import { today } from "@/utils/dateTimeView";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
import { Voting_ComponentDetailDataSection } from "./ComponentDetailDataSection";
import { apiVotingVote } from "@/service/api-client/api-voting";
import { useAuth } from "@/hooks/use-auth";
export function Voting_BoxDetailPublishSection({
headerAvatar,
@@ -40,7 +41,10 @@ export function Voting_BoxDetailPublishSection({
id: data?.id,
data: newData,
});
console.log("[RES VOTE]", response);
if (response.success) {
router.push(`/voting/${data?.id}/list-of-contributor`);
}
} catch (error) {
console.log("[ERROR]", error);
}
@@ -79,13 +83,30 @@ export function Voting_BoxDetailPublishSection({
<RadioGroup value={value} onChange={setValue}>
{data?.Voting_DaftarNamaVote?.map((item: any, i: number) => (
<View key={i}>
<RadioCustom label={item?.value} value={item?.id} />
<RadioCustom
disabled={
today.getDate() < new Date(data?.awalVote).getDate()
}
label={item?.value}
value={item?.id}
/>
</View>
))}
</RadioGroup>
</StackCustom>
<ButtonCustom disabled={value === ""} onPress={handlerSubmitVote}>
<ButtonCustom
disabled={value === ""}
onPress={() => {
AlertDefaultSystem({
title: "Anda melaukan voting",
message: "Yakin dengan pilihan anda ini ?",
textLeft: "Batal",
textRight: "Ya",
onPressRight: () => handlerSubmitVote(),
});
}}
>
Vote
</ButtonCustom>
</>

View File

@@ -0,0 +1,71 @@
import { apiConfig } from "../api-config";
export async function apiCollaborationCreate({ data }: { data: any }) {
try {
const response = await apiConfig.post(`/mobile/collaboration`, {
data: data,
});
return response.data;
} catch (error) {
throw error;
}
}
export async function apiCollaborationGetAll() {
try {
const response = await apiConfig.get(`/mobile/collaboration`);
return response.data;
} catch (error) {
throw error;
}
}
export async function apiCollaborationGetOne({ id }: { id: string }) {
try {
const response = await apiConfig.get(`/mobile/collaboration/${id}`);
return response.data;
} catch (error) {
throw error;
}
}
export async function apiCollaborationCreatePartisipasi({
id,
data,
}: {
id: string;
data: any;
}) {
try {
const response = await apiConfig.post(
`/mobile/collaboration/${id}/participants`,
{
data: data,
}
);
return response.data;
} catch (error) {
throw error;
}
}
export async function apiCollaborationGetParticipants({
id,
category,
authorId,
}: {
id: string;
category: "list" | "check-participant";
authorId?: string;
}) {
try {
const authorQuery = authorId ? `&authorId=${authorId}` : "";
const response = await apiConfig.get(
`/mobile/collaboration/${id}/participants?category=${category}${authorQuery}`
);
return response.data;
} catch (error) {
throw error;
}
}

View File

@@ -28,4 +28,13 @@ export async function apiMasterEventType() {
} catch (error) {
throw error;
}
}
}
export async function apiMasterCollaborationType() {
try {
const response = await apiConfig.get(`/mobile/master/collaboration-industry`);
return response.data;
} catch (error) {
throw error;
}
}

View File

@@ -62,12 +62,15 @@ export async function apiVotingDelete({ id }: { id: string }) {
export async function apiVotingUpdateData({
id,
data,
category,
}: {
id: string;
data: any;
category: "edit" | "archive";
}) {
const categoryQuery = `?category=${category}`;
try {
const response = await apiConfig.put(`/mobile/voting/${id}`, {
const response = await apiConfig.put(`/mobile/voting/${id}${categoryQuery}`, {
data: data,
});
return response.data;
@@ -76,10 +79,12 @@ export async function apiVotingUpdateData({
}
}
export async function apiVotingGetAll({ search }: { search: string }) {
export async function apiVotingGetAll({ search, category, authorId }: { search?: string, category: "beranda" | "contribution" | "all-history" | "my-history", authorId?: string }) {
try {
const searchQuery = search ? `?search=${search}` : "";
const response = await apiConfig.get(`/mobile/voting${searchQuery}`);
const categoryQuery = category ? `?category=${category}` : "";
const searchQuery = search ? `&search=${search}` : "";
const authorIdQuery = authorId ? `&authorId=${authorId}` : "";
const response = await apiConfig.get(`/mobile/voting${categoryQuery}${searchQuery}${authorIdQuery}`);
return response.data;
} catch (error) {
throw error;
@@ -97,18 +102,23 @@ export async function apiVotingVote({ id, data }: { id: string; data: any }) {
}
}
export async function apiVotingCheckContribution({
export async function apiVotingContribution({
id,
authorId,
category,
}: {
id: string;
authorId: string;
category: "list" | "checked";
}) {
const query =
category === "list"
? "?category=list"
: `?category=checked&authorId=${authorId}`;
try {
const response = await apiConfig.get(
`/mobile/voting/${id}/contribution?authorId=${authorId}`
`/mobile/voting/${id}/contribution${query}`
);
console.log("[DATA CONTRIBUION]", response.data);
return response.data;
} catch (error) {
throw error;

View File

@@ -1,5 +1,6 @@
import dayjs from "dayjs";
export const today = new Date();
export const dateTimeView = ({
date,
withoutTime = false,