All files / apps/host/src/components/RequestCardDetail index.tsx

93.33% Statements 14/15
73.91% Branches 17/23
100% Functions 4/4
100% Lines 13/13

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>
  );
};