All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m46s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 37s
Deploy to Staging / Verify Staging (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
- Create ExpirationBadge component with 30-day warning and expired states - Create DocumentCardMetadata component for type-specific field display - Update DocumentsPage to show metadata and expiration badges on cards - Update DocumentsMobileScreen with metadata and badges (mobile variant) - Redesign DocumentDetailPage with side-by-side layout (desktop) and stacked layout (mobile) showing full metadata panel - Add 33 unit tests for new components - Fix jest.config.ts testMatch pattern for test discovery 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import React from 'react';
|
|
import dayjs from 'dayjs';
|
|
|
|
interface ExpirationBadgeProps {
|
|
/** The expiration date in ISO format (YYYY-MM-DD) */
|
|
expirationDate: string | null | undefined;
|
|
/** Additional CSS classes */
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* Displays a warning badge for documents expiring within 30 days or already expired.
|
|
* Returns null if no expiration date is provided.
|
|
*/
|
|
export const ExpirationBadge: React.FC<ExpirationBadgeProps> = ({
|
|
expirationDate,
|
|
className = '',
|
|
}) => {
|
|
if (!expirationDate) {
|
|
return null;
|
|
}
|
|
|
|
const today = dayjs().startOf('day');
|
|
const expDate = dayjs(expirationDate).startOf('day');
|
|
const daysUntilExpiration = expDate.diff(today, 'day');
|
|
|
|
// Already expired
|
|
if (daysUntilExpiration < 0) {
|
|
return (
|
|
<span
|
|
className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400 ${className}`}
|
|
>
|
|
Expired
|
|
</span>
|
|
);
|
|
}
|
|
|
|
// Expiring within 30 days
|
|
if (daysUntilExpiration <= 30) {
|
|
const label =
|
|
daysUntilExpiration === 0
|
|
? 'Expires today'
|
|
: daysUntilExpiration === 1
|
|
? 'Expires tomorrow'
|
|
: `Expires in ${daysUntilExpiration} days`;
|
|
|
|
return (
|
|
<span
|
|
className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400 ${className}`}
|
|
>
|
|
{label}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
// Not expiring soon - no badge
|
|
return null;
|
|
};
|
|
|
|
export default ExpirationBadge;
|