Compare commits
14 Commits
amalia/15-
...
amalia/12-
| Author | SHA1 | Date | |
|---|---|---|---|
| ca3d0d9d19 | |||
| 42f245f37c | |||
| 6acfcf9a54 | |||
| 2b7022ee3d | |||
| ec24cb70cb | |||
| 5451dc092f | |||
| 74ba2641ca | |||
| fb8a140a31 | |||
| f341bd01c6 | |||
| c458504da2 | |||
| a0d1b90662 | |||
| bd9fe8676d | |||
| 56856a96fd | |||
| 049f6c63cc |
@@ -4,7 +4,7 @@ export default {
|
||||
expo: {
|
||||
name: "Desa+",
|
||||
slug: "mobile-darmasaba",
|
||||
version: "2.0.3", // Versi aplikasi (App Store)
|
||||
version: "2.0.5", // Versi aplikasi (App Store)
|
||||
jsEngine: "jsc",
|
||||
orientation: "portrait",
|
||||
icon: "./assets/images/logo-icon-small.png",
|
||||
@@ -14,7 +14,7 @@ export default {
|
||||
ios: {
|
||||
supportsTablet: true,
|
||||
bundleIdentifier: "mobiledarmasaba.app",
|
||||
buildNumber: "5",
|
||||
buildNumber: "7",
|
||||
infoPlist: {
|
||||
ITSAppUsesNonExemptEncryption: false,
|
||||
CFBundleDisplayName: "Desa+"
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
},
|
||||
android: {
|
||||
package: "mobiledarmasaba.app",
|
||||
versionCode: 12,
|
||||
versionCode: 15,
|
||||
adaptiveIcon: {
|
||||
foregroundImage: "./assets/images/logo-icon-small.png",
|
||||
backgroundColor: "#ffffff"
|
||||
@@ -77,7 +77,8 @@ export default {
|
||||
URL_OTP: process.env.URL_OTP,
|
||||
URL_STORAGE: process.env.URL_STORAGE,
|
||||
URL_FIREBASE_DB: process.env.URL_FIREBASE_DB,
|
||||
PASS_ENC: process.env.PASS_ENC
|
||||
PASS_ENC: process.env.PASS_ENC,
|
||||
WA_SERVER_TOKEN: process.env.WA_SERVER_TOKEN,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,7 +19,6 @@ import { getMessaging, onMessage } from "@react-native-firebase/messaging";
|
||||
import { Redirect, router, Stack, usePathname } from "expo-router";
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { useEffect } from "react";
|
||||
import { Platform } from "react-native";
|
||||
import { Easing, Notifier } from 'react-native-notifier';
|
||||
import { Provider } from "react-redux";
|
||||
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import HeaderRightAnnouncementDetail from "@/components/announcement/headerAnnouncementDetail";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import Skeleton from "@/components/skeleton";
|
||||
import Text from '@/components/Text';
|
||||
import { ConstEnv } from "@/constants/ConstEnv";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiGetAnnouncementOne } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Entypo, MaterialIcons } from "@expo/vector-icons";
|
||||
import { Entypo, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
|
||||
import * as FileSystem from 'expo-file-system';
|
||||
import { startActivityAsync } from 'expo-intent-launcher';
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import * as Sharing from 'expo-sharing';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Dimensions, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { Alert, Dimensions, Platform, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import * as mime from 'react-native-mime-types';
|
||||
import RenderHTML from 'react-native-render-html';
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
type Props = {
|
||||
@@ -23,22 +30,30 @@ export default function DetailAnnouncement() {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [data, setData] = useState<Props>({ id: '', title: '', desc: '' })
|
||||
const [dataMember, setDataMember] = useState<any>({})
|
||||
const [dataFile, setDataFile] = useState<{ idStorage: string; name: string; extension: string }[]>([])
|
||||
const update = useSelector((state: any) => state.announcementUpdate)
|
||||
const entityUser = useSelector((state: any) => state.user)
|
||||
const contentWidth = Dimensions.get('window').width
|
||||
const [loading, setLoading] = useState(true)
|
||||
const arrSkeleton = Array.from({ length: 2 }, (_, index) => index)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const [loadingOpen, setLoadingOpen] = useState(false)
|
||||
|
||||
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetAnnouncementOne({ id: id, user: hasil })
|
||||
setData(response.data)
|
||||
setDataMember(response.member)
|
||||
if (response.success) {
|
||||
setData(response.data)
|
||||
setDataMember(response.member)
|
||||
} else {
|
||||
Toast.show({ type: 'small', text1: response.message })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
Toast.show({ type: 'small', text1: 'Gagal mengambil data' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -64,6 +79,37 @@ export default function DetailAnnouncement() {
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
const openFile = (item: { idStorage: string; name: string; extension: string }) => {
|
||||
if (Platform.OS == 'android') setLoadingOpen(true)
|
||||
let remoteUrl = ConstEnv.url_storage + '/files/' + item.idStorage;
|
||||
const fileName = item.name + '.' + item.extension;
|
||||
let localPath = `${FileSystem.documentDirectory}/${fileName}`;
|
||||
const mimeType = mime.lookup(fileName)
|
||||
|
||||
FileSystem.downloadAsync(remoteUrl, localPath).then(async ({ uri }) => {
|
||||
const contentURL = await FileSystem.getContentUriAsync(uri);
|
||||
setLoadingOpen(false)
|
||||
try {
|
||||
if (Platform.OS == 'android') {
|
||||
await startActivityAsync(
|
||||
'android.intent.action.VIEW',
|
||||
{
|
||||
data: contentURL,
|
||||
flags: 1,
|
||||
type: mimeType as string,
|
||||
}
|
||||
);
|
||||
} else if (Platform.OS == 'ios') {
|
||||
Sharing.shareAsync(localPath);
|
||||
}
|
||||
} catch (error) {
|
||||
Alert.alert('INFO', 'Gagal membuka file, tidak ada aplikasi yang dapat membuka file ini');
|
||||
} finally {
|
||||
if (Platform.OS == 'android') setLoadingOpen(false)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -111,6 +157,7 @@ export default function DetailAnnouncement() {
|
||||
<RenderHTML
|
||||
contentWidth={contentWidth}
|
||||
source={{ html: data?.desc }}
|
||||
baseStyle={{ color: 'black' }}
|
||||
/>
|
||||
:
|
||||
<Text>{data?.desc}</Text>
|
||||
@@ -120,7 +167,26 @@ export default function DetailAnnouncement() {
|
||||
}
|
||||
|
||||
</View>
|
||||
<View style={[Styles.wrapPaper, Styles.mv15]}>
|
||||
{
|
||||
dataFile.length > 0 && (
|
||||
<View style={[Styles.wrapPaper, Styles.mt10]}>
|
||||
<View style={[Styles.mb05]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>File</Text>
|
||||
</View>
|
||||
{dataFile.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
||||
title={item.name}
|
||||
titleWeight="normal"
|
||||
onPress={() => { openFile({ idStorage: item.idStorage, name: item.name, extension: item.extension }) }}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
<View style={[Styles.wrapPaper, Styles.mt10]}>
|
||||
{
|
||||
loading ?
|
||||
arrSkeleton.map((item, index) => {
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ButtonSelect from "@/components/buttonSelect";
|
||||
import DrawerBottom from "@/components/drawerBottom";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import MenuItemRow from "@/components/menuItemRow";
|
||||
import ModalSelectMultiple from "@/components/modalSelectMultiple";
|
||||
import Text from "@/components/Text";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { setUpdateAnnouncement } from "@/lib/announcementUpdate";
|
||||
import { apiCreateAnnouncement } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Entypo } from "@expo/vector-icons";
|
||||
import { Entypo, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||
import * as DocumentPicker from "expo-document-picker";
|
||||
import { router, Stack } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SafeAreaView, ScrollView, StyleSheet, View } from "react-native";
|
||||
@@ -23,6 +27,9 @@ export default function CreateAnnouncement() {
|
||||
const [modalDivisi, setModalDivisi] = useState(false);
|
||||
const [divisionMember, setDivisionMember] = useState<any>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [fileForm, setFileForm] = useState<any[]>([])
|
||||
const [isModalFile, setModalFile] = useState(false)
|
||||
const [indexDelFile, setIndexDelFile] = useState<number>(0)
|
||||
const [dataForm, setDataForm] = useState({
|
||||
title: "",
|
||||
desc: "",
|
||||
@@ -84,6 +91,25 @@ export default function CreateAnnouncement() {
|
||||
}
|
||||
}
|
||||
|
||||
const pickDocumentAsync = async () => {
|
||||
let result = await DocumentPicker.getDocumentAsync({
|
||||
type: ["*/*"],
|
||||
multiple: true
|
||||
});
|
||||
if (!result.canceled) {
|
||||
for (let i = 0; i < result.assets?.length; i++) {
|
||||
if (result.assets[i].uri) {
|
||||
setFileForm((prev) => [...prev, result.assets[i]])
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function deleteFile(index: number) {
|
||||
setFileForm([...fileForm.filter((val, i) => i !== index)])
|
||||
setModalFile(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -134,6 +160,27 @@ export default function CreateAnnouncement() {
|
||||
onChange={(val) => validationForm("desc", val)}
|
||||
multiline
|
||||
/>
|
||||
<ButtonSelect value="Upload File" onPress={pickDocumentAsync} />
|
||||
{
|
||||
fileForm.length > 0
|
||||
&&
|
||||
<View style={[Styles.borderAll, Styles.round10, Styles.p10, Styles.mb10]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>File</Text>
|
||||
{
|
||||
fileForm.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType={fileForm.length > 1 ? "bottom" : "none"}
|
||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
||||
title={item.name}
|
||||
titleWeight="normal"
|
||||
onPress={() => { setIndexDelFile(index); setModalFile(true) }}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
}
|
||||
|
||||
<ButtonSelect
|
||||
value="Pilih divisi penerima pengumuman"
|
||||
onPress={() => {
|
||||
@@ -178,6 +225,16 @@ export default function CreateAnnouncement() {
|
||||
setModalDivisi(false)
|
||||
}}
|
||||
/>
|
||||
|
||||
<DrawerBottom animation="slide" isVisible={isModalFile} setVisible={setModalFile} title="Menu">
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<MenuItemRow
|
||||
icon={<Ionicons name="trash" color="black" size={25} />}
|
||||
title="Hapus"
|
||||
onPress={() => { deleteFile(indexDelFile) }}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ButtonSelect from "@/components/buttonSelect";
|
||||
import DrawerBottom from "@/components/drawerBottom";
|
||||
import { InputForm } from "@/components/inputForm";
|
||||
import MenuItemRow from "@/components/menuItemRow";
|
||||
import ModalSelectMultiple from "@/components/modalSelectMultiple";
|
||||
import Text from '@/components/Text';
|
||||
import Styles from "@/constants/Styles";
|
||||
import { setUpdateAnnouncement } from "@/lib/announcementUpdate";
|
||||
import { apiEditAnnouncement, apiGetAnnouncementOne } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Entypo } from "@expo/vector-icons";
|
||||
import { Entypo, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||
import * as DocumentPicker from "expo-document-picker";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SafeAreaView, ScrollView, View } from "react-native";
|
||||
@@ -33,6 +37,9 @@ export default function EditAnnouncement() {
|
||||
const [modalDivisi, setModalDivisi] = useState(false);
|
||||
const [disableBtn, setDisableBtn] = useState(true);
|
||||
const [dataMember, setDataMember] = useState<any>([]);
|
||||
const [fileForm, setFileForm] = useState<any[]>([])
|
||||
const [indexDelFile, setIndexDelFile] = useState<number>(0)
|
||||
const [isModalFile, setModalFile] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [dataForm, setDataForm] = useState({
|
||||
title: "",
|
||||
@@ -127,6 +134,25 @@ export default function EditAnnouncement() {
|
||||
}
|
||||
}
|
||||
|
||||
const pickDocumentAsync = async () => {
|
||||
let result = await DocumentPicker.getDocumentAsync({
|
||||
type: ["*/*"],
|
||||
multiple: true
|
||||
});
|
||||
if (!result.canceled) {
|
||||
for (let i = 0; i < result.assets?.length; i++) {
|
||||
if (result.assets[i].uri) {
|
||||
setFileForm((prev) => [...prev, result.assets[i]])
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function deleteFile(index: number) {
|
||||
setFileForm([...fileForm.filter((val, i) => i !== index)])
|
||||
setModalFile(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -179,6 +205,26 @@ export default function EditAnnouncement() {
|
||||
value={dataForm.desc}
|
||||
multiline
|
||||
/>
|
||||
<ButtonSelect value="Upload File" onPress={pickDocumentAsync} />
|
||||
{
|
||||
fileForm.length > 0
|
||||
&&
|
||||
<View style={[Styles.borderAll, Styles.round10, Styles.p10, Styles.mb10]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>File</Text>
|
||||
{
|
||||
fileForm.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType={fileForm.length > 1 ? "bottom" : "none"}
|
||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
||||
title={item.name}
|
||||
titleWeight="normal"
|
||||
onPress={() => { setIndexDelFile(index); setModalFile(true) }}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
}
|
||||
<ButtonSelect
|
||||
value="Pilih divisi penerima pengumuman"
|
||||
onPress={() => {
|
||||
@@ -223,6 +269,16 @@ export default function EditAnnouncement() {
|
||||
}}
|
||||
value={dataMember}
|
||||
/>
|
||||
|
||||
<DrawerBottom animation="slide" isVisible={isModalFile} setVisible={setModalFile} title="Menu">
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<MenuItemRow
|
||||
icon={<Ionicons name="trash" color="black" size={25} />}
|
||||
title="Hapus"
|
||||
onPress={() => { deleteFile(indexDelFile) }}
|
||||
/>
|
||||
</View>
|
||||
</DrawerBottom>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ export default function EditBanner() {
|
||||
>
|
||||
<Entypo name="image" size={50} color={"#aeaeae"} />
|
||||
<Text style={[Styles.textInformation, Styles.mt05]}>
|
||||
Mohon unggah gambar dalam resolusi 1535 x 450 piksel untuk
|
||||
Mohon unggah gambar dalam resolusi 1650 x 720 pixel untuk
|
||||
memastikan
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -137,7 +137,7 @@ export default function CreateBanner() {
|
||||
>
|
||||
<Entypo name="image" size={50} color={"#aeaeae"} />
|
||||
<Text style={[Styles.textInformation, Styles.mt05]}>
|
||||
Mohon unggah gambar dalam resolusi 1535 x 450 pixel untuk
|
||||
Mohon unggah gambar dalam resolusi 1650 x 720 pixel untuk
|
||||
memastikan
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function BannerList() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current));
|
||||
const deletedEntity = await apiDeleteBanner({ user: hasil }, dataId);
|
||||
if (deletedEntity.success) {
|
||||
if (deletedEntity.success ) {
|
||||
Toast.show({ type: 'small', text1: 'Berhasil menghapus data', })
|
||||
apiGetBanner({ user: hasil }).then((data) =>
|
||||
dispatch(setEntities(data.data))
|
||||
|
||||
@@ -222,7 +222,8 @@ export default function DetailDiscussionGeneral() {
|
||||
<MaterialIcons name="chat" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title={data?.title + " " + data?.createdAt}
|
||||
title={data?.title}
|
||||
titleShowAll={true}
|
||||
subtitle={
|
||||
!data?.isActive ?
|
||||
<LabelStatus category='warning' text='ARSIP' size="small" />
|
||||
|
||||
@@ -69,10 +69,9 @@ export default function CreateDivision() {
|
||||
if (!response.available) {
|
||||
AlertKonfirmasi({
|
||||
title: 'Peringatan',
|
||||
desc: 'Nama divisi sudah ada. Apakah anda yakin ingin membuat divisi dengan nama yang sama?',
|
||||
onPress: () => {
|
||||
handleSetData()
|
||||
}
|
||||
category: 'warning',
|
||||
desc: 'Nama divisi sudah ada. Tidak dapat membuat divisi dengan nama yang sama',
|
||||
onPress: () => { }
|
||||
})
|
||||
} else {
|
||||
handleSetData()
|
||||
|
||||
@@ -12,6 +12,7 @@ import { apiGetProfile } from "@/lib/api";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
type Props = {
|
||||
@@ -42,10 +43,15 @@ export default function MemberDetail() {
|
||||
try {
|
||||
setLoading(loading)
|
||||
const response = await apiGetProfile({ id: id })
|
||||
setData(response.data)
|
||||
setEdit(valueRoleUser.filter((v) => v.login == entityUser.role)[0]?.data.some((i: any) => i.id == response.data.idUserRole))
|
||||
if (response.success) {
|
||||
setData(response.data)
|
||||
setEdit(valueRoleUser.filter((v) => v.login == entityUser.role)[0]?.data.some((i: any) => i.id == response.data.idUserRole))
|
||||
} else {
|
||||
Toast.show({ type: 'small', text1: response.message })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
Toast.show({ type: 'small', text1: 'Gagal mengambil data' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -84,7 +90,7 @@ export default function MemberDetail() {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<View style={[Styles.wrapHeadViewMember,]}>
|
||||
<View style={[Styles.wrapHeadViewMember]}>
|
||||
{
|
||||
loading ?
|
||||
<>
|
||||
|
||||
@@ -5,17 +5,27 @@ type Props = {
|
||||
title: string,
|
||||
desc: string
|
||||
onPress: () => void
|
||||
category?: string
|
||||
}
|
||||
|
||||
export default function AlertKonfirmasi({ title, desc, onPress }: Props) {
|
||||
Alert.alert(title, desc, [
|
||||
{
|
||||
text: 'Tidak',
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Ya',
|
||||
onPress: () => { onPress() }
|
||||
},
|
||||
]);
|
||||
export default function AlertKonfirmasi({ title, desc, onPress, category }: Props) {
|
||||
if (category == "warning") {
|
||||
Alert.alert(title, desc, [
|
||||
{
|
||||
text: 'Oke',
|
||||
style: 'cancel',
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
Alert.alert(title, desc, [
|
||||
{
|
||||
text: 'Tidak',
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Ya',
|
||||
onPress: () => { onPress() }
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,10 @@ type Props = {
|
||||
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 }: Props) {
|
||||
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;
|
||||
const lebar = width ? lebarDim * width / 100 : 'auto';
|
||||
const textColorFix = textColor ? textColor : 'black';
|
||||
@@ -49,7 +50,7 @@ export default function BorderBottomItem({ title, subtitle, icon, desc, onPress,
|
||||
{icon}
|
||||
<View style={[Styles.rowSpaceBetween, width ? { width: lebar } : { width: '88%' }]}>
|
||||
<View style={[Styles.ml10, rightTopInfo ? { width: '70%' } : { width: '90%' }]}>
|
||||
<Text style={[titleWeight == 'normal' ? Styles.textDefault : Styles.textDefaultSemiBold, { color: textColorFix }]} numberOfLines={1} ellipsizeMode='tail'>{title}</Text>
|
||||
<Text style={[titleWeight == 'normal' ? Styles.textDefault : Styles.textDefaultSemiBold, { color: textColorFix }]} numberOfLines={titleShowAll ? 0 : 1} ellipsizeMode='tail'>{title}</Text>
|
||||
{
|
||||
subtitle &&
|
||||
typeof subtitle == "string"
|
||||
|
||||
@@ -15,16 +15,16 @@ export default function DiscussionItem({ title, user, date, onPress }: Props) {
|
||||
<Pressable style={[Styles.wrapItemDiscussion]} onPress={onPress}>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mb10]}>
|
||||
<Ionicons name="chatbox-ellipses-outline" size={22} color="black" style={Styles.mr10} />
|
||||
<View style={[{flex:1}]}>
|
||||
<View style={[{ flex: 1 }]}>
|
||||
<Text style={{ fontWeight: 'bold' }} numberOfLines={1} ellipsizeMode="tail">{title}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={Styles.rowSpaceBetween}>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<View style={[Styles.rowSpaceBetween]}>
|
||||
<View style={[Styles.rowItemsCenter, { flex: 1 }]}>
|
||||
<Feather name="user" size={18} color="grey" style={Styles.mr05} />
|
||||
<Text style={[Styles.textInformation]}>{user}</Text>
|
||||
<Text style={[Styles.textInformation]} numberOfLines={1} ellipsizeMode="tail">{user}</Text>
|
||||
</View>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<View style={[Styles.rowItemsCenter, { flex: 1, justifyContent: 'flex-end' }]}>
|
||||
<Feather name="clock" size={18} color="grey" style={Styles.mr05} />
|
||||
<Text style={[Styles.textInformation]}>{date}</Text>
|
||||
</View>
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function TaskDivisionDetail({ refreshing }: { refreshing: boolean
|
||||
:
|
||||
data.length > 0 ?
|
||||
data.map((item, index) => (
|
||||
<Pressable key={index} style={[Styles.wrapPaper]} onPress={() => { router.push(`/division/${id}/task/${item.idProject}`) }}>
|
||||
<Pressable key={index} style={[Styles.wrapPaper, Styles.mb05]} onPress={() => { router.push(`/division/${id}/task/${item.idProject}`) }}>
|
||||
<Text style={[Styles.textDefaultSemiBold]} numberOfLines={1} ellipsizeMode="tail">{item.title} - {item.projectTitle}</Text>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
|
||||
<Feather name="clock" size={18} color="grey" style={Styles.mr05} />
|
||||
|
||||
@@ -343,7 +343,9 @@ const Styles = StyleSheet.create({
|
||||
borderRadius: 15,
|
||||
backgroundColor: '#19345E',
|
||||
display: 'flex',
|
||||
width: '92%'
|
||||
width: '92%',
|
||||
resizeMode: 'stretch',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
wrapGridContent: {
|
||||
shadowColor: '#171717',
|
||||
@@ -473,6 +475,7 @@ const Styles = StyleSheet.create({
|
||||
wrapHeadViewMember: {
|
||||
backgroundColor: '#19345E',
|
||||
paddingVertical: 30,
|
||||
paddingHorizontal: 15,
|
||||
alignItems: 'center',
|
||||
borderBottomLeftRadius: 25,
|
||||
borderBottomRightRadius: 25
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.3</string>
|
||||
<string>2.0.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
@@ -39,7 +39,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>5</string>
|
||||
<string>7</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
15
lib/api.ts
15
lib/api.ts
@@ -11,7 +11,20 @@ export const apiCheckPhoneLogin = async (body: { phone: string }) => {
|
||||
}
|
||||
|
||||
export const apiSendOtp = async (body: { phone: string, otp: number }) => {
|
||||
const res = await axios.get(`${Constants.expoConfig?.extra?.URL_OTP}/code?nom=${body.phone}&text=*Desa%2B*%0AMasukkan%20kode%20ini%20*${encodeURIComponent(body.otp)}*%20pada%20aplikasi%20Desa%2B%20anda.%20Jangan%20berikan%20pada%20siapapun.`)
|
||||
const message = "Desa+\nMasukkan kode ini " + body.otp + " pada aplikasi Desa+ anda. Jangan berikan pada siapapun."
|
||||
const textFix = encodeURIComponent(message)
|
||||
// const res = await axios.get(`${Constants.expoConfig?.extra?.URL_OTP}/code?nom=${body.phone}&text=*Desa%2B*%0AMasukkan%20kode%20ini%20*${encodeURIComponent(body.otp)}*%20pada%20aplikasi%20Desa%2B%20anda.%20Jangan%20berikan%20pada%20siapapun.`)
|
||||
const res = await fetch(
|
||||
`${Constants.expoConfig?.extra?.URL_OTP}/code?nom=${body.phone}&text=${textFix}`,
|
||||
{
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
Authorization: `Bearer ${Constants.expoConfig?.extra?.WA_SERVER_TOKEN}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return res.status
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user