Compare commits
15 Commits
amalia/13-
...
join
| Author | SHA1 | Date | |
|---|---|---|---|
| e2a601c590 | |||
| 4681f0a0cc | |||
| 31b7cf6a30 | |||
| 64aaafa2be | |||
| 42cb7c8f8e | |||
| 8c63c08bc3 | |||
| 6ca935483a | |||
| 039b26f5aa | |||
| 10212aa5de | |||
| f0373ef479 | |||
| 700192dd8d | |||
| 27b0b7d51f | |||
| 65278df750 | |||
| 8b98fee632 | |||
| e254cf8ed2 |
@@ -79,6 +79,12 @@ export default {
|
||||
URL_FIREBASE_DB: process.env.URL_FIREBASE_DB,
|
||||
PASS_ENC: process.env.PASS_ENC,
|
||||
WA_SERVER_TOKEN: process.env.WA_SERVER_TOKEN,
|
||||
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
|
||||
FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN,
|
||||
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
|
||||
FIREBASE_STORAGE_BUCKET: process.env.FIREBASE_STORAGE_BUCKET,
|
||||
FIREBASE_MESSAGING_SENDER_ID: process.env.FIREBASE_MESSAGING_SENDER_ID,
|
||||
FIREBASE_APP_ID: process.env.FIREBASE_APP_ID,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,6 +112,18 @@ export default function RootLayout() {
|
||||
)
|
||||
}} />
|
||||
<Stack.Screen name="profile" options={{ title: 'Profile' }} />
|
||||
<Stack.Screen name="setting/index" options={{
|
||||
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
title: 'Pengaturan',
|
||||
headerTitleAlign: 'center',
|
||||
// headerRight: () => <HeaderRightProjectList />
|
||||
header: () => (
|
||||
<AppHeader title="Pengaturan"
|
||||
showBack={true}
|
||||
onPressLeft={() => router.back()}
|
||||
/>
|
||||
)
|
||||
}} />
|
||||
<Stack.Screen name="member/index" options={{
|
||||
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
title: 'Anggota',
|
||||
|
||||
@@ -200,12 +200,12 @@ export default function DetailAnnouncement() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={() => handleRefresh()}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<View style={[Styles.p15, Styles.mb50]}>
|
||||
<View style={[Styles.wrapPaper, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.borderAll, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
{
|
||||
loading ?
|
||||
<View>
|
||||
@@ -243,7 +243,7 @@ export default function DetailAnnouncement() {
|
||||
</View>
|
||||
{
|
||||
dataFile.length > 0 && (
|
||||
<View style={[Styles.wrapPaper, Styles.mt10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.borderAll, Styles.mt10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<View style={[Styles.mb05]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>File</Text>
|
||||
</View>
|
||||
@@ -268,7 +268,7 @@ export default function DetailAnnouncement() {
|
||||
</View>
|
||||
)
|
||||
}
|
||||
<View style={[Styles.wrapPaper, Styles.mt10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.borderAll, Styles.mt10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
{
|
||||
loading ?
|
||||
arrSkeleton.map((item, index) => {
|
||||
|
||||
@@ -112,9 +112,9 @@ export default function Announcement() {
|
||||
borderType="bottom"
|
||||
bgColor="transparent"
|
||||
icon={
|
||||
<View style={[Styles.iconContent]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'black'} />
|
||||
</View>
|
||||
// <View style={[Styles.iconContent]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'white'} />
|
||||
// </View>
|
||||
}
|
||||
title={item.title}
|
||||
desc={item.desc.replace(/<[^>]*>?/gm, '').replace(/\r?\n|\r/g, ' ')}
|
||||
@@ -130,7 +130,7 @@ export default function Announcement() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi"
|
||||
import AppHeader from "@/components/AppHeader"
|
||||
import HeaderRightBannerList from "@/components/banner/headerBannerList"
|
||||
import BorderBottomItem from "@/components/borderBottomItem"
|
||||
import DrawerBottom from "@/components/drawerBottom"
|
||||
import MenuItemRow from "@/components/menuItemRow"
|
||||
import ModalConfirmation from "@/components/ModalConfirmation"
|
||||
import ModalLoading from "@/components/modalLoading"
|
||||
import Text from "@/components/Text"
|
||||
import { ConstEnv } from "@/constants/ConstEnv"
|
||||
@@ -42,6 +42,7 @@ export default function BannerList() {
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const [loadingOpen, setLoadingOpen] = useState(false)
|
||||
const [viewImg, setViewImg] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
const handleDeleteEntity = async () => {
|
||||
try {
|
||||
@@ -132,7 +133,7 @@ export default function BannerList() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
style={[Styles.h100, { backgroundColor: colors.background }]}
|
||||
@@ -196,11 +197,9 @@ export default function BannerList() {
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus data?',
|
||||
onPress: () => { handleDeleteEntity() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@@ -213,6 +212,19 @@ export default function BannerList() {
|
||||
onRequestClose={() => setViewImg(false)}
|
||||
doubleTapToZoomEnabled
|
||||
/>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus data?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteEntity()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import BorderBottomItem2 from "@/components/borderBottomItem2";
|
||||
@@ -8,10 +7,10 @@ import ImageUser from "@/components/imageNew";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import LabelStatus from "@/components/labelStatus";
|
||||
import MenuItemRow from "@/components/menuItemRow";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import Skeleton from "@/components/skeleton";
|
||||
import SkeletonContent from "@/components/skeletonContent";
|
||||
import Text from '@/components/Text';
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
import { ConstEnv } from "@/constants/ConstEnv";
|
||||
import { regexOnlySpacesOrEnter } from "@/constants/OnlySpaceOrEnter";
|
||||
import Styles from "@/constants/Styles";
|
||||
@@ -81,6 +80,7 @@ export default function DetailDiscussionGeneral() {
|
||||
comment: ''
|
||||
})
|
||||
const [viewEdit, setViewEdit] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const onValueChange = reference.on('value', snapshot => {
|
||||
@@ -247,7 +247,7 @@ export default function DetailDiscussionGeneral() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={() => handleRefresh()}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -370,7 +370,7 @@ export default function DetailDiscussionGeneral() {
|
||||
Platform.OS == 'android' && Styles.mb12,
|
||||
]}
|
||||
>
|
||||
<MaterialIcons name="send" size={25} style={(loadingSendKomentar || selectKomentar.comment == '' || regexOnlySpacesOrEnter.test(selectKomentar.comment) || data?.status === 2 || !data?.isActive || (!memberDiscussion && (entityUser.role == "user" || entityUser.role == "coadmin"))) ? {color:colors.dimmed} : {color:colors.tint}} />
|
||||
<MaterialIcons name="send" size={25} style={(loadingSendKomentar || selectKomentar.comment == '' || regexOnlySpacesOrEnter.test(selectKomentar.comment) || data?.status === 2 || !data?.isActive || (!memberDiscussion && (entityUser.role == "user" || entityUser.role == "coadmin"))) ? { color: colors.dimmed } : { color: colors.tint }} />
|
||||
</Pressable>
|
||||
}
|
||||
/>
|
||||
@@ -396,7 +396,7 @@ export default function DetailDiscussionGeneral() {
|
||||
Platform.OS == 'android' && Styles.mb12,
|
||||
]}
|
||||
>
|
||||
<MaterialIcons name="send" size={25} style={(loadingSendKomentar || komentar == '' || regexOnlySpacesOrEnter.test(komentar) || data?.status === 2 || !data?.isActive || (!memberDiscussion && (entityUser.role == "user" || entityUser.role == "coadmin"))) ? {color: colors.dimmed} : {color:colors.tint}} />
|
||||
<MaterialIcons name="send" size={25} style={(loadingSendKomentar || komentar == '' || regexOnlySpacesOrEnter.test(komentar) || data?.status === 2 || !data?.isActive || (!memberDiscussion && (entityUser.role == "user" || entityUser.role == "coadmin"))) ? { color: colors.dimmed } : { color: colors.tint }} />
|
||||
</Pressable>
|
||||
}
|
||||
/>
|
||||
@@ -425,17 +425,27 @@ export default function DetailDiscussionGeneral() {
|
||||
icon={<Ionicons name="trash-outline" color={colors.text} size={25} />}
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus komentar?',
|
||||
onPress: () => {
|
||||
handleDeleteKomentar()
|
||||
}
|
||||
})
|
||||
setVisible(false)
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus komentar?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteKomentar()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -94,7 +94,7 @@ export default function AddMemberDiscussionDetail() {
|
||||
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
@@ -127,7 +127,7 @@ export default function AddMemberDiscussionDetail() {
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<View style={[Styles.p15, { backgroundColor: colors.background }]}>
|
||||
<View style={[Styles.p15, {flex: 1, backgroundColor: colors.background }]}>
|
||||
<InputSearch onChange={setSearch} value={search} />
|
||||
|
||||
{
|
||||
@@ -188,6 +188,6 @@ export default function AddMemberDiscussionDetail() {
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -166,7 +166,7 @@ export default function Discussion() {
|
||||
leftBottomInfo={
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
<Ionicons name="chatbox-ellipses-outline" size={18} color={colors.dimmed} style={Styles.mr05} />
|
||||
<Text style={[Styles.textInformation, {color: colors.dimmed}, Styles.mb05]}>Diskusikan</Text>
|
||||
<Text style={[Styles.textInformation, { color: colors.dimmed }, Styles.mb05]}>Diskusikan</Text>
|
||||
</View>
|
||||
}
|
||||
rightBottomInfo={`${item.total_komentar} Komentar`}
|
||||
@@ -182,7 +182,7 @@ export default function Discussion() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import DrawerBottom from "@/components/drawerBottom";
|
||||
import ImageUser from "@/components/imageNew";
|
||||
import MenuItemRow from "@/components/menuItemRow";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import SkeletonTwoItem from "@/components/skeletonTwoItem";
|
||||
import Text from '@/components/Text';
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
@@ -36,6 +36,8 @@ export default function MemberDiscussionDetail() {
|
||||
const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
@@ -151,20 +153,28 @@ export default function MemberDiscussionDetail() {
|
||||
title="Keluarkan"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin mengeluarkan anggota?',
|
||||
onPress: () => {
|
||||
handleDeleteUser()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin mengeluarkan anggota?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteUser()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi"
|
||||
import ModalConfirmation from "@/components/ModalConfirmation"
|
||||
import AppHeader from "@/components/AppHeader"
|
||||
import BorderBottomItem from "@/components/borderBottomItem"
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader"
|
||||
@@ -57,6 +57,7 @@ export default function DetailEventCalendar() {
|
||||
const dispatch = useDispatch()
|
||||
const entityUser = useSelector((state: any) => state.user);
|
||||
const [isMemberDivision, setIsMemberDivision] = useState(false);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
@@ -179,6 +180,7 @@ export default function DetailEventCalendar() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -301,18 +303,26 @@ export default function DetailEventCalendar() {
|
||||
title="Keluarkan"
|
||||
onPress={() => {
|
||||
setModalMember(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin mengeluarkan anggota?',
|
||||
onPress: () => {
|
||||
handleDeleteUser()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin mengeluarkan anggota?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteUser()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Keluar"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -155,6 +155,7 @@ export default function CalendarDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
style={[Styles.h100]}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import BorderBottomItem2 from "@/components/borderBottomItem2";
|
||||
@@ -8,6 +7,7 @@ import ImageUser from "@/components/imageNew";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import LabelStatus from "@/components/labelStatus";
|
||||
import MenuItemRow from "@/components/menuItemRow";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import Skeleton from "@/components/skeleton";
|
||||
import SkeletonContent from "@/components/skeletonContent";
|
||||
import Text from "@/components/Text";
|
||||
@@ -23,9 +23,9 @@ import {
|
||||
} 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 { useTheme } from "@/providers/ThemeProvider";
|
||||
import { useHeaderHeight } from '@react-navigation/elements';
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
@@ -92,6 +92,7 @@ export default function DiscussionDetail() {
|
||||
comment: ''
|
||||
})
|
||||
const [viewEdit, setViewEdit] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
|
||||
|
||||
@@ -314,6 +315,7 @@ export default function DiscussionDetail() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -385,6 +387,7 @@ export default function DiscussionDetail() {
|
||||
desc={item.comment}
|
||||
rightBottomInfo={item.isEdited ? "Edited" : ""}
|
||||
descEllipsize={detailMore.includes(item.id) ? false : true}
|
||||
bgColor="transparent"
|
||||
onPress={() => {
|
||||
setDetailMore((prev: any) => {
|
||||
if (prev.includes(item.id)) {
|
||||
@@ -541,17 +544,27 @@ export default function DiscussionDetail() {
|
||||
icon={<Ionicons name="trash-outline" color={colors.text} size={25} />}
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus komentar?',
|
||||
onPress: () => {
|
||||
handleDeleteKomentar()
|
||||
}
|
||||
})
|
||||
setVisible(false)
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus komentar?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteKomentar()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ export default function DiscussionDivision() {
|
||||
</View>
|
||||
}
|
||||
rightBottomInfo={item.total_komentar + ' Komentar'}
|
||||
bgColor="transparent"
|
||||
/>
|
||||
)
|
||||
}}
|
||||
@@ -203,6 +204,7 @@ export default function DiscussionDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import { ButtonHeader } from "@/components/buttonHeader";
|
||||
import HeaderRightDocument from "@/components/document/headerDocument";
|
||||
@@ -89,6 +89,7 @@ export default function DocumentDivision() {
|
||||
const [loadingOpen, setLoadingOpen] = useState(false)
|
||||
const [isMemberDivision, setIsMemberDivision] = useState(false)
|
||||
const entityUser = useSelector((state: any) => state.user)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [bodyRename, setBodyRename] = useState({
|
||||
id: "",
|
||||
name: "",
|
||||
@@ -414,6 +415,7 @@ export default function DocumentDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
@@ -499,13 +501,7 @@ export default function DocumentDivision() {
|
||||
}
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
AlertKonfirmasi({
|
||||
title: "Konfirmasi",
|
||||
desc: "Apakah anda yakin ingin menghapus dokumen?",
|
||||
onPress: () => {
|
||||
handleDelete();
|
||||
},
|
||||
});
|
||||
setShowDeleteModal(true)
|
||||
}}
|
||||
column="many"
|
||||
color="white"
|
||||
@@ -612,6 +608,19 @@ export default function DocumentDivision() {
|
||||
value={id}
|
||||
item={selectedFiles[0]?.id}
|
||||
/>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus dokumen?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ export default function DetailTaskDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -235,6 +235,7 @@ export default function ListTask() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@@ -301,6 +302,7 @@ export default function ListTask() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ButtonSelect from "@/components/buttonSelect";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import ModalAddDetailTugasTask from "@/components/task/modalAddDetailTugasTask";
|
||||
import Text from "@/components/Text";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { apiEditTaskTugas, apiGetTaskTugas } from "@/lib/api";
|
||||
import { formatDateOnly } from "@/lib/fun_formatDateOnly";
|
||||
import { getDatesInRange } from "@/lib/fun_getDatesInRange";
|
||||
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { useHeaderHeight } from '@react-navigation/elements';
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import 'intl';
|
||||
@@ -19,7 +20,6 @@ import { useEffect, useState } from "react";
|
||||
import {
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
Pressable,
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
View
|
||||
@@ -263,7 +263,7 @@ export default function UpdateProjectTaskDivision() {
|
||||
<Text style={[Styles.mb05]}>
|
||||
Tanggal Mulai <Text style={{ color: colors.error }}>*</Text>
|
||||
</Text>
|
||||
<View style={[Styles.wrapPaper, Styles.p10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.noShadow, Styles.borderAll, Styles.p10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<Text style={{ textAlign: "center" }}>{from}</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -271,7 +271,7 @@ export default function UpdateProjectTaskDivision() {
|
||||
<Text style={[Styles.mb05]}>
|
||||
Tanggal Berakhir <Text style={{ color: colors.error }}>*</Text>
|
||||
</Text>
|
||||
<View style={[Styles.wrapPaper, Styles.p10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.noShadow, Styles.borderAll, Styles.p10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<Text style={{ textAlign: "center" }}>{to}</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -281,13 +281,14 @@ export default function UpdateProjectTaskDivision() {
|
||||
Tanggal tidak boleh kosong
|
||||
</Text>
|
||||
)}
|
||||
<Pressable
|
||||
{/* <Pressable
|
||||
style={[Styles.btnTab, Styles.btnLainnya, dsbButton && Styles.btnDisabled]}
|
||||
disabled={dsbButton}
|
||||
onPress={() => { setModalDetail(true) }}
|
||||
>
|
||||
<Text style={[dsbButton ? Styles.cGray : Styles.cWhite]}>Detail</Text>
|
||||
</Pressable>
|
||||
</Pressable> */}
|
||||
<ButtonSelect value="Detail" onPress={() => { setModalDetail(true) }} />
|
||||
</View>
|
||||
<InputForm
|
||||
label="Judul Tugas"
|
||||
|
||||
@@ -78,6 +78,7 @@ export default function DetailDivisionFitur() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
showsVerticalScrollIndicator={false}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi"
|
||||
import ModalConfirmation from "@/components/ModalConfirmation"
|
||||
import AppHeader from "@/components/AppHeader"
|
||||
import BorderBottomItem from "@/components/borderBottomItem"
|
||||
import HeaderRightDivisionInfo from "@/components/division/headerDivisionInfo"
|
||||
@@ -59,14 +59,13 @@ export default function InformationDivision() {
|
||||
name: '',
|
||||
isAdmin: false
|
||||
})
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
function handleMemberOut() {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin mengeluarkan anggota?',
|
||||
onPress: () => { memberOut() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}
|
||||
|
||||
async function memberOut() {
|
||||
@@ -187,6 +186,7 @@ export default function InformationDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
style={[Styles.h100, { backgroundColor: colors.background }]}
|
||||
@@ -287,6 +287,19 @@ export default function InformationDivision() {
|
||||
</Pressable>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin mengeluarkan anggota?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
memberOut()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Keluar"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import ButtonNextHeader from "@/components/buttonNextHeader";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
@@ -25,6 +25,7 @@ export default function CreateDivision() {
|
||||
const entityUser = useSelector((state: any) => state.user)
|
||||
const userLogin = useSelector((state: any) => state.entities)
|
||||
const [loadingBtn, setLoadingBtn] = useState(false)
|
||||
const [showWarningModal, setShowWarningModal] = useState(false)
|
||||
const [error, setError] = useState({
|
||||
idGroup: false,
|
||||
name: false,
|
||||
@@ -69,12 +70,7 @@ export default function CreateDivision() {
|
||||
const response = await apiCheckDivisionName({ data: { ...dataForm }, user: hasil })
|
||||
if (response.success) {
|
||||
if (!response.available) {
|
||||
AlertKonfirmasi({
|
||||
title: 'Peringatan',
|
||||
category: 'warning',
|
||||
desc: 'Nama divisi sudah ada. Tidak dapat membuat divisi dengan nama yang sama',
|
||||
onPress: () => { }
|
||||
})
|
||||
setShowWarningModal(true)
|
||||
} else {
|
||||
handleSetData()
|
||||
}
|
||||
@@ -181,6 +177,15 @@ export default function CreateDivision() {
|
||||
open={isSelect}
|
||||
valChoose={chooseGroup.val}
|
||||
/>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showWarningModal}
|
||||
title="Peringatan"
|
||||
message="Nama divisi sudah ada. Tidak dapat membuat divisi dengan nama yang sama"
|
||||
onConfirm={() => setShowWarningModal(false)}
|
||||
onCancel={() => setShowWarningModal(false)}
|
||||
confirmText="Oke"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -253,6 +253,7 @@ export default function ListDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@@ -288,6 +289,7 @@ export default function ListDivision() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import ModalSelect from "@/components/modalSelect";
|
||||
@@ -219,24 +219,40 @@ export default function EditProfile() {
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
headerLeft: () => (
|
||||
<ButtonBackHeader
|
||||
onPress={() => {
|
||||
router.back();
|
||||
}}
|
||||
/>
|
||||
),
|
||||
// headerLeft: () => (
|
||||
// <ButtonBackHeader
|
||||
// onPress={() => {
|
||||
// router.back();
|
||||
// }}
|
||||
// />
|
||||
// ),
|
||||
headerTitle: "Edit Profile",
|
||||
headerTitleAlign: "center",
|
||||
headerRight: () => (
|
||||
<ButtonSaveHeader
|
||||
disable={disableBtn || loading ? true : false}
|
||||
category="update"
|
||||
onPress={() => {
|
||||
handleEdit()
|
||||
}}
|
||||
header: () => (
|
||||
<AppHeader
|
||||
title="Edit Profile"
|
||||
showBack={true}
|
||||
onPressLeft={() => router.back()}
|
||||
right={
|
||||
<ButtonSaveHeader
|
||||
disable={disableBtn || loading ? true : false}
|
||||
category="update"
|
||||
onPress={() => {
|
||||
handleEdit()
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
),
|
||||
)
|
||||
// headerRight: () => (
|
||||
// <ButtonSaveHeader
|
||||
// disable={disableBtn || loading ? true : false}
|
||||
// category="update"
|
||||
// onPress={() => {
|
||||
// handleEdit()
|
||||
// }}
|
||||
// />
|
||||
// ),
|
||||
}}
|
||||
/>
|
||||
<KeyboardAvoidingView
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import { ButtonForm } from "@/components/buttonForm";
|
||||
import ButtonTab from "@/components/buttonTab";
|
||||
@@ -35,6 +35,7 @@ export default function Index() {
|
||||
const [search, setSearch] = useState('')
|
||||
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [status, setStatus] = useState<'true' | 'false'>('true')
|
||||
const [loadingSubmit, setLoadingSubmit] = useState(false)
|
||||
const [idChoose, setIdChoose] = useState('')
|
||||
@@ -189,7 +190,7 @@ export default function Index() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@@ -205,11 +206,9 @@ export default function Index() {
|
||||
title={activeChoose ? "Non Aktifkan" : "Aktifkan"}
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: activeChoose ? 'Apakah anda yakin ingin menonaktifkan data?' : 'Apakah anda yakin ingin mengaktifkan data?',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
<MenuItemRow
|
||||
@@ -244,6 +243,19 @@ export default function Index() {
|
||||
</View>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message={activeChoose ? 'Apakah anda yakin ingin menonaktifkan data?' : 'Apakah anda yakin ingin mengaktifkan data?'}
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText={activeChoose ? "Nonaktifkan" : "Aktifkan"}
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</View >
|
||||
|
||||
)
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function Home() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
showsVerticalScrollIndicator={false}
|
||||
|
||||
@@ -99,7 +99,7 @@ export default function MemberDetail() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.text}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -171,7 +171,7 @@ export default function Index() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import BorderBottomItemVertical from "@/components/borderBottomItemVertical";
|
||||
import SkeletonTwoItem from "@/components/skeletonTwoItem";
|
||||
import Text from "@/components/Text";
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
@@ -116,11 +117,11 @@ export default function Notification() {
|
||||
getItem={getItem}
|
||||
renderItem={({ item, index }: { item: Props, index: number }) => {
|
||||
return (
|
||||
<BorderBottomItem
|
||||
<BorderBottomItemVertical
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, item.isRead ? ColorsStatus.secondary : ColorsStatus.primary]}>
|
||||
<Feather name="bell" size={25} color="white" />
|
||||
<View style={[Styles.iconContent, item.isRead && ColorsStatus.secondary]}>
|
||||
<Feather name="bell" size={25} color="black" />
|
||||
</View>
|
||||
}
|
||||
title={item.title}
|
||||
@@ -129,8 +130,8 @@ export default function Notification() {
|
||||
textColor={item.isRead ? 'gray' : colors.text}
|
||||
onPress={() => {
|
||||
handleReadNotification(item.id, item.category, item.idContent)
|
||||
|
||||
}}
|
||||
bgColor={'transparent'}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
@@ -142,7 +143,7 @@ export default function Notification() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import { ButtonForm } from "@/components/buttonForm";
|
||||
import ButtonTab from "@/components/buttonTab";
|
||||
@@ -50,6 +50,7 @@ export default function Index() {
|
||||
name: false,
|
||||
});
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
const dispatch = useDispatch()
|
||||
const update = useSelector((state: any) => state.positionUpdate)
|
||||
@@ -215,7 +216,7 @@ export default function Index() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@@ -230,11 +231,9 @@ export default function Index() {
|
||||
title={chooseData.active ? 'Non Aktifkan' : "Aktifkan"}
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: chooseData.active ? 'Apakah anda yakin ingin menonaktifkan data?' : 'Apakah anda yakin ingin mengaktifkan data?',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
<MenuItemRow
|
||||
@@ -271,6 +270,19 @@ export default function Index() {
|
||||
</View>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message={chooseData.active ? 'Apakah anda yakin ingin menonaktifkan data?' : 'Apakah anda yakin ingin mengaktifkan data?'}
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText={chooseData.active ? "Nonaktifkan" : "Aktifkan"}
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import { ButtonHeader } from "@/components/buttonHeader";
|
||||
import ItemDetailMember from "@/components/itemDetailMember";
|
||||
@@ -6,39 +5,42 @@ import Text from "@/components/Text";
|
||||
import { assetUserImage } from "@/constants/AssetsError";
|
||||
import { ConstEnv } from "@/constants/ConstEnv";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiGetProfile } from "@/lib/api";
|
||||
import { setEntities } from "@/lib/entitiesSlice";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { AntDesign, Ionicons } from "@expo/vector-icons";
|
||||
import { router, Stack } from "expo-router";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
import { router, Stack } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { Image, Modal, Pressable, SafeAreaView, ScrollView, TouchableOpacity, View } from "react-native";
|
||||
import { Image, Pressable, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import ImageViewing from 'react-native-image-viewing';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
export default function Profile() {
|
||||
const { signOut } = useAuthSession()
|
||||
const { theme, setTheme, colors } = useTheme();
|
||||
const { colors } = useTheme();
|
||||
const entities = useSelector((state: any) => state.entities)
|
||||
const [error, setError] = useState(false)
|
||||
const [preview, setPreview] = useState(false)
|
||||
const [showThemeModal, setShowThemeModal] = useState(false)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const dispatch = useDispatch()
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
|
||||
const ThemeOption = ({ label, value, icon }: { label: string, value: 'light' | 'dark' | 'system', icon: string }) => (
|
||||
<TouchableOpacity
|
||||
style={[Styles.itemSelectModal, { backgroundColor: theme === value ? colors.primary + '10' : 'transparent', borderColor: colors.icon + '20' }]}
|
||||
onPress={() => {
|
||||
setTheme(value);
|
||||
setShowThemeModal(false);
|
||||
}}
|
||||
>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<Ionicons name={icon as any} size={20} color={theme === value ? colors.primary : colors.text} style={{ marginRight: 10 }} />
|
||||
<Text style={{ color: colors.text, fontWeight: theme === value ? 'bold' : 'normal' }}>{label}</Text>
|
||||
</View>
|
||||
{theme === value && <Ionicons name="checkmark" size={20} color={colors.primary} />}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
async function handleUserLogin() {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
apiGetProfile({ id: hasil })
|
||||
.then((data) => dispatch(setEntities(data.data)))
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
});
|
||||
}
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
handleUserLogin()
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||
@@ -53,13 +55,9 @@ export default function Profile() {
|
||||
onPressLeft={() => router.back()}
|
||||
right={
|
||||
<ButtonHeader
|
||||
item={<AntDesign name="logout" size={20} color="white" />}
|
||||
item={<Feather name="settings" size={20} color="white" />}
|
||||
onPress={() => {
|
||||
AlertKonfirmasi({
|
||||
title: 'Keluar',
|
||||
desc: 'Apakah anda yakin ingin keluar?',
|
||||
onPress: () => { signOut() }
|
||||
})
|
||||
router.push('/setting')
|
||||
}}
|
||||
/>
|
||||
}
|
||||
@@ -67,7 +65,16 @@ export default function Profile() {
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<ScrollView style={[Styles.h100, { backgroundColor: colors.background }]}>
|
||||
<ScrollView
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
style={[Styles.h100, { backgroundColor: colors.background }]}
|
||||
>
|
||||
<View style={{ flexDirection: 'column' }}>
|
||||
<LinearGradient
|
||||
colors={[colors.header, colors.homeGradient]}
|
||||
@@ -84,31 +91,8 @@ export default function Profile() {
|
||||
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{entities.role}</Text>
|
||||
</LinearGradient>
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={[Styles.rowSpaceBetween, Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>Tampilan</Text>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowThemeModal(true)}
|
||||
style={[Styles.wrapItemBorderAll, { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderColor: colors.icon + '40', backgroundColor: colors.background }]}
|
||||
>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<Ionicons name="color-palette-outline" size={20} color={colors.text} style={{ marginRight: 10 }} />
|
||||
<Text style={{ color: colors.text }}>Tema Aplikasi</Text>
|
||||
</View>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<Text style={{ color: colors.icon, marginRight: 5, fontSize: 13 }}>
|
||||
{theme === 'light' ? 'Terang' : theme === 'dark' ? 'Gelap' : 'Sistem'}
|
||||
</Text>
|
||||
<Ionicons name="chevron-forward" size={16} color={colors.icon} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={[Styles.rowSpaceBetween, Styles.mt15]}>
|
||||
<View style={[Styles.rowSpaceBetween]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>Informasi</Text>
|
||||
{
|
||||
entities.idUserRole != "developer" && <Text onPress={() => { router.push('/edit-profile') }} style={[Styles.textLink]}>Edit</Text>
|
||||
}
|
||||
</View>
|
||||
{/* Note: ItemDetailMember might need updates to support dynamic colors if it uses default text colors */}
|
||||
<ItemDetailMember category="nik" value={entities.nik} />
|
||||
@@ -121,29 +105,6 @@ export default function Profile() {
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<Modal
|
||||
animationType="fade"
|
||||
transparent={true}
|
||||
visible={showThemeModal}
|
||||
onRequestClose={() => setShowThemeModal(false)}
|
||||
>
|
||||
<TouchableOpacity style={Styles.modalBgTransparant} activeOpacity={1} onPress={() => setShowThemeModal(false)}>
|
||||
<View style={[Styles.modalContent, { backgroundColor: colors.background }]}>
|
||||
<View style={[Styles.titleContainer, { backgroundColor: colors.background, borderBottomColor: colors.icon + '20', borderBottomWidth: 1 }]}>
|
||||
<Text style={[Styles.textSubtitle, { color: colors.text }]}>Pilih Tema</Text>
|
||||
<TouchableOpacity onPress={() => setShowThemeModal(false)}>
|
||||
<Ionicons name="close" size={24} color={colors.text} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={{ padding: 10 }}>
|
||||
<ThemeOption label="Terang" value="light" icon="sunny-outline" />
|
||||
<ThemeOption label="Gelap" value="dark" icon="moon-outline" />
|
||||
<ThemeOption label="Sistem" value="system" icon="phone-portrait-outline" />
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
|
||||
<ImageViewing
|
||||
images={[{ uri: error ? assetUserImage.uri : `${ConstEnv.url_storage}/files/${entities.img}` }]}
|
||||
imageIndex={0}
|
||||
|
||||
@@ -118,7 +118,7 @@ export default function DetailProject() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -275,6 +275,7 @@ export default function ListProject() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@@ -353,6 +354,7 @@ export default function ListProject() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ButtonSelect from "@/components/buttonSelect";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import ModalAddDetailTugasProject from "@/components/project/modalAddDetailTugasProject";
|
||||
import Text from "@/components/Text";
|
||||
@@ -16,7 +17,7 @@ import 'intl';
|
||||
import 'intl/locale-data/jsonp/id';
|
||||
import moment from "moment";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { KeyboardAvoidingView, Platform, Pressable, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { KeyboardAvoidingView, Platform, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import DateTimePicker, { DateType } from "react-native-ui-datepicker";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
@@ -235,13 +236,13 @@ export default function UpdateProjectTask() {
|
||||
<View style={[Styles.rowSpaceBetween]}>
|
||||
<View style={[{ width: '48%' }]}>
|
||||
<Text style={[Styles.mb05]}>Tanggal Mulai <Text style={{ color: colors.error }}>*</Text></Text>
|
||||
<View style={[Styles.wrapPaper, Styles.p10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.noShadow, Styles.borderAll, Styles.p10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<Text style={{ textAlign: 'center' }}>{from}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={[{ width: '48%' }]}>
|
||||
<Text style={[Styles.mb05]}>Tanggal Berakhir <Text style={{ color: colors.error }}>*</Text></Text>
|
||||
<View style={[Styles.wrapPaper, Styles.p10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, Styles.noShadow, Styles.borderAll, Styles.p10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<Text style={{ textAlign: 'center' }}>{to}</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -249,13 +250,14 @@ export default function UpdateProjectTask() {
|
||||
{
|
||||
(error.endDate || error.startDate) && <Text style={[Styles.textInformation, { color: colors.error }, Styles.mt05]}>Tanggal tidak boleh kosong</Text>
|
||||
}
|
||||
<Pressable
|
||||
{/* <Pressable
|
||||
style={[Styles.btnTab, Styles.btnLainnya, dsbButton && Styles.btnDisabled]}
|
||||
disabled={dsbButton}
|
||||
onPress={() => { setModalDetail(true) }}
|
||||
>
|
||||
<Text style={[dsbButton ? Styles.cGray : Styles.cWhite]}>Detail</Text>
|
||||
</Pressable>
|
||||
</Pressable> */}
|
||||
<ButtonSelect value="Detail" onPress={() => { setModalDetail(true) }} />
|
||||
</View>
|
||||
<InputForm
|
||||
label="Judul Tugas"
|
||||
|
||||
@@ -103,7 +103,7 @@ export default function Search() {
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
tintColor={colors.primary}
|
||||
tintColor={colors.icon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
186
app/(application)/setting/index.tsx
Normal file
186
app/(application)/setting/index.tsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||
import Text from "@/components/Text";
|
||||
import ButtonSetting from "@/components/buttonSetting";
|
||||
import DrawerBottom from "@/components/drawerBottom";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiRegisteredToken, apiUnregisteredToken } from "@/lib/api";
|
||||
import { checkPermission, getToken, openSettings, requestPermission } from "@/lib/useNotification";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { Feather, Ionicons } from "@expo/vector-icons";
|
||||
import { router } from "expo-router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { AppState, AppStateStatus, Pressable, View } from "react-native";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export default function ListSetting() {
|
||||
const { theme, setTheme, colors } = useTheme()
|
||||
const { signOut } = useAuthSession()
|
||||
const [isNotificationEnabled, setIsNotificationEnabled] = useState<boolean | null>(null);
|
||||
const entities = useSelector((state: any) => state.entities)
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [modalConfig, setModalConfig] = useState({
|
||||
title: '',
|
||||
message: '',
|
||||
confirmText: 'Buka Pengaturan',
|
||||
onConfirm: () => { }
|
||||
});
|
||||
|
||||
const [showLogoutModal, setShowLogoutModal] = useState(false)
|
||||
const [showThemeModal, setShowThemeModal] = useState(false)
|
||||
|
||||
const registerToken = async () => {
|
||||
try {
|
||||
const token = await getToken();
|
||||
if (token) {
|
||||
await apiRegisteredToken({ user: entities.id, token });
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error registering token:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const unregisterToken = async () => {
|
||||
try {
|
||||
const token = await getToken();
|
||||
if (token) {
|
||||
await apiUnregisteredToken({ user: entities.id, token });
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error unregistering token:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const checkNotif = useCallback(async () => {
|
||||
const status = await checkPermission();
|
||||
setIsNotificationEnabled((prev) => {
|
||||
if (prev === false && status === true) {
|
||||
registerToken();
|
||||
} else if (prev === true && status === false) {
|
||||
unregisterToken();
|
||||
}
|
||||
return !!status;
|
||||
});
|
||||
}, [entities.id]);
|
||||
|
||||
useEffect(() => {
|
||||
checkNotif();
|
||||
|
||||
const subscription = AppState.addEventListener('change', (nextAppState: AppStateStatus) => {
|
||||
if (nextAppState === 'active') {
|
||||
checkNotif();
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
subscription.remove();
|
||||
};
|
||||
}, [checkNotif]);
|
||||
|
||||
const handleToggleNotif = async () => {
|
||||
if (isNotificationEnabled) {
|
||||
setModalConfig({
|
||||
title: "Matikan Notifikasi?",
|
||||
message: "Anda akan diarahkan ke pengaturan sistem untuk mematikan notifikasi.",
|
||||
confirmText: "Buka Pengaturan",
|
||||
onConfirm: () => {
|
||||
setModalVisible(false);
|
||||
openSettings();
|
||||
}
|
||||
});
|
||||
setModalVisible(true);
|
||||
} else {
|
||||
const granted = await requestPermission();
|
||||
if (granted) {
|
||||
setIsNotificationEnabled(true);
|
||||
registerToken();
|
||||
} else {
|
||||
setModalConfig({
|
||||
title: "Aktifkan Notifikasi?",
|
||||
message: "Izin notifikasi tidak diberikan. Buka pengaturan sistem untuk mengaktifkannya?",
|
||||
confirmText: "Buka Pengaturan",
|
||||
onConfirm: () => {
|
||||
setModalVisible(false);
|
||||
openSettings();
|
||||
}
|
||||
});
|
||||
setModalVisible(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const ThemeOption = ({ label, value, icon }: { label: string, value: 'light' | 'dark' | 'system', icon: string }) => (
|
||||
<Pressable
|
||||
style={[Styles.itemSelectModal, { borderColor: colors.icon + '20' }]}
|
||||
onPress={() => {
|
||||
setTheme(value);
|
||||
}}
|
||||
>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<Ionicons name={icon as any} size={20} color={colors.text} style={{ marginRight: 10 }} />
|
||||
<Text style={{ color: colors.text }}>{label}</Text>
|
||||
</View>
|
||||
{theme === value && <Ionicons name="checkmark" size={20} color={colors.text} />}
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={[Styles.p15, { flex: 1, backgroundColor: colors.background }]}>
|
||||
<View style={[Styles.wrapPaper, { backgroundColor: colors.card, borderColor: colors.icon + '20' }, Styles.p0, Styles.round05]}>
|
||||
{
|
||||
entities.idUserRole != "developer" &&
|
||||
<ButtonSetting
|
||||
title="Edit Profile"
|
||||
icon={<Feather name="user" size={20} color={colors.text} />}
|
||||
onPress={() => { router.push('/edit-profile') }}
|
||||
/>
|
||||
}
|
||||
<ButtonSetting
|
||||
title="Tema Aplikasi"
|
||||
icon={<Ionicons name="color-palette-outline" size={20} color={colors.text} />}
|
||||
onPress={() => setShowThemeModal(true)}
|
||||
value={theme === 'light' ? 'Terang' : theme === 'dark' ? 'Gelap' : 'Sistem'}
|
||||
/>
|
||||
<ButtonSetting
|
||||
title="Notifikasi"
|
||||
icon={<Feather name="bell" size={20} color={colors.text} />}
|
||||
onPress={handleToggleNotif}
|
||||
value={isNotificationEnabled === null ? 'Memuat...' : isNotificationEnabled ? 'Aktif' : 'Nonaktif'}
|
||||
/>
|
||||
<ButtonSetting
|
||||
title="Keluar"
|
||||
icon={<Feather name="log-out" size={20} color={colors.text} />}
|
||||
onPress={() => setShowLogoutModal(true)}
|
||||
borderBottom={false}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={modalVisible}
|
||||
title={modalConfig.title}
|
||||
message={modalConfig.message}
|
||||
confirmText={modalConfig.confirmText}
|
||||
onConfirm={modalConfig.onConfirm}
|
||||
onCancel={() => setModalVisible(false)}
|
||||
/>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showLogoutModal}
|
||||
title="Keluar"
|
||||
message="Apakah anda yakin ingin keluar?"
|
||||
onConfirm={() => {
|
||||
setShowLogoutModal(false)
|
||||
signOut()
|
||||
}}
|
||||
onCancel={() => setShowLogoutModal(false)}
|
||||
confirmText="Keluar"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
<DrawerBottom animation="slide" isVisible={showThemeModal} setVisible={setShowThemeModal} title="Tema Aplikasi">
|
||||
<ThemeOption label="Terang" value="light" icon="sunny-outline" />
|
||||
<ThemeOption label="Gelap" value="dark" icon="moon-outline" />
|
||||
<ThemeOption label="Sistem" value="system" icon="phone-portrait-outline" />
|
||||
</DrawerBottom>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -20,10 +20,16 @@ export default function Index() {
|
||||
|
||||
const { signIn } = useAuthSession();
|
||||
const login = (): void => {
|
||||
const random: string = 'contohLoginMobileDarmasaba';
|
||||
var mytexttoEncryption = "contohLoginMobileDarmasaba"
|
||||
const encrypted = CryptoES.AES.encrypt(mytexttoEncryption, ConstEnv.pass_encrypt).toString();
|
||||
signIn(encrypted);
|
||||
// WARNING: This is a hardcoded bypass for development purposes.
|
||||
// It should be removed or secured before production release.
|
||||
if (__DEV__) {
|
||||
const random: string = 'contohLoginMobileDarmasaba';
|
||||
var mytexttoEncryption = "contohLoginMobileDarmasaba"
|
||||
const encrypted = CryptoES.AES.encrypt(mytexttoEncryption, ConstEnv.pass_encrypt).toString();
|
||||
signIn(encrypted);
|
||||
} else {
|
||||
console.warn("Bypass login disabled in production.");
|
||||
}
|
||||
}
|
||||
return (
|
||||
<View style={[Styles.wrapLogin, { backgroundColor: colors.background }]} >
|
||||
|
||||
BIN
assets/images/bgproject-dark.png
Normal file
BIN
assets/images/bgproject-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
assets/images/bgproject-light.png
Normal file
BIN
assets/images/bgproject-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
assets/images/cogniti-dark.png
Normal file
BIN
assets/images/cogniti-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/cogniti-light.png
Normal file
BIN
assets/images/cogniti-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/images/logo-dark.png
Normal file
BIN
assets/images/logo-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
82
components/ModalConfirmation.tsx
Normal file
82
components/ModalConfirmation.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import Styles from '@/constants/Styles';
|
||||
import { useTheme } from '@/providers/ThemeProvider';
|
||||
import React from 'react';
|
||||
import { Modal, TouchableOpacity, View } from 'react-native';
|
||||
import Text from './Text';
|
||||
|
||||
interface ModalConfirmationProps {
|
||||
visible: boolean;
|
||||
title: string;
|
||||
message: string;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
isDestructive?: boolean;
|
||||
}
|
||||
|
||||
const ModalConfirmation: React.FC<ModalConfirmationProps> = ({
|
||||
visible,
|
||||
title,
|
||||
message,
|
||||
onConfirm,
|
||||
onCancel,
|
||||
confirmText = 'Ya',
|
||||
cancelText = 'Batal',
|
||||
isDestructive = false,
|
||||
}) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
transparent
|
||||
visible={visible}
|
||||
animationType="fade"
|
||||
onRequestClose={onCancel}
|
||||
>
|
||||
<View style={Styles.modalOverlay}>
|
||||
<View style={[Styles.modalConfirmContainer, { backgroundColor: colors.modalBackground }]}>
|
||||
<View style={Styles.modalConfirmContent}>
|
||||
<Text style={Styles.modalConfirmTitle}>{title}</Text>
|
||||
<Text style={[Styles.modalConfirmMessage, { color: colors.text }]}>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={[Styles.modalConfirmDivider, { backgroundColor: colors.icon + '20' }]} />
|
||||
|
||||
<View style={Styles.modalConfirmFooter}>
|
||||
<TouchableOpacity
|
||||
style={Styles.modalConfirmButton}
|
||||
onPress={onCancel}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Text style={[Styles.modalConfirmButtonText, { color: colors.text }]}>
|
||||
{cancelText}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={[Styles.modalConfirmVerticalDivider, { backgroundColor: colors.icon + '20' }]} />
|
||||
|
||||
<TouchableOpacity
|
||||
style={Styles.modalConfirmButton}
|
||||
onPress={onConfirm}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
Styles.modalConfirmButtonText,
|
||||
{ color: isDestructive ? colors.error : colors.text }
|
||||
]}
|
||||
>
|
||||
{confirmText}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalConfirmation;
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -22,6 +22,7 @@ export default function HeaderRightAnnouncementDetail({ id }: Props) {
|
||||
const { colors } = useTheme();
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const update = useSelector((state: any) => state.announcementUpdate)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
|
||||
@@ -60,17 +61,26 @@ export default function HeaderRightAnnouncementDetail({ id }: Props) {
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus pengumuman ini?',
|
||||
onPress: () => {
|
||||
handleDelete()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus pengumuman ini?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -53,11 +53,10 @@ export default function ViewLogin({ onValidate }: Props) {
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||
<StatusBar style={theme === 'dark' ? 'light' : 'dark'} translucent={false} backgroundColor={colors.background} />
|
||||
<ToastCustom />
|
||||
<View style={[Styles.p20, Styles.h100]}>
|
||||
<View style={{ alignItems: "center", marginTop: 70, marginBottom: 50 }}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo.png")}
|
||||
source={theme === 'dark' ? require("../../assets/images/logo-dark.png") : require("../../assets/images/logo.png")}
|
||||
style={[{ width: 300, height: 150 }]}
|
||||
width={270}
|
||||
height={110}
|
||||
@@ -71,18 +70,28 @@ export default function ViewLogin({ onValidate }: Props) {
|
||||
}}
|
||||
type="numeric"
|
||||
placeholder="XXX-XXX-XXXX"
|
||||
round
|
||||
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
|
||||
info="Kami akan mengirim kode verifikasi melalui WhatsApp, guna mengonfirmasikan nomor Anda." />
|
||||
<ButtonForm
|
||||
text="MASUK"
|
||||
onPress={() => { handleCheckPhone() }}
|
||||
disabled={disableLogin}
|
||||
/>
|
||||
<View style={[{ width: '50%', alignSelf: 'center' }]}>
|
||||
<ButtonForm
|
||||
text="MASUK"
|
||||
onPress={() => { handleCheckPhone() }}
|
||||
disabled={disableLogin}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ flex: 1 }} />
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<Image
|
||||
source={theme === 'dark' ? require("../../assets/images/cogniti-dark.png") : require("../../assets/images/cogniti-light.png")}
|
||||
style={{ width: 86, height: 27 }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
loadingLogin && <ModalLoading isVisible={true} setVisible={setLoadingLogin} />
|
||||
}
|
||||
<ToastCustom position="bottom" />
|
||||
</SafeAreaView>
|
||||
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useTheme } from "@/providers/ThemeProvider";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import { StatusBar } from "expo-status-bar";
|
||||
import { useState } from "react";
|
||||
import { Image, Platform, View } from "react-native";
|
||||
import { Image, SafeAreaView, View } from "react-native";
|
||||
import { OtpInput } from "react-native-otp-entry";
|
||||
import Toast from 'react-native-toast-message';
|
||||
import { ButtonForm } from "../buttonForm";
|
||||
@@ -58,13 +58,12 @@ export default function ViewVerification({ phone, otp }: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||
<StatusBar style={theme === 'dark' ? 'light' : 'dark'} translucent={false} backgroundColor={colors.background} />
|
||||
<ToastCustom />
|
||||
<View style={[Styles.wrapLogin, { backgroundColor: colors.background }]} >
|
||||
<View style={[Styles.p20, Styles.h100]} >
|
||||
<View style={{ alignItems: "center", marginTop: 70, marginBottom: 50 }}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo.png")}
|
||||
source={theme === 'dark' ? require("../../assets/images/logo-dark.png") : require("../../assets/images/logo.png")}
|
||||
style={[{ width: 300, height: 150 }]}
|
||||
width={270}
|
||||
height={110}
|
||||
@@ -90,14 +89,25 @@ export default function ViewVerification({ phone, otp }: Props) {
|
||||
pinCodeTextStyle: { color: colors.text }
|
||||
}}
|
||||
/>
|
||||
<ButtonForm
|
||||
text="SUBMIT"
|
||||
onPress={() => { onCheckOtp() }}
|
||||
/>
|
||||
<Text style={[Styles.textInformation, Styles.mt05, Styles.cDefault, { textAlign: 'center', color: colors.tint }]}>
|
||||
Tidak Menerima kode verifikasi? <Text onPress={() => { resendOtp() }}>Kirim Ulang</Text>
|
||||
<View style={[{ width: '50%', alignSelf: 'center' }]}>
|
||||
<ButtonForm
|
||||
text="SUBMIT"
|
||||
onPress={() => { onCheckOtp() }}
|
||||
/>
|
||||
</View>
|
||||
<Text style={[Styles.textInformation, Styles.mt05, { textAlign: 'center', color: colors.dimmed }]}>
|
||||
Tidak Menerima kode verifikasi? <Text onPress={() => { resendOtp() }} style={[{ color: colors.tint }]}>Kirim Ulang</Text>
|
||||
</Text>
|
||||
<View style={{ flex: 1 }} />
|
||||
<View style={[{ alignItems: 'center' }]}>
|
||||
<Image
|
||||
source={theme === 'dark' ? require("../../assets/images/cogniti-dark.png") : require("../../assets/images/cogniti-light.png")}
|
||||
style={{ width: 86, height: 27 }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
<ToastCustom position="bottom" />
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -18,17 +18,14 @@ type Props = {
|
||||
rightBottomInfo?: React.ReactNode | string
|
||||
titleWeight?: 'normal' | 'bold'
|
||||
bgColor?: string
|
||||
width?: number
|
||||
descEllipsize?: boolean
|
||||
textColor?: string,
|
||||
colorPress?: boolean
|
||||
titleShowAll?: boolean
|
||||
}
|
||||
|
||||
export default function BorderBottomItem({ title, subtitle, icon, desc, onPress, onLongPress, rightTopInfo, borderType, leftBottomInfo, rightBottomInfo, titleWeight, bgColor, width, descEllipsize, textColor, colorPress, titleShowAll }: Props) {
|
||||
const lebarDim = Dimensions.get("window").width;
|
||||
export default function BorderBottomItem({ title, subtitle, icon, desc, onPress, onLongPress, rightTopInfo, borderType, leftBottomInfo, rightBottomInfo, titleWeight, bgColor, descEllipsize, textColor, colorPress, titleShowAll }: Props) {
|
||||
const { colors } = useTheme();
|
||||
const lebar = width ? lebarDim * width / 100 : 'auto';
|
||||
const textColorFix = textColor ? textColor : colors.text;
|
||||
const [isTap, setIsTap] = useState(false);
|
||||
|
||||
@@ -50,8 +47,8 @@ export default function BorderBottomItem({ title, subtitle, icon, desc, onPress,
|
||||
>
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
{icon}
|
||||
<View style={[Styles.rowSpaceBetween, width ? { width: lebar } : { width: '88%' }]}>
|
||||
<View style={[Styles.ml10, rightTopInfo ? { width: '70%' } : { width: '90%' }]}>
|
||||
<View style={[Styles.rowSpaceBetween, Styles.flex1]}>
|
||||
<View style={[Styles.ml10, Styles.flex1, Styles.mr10]}>
|
||||
<Text style={[titleWeight == 'normal' ? Styles.textDefault : Styles.textDefaultSemiBold, { color: textColorFix }]} numberOfLines={titleShowAll ? 0 : 1} ellipsizeMode='tail'>{title}</Text>
|
||||
{
|
||||
subtitle &&
|
||||
@@ -81,7 +78,7 @@ export default function BorderBottomItem({ title, subtitle, icon, desc, onPress,
|
||||
}
|
||||
{
|
||||
typeof rightBottomInfo == 'string' ?
|
||||
<Text style={[Styles.textInformation, {color: colors.dimmed }]}>{rightBottomInfo}</Text>
|
||||
<Text style={[Styles.textInformation, { color: colors.dimmed }]}>{rightBottomInfo}</Text>
|
||||
:
|
||||
rightBottomInfo
|
||||
}
|
||||
|
||||
53
components/borderBottomItemVertical.tsx
Normal file
53
components/borderBottomItemVertical.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import Styles from "@/constants/Styles";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import React, { useState } from "react";
|
||||
import { Pressable, View } from "react-native";
|
||||
import Text from "./Text";
|
||||
|
||||
type Props = {
|
||||
title?: string
|
||||
icon: React.ReactNode
|
||||
desc?: string
|
||||
rightTopInfo?: string
|
||||
onPress?: () => void
|
||||
onLongPress?: () => void
|
||||
borderType: 'all' | 'bottom' | 'none'
|
||||
titleWeight?: 'normal' | 'bold'
|
||||
bgColor?: string
|
||||
descEllipsize?: boolean
|
||||
textColor?: string,
|
||||
titleShowAll?: boolean
|
||||
}
|
||||
|
||||
export default function BorderBottomItemVertical({ title, icon, desc, onPress, onLongPress, rightTopInfo, borderType, titleWeight, bgColor, descEllipsize, textColor, titleShowAll }: Props) {
|
||||
const { colors } = useTheme();
|
||||
const textColorFix = textColor ? textColor : colors.text;
|
||||
|
||||
return (
|
||||
<Pressable onLongPress={onLongPress} onPress={onPress}
|
||||
style={({ pressed }) => [
|
||||
borderType == 'bottom'
|
||||
? [Styles.wrapItemBorderBottom, { borderBottomColor: colors.icon + '20' }]
|
||||
: borderType == 'all'
|
||||
? [Styles.wrapItemBorderAll, { borderColor: colors.icon + '20' }]
|
||||
: Styles.wrapItemBorderNone,
|
||||
bgColor == "transparent" ? { backgroundColor: 'transparent' } : { backgroundColor: colors.card },
|
||||
]}
|
||||
>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
{icon}
|
||||
<View style={[Styles.ml10, Styles.flex1]}>
|
||||
<View style={Styles.rowSpaceBetween}>
|
||||
<View style={[Styles.flex1, Styles.mr10]}>
|
||||
<Text style={[titleWeight == 'normal' ? Styles.textDefault : Styles.textDefaultSemiBold, { color: textColorFix }]} numberOfLines={titleShowAll ? 0 : 1} ellipsizeMode='tail'>{title}</Text>
|
||||
</View>
|
||||
{
|
||||
rightTopInfo && <Text style={[Styles.textInformation, Styles.mt05, { color: textColorFix }]}>{rightTopInfo}</Text>
|
||||
}
|
||||
</View>
|
||||
{desc && <Text style={[Styles.textDefault, { textAlign: 'left', color: textColorFix }]} numberOfLines={descEllipsize == false ? 0 : 2} ellipsizeMode='tail'>{desc}</Text>}
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { TouchableOpacity } from "react-native";
|
||||
import Text from './Text';
|
||||
|
||||
@@ -10,8 +10,9 @@ type Props = {
|
||||
};
|
||||
|
||||
export function ButtonForm({ text, onPress, disabled }: Props) {
|
||||
const { colors } = useTheme();
|
||||
return (
|
||||
<TouchableOpacity style={[Styles.btnRound, { marginTop: 30,}, disabled && ColorsStatus.gray]} onPress={onPress} disabled={disabled}>
|
||||
<TouchableOpacity style={[Styles.btnRound, Styles.round05, Styles.mt30, { backgroundColor: colors.primary }, disabled && { backgroundColor: colors.tabIconDefault }]} onPress={onPress} disabled={disabled}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.cWhite]}>{text}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Feather } from "@expo/vector-icons"
|
||||
import AlertKonfirmasi from "./alertKonfirmasi"
|
||||
import ModalConfirmation from "./ModalConfirmation"
|
||||
import { ButtonHeader } from "./buttonHeader"
|
||||
import { useState } from "react"
|
||||
|
||||
type Props = {
|
||||
category: 'create' | 'update' | 'cancel' | 'update-calendar'
|
||||
@@ -9,29 +10,37 @@ type Props = {
|
||||
}
|
||||
|
||||
export default function ButtonSaveHeader({ category, onPress, disable }: Props) {
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
return (
|
||||
<>
|
||||
<ButtonHeader
|
||||
item={<Feather name="check" size={25} color={disable ? "grey" : "white"} />}
|
||||
onPress={() => {
|
||||
if (!disable) {
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: category == 'create'
|
||||
? 'Apakah anda yakin ingin menambahkan data?'
|
||||
: category == 'cancel'
|
||||
? 'Apakah anda yakin ingin membatalkan kegiatan? Pembatalan bersifat permanen'
|
||||
: category == 'update-calendar'
|
||||
? 'Apakah Anda yakin ingin mengubah data acara ini? Data ini akan mempengaruhi semua data yang terkait'
|
||||
: 'Apakah anda yakin mengubah data?',
|
||||
onPress: () => {
|
||||
onPress && onPress()
|
||||
}
|
||||
})
|
||||
setShowModal(true)
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showModal}
|
||||
title="Konfirmasi"
|
||||
message={
|
||||
category == 'create'
|
||||
? 'Apakah anda yakin ingin menambahkan data?'
|
||||
: category == 'cancel'
|
||||
? 'Apakah anda yakin ingin membatalkan kegiatan? Pembatalan bersifat permanen'
|
||||
: category == 'update-calendar'
|
||||
? 'Apakah Anda yakin ingin mengubah data acara ini? Data ini akan mempengaruhi semua data yang terkait'
|
||||
: 'Apakah anda yakin mengubah data?'
|
||||
}
|
||||
onConfirm={() => {
|
||||
setShowModal(false)
|
||||
onPress && onPress()
|
||||
}}
|
||||
onCancel={() => setShowModal(false)}
|
||||
confirmText="Ya"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
33
components/buttonSetting.tsx
Normal file
33
components/buttonSetting.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import Styles from "@/constants/Styles";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { ReactNode } from "react";
|
||||
import { Pressable, View } from "react-native";
|
||||
import Text from "./Text";
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
onPress?: () => void,
|
||||
icon?: ReactNode,
|
||||
borderBottom?: boolean
|
||||
value?: string
|
||||
}
|
||||
|
||||
export default function ButtonSetting({ title, onPress, icon, borderBottom = true, value }: Props) {
|
||||
const { colors } = useTheme();
|
||||
return (
|
||||
<Pressable onPress={onPress}>
|
||||
<View style={[
|
||||
Styles.p10,
|
||||
Styles.rowSpaceBetween,
|
||||
{ borderBottomWidth: borderBottom ? 1 : 0, borderColor: colors.icon + '20' },
|
||||
]}>
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
{icon}
|
||||
<Text style={[{ color: colors.text }, Styles.ml05]}>{title}</Text>
|
||||
</View>
|
||||
{value && <Text style={[{ color: colors.dimmed }]}>{value}</Text>}
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -23,6 +23,7 @@ export default function HeaderRightCalendarDetail({ id, idReminder }: Props) {
|
||||
const { colors } = useTheme()
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const update = useSelector((state: any) => state.calendarUpdate)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@@ -71,17 +72,26 @@ export default function HeaderRightCalendarDetail({ id, idReminder }: Props) {
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus data ini? Data ini akan mempengaruhi semua data yang terkait',
|
||||
onPress: () => {
|
||||
handleDeleteCalendar()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus data ini? Data ini akan mempengaruhi semua data yang terkait"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteCalendar()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -25,6 +25,8 @@ export default function HeaderRightDiscussionDetail({ id, status, isActive }: Pr
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const update = useSelector((state: any) => state.discussionUpdate)
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [modalConfig, setModalConfig] = useState({ title: '', message: '', onConfirm: () => { } })
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const handleOpenClose = async () => {
|
||||
@@ -86,13 +88,14 @@ export default function HeaderRightDiscussionDetail({ id, status, isActive }: Pr
|
||||
title={status == 1 ? 'Tutup Diskusi' : 'Buka Diskusi'}
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: `Apakah anda yakin ingin ${status == 1 ? 'menutup' : 'membuka'} diskusi?`,
|
||||
onPress: () => {
|
||||
handleOpenClose()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
setModalConfig({
|
||||
title: 'Konfirmasi',
|
||||
message: `Apakah anda yakin ingin ${status == 1 ? 'menutup' : 'membuka'} diskusi?`,
|
||||
onConfirm: () => handleOpenClose()
|
||||
})
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
@@ -102,17 +105,31 @@ export default function HeaderRightDiscussionDetail({ id, status, isActive }: Pr
|
||||
title={isActive ? 'Arsipkan' : 'Aktifkan Diskusi'}
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: isActive ? 'Apakah anda yakin ingin mengarsipkan diskusi?' : 'Apakah anda yakin ingin mengaktifkan diskusi?',
|
||||
onPress: () => {
|
||||
handleArchive()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
setModalConfig({
|
||||
title: 'Konfirmasi',
|
||||
message: isActive ? 'Apakah anda yakin ingin mengarsipkan diskusi?' : 'Apakah anda yakin ingin mengaktifkan diskusi?',
|
||||
onConfirm: () => handleArchive()
|
||||
})
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showModal}
|
||||
title={modalConfig.title}
|
||||
message={modalConfig.message}
|
||||
onConfirm={() => {
|
||||
setShowModal(false)
|
||||
modalConfig.onConfirm()
|
||||
}}
|
||||
onCancel={() => setShowModal(false)}
|
||||
confirmText="Ya"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -25,6 +25,8 @@ export default function HeaderRightDiscussionGeneralDetail({ id, active, status
|
||||
const { colors } = useTheme();
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const entityUser = useSelector((state: any) => state.user)
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [modalConfig, setModalConfig] = useState({ title: '', message: '', onConfirm: () => { } })
|
||||
const dispatch = useDispatch()
|
||||
const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
|
||||
|
||||
@@ -88,13 +90,14 @@ export default function HeaderRightDiscussionGeneralDetail({ id, active, status
|
||||
title={status == 1 ? 'Tutup Diskusi' : 'Buka Diskusi'}
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: status == 1 ? 'Apakah anda yakin ingin menutup diskusi?' : 'Apakah anda yakin ingin membuka diskusi?',
|
||||
onPress: () => {
|
||||
handleUpdateStatus()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
setModalConfig({
|
||||
title: 'Konfirmasi',
|
||||
message: status == 1 ? 'Apakah anda yakin ingin menutup diskusi?' : 'Apakah anda yakin ingin membuka diskusi?',
|
||||
onConfirm: () => handleUpdateStatus()
|
||||
})
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
@@ -105,11 +108,14 @@ export default function HeaderRightDiscussionGeneralDetail({ id, active, status
|
||||
title="Aktifkan Diskusi"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin mengaktifkan diskusi ini?',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setModalConfig({
|
||||
title: 'Konfirmasi',
|
||||
message: 'Apakah anda yakin ingin mengaktifkan diskusi ini?',
|
||||
onConfirm: () => handleDelete()
|
||||
})
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -125,16 +131,32 @@ export default function HeaderRightDiscussionGeneralDetail({ id, active, status
|
||||
title="Arsipkan"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin mengarsipkan diskusi?',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setModalConfig({
|
||||
title: 'Konfirmasi',
|
||||
message: 'Apakah anda yakin ingin mengarsipkan diskusi?',
|
||||
onConfirm: () => handleDelete()
|
||||
})
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showModal}
|
||||
title={modalConfig.title}
|
||||
message={modalConfig.message}
|
||||
onConfirm={() => {
|
||||
setShowModal(false)
|
||||
modalConfig.onConfirm()
|
||||
}}
|
||||
onCancel={() => setShowModal(false)}
|
||||
confirmText="Ya"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
38
components/division/FiturGridItem.tsx
Normal file
38
components/division/FiturGridItem.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import Styles from "@/constants/Styles";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import React from "react";
|
||||
import { Pressable, View } from "react-native";
|
||||
import Text from "../Text";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
icon: React.ReactNode;
|
||||
onPress: () => void;
|
||||
};
|
||||
|
||||
export default function FiturGridItem({ title, subtitle, icon, onPress }: Props) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
style={({ pressed }) => [
|
||||
Styles.wrapGridItem,
|
||||
{
|
||||
backgroundColor: colors.card,
|
||||
borderColor: colors.icon + '20',
|
||||
},
|
||||
pressed && { opacity: 0.7 }
|
||||
]}
|
||||
>
|
||||
<View style={[Styles.p05, { marginRight: 10 }]}>
|
||||
{icon}
|
||||
</View>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={[Styles.textDefaultSemiBold, { color: colors.text, lineHeight: 20 }]} numberOfLines={1}>{title}</Text>
|
||||
<Text style={[Styles.textMediumNormal, { color: colors.dimmed, lineHeight: 15 }]} numberOfLines={1}>{subtitle}</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import { AntDesign, Feather, MaterialIcons, SimpleLineIcons } from "@expo/vector
|
||||
import { router, useLocalSearchParams } from "expo-router"
|
||||
import { useEffect, useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import BorderBottomItem from "../borderBottomItem"
|
||||
import { useTheme } from "@/providers/ThemeProvider"
|
||||
import Text from "../Text"
|
||||
import FiturGridItem from "./FiturGridItem"
|
||||
|
||||
type Props = {
|
||||
tugas: number
|
||||
@@ -50,66 +50,34 @@ export default function FiturDivisionDetail({ refreshing }: { refreshing: boolea
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>Fitur</Text>
|
||||
<View>
|
||||
<View style={[Styles.rowSpaceBetween]}>
|
||||
<BorderBottomItem
|
||||
bgColor={colors.card}
|
||||
borderType="all"
|
||||
icon={
|
||||
<View style={[Styles.p05]}>
|
||||
<AntDesign name="filetext1" size={28} color={colors.text} />
|
||||
</View>
|
||||
}
|
||||
title="Tugas"
|
||||
subtitle={`${data.tugas} Tugas`}
|
||||
width={30}
|
||||
onPress={() => { router.push(`/division/${id}/task?status=0`) }}
|
||||
/>
|
||||
<View style={{ flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between' }}>
|
||||
<FiturGridItem
|
||||
title="Tugas"
|
||||
subtitle={`${data.tugas} Tugas`}
|
||||
icon={<AntDesign name="filetext1" size={28} color={colors.text} />}
|
||||
onPress={() => { router.push(`/division/${id}/task?status=0`) }}
|
||||
/>
|
||||
|
||||
<BorderBottomItem
|
||||
bgColor={colors.card}
|
||||
borderType="all"
|
||||
icon={
|
||||
<View style={[Styles.p05]}>
|
||||
<Feather name="paperclip" size={28} color={colors.text} />
|
||||
</View>
|
||||
}
|
||||
title="Dokumen"
|
||||
subtitle={`${data.dokumen} File`}
|
||||
width={30}
|
||||
onPress={() => { router.push(`/division/${id}/document`) }}
|
||||
/>
|
||||
</View>
|
||||
<FiturGridItem
|
||||
title="Dokumen"
|
||||
subtitle={`${data.dokumen} File`}
|
||||
icon={<Feather name="paperclip" size={28} color={colors.text} />}
|
||||
onPress={() => { router.push(`/division/${id}/document`) }}
|
||||
/>
|
||||
|
||||
<View style={[Styles.rowSpaceBetween]}>
|
||||
<BorderBottomItem
|
||||
bgColor={colors.card}
|
||||
borderType="all"
|
||||
icon={
|
||||
<View style={[Styles.p05]}>
|
||||
<SimpleLineIcons name="bubbles" size={28} color={colors.text} />
|
||||
</View>
|
||||
}
|
||||
title="Diskusi"
|
||||
subtitle={`${data.diskusi} Diskusi`}
|
||||
width={30}
|
||||
onPress={() => { router.push(`/division/${id}/discussion?active=true`) }}
|
||||
/>
|
||||
<FiturGridItem
|
||||
title="Diskusi"
|
||||
subtitle={`${data.diskusi} Diskusi`}
|
||||
icon={<SimpleLineIcons name="bubbles" size={28} color={colors.text} />}
|
||||
onPress={() => { router.push(`/division/${id}/discussion?active=true`) }}
|
||||
/>
|
||||
|
||||
<BorderBottomItem
|
||||
bgColor={colors.card}
|
||||
borderType="all"
|
||||
icon={
|
||||
<View style={[Styles.p05]}>
|
||||
<AntDesign name="calendar" size={28} color={colors.text} />
|
||||
</View>
|
||||
}
|
||||
title="Kalender"
|
||||
subtitle={`${data.kalender} Acara`}
|
||||
width={30}
|
||||
onPress={() => { router.push(`/division/${id}/calendar`) }}
|
||||
/>
|
||||
</View>
|
||||
<FiturGridItem
|
||||
title="Kalender"
|
||||
subtitle={`${data.kalender} Acara`}
|
||||
icon={<AntDesign name="calendar" size={28} color={colors.text} />}
|
||||
onPress={() => { router.push(`/division/${id}/calendar`) }}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -23,6 +23,7 @@ export default function HeaderRightDivisionInfo({ id, active }: Props) {
|
||||
const { colors } = useTheme();
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const update = useSelector((state: any) => state.divisionUpdate)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@@ -62,15 +63,26 @@ export default function HeaderRightDivisionInfo({ id, active }: Props) {
|
||||
title={active ? "Non Aktifkan" : "Aktifkan"}
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: active ? 'Apakah anda yakin ingin menonaktifkan divisi?' : 'Apakah anda yakin ingin mengaktifkan divisi?',
|
||||
onPress: () => { handleUpdateStatus() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showModal}
|
||||
title="Konfirmasi"
|
||||
message={active ? 'Apakah anda yakin ingin menonaktifkan divisi?' : 'Apakah anda yakin ingin mengaktifkan divisi?'}
|
||||
onConfirm={() => {
|
||||
setShowModal(false)
|
||||
handleUpdateStatus()
|
||||
}}
|
||||
onCancel={() => setShowModal(false)}
|
||||
confirmText="Konfirmasi"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { useState } from "react";
|
||||
import { Pressable, ScrollView, View } from "react-native";
|
||||
import { useSharedValue } from "react-native-reanimated";
|
||||
import Toast from "react-native-toast-message";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import { InputForm } from "../inputForm";
|
||||
import ItemAccordion from "../itemAccordion";
|
||||
@@ -29,6 +29,7 @@ export default function MenuBottomSelectDocument({ onDone }: Props) {
|
||||
const [isRename, setRename] = useState(false)
|
||||
const [isShare, setShare] = useState(false)
|
||||
const [isMoveCopy, setMoveCopy] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [valMoveCopy, setValMoveCopy] = useState<'move' | 'copy'>('copy')
|
||||
const open = useSharedValue(false)
|
||||
|
||||
@@ -58,15 +59,7 @@ export default function MenuBottomSelectDocument({ onDone }: Props) {
|
||||
icon={<MaterialCommunityIcons name="trash-can-outline" color="white" size={25} />}
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus data?',
|
||||
|
||||
onPress: () => {
|
||||
onDone()
|
||||
Toast.show({ type: 'small', text1: 'Berhasil menghapus data', })
|
||||
}
|
||||
})
|
||||
setShowDeleteModal(true)
|
||||
}}
|
||||
column="many"
|
||||
color="white"
|
||||
@@ -213,6 +206,20 @@ export default function MenuBottomSelectDocument({ onDone }: Props) {
|
||||
}}
|
||||
/>
|
||||
<ModalSalinMove open={isMoveCopy} close={setMoveCopy} category={valMoveCopy} onConfirm={(value: string) => { }} dataChoose={[]} />
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus data?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
onDone()
|
||||
Toast.show({ type: 'small', text1: 'Berhasil menghapus data', })
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -78,11 +78,11 @@ export default function ProjectHome({ refreshing }: { refreshing: boolean }) {
|
||||
<LabelStatus
|
||||
size="default"
|
||||
category={
|
||||
data[index].status === 0 ? 'primary' :
|
||||
data[index].status === 0 ? 'secondary' :
|
||||
data[index].status === 1 ? 'warning' :
|
||||
data[index].status === 2 ? 'success' :
|
||||
data[index].status === 3 ? 'error' :
|
||||
'primary'
|
||||
'secondary'
|
||||
}
|
||||
text={
|
||||
data[index].status === 0 ? 'SEGERA' :
|
||||
|
||||
@@ -74,7 +74,7 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
|
||||
/>
|
||||
</View>
|
||||
{error && (<Text style={[Styles.textInformation, { color: colors.error }, Styles.mt05]}>{errorText}</Text>)}
|
||||
{info != undefined && (<Text style={[Styles.textInformation, { color: colors.icon }, Styles.mt05]}>{info}</Text>)}
|
||||
{info != undefined && (<Text style={[Styles.textInformation, { color: colors.dimmed }, Styles.mt05]}>{info}</Text>)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -23,6 +23,7 @@ export default function HeaderRightMemberDetail({ active, id }: Props) {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const update = useSelector((state: any) => state.memberUpdate)
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const { colors } = useTheme();
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@@ -54,13 +55,9 @@ export default function HeaderRightMemberDetail({ active, id }: Props) {
|
||||
title={active ? "Non Aktifkan" : "Aktifkan"}
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: active ? 'Apakah anda yakin ingin menonaktifkan user?' : 'Apakah anda yakin ingin mengaktifkan user?',
|
||||
onPress: () => {
|
||||
handleActive()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
<MenuItemRow
|
||||
@@ -73,6 +70,19 @@ export default function HeaderRightMemberDetail({ active, id }: Props) {
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showModal}
|
||||
title="Konfirmasi"
|
||||
message={active ? 'Apakah anda yakin ingin menonaktifkan user?' : 'Apakah anda yakin ingin mengaktifkan user?'}
|
||||
onConfirm={() => {
|
||||
setShowModal(false)
|
||||
handleActive()
|
||||
}}
|
||||
onCancel={() => setShowModal(false)}
|
||||
confirmText="Konfirmasi"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -162,7 +162,7 @@ export default function ModalSelect({ open, close, title, category, idParent, on
|
||||
category != 'status-task' ?
|
||||
data.length > 0 ?
|
||||
data.map((item: any, index: any) => (
|
||||
<Pressable key={index} style={[Styles.itemSelectModal]} onPress={() => { onChoose(item.id, item.name, item.img) }}>
|
||||
<Pressable key={index} style={[Styles.itemSelectModal, {borderColor:colors.icon+'20'}]} onPress={() => { onChoose(item.id, item.name, item.img) }}>
|
||||
{
|
||||
category == 'member'
|
||||
?
|
||||
@@ -188,7 +188,7 @@ export default function ModalSelect({ open, close, title, category, idParent, on
|
||||
<>
|
||||
{
|
||||
dataStatus.map((item: any, index: any) => (
|
||||
<Pressable key={index} style={[Styles.itemSelectModal]} onPress={() => {
|
||||
<Pressable key={index} style={[Styles.itemSelectModal, {borderColor:colors.icon+'20'}]} onPress={() => {
|
||||
onSelect(item)
|
||||
close(false)
|
||||
}}>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { useTheme } from "@/providers/ThemeProvider";
|
||||
import { Pressable, View } from "react-native";
|
||||
import { ImageBackground, Pressable, View } from "react-native";
|
||||
import Text from "./Text";
|
||||
|
||||
import bgDark from '@/assets/images/bgproject-dark.png';
|
||||
import bgLight from '@/assets/images/bgproject-light.png';
|
||||
|
||||
type Props = {
|
||||
content: 'carousel' | 'page';
|
||||
children: React.ReactNode;
|
||||
@@ -15,13 +18,27 @@ type Props = {
|
||||
height?: number
|
||||
};
|
||||
export default function PaperGridContent({ content, children, title, headerColor, onPress, contentPosition, titleTail, height }: Props) {
|
||||
const { colors } = useTheme();
|
||||
const { colors, activeTheme } = useTheme();
|
||||
const bgSource = activeTheme === 'light' ? bgLight : bgDark;
|
||||
return (
|
||||
<Pressable onPress={onPress}>
|
||||
<View style={[content == 'carousel' ? Styles.wrapGridCaraousel : Styles.wrapGridContent]}>
|
||||
<View style={[Styles.headerPaperGrid, headerColor == 'warning' ? ColorsStatus.warning : { backgroundColor: colors.primary }]}>
|
||||
<Text numberOfLines={titleTail ? titleTail : undefined} style={[Styles.textSubtitle, headerColor == 'warning' ? Styles.cDefault : Styles.cWhite, { textAlign: 'center' }]}>{title}</Text>
|
||||
</View>
|
||||
{
|
||||
headerColor == 'warning' ? (
|
||||
<View style={[Styles.headerPaperGrid, ColorsStatus.warning]}>
|
||||
<Text numberOfLines={titleTail ? titleTail : undefined} style={[Styles.textSubtitle, Styles.cDefault, { textAlign: 'center' }]}>{title}</Text>
|
||||
</View>
|
||||
) : (
|
||||
<ImageBackground
|
||||
source={bgSource}
|
||||
resizeMode="cover"
|
||||
imageStyle={{ borderTopLeftRadius: 5, borderTopRightRadius: 5 }}
|
||||
style={[Styles.headerPaperGrid, { backgroundColor: colors.primary }]}
|
||||
>
|
||||
<Text numberOfLines={titleTail ? titleTail : undefined} style={[Styles.textSubtitle, Styles.cWhite, { textAlign: 'center' }]}>{title}</Text>
|
||||
</ImageBackground>
|
||||
)
|
||||
}
|
||||
<View style={[
|
||||
contentPosition && contentPosition == 'top' ? Styles.contentPaperGrid2 : Styles.contentPaperGrid,
|
||||
{ backgroundColor: colors.card },
|
||||
|
||||
@@ -9,8 +9,9 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import { InputForm } from "../inputForm"
|
||||
import MenuItemRow from "../menuItemRow"
|
||||
@@ -29,6 +30,7 @@ export default function HeaderRightProjectDetail({ id, status }: Props) {
|
||||
const dispatch = useDispatch()
|
||||
const update = useSelector((state: any) => state.projectUpdate)
|
||||
const [isAddLink, setAddLink] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [link, setLink] = useState("")
|
||||
|
||||
async function handleDelete() {
|
||||
@@ -152,11 +154,9 @@ export default function HeaderRightProjectDetail({ id, status }: Props) {
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin menghapus kegiatan ini? Kegiatan yang dihapus tidak dapat dikembalikan',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
:
|
||||
@@ -173,6 +173,19 @@ export default function HeaderRightProjectDetail({ id, status }: Props) {
|
||||
}
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin menghapus kegiatan ini? Kegiatan yang dihapus tidak dapat dikembalikan"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
|
||||
<ModalFloat
|
||||
title="Tambah Link"
|
||||
isVisible={isAddLink}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Alert, Platform, View } from "react-native";
|
||||
import * as mime from 'react-native-mime-types';
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import MenuItemRow from "../menuItemRow";
|
||||
@@ -42,6 +42,7 @@ export default function SectionFile({ status, member, refreshing }: { status: nu
|
||||
const [loading, setLoading] = useState(true)
|
||||
const arrSkeleton = Array.from({ length: 3 })
|
||||
const [selectFile, setSelectFile] = useState<Props | null>(null)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [loadingOpen, setLoadingOpen] = useState(false)
|
||||
|
||||
async function handleLoad(loading: boolean) {
|
||||
@@ -185,19 +186,27 @@ export default function SectionFile({ status, member, refreshing }: { status: nu
|
||||
onPress={() => {
|
||||
if (status == 3) return
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan',
|
||||
onPress: () => {
|
||||
handleDelete()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { useEffect, useState } from "react";
|
||||
import { Linking, View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import MenuItemRow from "../menuItemRow";
|
||||
@@ -32,6 +32,7 @@ export default function SectionLink({ status, member, refreshing }: { status: nu
|
||||
const update = useSelector((state: any) => state.projectUpdate)
|
||||
const dispatch = useDispatch()
|
||||
const [selectLink, setSelectLink] = useState<Props | null>(null)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
@@ -122,19 +123,27 @@ export default function SectionLink({ status, member, refreshing }: { status: nu
|
||||
onPress={() => {
|
||||
if (status == 3) return
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin menghapus link ini? Link yang dihapus tidak dapat dikembalikan',
|
||||
onPress: () => {
|
||||
handleDelete()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin menghapus link ini? Link yang dihapus tidak dapat dikembalikan"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import ImageUser from "../imageNew";
|
||||
@@ -35,6 +35,8 @@ export default function SectionMember({ status, refreshing }: { status: number |
|
||||
const [isModal, setModal] = useState(false);
|
||||
const { token, decryptToken } = useAuthSession();
|
||||
const { id } = useLocalSearchParams<{ id: string }>();
|
||||
const [selectLink, setSelectLink] = useState<Props | null>(null);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [data, setData] = useState<Props[]>([]);
|
||||
const [loading, setLoading] = useState(true)
|
||||
const arrSkeleton = Array.from({ length: 3 })
|
||||
@@ -168,16 +170,27 @@ export default function SectionMember({ status, refreshing }: { status: number |
|
||||
title="Keluarkan"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: "Konfirmasi",
|
||||
desc: "Apakah Anda yakin ingin mengeluarkan anggota?",
|
||||
onPress: () => { handleDeleteMember() },
|
||||
});
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin mengeluarkan anggota?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteMember()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Keluarkan"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import ItemSectionTanggalTugas from "../itemSectionTanggalTugas";
|
||||
import MenuItemRow from "../menuItemRow";
|
||||
@@ -45,6 +45,7 @@ export default function SectionTanggalTugasProject({ status, member, refreshing
|
||||
id: '',
|
||||
status: 0,
|
||||
})
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
@@ -215,16 +216,27 @@ export default function SectionTanggalTugasProject({ status, member, refreshing
|
||||
title="Hapus Tugas"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: "Konfirmasi",
|
||||
desc: "Apakah anda yakin ingin menghapus data ini?",
|
||||
onPress: () => { handleDelete() },
|
||||
});
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus data ini?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
|
||||
<ModalSelect
|
||||
category="status-task"
|
||||
close={() => { setSelect(false) }}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import Toast from "react-native-toast-message"
|
||||
import { useDispatch, useSelector } from "react-redux"
|
||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||
import ModalConfirmation from "../ModalConfirmation"
|
||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||
import DrawerBottom from "../drawerBottom"
|
||||
import { InputForm } from "../inputForm"
|
||||
@@ -31,6 +31,7 @@ export default function HeaderRightTaskDetail({ id, division, status, isAdminDiv
|
||||
const dispatch = useDispatch()
|
||||
const update = useSelector((state: any) => state.taskUpdate)
|
||||
const [isAddLink, setAddLink] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [link, setLink] = useState("")
|
||||
|
||||
async function handleDelete() {
|
||||
@@ -158,11 +159,9 @@ export default function HeaderRightTaskDetail({ id, division, status, isAdminDiv
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin menghapus tugas ini? Tugas yang dihapus tidak dapat dikembalikan',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -180,6 +179,19 @@ export default function HeaderRightTaskDetail({ id, division, status, isAdminDiv
|
||||
}
|
||||
</DrawerBottom >
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin menghapus tugas ini? Tugas yang dihapus tidak dapat dikembalikan"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
|
||||
<ModalFloat
|
||||
title="Tambah Link"
|
||||
isVisible={isAddLink}
|
||||
|
||||
@@ -14,7 +14,8 @@ import { Alert, Platform, View } from "react-native";
|
||||
import * as mime from 'react-native-mime-types';
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import ButtonMenuHeader from "../buttonMenuHeader";
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import MenuItemRow from "../menuItemRow";
|
||||
@@ -32,6 +33,9 @@ type Props = {
|
||||
export default function SectionFileTask({ refreshing, isMemberDivision }: { refreshing: boolean, isMemberDivision: boolean }) {
|
||||
const { colors } = useTheme()
|
||||
const [isModal, setModal] = useState(false)
|
||||
const [isAddLink, setAddLink] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [link, setLink] = useState("")
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { detail } = useLocalSearchParams<{ detail: string }>()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
@@ -174,14 +178,9 @@ export default function SectionFileTask({ refreshing, isMemberDivision }: { refr
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan',
|
||||
onPress: () => {
|
||||
handleDelete()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
:
|
||||
@@ -190,6 +189,19 @@ export default function SectionFileTask({ refreshing, isMemberDivision }: { refr
|
||||
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { useEffect, useState } from "react";
|
||||
import { Linking, View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import MenuItemRow from "../menuItemRow";
|
||||
@@ -30,6 +30,7 @@ export default function SectionLinkTask({ refreshing, isMemberDivision }: { refr
|
||||
const update = useSelector((state: any) => state.taskUpdate)
|
||||
const dispatch = useDispatch()
|
||||
const [selectLink, setSelectLink] = useState<Props | null>(null)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const entityUser = useSelector((state: any) => state.user);
|
||||
|
||||
async function handleLoad() {
|
||||
@@ -112,11 +113,9 @@ export default function SectionLinkTask({ refreshing, isMemberDivision }: { refr
|
||||
title="Hapus"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah Anda yakin ingin menghapus link ini? Link yang dihapus tidak dapat dikembalikan',
|
||||
onPress: () => { handleDelete() }
|
||||
})
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
:
|
||||
@@ -125,6 +124,19 @@ export default function SectionLinkTask({ refreshing, isMemberDivision }: { refr
|
||||
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin menghapus link ini? Link yang dihapus tidak dapat dikembalikan"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import BorderBottomItem from "../borderBottomItem";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import ImageUser from "../imageNew";
|
||||
@@ -30,6 +30,8 @@ type Props = {
|
||||
export default function SectionMemberTask({ refreshing, isAdminDivision }: { refreshing: boolean, isAdminDivision: boolean }) {
|
||||
const { colors } = useTheme()
|
||||
const [isModal, setModal] = useState(false);
|
||||
const [selectLink, setSelectLink] = useState<Props | null>(null)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const entityUser = useSelector((state: any) => state.user);
|
||||
const { token, decryptToken } = useAuthSession();
|
||||
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
|
||||
@@ -132,7 +134,7 @@ export default function SectionMemberTask({ refreshing, isAdminDivision }: { ref
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Text style={[ Styles.textDefault, { textAlign: "center", color:colors.dimmed }, ]} >
|
||||
<Text style={[Styles.textDefault, { textAlign: "center", color: colors.dimmed },]} >
|
||||
Tidak ada anggota
|
||||
</Text>
|
||||
)
|
||||
@@ -177,11 +179,9 @@ export default function SectionMemberTask({ refreshing, isAdminDivision }: { ref
|
||||
title="Keluarkan"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: "Konfirmasi",
|
||||
desc: "Apakah Anda yakin ingin mengeluarkan anggota?",
|
||||
onPress: () => { handleDeleteMember() },
|
||||
});
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
:
|
||||
@@ -189,6 +189,19 @@ export default function SectionMemberTask({ refreshing, isAdminDivision }: { ref
|
||||
}
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah Anda yakin ingin mengeluarkan anggota?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDeleteMember()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Keluarkan"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||
import ModalConfirmation from "../ModalConfirmation";
|
||||
import DrawerBottom from "../drawerBottom";
|
||||
import ItemSectionTanggalTugas from "../itemSectionTanggalTugas";
|
||||
import MenuItemRow from "../menuItemRow";
|
||||
@@ -44,6 +44,7 @@ export default function SectionTanggalTugasTask({ refreshing, isMemberDivision }
|
||||
id: '',
|
||||
status: 0,
|
||||
})
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
@@ -211,14 +212,9 @@ export default function SectionTanggalTugasTask({ refreshing, isMemberDivision }
|
||||
title="Hapus Tugas"
|
||||
onPress={() => {
|
||||
setModal(false)
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menghapus data ini?',
|
||||
onPress: () => {
|
||||
handleDelete()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, 600)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@@ -227,6 +223,19 @@ export default function SectionTanggalTugasTask({ refreshing, isMemberDivision }
|
||||
}
|
||||
</DrawerBottom>
|
||||
|
||||
<ModalConfirmation
|
||||
visible={showDeleteModal}
|
||||
title="Konfirmasi"
|
||||
message="Apakah anda yakin ingin menghapus data ini?"
|
||||
onConfirm={() => {
|
||||
setShowDeleteModal(false)
|
||||
handleDelete()
|
||||
}}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
confirmText="Hapus"
|
||||
cancelText="Batal"
|
||||
/>
|
||||
|
||||
<ModalSelect
|
||||
category="status-task"
|
||||
close={() => setSelect(false)}
|
||||
|
||||
@@ -7,12 +7,19 @@ import Text from "./Text";
|
||||
export default function ToastCustom({ position }: { position?: 'top' | 'bottom' }) {
|
||||
const { colors } = useTheme()
|
||||
return (
|
||||
<Toast autoHide onPress={() => Toast.hide()} visibilityTime={1500} position={position || 'bottom'} config={{
|
||||
small: ({ text1 }) => (
|
||||
<View style={[Styles.toastContainer, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<Text style={{ fontSize: 12 }}>{text1}</Text>
|
||||
</View>
|
||||
)
|
||||
}} />
|
||||
<Toast
|
||||
autoHide
|
||||
onPress={() => Toast.hide()}
|
||||
visibilityTime={1500}
|
||||
position={position || 'bottom'}
|
||||
bottomOffset={80}
|
||||
config={{
|
||||
small: ({ text1 }) => (
|
||||
<View style={[Styles.toastContainer, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
|
||||
<Text style={{ fontSize: 12 }}>{text1}</Text>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -6,7 +6,7 @@ export const Colors = {
|
||||
text: '#11181C',
|
||||
background: '#f7f7f7ff',
|
||||
tint: tintColorLight,
|
||||
primary: '#19345E',
|
||||
primary: '#1F3C88',
|
||||
icon: '#1F3C88',
|
||||
card: '#ffffff',
|
||||
tabIconDefault: '#687076',
|
||||
@@ -24,7 +24,7 @@ export const Colors = {
|
||||
text: '#ECEDEE',
|
||||
background: '#0F1B2D',
|
||||
tint: tintColorDark,
|
||||
primary: '#19345E',
|
||||
primary: '#123A6F',
|
||||
icon: '#9DB9E8',
|
||||
card: '#16233A', // slightly lighter than background #151718
|
||||
tabIconDefault: '#9BA1A6',
|
||||
|
||||
@@ -2,5 +2,14 @@ import Constants from 'expo-constants';
|
||||
|
||||
export const ConstEnv = {
|
||||
url_storage: Constants?.expoConfig?.extra?.URL_STORAGE,
|
||||
pass_encrypt: Constants?.expoConfig?.extra?.PASS_ENC
|
||||
pass_encrypt: Constants?.expoConfig?.extra?.PASS_ENC,
|
||||
firebase: {
|
||||
apiKey: Constants?.expoConfig?.extra?.FIREBASE_API_KEY,
|
||||
authDomain: Constants?.expoConfig?.extra?.FIREBASE_AUTH_DOMAIN,
|
||||
projectId: Constants?.expoConfig?.extra?.FIREBASE_PROJECT_ID,
|
||||
storageBucket: Constants?.expoConfig?.extra?.FIREBASE_STORAGE_BUCKET,
|
||||
messagingSenderId: Constants?.expoConfig?.extra?.FIREBASE_MESSAGING_SENDER_ID,
|
||||
appId: Constants?.expoConfig?.extra?.FIREBASE_APP_ID,
|
||||
databaseURL: Constants?.expoConfig?.extra?.URL_FIREBASE_DB,
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,9 @@ const Styles = StyleSheet.create({
|
||||
mb15: {
|
||||
marginBottom: 15
|
||||
},
|
||||
mb20: {
|
||||
marginBottom: 20
|
||||
},
|
||||
mb30: {
|
||||
marginBottom: 30
|
||||
},
|
||||
@@ -130,6 +133,9 @@ const Styles = StyleSheet.create({
|
||||
mt15: {
|
||||
marginTop: 15
|
||||
},
|
||||
mt30: {
|
||||
marginTop: 30
|
||||
},
|
||||
mr05: {
|
||||
marginRight: 5
|
||||
},
|
||||
@@ -291,9 +297,9 @@ const Styles = StyleSheet.create({
|
||||
borderWidth: 1,
|
||||
},
|
||||
btnRound: {
|
||||
backgroundColor: '#19345E',
|
||||
backgroundColor: '#1F3C88',
|
||||
borderWidth: 0,
|
||||
borderColor: '#19345E',
|
||||
borderColor: '#1F3C88',
|
||||
alignItems: 'center',
|
||||
borderRadius: 30,
|
||||
marginTop: 15,
|
||||
@@ -309,7 +315,7 @@ const Styles = StyleSheet.create({
|
||||
},
|
||||
btnLainnya: {
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: '#19345E',
|
||||
backgroundColor: '#1F3C88',
|
||||
paddingVertical: 5,
|
||||
marginVertical: 5
|
||||
},
|
||||
@@ -473,7 +479,7 @@ const Styles = StyleSheet.create({
|
||||
borderColor: '#d6d8f6',
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
marginBottom: 10
|
||||
marginBottom: 5
|
||||
},
|
||||
wrapItemBorderNone: {
|
||||
padding: 10,
|
||||
@@ -502,7 +508,7 @@ const Styles = StyleSheet.create({
|
||||
iconContent: {
|
||||
padding: 10,
|
||||
borderRadius: 100,
|
||||
backgroundColor:'#E5E7EB'
|
||||
backgroundColor: '#E5E7EB'
|
||||
},
|
||||
wrapHeadViewMember: {
|
||||
backgroundColor: '#19345E',
|
||||
@@ -578,7 +584,6 @@ const Styles = StyleSheet.create({
|
||||
padding: 10,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
borderColor: '#d6d8f6',
|
||||
borderBottomWidth: 1,
|
||||
alignItems: 'center'
|
||||
},
|
||||
@@ -723,6 +728,69 @@ const Styles = StyleSheet.create({
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 5,
|
||||
elevation: 50,
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.6)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalConfirmContainer: {
|
||||
width: '80%',
|
||||
borderRadius: 14,
|
||||
overflow: 'hidden',
|
||||
elevation: 5,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 3.84,
|
||||
},
|
||||
modalConfirmContent: {
|
||||
padding: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalConfirmTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 8,
|
||||
textAlign: 'center',
|
||||
},
|
||||
modalConfirmMessage: {
|
||||
fontSize: 14,
|
||||
textAlign: 'center',
|
||||
lineHeight: 20,
|
||||
},
|
||||
modalConfirmDivider: {
|
||||
height: 1,
|
||||
width: '100%',
|
||||
},
|
||||
modalConfirmFooter: {
|
||||
flexDirection: 'row',
|
||||
height: 50,
|
||||
},
|
||||
modalConfirmButton: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalConfirmButtonText: {
|
||||
fontSize: 16,
|
||||
},
|
||||
modalConfirmVerticalDivider: {
|
||||
width: 1,
|
||||
height: '100%',
|
||||
},
|
||||
wrapGridItem: {
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
padding: 10,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
width: '48.5%',
|
||||
marginBottom: 10,
|
||||
},
|
||||
flex1: {
|
||||
flex: 1
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
24
declarations.d.ts
vendored
Normal file
24
declarations.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
declare module "*.png" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.jpg" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.jpeg" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.svg" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.gif" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
61
lib/api.ts
61
lib/api.ts
@@ -96,30 +96,18 @@ export const apiGetGroup = async ({ user, active, search }: { user: string, acti
|
||||
};
|
||||
|
||||
export const apiCreateGroup = async (data: { user: string, name: string }) => {
|
||||
await api.post('mobile/group', data).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.post('mobile/group', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiEditGroup = async (data: { user: string, name: string }, id: string) => {
|
||||
await api.put(`mobile/group/${id}`, data).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.put(`mobile/group/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiDeleteGroup = async (data: { user: string, isActive: boolean }, id: string) => {
|
||||
await api.delete(`mobile/group/${id}`, { data }).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.delete(`mobile/group/${id}`, { data });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiGetPosition = async ({ user, active, search, group }: { user: string, active: string, search: string, group?: string }) => {
|
||||
@@ -128,22 +116,14 @@ export const apiGetPosition = async ({ user, active, search, group }: { user: st
|
||||
};
|
||||
|
||||
export const apiCreatePosition = async (data: { user: string, name: string, idGroup: string }) => {
|
||||
await api.post('mobile/position', data).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.post('mobile/position', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
|
||||
export const apiDeletePosition = async (data: { user: string, isActive: boolean }, id: string) => {
|
||||
await api.delete(`mobile/position/${id}`, { data }).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.delete(`mobile/position/${id}`, { data });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiEditPosition = async (data: { user: string, name: string, idGroup: string }, id: string) => {
|
||||
@@ -207,12 +187,8 @@ export const apiUpdateDiscussionGeneralCommentar = async ({ id, data }: { id: st
|
||||
|
||||
|
||||
export const apiDeleteMemberDiscussionGeneral = async (data: { user: string, idUser: string }, id: string) => {
|
||||
await api.delete(`mobile/discussion-general/${id}/member`, { data }).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.delete(`mobile/discussion-general/${id}/member`, { data });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
|
||||
@@ -222,19 +198,10 @@ export const apiUpdateStatusDiscussionGeneral = async ({ id, data }: { id: strin
|
||||
};
|
||||
|
||||
export const apiDeleteDiscussionGeneral = async (data: { user: string, active: boolean }, id: string) => {
|
||||
await api.delete(`mobile/discussion-general/${id}`, { data }).then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
const response = await api.delete(`mobile/discussion-general/${id}`, { data });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// export const apiEditDiscussionGeneral = async (data: { user: string, title: string, desc: string }, id: string) => {
|
||||
// const response = await api.put(`/mobile/discussion-general/${id}`, data)
|
||||
// return response.data;
|
||||
// };
|
||||
|
||||
export const apiEditDiscussionGeneral = async (data: FormData, id: string) => {
|
||||
const response = await api.put(`/mobile/discussion-general/${id}`, data, {
|
||||
headers: {
|
||||
|
||||
@@ -23,6 +23,10 @@ export function pushToPage(category: string, idContent: string) {
|
||||
return router.push(`/member/${idContent}`)
|
||||
} else if (cat[0] == 'project') {
|
||||
return router.push(`/project/${idContent}`)
|
||||
} else if (cat[0] == 'group') {
|
||||
return router.push(`/group`)
|
||||
} else if (cat[0] == 'position') {
|
||||
return router.push(`/position`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,25 +6,29 @@ import {
|
||||
} from '@react-native-firebase/messaging';
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import { useEffect } from 'react';
|
||||
import { PermissionsAndroid, Platform } from 'react-native';
|
||||
import { Linking, PermissionsAndroid, Platform } from 'react-native';
|
||||
import { ConstEnv } from '@/constants/ConstEnv';
|
||||
|
||||
// Firebase config
|
||||
const RNfirebaseConfig = {
|
||||
apiKey: "AIzaSyB2hbsW91J3oRQx4_jgrCCNY0tNt5-21e8",
|
||||
authDomain: "googleapis.com",
|
||||
projectId: "mobile-darmasaba",
|
||||
storageBucket: "mobile-darmasaba.appspot.com",
|
||||
messagingSenderId: "867439221179",
|
||||
appId: "1:867439221179:android:4509f77478c8dce99b0c9e",
|
||||
databaseURL: "https://mobile-darmasaba-default-rtdb.asia-southeast1.firebasedatabase.app/"
|
||||
apiKey: ConstEnv.firebase.apiKey,
|
||||
authDomain: ConstEnv.firebase.authDomain,
|
||||
projectId: ConstEnv.firebase.projectId,
|
||||
storageBucket: ConstEnv.firebase.storageBucket,
|
||||
messagingSenderId: ConstEnv.firebase.messagingSenderId,
|
||||
appId: ConstEnv.firebase.appId,
|
||||
databaseURL: ConstEnv.firebase.databaseURL
|
||||
};
|
||||
|
||||
const initializeFirebase = async () => {
|
||||
try {
|
||||
const app = getApps().length ? getApp() : initializeApp(RNfirebaseConfig);
|
||||
let app;
|
||||
const apps = getApps();
|
||||
if (apps.length) {
|
||||
app = getApp() as any;
|
||||
} else {
|
||||
app = initializeApp(RNfirebaseConfig) as any;
|
||||
}
|
||||
const mess = getMessaging(app);
|
||||
// await registerDeviceForRemoteMessages(mess);
|
||||
// `registerDeviceForRemoteMessages` tidak perlu lagi
|
||||
await setAutoInitEnabled(mess, true);
|
||||
|
||||
return mess;
|
||||
@@ -33,6 +37,30 @@ const initializeFirebase = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
export const checkPermission = async () => {
|
||||
try {
|
||||
if (Platform.OS === 'android') {
|
||||
return await PermissionsAndroid.check(
|
||||
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
|
||||
);
|
||||
} else if (Platform.OS === 'ios') {
|
||||
const { status } = await Notifications.getPermissionsAsync();
|
||||
return status === 'granted';
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Error checking notification permissions:', err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const openSettings = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
Linking.openURL('app-settings:');
|
||||
} else {
|
||||
Linking.openSettings();
|
||||
}
|
||||
};
|
||||
|
||||
export const requestPermission = async () => {
|
||||
try {
|
||||
if (Platform.OS === 'android') {
|
||||
|
||||
@@ -40,9 +40,8 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea
|
||||
}, []);
|
||||
|
||||
const decryptToken = (async (token: string) => {
|
||||
var C = require("crypto-js");
|
||||
var Decrypted = C.AES.decrypt(token, ConstEnv.pass_encrypt);
|
||||
var result = Decrypted.toString(C.enc.Utf8);
|
||||
var Decrypted = CryptoES.AES.decrypt(token, ConstEnv.pass_encrypt);
|
||||
var result = Decrypted.toString(CryptoES.enc.Utf8);
|
||||
return result
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user