upd: redesign

Deskripsi:
- fitur ganti mode tema
- penerapan tema pada semua fitur

NO Issues
This commit is contained in:
2026-02-09 17:49:25 +08:00
parent ddfee00410
commit d3802ca26c
157 changed files with 1278 additions and 692 deletions

View File

@@ -18,6 +18,7 @@ import Styles from "@/constants/Styles";
import { apiDeleteDiscussionGeneralCommentar, apiGetDiscussionGeneralOne, apiSendDiscussionGeneralCommentar, apiUpdateDiscussionGeneralCommentar } from "@/lib/api";
import { getDB } from "@/lib/firebaseDatabase";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Feather, Ionicons, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
import { ref } from '@react-native-firebase/database';
import { useHeaderHeight } from '@react-navigation/elements';
@@ -56,6 +57,7 @@ type PropsFile = {
export default function DetailDiscussionGeneral() {
const { token, decryptToken } = useAuthSession()
const { colors } = useTheme();
const entityUser = useSelector((state: any) => state.user)
const entities = useSelector((state: any) => state.entities)
const { id } = useLocalSearchParams<{ id: string }>();
@@ -237,14 +239,15 @@ export default function DetailDiscussionGeneral() {
)
}}
/>
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: colors.background }}>
<ScrollView
showsVerticalScrollIndicator={false}
style={[Styles.h100]}
style={[Styles.h100, { backgroundColor: colors.background }]}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={() => handleRefresh()}
tintColor={colors.primary}
/>
}
>
@@ -333,7 +336,7 @@ export default function DetailDiscussionGeneral() {
<View style={[
Styles.contentItemCenter,
Styles.w100,
{ backgroundColor: "#f4f4f4" },
{ backgroundColor: colors.card },
viewEdit && Styles.borderTop
]}>
{
@@ -341,11 +344,11 @@ export default function DetailDiscussionGeneral() {
<>
<View style={[Styles.w90, Styles.rowSpaceBetween, Styles.pv05]}>
<View style={[Styles.rowItemsCenter]}>
<Feather name="edit-3" color="black" size={22} style={[Styles.mh05]} />
<Feather name="edit-3" color={colors.text} size={22} style={[Styles.mh05]} />
<Text style={[Styles.textMediumSemiBold]}>Edit Komentar</Text>
</View>
<Pressable onPress={() => handleViewEditKomentar()}>
<MaterialIcons name="close" color="black" size={22} />
<MaterialIcons name="close" color={colors.text} size={22} />
</Pressable>
</View>
<InputForm
@@ -415,12 +418,12 @@ export default function DetailDiscussionGeneral() {
<DrawerBottom animation="slide" isVisible={isVisible} setVisible={setVisible} title="Komentar">
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<MaterialCommunityIcons name="pencil-outline" color="black" size={25} />}
icon={<MaterialCommunityIcons name="pencil-outline" color={colors.text} size={25} />}
title="Edit"
onPress={() => { handleViewEditKomentar() }}
/>
<MenuItemRow
icon={<MaterialIcons name="delete" color="black" size={25} />}
icon={<MaterialIcons name="delete" color={colors.text} size={25} />}
title="Hapus"
onPress={() => {
AlertKonfirmasi({

View File

@@ -9,6 +9,7 @@ import Styles from "@/constants/Styles";
import { apiAddMemberDiscussionGeneral, apiGetDiscussionGeneralOne, apiGetUser } from "@/lib/api";
import { setUpdateDiscussionGeneralDetail } from "@/lib/discussionGeneralDetail";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { AntDesign } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
@@ -26,6 +27,7 @@ export default function AddMemberDiscussionDetail() {
const dispatch = useDispatch()
const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
const { token, decryptToken } = useAuthSession()
const { colors } = useTheme();
const { id } = useLocalSearchParams<{ id: string }>()
const [dataOld, setDataOld] = useState<Props[]>([])
const [data, setData] = useState<Props[]>([])
@@ -125,7 +127,7 @@ export default function AddMemberDiscussionDetail() {
)
}}
/>
<View style={[Styles.p15]}>
<View style={[Styles.p15, { backgroundColor: colors.background }]}>
<InputSearch onChange={setSearch} value={search} />
{
@@ -175,7 +177,7 @@ export default function AddMemberDiscussionDetail() {
</View>
</View>
{
selectMember.some((i: any) => i.idUser == item.id) && <AntDesign name="check" size={20} color={'black'} />
selectMember.some((i: any) => i.idUser == item.id) && <AntDesign name="check" size={20} color={colors.text} />
}
</Pressable>
)

View File

@@ -16,6 +16,7 @@ import { apiCreateDiscussionGeneral } from "@/lib/api";
import { setUpdateDiscussionGeneralDetail } from "@/lib/discussionGeneralDetail";
import { setMemberChoose } from "@/lib/memberChoose";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import * as DocumentPicker from "expo-document-picker";
import { router, Stack } from "expo-router";
@@ -27,6 +28,7 @@ import { useDispatch, useSelector } from "react-redux";
export default function CreateDiscussionGeneral() {
const { token, decryptToken } = useAuthSession()
const { colors } = useTheme();
const entityUser = useSelector((state: any) => state.user);
const userLogin = useSelector((state: any) => state.entities)
const [chooseGroup, setChooseGroup] = useState({ val: "", label: "" });
@@ -163,7 +165,7 @@ export default function CreateDiscussionGeneral() {
}
return (
<SafeAreaView>
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
<Stack.Screen
options={{
// headerLeft: () => (
@@ -205,7 +207,7 @@ export default function CreateDiscussionGeneral() {
}}
/>
<LoadingOverlay visible={loading} />
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100, { backgroundColor: colors.background }]}>
<View style={[Styles.p15, Styles.mb100]}>
{
(entityUser.role == "supadmin" ||
@@ -215,6 +217,7 @@ export default function CreateDiscussionGeneral() {
placeholder="Pilih Lembaga Desa"
value={chooseGroup.label}
required
bg={colors.card}
onPress={() => {
setValChoose(chooseGroup.val);
setValSelect("group");
@@ -231,6 +234,7 @@ export default function CreateDiscussionGeneral() {
placeholder="Judul"
required
error={error.title}
bg={colors.card}
errorText="Judul tidak boleh kosong"
onChange={(val) => { validationForm("title", val) }}
/>
@@ -240,6 +244,7 @@ export default function CreateDiscussionGeneral() {
placeholder="Hal yang didiskusikan"
required
error={error.desc}
bg={colors.card}
errorText="Diskusi tidak boleh kosong"
onChange={(val) => { validationForm("desc", val) }}
multiline
@@ -248,14 +253,14 @@ export default function CreateDiscussionGeneral() {
{
fileForm.length > 0
&&
<View style={[Styles.borderAll, Styles.round10, Styles.p10, Styles.mb10]}>
<View style={[Styles.borderAll, Styles.round10, Styles.p10, Styles.mb10, { borderColor: colors.icon }]}>
<Text style={[Styles.textDefaultSemiBold]}>File</Text>
{
fileForm.map((item, index) => (
<BorderBottomItem
key={index}
borderType={fileForm.length > 1 ? "bottom" : "none"}
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
icon={<MaterialCommunityIcons name="file-outline" size={25} color={colors.text} />}
title={item.name}
titleWeight="normal"
onPress={() => { setIndexDelFile(index); setModalFile(true) }}
@@ -291,7 +296,7 @@ export default function CreateDiscussionGeneral() {
<Text>Total {entitiesMember.length} Anggota</Text>
</View>
<View style={[Styles.borderAll, Styles.round10, Styles.p10]}>
<View style={[Styles.borderAll, Styles.round10, Styles.p10, { borderColor: colors.icon }]}>
{
entitiesMember.map((item: { img: any; name: any; }, index: any) => {
return (
@@ -327,7 +332,7 @@ export default function CreateDiscussionGeneral() {
<DrawerBottom animation="slide" isVisible={isModalFile} setVisible={setModalFile} title="Menu">
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
icon={<Ionicons name="trash" color={colors.text} size={25} />}
title="Hapus"
onPress={() => { deleteFile(indexDelFile) }}
/>

View File

@@ -11,6 +11,7 @@ import Styles from "@/constants/Styles";
import { apiEditDiscussionGeneral, apiGetDiscussionGeneralOne } from "@/lib/api";
import { setUpdateDiscussionGeneralDetail } from "@/lib/discussionGeneralDetail";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import * as DocumentPicker from "expo-document-picker";
import { router, Stack, useLocalSearchParams } from "expo-router";
@@ -21,6 +22,7 @@ import { useDispatch, useSelector } from "react-redux";
export default function EditDiscussionGeneral() {
const { token, decryptToken } = useAuthSession();
const { colors } = useTheme();
const { id } = useLocalSearchParams<{ id: string }>();
const [disableBtn, setDisableBtn] = useState(false)
const dispatch = useDispatch()
@@ -162,7 +164,7 @@ export default function EditDiscussionGeneral() {
}
return (
<SafeAreaView>
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
<Stack.Screen
options={{
// headerLeft: () => (
@@ -198,13 +200,14 @@ export default function EditDiscussionGeneral() {
}}
/>
<LoadingOverlay visible={loading} />
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100, { backgroundColor: colors.background }]}>
<View style={[Styles.p15]}>
<InputForm
label="Judul"
type="default"
placeholder="Judul"
required
bg={colors.card}
error={error.title}
value={dataForm.title}
errorText="Judul tidak boleh kosong"
@@ -215,6 +218,7 @@ export default function EditDiscussionGeneral() {
type="default"
placeholder="Hal yang didiskusikan"
required
bg={colors.card}
error={error.desc}
value={dataForm.desc}
errorText="Diskusi tidak boleh kosong"
@@ -225,14 +229,14 @@ export default function EditDiscussionGeneral() {
{
(fileForm.length > 0 || dataFile.filter((val) => !val.delete).length > 0)
&&
<View style={[Styles.borderAll, Styles.round10, Styles.p10, Styles.mb10]}>
<View style={[Styles.borderAll, Styles.round10, Styles.p10, Styles.mb10, { borderColor: colors.icon }]}>
<Text style={[Styles.textDefaultSemiBold]}>File</Text>
{
dataFile.filter((val) => !val.delete).map((item, index) => (
<BorderBottomItem
key={index}
borderType={(fileForm.length + dataFile.length) > 1 ? "bottom" : "none"}
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
icon={<MaterialCommunityIcons name="file-outline" size={25} color={colors.text} />}
title={item.name + '.' + item.extension}
titleWeight="normal"
onPress={() => { setIndexDelFile({ id: item.id, cat: "oldFile" }); setModalFile(true) }}
@@ -244,7 +248,7 @@ export default function EditDiscussionGeneral() {
<BorderBottomItem
key={index}
borderType={(fileForm.length + dataFile.length) > 1 ? "bottom" : "none"}
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
icon={<MaterialCommunityIcons name="file-outline" size={25} color={colors.text} />}
title={item.name}
titleWeight="normal"
onPress={() => { setIndexDelFile({ id: index, cat: "newFile" }); setModalFile(true) }}
@@ -259,7 +263,7 @@ export default function EditDiscussionGeneral() {
<DrawerBottom animation="slide" isVisible={isModalFile} setVisible={setModalFile} title="Menu">
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
icon={<Ionicons name="trash" color={colors.text} size={25} />}
title="Hapus"
onPress={() => { deleteFile(indexDelFile.id, indexDelFile.cat) }}
/>

View File

@@ -8,6 +8,7 @@ import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { apiGetDiscussionGeneral } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { AntDesign, Feather, Ionicons, MaterialIcons } from "@expo/vector-icons";
import { router, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
@@ -27,6 +28,7 @@ type Props = {
export default function Discussion() {
const entityUser = useSelector((state: any) => state.user)
const { token, decryptToken } = useAuthSession()
const { colors } = useTheme();
const { active, group } = useLocalSearchParams<{ active?: string, group?: string }>()
const [search, setSearch] = useState('')
const [nameGroup, setNameGroup] = useState('')
@@ -96,24 +98,24 @@ export default function Discussion() {
})
return (
<View style={[Styles.p15, { flex: 1 }]}>
<View style={[Styles.p15, { flex: 1, backgroundColor: colors.background }]}>
<View>
{
entityUser.role != "user" && entityUser.role != "coadmin" &&
<View style={[Styles.wrapBtnTab]}>
<View style={[Styles.wrapBtnTab, { backgroundColor: colors.card }]}>
<ButtonTab
active={status == "false" ? "false" : "true"}
value="true"
onPress={() => { setStatus("true") }}
label="Aktif"
icon={<Feather name="check-circle" color={status == "false" ? 'black' : 'white'} size={20} />}
icon={<Feather name="check-circle" color={status == "false" ? colors.text : 'white'} size={20} />}
n={2} />
<ButtonTab
active={status == "false" ? "false" : "true"}
value="false"
onPress={() => { setStatus("false") }}
label="Arsip"
icon={<AntDesign name="closecircleo" color={status == "true" ? 'black' : 'white'} size={20} />}
icon={<AntDesign name="closecircleo" color={status == "true" ? colors.text : 'white'} size={20} />}
n={2} />
</View>
}
@@ -178,6 +180,7 @@ export default function Discussion() {
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
tintColor={colors.primary}
/>
}
/>

View File

@@ -11,6 +11,7 @@ import { ConstEnv } from "@/constants/ConstEnv";
import Styles from "@/constants/Styles";
import { apiDeleteMemberDiscussionGeneral, apiGetDiscussionGeneralOne } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Feather, MaterialCommunityIcons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
@@ -26,6 +27,7 @@ type Props = {
export default function MemberDiscussionDetail() {
const { token, decryptToken } = useAuthSession()
const { colors } = useTheme();
const entityUser = useSelector((state: any) => state.user)
const { id } = useLocalSearchParams<{ id: string }>()
const [data, setData] = useState<Props[]>([])
@@ -71,7 +73,7 @@ export default function MemberDiscussionDetail() {
}
return (
<SafeAreaView>
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
<Stack.Screen
options={{
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
@@ -86,10 +88,10 @@ export default function MemberDiscussionDetail() {
)
}}
/>
<ScrollView>
<ScrollView style={{ backgroundColor: colors.background }}>
<View style={[Styles.p15]}>
<Text style={[Styles.textDefault, Styles.mv05]}>{data.length} Anggota</Text>
<View style={[Styles.wrapPaper, Styles.mb100]}>
<View style={[Styles.wrapPaper, { backgroundColor: colors.card, borderColor: colors.background }]}>
{
entityUser.role != "user" && entityUser.role != "coadmin" &&
<BorderBottomItem
@@ -135,7 +137,7 @@ export default function MemberDiscussionDetail() {
<DrawerBottom animation="slide" isVisible={isModal} setVisible={setModal} title={chooseUser.name}>
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<MaterialCommunityIcons name="account-eye" color="black" size={25} />}
icon={<MaterialCommunityIcons name="account-eye" color={colors.text} size={25} />}
title="Lihat Profil"
onPress={() => {
setModal(false)
@@ -145,7 +147,7 @@ export default function MemberDiscussionDetail() {
{
entityUser.role != "user" && entityUser.role != "coadmin" &&
<MenuItemRow
icon={<MaterialCommunityIcons name="account-remove" color="black" size={25} />}
icon={<MaterialCommunityIcons name="account-remove" color={colors.text} size={25} />}
title="Keluarkan"
onPress={() => {
setModal(false)