Compare commits

...

12 Commits

Author SHA1 Message Date
da89673271 upd: alert pick image
Deskripsi:
- menghilangkan alert pada picker image

No Issues
2025-08-06 17:24:10 +08:00
d052b7a0d4 upd: tampilan statys
Deskripsi:
- update label status
- menampilkan status pada detail member

No Issues
2025-08-06 17:18:34 +08:00
9370aac9a3 fix : file
Deskripsi:
- lihat atau share file
- view file ios pada home divisi > ga pake loading

No Issues
2025-08-06 17:09:46 +08:00
1298ec079a upd: tampilan pengumuman
Deskripsi:
- menambah tinggi text area
- mengurangi margin list divisi

No Issues
2025-08-06 16:50:31 +08:00
5db712d4b9 upd: notifikasi diskusi umum 2025-08-06 11:58:54 +08:00
1e2069ca42 fix: jarak keyboard
Deskripsi:
- otomatis jarak input dengan keyboard ios

No Issues
2025-08-05 17:24:49 +08:00
1d555bf950 upd: inputdate
Deskripsi:
- custom tampilan input datetime picker pada ios

No Issues
2025-08-05 16:40:37 +08:00
45d08e1df5 fix: kalender
Deskripsi:
- month kalender

No ISsues
2025-08-05 15:50:56 +08:00
7470e8a9c2 fix : group
Deskripsi:
- validasi tambah group
- validasi edit group
- load refresh modal

No Issues
2025-08-05 15:34:40 +08:00
308fda6920 fix : tampilan
Deskripsi:
- form input on ios

No ISsues
2025-08-05 15:10:44 +08:00
7ad846ff9c upd: akses user
Deskripsi:
- header list project > role user bisa akses filter

No Issues
2025-08-05 12:07:17 +08:00
92564373fe fix : input kalendar date
Deskripsi:
- tambah package intl

No Issues
2025-08-05 11:41:03 +08:00
32 changed files with 239 additions and 91 deletions

View File

@@ -13,8 +13,9 @@ import { apiReadOneNotification } from "@/lib/api";
import { pushToPage } from "@/lib/pushToPage";
import store from "@/lib/store";
import { useAuthSession } from "@/providers/AuthProvider";
import AsyncStorage from "@react-native-async-storage/async-storage";
import firebase from '@react-native-firebase/app';
import { Redirect, router, Stack } from "expo-router";
import { Redirect, router, Stack, usePathname } from "expo-router";
import { StatusBar } from 'expo-status-bar';
import { useEffect } from "react";
import { Easing, Notifier } from 'react-native-notifier';
@@ -22,6 +23,7 @@ import { Provider } from "react-redux";
export default function RootLayout() {
const { token, decryptToken, isLoading } = useAuthSession()
const pathname = usePathname()
async function handleReadNotification(id: string, category: string, idContent: string) {
try {
@@ -33,12 +35,30 @@ export default function RootLayout() {
}
}
useEffect(() => {
const checkNavigation = async () => {
const navData = await AsyncStorage.getItem('navigateOnOpen');
if (navData) {
const { screen, content } = JSON.parse(navData);
await AsyncStorage.removeItem('navigateOnOpen'); // reset
pushToPage(screen, content)
}
};
checkNavigation();
}, []);
useEffect(() => {
const unsubscribe = firebase.app().messaging().onMessage(async remoteMessage => {
const id = remoteMessage?.data?.id;
const category = remoteMessage?.data?.category;
const content = remoteMessage?.data?.content;
if (remoteMessage.notification != undefined && remoteMessage.notification.title != undefined && remoteMessage.notification.body != undefined) {
if (
remoteMessage.notification != undefined &&
remoteMessage.notification.title != undefined &&
remoteMessage.notification.body != undefined &&
pathname != `/${category}/${content}`
) {
Notifier.showNotification({
title: remoteMessage.notification?.title,
description: remoteMessage.notification?.body,

View File

@@ -149,7 +149,7 @@ export default function CreateAnnouncement() {
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
{
item.Division.map((division: any, i: any) => (
<View key={i} style={[Styles.rowItemsCenter, Styles.mv05]}>
<View key={i} style={[Styles.rowItemsCenter]}>
<Entypo name="dot-single" size={24} color="black" />
<Text style={[Styles.textDefault]}>{division.name}</Text>
</View>

View File

@@ -193,7 +193,7 @@ export default function EditAnnouncement() {
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
{
item.Division.map((division: any, i: any) => (
<View key={i} style={[Styles.rowItemsCenter, Styles.mv05]}>
<View key={i} style={[Styles.rowItemsCenter]}>
<Entypo name="dot-single" size={24} color="black" />
<Text style={[Styles.textDefault]}>{division.name}</Text>
</View>

View File

@@ -43,8 +43,6 @@ export default function EditBanner() {
if (!result.canceled) {
setSelectedImage(result.assets[0].uri);
setImgForm(result.assets[0]);
} else {
alert("Tidak ada gambar yang dipilih");
}
};

View File

@@ -42,8 +42,6 @@ export default function CreateBanner() {
if (result.assets?.[0].uri) {
setSelectedImage(result.assets[0].uri);
setImgForm(result.assets[0]);
} else {
alert("Tidak ada gambar yang dipilih");
}
}
};

View File

@@ -155,7 +155,7 @@ export default function BannerList() {
/>
<MenuItemRow
icon={<MaterialCommunityIcons name="file-eye" color="black" size={25} />}
title="Lihat File"
title="Lihat / Share"
onPress={() => { openFile() }}
/>
<MenuItemRow

View File

@@ -17,6 +17,7 @@ import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { KeyboardAvoidingView, Platform, Pressable, ScrollView, View } from "react-native";
import { useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
type Props = {
id: string
@@ -49,6 +50,7 @@ export default function DetailDiscussionGeneral() {
const [loadingKomentar, setLoadingKomentar] = useState(true)
const arrSkeleton = Array.from({ length: 3 }, (_, index) => index)
const reference = firebase.app().database('https://mobile-darmasaba-default-rtdb.asia-southeast1.firebasedatabase.app').ref(`/discussion-general/${id}`);
const headerHeight = useHeaderHeight();
useEffect(() => {
const onValueChange = reference.on('value', snapshot => {
@@ -197,7 +199,7 @@ export default function DetailDiscussionGeneral() {
</ScrollView>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<View style={[
Styles.contentItemCenter,

View File

@@ -17,6 +17,7 @@ import {
View
} from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
export default function CalendarDivisionCreate() {
const { id } = useLocalSearchParams<{ id: string }>()
@@ -24,6 +25,7 @@ export default function CalendarDivisionCreate() {
const [isSelect, setSelect] = useState(false)
const update = useSelector((state: any) => state.calendarCreate)
const dispatch = useDispatch()
const headerHeight = useHeaderHeight();
const [error, setError] = useState({
title: false,
dateStart: false,
@@ -145,7 +147,7 @@ export default function CalendarDivisionCreate() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15]}>

View File

@@ -78,7 +78,9 @@ export default function CalendarDivision() {
} catch (error) {
console.error(error);
} finally {
setLoadingBtn(false)
setTimeout(() => {
setLoadingBtn(false)
}, 500)
}
}
@@ -155,6 +157,7 @@ export default function CalendarDivision() {
date={selected}
month={month}
onChange={({ date }) => setSelected(date)}
onMonthChange={(month) => setMonth(month)}
styles={{
selected: Styles.selectedDate,
month_label: Styles.cBlack,

View File

@@ -20,6 +20,7 @@ import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { KeyboardAvoidingView, Platform, Pressable, RefreshControl, ScrollView, View } from "react-native";
import { useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
type Props = {
id: string;
@@ -59,6 +60,7 @@ export default function DiscussionDetail() {
const arrSkeleton = Array.from({ length: 3 })
const reference = firebase.app().database('https://mobile-darmasaba-default-rtdb.asia-southeast1.firebasedatabase.app').ref(`/discussion-division/${detail}`);
const [refreshing, setRefreshing] = useState(false)
const headerHeight = useHeaderHeight();
useEffect(() => {
@@ -283,7 +285,7 @@ export default function DiscussionDetail() {
</ScrollView>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<View
style={[

View File

@@ -8,6 +8,8 @@ import { setUpdateTask } from "@/lib/taskUpdate";
import { useAuthSession } from "@/providers/AuthProvider";
import dayjs from "dayjs";
import { router, Stack, useLocalSearchParams } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import { useEffect, useState } from "react";
import {
KeyboardAvoidingView, Platform, SafeAreaView,
@@ -17,6 +19,7 @@ import {
import Toast from "react-native-toast-message";
import DateTimePicker, { DateType } from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
export default function TaskDivisionAddTask() {
const { token, decryptToken } = useAuthSession();
@@ -25,6 +28,7 @@ export default function TaskDivisionAddTask() {
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
const [disable, setDisable] = useState(true);
const [loading, setLoading] = useState(false)
const headerHeight = useHeaderHeight();
const [range, setRange] = useState<{
startDate: DateType;
endDate: DateType;
@@ -127,7 +131,7 @@ export default function TaskDivisionAddTask() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
@@ -141,6 +145,13 @@ export default function TaskDivisionAddTask() {
selected: Styles.selectedDate,
selected_label: Styles.cWhite,
range_fill: Styles.selectRangeDate,
month_label: Styles.cBlack,
month_selector_label: Styles.cBlack,
year_label: Styles.cBlack,
year_selector_label: Styles.cBlack,
day_label: Styles.cBlack,
time_label: Styles.cBlack,
weekday_label: Styles.cBlack,
}}
/>
</View>

View File

@@ -6,6 +6,8 @@ import Styles from "@/constants/Styles";
import { setTaskCreate } from "@/lib/taskCreate";
import dayjs from "dayjs";
import { router, Stack } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import { useEffect, useState } from "react";
import {
KeyboardAvoidingView,
@@ -18,8 +20,10 @@ import DateTimePicker, {
DateType
} from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
export default function CreateTaskAddTugas() {
const headerHeight = useHeaderHeight();
const dispatch = useDispatch()
const [disable, setDisable] = useState(true);
const [range, setRange] = useState<{
@@ -101,7 +105,7 @@ export default function CreateTaskAddTugas() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
@@ -115,6 +119,13 @@ export default function CreateTaskAddTugas() {
selected: Styles.selectedDate,
selected_label: Styles.cWhite,
range_fill: Styles.selectRangeDate,
month_label: Styles.cBlack,
month_selector_label: Styles.cBlack,
year_label: Styles.cBlack,
year_selector_label: Styles.cBlack,
day_label: Styles.cBlack,
time_label: Styles.cBlack,
weekday_label: Styles.cBlack,
}}
/>
</View>

View File

@@ -6,8 +6,11 @@ import Styles from "@/constants/Styles";
import { apiEditTaskTugas, apiGetTaskTugas } from "@/lib/api";
import { setUpdateTask } from "@/lib/taskUpdate";
import { useAuthSession } from "@/providers/AuthProvider";
import { useHeaderHeight } from '@react-navigation/elements';
import dayjs from "dayjs";
import { router, Stack, useLocalSearchParams } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import { useEffect, useState } from "react";
import {
KeyboardAvoidingView,
@@ -21,6 +24,7 @@ import DateTimePicker, { DateType } from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
export default function UpdateProjectTaskDivision() {
const headerHeight = useHeaderHeight();
const { detail } = useLocalSearchParams<{ detail: string }>();
const dispatch = useDispatch();
const update = useSelector((state: any) => state.taskUpdate);
@@ -149,7 +153,7 @@ export default function UpdateProjectTaskDivision() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
@@ -166,6 +170,13 @@ export default function UpdateProjectTaskDivision() {
selected: Styles.selectedDate,
selected_label: Styles.cWhite,
range_fill: Styles.selectRangeDate,
month_label: Styles.cBlack,
month_selector_label: Styles.cBlack,
year_label: Styles.cBlack,
year_selector_label: Styles.cBlack,
day_label: Styles.cBlack,
time_label: Styles.cBlack,
weekday_label: Styles.cBlack,
}}
/>
)}

View File

@@ -201,7 +201,6 @@ export default function EditProfile() {
setSelectedImage(result.assets[0].uri);
setImgForm(result.assets[0]);
} else {
alert("Tidak ada gambar yang dipilih");
setErrorImg(false)
}
};

View File

@@ -42,14 +42,9 @@ export default function Index() {
const dispatch = useDispatch()
const update = useSelector((state: any) => state.groupUpdate)
const [data11, setData1] = useState(Array.from({ length: 20 }, (_, i) => `Item ${i}`));
const renderItem = ({ item }: { item: string }) => (
<View style={{ padding: 20, borderBottomWidth: 1, borderColor: '#ccc' }}>
<Text>{item}</Text>
</View>
);
const [error, setError] = useState({
title: false,
});
async function handleEdit() {
@@ -109,6 +104,17 @@ export default function Index() {
setRefreshing(false)
};
function validationForm(val: any, cat: 'title') {
if (cat === 'title') {
setTitleChoose(val)
if (val == "" || val.length < 3) {
setError((prev) => ({ ...prev, title: true }))
} else {
setError((prev) => ({ ...prev, title: false }))
}
}
}
return (
<SafeAreaView>
@@ -207,10 +213,18 @@ export default function Index() {
<DrawerBottom animation="none" keyboard height={30} isVisible={isVisibleEdit} setVisible={() => setVisibleEdit(false)} title="Edit Lembaga Desa">
<View style={{ flex: 1 }}>
<View>
<InputForm type="default" placeholder="Nama Lembaga Desa" required label="Lembaga Desa" value={titleChoose} onChange={setTitleChoose} />
<InputForm
type="default"
placeholder="Nama Lembaga Desa"
required
label="Lembaga Desa"
value={titleChoose}
error={error.title}
errorText="Lembaga Desa tidak boleh kosong & minimal 3 karakter"
onChange={(val) => { validationForm(val, 'title') }} />
</View>
<View>
<ButtonForm text="SIMPAN" onPress={() => { handleEdit() }} />
<ButtonForm text="SIMPAN" disabled={Object.values(error).some((v) => v == true) || titleChoose == ""} onPress={() => { handleEdit() }} />
</View>
</View>
</DrawerBottom>

View File

@@ -1,6 +1,7 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import ImageUser from "@/components/imageNew";
import ItemDetailMember from "@/components/itemDetailMember";
import LabelStatus from "@/components/labelStatus";
import HeaderRightMemberDetail from "@/components/member/headerMemberDetail";
import Skeleton from "@/components/skeleton";
import Text from "@/components/Text";
@@ -102,6 +103,11 @@ export default function MemberDetail() {
<View style={[Styles.p15]}>
<View style={[Styles.rowSpaceBetween]}>
<Text style={[Styles.textDefaultSemiBold]}>Informasi</Text>
<LabelStatus
size="small"
category={data?.isActive ? 'success' : 'error'}
text={data?.isActive ? 'AKTIF' : 'TIDAK AKTIF'}
/>
</View>
{
loading ?

View File

@@ -24,8 +24,10 @@ import {
} from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
export default function CreateMember() {
const headerHeight = useHeaderHeight();
const dispatch = useDispatch()
const update = useSelector((state: any) => state.memberUpdate)
const { token, decryptToken } = useAuthSession()
@@ -199,9 +201,6 @@ export default function CreateMember() {
if (!result.canceled) {
setSelectedImage(result.assets[0].uri);
setImgForm(result.assets[0]);
} else {
alert("Tidak ada gambar yang dipilih");
}
};
@@ -230,7 +229,7 @@ export default function CreateMember() {
<KeyboardAvoidingView
style={[Styles.h100]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15]}>

View File

@@ -22,6 +22,7 @@ import {
} from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
type Props = {
id: string;
@@ -38,6 +39,7 @@ type Props = {
};
export default function EditMember() {
const headerHeight = useHeaderHeight();
const dispatch = useDispatch()
const update = useSelector((state: any) => state.memberUpdate)
const { token, decryptToken } = useAuthSession()
@@ -226,7 +228,6 @@ export default function EditMember() {
setSelectedImage(result.assets[0].uri);
setImgForm(result.assets[0]);
} else {
alert("Tidak ada gambar yang dipilih");
setErrorImg(false)
}
};
@@ -259,7 +260,7 @@ export default function EditMember() {
<KeyboardAvoidingView
style={[Styles.h100]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>

View File

@@ -6,6 +6,8 @@ import Styles from "@/constants/Styles";
import { apiCreateProjectTask } from "@/lib/api";
import { setUpdateProject } from "@/lib/projectUpdate";
import { useAuthSession } from "@/providers/AuthProvider";
import 'intl';
import 'intl/locale-data/jsonp/id';
import dayjs from "dayjs";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
@@ -21,8 +23,10 @@ import DateTimePicker, {
DateType
} from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
export default function ProjectAddTask() {
const headerHeight = useHeaderHeight();
const { token, decryptToken } = useAuthSession()
const dispatch = useDispatch()
const update = useSelector((state: any) => state.projectUpdate)
@@ -77,7 +81,7 @@ export default function ProjectAddTask() {
dispatch(setUpdateProject({ ...update, task: !update.task, progress: !update.progress }))
Toast.show({ type: 'small', text1: 'Berhasil menambah data', })
router.back();
}else{
} else {
Toast.show({ type: 'small', text1: response.message, })
}
} catch (error) {
@@ -112,7 +116,7 @@ export default function ProjectAddTask() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
@@ -126,6 +130,13 @@ export default function ProjectAddTask() {
selected: Styles.selectedDate,
selected_label: Styles.cWhite,
range_fill: Styles.selectRangeDate,
month_label: Styles.cBlack,
month_selector_label: Styles.cBlack,
year_label: Styles.cBlack,
year_selector_label: Styles.cBlack,
day_label: Styles.cBlack,
time_label: Styles.cBlack,
weekday_label: Styles.cBlack,
}}
/>
</View>

View File

@@ -6,6 +6,8 @@ import Styles from "@/constants/Styles";
import { setTaskCreate } from "@/lib/taskCreate";
import dayjs from "dayjs";
import { router, Stack } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import { useEffect, useState } from "react";
import {
KeyboardAvoidingView,
@@ -18,8 +20,10 @@ import DateTimePicker, {
DateType
} from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
import { useHeaderHeight } from '@react-navigation/elements';
export default function CreateProjectAddTask() {
const headerHeight = useHeaderHeight();
const dispatch = useDispatch()
const [disable, setDisable] = useState(true);
const [range, setRange] = useState<{
@@ -101,7 +105,7 @@ export default function CreateProjectAddTask() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
@@ -115,6 +119,13 @@ export default function CreateProjectAddTask() {
selected: Styles.selectedDate,
selected_label: Styles.cWhite,
range_fill: Styles.selectRangeDate,
month_label: Styles.cBlack,
month_selector_label: Styles.cBlack,
year_label: Styles.cBlack,
year_selector_label: Styles.cBlack,
day_label: Styles.cBlack,
time_label: Styles.cBlack,
weekday_label: Styles.cBlack,
}}
/>
</View>

View File

@@ -6,8 +6,11 @@ import Styles from "@/constants/Styles";
import { apiEditProjectTask, apiGetProjectTask } from "@/lib/api";
import { setUpdateProject } from "@/lib/projectUpdate";
import { useAuthSession } from "@/providers/AuthProvider";
import { useHeaderHeight } from '@react-navigation/elements';
import dayjs from "dayjs";
import { router, Stack, useLocalSearchParams } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import { useEffect, useState } from "react";
import { KeyboardAvoidingView, Platform, SafeAreaView, ScrollView, View } from "react-native";
import Toast from "react-native-toast-message";
@@ -15,6 +18,7 @@ import DateTimePicker, { DateType } from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
export default function UpdateProjectTask() {
const headerHeight = useHeaderHeight();
const dispatch = useDispatch()
const update = useSelector((state: any) => state.projectUpdate)
const { token, decryptToken } = useAuthSession();
@@ -123,7 +127,7 @@ export default function UpdateProjectTask() {
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={110}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
@@ -136,13 +140,19 @@ export default function UpdateProjectTask() {
startDate={range.startDate}
endDate={range.endDate}
onChange={(param) => setRange(param)}
// styles={defaultStyles}
month={month}
year={year}
styles={{
selected: Styles.selectedDate,
selected_label: Styles.cWhite,
range_fill: Styles.selectRangeDate,
month_label: Styles.cBlack,
month_selector_label: Styles.cBlack,
year_label: Styles.cBlack,
year_selector_label: Styles.cBlack,
day_label: Styles.cBlack,
time_label: Styles.cBlack,
weekday_label: Styles.cBlack,
}}
/>
}

View File

@@ -51,7 +51,7 @@ export default function FileDivisionDetail() {
const openFile = (item: Props) => {
setLoadingOpen(true)
if (Platform.OS == 'android') setLoadingOpen(true)
let remoteUrl = 'https://wibu-storage.wibudev.com/api/files/' + item.idStorage;
const fileName = item.name + '.' + item.extension;
let localPath = `${FileSystem.documentDirectory}/${fileName}`;
@@ -59,6 +59,7 @@ export default function FileDivisionDetail() {
FileSystem.downloadAsync(remoteUrl, localPath).then(async ({ uri }) => {
const contentURL = await FileSystem.getContentUriAsync(uri);
setLoadingOpen(false)
try {
if (Platform.OS == 'android') {
// open with android intent
@@ -79,7 +80,7 @@ export default function FileDivisionDetail() {
} catch (error) {
Alert.alert('INFO', 'Gagal membuka file, tidak ada aplikasi yang dapat membuka file ini');
} finally {
setLoadingOpen(false)
if (Platform.OS == 'android') setLoadingOpen(false)
}
});
};

View File

@@ -48,9 +48,9 @@ export default function HeaderRightGroupList() {
if (cat === 'title') {
setTitle(val)
if (val == "" || val.length < 3) {
setError({ ...error, title: true })
setError((prev) => ({ ...prev, title: true }))
} else {
setError({ ...error, title: false })
setError((prev) => ({ ...prev, title: false }))
}
}
}
@@ -91,7 +91,7 @@ export default function HeaderRightGroupList() {
/>
</View>
<View>
<ButtonForm text="SIMPAN" onPress={() => { onCheck() }} />
<ButtonForm text="SIMPAN" disabled={Object.values(error).some((v) => v == true) || title == ""} onPress={() => { onCheck() }} />
</View>
</View>
</DrawerBottom>

View File

@@ -1,11 +1,11 @@
import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { stringToDate } from "@/lib/fun_stringToDate";
import DateTimePicker from "@react-native-community/datetimepicker";
import dayjs from "dayjs";
import { useState } from "react";
import { Pressable, View } from "react-native";
import { Platform, Pressable, View } from "react-native";
import Text from "./Text";
import ModalFloat from "./modalFloat";
type Props = {
label?: string;
@@ -58,14 +58,34 @@ export function InputDate({ label, value, placeholder, onChange, info, disable,
{info != undefined && (<Text style={[Styles.textInformation, Styles.mt05, Styles.cGray]}>{info}</Text>)}
</View>
{
modal && (
<DateTimePicker
value={new Date()}
mode={mode}
display="default"
onChange={(event, date) => { onChangeDate(event.type, date) }}
onTouchCancel={() => setModal(false)}
/>
Platform.OS === 'ios' ? (
modal && (
<ModalFloat
isVisible={modal}
setVisible={setModal}
onSubmit={() => { }}
buttonHide
disableSubmit
title={mode == "date" ? "Pilih Tanggal" : mode == "time" ? "Pilih Jam" : "Pilih Tanggal & Jam"}>
<DateTimePicker
value={new Date()}
mode={mode}
display="spinner"
onChange={(event, date) => { onChangeDate(event.type, date) }}
onTouchCancel={() => setModal(false)}
/>
</ModalFloat>
)
) : (
modal && (
<DateTimePicker
value={new Date()}
mode={mode}
display="inline"
onChange={(event, date) => { onChangeDate(event.type, date) }}
onTouchCancel={() => setModal(false)}
/>
)
)
}
</>

View File

@@ -1,5 +1,5 @@
import Styles from "@/constants/Styles";
import { Dimensions, TextInput, View } from "react-native";
import { Dimensions, Platform, TextInput, View } from "react-native";
import Text from "./Text";
type Props = {
@@ -36,7 +36,14 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
</Text>
)
}
<View style={[Styles.inputRoundForm, itemRight != undefined ? Styles.inputRoundFormRight : Styles.inputRoundFormLeft, round && Styles.round30, { backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' }, error && { borderColor: "red" }]}>
<View style={[
Styles.inputRoundForm,
itemRight != undefined ? Styles.inputRoundFormRight : Styles.inputRoundFormLeft,
round && Styles.round30,
{ backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' },
error && { borderColor: "red" },
Platform.OS == 'ios' && { paddingVertical: 10 },
]}>
{itemRight != undefined ? itemRight : itemLeft}
<TextInput
editable={!disable}
@@ -71,11 +78,11 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
placeholder={placeholder}
keyboardType={type}
editable={!disable}
style={[Styles.inputRoundForm, error && { borderColor: "red" }, round && Styles.round30, { backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' }, { color: 'black' }, multiline && { height: 100, textAlignVertical: 'top' }]}
style={[Styles.inputRoundForm, error && { borderColor: "red" }, round && Styles.round30, { backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' }, { color: 'black' }, multiline && { height: 150, textAlignVertical: 'top' }]}
onChangeText={onChange}
placeholderTextColor={'gray'}
multiline={multiline}
numberOfLines={multiline ? 4 : undefined}
numberOfLines={multiline ? 5 : undefined}
/>
{error && (<Text style={[Styles.textInformation, Styles.cError, Styles.mt05]}>{errorText}</Text>)}
{info != undefined && (<Text style={[Styles.textInformation, Styles.mt05, Styles.cGray]}>{info}</Text>)}

View File

@@ -10,7 +10,7 @@ type Props = {
}
export default function LabelStatus({ category, text, size }: Props) {
return (
<View style={[size == "small" ? Styles.labelStatusSmall : Styles.labelStatus, ColorsStatus[category], Styles.round10]}>
<View style={[size == "small" ? Styles.labelStatusSmall : Styles.labelStatus, ColorsStatus[category], Styles.round10, Styles.contentItemCenter]}>
<Text style={[size == "small" ? Styles.textSmallSemiBold : Styles.textMediumSemiBold, Styles.cWhite, { textAlign: 'center' }]}>{text}</Text>
</View>
)

View File

@@ -1,7 +1,7 @@
import Styles from '@/constants/Styles';
import { Pressable, View } from 'react-native';
import Text from './Text';
import Modal from 'react-native-modal';
import Text from './Text';
type Props = {
isVisible: boolean
@@ -10,9 +10,10 @@ type Props = {
children: React.ReactNode
onSubmit: () => void
disableSubmit?: boolean
buttonHide?: boolean
}
export default function ModalFloat({ isVisible, setVisible, title, children, onSubmit, disableSubmit }: Props) {
export default function ModalFloat({ isVisible, setVisible, title, children, onSubmit, disableSubmit, buttonHide }: Props) {
return (
<Modal
animationIn={"fadeIn"}
@@ -28,14 +29,18 @@ export default function ModalFloat({ isVisible, setVisible, title, children, onS
<View style={[Styles.mb10]}>
{children}
</View>
<View style={[Styles.rowItemsCenter, { justifyContent: 'flex-end' }]}>
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10, Styles.mr10]} onPress={() => { setVisible(false) }}>
<Text style={[Styles.textDefault]}>Batal</Text>
</Pressable>
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10]} onPress={onSubmit} disabled={disableSubmit}>
<Text style={[Styles.textDefault, disableSubmit && Styles.cGray]}>Simpan</Text>
</Pressable>
</View>
{
!buttonHide && (
<View style={[Styles.rowItemsCenter, { justifyContent: 'flex-end' }]}>
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10, Styles.mr10]} onPress={() => { setVisible(false) }}>
<Text style={[Styles.textDefault]}>Batal</Text>
</Pressable>
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10]} onPress={onSubmit} disabled={disableSubmit}>
<Text style={[Styles.textDefault, disableSubmit && Styles.cGray]}>Simpan</Text>
</Pressable>
</View>
)
}
</View>
</Modal>
)

View File

@@ -9,13 +9,13 @@ import { useAuthSession } from "@/providers/AuthProvider"
import { AntDesign } from "@expo/vector-icons"
import { useEffect, useState } from "react"
import { Pressable, ScrollView, View } from "react-native"
import Text from "./Text";
import { useDispatch, useSelector } from "react-redux"
import { ButtonForm } from "./buttonForm"
import DrawerBottom from "./drawerBottom"
import ImageUser from "./imageNew"
import ImageWithLabel from "./imageWithLabel"
import InputSearch from "./inputSearch"
import Text from "./Text"
type Props = {
open: boolean
@@ -89,8 +89,7 @@ export default function ModalSelect({ open, close, title, category, idParent, on
useEffect(() => {
if (category == 'group') {
if (entitiesGroup.length == 0)
handleLoadGroup()
handleLoadGroup()
setData(entitiesGroup)
} else if (category == 'position') {
handleLoadPosition()
@@ -174,9 +173,9 @@ export default function ModalSelect({ open, close, title, category, idParent, on
{
(category == 'member')
?
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={'black'} />
:
chooseValue.val == item.id && <AntDesign name="check" size={20} color={'black'}/>
chooseValue.val == item.id && <AntDesign name="check" size={20} color={'black'} />
}
</Pressable>
))
@@ -192,7 +191,7 @@ export default function ModalSelect({ open, close, title, category, idParent, on
}}>
<Text style={[chooseValue.val == item.val ? Styles.textDefaultSemiBold : Styles.textDefault]}>{item.label}</Text>
{
valChoose == item.val && <AntDesign name="check" size={20} color={'black'}/>
valChoose == item.val && <AntDesign name="check" size={20} color={'black'} />
}
</Pressable>
))

View File

@@ -30,19 +30,16 @@ export default function HeaderRightProjectList() {
}}
/>
}
{
(entityUser.role == 'supadmin' || entityUser.role == 'developer') &&
<MenuItemRow
icon={<AntDesign name="filter" color="black" size={25} />}
title="Filter"
onPress={() => {
setVisible(false)
setTimeout(() => {
setFilter(true)
}, 600)
}}
/>
}
<MenuItemRow
icon={<AntDesign name="filter" color="black" size={25} />}
title="Filter"
onPress={() => {
setVisible(false)
setTimeout(() => {
setFilter(true)
}, 600)
}}
/>
</View>
</DrawerBottom>
<ModalFilter

View File

@@ -173,7 +173,7 @@ export default function SectionFile({ status, member, refreshing }: { status: nu
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<MaterialCommunityIcons name="file-eye" color="black" size={25} />}
title="Lihat File"
title="Lihat / Share"
onPress={() => {
openFile()
}}

View File

@@ -157,7 +157,7 @@ export default function SectionFileTask({refreshing}: {refreshing: boolean}) {
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<MaterialCommunityIcons name="file-eye" color="black" size={25} />}
title="Lihat File"
title="Lihat / Share"
onPress={() => {
openFile()
// setModal(false)

View File

@@ -1,3 +1,4 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { getApp, getApps, initializeApp } from '@react-native-firebase/app';
import messaging, { getMessaging } from '@react-native-firebase/messaging';
import { useEffect } from 'react';
@@ -24,9 +25,18 @@ const initializeFirebase = async () => {
// Set auto initialization and background message handler
mess.setAutoInitEnabled(true);
// mess.setBackgroundMessageHandler(async remoteMessage => {
// // console.log('Message handled in the background!', remoteMessage);
// // pushToPage(String(remoteMessage?.data?.category), String(remoteMessage?.data?.content))
// });
mess.setBackgroundMessageHandler(async remoteMessage => {
// console.log('Message handled in the background!', remoteMessage);
// pushToPage(String(remoteMessage?.data?.category), String(remoteMessage?.data?.content))
const screen = remoteMessage?.data?.category;
const content = remoteMessage?.data?.content;
if (screen && content) {
await AsyncStorage.setItem('navigateOnOpen', JSON.stringify({ screen, content }));
}
});
return mess