2025-07-30 14:10:23 +02:00

173 lines
6.1 KiB
TypeScript

import { toast } from '@backpackapp-io/react-native-toast';
import Ionicons from '@expo/vector-icons/Ionicons';
import { Stack, useLocalSearchParams, useRouter } from 'expo-router';
import React, { useState } from 'react';
import { Pressable, ScrollView, StyleSheet, TextInput, View } from 'react-native';
import { EmojiPopup } from 'react-native-emoji-popup';
import { ThemedView } from '../..//components/ThemedView';
import { Category, CategoryQuery } from '../..//models/category';
import { CategoryRepository } from '../..//repositories/CategoryRepository';
import { ThemedText } from '../../components/ThemedText';
import { SQLiteDataService } from '../../services/data/sqliteDataService';
const categoryRepository = new CategoryRepository(new SQLiteDataService<Category>(CategoryQuery));
export default function CategoryForm() {
const { category: categoryJson } = useLocalSearchParams();
const category: Category = categoryJson ? JSON.parse(categoryJson as string) : null;
const router = useRouter();
const [newCategory, setNewCategory] = useState({
title: category?.title || '',
icon: category?.icon || '',
});
return (
<ThemedView style={styles.mainContainer} >
<Stack.Screen options={{ header: () => null }} />
<ThemedView style={styles.headerContainer}>
<ThemedText type="title" style={{
color: '#fff',
}}> Taskeep! </ThemedText>
< Pressable onPress={() => {
router.back();
}
}>
<Ionicons name='close-circle-outline' size={32} color="#fff" />
</Pressable>
</ThemedView>
< ScrollView style={styles.scrollView} >
<ThemedText type="subtitle">Add a new category</ThemedText>
<ThemedView style={styles.stepContainer}>
<EmojiPopup onEmojiSelected={emoji => setNewCategory({ ...newCategory, icon: emoji })} >
<ThemedView style={styles.addIconView}>
{newCategory.icon != "" ? <ThemedText>{newCategory.icon}</ThemedText> : <Ionicons name={newCategory.icon || "happy-outline"} size={24} color="#ccc" />}
<ThemedText>{newCategory.icon != "" ? "Change" : "Select"} icon *</ThemedText>
</ThemedView>
</EmojiPopup>
<TextInput
placeholder="Category title *"
style={styles.inputText}
placeholderTextColor="#333"
value={newCategory.title}
onChange={(e) => setNewCategory({ ...newCategory, title: e.nativeEvent.text })}
/>
</ThemedView>
<Pressable style={styles.addButton} onPress={() => {
if (newCategory.title!.length > 0 && newCategory.icon!.length != 1) {
if (category && category.id) {
// Update existing task
categoryRepository.update(category.id, {
...category,
...newCategory
}).then(() => {
toast.success("Category updated successfully!");
router.back();
});
} else {
// Create new task
categoryRepository.create(new Category(newCategory.title, newCategory.icon)).then(() => {
toast.success("Category added successfully!");
router.back();
});
}
} else {
toast.error("Please select an icon and enter a title for the category.");
}
}}>
<Ionicons name='checkmark-circle-outline' size={24} color="#fff" />
<ThemedText style={styles.addButtonText}>{category?.id ? "Update" : "Add"} Category</ThemedText>
</Pressable>
< View style={{ height: 50 }} />
</ScrollView >
</ThemedView >
);
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
},
headerContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
gap: 8,
paddingHorizontal: 24,
paddingTop: 50,
paddingBottom: 18,
backgroundColor: '#6a254fff',
},
scrollView: {
padding: 24,
flex: 1,
},
stepContainer: {
gap: 8,
marginBottom: 8,
marginTop: 16,
flexDirection: 'row',
alignItems: 'center'
},
reactLogo: {
height: 178,
width: 290,
bottom: 0,
left: 0,
position: 'absolute',
},
inputText: {
backgroundColor: '#fff',
height: 50,
color: '#333333',
borderRadius: 8,
padding: 10,
lineHeight: 30,
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: 32,
flex: 1,
borderWidth: 2,
borderColor: '#ccc',
},
textArea: {
backgroundColor: '#fff',
color: '#333333',
borderRadius: 8,
padding: 10,
paddingHorizontal: 32,
minHeight: 100,
textAlignVertical: 'top'
},
addButton: {
flexDirection: 'row',
gap: 8,
backgroundColor: '#b91f7eff',
color: '#fff',
borderRadius: 8,
padding: 20,
alignItems: 'center',
justifyContent: 'center',
},
addButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
},
addIconView: {
flexDirection: 'row',
color: '#fff',
gap: 4,
backgroundColor: '#transparent',
borderWidth: 2,
borderColor: '#ccc',
padding: 12,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
},
});