upd: ui home

Deskripsi:
- update package
- ui diskusi home
- ui event home
- ui bar chart home
- ui pie chart home
- ui divisi home

No Issues
This commit is contained in:
amel
2025-02-26 12:32:01 +08:00
parent 31b85dad69
commit 633b18e92d
19 changed files with 477 additions and 10 deletions

View File

@@ -1,7 +1,15 @@
import CaraouselHome from "@/components/home/carouselHome"; import CaraouselHome from "@/components/home/carouselHome";
import ChartDokumenHome from "@/components/home/chartDokumenHome";
import ChartProgresHome from "@/components/home/chartProgresHome";
import DisccussionHome from "@/components/home/discussionHome";
import DivisionHome from "@/components/home/divisionHome";
import EventHome from "@/components/home/eventHome";
import FiturHome from "@/components/home/fiturHome";
import { HeaderRightHome } from "@/components/home/headerRightHome"; import { HeaderRightHome } from "@/components/home/headerRightHome";
import ProjectHome from "@/components/home/projectHome";
import Styles from "@/constants/Styles";
import { Stack } from "expo-router"; import { Stack } from "expo-router";
import { SafeAreaView, ScrollView } from "react-native"; import { SafeAreaView, ScrollView, View } from "react-native";
export default function Home() { export default function Home() {
return ( return (
@@ -15,7 +23,16 @@ export default function Home() {
}} }}
/> />
<ScrollView> <ScrollView>
<CaraouselHome/> <CaraouselHome />
<View style={[Styles.ph15]}>
<FiturHome />
<ProjectHome />
<DivisionHome />
<ChartProgresHome />
<ChartDokumenHome />
<EventHome />
<DisccussionHome />
</View>
</ScrollView> </ScrollView>
</SafeAreaView> </SafeAreaView>
) )

BIN
bun.lockb

Binary file not shown.

View File

@@ -0,0 +1,22 @@
import Styles from "@/constants/Styles";
import React from "react";
import { Text, TouchableWithoutFeedback, View } from "react-native";
type Props = {
onPress?: () => void;
icon: React.ReactNode;
text: string;
};
export function ButtonFiturMenu({ onPress, icon, text }: Props) {
return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={{ alignItems: 'center' }}>
<View style={[Styles.btnFiturMenu]}>
{icon}
</View>
<Text style={[Styles.mt05]}>{text}</Text>
</View>
</TouchableWithoutFeedback>
)
}

View File

@@ -0,0 +1,30 @@
import Styles from "@/constants/Styles";
import { Ionicons, Feather } from "@expo/vector-icons";
import { Text, View } from "react-native";
type Props = {
title: string
user: string
date: string
}
export default function DiscussionItem({ title, user, date }: Props) {
return (
<View style={[Styles.wrapItemDiscussion]}>
<View style={[Styles.rowItemsCenter, Styles.mb10]}>
<Ionicons name="chatbox-ellipses-outline" size={22} color="black" style={Styles.mr10} />
<Text style={{ fontWeight: 'bold' }}>{title}</Text>
</View>
<View style={Styles.rowSpaceBetween}>
<View style={Styles.rowItemsCenter}>
<Feather name="user" size={18} color="grey" style={Styles.mr05} />
<Text style={[Styles.textInformation]}>{user}</Text>
</View>
<View style={Styles.rowItemsCenter}>
<Feather name="clock" size={18} color="grey" style={Styles.mr05} />
<Text style={[Styles.textInformation]}>{date}</Text>
</View>
</View>
</View>
)
}

23
components/eventItem.tsx Normal file
View File

@@ -0,0 +1,23 @@
import Styles from "@/constants/Styles"
import { Text, View } from "react-native"
type Props = {
category: 'purple' | 'orange'
title: string
user: string
jamAwal: string
jamAkhir: string
}
export default function EventItem({ category, title, user, jamAwal, jamAkhir }: Props) {
return (
<View style={[Styles.itemEvent, { backgroundColor: category == 'orange' ? '#FED6C5' : '#D8D8F1' }]}>
<View style={[Styles.dividerEvent, { backgroundColor: category == 'orange' ? '#FB804C' : '#535FCA' }]} />
<View>
<Text>{jamAwal} - {jamAkhir}</Text>
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>{title}</Text>
<Text>Dibuat oleh : {user}</Text>
</View>
</View>
)
}

View File

@@ -11,7 +11,7 @@ export default function CaraouselHome() {
const progress = useSharedValue<number>(0); const progress = useSharedValue<number>(0);
return ( return (
<View style={{ marginVertical: 20 }}> <View style={[Styles.mv15]}>
<Carousel <Carousel
ref={ref} ref={ref}
width={width} width={width}

View File

@@ -0,0 +1,39 @@
import Styles from "@/constants/Styles";
import { Dimensions, Text, View } from "react-native";
import { BarChart } from "react-native-gifted-charts";
export default function ChartDokumenHome() {
const barData = [
{ value: 23, label: 'Gambar', frontColor: '#fac858' },
{ value: 12, label: 'Dokumen', frontColor: '#92cc76' },
];
const width = Dimensions.get("window").width;
return (
<View style={[Styles.wrapPaper, Styles.contentItemCenter, Styles.mb15]}>
<Text style={[Styles.textSubtitle, Styles.mv15]}>JUMLAH DOKUMEN</Text>
<BarChart
showFractionalValues={false}
showYAxisIndices
noOfSections={4}
maxValue={25}
data={barData}
isAnimated
width={width - 140}
barWidth={width * 0.25}
renderTooltip={(item: any, index: any) => {
return (
<View
style={{
alignItems: 'center',
justifyContent: 'center',
width: width * 0.25
}}>
<Text>{item.value}</Text>
</View>
);
}}
/>
</View>
)
}

View File

@@ -0,0 +1,31 @@
import Styles from "@/constants/Styles";
import { Text, View } from "react-native";
import { PieChart } from "react-native-gifted-charts";
export default function ChartProgresHome() {
const pieData = [
{ value: 54, text: "54%", color: '#177AD5' },
{ value: 40, text: "40%", color: '#92cc76' },
{ value: 20, text: "20%", color: '#ED6665' },
{ value: 0, text: "0%", color: '#fac858' },
];
return (
<View style={[Styles.wrapPaper, Styles.contentItemCenter, Styles.mb15]}>
<Text style={[Styles.textSubtitle, Styles.mv15]}>PROGRES KEGIATAN</Text>
<PieChart
data={pieData}
showText
showValuesAsTooltipText
textColor="black"
radius={120}
textSize={15}
focusOnPress={false}
showValuesAsLabels
showTextBackground={false}
textBackgroundRadius={0}
isAnimated
/>
</View>
)
}

View File

@@ -0,0 +1,16 @@
import Styles from "@/constants/Styles";
import { Text, View } from "react-native";
import DiscussionItem from "../discussionItem";
export default function DisccussionHome() {
return (
<View style={[Styles.mb15]}>
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Diskusi</Text>
<View style={[Styles.wrapPaper]}>
<DiscussionItem title="Bagaimana cara mengatasi banjir?" user="Amalia" date="13 Februari 2025" />
<DiscussionItem title="Bagaimana cara mengatasi banjir?" user="Amalia" date="13 Februari 2025" />
<DiscussionItem title="Bagaimana cara mengatasi banjir?" user="Amalia" date="13 Februari 2025" />
</View>
</View>
)
}

View File

@@ -0,0 +1,38 @@
import Styles from "@/constants/Styles";
import React from "react";
import { Dimensions, Text, View } from "react-native";
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
import PaperGridContent from "../paperGridContent";
export default function DivisionHome() {
const data = [...new Array(6).keys()];
const ref = React.useRef<ICarouselInstance>(null);
const width = Dimensions.get("window").width;
return (
<View style={[Styles.mb15]}>
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Divisi Teraktif</Text>
<Carousel
ref={ref}
width={width}
height={235}
data={data}
loop={true}
autoPlay={false}
autoPlayReverse={false}
pagingEnabled={true}
snapEnabled={true}
vertical={false}
renderItem={({ index }) => (
<PaperGridContent content="carousel" title="Kesekretariatan" headerColor="warning">
<View>
<Text style={{ fontSize: 50, textAlign: "center", fontWeight: 'bold' }}>12</Text>
<Text style={[Styles.textSubtitle, { textAlign: "center" }]}>KEGIATAN</Text>
</View>
</PaperGridContent>
)}
/>
</View>
)
}

View File

@@ -0,0 +1,15 @@
import Styles from "@/constants/Styles";
import { Text, View } from "react-native";
import EventItem from "../eventItem";
export default function EventHome() {
return (
<View style={[Styles.mb15]}>
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Acara Hari Ini</Text>
<View style={[Styles.wrapPaper]}>
<EventItem category="purple" title="Meeting Pertama" user="Amalia" jamAwal="10.00" jamAkhir="11.00" />
<EventItem category="orange" title="Meeting Pertama" user="Amalia" jamAwal="10.00" jamAkhir="11.00" />
</View>
</View>
)
}

View File

@@ -1,3 +1,19 @@
export default function FiturHome(){ import Styles from "@/constants/Styles"
import { AntDesign, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons"
import React from "react"
import { Text, View } from "react-native"
import { ButtonFiturMenu } from "../buttonFiturMenu"
export default function FiturHome() {
return (
<View style={[Styles.mb15]}>
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Fitur</Text>
<View style={[Styles.rowSpaceBetween]}>
<ButtonFiturMenu icon={<MaterialIcons name="group" size={35} color="black" />} text="Divisi" />
<ButtonFiturMenu icon={<AntDesign name="areachart" size={35} color="black" />} text="Kegiatan" />
<ButtonFiturMenu icon={<MaterialIcons name="campaign" size={35} color="black" />} text="Pengumuman" />
<ButtonFiturMenu icon={<MaterialCommunityIcons name="view-grid" size={35} color="black" />} text="Semua" />
</View>
</View>
)
} }

View File

@@ -2,14 +2,11 @@ import { View } from "react-native"
import { router } from "expo-router" import { router } from "expo-router"
import Feather from '@expo/vector-icons/Feather'; import Feather from '@expo/vector-icons/Feather';
import { ButtonHeader } from "../buttonHeader"; import { ButtonHeader } from "../buttonHeader";
import Styles from "@/constants/Styles";
export function HeaderRightHome() { export function HeaderRightHome() {
return ( return (
<View style={{ <View style={[Styles.rowSpaceBetween, { width: 140 }]}>
flexDirection: 'row',
justifyContent: 'space-between',
width: 140,
}}>
<ButtonHeader item={<Feather name="search" size={20} color="white" />} onPress={() => { router.push('/') }} /> <ButtonHeader item={<Feather name="search" size={20} color="white" />} onPress={() => { router.push('/') }} />
<ButtonHeader item={<Feather name="bell" size={20} color="white" />} onPress={() => { router.push('/') }} /> <ButtonHeader item={<Feather name="bell" size={20} color="white" />} onPress={() => { router.push('/') }} />
<ButtonHeader item={<Feather name="user" size={20} color="white" />} onPress={() => { router.push('/') }} /> <ButtonHeader item={<Feather name="user" size={20} color="white" />} onPress={() => { router.push('/') }} />

View File

@@ -0,0 +1,42 @@
import Styles from "@/constants/Styles";
import React from "react";
import { Dimensions, Text, View } from "react-native";
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
import ProgressBar from "../progressBar";
import { ColorsStatus } from "@/constants/ColorsStatus";
import PaperGridContent from "../paperGridContent";
export default function ProjectHome() {
const data = [...new Array(6).keys()];
const ref = React.useRef<ICarouselInstance>(null);
const width = Dimensions.get("window").width;
return (
<View style={[Styles.mb15]}>
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Kegiatan Terupdate</Text>
<Carousel
ref={ref}
width={width}
height={235}
data={data}
loop={true}
autoPlay={false}
autoPlayReverse={false}
pagingEnabled={true}
snapEnabled={true}
vertical={false}
renderItem={({ index }) => (
<PaperGridContent content="carousel" title="Pembangunan Jembatan" headerColor="primary">
<ProgressBar />
<View style={[Styles.rowSpaceBetween]}>
<Text style={[Styles.textDefault, Styles.cGray]}>13 Februari 2025</Text>
<View style={[Styles.labelStatus, ColorsStatus.warning]}>
<Text style={[Styles.textMediumSemiBold, Styles.cWhite]}>DIKERJAKAN</Text>
</View>
</View>
</PaperGridContent>
)}
/>
</View>
)
}

View File

@@ -0,0 +1,23 @@
import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { Text, View } from "react-native";
import ProgressBar from "./progressBar";
type Props = {
content: 'carousel' | 'page';
children: React.ReactNode;
title: string
headerColor: 'primary' | 'warning'
};
export default function PaperGridContent({ content, children, title, headerColor }: Props) {
return (
<View style={[content == 'carousel' ? Styles.wrapGridCaraousel : Styles.wrapGridContent, headerColor == 'warning' ? ColorsStatus.warning : ColorsStatus.primary]}>
<View style={[Styles.headerPaperGrid]}>
<Text style={[Styles.textSubtitle, headerColor == 'warning' ? Styles.cDefault : Styles.cWhite]}>{title}</Text>
</View>
<View style={[Styles.contentPaperGrid]}>
{children}
</View>
</View>
)
}

View File

@@ -0,0 +1,23 @@
import Styles from "@/constants/Styles";
import { useEffect, useState } from "react";
import { Animated, Text, View } from "react-native";
export default function ProgressBar() {
const [progress, setProgress] = useState(new Animated.Value(0));
useEffect(() => {
Animated.timing(progress, {
// 100% = 255
toValue: 127.5,
duration: 1000,
useNativeDriver: false
}).start();
}, []);
return (
<View style={Styles.wrapBar}>
<Animated.View style={[Styles.contentBar, { width: progress }]} />
</View>
)
}

17
constants/ColorsStatus.ts Normal file
View File

@@ -0,0 +1,17 @@
export const ColorsStatus = {
primary: {
backgroundColor: '#19345E'
},
success: {
backgroundColor: 'green'
},
info: {
backgroundColor: 'blue'
},
warning: {
backgroundColor: '#FCAA4B'
},
error: {
backgroundColor: '#DB1514'
}
}

View File

@@ -56,20 +56,64 @@ const Styles = StyleSheet.create({
cDefault: { cDefault: {
color: '#19345E' color: '#19345E'
}, },
mb05: {
marginBottom: 5
},
mb10: {
marginBottom: 10
},
mb15: { mb15: {
marginBottom: 15 marginBottom: 15
}, },
mb30: { mb30: {
marginBottom: 30 marginBottom: 30
}, },
mv05: {
marginVertical: 5
},
mv15: {
marginVertical: 15
},
mv10: {
marginVertical: 10
},
mt05: {
marginTop: 5
},
mr05:{
marginRight: 5
},
mr10: {
marginRight: 10
},
ph15: {
paddingHorizontal: 15,
},
round30: { round30: {
borderRadius: 30 borderRadius: 30
}, },
labelStatus: {
paddingHorizontal: 15,
borderRadius: 10
},
rowSpaceBetween: {
justifyContent: 'space-between',
flexDirection: 'row'
},
rowItemsCenter: {
flexDirection: 'row',
alignItems: 'center'
},
btnIconHeader: { btnIconHeader: {
backgroundColor: '#384288', backgroundColor: '#384288',
padding: 7, padding: 7,
borderRadius: 100, borderRadius: 100,
}, },
btnFiturMenu: {
backgroundColor: '#FCAA4B',
padding: 10,
borderRadius: 100,
},
btnRound: { btnRound: {
backgroundColor: '#19345E', backgroundColor: '#19345E',
borderWidth: 0, borderWidth: 0,
@@ -118,6 +162,77 @@ const Styles = StyleSheet.create({
borderRadius: 15, borderRadius: 15,
backgroundColor: '#19345E', backgroundColor: '#19345E',
display: 'flex', display: 'flex',
},
wrapGridContent: {
shadowColor: '#171717',
shadowOffset: { width: -2, height: 4 },
shadowOpacity: 0.2,
shadowRadius: 3,
elevation: 10,
borderRadius: 15,
},
wrapGridCaraousel: {
width: '80%',
height: 200,
shadowColor: '#171717',
shadowOffset: { width: -2, height: 4 },
shadowOpacity: 0.2,
shadowRadius: 3,
elevation: 10,
borderRadius: 15,
},
headerPaperGrid: {
paddingVertical: 25,
alignItems: 'center',
borderTopStartRadius: 15,
borderTopEndRadius: 15
},
contentPaperGrid: {
backgroundColor: 'white',
height: 150,
borderBottomEndRadius: 15,
borderBottomStartRadius: 15,
paddingHorizontal: 20,
justifyContent: 'space-evenly'
},
wrapBar: {
height: 20,
backgroundColor: '#ccc',
borderRadius: 10,
margin: 10,
},
contentBar: {
height: 20,
backgroundColor: 'orange',
borderRadius: 10,
},
wrapPaper: {
padding: 15,
backgroundColor: 'white',
borderRadius: 15,
},
contentItemCenter: {
justifyContent: 'center',
alignItems: 'center'
},
itemEvent: {
padding: 10,
borderRadius: 10,
flexDirection: 'row',
alignContent: 'stretch',
marginBottom: 10
},
dividerEvent: {
width: 7,
borderRadius: 5,
marginRight: 10
},
wrapItemDiscussion: {
padding: 10,
borderRadius: 10,
borderColor: '#d6d8f6',
borderWidth: 1,
marginBottom: 10
} }
}) })

View File

@@ -23,6 +23,7 @@
"expo-constants": "~17.0.7", "expo-constants": "~17.0.7",
"expo-font": "~13.0.4", "expo-font": "~13.0.4",
"expo-haptics": "~14.0.1", "expo-haptics": "~14.0.1",
"expo-linear-gradient": "~14.0.2",
"expo-linking": "~7.0.5", "expo-linking": "~7.0.5",
"expo-router": "~4.0.17", "expo-router": "~4.0.17",
"expo-splash-screen": "~0.29.22", "expo-splash-screen": "~0.29.22",
@@ -35,10 +36,12 @@
"react-native": "0.76.7", "react-native": "0.76.7",
"react-native-confirmation-code-field": "^7.4.0", "react-native-confirmation-code-field": "^7.4.0",
"react-native-gesture-handler": "~2.20.2", "react-native-gesture-handler": "~2.20.2",
"react-native-gifted-charts": "^1.4.57",
"react-native-reanimated": "~3.16.1", "react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "^4.0.2", "react-native-reanimated-carousel": "^4.0.2",
"react-native-safe-area-context": "4.12.0", "react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.4.0", "react-native-screens": "~4.4.0",
"react-native-svg": "15.8.0",
"react-native-web": "~0.19.13", "react-native-web": "~0.19.13",
"react-native-webview": "13.12.5" "react-native-webview": "13.12.5"
}, },