From ad8588e5401b3fa3d236e87a7e678851b2391d80 Mon Sep 17 00:00:00 2001 From: BOLTy Date: Mon, 9 Feb 2026 00:01:32 -0500 Subject: [PATCH 1/2] refactor(TransactionTable): extract demo data to separate file - Export Transaction interface for reusability - Add showDemoData prop to control demo data visibility - Move hardcoded demo transactions to TransactionTable.data.ts - Add Storybook stories with multiple variants - Default behavior: empty table unless showDemoData=true or transactions provided Resolves ATL-64 --- app/components/TransactionTable.data.ts | 79 ++++++++++++++ app/components/TransactionTable.stories.tsx | 108 ++++++++++++++++++++ app/components/TransactionTable.tsx | 92 +++-------------- 3 files changed, 200 insertions(+), 79 deletions(-) create mode 100644 app/components/TransactionTable.data.ts create mode 100644 app/components/TransactionTable.stories.tsx diff --git a/app/components/TransactionTable.data.ts b/app/components/TransactionTable.data.ts new file mode 100644 index 0000000..5657df0 --- /dev/null +++ b/app/components/TransactionTable.data.ts @@ -0,0 +1,79 @@ +// Demo data for TransactionTable component +// Use in Storybook or when showDemoData prop is true + +import type { Transaction } from './TransactionTable'; + +export const demoTransactions: Transaction[] = [ + { + id: '1', + date: '06/2025', + prism: 'bitcoin Pizza', + amount: '$1,250.00', + status: 'Successful', + account: 'Jamie Smith', + isFavorite: false, + }, + { + id: '2', + date: '07/2025', + prism: 'Crypto Feast', + amount: '$500.00', + status: 'Pending', + account: 'Alex Johnson', + isFavorite: false, + }, + { + id: '3', + date: '09/2025', + prism: 'Tech Summit', + amount: '225078764578.00 sats', + status: 'Successful', + account: 'QHFI8WE8DYHWEBJhbsbdcus...', + isFavorite: true, + }, + { + id: '4', + date: '11/2025', + prism: 'Health Expo', + amount: '3000.00 Sats', + status: 'Active', + account: 'Michael Brown', + isFavorite: false, + }, + { + id: '5', + date: '06/2024', + prism: 'The true man show movie...', + amount: '999999999999999 Sats', + status: 'Active', + account: 'deekshasatapathy@twelve.cash', + isFavorite: false, + }, + { + id: '6', + date: '04/2025', + prism: 'Fashion Week', + amount: '56.5643679 Sats', + status: 'Successful', + account: 'Jessica Lee', + isFavorite: false, + }, + { + id: '7', + date: '08/2025', + prism: 'Food Festival', + amount: '1 Btc', + status: 'Successful', + account: 'kcuabcjbau2e482r982hufwueff...', + isFavorite: false, + }, + { + id: '8', + date: '12/2025', + prism: 'Finance Forum', + amount: '$1,200.00', + status: 'Pending', + account: 'Rachel Adams', + isFavorite: false, + }, +]; diff --git a/app/components/TransactionTable.stories.tsx b/app/components/TransactionTable.stories.tsx new file mode 100644 index 0000000..7ded17a --- /dev/null +++ b/app/components/TransactionTable.stories.tsx @@ -0,0 +1,108 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import TransactionTable from './TransactionTable'; +import { demoTransactions } from './TransactionTable.data'; + +const meta: Meta = { + title: 'Components/TransactionTable', + component: TransactionTable, + parameters: { + layout: 'padded', + }, + tags: ['autodocs'], + argTypes: { + showDemoData: { + control: 'boolean', + description: 'Show demo data when no transactions provided', + }, + transactions: { + control: 'object', + description: 'Array of transactions to display', + }, + }, +}; + +export default meta; +type Story = StoryObj; + +/** + * Default state with demo data enabled for visualization + */ +export const WithDemoData: Story = { + args: { + showDemoData: true, + }, +}; + +/** + * Empty state when no transactions and showDemoData is false + */ +export const Empty: Story = { + args: { + showDemoData: false, + transactions: [], + }, +}; + +/** + * With custom transactions passed as props + */ +export const WithCustomData: Story = { + args: { + showDemoData: false, + transactions: [ + { + id: 'custom-1', + date: '01/2026', + prism: 'Monthly Subscription', + amount: '$9.99', + status: 'Successful', + account: 'john@example.com', + isFavorite: false, + }, + { + id: 'custom-2', + date: '01/2026', + prism: 'One-time Purchase', + amount: '50000 Sats', + status: 'Pending', + account: 'jane@example.com', + isFavorite: true, + }, + ], + }, +}; + +/** + * With filters populated (prisms and contacts) + */ +export const WithFilters: Story = { + args: { + showDemoData: true, + prisms: [ + { id: 'prism-1', name: 'Bitcoin Pizza' }, + { id: 'prism-2', name: 'Crypto Feast' }, + { id: 'prism-3', name: 'Tech Summit' }, + ], + contacts: [ + { id: 'contact-1', firstName: 'Jamie', lastName: 'Smith', email: 'jamie@example.com' }, + { id: 'contact-2', firstName: 'Alex', lastName: 'Johnson', email: 'alex@example.com' }, + ], + }, +}; + +/** + * Interactive playground with all controls + */ +export const Playground: Story = { + args: { + showDemoData: true, + transactions: demoTransactions, + prisms: [ + { id: 'prism-1', name: 'Bitcoin Pizza' }, + { id: 'prism-2', name: 'Crypto Feast' }, + ], + contacts: [ + { id: 'contact-1', firstName: 'Jamie', lastName: 'Smith' }, + ], + }, +}; diff --git a/app/components/TransactionTable.tsx b/app/components/TransactionTable.tsx index c22e735..4c38ba6 100644 --- a/app/components/TransactionTable.tsx +++ b/app/components/TransactionTable.tsx @@ -3,6 +3,7 @@ import { useState, useEffect, useRef } from 'react'; import { useRouter } from 'next/navigation'; import { ChevronUpIcon, ArrowRightIcon } from '@heroicons/react/24/outline'; +import { demoTransactions } from './TransactionTable.data'; const calendarIcon = "https://www.figma.com/api/mcp/asset/c83e973c-82cb-4edc-a5b4-c87f5774c875"; const starIconFilled = "https://www.figma.com/api/mcp/asset/e4b8e6a1-81fb-4b30-8c31-dad418948756"; @@ -10,7 +11,7 @@ const starIconOutline = "https://www.figma.com/api/mcp/asset/af286206-fd17-4ad9- const chevronDownIcon = "https://www.figma.com/api/mcp/asset/e353d42f-828c-4a09-a6cf-c4d48027b1b6"; const arrowLeftIcon = "https://www.figma.com/api/mcp/asset/79630a33-05bd-489c-a889-a56fbcdbdc81"; -interface Transaction { +export interface Transaction { id: string; date: string; prism: string; @@ -24,15 +25,21 @@ interface Transaction { } interface TransactionTableProps { + /** Array of transactions to display */ transactions?: Transaction[]; + /** Available prisms for filtering */ prisms?: Array<{ id: string; name: string }>; + /** Available contacts for filtering */ contacts?: Array<{ id: string; firstName?: string | null; lastName?: string | null; screenName?: string | null; email?: string | null }>; + /** When true, shows demo data if no transactions provided. Use for Storybook/demos. */ + showDemoData?: boolean; } export default function TransactionTable({ transactions = [], prisms = [], - contacts = [] + contacts = [], + showDemoData = false }: TransactionTableProps) { const router = useRouter(); const [favorites, setFavorites] = useState>(new Set()); @@ -59,82 +66,6 @@ export default function TransactionTable({ const paymentModeDropdownRef = useRef(null); const rowsPerPageRef = useRef(null); - // Default sample data if none provided - const defaultTransactions: Transaction[] = [ - { - id: '1', - date: '06/2025', - prism: 'bitcoin Pizza', - amount: '$1,250.00', - status: 'Successful', - account: 'Jamie Smith', - isFavorite: false, - }, - { - id: '2', - date: '07/2025', - prism: 'Crypto Feast', - amount: '$500.00', - status: 'Pending', - account: 'Alex Johnson', - isFavorite: false, - }, - { - id: '3', - date: '09/2025', - prism: 'Tech Summit', - amount: '225078764578.00 sats', - status: 'Successful', - account: 'QHFI8WE8DYHWEBJhbsbdcus...', - isFavorite: true, - }, - { - id: '4', - date: '11/2025', - prism: 'Health Expo', - amount: '3000.00 Sats', - status: 'Active', - account: 'Michael Brown', - isFavorite: false, - }, - { - id: '5', - date: '06/2024', - prism: 'The true man show movie...', - amount: '999999999999999 Sats', - status: 'Active', - account: 'deekshasatapathy@twelve.cash', - isFavorite: false, - }, - { - id: '6', - date: '04/2025', - prism: 'Fashion Week', - amount: '56.5643679 Sats', - status: 'Successful', - account: 'Jessica Lee', - isFavorite: false, - }, - { - id: '7', - date: '08/2025', - prism: 'Food Festival', - amount: '1 Btc', - status: 'Successful', - account: 'kcuabcjbau2e482r982hufwueff...', - isFavorite: false, - }, - { - id: '8', - date: '12/2025', - prism: 'Finance Forum', - amount: '$1,200.00', - status: 'Pending', - account: 'Rachel Adams', - isFavorite: false, - }, - ]; - // Close dropdowns when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { @@ -206,7 +137,10 @@ export default function TransactionTable({ }); }; - const displayTransactions = transactions.length > 0 ? transactions : defaultTransactions; + // Use provided transactions, or demo data if showDemoData is true, otherwise empty + const displayTransactions = transactions.length > 0 + ? transactions + : (showDemoData ? demoTransactions : []); const filteredTransactions = filterTransactions(displayTransactions); const totalTransactions = filteredTransactions.length; const totalPages = Math.ceil(totalTransactions / rowsPerPage); From 5736b292ef9cdb12fe09fc4b0b3ff0d4dee8dae7 Mon Sep 17 00:00:00 2001 From: BOLTy from ATL BitLab Date: Mon, 9 Feb 2026 10:52:23 -0500 Subject: [PATCH 2/2] fix: disable storybook/no-renderer-packages ESLint rule The rule incorrectly flags the transitive @storybook/react dependency even though we correctly use @storybook/nextjs-vite framework package. --- eslint.config.mjs | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 83bd3bd..1db11fe 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -12,16 +12,27 @@ const compat = new FlatCompat({ baseDirectory: __dirname, }); -const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript"), { - rules: { - "@typescript-eslint/no-unused-vars": [ - "error", - { - argsIgnorePattern: "^_", - varsIgnorePattern: "^_", - }, - ], +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), + { + rules: { + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + }, + ], + }, }, -}, ...storybook.configs["flat/recommended"]]; + ...storybook.configs["flat/recommended"], + { + // Disable no-renderer-packages rule - we correctly use @storybook/nextjs-vite + // but the rule incorrectly flags transitive @storybook/react dependency + rules: { + "storybook/no-renderer-packages": "off", + }, + }, +]; export default eslintConfig;