docs: comprehensive learning materials
- Prerequisites (Node.js, Expo, VS Code) - Detailed folder structure explanation - Materi per commit dengan code snippets - Cara menggunakan untuk pembelajaran - Cara run aplikasi (Android, iOS, Web, Smartphone) - Debugging tips - Complete commit list
This commit is contained in:
parent
fafc765b3f
commit
0e35047375
@ -2,46 +2,556 @@
|
||||
|
||||
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:
|
||||
|
||||
1. **Node.js** (versi 18 atau terbaru)
|
||||
- Download: https://nodejs.org
|
||||
- Cek: `node --version`
|
||||
|
||||
2. **Expo CLI**
|
||||
```bash
|
||||
npm install -g expo-cli
|
||||
```
|
||||
|
||||
3. **Code Editor** (VS Code direkomendasikan)
|
||||
- Download: https://code.visualstudio.com
|
||||
|
||||
4. **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: Project Setup
|
||||
1. **Setup Project** - Install dependencies, types
|
||||
2. **Theme Constants** - COLORS, FONTS
|
||||
3. **Helper Functions** - formatRupiah, calculateBalance
|
||||
### Fase 1: Setup & Types (Commit 1-3)
|
||||
|
||||
### Fase 2: Components
|
||||
4. **Header** - Komponen title
|
||||
5. **BalanceCard** - Tampilan saldo
|
||||
6. **TransactionForm** - Form input transaksi
|
||||
7. **TransactionList** - List riwayat
|
||||
#### Commit 1: Setup Project
|
||||
**Topik:** Install dependencies, TypeScript interfaces
|
||||
|
||||
### Fase 3: State Management
|
||||
8. **useTransactions Hook** - Load data
|
||||
9. **addTransaction** - Tambah transaksi
|
||||
10. **deleteTransaction** - Hapus transaksi
|
||||
**Materi yang dipelajari:**
|
||||
- Cara install package dengan npm
|
||||
- TypeScript interface untuk mendefinisikan bentuk data
|
||||
- Export/import module
|
||||
|
||||
### Fase 4: Screen Integration
|
||||
11. **HomeScreen** - Gabung komponen
|
||||
12. **App Index** - Entry point
|
||||
13. **Tab Navigation** - Tab navigation
|
||||
14. **Explore/Stats** - Halaman statistik
|
||||
15. **Root Layout** - Layout utama
|
||||
|
||||
## Cara Menggunakan
|
||||
|
||||
1. Clone repository
|
||||
2. Ikuti commit satu per satu:
|
||||
```bash
|
||||
git log --oneline # Lihat semua commits
|
||||
git checkout <commit-hash> # Pindah ke commit tertentu
|
||||
**Code penting:**
|
||||
```typescript
|
||||
// types/index.ts
|
||||
export interface Transaction {
|
||||
id: string;
|
||||
amount: number;
|
||||
description: string;
|
||||
type: 'income' | 'expense';
|
||||
category: string;
|
||||
date: string;
|
||||
}
|
||||
```
|
||||
3. Run `npm install` dan `npx expo start`
|
||||
|
||||
**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:**
|
||||
```typescript
|
||||
// constants/theme.ts
|
||||
export const COLORS = {
|
||||
income: '#4CAF50',
|
||||
expense: '#F44336',
|
||||
background: '#F5F5F5',
|
||||
card: '#FFFFFF',
|
||||
text: '#333333',
|
||||
primary: '#2196F3',
|
||||
} as const;
|
||||
```
|
||||
|
||||
**Poin pembelajaran:**
|
||||
- `as const` membuat 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:**
|
||||
```typescript
|
||||
// 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.NumberFormat` untuk mata uang Indonesia
|
||||
- `reduce` untuk menjumlahkan array
|
||||
- `filter` untuk 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:**
|
||||
```typescript
|
||||
// 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.FC` adalah 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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
// 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:**
|
||||
- `useState` menyimpan state komponen
|
||||
- `onChangeText` menangkap input teks
|
||||
- `keyboardType="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:**
|
||||
```typescript
|
||||
// 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
|
||||
- `keyExtractor` untuk key unik
|
||||
- `renderItem` menerima 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:**
|
||||
```typescript
|
||||
// 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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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:**
|
||||
- `filter` mengembalikan 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:**
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
1. **Clone repository:**
|
||||
```bash
|
||||
git clone <repo-url>
|
||||
cd duit
|
||||
```
|
||||
|
||||
2. **Lihat semua commits:**
|
||||
```bash
|
||||
git log --oneline
|
||||
```
|
||||
|
||||
3. **Pergi ke commit tertentu:**
|
||||
```bash
|
||||
git checkout <commit-hash>
|
||||
```
|
||||
|
||||
4. **Install dan run:**
|
||||
```bash
|
||||
npm install
|
||||
npx expo start
|
||||
```
|
||||
|
||||
### Cara 2: Belajar dari Kode
|
||||
|
||||
1. Clone repository di commit terakhir
|
||||
2. Baca kode di setiap file
|
||||
3. Pahami hubungan antar komponen
|
||||
4. Modifikasi untuk latihan
|
||||
|
||||
### Cara 3: Latihan Pengembangan
|
||||
|
||||
1. 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
|
||||
```bash
|
||||
npx expo start --android
|
||||
```
|
||||
|
||||
### Di Emulator iOS (Mac only)
|
||||
```bash
|
||||
npx expo start --ios
|
||||
```
|
||||
|
||||
### Di Browser (Web)
|
||||
```bash
|
||||
npx expo start --web
|
||||
```
|
||||
|
||||
### Di Smartphone
|
||||
1. Install "Expo Go" dari App Store/Play Store
|
||||
2. Scan QR code dari terminal
|
||||
|
||||
---
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
1. **React Native Debugger**
|
||||
- iOS: `Cmd + D`
|
||||
- Android: `Cmd + M` atau `Ctrl + M`
|
||||
- Enable "Debug JS Remotely"
|
||||
|
||||
2. **Console.log**
|
||||
```typescript
|
||||
console.log('Data:', transactions);
|
||||
```
|
||||
|
||||
3. **Error Boundary**
|
||||
- Perhatikan error merah di emulator
|
||||
- Check terminal untuk stack trace
|
||||
|
||||
---
|
||||
|
||||
## Fitur Aplikasi
|
||||
- Tambah income/pengeluaran
|
||||
- Lihat saldo total
|
||||
- Riwayat transaksi
|
||||
- Hapus transaksi
|
||||
- Simpan data lokal
|
||||
- Statistik bulanan
|
||||
- Kategori pengeluaran
|
||||
|
||||
- ✅ 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
|
||||
|
||||
- [React Native Docs](https://reactnative.dev/docs/getting-started)
|
||||
- [Expo Docs](https://docs.expo.dev)
|
||||
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
|
||||
|
||||
---
|
||||
|
||||
**Happy Learning! 🚀**
|
||||
Loading…
Reference in New Issue
Block a user