Membangun sistem frontend admin dashboard berbasis React 19 + TypeScript dengan pendekatan feature-based architecture dan HeroUI design system, mengutamakan:
- β¨ Scalability β siap untuk pengembangan jangka panjang
- βοΈ Maintainability β mudah di-maintain oleh tim atau developer baru
- π§ͺ Testability β mudah dilakukan unit test dengan renderWithProviders
- π¦ Dependency Hygiene β versi dan type declaration selalu konsisten
- π¨ Design Consistency β menggunakan HeroUI sebagai design system utama
| Komponen | Teknologi | Status |
|---|---|---|
| Core Framework | React 19.1.0 + Vite | β Aktif |
| UI Components | HeroUI (NextUI fork) 2.x | β Aktif |
| Styling | Tailwind CSS 3.4 + HeroUI Theme | β Aktif |
| Routing | React Router DOM v6.30.1 | β Aktif |
| State Management | React Query (TanStack) + Zustand | β Aktif |
| Form Handling | React Hook Form + Zod | π Planned |
| Type Safety | TypeScript 5.x | β Aktif |
| Testing | Vitest + Testing Library | π Planned |
fe-dashboard/
βββ README.md # Project documentation
βββ package.json # Dependencies and scripts
βββ vite.config.ts # Vite build configuration
βββ tailwind.config.js # Tailwind CSS + HeroUI configuration
βββ tsconfig.json # TypeScript configuration
β
βββ public/ # Static assets
β βββ assets/ # Images, icons
β
βββ src/
βββ App.tsx # Root component with routing
βββ main.tsx # Application entry point
βββ index.css # Global styles + HeroUI imports
β
βββ app/ # App-level configuration
β βββ layout/
β βββ AppLayout.tsx # Main layout wrapper
β
βββ components/ # Shared components
β βββ shared/ # Reusable app components
β βββ PageHeader/ # Page header component
β βββ DataTable/ # Enhanced table component
β
βββ features/ # Feature modules
β βββ auth/ # Authentication
β β βββ ui/ # Auth pages
β β βββ LoginPage.tsx
β β βββ RegisterPage.tsx
β β
β βββ dashboard/ # Dashboard feature
β β βββ ui/
β β βββ DashboardHome.tsx
β β
β βββ example/ # Example components
β β βββ ui/
β β βββ FormPage.tsx
β β βββ TablePage.tsx
β β βββ ChartPage.tsx
β β βββ GetdataPage.tsx
β β
β βββ rup-data/ # π― RUP Data Feature (Pattern Reference)
β βββ RupDataPage.tsx # Main page component
β βββ api.ts # API service
β βββ hooks.ts # Custom hooks
β βββ types.ts # TypeScript interfaces
β
βββ services/ # Global services (future)
βββ hooks/ # Global custom hooks (future)
βββ utils/ # Utility functions (future)
βββ types/ # Global TypeScript types (future)
Folder rup-data menunjukkan pattern yang sedang digunakan dalam proyek ini:
src/features/rup-data/
βββ RupDataPage.tsx # Main page component
βββ api.ts # API service layer
βββ hooks.ts # Custom hooks
βββ types.ts # TypeScript interfaces
import React from 'react';
import { Button, Chip } from '@heroui/react';
import { Download, RefreshCw } from 'lucide-react';
import { PageHeader } from '../../components/shared/PageHeader/PageHeader';
import { DataTable } from '../../components/shared/DataTable/DataTable';
import { useRupData } from './hooks';
export default function RupDataPage() {
const { data, loading, error, refetch } = useRupData();
// Component logic here
return (
<div className="container mx-auto p-6">
<PageHeader title="Data RUP 2025" />
<DataTable data={data} />
</div>
);
}import axios from 'axios';
import type { RupItem } from './types';
const RUP_API_URL = '/rup-api/endpoint/url';
export async function fetchRupData(): Promise<RupItem[]> {
try {
const response = await axios.get<RupItem[]>(RUP_API_URL);
return response.data;
} catch (error) {
throw new Error('Failed to fetch RUP data');
}
}import { useState, useEffect } from 'react';
import { fetchRupData } from './api';
import type { RupItem } from './types';
export function useRupData() {
const [data, setData] = useState<RupItem[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Hook logic here
return { data, loading, error, refetch };
}export interface RupItem {
kd_rup: string;
nama_satker: string;
nama_paket: string;
pagu: number;
metode_pengadaan: string;
jenis_pengadaan: string;
}npm installnpm run devnpm run build- Layout: Card, CardBody, CardHeader, Divider, Spacer
- Navigation: Breadcrumbs, Pagination
- Forms: Input, Select, Button, Checkbox
- Data Display: Table, TableHeader, TableBody, Chip, Badge
- Feedback: Modal, Toast, Skeleton, Spinner
- Icons: Lucide React icons integration
- PageHeader - Header standar untuk semua halaman
- DataTable - Wrapper enhanced untuk HeroUI Table dengan:
- Search functionality
- Pagination
- Loading states
- Error handling
- Custom cell rendering
Routes didefinisikan di src/App.tsx:
function App() {
return (
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
{/* Protected routes inside layout */}
<Route path="/" element={<AppLayout />}>
<Route index element={<DashboardHome />}/>
<Route path="dashboard" element={<DashboardHome />} />
<Route path="form" element={<FormPage />} />
<Route path="table" element={<TablePage />} />
<Route path="rup-data" element={<RupDataPage />} />
</Route>
</Routes>
);
}Ikuti pattern yang ada di folder rup-data:
# 1. Buat folder feature
mkdir src/features/new-feature
# 2. Buat file-file standar
touch src/features/new-feature/NewFeaturePage.tsx
touch src/features/new-feature/api.ts
touch src/features/new-feature/hooks.ts
touch src/features/new-feature/types.ts- Feature folders: kebab-case (
rup-data,user-management) - Page components: PascalCase dengan suffix
Page(RupDataPage.tsx) - API files: camelCase (
api.ts,hooks.ts,types.ts) - Interfaces: PascalCase (
RupItem,UserProfile)
// β
Good: Import HeroUI components
import { Button, Card, Table } from '@heroui/react';
// β
Good: Import shared components
import { PageHeader } from '../../components/shared/PageHeader/PageHeader';
// β
Good: Import from same feature
import { useRupData } from './hooks';
import type { RupItem } from './types';
// β Avoid: Cross-feature imports
import { useUserData } from '../user-management/hooks';// Standard page component structure
export default function FeaturePage() {
// 1. Hooks and state
const { data, loading, error } = useFeatureData();
// 2. Event handlers
const handleAction = () => { /* logic */ };
// 3. Render helpers
const renderCell = (item, key) => { /* rendering */ };
// 4. JSX return
return (
<div className="container mx-auto p-6">
<PageHeader title="Feature Name" />
{/* component content */}
</div>
);
}src/features/rup-data/
βββ RupDataPage.tsx
βββ RupDataPage.test.tsx # Component tests
βββ api.ts
βββ api.test.ts # API tests
βββ hooks.ts
βββ hooks.test.ts # Hook tests
βββ types.ts
// tests/utils/renderWithProviders.tsx
export const renderWithProviders = (ui: React.ReactElement) => {
const Wrapper = ({ children }) => (
<QueryClientProvider client={testQueryClient}>
<HeroUIProvider>
<BrowserRouter>
{children}
</BrowserRouter>
</HeroUIProvider>
</QueryClientProvider>
);
return render(ui, { wrapper: Wrapper });
};// tailwind.config.js
import { heroui } from '@heroui/react';
export default {
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}"
],
plugins: [heroui()],
};// tsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"features/*": ["features/*"],
"components/*": ["components/*"],
"utils/*": ["utils/*"]
}
}
}- Complete migration all example features to HeroUI
- Implement proper error boundary components
- Add form validation with React Hook Form + Zod
- Setup testing environment with Vitest
- Add user authentication system
- Implement global state management with Zustand
- Add internationalization (i18n) support
- Setup CI/CD pipeline
- Add accessibility (a11y) compliance
- Expand feature structure when features become complex
- Add sub-folders (
components/,utils/) within features if needed - Consider context providers for complex features
- Implement proper error handling patterns
- Follow the feature-based architecture pattern shown in
rup-data - Use HeroUI components for all UI elements
- Keep features self-contained and avoid cross-feature dependencies
- Update this README when adding new patterns or conventions
- Follow TypeScript best practices
MIT License - see LICENSE file for details.