duit/components/TransactionForm.tsx

219 lines
5.2 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
StyleSheet,
ScrollView,
} from 'react-native';
import { COLORS, FONTS } from '../constants/theme';
import { Transaction, CATEGORIES } from '../types';
import { generateId, getCurrentDate } from '../utils/helpers';
interface TransactionFormProps {
onAdd: (transaction: Transaction) => void;
}
export const TransactionForm: React.FC<TransactionFormProps> = ({ onAdd }) => {
const [amount, setAmount] = useState('');
const [description, setDescription] = useState('');
const [type, setType] = useState<'income' | 'expense'>('expense');
const [category, setCategory] = useState('lainnya');
const handleSubmit = () => {
if (!amount || !description) return;
const transaction: Transaction = {
id: generateId(),
amount: parseInt(amount, 10),
description,
type,
category,
date: getCurrentDate(),
};
onAdd(transaction);
setAmount('');
setDescription('');
};
return (
<View style={styles.container}>
<Text style={styles.title}>Tambah Transaksi</Text>
<View style={styles.typeContainer}>
<TouchableOpacity
style={[
styles.typeButton,
type === 'expense' && styles.typeButtonActiveExpense,
]}
onPress={() => setType('expense')}
>
<Text
style={[
styles.typeText,
type === 'expense' && styles.typeTextActive,
]}
>
Pengeluaran
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.typeButton,
type === 'income' && styles.typeButtonActiveIncome,
]}
onPress={() => setType('income')}
>
<Text
style={[
styles.typeText,
type === 'income' && styles.typeTextActive,
]}
>
Pemasukan
</Text>
</TouchableOpacity>
</View>
<TextInput
style={styles.input}
placeholder="Jumlah (Rp)"
value={amount}
onChangeText={setAmount}
keyboardType="numeric"
placeholderTextColor={COLORS.textSecondary}
/>
<TextInput
style={styles.input}
placeholder="Deskripsi"
value={description}
onChangeText={setDescription}
placeholderTextColor={COLORS.textSecondary}
/>
<Text style={styles.categoryLabel}>Kategori</Text>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View style={styles.categoryContainer}>
{CATEGORIES.map((cat) => (
<TouchableOpacity
key={cat.id}
style={[
styles.categoryButton,
category === cat.id && styles.categoryButtonActive,
]}
onPress={() => setCategory(cat.id)}
>
<Text
style={[
styles.categoryText,
category === cat.id && styles.categoryTextActive,
]}
>
{cat.label}
</Text>
</TouchableOpacity>
))}
</View>
</ScrollView>
<TouchableOpacity style={styles.submitButton} onPress={handleSubmit}>
<Text style={styles.submitText}>Simpan</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: COLORS.card,
margin: 16,
marginTop: 0,
padding: 16,
borderRadius: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
title: {
fontSize: FONTS.regular,
fontWeight: 'bold',
color: COLORS.text,
marginBottom: 16,
},
typeContainer: {
flexDirection: 'row',
marginBottom: 16,
gap: 8,
},
typeButton: {
flex: 1,
padding: 12,
borderRadius: 8,
alignItems: 'center',
backgroundColor: COLORS.background,
},
typeButtonActiveExpense: {
backgroundColor: COLORS.expense,
},
typeButtonActiveIncome: {
backgroundColor: COLORS.income,
},
typeText: {
fontSize: FONTS.regular,
color: COLORS.textSecondary,
},
typeTextActive: {
color: COLORS.card,
fontWeight: '600',
},
input: {
backgroundColor: COLORS.background,
borderRadius: 8,
padding: 12,
marginBottom: 12,
fontSize: FONTS.regular,
color: COLORS.text,
},
categoryLabel: {
fontSize: FONTS.small,
color: COLORS.textSecondary,
marginBottom: 8,
},
categoryContainer: {
flexDirection: 'row',
gap: 8,
marginBottom: 16,
},
categoryButton: {
paddingHorizontal: 12,
paddingVertical: 8,
borderRadius: 16,
backgroundColor: COLORS.background,
},
categoryButtonActive: {
backgroundColor: COLORS.primary,
},
categoryText: {
fontSize: FONTS.small,
color: COLORS.textSecondary,
},
categoryTextActive: {
color: COLORS.card,
},
submitButton: {
backgroundColor: COLORS.primary,
padding: 14,
borderRadius: 8,
alignItems: 'center',
},
submitText: {
color: COLORS.card,
fontSize: FONTS.regular,
fontWeight: '600',
},
});