From 342e81cb7f0050c75ed1a77ba69d1eafb33e3f15 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Sun, 11 Jan 2026 11:09:45 +0800 Subject: [PATCH 1/2] feat: add last update timestamp --- .claude/agents/code-reviewer.md | 120 ++++++++++++++++++ .../skills/data-and-state-management/SKILL.md | 2 +- .claude/skills/feature-structure/SKILL.md | 2 +- .claude/skills/transaction-hooks/SKILL.md | 2 +- .claude/skills/ui-components/SKILL.md | 2 +- .../table/markets-table-actions.tsx | 10 +- .../components/table/markets-table.tsx | 3 +- 7 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 .claude/agents/code-reviewer.md diff --git a/.claude/agents/code-reviewer.md b/.claude/agents/code-reviewer.md new file mode 100644 index 00000000..141dc865 --- /dev/null +++ b/.claude/agents/code-reviewer.md @@ -0,0 +1,120 @@ +--- +name: code-reviewer +description: Used PROACTIVELY after writing or modifying any code. Reviews against project standards, TypeScript strict mode, and coding conventions. Checks for anti-patterns, security issues, and performance problems. +model: opus +--- + +Senior code reviewer ensuring high standards for the codebase. + +## Core Setup + +**When invoked**: Run `git diff` to see recent changes, focus on modified files, begin review immediately. + +**Feedback Format**: Organize by priority with specific line references and fix examples. +- **Critical**: Must fix (security, breaking changes, logic errors) +- **Warning**: Should fix (conventions, performance, duplication) +- **Suggestion**: Consider improving (naming, optimization, docs) + +## Review Checklist + +### Logic & Flow +- Logical consistency and correct control flow +- Dead code detection, side effects intentional +- Race conditions in async operations +- Inappropriate lifecycle management that could cause infinite loops + +### TypeScript & Code Style +- **Always define types explicitly** - no `any`, `unknown` without handling +- **Prefer `interface`** over `type` (except unions/intersections) +- **No type assertions** (`as Type`) without justification +- Proper naming (PascalCase components, camelCase functions, `is`/`has` booleans) + +### Immutability & Pure Functions +- **No data mutation** - use spread operators, immutable updates +- **No nested if/else** - use early returns, max 2 nesting levels. Use guard clauses. +- Small focused functions, composition over inheritance + +### Loading & Empty States (Critical) +- **Loading ONLY when no data** - `if (loading && !data)` not just `if (loading)` +- **Every list MUST have empty state** - `ListEmptyComponent` required +- **Error state ALWAYS first** - check error before loading +- **State order**: Error → Loading (no data) → Empty → Success + +```typescript +// CORRECT - Proper state handling order +if (error) return ; +if (loading && !data) return ; +if (!data?.items.length) return ; +return ; +``` + +### Error Handling +- **NEVER silent errors** - always show user feedback +- **Mutations need onError** - with toast AND logging +- Include context: operation names, resource IDs + +### Mutation UI Requirements (Critical) +- **Button must be `isDisabled` during mutation** - prevent double-clicks +- **Button must show `isLoading` state** - visual feedback +- **onError must show toast** - user knows it failed +- **onCompleted success toast** - optional, use for important actions + +```typescript +// CORRECT - Complete mutation pattern +const [submit, { loading }] = useSubmitMutation({ + onError: (error) => { + console.error('submit failed:', error); + toast.error({ title: 'Save failed' }); + }, +}); + + +``` + +### Security & Performance +- Input validation at boundaries +- Error boundaries for components +- Use bigint for asset and balance calculations + +## Code Patterns + +```typescript +// Mutation +items.push(newItem); // Bad +[...items, newItem]; // Good + +// Conditionals +if (user) { if (user.isActive) { ... } } // Bad +if (!user || !user.isActive) return; // Good + +// Loading states +if (loading) return ; // Bad - flashes on refetch +if (loading && !data) return ; // Good - only when no data + +// Button during mutation + // Bad - can double-click + // Good + +// Empty states + // Bad - no empty state +} /> // Good +``` + +## Review Process + +1. **Run checks**: `pnpm run lint` for automated issues +2. **Analyze diff**: `git diff` for all changes +3. **Logic review**: Read line by line, trace execution paths +4. **Apply checklist**: TypeScript, React, testing, security +5. **Common sense filter**: Flag anything that doesn't make intuitive sense + +## Integration with Other Skills + +- **ui-components**: UI patterns +- **data-and-state-management**: For how data, hooks, and components should be structured diff --git a/.claude/skills/data-and-state-management/SKILL.md b/.claude/skills/data-and-state-management/SKILL.md index f40b662d..08e54634 100644 --- a/.claude/skills/data-and-state-management/SKILL.md +++ b/.claude/skills/data-and-state-management/SKILL.md @@ -1,6 +1,6 @@ --- name: data-and-state-management -description: Core patterns for data fetching, state management, and user preferences. Use when implementing new features that require getting data from APIs or managing shared state. +description: Core patterns for data fetching, state management, and user preferences. Use when implementing new features that require getting data from Our APIs, Morpho API, on-chain states or managing shared state. --- diff --git a/.claude/skills/feature-structure/SKILL.md b/.claude/skills/feature-structure/SKILL.md index f27f615a..71836688 100644 --- a/.claude/skills/feature-structure/SKILL.md +++ b/.claude/skills/feature-structure/SKILL.md @@ -1,6 +1,6 @@ --- name: feature-structure -description: Architecture patterns for organizing feature modules in the codebase. Use when creating new features to ensure consistent structure and maintainability. +description: Architecture patterns for organizing feature modules in the codebase. Use when creating new files, brand new features or pages. --- diff --git a/.claude/skills/transaction-hooks/SKILL.md b/.claude/skills/transaction-hooks/SKILL.md index 2d943a4d..e73e9e97 100644 --- a/.claude/skills/transaction-hooks/SKILL.md +++ b/.claude/skills/transaction-hooks/SKILL.md @@ -1,6 +1,6 @@ --- name: transaction-hooks -description: Core patterns to follow for implementing transaction hooks with transaction tracking. Use when implementing new features interacting with EVM contracts. +description: Patterns to follow for implementing transaction hooks with tracking. Use when implementing new features interacting with EVM contracts, signing transactions, permit... etc. --- diff --git a/.claude/skills/ui-components/SKILL.md b/.claude/skills/ui-components/SKILL.md index 3cc650ba..bafccfb6 100644 --- a/.claude/skills/ui-components/SKILL.md +++ b/.claude/skills/ui-components/SKILL.md @@ -1,6 +1,6 @@ --- name: ui-components -description: Core component library and design system patterns. Use when building UI, using design tokens, or working with the component library. +description: Core component library and design system patterns. Use when building UI, building new components, new page, using design tokens, or working with the component library. --- # Core Components diff --git a/src/features/markets/components/table/markets-table-actions.tsx b/src/features/markets/components/table/markets-table-actions.tsx index 43bb3c4c..d5c270a8 100644 --- a/src/features/markets/components/table/markets-table-actions.tsx +++ b/src/features/markets/components/table/markets-table-actions.tsx @@ -1,5 +1,6 @@ 'use client'; +import moment from 'moment'; import { RefetchIcon } from '@/components/ui/refetch-icon'; import { CgDisplayFullwidth } from 'react-icons/cg'; import { FiSettings } from 'react-icons/fi'; @@ -15,15 +16,22 @@ type MarketsTableActionsProps = { onRefresh: () => void; isRefetching: boolean; isMobile: boolean; + dataUpdatedAt?: number; }; -export function MarketsTableActions({ onRefresh, isRefetching, isMobile }: MarketsTableActionsProps) { +export function MarketsTableActions({ onRefresh, isRefetching, isMobile, dataUpdatedAt }: MarketsTableActionsProps) { const { open: openModal } = useModal(); const { tableViewMode, setTableViewMode } = useMarketPreferences(); const effectiveTableViewMode = isMobile ? 'compact' : tableViewMode; return ( <> + {dataUpdatedAt && ( + + {moment(dataUpdatedAt).format('h:mm: A')} ({moment(dataUpdatedAt).fromNow()}) + + )} + openModal('marketSettings', {})} /> } className="w-full" From 1d2c96cbdffa5a10343209a2c24110f41461eb09 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Sun, 11 Jan 2026 11:13:54 +0800 Subject: [PATCH 2/2] chore: simplify --- .../components/table/markets-table-actions.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/features/markets/components/table/markets-table-actions.tsx b/src/features/markets/components/table/markets-table-actions.tsx index d5c270a8..4ac06acc 100644 --- a/src/features/markets/components/table/markets-table-actions.tsx +++ b/src/features/markets/components/table/markets-table-actions.tsx @@ -16,7 +16,7 @@ type MarketsTableActionsProps = { onRefresh: () => void; isRefetching: boolean; isMobile: boolean; - dataUpdatedAt?: number; + dataUpdatedAt: number; }; export function MarketsTableActions({ onRefresh, isRefetching, isMobile, dataUpdatedAt }: MarketsTableActionsProps) { @@ -26,10 +26,17 @@ export function MarketsTableActions({ onRefresh, isRefetching, isMobile, dataUpd return ( <> - {dataUpdatedAt && ( - - {moment(dataUpdatedAt).format('h:mm: A')} ({moment(dataUpdatedAt).fromNow()}) - + {dataUpdatedAt !== 0 && ( + + } + > + {moment(dataUpdatedAt).format('h:mm:ss A')} + )} openModal('marketSettings', {})} />