SkateSpots/src/components/EscrowPanel.tsx
SkateSpots 9357386bbd i18n(es): batch 3 part 2 — locale-aware dates & relative times
- New src/lib/dateFnsI18n.ts re-exports date-fns with formatDistanceToNow /
  formatDistanceToNowStrict / formatDistance / format defaulting to the active
  locale, plus dateLocaleCode() for native toLocale{Date,Time}String calls.
- LanguageProvider keeps the locale in sync during render, so the first paint is
  already in-language.
- Codemod: 11 date-fns imports now use the shim; ~39 native date/time calls pass
  the app locale code instead of undefined/[]/hardcoded 'en-US'. Number
  .toLocaleString() calls are deliberately untouched.
2026-10-02 15:19:38 +07:00

75 lines
2.2 KiB
TypeScript

import { dateLocaleCode } from '@/lib/dateFnsI18n';
import { useMemo } from 'react';
import { Lock } from 'lucide-react';
import { parseEscrowToken, type EscrowTokenInfo } from '@/lib/cashuEscrow';
import { cn } from '@/lib/utils';
import { useTranslation } from '@/contexts/language';
function hostOf(url: string): string {
try {
return new URL(url).host;
} catch {
return url;
}
}
function formatDate(seconds: number): string {
return new Date(seconds * 1000).toLocaleDateString(dateLocaleCode(), {
year: 'numeric',
month: 'short',
day: 'numeric',
});
}
/**
* Read-only escrow summary for a locked Cashu token. Pure/offline (uses
* `parseEscrowToken`), so it renders on web as well as native — only the
* mint-touching create/redeem actions are native-only.
*/
export function EscrowPanel({ token, className }: { token: string; className?: string }) {
const { t } = useTranslation();
const info = useMemo<EscrowTokenInfo | null>(() => {
try {
return parseEscrowToken(token);
} catch {
return null;
}
}, [token]);
if (!info || !info.locked) return null;
const locktime = info.policy?.locktime;
return (
<div
className={cn(
'rounded-xl border border-[#ff6600]/30 bg-[#ff6600]/5 p-3 text-xs',
className,
)}
>
<div className="flex items-center gap-2 font-bold text-[#ff6600]">
<Lock className="h-3.5 w-3.5" />
{t('marketUi.escrowPanel.escrowed', { amount: info.amount.toLocaleString() })}
</div>
<div className="mt-1 space-y-0.5 text-gray-400">
<p>
{t('marketUi.escrowPanel.mint')}: <span className="text-gray-300">{hostOf(info.mint)}</span>
</p>
{locktime ? (
<p>
{info.refundable ? (
<>{t('marketUi.escrowPanel.refundSinceBefore')}{' '}
<span className="text-[#ccff00]">{formatDate(locktime)}</span>
</>
) : (
<>{t('marketUi.escrowPanel.redeemBefore')}{' '}
<span className="text-gray-300">{formatDate(locktime)}</span>
</>
)}
</p>
) : (
<p>{t('marketUi.escrowPanel.noExpiry')}</p>
)}
</div>
</div>
);
}