All files / src/features/dashboard/components conversion-rate-card.tsx

93.33% Statements 14/15
75% Branches 6/8
100% Functions 6/6
93.33% Lines 14/15

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 120 121 122 123 124 125                  2x                                         2x 30x                   84x                 2x       16x                     16x     16x                   16x       16x                     13x               12x 12x       30x                                    
import { ArrowRight } from 'lucide-react';
import type { MenuItemConfig } from '@/components/action-menu';
import { DashboardCardWrapper } from './shared/dashboard-card-wrapper';
import { DashboardStateRenderer } from './shared/dashboard-state-renderer';
import { Heading } from '@/components/heading';
import { useConversionRates } from '../hooks/use-conversion-rates';
import { useCardVisibility } from '../hooks/use-card-visibility';
 
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
('use memo');
 
// Conversion data interfaces
interface ConversionItem {
  currency: string;
  rate: string;
}
 
interface ConversionColumnData {
  title: string;
  items: ConversionItem[];
}
 
interface ConversionRateCardProps {
  columns: ConversionColumnData[];
  actionItems?: MenuItemConfig[];
  loading?: boolean;
  error?: string | null;
  onRetry?: () => void;
}
 
const ConversionColumn = ({ title, items }: ConversionColumnData) => (
  <div>
    <Heading
      as="h3"
      size="h6"
      className="font-semibold bg-gradient-vertical bg-clip-text text-transparent mb-4"
    >
      {title}
    </Heading>
    <div className="space-y-3">
      {items.map((item, index) => (
        <div key={index} className="flex justify-between items-center py-2">
          <span className="flex-1 text-sm text-default">{item.currency}</span>
          <span className="flex-1 text-sm text-default">{item.rate}</span>
        </div>
      ))}
    </div>
  </div>
);
 
export const ConversionRateCard = ({
  actionItems,
}: ConversionRateCardProps) => {
  // Manage card visibility
  const { isVisible, hideCard } = useCardVisibility({
    id: 'conversionCard',
    defaultVisible: true,
  });
 
  // Use existing API data hook
  const {
    data: conversionRatesData,
    isLoading: conversionLoading,
    error: conversionError,
    refetch: refetchConversionRates,
  } = useConversionRates();
 
  // Create action items with hide functionality
  const cardActionItems: MenuItemConfig[] = actionItems || [
    { label: 'View' },
    {
      label: 'Delete',
      variant: 'destructive',
      onClick: hideCard,
    },
  ];
 
  // Don't render if card is hidden
  Iif (!isVisible) {
    return null;
  }
 
  return (
    <DashboardCardWrapper
      title="Conversion Rate to Naira"
      actionItems={cardActionItems}
      contentClassName="p-6 flex"
      className="mt-8"
    >
      <DashboardStateRenderer
        loading={conversionLoading}
        error={conversionError?.message || null}
        data={conversionRatesData || []}
        isEmpty={data => (data as ConversionColumnData[]).length === 0}
        onRetry={refetchConversionRates}
        loadingMessage="Loading conversion rates..."
        errorTitle=""
        emptyMessage="No conversion rates available"
        className="h-64"
      >
        {conversionData => {
          const typedData = conversionData as ConversionColumnData[];
          return (
            <>
              <div className="flex-1 grid grid-cols-3 gap-8">
                {typedData.map((column, index) => (
                  <ConversionColumn key={index} {...column} />
                ))}
              </div>
              <button
                className="self-center w-12 h-12 bg-gradient-vertical rounded-full flex items-center justify-center shadow-lg transition-all duration-200 hover:scale-105"
                aria-label="View more conversion rates"
              >
                <ArrowRight className="w-6 h-6 text-white" aria-hidden="true" />
              </button>
            </>
          );
        }}
      </DashboardStateRenderer>
    </DashboardCardWrapper>
  );
};
 
export type { ConversionItem, ConversionColumnData, ConversionRateCardProps };