fix(tool-search): add published date, center copy button

- Add formatTimeAgo utility function for relative time display
- Show "Published X ago" at bottom of each tool card using npmPublishedAt
- Center CodeBlock copy button vertically for better alignment
- Update Tool interface to include npmPublishedAt from API
This commit is contained in:
Ajax Davis 2025-12-11 11:37:42 +10:00
parent 256699099b
commit 2a16218871
3 changed files with 46 additions and 16 deletions

View file

@ -10,6 +10,7 @@ import { Input } from '@tpmjs/ui/Input/Input';
import { ProgressBar } from '@tpmjs/ui/ProgressBar/ProgressBar';
import { Select } from '@tpmjs/ui/Select/Select';
import { Spinner } from '@tpmjs/ui/Spinner/Spinner';
import { formatTimeAgo } from '@tpmjs/utils/format';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import { AppHeader } from '~/components/AppHeader';
@ -25,6 +26,7 @@ interface Tool {
package: {
npmPackageName: string;
npmVersion: string;
npmPublishedAt: string;
category: string;
npmRepository: { url: string; type: string } | null;
isOfficial: boolean;
@ -323,19 +325,23 @@ export default function ToolSearchPage(): React.ReactElement {
)}
</div>
{/* Install command - onClick prevents propagation to parent Link */}
<div
className="mt-auto"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="presentation"
>
<CodeBlock
code={`npm install ${tool.package.npmPackageName}`}
language="bash"
size="sm"
showCopy={true}
/>
{/* Bottom section with install command and published date */}
<div className="mt-auto space-y-2">
<div
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="presentation"
>
<CodeBlock
code={`npm install ${tool.package.npmPackageName}`}
language="bash"
size="sm"
showCopy={true}
/>
</div>
<div className="text-xs text-foreground-tertiary">
Published {formatTimeAgo(tool.package.npmPublishedAt)}
</div>
</div>
</CardContent>
</Card>

View file

@ -59,12 +59,12 @@ export const codeBlockCodeVariants = createVariants({
*/
export const codeBlockCopyButtonVariants = createVariants({
base: [
// Position
'absolute top-2 right-2',
// Position - vertically centered on right side
'absolute right-2 top-1/2 -translate-y-1/2',
// Display
'flex items-center justify-center',
// Size
'w-8 h-8',
'w-7 h-7',
// Background
'bg-surface-elevated hover:bg-accent',
// Border

View file

@ -9,3 +9,27 @@ export function formatDate(date: Date): string {
export function formatNumber(num: number): string {
return new Intl.NumberFormat('en-US').format(num);
}
/**
* Format a date as a relative time string (e.g., "2 days ago", "3 months ago")
*/
export function formatTimeAgo(date: Date | string): string {
const now = new Date();
const then = typeof date === 'string' ? new Date(date) : date;
const diffMs = now.getTime() - then.getTime();
const diffSecs = Math.floor(diffMs / 1000);
const diffMins = Math.floor(diffSecs / 60);
const diffHours = Math.floor(diffMins / 60);
const diffDays = Math.floor(diffHours / 24);
const diffWeeks = Math.floor(diffDays / 7);
const diffMonths = Math.floor(diffDays / 30);
const diffYears = Math.floor(diffDays / 365);
if (diffSecs < 60) return 'just now';
if (diffMins < 60) return `${diffMins}m ago`;
if (diffHours < 24) return `${diffHours}h ago`;
if (diffDays < 7) return `${diffDays}d ago`;
if (diffWeeks < 4) return `${diffWeeks}w ago`;
if (diffMonths < 12) return `${diffMonths}mo ago`;
return `${diffYears}y ago`;
}