Files
projectsend/resources/js/components/dashboard-widgets/api-widget.tsx
ignacionelson 6e47d76ba6 ProjectSend 2.0.0
Client file sharing, rebuilt from the ground up: a private area per
client, resumable uploads, folders, groups and categories, sharing with
expiry dates and download limits, comments, file versions, an activity
log, a REST API, and sixteen languages.

This repository begins here. ProjectSend 2 was developed privately, and
that development history is not published — the previous generation
remains available, with its own history, at projectsend/legacy.

Free software under the GNU General Public License v2, or (at your
option) any later version.
2026-08-14 01:38:12 -03:00

66 lines
2.5 KiB
TypeScript

import { Link } from '@inertiajs/react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { useFormatDate } from '@/hooks/use-format-date';
import { useTranslation } from '@/hooks/use-translation';
export interface ApiUsageSummary {
requests_7d: number;
tokens: number;
expired_tokens: number;
last_used_at: string | null;
}
/**
* The viewer's own API usage at a glance. Scoped to their own tokens, like
* the API dashboard it links to — a widget everyone sees must not become a
* window onto colleagues' integrations.
*/
export function ApiWidget({ summary }: { summary: ApiUsageSummary }) {
const { t } = useTranslation();
const { date } = useFormatDate();
if (summary.tokens === 0) {
return (
<div className="space-y-3">
<p className="text-muted-foreground text-sm">{t('You have no API tokens. Create one to let an external tool act on your behalf.')}</p>
<Button variant="outline" size="sm" asChild>
<Link href="/settings/api-tokens/create">{t('Create token')}</Link>
</Button>
</div>
);
}
return (
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-muted-foreground text-xs font-medium">{t('Requests (7 days)')}</p>
<p className="mt-1 text-2xl font-semibold tabular-nums">{summary.requests_7d}</p>
</div>
<div>
<p className="text-muted-foreground text-xs font-medium">{t('Tokens')}</p>
<p className="mt-1 flex items-center gap-2 text-2xl font-semibold tabular-nums">
{summary.tokens}
{summary.expired_tokens > 0 && (
<Badge variant="destructive" className="text-xs">
{t(':count expired', { count: summary.expired_tokens })}
</Badge>
)}
</p>
</div>
</div>
<p className="text-muted-foreground text-xs">
{summary.last_used_at ? t('Last used :date', { date: date(summary.last_used_at) }) : t('Never used')}
</p>
<Button variant="ghost" size="sm" asChild className="px-0">
<Link href="/api">{t('Open the API dashboard')}</Link>
</Button>
</div>
);
}