- Add warning about commit order - Explain dependencies between commits - Mention which commits need prerequisite commits
13 KiB
Finance Tracker - Materi Pembelajaran React Native
Project ini adalah aplikasi penghitung income dan expense keuangan untuk pembelajaran React Native. Setiap commit merepresentasikan satu tahap pembelajaran yang dapat diikuti oleh murid dan pengajar.
Prerequisites
Sebelum memulai, pastikan komputer Anda sudah terinstall:
-
Node.js (versi 18 atau terbaru)
- Download: https://nodejs.org
- Cek:
node --version
-
Expo CLI
npm install -g expo-cli -
Code Editor (VS Code direkomendasikan)
- Download: https://code.visualstudio.com
-
Untuk Running di Android:
- Android Studio (dengan SDK)
- Atau gunakan Expo Go di smartphone
Struktur Folder Project
duit/
├── app/ # File routing (expo-router)
│ ├── _layout.tsx # Root layout
│ └── (tabs)/ # Tab navigation
│ ├── _layout.tsx # Tab config
│ ├── index.tsx # Home screen
│ └── explore.tsx # Stats screen
├── components/ # Komponen React Native
│ ├── Header.tsx # Header component
│ ├── BalanceCard.tsx # Balance display
│ ├── TransactionForm.tsx # Input form
│ └── TransactionList.tsx # Transaction list
├── hooks/ # Custom hooks
│ └── useTransactions.ts # Data management hook
├── types/ # TypeScript types
│ └── index.ts # Transaction interface
├── utils/ # Utility functions
│ └── helpers.ts # Helper functions
├── constants/ # Konstanta
│ └── theme.ts # Colors & fonts
├── package.json
└── LEARNING_MATERIALS.md
Daftar Commit Pembelajaran
Fase 1: Setup & Types (Commit 1-3)
Commit 1: Setup Project
Topik: Install dependencies, TypeScript interfaces
Materi yang dipelajari:
- Cara install package dengan npm
- TypeScript interface untuk mendefinisikan bentuk data
- Export/import module
Code penting:
// types/index.ts
export interface Transaction {
id: string;
amount: number;
description: string;
type: 'income' | 'expense';
category: string;
date: string;
}
Poin pembelajaran:
- Interface adalah "blueprint" untuk object
- Tipe data yang tersedia: string, number, boolean
Commit 2: Theme Constants
Topik: Konstanta warna dan font
Materi yang dipelajari:
- Mendefinisikan konstanta di React Native
- Konfigurasi tema aplikasi
Code penting:
// constants/theme.ts
export const COLORS = {
income: '#4CAF50',
expense: '#F44336',
background: '#F5F5F5',
card: '#FFFFFF',
text: '#333333',
primary: '#2196F3',
} as const;
Poin pembelajaran:
as constmembuat object jadi readonly- Gunakan konsistensi warna di seluruh app
Commit 3: Helper Functions
Topik: Fungsi utility
Materi yang dipelajari:
- Membuat fungsi helper yang reusable
- Formatting angka dan tanggal
- Array reduce untuk kalkulasi
Code penting:
// utils/helpers.ts
export const formatRupiah = (amount: number): string => {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
}).format(amount);
};
export const calculateBalance = (transactions: Transaction[]): BalanceInfo => {
const income = transactions
.filter((t) => t.type === 'income')
.reduce((sum, t) => sum + t.amount, 0);
// ...
};
Poin pembelajaran:
Intl.NumberFormatuntuk mata uang Indonesiareduceuntuk menjumlahkan arrayfilteruntuk menyaring array
Fase 2: Components (Commit 4-7)
Commit 4: Header Component
Topik: Komponen Pertama
Materi yang dipelajari:
- Cara membuat komponen React Native
- View, Text, StyleSheet
- Interface props
Code penting:
// components/Header.tsx
interface HeaderProps {
title: string;
}
export const Header: React.FC<HeaderProps> = ({ title }) => {
return (
<View style={styles.container}>
<Text style={styles.title}>{title}</Text>
</View>
);
};
Poin pembelajaran:
- Komponen adalah fungsi yang return JSX
- Props digunakan untuk data dinamis
React.FCadalah type untuk functional component
Commit 5: BalanceCard Component
Topik: Props dan conditional styling
Materi yang dipelajari:
- Menerima object sebagai props
- Conditional styling (warna berbeda untuk income/expense)
Code penting:
interface BalanceCardProps {
balance: BalanceInfo;
}
export const BalanceCard: React.FC<BalanceCardProps> = ({ balance }) => {
return (
<View>
<Text style={[styles.amount, styles.income]}>
+{formatRupiah(balance.income)}
</Text>
</View>
);
};
Poin pembelajaran:
- Destructure props dengan
{ balance } - Conditional class dengan array
[styles.base, isActive && styles.active]
Commit 6: TransactionForm Component
Topik: Form input dengan useState
Materi yang dipelajari:
- useState untuk form inputs
- TextInput component
- TouchableOpacity untuk button
- ScrollView horizontal
Code penting:
// components/TransactionForm.tsx
const [amount, setAmount] = useState('');
const [description, setDescription] = useState('');
const [type, setType] = useState<'income' | 'expense'>('expense');
<TextInput
style={styles.input}
placeholder="Jumlah (Rp)"
value={amount}
onChangeText={setAmount}
keyboardType="numeric"
/>
<TouchableOpacity onPress={() => setType('expense')}>
<Text>Pengeluaran</Text>
</TouchableOpacity>
Poin pembelajaran:
useStatemenyimpan state komponenonChangeTextmenangkap input tekskeyboardType="numeric"untuk number only- TouchableOpacity = button yang bisa ditekan
Commit 7: TransactionList Component
Topik: FlatList dan rendering
Materi yang dipelajari:
- FlatList untuk list panjang
- renderItem function
- Empty state handling
Code penting:
// components/TransactionList.tsx
<FlatList
data={transactions}
keyExtractor={(item) => item.id}
renderItem={renderItem}
scrollEnabled={false}
/>
if (transactions.length === 0) {
return <View style={styles.empty}>...</View>;
}
Poin pembelajaran:
- FlatList lebih efficient dari map
keyExtractoruntuk key unikrenderItemmenerima object{ item }
Fase 3: State Management (Commit 8-10)
Commit 8: useTransactions Hook
Topik: Custom hooks
Materi yang dipelajari:
- Membuat custom hook
- useState dan useEffect
- Load data dari AsyncStorage
Code penting:
// hooks/useTransactions.ts
export const useTransactions = () => {
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [loading, setLoading] = useState(true);
const loadTransactions = async () => {
const stored = await AsyncStorage.getItem(STORAGE_KEY);
if (stored) setTransactions(JSON.parse(stored));
};
useEffect(() => {
loadTransactions();
}, []);
return { transactions, loading };
};
Poin pembelajaran:
- Hook adalah fungsi dengan "use" prefix
- useEffect untuk side effects (API calls)
- AsyncStorage untuk persistence lokal
Commit 9: addTransaction
Topik: State update dengan callback
Materi yang dipelajari:
- Menambah item ke state
- Callback function
- useCallback untuk optimisasi
Code penting:
const addTransaction = useCallback((transaction: Transaction) => {
setTransactions((prev) => {
const updated = [transaction, ...prev];
AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
return updated;
});
}, []);
Poin pembelajaran:
- Gunakan functional update
setTransactions(prev => ...) - Selalu simpan ke storage setelah update
Commit 10: deleteTransaction
Topik: Hapus item dari state
Materi yang dipelajari:
- Filter untuk hapus item
- Update berdasarkan id
Code penting:
const deleteTransaction = useCallback((id: string) => {
setTransactions((prev) => {
const updated = prev.filter((t) => t.id !== id);
AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
return updated;
});
}, []);
Poin pembelajaran:
filtermengembalikan array baru (tidak mutate)- Compare dengan
!==untuk hapus berdasarkan id
Fase 4: Screen Integration (Commit 11-15)
Commit 11: HomeScreen
Topik: Menggabungkan komponen
Materi yang dipelajari:
- Import dan gunakan komponen
- Loading state
- ScrollView
Code penting:
// screens/HomeScreen.tsx
export default function HomeScreen() {
const { transactions, loading, addTransaction, deleteTransaction } = useTransactions();
const balance = calculateBalance(transactions);
if (loading) {
return <ActivityIndicator />;
}
return (
<View>
<Header title="Pengeluaran Kita" />
<ScrollView>
<BalanceCard balance={balance} />
<TransactionForm onAdd={addTransaction} />
<TransactionList transactions={transactions} onDelete={deleteTransaction} />
</ScrollView>
</View>
);
}
Poin pembelajaran:
- Custom hook return multiple values dengan destructuring
- ActivityIndicator untuk loading state
- ScrollView untuk konten panjang
Commit 12-15: App Integration
Topik: Expo Router & Navigation
Materi yang dipelajari:
- File-based routing dengan expo-router
- Tab navigation
- Layout configuration
Fase 5: Enhancements (Commit 16-21)
Topics tambahan:
- Categories management
- Form validation
- Code refactoring
Cara Menggunakan untuk Pembelajaran
Cara 1: Ikuti Commit Satu per Satu
-
Clone repository:
git clone <repo-url> cd duit -
Lihat semua commits:
git log --oneline -
Pergi ke commit tertentu:
git checkout <commit-hash> -
Install dan run:
npm install npx expo start
⚠️ PENTING: Urutan Commit yang harus Diperhatikan
Beberapa commit memiliki dependensi. Berikut urutannya:
| Jika ingin belajar | Pastikan sudah checkout ke commit |
|---|---|
| Commit 4-7 (Components) | Setelah commit 3 |
| Commit 11+ (HomeScreen) | Setelah commit 10 (useTransactions) |
| Commit 14 (Stats Screen) | Setelah commit 10 (useTransactions) |
| Commit 18+ (Categories) | Setelah commit 17 |
Jangan langsung checkout ke commit tinggi tanpa mengikuti urutan, karena akan terjadi error (beberapa komponen/hooks belum tersedia).
Cara 2: Belajar dari Kode
- Clone repository di commit terakhir
- Baca kode di setiap file
- Pahami hubungan antar komponen
- Modifikasi untuk latihan
Cara 3: Latihan Pengembangan
- Di commit terakhir, tambahkan fitur:
- Filter transaksi per kategori
- Edit transaksi yang sudah ada
- Export data ke CSV
- Dark mode
Cara Run Aplikasi
Di Emulator Android
npx expo start --android
Di Emulator iOS (Mac only)
npx expo start --ios
Di Browser (Web)
npx expo start --web
Di Smartphone
- Install "Expo Go" dari App Store/Play Store
- Scan QR code dari terminal
Debugging Tips
-
React Native Debugger
- iOS:
Cmd + D - Android:
Cmd + MatauCtrl + M - Enable "Debug JS Remotely"
- iOS:
-
Console.log
console.log('Data:', transactions); -
Error Boundary
- Perhatikan error merah di emulator
- Check terminal untuk stack trace
Fitur Aplikasi
- ✅ Tambah income/pengeluaran
- ✅ Lihat saldo total
- ✅ Riwayat transaksi
- ✅ Hapus transaksi
- ✅ Kategori transaksi
- ✅ Simpan data lokal (AsyncStorage)
- ✅ Tab navigation (Keuangan & Statistik)
- ✅ Ringkasan bulanan
- ✅ Kategori pengeluaran terbesar
Daftar Commit Lengkap
| # | Commit Hash | Deskripsi |
|---|---|---|
| 1 | feat: setup project and add types | Install AsyncStorage, Transaction interface |
| 2 | feat: add theme constants | COLORS, FONTS |
| 3 | feat: add helper utility functions | formatRupiah, calculateBalance |
| 4 | feat: create Header component | Komponen title |
| 5 | feat: create BalanceCard component | Tampilan saldo |
| 6 | feat: create TransactionForm component | Form input |
| 7 | feat: create TransactionList component | List riwayat |
| 8 | feat: create useTransactions hook | Load data |
| 9 | feat: add addTransaction function | Tambah transaksi |
| 10 | feat: add deleteTransaction function | Hapus transaksi |
| 11 | feat: create HomeScreen | Gabung komponen |
| 12 | feat: update index to use HomeScreen | Entry point |
| 13 | feat: configure tab navigation | Tab config |
| 14 | feat: create Explore/StatsScreen | Statistik |
| 15 | feat: simplify root layout | Layout utama |
| 16 | docs: add learning materials | Dokumentasi |
| 17 | feat: add CATEGORIES constant | Categories array |
| 18 | refactor: use CATEGORIES from types | Import categories |
| 19 | refactor: add getCategoryLabel helper | Helper function |
| 20 | feat: add form validation | Alert, validation |
Referensi
Happy Learning! 🚀