flexprice/flexprice-front

add metadata display section in InvoiceDetail

オープン

#370 opened on 2025/09/18

 (1 件のコメント) (0 件のリアクション) (1 人の担当者)TypeScript (106 件のフォーク)auto 404
good first issuehacktoberfestjavascriptreact

Repository metrics

Stars
 (32 個のスター)
PR merge metrics
 (PR metrics pending)

説明

dd a dedicated Metadata section to the InvoiceDetail view/component to display invoice metadata (arbitrary key/value pairs).
This improves visibility and UX for billing-related metadata such as order ids, external references, or notes.


Goals

  • Show invoice metadata clearly in the Invoice detail page.
  • Provide copy-to-clipboard support for values.
  • Handle empty, long, or sensitive metadata gracefully.

Acceptance Criteria

  1. Section placement

    • Appears in InvoiceDetail below invoice header (or sidebar if layout allows).
    • Title: Metadata.
  2. Data

    • Source: invoice.metadata (Record<string, string | number | null>).
    • Show No metadata available if empty.
  3. Rendering

    • Two-column layout: key (left), value (right).
    • Humanize keys (e.g., external_order_idExternal order id).
    • Truncate long values; show full value in tooltip + allow copy.
  4. Interactions

    • Copy button for each value → copies full string to clipboard.
    • Tooltip on hover shows full value.
    • Accessible via keyboard with aria-labels.
  5. Styling

    • Use Tailwind + shadcn/ui.
    • Compact, scannable layout with consistent spacing.
    • Keys column fixed width; values truncated or wrapped.
  6. Edge cases

    • Null values → render as empty string.
    • Very long values → truncate + tooltip.
    • Sensitive keys (token, secret, password, cvv, ssn) → mask value with Hidden for security.
  7. Tests

    • Renders metadata list.
    • Shows “No metadata available” when empty.
    • Copy button copies correct value.
    • Sensitive keys are masked.

Implementation Notes

  • Create reusable InvoiceMetadata component.
  • Input: metadata?: Record<string, unknown>.
  • Isolated so it can be reused elsewhere.

Minimal Example (React + TS):

function humanizeKey(k: string) {
  return k.replace(/[_-]/g, " ").replace(/\b\w/g, c => c.toUpperCase());
}

function isSensitive(key: string) {
  return /(token|secret|password|ssn|cvv)/i.test(key);
}

コントリビューターガイド