farhantock
5 months ago
2 changed files with 634 additions and 0 deletions
@ -0,0 +1,176 @@ |
|||||||
|
import { TouchableRipple, Button, Card, Text, Avatar, List, Appbar } from 'react-native-paper'; |
||||||
|
import { View, StyleSheet, ScrollView } from 'react-native'; |
||||||
|
import React, { useState } from 'react'; |
||||||
|
import { colors } from '../../../utils/color' |
||||||
|
import Icon from 'react-native-vector-icons/AntDesign'; |
||||||
|
import moment from 'moment'; |
||||||
|
import 'moment/locale/id'; |
||||||
|
import person from '../../../assets/images/courier_man.png' |
||||||
|
import { strings } from '../../../utils/i18n'; |
||||||
|
moment.locale('id'); |
||||||
|
export default function PersonelScreen({ route, navigation }) { |
||||||
|
const role = 'Danru' |
||||||
|
|
||||||
|
const dummyData = [ |
||||||
|
{ id: '2', status: "Sakit", position: "Guard", name: "ibnu", date: '2024-02-10', timeIn: '08:15', timeOut: '17:30' }, |
||||||
|
{ id: '3', status: "Cuti", position: "Guard", name: "ardhi", date: '2024-02-11', timeIn: '08:10', timeOut: '17:20' }, |
||||||
|
{ id: '4', status: "", position: "Admin", name: "hana", date: '2024-02-12', timeIn: '08:10', timeOut: '17:20' }, |
||||||
|
{ id: '5', status: "", position: "Guard", name: "satori", date: '2024-02-13', timeIn: '08:10', timeOut: '17:20' }, |
||||||
|
{ id: '6', status: "", position: "Guard", name: "khaidir", date: '2024-02-14', timeIn: '08:10', timeOut: '17:20' }, |
||||||
|
]; |
||||||
|
|
||||||
|
const getCardColor = (status) => { |
||||||
|
switch (status) { |
||||||
|
case 'Sakit': |
||||||
|
return colors.mistBlue; |
||||||
|
case 'Alpa': |
||||||
|
return colors.semiRed; |
||||||
|
case 'Izin': |
||||||
|
return colors.semiYellow; |
||||||
|
case 'Cuti': |
||||||
|
return colors.amethystSmoke; |
||||||
|
default: |
||||||
|
return colors.mercury; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const getTextColor = (status) => { |
||||||
|
switch (status) { |
||||||
|
case 'Sakit': |
||||||
|
return colors.white; |
||||||
|
case 'Alpa': |
||||||
|
return colors.beanRed; |
||||||
|
case 'Izin': |
||||||
|
return colors.orange; |
||||||
|
case 'Cuti': |
||||||
|
return colors.white; |
||||||
|
default: |
||||||
|
return colors.mistBlue; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const getTextStatusColor = (status) => { |
||||||
|
switch (status) { |
||||||
|
case 'Sakit': |
||||||
|
return colors.mistBlue; |
||||||
|
case 'Alpa': |
||||||
|
return colors.beanRed; |
||||||
|
case 'Izin': |
||||||
|
return colors.orange; |
||||||
|
case 'Cuti': |
||||||
|
return colors.amethystSmoke; |
||||||
|
default: |
||||||
|
return colors.mercury; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<View style={styles.container}> |
||||||
|
<Appbar.Header mode='center-aligned' style={{ backgroundColor: colors.blue, elevation: 4 }}> |
||||||
|
<Appbar.BackAction color={colors.pureWhite} onPress={() => { navigation.goBack() }} /> |
||||||
|
<Appbar.Content titleStyle={{ fontWeight: 'bold' }} color={colors.pureWhite} title={strings('activity.personel')} /> |
||||||
|
</Appbar.Header> |
||||||
|
{role === 'Danru' ? |
||||||
|
<ScrollView style={{ flex: 1, marginHorizontal: 5 }}> |
||||||
|
{dummyData.map((item) => ( |
||||||
|
<List.Section> |
||||||
|
<List.Accordion |
||||||
|
titleStyle={{ color: getTextColor(item.status) }} |
||||||
|
title={`${item.name} - ${item.position} ${item.status}`} // Added status to the title
|
||||||
|
style={{ backgroundColor: getCardColor(item.status), borderRadius: 10 }} |
||||||
|
left={() => <Avatar.Image size={28} source={person} style={{ marginRight: 5, marginLeft: 10 }} />}> |
||||||
|
<View style={styles.row}> |
||||||
|
|
||||||
|
<Button mode="contained" compact={true} style={{ marginHorizontal: 1, backgroundColor: colors.black, borderRadius: 5, flex: 1, }} onPress={() => console.log('Handle Saved')}> |
||||||
|
sakit |
||||||
|
</Button> |
||||||
|
<Button mode="contained" compact={true} textColor={colors.orange} style={{ marginHorizontal: 1, backgroundColor: colors.semiYellow, borderRadius: 5, flex: 1, }} onPress={() => console.log('Handle Saved')}> |
||||||
|
Izin |
||||||
|
</Button> |
||||||
|
<Button mode="contained" compact={true} style={{ marginHorizontal: 1, backgroundColor: colors.amethystSmoke, borderRadius: 5, flex: 1, }} onPress={() => console.log('Handle Saved')}> |
||||||
|
Cuti |
||||||
|
</Button> |
||||||
|
<Button mode="contained" compact={true} style={{ marginHorizontal: 1, backgroundColor: colors.beanRed, borderRadius: 5, flex: 1, }} onPress={() => console.log('Handle Saved')}> |
||||||
|
Alpa |
||||||
|
</Button> |
||||||
|
<Button mode="contained" compact={true} style={{ marginHorizontal: 1, backgroundColor: colors.mercury, borderRadius: 5, flex: 1, }} onPress={() => console.log('Handle Saved')}> |
||||||
|
Batal |
||||||
|
</Button> |
||||||
|
|
||||||
|
</View> |
||||||
|
</List.Accordion> |
||||||
|
</List.Section> |
||||||
|
|
||||||
|
|
||||||
|
))} |
||||||
|
</ScrollView> |
||||||
|
: <ScrollView style={{ flex: 1, marginHorizontal: 5 }}> |
||||||
|
{dummyData.map((item) => ( |
||||||
|
<List.Section> |
||||||
|
<List.Item |
||||||
|
titleStyle={{ color: getTextColor(item.status) }} |
||||||
|
title={`${item.name} - ${item.position} ${item.status}`} // Added status to the title
|
||||||
|
style={{ backgroundColor: getCardColor(item.status), borderRadius: 10 }} |
||||||
|
left={() => <Avatar.Image size={28} source={person} style={{ marginRight: 5, marginLeft: 10 }} />} |
||||||
|
right={() => { |
||||||
|
if (item.status !== "") { |
||||||
|
return ( |
||||||
|
<View style={[styles.status, { backgroundColor: colors.pureWhite }]}> |
||||||
|
<Text style={{ color: getTextStatusColor(item.status), fontWeight: 'bold', paddingLeft: 3 }}> |
||||||
|
{item.status} |
||||||
|
</Text> |
||||||
|
</View> |
||||||
|
); |
||||||
|
} else { return null; } |
||||||
|
}} |
||||||
|
> |
||||||
|
</List.Item> |
||||||
|
</List.Section> |
||||||
|
))} |
||||||
|
</ScrollView>} |
||||||
|
<View style={styles.buttonContainer}> |
||||||
|
<Button mode="outlined" style={styles.button} textColor={colors.mistBlue} onPress={() => { navigation.goBack() }} > |
||||||
|
Kembali |
||||||
|
</Button> |
||||||
|
<Button mode="contained" style={[styles.button, { backgroundColor: colors.blue }]} onPress={() => console.log('Handle Saved')}> |
||||||
|
Simpan |
||||||
|
</Button> |
||||||
|
</View> |
||||||
|
</View > |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const styles = StyleSheet.create({ |
||||||
|
container: { |
||||||
|
flex: 1, |
||||||
|
marginTop: 20, |
||||||
|
backgroundColor: colors.pureWhite |
||||||
|
}, |
||||||
|
status: { |
||||||
|
backgroundColor: colors.semiBlue, |
||||||
|
borderRadius: 10, |
||||||
|
padding: 5, |
||||||
|
}, |
||||||
|
row: { |
||||||
|
flexDirection: 'row', |
||||||
|
paddingLeft: 0, |
||||||
|
marginVertical: 5, |
||||||
|
}, |
||||||
|
card: { |
||||||
|
marginHorizontal: 10, |
||||||
|
marginVertical: 4, |
||||||
|
elevation: 4, |
||||||
|
}, |
||||||
|
button: { |
||||||
|
flex: 1, |
||||||
|
margin: 5, |
||||||
|
borderRadius: 5 |
||||||
|
}, |
||||||
|
buttonContainer: { |
||||||
|
flexDirection: 'row', |
||||||
|
justifyContent: 'space-between', |
||||||
|
padding: 10, |
||||||
|
paddingBottom: 20, |
||||||
|
backgroundColor: colors.pureWhite, |
||||||
|
}, |
||||||
|
}); |
@ -0,0 +1,458 @@ |
|||||||
|
import React, { useEffect, useCallback, useMemo, useState, useRef } from 'react'; |
||||||
|
import { StatusBar } from 'react-native'; |
||||||
|
import { Button, IconButton, Text, Appbar, TextInput, TouchableRipple, Card, List, Searchbar, RadioButton } from 'react-native-paper'; |
||||||
|
import { StyleSheet, View, ScrollView, PermissionsAndroid, Image } from 'react-native'; |
||||||
|
import Icon from 'react-native-vector-icons/AntDesign'; |
||||||
|
import { colors } from '../../../../utils/color'; |
||||||
|
import { strings } from '../../../../utils/i18n'; |
||||||
|
import { launchCamera } from 'react-native-image-picker'; |
||||||
|
import { requestAccessStoragePermission } from '../../../../utils/storage'; |
||||||
|
import { getCoords } from '../../../../utils/geolocation'; |
||||||
|
import { |
||||||
|
BottomSheetModal, |
||||||
|
BottomSheetModalProvider, |
||||||
|
BottomSheetView, |
||||||
|
BottomSheetScrollView |
||||||
|
} from '@gorhom/bottom-sheet'; |
||||||
|
import RNFS from 'react-native-fs'; |
||||||
|
import ImageMarker, { Position, TextBackgroundType } from 'react-native-image-marker'; |
||||||
|
import DateTimePicker from '@react-native-community/datetimepicker'; |
||||||
|
import moment from 'moment'; |
||||||
|
|
||||||
|
export default function DialogForm({ route, navigation }) { |
||||||
|
const [images, setImages] = useState([]); |
||||||
|
const [equipment, setEquipment] = useState([]); |
||||||
|
const [selectedImageUri, setSelectedImageUri] = useState(null); |
||||||
|
const [filter, setFilter] = useState('') |
||||||
|
const bottomSheetModal = useRef(null); |
||||||
|
const bottomSheetImage = useRef(null); |
||||||
|
const [showDamageDatePicker, setShowDamageDatePicker] = useState(false); |
||||||
|
|
||||||
|
const dummyData = [ |
||||||
|
{ name: 'HT', description: "", status: "", damageDate: "" }, |
||||||
|
{ name: 'Borgol', description: "", status: "", damageDate: "" }, |
||||||
|
{ name: 'Mobil', description: "", status: "", damageDate: "" }, |
||||||
|
{ name: 'Senter', description: "", status: "", damageDate: "" }, |
||||||
|
{ name: 'Traffic cone (stick)', description: "", status: "", damageDate: "" }, |
||||||
|
{ name: 'Laptop', description: "", status: "", damageDate: "" }, |
||||||
|
]; |
||||||
|
|
||||||
|
const handleSelectEquipment = (data) => { |
||||||
|
setEquipment(prevEquipment => { |
||||||
|
if (prevEquipment.some(item => item.name === data.name)) { |
||||||
|
return prevEquipment; |
||||||
|
} |
||||||
|
return [...prevEquipment, data]; |
||||||
|
}); |
||||||
|
setFilter('') |
||||||
|
bottomSheetModal.current?.dismiss(); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleStatus = (data, newStatus) => { |
||||||
|
setEquipment(prevEquipment => { |
||||||
|
return prevEquipment.map(item => { |
||||||
|
if (item.name === data) { |
||||||
|
return { ...item, status: newStatus }; |
||||||
|
} |
||||||
|
return item; |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
const handleDamageDateChange = (data, selectedDate) => { |
||||||
|
const currentDate = selectedDate; |
||||||
|
setShowDamageDatePicker(false); |
||||||
|
setEquipment(prevEquipment => { |
||||||
|
return prevEquipment.map(item => { |
||||||
|
if (item.name === data) { |
||||||
|
return { ...item, damageDate: currentDate }; |
||||||
|
} |
||||||
|
return item; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
const showDamageDatePickerFunc = () => { |
||||||
|
setShowDamageDatePicker(true); |
||||||
|
}; |
||||||
|
|
||||||
|
console.log("equipment", equipment); |
||||||
|
const handleSetImageUri = (uri, description) => { |
||||||
|
const newImage = { uri: uri, description: description || "" }; |
||||||
|
setImages(prevImages => [...prevImages, newImage]); |
||||||
|
} |
||||||
|
|
||||||
|
const handleDeleteImage = (index) => { |
||||||
|
const updatedImages = [...images]; |
||||||
|
updatedImages.splice(index, 1); |
||||||
|
setImages(updatedImages); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleOpenSheet = useCallback(() => { |
||||||
|
bottomSheetModal.current?.present(); |
||||||
|
}, []); |
||||||
|
const handleOpenSheetImage = useCallback((uri) => { |
||||||
|
|
||||||
|
setSelectedImageUri(uri); |
||||||
|
bottomSheetImage.current?.present(); |
||||||
|
}, []); |
||||||
|
|
||||||
|
|
||||||
|
const handleTakePicture = async () => { |
||||||
|
try { |
||||||
|
const granted = await PermissionsAndroid.request( |
||||||
|
PermissionsAndroid.PERMISSIONS.CAMERA, |
||||||
|
{ |
||||||
|
title: strings('takePicture.cameraPermissionTitle'), |
||||||
|
message: strings('takePicture.cameraPermissionMessage'), |
||||||
|
buttonNeutral: strings('takePicture.cameraPermissionBtnNeutral'), |
||||||
|
buttonNegative: strings('takePicture.cameraPermissionBtnCancel'), |
||||||
|
buttonPositive: strings('takePicture.cameraPermissionBtnPositive'), |
||||||
|
}, |
||||||
|
); |
||||||
|
if (granted === PermissionsAndroid.RESULTS.GRANTED) { |
||||||
|
handleLaunchCamera() |
||||||
|
} else { |
||||||
|
} |
||||||
|
} catch (err) { |
||||||
|
console.warn(err); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const handleLaunchCamera = () => { |
||||||
|
let options = { |
||||||
|
storageOptions: { |
||||||
|
skipBackup: true, |
||||||
|
path: 'images', |
||||||
|
}, |
||||||
|
cameraType: 'front', |
||||||
|
maxWidth: 768, |
||||||
|
maxHeight: 1024, |
||||||
|
saveToPhotos: false, |
||||||
|
includeBase64: true |
||||||
|
}; |
||||||
|
|
||||||
|
launchCamera(options, (response) => { |
||||||
|
if (response.didCancel) { |
||||||
|
} else if (response.error) { |
||||||
|
} else if (response.customButton) { |
||||||
|
} else { |
||||||
|
if (response.assets && response.assets.length > 0) { |
||||||
|
handleSetImageUri(response.assets[0].uri); |
||||||
|
getCoords(loc => { |
||||||
|
if (loc) { |
||||||
|
let imageObject = { |
||||||
|
"image_uri": response.assets[0].uri, |
||||||
|
"image_blob": response.assets[0].base64, |
||||||
|
"lat": loc.lat, |
||||||
|
"lon": loc.lon |
||||||
|
} |
||||||
|
addOverlay(imageObject) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
const addOverlay = async (imageObject) => { |
||||||
|
try { |
||||||
|
const timestamp = new Date().toLocaleString(); |
||||||
|
const location = { latitude: imageObject.lat, longitude: imageObject.lon }; |
||||||
|
|
||||||
|
const overlayText = `${timestamp}\nLatitude: ${location.latitude}\nLongitude: ${location.longitude}`; |
||||||
|
|
||||||
|
if (imageObject.image_uri) { |
||||||
|
const markedImage = await ImageMarker.markText({ |
||||||
|
backgroundImage: { |
||||||
|
src: { uri: imageObject.image_uri } |
||||||
|
}, |
||||||
|
watermarkTexts: [{ |
||||||
|
text: overlayText, |
||||||
|
positionOptions: { |
||||||
|
position: Position.bottomLeft, |
||||||
|
}, |
||||||
|
style: { |
||||||
|
color: '#ffffff', |
||||||
|
fontSize: 8, |
||||||
|
fontName: 'Arial', |
||||||
|
textBackgroundStyle: { |
||||||
|
padding: 10, |
||||||
|
type: TextBackgroundType.none, |
||||||
|
color: '#00000080' |
||||||
|
} |
||||||
|
}, |
||||||
|
}], |
||||||
|
position: 'bottomLeft', |
||||||
|
color: '#ffffff', |
||||||
|
fontName: 'Arial-BoldMT', |
||||||
|
fontSize: 16, |
||||||
|
scale: 1, |
||||||
|
}); |
||||||
|
await saveToTemporaryFolder(markedImage, imageObject); |
||||||
|
} |
||||||
|
|
||||||
|
} catch (error) { |
||||||
|
console.error('Error adding overlay:', error); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const saveToTemporaryFolder = async (markedImage, imageObject) => { |
||||||
|
try { |
||||||
|
const tempPath = `file://${RNFS.TemporaryDirectoryPath}/equipment/${moment().format('YYYYMMDDHHmmss')}.jpg`; |
||||||
|
|
||||||
|
if (!requestAccessStoragePermission()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
await RNFS.copyFile(markedImage, tempPath); |
||||||
|
const imageBase64 = await RNFS.readFile(tempPath, 'base64'); |
||||||
|
storePhoto(imageObject.user_id, imageObject.drop_point_id, tempPath, imageBase64, imageObject.lat, imageObject.lon) |
||||||
|
reloadPhotos(); |
||||||
|
} catch (error) { |
||||||
|
console.error('Error saving image to temporary folder:', error); |
||||||
|
} |
||||||
|
} |
||||||
|
const renderImages = useMemo(() => images.map((image, index) => ( |
||||||
|
<> |
||||||
|
<View key={index} style={styles.imageBlock}> |
||||||
|
<TouchableRipple onPress={() => { handleOpenSheetImage(image.uri) }}> |
||||||
|
<View style={styles.imageContainer}> |
||||||
|
<Image |
||||||
|
source={{ uri: image.uri }} |
||||||
|
style={styles.image} |
||||||
|
resizeMode="cover" |
||||||
|
/> |
||||||
|
</View> |
||||||
|
</TouchableRipple> |
||||||
|
</View> |
||||||
|
|
||||||
|
<Button icon="delete" style={{ borderRadius: 10, backgroundColor: colors.semiRed, marginHorizontal: 5, marginBottom: 10 }} textColor={colors.beanRed} mode="contained-tonal" onPress={() => handleDeleteImage(index)}> |
||||||
|
{strings('global.delete')} |
||||||
|
</Button> |
||||||
|
</> |
||||||
|
)), [images]); |
||||||
|
|
||||||
|
const renderEquipment = (data) => ( |
||||||
|
<View> |
||||||
|
<TouchableRipple key={data.name} onPress={() => handleSelectEquipment(data)}> |
||||||
|
<List.Item |
||||||
|
title={data.name} |
||||||
|
/> |
||||||
|
</TouchableRipple> |
||||||
|
</View> |
||||||
|
); |
||||||
|
|
||||||
|
const filteredData = dummyData.filter(item => item.name.toLowerCase().includes(filter.toLowerCase())); |
||||||
|
return ( |
||||||
|
<> |
||||||
|
<StatusBar backgroundColor={colors.blue} barStyle='light-content' translucent={true} /> |
||||||
|
<Appbar.Header mode='center-aligned' style={{ backgroundColor: colors.blue, elevation: 4 }}> |
||||||
|
<Appbar.BackAction color={colors.pureWhite} onPress={() => { navigation.goBack() }} /> |
||||||
|
<Appbar.Content titleStyle={{ fontWeight: 'bold' }} color={colors.pureWhite} title={strings('activity.ppe')} /> |
||||||
|
</Appbar.Header> |
||||||
|
<View style={{ flex: 1, backgroundColor: colors.pureWhite }}> |
||||||
|
<View style={styles.container}> |
||||||
|
<TouchableRipple onPress={handleOpenSheet}> |
||||||
|
<TextInput |
||||||
|
style={{ marginTop: 10 }} |
||||||
|
dense={true} |
||||||
|
editable={false} |
||||||
|
underlineColor={colors.amethystSmoke} |
||||||
|
activeOutlineColor={colors.blue} |
||||||
|
label="Pilih Perlengkapan Personel" |
||||||
|
mode="outlined" |
||||||
|
/> |
||||||
|
</TouchableRipple> |
||||||
|
<Text variant="titleSmall" style={{ marginTop: 10, marginLeft: 10 }}>{strings('activity.ppeUse')}</Text> |
||||||
|
<ScrollView style={[styles.scrollViewContainer, { backgroundColor: colors.pureWhite }]}> |
||||||
|
{equipment.map(item => |
||||||
|
<List.Accordion |
||||||
|
titleStyle={{ color: colors.blue }} |
||||||
|
rippleColor={colors.semiBlue} |
||||||
|
title={item.name} |
||||||
|
style={styles.accordion} |
||||||
|
> |
||||||
|
<View style={{ marginHorizontal: 10, marginVertical: 5 }}> |
||||||
|
<View style={{ flexDirection: 'row', marginHorizontal: 10, marginVertical: 5 }}> |
||||||
|
<RadioButton |
||||||
|
status={item.status === 'Baik' ? 'checked' : 'unchecked'} |
||||||
|
onPress={() => handleStatus(item.name, 'Baik')} |
||||||
|
color={colors.blue} |
||||||
|
uncheckedColor={colors.amethystSmoke} |
||||||
|
|
||||||
|
/> |
||||||
|
<TouchableRipple rippleColor={colors.pureWhite} onPress={() => handleStatus(item.name, 'Baik')}> |
||||||
|
<Text variant="bodySmall" style={{ color: colors.black, fontSize: 14, marginBottom: 6, marginTop: 10 }}> |
||||||
|
Baik |
||||||
|
</Text> |
||||||
|
</TouchableRipple> |
||||||
|
<RadioButton |
||||||
|
status={item.status === 'Rusak' ? 'checked' : 'unchecked'} |
||||||
|
onPress={() => handleStatus(item.name, 'Rusak')} |
||||||
|
color={colors.blue} |
||||||
|
uncheckedColor={colors.amethystSmoke} |
||||||
|
|
||||||
|
/> |
||||||
|
<TouchableRipple rippleColor={colors.pureWhite} onPress={() => handleStatus(item.name, 'Rusak')}> |
||||||
|
<Text variant="bodySmall" style={{ color: colors.black, fontSize: 14, marginBottom: 6, marginTop: 10 }}> |
||||||
|
Rusak |
||||||
|
</Text> |
||||||
|
</TouchableRipple> |
||||||
|
|
||||||
|
</View> |
||||||
|
{item.status === 'Rusak' && |
||||||
|
<> |
||||||
|
<TouchableRipple rippleColor={colors.pureWhite} onPress={showDamageDatePickerFunc}> |
||||||
|
<TextInput |
||||||
|
value={item.damageDate ? moment(item.damageDate).format("DD-MM-YYYY") : ''} |
||||||
|
dense={true} |
||||||
|
editable={false} |
||||||
|
underlineColor={colors.amethystSmoke} |
||||||
|
activeOutlineColor={colors.blue} |
||||||
|
label="Tanggal kerusakan" |
||||||
|
mode="outlined" |
||||||
|
/> |
||||||
|
</TouchableRipple> |
||||||
|
<TextInput |
||||||
|
style={{ marginTop: 10 }} |
||||||
|
dense={true} |
||||||
|
underlineColor={colors.amethystSmoke} |
||||||
|
activeOutlineColor={colors.blue} |
||||||
|
label="Deskripsi" |
||||||
|
mode="outlined" |
||||||
|
multiline={true} |
||||||
|
numberOfLines={5} |
||||||
|
/> |
||||||
|
</> |
||||||
|
} |
||||||
|
|
||||||
|
{showDamageDatePicker && ( |
||||||
|
<DateTimePicker |
||||||
|
value={item.damageDate || new Date()} |
||||||
|
mode="date" |
||||||
|
display="default" |
||||||
|
onChange={handleDamageDateChange(item.name)} |
||||||
|
/> |
||||||
|
)} |
||||||
|
|
||||||
|
{renderImages} |
||||||
|
</View> |
||||||
|
</List.Accordion> |
||||||
|
)} |
||||||
|
|
||||||
|
</ScrollView> |
||||||
|
<Button icon="camera-plus" style={{ borderRadius: 10, backgroundColor: colors.semiBlue, marginVertical: 10, marginHorizontal: 5, }} textColor={colors.blue} mode="contained-tonal" onPress={handleTakePicture}> |
||||||
|
{strings('global.addImage')} |
||||||
|
</Button> |
||||||
|
</View > |
||||||
|
|
||||||
|
<View style={styles.buttonContainer}> |
||||||
|
<Button mode="outlined" style={styles.button} textColor={colors.mistBlue} onPress={() => { navigation.goBack() }} > |
||||||
|
Kembali |
||||||
|
</Button> |
||||||
|
<Button mode="contained" style={[styles.button, { backgroundColor: colors.blue }]} onPress={() => console.log('Handle Saved')}> |
||||||
|
Simpan |
||||||
|
</Button> |
||||||
|
</View> |
||||||
|
</View > |
||||||
|
<BottomSheetModalProvider> |
||||||
|
<BottomSheetModal |
||||||
|
ref={bottomSheetModal} |
||||||
|
index={0} |
||||||
|
snapPoints={['50%']} |
||||||
|
bottomInset={10} |
||||||
|
detached={true} |
||||||
|
keyboardBehavior="fillParent" |
||||||
|
style={{ marginHorizontal: 15 }} |
||||||
|
> |
||||||
|
<Searchbar |
||||||
|
mode='bar' |
||||||
|
placeholder="Cari Peralatan" |
||||||
|
onChangeText={text => setFilter(text)} |
||||||
|
value={filter} |
||||||
|
traileringIconColor={colors.white} |
||||||
|
style={{ backgroundColor: colors.white }} |
||||||
|
showDivider={true} |
||||||
|
elevation={1} |
||||||
|
/> |
||||||
|
<BottomSheetScrollView contentContainerStyle={styles.scrollView}> |
||||||
|
{filteredData.map(item => renderEquipment(item))} |
||||||
|
</BottomSheetScrollView> |
||||||
|
</BottomSheetModal> |
||||||
|
<BottomSheetModal |
||||||
|
ref={bottomSheetImage} |
||||||
|
index={0} |
||||||
|
snapPoints={['50%']} |
||||||
|
> |
||||||
|
<BottomSheetView style={{ alignItems: 'center' }} > |
||||||
|
<Image |
||||||
|
source={{ uri: selectedImageUri }} |
||||||
|
style={styles.imageDetail} |
||||||
|
resizeMode="cover" |
||||||
|
/> |
||||||
|
</BottomSheetView> |
||||||
|
</BottomSheetModal> |
||||||
|
</BottomSheetModalProvider> |
||||||
|
|
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const styles = StyleSheet.create({ |
||||||
|
container: { |
||||||
|
flex: 1, |
||||||
|
marginHorizontal: 10 |
||||||
|
}, |
||||||
|
|
||||||
|
scrollViewContainer: { |
||||||
|
flex: 1, |
||||||
|
marginVertical: 10, |
||||||
|
}, |
||||||
|
card: { |
||||||
|
flex: 1, |
||||||
|
marginHorizontal: 8, |
||||||
|
marginVertical: 5, |
||||||
|
backgroundColor: colors.pureWhite, |
||||||
|
}, |
||||||
|
subText: { |
||||||
|
fontSize: 12, |
||||||
|
color: colors.blue |
||||||
|
}, |
||||||
|
button: { |
||||||
|
flex: 1, |
||||||
|
margin: 5, |
||||||
|
borderRadius: 5 |
||||||
|
}, |
||||||
|
buttonContainer: { |
||||||
|
flexDirection: 'row', |
||||||
|
justifyContent: 'space-between', |
||||||
|
padding: 10, |
||||||
|
paddingBottom: 20, |
||||||
|
backgroundColor: colors.pureWhite, |
||||||
|
}, |
||||||
|
imageBlock: { |
||||||
|
marginVertical: 10, |
||||||
|
alignItems: 'center', |
||||||
|
}, |
||||||
|
imageContainer: { |
||||||
|
flexDirection: 'row', |
||||||
|
alignItems: 'center', |
||||||
|
}, |
||||||
|
image: { |
||||||
|
width: 330, |
||||||
|
height: 150, |
||||||
|
borderRadius: 7 |
||||||
|
}, |
||||||
|
imageDetail: { |
||||||
|
width: 330, |
||||||
|
height: 300, |
||||||
|
borderRadius: 7 |
||||||
|
}, |
||||||
|
accordion: { |
||||||
|
backgroundColor: colors.semiBlue, |
||||||
|
color: colors.blue, |
||||||
|
marginHorizontal: 10, |
||||||
|
marginTop: 10, |
||||||
|
borderRadius: 5 |
||||||
|
}, |
||||||
|
}) |
Loading…
Reference in new issue