Currency Api Dashboard

TypeScript

Modern currency exchange rate dashboard with real-time market data, conversion tools, analytics, historical trends, and responsive admin interface.

Stars
18
Forks
1
Downloads
N/A
Open Issues
0
Files main

Repository Files

Loading file structure...
resources/js/pages/dashboard/currencies.tsx
import { Head } from '@inertiajs/react';
import { Search } from 'lucide-react';
import React, { useState, useMemo } from 'react';

interface Currency {
    id: number;
    code: string;
    name: string;
    country: string | null;
    rate: number;
    active: boolean;
}

interface CurrenciesPageProps {
    currencies: Currency[];
}

export default function CurrenciesPage({
    currencies = [],
}: CurrenciesPageProps) {
    const [searchQuery, setSearchQuery] = useState<string>('');

    // Calculator mapping helper for INR calculations
    const inrUsdRate = useMemo(() => {
        const inrCurrency = currencies.find((c) => c.code === 'INR');

        return inrCurrency ? inrCurrency.rate : 83.25;
    }, [currencies]);

    // Filter currencies for directory search
    const filteredCurrencies = useMemo(() => {
        if (!searchQuery) {
            return currencies;
        }

        const query = searchQuery.toLowerCase();

        return currencies.filter(
            (c) =>
                c.code.toLowerCase().includes(query) ||
                c.name.toLowerCase().includes(query) ||
                (c.country && c.country.toLowerCase().includes(query)),
        );
    }, [currencies, searchQuery]);

    return (
        <>
            <Head title="Currencies Directory" />
            <div className="min-h-screen w-full space-y-6 bg-background p-4 text-foreground md:p-6">
                {/* Directory Content (Full Width) */}
                <div className="bg-card text-card-foreground shadow-xs">
                    <div className="flex flex-col gap-4 border-b border-border pb-3 sm:flex-row sm:items-center sm:justify-between">
                        <div>
                            <h1 className="text-lg font-bold">
                                Exchange Rates Registry
                            </h1>
                            <p className="text-sm text-muted-foreground">
                                Comprehensive lookup list of supported systems.
                            </p>
                        </div>
                        <div className="relative w-full sm:w-80">
                            <Search className="absolute top-2.5 left-3 h-4 w-4 text-muted-foreground" />
                            <input
                                type="text"
                                placeholder="Search code, currency name or country..."
                                value={searchQuery}
                                onChange={(e) => setSearchQuery(e.target.value)}
                                className="flex h-9 w-full rounded-md border border-input bg-transparent py-1 pr-3 pl-9 text-sm shadow-xs transition-colors focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-hidden"
                            />
                        </div>
                    </div>
                    <div className="pt-6">
                        <div className="overflow-hidden rounded-lg border border-border">
                            <div className="max-h-[600px] overflow-x-auto">
                                <table className="w-full border-collapse text-left text-sm">
                                    <thead>
                                        <tr className="border-b border-border bg-muted/40 font-semibold text-muted-foreground">
                                            <th className="w-20 p-3.5 text-center">
                                                Code
                                            </th>
                                            <th className="p-3.5">
                                                Currency Description
                                            </th>
                                            <th className="hidden p-3.5 md:table-cell">
                                                Country Mapping
                                            </th>
                                            <th className="w-48 p-3.5 pr-6 text-right">
                                                USD Rate
                                            </th>
                                            <th className="w-48 p-3.5 pr-6 text-right">
                                                INR Rate
                                            </th>
                                        </tr>
                                    </thead>
                                    <tbody className="divide-y divide-border">
                                        {filteredCurrencies.length === 0 ? (
                                            <tr>
                                                <td
                                                    colSpan={5}
                                                    className="p-8 text-center text-muted-foreground"
                                                >
                                                    No currencies found matching
                                                    "{searchQuery}"
                                                </td>
                                            </tr>
                                        ) : (
                                            filteredCurrencies.map((c) => {
                                                const inrRate = inrUsdRate
                                                    ? c.rate / inrUsdRate
                                                    : 0;

                                                return (
                                                    <tr
                                                        key={c.id}
                                                        className="transition-colors hover:bg-muted/10"
                                                    >
                                                        <td className="p-3.5 text-center font-mono font-bold text-primary">
                                                            {c.code}
                                                        </td>
                                                        <td className="p-3.5 font-semibold text-foreground">
                                                            {c.name}
                                                        </td>
                                                        <td
                                                            className="hidden max-w-sm truncate p-3.5 text-xs text-muted-foreground md:table-cell"
                                                            title={
                                                                c.country ||
                                                                'N/A'
                                                            }
                                                        >
                                                            {c.country || 'N/A'}
                                                        </td>
                                                        <td className="p-3.5 pr-6 text-right font-mono font-semibold text-foreground">
                                                            {c.rate.toLocaleString(
                                                                undefined,
                                                                {
                                                                    minimumFractionDigits: 4,
                                                                    maximumFractionDigits: 6,
                                                                },
                                                            )}
                                                        </td>
                                                        <td className="p-3.5 pr-6 text-right font-mono font-semibold text-primary">
                                                            {inrRate.toLocaleString(
                                                                undefined,
                                                                {
                                                                    minimumFractionDigits: 4,
                                                                    maximumFractionDigits: 6,
                                                                },
                                                            )}
                                                        </td>
                                                    </tr>
                                                );
                                            })
                                        )}
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </>
    );
}

CurrenciesPage.layout = {
    breadcrumbs: [
        {
            title: 'Dashboard',
            href: '/dashboard',
        },
        {
            title: 'Currencies',
            href: '/dashboard/currencies',
        },
    ],
};