226 lines
5.6 KiB
TypeScript
226 lines
5.6 KiB
TypeScript
import React from "react";
|
|
import {
|
|
View,
|
|
Text,
|
|
TouchableOpacity,
|
|
StyleSheet,
|
|
Platform,
|
|
TextInput,
|
|
} from "react-native";
|
|
import { Ionicons } from "@expo/vector-icons";
|
|
import { useI18n } from "@/hooks/use-i18n";
|
|
import { useThemeContext } from "@/hooks/use-theme-context";
|
|
|
|
interface FishingGear {
|
|
id: string;
|
|
name: string;
|
|
number: string;
|
|
}
|
|
|
|
interface FishingGearListProps {
|
|
items: FishingGear[];
|
|
onChange: (items: FishingGear[]) => void;
|
|
}
|
|
|
|
export default function FishingGearList({
|
|
items,
|
|
onChange,
|
|
}: FishingGearListProps) {
|
|
const { t } = useI18n();
|
|
const { colors } = useThemeContext();
|
|
|
|
const handleAddGear = () => {
|
|
const newGear: FishingGear = {
|
|
id: Date.now().toString(),
|
|
name: "",
|
|
number: "",
|
|
};
|
|
onChange([...items, newGear]);
|
|
};
|
|
|
|
const handleRemoveGear = (id: string) => {
|
|
onChange(items.filter((item) => item.id !== id));
|
|
};
|
|
|
|
const handleDuplicateGear = (gear: FishingGear) => {
|
|
const duplicatedGear: FishingGear = {
|
|
id: Date.now().toString(),
|
|
name: gear.name,
|
|
number: gear.number,
|
|
};
|
|
onChange([...items, duplicatedGear]);
|
|
};
|
|
|
|
const handleUpdateGear = (id: string, field: keyof FishingGear, value: string) => {
|
|
onChange(
|
|
items.map((item) =>
|
|
item.id === id ? { ...item, [field]: value } : item
|
|
)
|
|
);
|
|
};
|
|
|
|
const themedStyles = {
|
|
sectionTitle: { color: colors.text },
|
|
fieldLabel: { color: colors.text },
|
|
input: {
|
|
backgroundColor: colors.card,
|
|
borderColor: colors.border,
|
|
color: colors.text,
|
|
},
|
|
addButton: {
|
|
borderColor: colors.primary,
|
|
},
|
|
addButtonText: { color: colors.primary },
|
|
};
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<Text style={[styles.sectionTitle, themedStyles.sectionTitle]}>
|
|
{t("diary.fishingGearList")}
|
|
</Text>
|
|
|
|
{/* Gear Items List */}
|
|
{items.map((gear, index) => (
|
|
<View key={gear.id} style={styles.gearRow}>
|
|
{/* Name Input */}
|
|
<View style={styles.inputGroup}>
|
|
<Text style={[styles.fieldLabel, themedStyles.fieldLabel]}>
|
|
{t("diary.gearName")}
|
|
</Text>
|
|
<TextInput
|
|
style={[styles.input, styles.nameInput, themedStyles.input]}
|
|
value={gear.name}
|
|
onChangeText={(value) => handleUpdateGear(gear.id, "name", value)}
|
|
placeholder={t("diary.gearNamePlaceholder")}
|
|
placeholderTextColor={colors.textSecondary}
|
|
/>
|
|
</View>
|
|
|
|
{/* Number Input */}
|
|
<View style={styles.inputGroup}>
|
|
<Text style={[styles.fieldLabel, themedStyles.fieldLabel]}>
|
|
{t("diary.gearNumber")}
|
|
</Text>
|
|
<TextInput
|
|
style={[styles.input, styles.numberInput, themedStyles.input]}
|
|
value={gear.number}
|
|
onChangeText={(value) => handleUpdateGear(gear.id, "number", value)}
|
|
placeholder={t("diary.gearNumberPlaceholder")}
|
|
placeholderTextColor={colors.textSecondary}
|
|
keyboardType="numeric"
|
|
/>
|
|
</View>
|
|
|
|
{/* Action Buttons */}
|
|
<View style={styles.actionButtons}>
|
|
<TouchableOpacity
|
|
onPress={() => handleDuplicateGear(gear)}
|
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
>
|
|
<Ionicons name="copy-outline" size={20} color={colors.text} />
|
|
</TouchableOpacity>
|
|
<TouchableOpacity
|
|
onPress={() => handleRemoveGear(gear.id)}
|
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
>
|
|
<Ionicons name="trash-outline" size={20} color={colors.error} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
))}
|
|
|
|
{/* Add Button */}
|
|
<TouchableOpacity
|
|
style={[styles.addButton, themedStyles.addButton]}
|
|
onPress={handleAddGear}
|
|
activeOpacity={0.7}
|
|
>
|
|
<Ionicons name="add" size={20} color={colors.primary} />
|
|
<Text style={[styles.addButtonText, themedStyles.addButtonText]}>
|
|
{t("diary.addFishingGear")}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
marginBottom: 20,
|
|
},
|
|
sectionTitle: {
|
|
fontSize: 16,
|
|
fontWeight: "700",
|
|
marginBottom: 16,
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
gearRow: {
|
|
flexDirection: "row",
|
|
alignItems: "flex-end",
|
|
gap: 12,
|
|
marginBottom: 16,
|
|
},
|
|
inputGroup: {
|
|
flex: 1,
|
|
},
|
|
fieldLabel: {
|
|
fontSize: 14,
|
|
fontWeight: "500",
|
|
marginBottom: 6,
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
input: {
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 10,
|
|
fontSize: 15,
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
nameInput: {
|
|
flex: 1,
|
|
},
|
|
numberInput: {
|
|
flex: 1,
|
|
},
|
|
actionButtons: {
|
|
flexDirection: "row",
|
|
gap: 12,
|
|
alignItems: "center",
|
|
paddingBottom: 10,
|
|
},
|
|
addButton: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
gap: 8,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 16,
|
|
borderWidth: 1.5,
|
|
borderRadius: 8,
|
|
borderStyle: "dashed",
|
|
marginTop: 4,
|
|
},
|
|
addButtonText: {
|
|
fontSize: 14,
|
|
fontWeight: "600",
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
});
|