Browse Source

fix(presence): add skeleton

master
farhantock 3 months ago
parent
commit
710b32acfa
  1. 209
      src/screens/presence/index.js

209
src/screens/presence/index.js

@ -1,75 +1,176 @@
import { TouchableRipple, TextInput, Card, Text, Appbar } from 'react-native-paper';
import { View, StyleSheet, ScrollView } from 'react-native';
import React, { useState } from 'react';
import { View, StyleSheet, ScrollView, RefreshControl, StatusBar, Image } from 'react-native';
import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { colors } from '../../utils/color'
import Icon from 'react-native-vector-icons/AntDesign';
import moment from 'moment';
import 'moment/locale/id';
import RequestModule from '../../services/api/request';
import renderSkeleton from '../../components/renderSkeleton'
import {
BottomSheetModal,
BottomSheetModalProvider,
BottomSheetView
} from '@gorhom/bottom-sheet';
moment.locale('id');
const PAGE_SIZE = 25;
export default function PresenceScreen({ route, navigation }) {
const request = new RequestModule('presence');
const [refreshing, setRefreshing] = useState(false);
const [page, setPage] = useState(0);
const [dataPresence, setDataPresence] = useState([]);
const [loading, setLoading] = useState(false);
const bottomSheetImage = useRef(null);
const [selectedImageUri, setSelectedImageUri] = useState(null);
const handleOpenSheetImage = useCallback((uri) => {
console.log('URI received:', uri);
setSelectedImageUri(uri);
bottomSheetImage.current?.present();
}, []);
const onRefresh = useCallback(() => {
setRefreshing(true);
setPage(0);
getPresenceHistory(0);
}, []);
useEffect(() => {
getPresenceHistory(page);
}, [page]);
const getPresenceHistory = async (pageNum) => {
if (loading) return;
setLoading(true);
const payload = {
paging: { start: pageNum * PAGE_SIZE, length: PAGE_SIZE },
columns: [
{ name: 'deleted_at', logic_operator: 'IS NULL', operator: 'AND' },
],
orders: { columns: ['created_at', 'id'], ascending: false },
};
const result = await request.getDataSearch(payload);
setDataPresence((prevData) =>
pageNum === 0 ? result.data.data : [...prevData, ...result.data.data]
);
setPage(pageNum + 1);
setRefreshing(false);
setLoading(false);
};
// console.log("uri", dataPresence[0].attachments);
const convertDuration = (data) => {
const hours = Math.floor(data / 60);
const minutes = data % 60;
return `${hours} jam ${minutes} menit`;
}
const dummyData = [
{ id: '1', date: '2024-02-09', timeIn: '08:00', timeOut: '17:00', shift: "Pagi", duration: new Date(0, 0, 0, 8, 0, 0) },
{ id: '2', date: '2024-02-10', timeIn: '08:15', timeOut: '17:30', shift: "Pagi", duration: new Date(0, 0, 0, 8, 30, 0) },
{ id: '3', date: '2024-02-11', timeIn: '08:10', timeOut: '17:20', shift: "Pagi", duration: new Date(0, 0, 0, 9, 0, 0) },
{ id: '4', date: '2024-02-12', timeIn: '08:10', timeOut: '17:20', shift: "Pagi", duration: new Date(0, 0, 0, 10, 0, 0) },
{ id: '5', date: '2024-02-13', timeIn: '08:10', timeOut: '17:20', shift: "Pagi", duration: new Date(0, 0, 0, 11, 0, 0) },
{ id: '6', date: '2024-02-14', timeIn: '08:10', timeOut: '17:20', shift: "Pagi", duration: new Date(0, 0, 0, 9, 30, 0) },
{ id: '7', date: '2024-02-15', timeIn: '08:10', timeOut: '17:20', shift: "Pagi", duration: new Date(0, 0, 0, 12, 0, 0) },
];
const handleScroll = ({ nativeEvent }) => {
if (isCloseToBottom(nativeEvent)) {
getPresenceHistory(page);
}
};
const isCloseToBottom = ({ layoutMeasurement, contentOffset, contentSize }) => {
return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;
};
const renderImage = useMemo(() => {
console.log('Rendering image with URI:', selectedImageUri);
return (
<Image
source={{ uri: selectedImageUri }}
style={styles.imageDetail}
resizeMode="cover"
/>
);
}, [selectedImageUri]);
return (
<>
<StatusBar backgroundColor={colors.blue} barStyle='ligth-content' translucent={true} />
<Appbar.Header mode='center-aligned' style={{ backgroundColor: colors.blue }}>
<Appbar.BackAction color={colors.pureWhite} onPress={() => { navigation.goBack() }} />
<Appbar.Content titleStyle={{ fontWeight: 'bold' }} color={colors.pureWhite} title='Riwayat kehadiran' />
</Appbar.Header>
<ScrollView style={{ flex: 1 }}>
{dummyData.map((item) => (
<Card key={item.id} style={styles.cardPrecense}>
<Card.Content>
<View style={[styles.row, { justifyContent: 'space-between' }]}>
<View style={[styles.row, styles.precenseDate]}>
<Icon name="calendar" size={20} color={colors.blue} />
<Text style={{ color: colors.blue, fontWeight: 'bold', paddingLeft: 3 }}>
{moment(item.date).format('dddd, DD MMMM - YYYY')}
</Text>
</View>
<View style={[styles.precenseDate, { backgroundColor: colors.semigreen }]}>
<Text style={{ color: colors.green, fontWeight: 'bold', paddingLeft: 3 }}>
Shift {item.shift}
</Text>
</View>
</View>
<ScrollView
style={{ flex: 1, marginTop: 5 }}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
colors={[colors.blue]}
progressBackgroundColor={colors.pureWhite}
/>
}
onScroll={handleScroll}
scrollEventThrottle={400}
>
{loading ? (
// renderSkeleton(10)
null
) : (
dataPresence.map((item) => (
<TouchableRipple onPress={() => item.attachments && item.attachments[0] && handleOpenSheetImage(item.attachments[0].url)} key={item.id}>
<Card key={item.id} style={styles.cardPrecense}>
<Card.Content>
<View style={[styles.row, { justifyContent: 'space-between' }]}>
<View style={[styles.row, styles.precenseDate]}>
<Icon name="calendar" size={20} color={colors.blue} />
<Text style={{ color: colors.blue, fontWeight: 'bold', paddingLeft: 3 }}>
{moment(item.datePresence).format('dddd, DD MMMM - YYYY')}
</Text>
</View>
<View style={[styles.precenseDate, { backgroundColor: colors.semigreen }]}>
<Text style={{ color: colors.green, fontWeight: 'bold', paddingLeft: 3 }}>
Shift {item.shift}
</Text>
</View>
</View>
<View style={[styles.row, { justifyContent: 'space-between' }]}>
<View style={styles.row}>
<Icon name="clockcircleo" size={20} color={colors.black} />
<Text style={{ color: colors.amethystSmoke, fontWeight: 'bold', paddingLeft: 3 }}>
Durasi Kerja
</Text>
</View>
<View style={styles.row}>
<Text style={{ color: colors.amethystSmoke }}>Masuk</Text>
<Icon name="minus" size={20} color={colors.amethystSmoke} />
<Text style={{ color: colors.amethystSmoke }}>Keluar</Text>
</View>
</View>
<View style={[styles.row, { justifyContent: 'space-between' }]}>
<View style={styles.row}>
<Text style={{ color: colors.black, paddingLeft: 5 }}>{item.timeIn} Jam</Text>
</View>
<View style={styles.row}>
<Text>{item.timeIn}</Text>
<Icon name="minus" size={20} color={colors.black} />
<Text>{item.timeOut}</Text>
</View>
</View>
</Card.Content>
</Card>
))}
<View style={[styles.row, { justifyContent: 'space-between' }]}>
<View style={styles.row}>
<Icon name="clockcircleo" size={20} color={colors.black} />
<Text style={{ color: colors.amethystSmoke, fontWeight: 'bold', paddingLeft: 3 }}>
Durasi Kerja
</Text>
</View>
<View style={styles.row}>
<Text style={{ color: colors.amethystSmoke }}>Masuk</Text>
<Icon name="minus" size={20} color={colors.amethystSmoke} />
<Text style={{ color: colors.amethystSmoke }}>Keluar</Text>
</View>
</View>
<View style={[styles.row, { justifyContent: 'space-between' }]}>
<View style={styles.row}>
<Text style={{ color: colors.black, paddingLeft: 5 }}>{item.duration ? convertDuration(item.duration) : ''}</Text>
</View>
<View style={styles.row}>
<Text>{moment(item.in_time).format('HH:mm')}</Text>
<Icon name="minus" size={20} color={colors.black} />
<Text>{item.out_time ? moment(item.out_time).format('HH:mm') : ''}</Text>
</View>
</View>
<Text>{item.attachments && item.attachments.length > 0 ? item.attachments[0].url : 'No attachments'}</Text>
</Card.Content>
</Card>
</TouchableRipple>
))
)}
</ScrollView>
<BottomSheetModalProvider>
<BottomSheetModal
ref={bottomSheetImage}
index={0}
snapPoints={['50%']}
>
<BottomSheetView style={{ alignItems: 'center' }} >
{renderImage}
</BottomSheetView>
</BottomSheetModal>
</BottomSheetModalProvider>
</>
)
}

Loading…
Cancel
Save