Add:
- BoxDetailContribution
- app/(application)/(user)/voting/[id]/contribution.tsx

Fix:
- app/(application)/(user)/voting/(tabs)/contribution.tsx
- app/(application)/(user)/voting/[id]/[status]/detail.tsx
- app/(application)/(user)/voting/[id]/list-of-contributor.tsx
- app/(application)/(user)/voting/[id]/index.tsx

# No Issue
This commit is contained in:
2025-07-28 17:29:52 +08:00
parent 4bcfcb5f5a
commit c9a1ac1db5
9 changed files with 246 additions and 81 deletions

View File

@@ -165,13 +165,6 @@ export default function UserLayout() {
headerLeft: () => <BackButton path="/home" />,
}}
/>
<Stack.Screen
name="voting/[id]/index"
options={{
title: "Detail Voting",
headerLeft: () => <BackButton />,
}}
/>
<Stack.Screen
name="voting/[id]/edit"
options={{

View File

@@ -1,25 +1,15 @@
import {
BadgeCustom,
StackCustom,
TextCustom,
ViewWrapper,
ViewWrapper
} from "@/components";
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
import { GStyles } from "@/styles/global-styles";
export default function VotingContribution() {
const bottomComponent = (
<StackCustom>
<TextCustom align="center">Pilihan Anda:</TextCustom>
<BadgeCustom style={[GStyles.alignSelfCenter]}>Pilihan 1</BadgeCustom>
</StackCustom>
);
return (
<ViewWrapper hideFooter>
{Array.from({ length: 5 }).map((_, index) => (
<Voting_BoxPublishSection
key={index}
bottomComponent={bottomComponent}
href={`/voting/${index}/contribution`}
/>
))}
</ViewWrapper>

View File

@@ -1,19 +1,16 @@
import {
AlertDefaultSystem,
BackButton,
DotButton,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
AlertDefaultSystem,
BackButton,
DotButton,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
} from "@/components";
import { IconArchive, IconEdit } from "@/components/_Icon";
import { IconArchive, IconContribution, IconEdit } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
import { Voting_BoxDetailSection } from "@/screens/Voting/BoxDetailSection";
import Voting_ButtonStatusSection from "@/screens/Voting/ButtonStatusSection";
import { Ionicons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useState } from "react";
@@ -44,7 +41,6 @@ export default function VotingDetailStatus() {
router.navigate(item.path as any);
setOpenDrawerPublish(false);
};
return (
<>
@@ -66,6 +62,7 @@ export default function VotingDetailStatus() {
<Spacing />
</ViewWrapper>
{/* ========= Draft Drawer ========= */}
<DrawerCustom
isVisible={openDrawerDraft}
closeDrawer={() => setOpenDrawerDraft(false)}
@@ -84,6 +81,7 @@ export default function VotingDetailStatus() {
/>
</DrawerCustom>
{/* ========= Publish Drawer ========= */}
<DrawerCustom
isVisible={openDrawerPublish}
closeDrawer={() => setOpenDrawerPublish(false)}
@@ -92,13 +90,7 @@ export default function VotingDetailStatus() {
<MenuDrawerDynamicGrid
data={[
{
icon: (
<Ionicons
name="people"
size={ICON_SIZE_SMALL}
color={MainColor.white}
/>
),
icon: <IconContribution />,
label: "Daftar Kontributor",
path: `/voting/${id}/list-of-contributor`,
},

View File

@@ -0,0 +1,65 @@
import {
AvatarUsernameAndOtherComponent,
BackButton,
DotButton,
DrawerCustom,
MenuDrawerDynamicGrid,
Spacing,
ViewWrapper,
} from "@/components";
import { IconContribution } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { Voting_BoxDetailContributionSection } from "@/screens/Voting/BoxDetailContribution";
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useState } from "react";
export default function VotingDetailContribution() {
const { id } = useLocalSearchParams();
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const handlePressPublish = (item: IMenuDrawerItem) => {
router.navigate(item.path as any);
setOpenDrawerPublish(false);
};
return (
<>
<Stack.Screen
options={{
title: "Detail Kontribusi",
headerLeft: () => <BackButton />,
headerRight: () => (
<DotButton onPress={() => setOpenDrawerPublish(true)} />
),
}}
/>
<ViewWrapper>
<Voting_BoxDetailContributionSection
headerAvatar={<AvatarUsernameAndOtherComponent />}
/>
<Voting_BoxDetailHasilVotingSection />
<Spacing />
</ViewWrapper>
{/* ========= Publish Drawer ========= */}
<DrawerCustom
isVisible={openDrawerPublish}
closeDrawer={() => setOpenDrawerPublish(false)}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: <IconContribution />,
label: "Daftar Kontributor",
path: `/voting/${id}/list-of-contributor`,
},
]}
onPressItem={handlePressPublish as any}
/>
</DrawerCustom>
</>
);
}

View File

@@ -1,25 +1,87 @@
import {
AvatarUsernameAndOtherComponent,
InformationBox,
StackCustom,
ViewWrapper
AlertDefaultSystem,
AvatarUsernameAndOtherComponent,
BackButton,
DotButton,
DrawerCustom,
InformationBox,
MenuDrawerDynamicGrid,
StackCustom,
ViewWrapper,
} from "@/components";
import { IconArchive, IconContribution } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
import { Voting_BoxDetailPublishSection } from "@/screens/Voting/BoxDetailPublishSection";
import React from "react";
import { router, Stack, useLocalSearchParams } from "expo-router";
import React, { useState } from "react";
export default function VotingDetail() {
const { id } = useLocalSearchParams();
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const handlePressPublish = (item: IMenuDrawerItem) => {
if (item.path === "") {
AlertDefaultSystem({
title: "Update Arsip",
message: "Apakah Anda yakin ingin mengarsipkan voting ini?",
textLeft: "Batal",
textRight: "Ya",
onPressRight: () => {
console.log("Hapus");
router.back();
},
});
}
router.navigate(item.path as any);
setOpenDrawerPublish(false);
};
return (
<ViewWrapper>
<StackCustom>
<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." />
<>
<Stack.Screen
options={{
title: `Detail Voting`,
headerLeft: () => <BackButton />,
headerRight: () => (
<DotButton onPress={() => setOpenDrawerPublish(true)} />
),
}}
/>
<Voting_BoxDetailPublishSection
headerAvatar={<AvatarUsernameAndOtherComponent />}
<ViewWrapper>
<StackCustom>
<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." />
<Voting_BoxDetailPublishSection
headerAvatar={<AvatarUsernameAndOtherComponent />}
/>
<Voting_BoxDetailHasilVotingSection />
</StackCustom>
</ViewWrapper>
{/* ========= Publish Drawer ========= */}
<DrawerCustom
isVisible={openDrawerPublish}
closeDrawer={() => setOpenDrawerPublish(false)}
height={"auto"}
>
<MenuDrawerDynamicGrid
data={[
{
icon: <IconContribution />,
label: "Daftar Kontributor",
path: `/voting/${id}/list-of-contributor`,
},
{
icon: <IconArchive />,
label: "Update Arsip",
path: "" as any,
},
]}
onPressItem={handlePressPublish as any}
/>
<Voting_BoxDetailHasilVotingSection />
</StackCustom>
</ViewWrapper>
</DrawerCustom>
</>
);
}

View File

@@ -1,15 +1,24 @@
import {
AvatarUsernameAndOtherComponent,
BaseBox,
ViewWrapper
AvatarUsernameAndOtherComponent,
BadgeCustom,
BaseBox,
ViewWrapper,
} from "@/components";
export default function Voting_ListOfContributor() {
return (
<ViewWrapper>
{Array.from({ length: 10 }).map((_, index) => (
<BaseBox key={index.toString()}>
<AvatarUsernameAndOtherComponent />
<BaseBox paddingTop={5} paddingBottom={5} key={index.toString()}>
<AvatarUsernameAndOtherComponent
rightComponent={
<BadgeCustom
style={{alignSelf: "flex-end" }}
>
Pilihan {index + 1}
</BadgeCustom>
}
/>
</BaseBox>
))}
</ViewWrapper>

View File

@@ -6,7 +6,7 @@ export default function IconContribution({ color }: { color?: string }) {
<>
<Ionicons
size={ICON_SIZE_SMALL}
name="extension-puzzle"
name="people"
color={color || "white"}
/>
</>

View File

@@ -1,8 +1,8 @@
import { ImageSourcePropType, View } from "react-native";
import { ImageSourcePropType } from "react-native";
import Divider from "../Divider/Divider";
import Grid from "../Grid/GridCustom";
import AvatarCustom from "../Image/AvatarCustom";
import TextCustom from "../Text/TextCustom";
import Divider from "../Divider/Divider"
const AvatarUsernameAndOtherComponent = ({
avatarHref,
@@ -19,30 +19,28 @@ const AvatarUsernameAndOtherComponent = ({
}) => {
return (
<>
<Grid containerStyle={{ zIndex: 10 }}>
<Grid.Col span={2}>
<AvatarCustom source={avatar} href={avatarHref as any} />
</Grid.Col>
<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={rightComponent ? 6 : 10}
style={{ justifyContent: "center" }}
span={4}
style={{ alignItems: "flex-end", justifyContent: "center" }}
>
<TextCustom truncate bold>
{name || "Username"}
</TextCustom>
{rightComponent}
</Grid.Col>
{rightComponent && (
<Grid.Col
span={4}
style={{ alignItems: "flex-end", justifyContent: "center" }}
>
{rightComponent}
</Grid.Col>
)}
</Grid>
{withBottomLine && <Divider marginTop={0} />}
<View>
</View>
)}
</Grid>
{withBottomLine && <Divider marginTop={0} />}
</>
);
};

View File

@@ -0,0 +1,56 @@
import {
BadgeCustom,
BoxWithHeaderSection,
Spacing,
StackCustom,
TextCustom,
} from "@/components";
import { GStyles } from "@/styles/global-styles";
import dayjs from "dayjs";
import { View } from "react-native";
export function Voting_BoxDetailContributionSection({
headerAvatar,
}: {
headerAvatar?: React.ReactNode;
}) {
return (
<>
<BoxWithHeaderSection>
{headerAvatar ? headerAvatar : <Spacing />}
<StackCustom gap={"lg"}>
<TextCustom align="center" bold size="large">
Title of Voting Here
</TextCustom>
<TextCustom>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Perspiciatis corporis blanditiis est provident corrupti facilis iste
cum voluptate. Natus eum aut quos consequatur doloribus fugiat sit
ullam minima non enim?
</TextCustom>
<View>
<TextCustom bold size="small" align="center">
Batas Voting
</TextCustom>
<BadgeCustom
style={[GStyles.alignSelfCenter, { width: "70%" }]}
variant="light"
>
{dayjs().format("DD/MM/YYYY")} -{" "}
{dayjs().add(1, "day").format("DD/MM/YYYY")}
</BadgeCustom>
</View>
<StackCustom gap={"xs"}>
<TextCustom bold size="small" align="center">
Pilihan Anda
</TextCustom>
<BadgeCustom style={[GStyles.alignSelfCenter]}>
Pilihan 1
</BadgeCustom>
</StackCustom>
</StackCustom>
</BoxWithHeaderSection>
</>
);
}