A filterable, sortable table application built with Next.js, TypeScript, and Tailwind CSS for exploring meal and training plans.
- Data Display: Interactive table showing items with ID, type, title, calories, and tags
- Search: Real-time text search across title, tags, and calories
- Type Filter: Filter by item type (All, Meals, Training)
- Sorting: Click column headers to sort ascending/descending
- Detail View: Hover cards showing detailed item information
- Responsive: Mobile-friendly design with adaptive layouts
βββ app/ # Next.js App Router
β βββ layout.tsx # Root layout with metadata
β βββ page.tsx # Main page component
βββ components/ # React components
β βββ ui/ # Reusable UI primitives (shadcn/ui)
β βββ card-table.tsx # Main container component
β βββ item-table.tsx # Core table with state management
β βββ search-input.tsx # Search functionality
β βββ type-filter.tsx # Type filtering buttons
β βββ sort-button.tsx # Sortable column headers
β βββ reusable-hover-card.tsx # Item detail display
βββ lib/
β βββ actions.tsx # Pure utility functions
β βββ data/
β βββ data.ts # Data loading and types
β βββ intern-case-2.json # Source data
βββ tests/
βββ tests.ts # Unit tests for utilities
- Separation of Concerns: Pure functions in
lib/actions.tsxseparate business logic from UI - Single Responsibility: Each component has one clear purpose
- Composition over Inheritance: Small, reusable components that compose together
- Props Interface: Clear TypeScript interfaces for all component props
- Local State: Using React useState for table state (sorting, filtering)
- Prop Drilling: Simple prop passing for this scale (alternative: Context API for larger apps)
- Immutable Updates: All state updates create new arrays/objects
JSON Data β data.ts β ItemTable β [SearchInput, TypeFilter] β Pure Functions β Updated State
- β App Router: Modern file-based routing
- β Server Components: Better performance for static content
- β TypeScript: Full type safety
- β Utility-first: Rapid development and consistent design
- β Component Library: Pre-built, accessible components
- β Responsive: Mobile-first design approach
- β Simple: No external state management needed
- β Performance: Local state prevents unnecessary re-renders
- β Scale Limitation: Would need Context/Redux for complex apps
- Choice: Client-side filtering and sorting
- Pro: Instant feedback, no network requests
- Con: Limited to small datasets (current: 4 items)
- Alternative: Server-side with pagination for large datasets
- Choice: Highly granular components (SearchInput, TypeFilter, SortButton)
- Pro: Reusable, testable, maintainable
- Con: More files and prop drilling
- Alternative: Monolithic components (faster initial development)
- Choice: Single responsive table (scale-based)
- Pro: Consistent experience across devices
- Con: May be cramped on very small screens
- Alternative: Card layout on mobile (implemented as hover cards)
- Choice: Unit tests for pure functions only
- Pro: Tests critical business logic
- Con: No integration/E2E tests
- Alternative: Full testing pyramid with React Testing Library
This project was developed with assistance from GitHub Copilot for:
- Generating tests for utility functions
- Fixing minor bugs and typos
- Style suggestions and code snippets
- Writing readme sections
const [isLoading, setIsLoading] = useState(false);
// Use TableSkeleton component during loadinguseHotkeys("ctrl+f", () => searchInputRef.current?.focus());
useHotkeys("escape", () => clearFilters());// Already implemented for pure functions
// Extend to: validation, edge cases, error handling# Install dependencies
bun install
# Run development server
bun run dev
# Run tests
bun run test
# Build for production
bun run builddev: Start development serverbuild: Build for productionstart: Start production serverlint: Run Biomeformat: Format code with Biometest: Run unit tests
- Framework: Next.js 15
- Language: TypeScript
- Styling: Tailwind CSS + shadcn/ui
- Runtime: Bun
- Testing: Node.js built-in test runner