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

@@ -10,6 +10,7 @@ import { ConstEnv } from "@/constants/ConstEnv";
import { valueRoleUser } from "@/constants/RoleUser";
import Styles from "@/constants/Styles";
import { apiGetProfile } from "@/lib/api";
import { useTheme } from "@/providers/ThemeProvider";
import { router, Stack, useLocalSearchParams } from "expo-router";
import React, { useEffect, useState } from "react";
import { Pressable, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
@@ -33,6 +34,7 @@ type Props = {
export default function MemberDetail() {
const { id } = useLocalSearchParams<{ id: string }>();
const { colors } = useTheme();
const [data, setData] = useState<Props>()
const [errorImg, setErrorImg] = useState(false)
const entityUser = useSelector((state: any) => state.user)
@@ -74,13 +76,11 @@ export default function MemberDetail() {
};
return (
<SafeAreaView>
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
<Stack.Screen
options={{
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Anggota',
headerTitleAlign: 'center',
// headerRight: () => (entityUser.role != "user") && isEdit ? <HeaderRightMemberDetail active={data?.isActive} id={id} /> : <></>,
header: () => (
<AppHeader title="Anggota"
showBack={true}
@@ -93,11 +93,12 @@ export default function MemberDetail() {
}}
/>
<ScrollView
style={[Styles.h100]}
style={[Styles.h100, { backgroundColor: colors.background }]}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
tintColor={colors.text}
/>
}
>
@@ -122,7 +123,7 @@ export default function MemberDetail() {
</View>
<View style={[Styles.p15]}>
<View style={[Styles.rowSpaceBetween]}>
<Text style={[Styles.textDefaultSemiBold]}>Informasi</Text>
<Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>Informasi</Text>
<LabelStatus
size="small"
category={data?.isActive ? 'success' : 'error'}

View File

@@ -10,6 +10,7 @@ import { apiCreateUser } from "@/lib/api";
import { validateName } from "@/lib/fun_validateName";
import { setUpdateMember } from "@/lib/memberSlice";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useHeaderHeight } from '@react-navigation/elements';
import * as ImagePicker from "expo-image-picker";
@@ -32,6 +33,7 @@ export default function CreateMember() {
const dispatch = useDispatch()
const update = useSelector((state: any) => state.memberUpdate)
const { token, decryptToken } = useAuthSession()
const { colors } = useTheme();
const [valSelect, setValSelect] = useState<"group" | "position" | "role" | "gender">("group");
const [chooseGroup, setChooseGroup] = useState({ val: "", label: "" });
const [choosePosition, setChoosePosition] = useState({ val: "", label: "" });
@@ -206,25 +208,11 @@ export default function CreateMember() {
};
return (
<SafeAreaView>
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
<Stack.Screen
options={{
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Tambah Anggota",
headerTitleAlign: "center",
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading}
// category="create"
// onPress={() => { handleCreate() }}
// />
// ),
header: () => (
<AppHeader title="Anggota"
showBack={true}
@@ -241,7 +229,7 @@ export default function CreateMember() {
}}
/>
<KeyboardAvoidingView
style={[Styles.h100]}
style={[Styles.h100, { backgroundColor: colors.background }]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={headerHeight}
>
@@ -271,6 +259,7 @@ export default function CreateMember() {
placeholder="Pilih Lembaga Desa"
value={chooseGroup.label}
required
bg={colors.card}
onPress={() => {
setValChoose(chooseGroup.val);
setValSelect("group");
@@ -285,6 +274,7 @@ export default function CreateMember() {
placeholder="Pilih Jabatan"
value={choosePosition.label}
required
bg={colors.card}
onPress={() => {
setValChoose(choosePosition.val);
setValSelect("position");
@@ -298,6 +288,7 @@ export default function CreateMember() {
placeholder="Pilih Role"
value={chooseRole.label}
required
bg={colors.card}
onPress={() => {
setValChoose(chooseRole.val);
setValSelect("role");
@@ -311,6 +302,7 @@ export default function CreateMember() {
type="numeric"
placeholder="NIK"
required
bg={colors.card}
error={error.nik}
errorText="NIK Harus 16 Karakter"
onChange={val => {
@@ -322,6 +314,7 @@ export default function CreateMember() {
type="default"
placeholder="Nama"
required
bg={colors.card}
error={error.name}
errorText="Nama harus 350 karakter (huruf, angka, spasi, dan simbol ringan (. , ' _ -))"
onChange={val => {
@@ -333,6 +326,7 @@ export default function CreateMember() {
type="default"
placeholder="Email"
required
bg={colors.card}
error={error.email}
errorText="Email tidak valid"
onChange={val => {
@@ -344,7 +338,8 @@ export default function CreateMember() {
type="numeric"
placeholder="8XX-XXX-XXX"
required
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
bg={colors.card}
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02, { color: colors.text }]}>+62</Text>}
error={error.phone}
errorText="Nomor Telepon tidak valid"
onChange={val => {
@@ -356,6 +351,7 @@ export default function CreateMember() {
placeholder="Pilih Jenis Kelamin"
value={chooseGender.label}
required
bg={colors.card}
onPress={() => {
setValChoose(chooseGender.val);
setValSelect("gender");

View File

@@ -10,6 +10,7 @@ import { apiEditUser, apiGetProfile } from "@/lib/api";
import { validateName } from "@/lib/fun_validateName";
import { setUpdateMember } from "@/lib/memberSlice";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useHeaderHeight } from '@react-navigation/elements';
import * as ImagePicker from "expo-image-picker";
@@ -47,6 +48,7 @@ export default function EditMember() {
const update = useSelector((state: any) => state.memberUpdate)
const { token, decryptToken } = useAuthSession()
const { id } = useLocalSearchParams<{ id: string }>();
const { colors } = useTheme();
const [errorImg, setErrorImg] = useState(false)
const [selectedImage, setSelectedImage] = useState<string | undefined | { uri: string }>(undefined);
const [choosePosition, setChoosePosition] = useState({ val: "", label: "" });
@@ -236,27 +238,11 @@ export default function EditMember() {
};
return (
<SafeAreaView>
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
<Stack.Screen
options={{
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Anggota",
headerTitleAlign: "center",
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading}
// category="update"
// onPress={() => {
// handleEdit()
// }}
// />
// ),
header: () => (
<AppHeader
title="Edit Anggota"
@@ -277,7 +263,7 @@ export default function EditMember() {
/>
<KeyboardAvoidingView
style={[Styles.h100]}
style={[Styles.h100, { backgroundColor: colors.background }]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={headerHeight}
>
@@ -325,6 +311,7 @@ export default function EditMember() {
placeholder="Pilih Jabatan"
value={choosePosition.label}
required
bg={colors.card}
onPress={() => {
setValChoose(choosePosition.val);
setValSelect("position");
@@ -338,6 +325,7 @@ export default function EditMember() {
placeholder="Pilih Role"
value={chooseRole.label}
required
bg={colors.card}
onPress={() => {
setValChoose(chooseRole.val);
setValSelect("role");
@@ -352,6 +340,7 @@ export default function EditMember() {
placeholder="NIK"
required
value={data?.nik}
bg={colors.card}
error={error.nik}
errorText="NIK Harus 16 Karakter"
onChange={val => {
@@ -364,6 +353,7 @@ export default function EditMember() {
placeholder="Nama"
required
value={data?.name}
bg={colors.card}
error={error.name}
errorText="Nama harus 350 karakter (huruf, angka, spasi, dan simbol ringan (. , ' _ -))"
onChange={val => {
@@ -376,6 +366,7 @@ export default function EditMember() {
placeholder="Email"
required
value={data?.email}
bg={colors.card}
error={error.email}
errorText="Email tidak valid"
onChange={val => {
@@ -387,8 +378,9 @@ export default function EditMember() {
type="numeric"
placeholder="8XX-XXX-XXX"
required
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02, { color: colors.text }]}>+62</Text>}
value={data?.phone}
bg={colors.card}
error={error.phone}
errorText="Nomor Telepon tidak valid"
onChange={val => {
@@ -400,6 +392,7 @@ export default function EditMember() {
placeholder="Pilih Jenis Kelamin"
value={chooseGender.label}
required
bg={colors.card}
onPress={() => {
setValChoose(chooseGender.val);
setValSelect("gender");

View File

@@ -9,6 +9,7 @@ import { ConstEnv } from "@/constants/ConstEnv";
import Styles from "@/constants/Styles";
import { apiGetUser } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { AntDesign, Feather } from "@expo/vector-icons";
import { router, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
@@ -33,6 +34,7 @@ export default function Index() {
const { active, group } = useLocalSearchParams<{ active?: string, group?: string }>()
const { token, decryptToken } = useAuthSession()
const entityUser = useSelector((state: any) => state.user)
const { colors } = useTheme();
const [search, setSearch] = useState('')
const [nameGroup, setNameGroup] = useState('')
const [data, setData] = useState<Props[]>([])
@@ -104,22 +106,22 @@ export default function Index() {
});
return (
<View style={[Styles.p15, { flex: 1 }]}>
<View style={[Styles.p15, { flex: 1, backgroundColor: colors.background }]}>
<View>
<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="Tidak Aktif"
icon={<AntDesign name="closecircleo" color={status == "false" ? 'white' : 'black'} size={20} />}
icon={<AntDesign name="closecircleo" color={status == "false" ? 'white' : colors.text} size={20} />}
n={2} />
</View>
<InputSearch onChange={setSearch} />
@@ -168,6 +170,7 @@ export default function Index() {
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
tintColor={colors.primary}
/>
}
/>