Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 4x 7x 7x 7x 7x 7x 12x 7x 7x 7x 7x 7x 12x | import { useMemo } from 'react';
import { Text, View } from 'react-native';
import { FlashList } from '@shopify/flash-list';
import { Avatar } from '@repo/ui/components/Avatar';
import { useTheme } from '@repo/ui/themes/ThemeContext';
import {
checkMaintenanceRequestProcessing,
formattedRequestData,
TITLE_REQUEST_MAPPING,
} from '@/utils/request';
import { getStatusColor, STATUS_MAP } from '@/constants/request';
import { Activity } from '@/types/request';
import { RequestCategory, RequestDetail } from '@/types/request';
import { ApprovalTimelineItem } from '../ApprovalTimelineItem';
import { InfoGrid } from '../InfoGrid';
interface RequestCardDetailProps extends RequestDetail {}
export const RequestCardDetail = (props: RequestCardDetailProps) => {
const { theme } = useTheme();
const { category, data, requesterInfo, requester, status, totalDaysOff, metadata, processingBy } =
props;
const { histories } = metadata || {};
const title = TITLE_REQUEST_MAPPING[category];
const infoData = formattedRequestData(data, category, false);
const getHistoryKey = (item: Activity, index: number) => `${item.email}-${index}`;
const reversedActivities = useMemo(() => {
Iif (!histories) return [];
return [...histories].reverse();
}, [histories]);
const isProcessingMaintenance = checkMaintenanceRequestProcessing({
category,
status,
processingBy,
});
return (
<View
className="flex-1 p-4 gap-4 rounded-lg shadow-xl"
style={{ backgroundColor: theme.colors.background.secondary }}
>
<View className="flex flex-row justify-between">
<Text className="text-2xl font-bold" style={{ color: theme.colors.text.primary }}>
{title}
</Text>
<Text
className="font-bold text-xl"
style={{ color: getStatusColor(STATUS_MAP[status], theme) }}
>
{isProcessingMaintenance ? 'In Progress' : STATUS_MAP[status]}
</Text>
</View>
<View
className="flex-row justify-between items-center p-4 rounded-lg"
style={{ backgroundColor: theme.colors.background.default }}
>
<View className="flex-row gap-4 items-center">
<Avatar
uri={requesterInfo?.avatar || undefined}
name={requesterInfo?.name ?? ''}
size={theme.metrics.spacing[13]}
/>
<Text className="text-xl font-semibold" style={{ color: theme.colors.text.primary }}>
{requesterInfo?.name ?? requester}
</Text>
</View>
{category === RequestCategory.TIME_OFF && (
<View
className="w-[40px] h-[40px] flex items-center justify-center rounded-full border border-[2px]"
style={{ borderColor: theme.colors.text.primary }}
>
<Text className="text-[24px]" style={{ color: theme.colors.text.primary }}>
{totalDaysOff || 0}
</Text>
</View>
)}
</View>
<View
className="p-4 rounded-lg flex-1 gap-2"
style={{ backgroundColor: theme.colors.background.default }}
>
<FlashList
data={reversedActivities ?? []}
keyExtractor={getHistoryKey}
showsVerticalScrollIndicator={false}
ListHeaderComponent={
<View>
<InfoGrid data={infoData} />
{histories && histories.length > 0 && (
<Text className="mt-4 mb-2" style={{ color: theme.colors.text.tertiary }}>
History
</Text>
)}
</View>
}
renderItem={({ item, index }) => (
<ApprovalTimelineItem
activity={item}
category={category}
processingBy={processingBy}
isLast={index === (histories?.length ?? 0) - 1}
/>
)}
/>
</View>
</View>
);
};
|