feat: enhance filament management and UI improvements
- Update SpoolPresetRepository to include user_id in the update query. - Expand .gitignore to include various environment and temporary files. - Revise agent documentation for better clarity and formatting. - Implement pull-to-refresh functionality in the inventory list. - Integrate API calls for deleting and updating filaments, ensuring state synchronization. - Add custom color picker for filament color selection with hex validation. - Update AndroidManifest and Gradle files for improved configuration and permissions. - Refactor MainActivity and MainApplication for better splash screen handling. - Update styles and colors for a cohesive UI experience. - Replace splash screen logos and icons with new assets.
This commit is contained in:
@@ -10,13 +10,15 @@ import { Ionicons } from '@expo/vector-icons';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { usePresetStore } from '@store/presetStore';
|
||||
import { useFilamentStore } from '@store/filamentStore';
|
||||
import { useAuthStore } from '@store/authStore';
|
||||
import { deleteFilamentUseCase, updateFilamentUseCase } from '@infrastructure/container';
|
||||
import { Input } from '@presentation/components/ui/Input';
|
||||
import { Button } from '@presentation/components/ui/Button';
|
||||
import { Card } from '@presentation/components/ui/Card';
|
||||
import { calcNetWeight } from '@domain/Filament';
|
||||
import { colors, typography, spacing, radius } from '@shared/theme';
|
||||
import { MATERIALS, type Material } from '@shared/constants';
|
||||
import { formatWeight } from '@shared/utils/filament';
|
||||
import { formatWeight, isValidHex, normalizeHex } from '@shared/utils/filament';
|
||||
|
||||
const schema = z.object({
|
||||
brand: z.string().min(1, 'Marca obrigatória'),
|
||||
@@ -48,6 +50,7 @@ export default function EditFilamentScreen(): React.ReactElement {
|
||||
const [selectedMaterial, setSelectedMaterial] = useState<Material>((filament?.material as Material) ?? 'PLA');
|
||||
const [selectedPresetId, setSelectedPresetId] = useState<string | null>(filament?.spoolPresetId ?? systemPresets[0]?.id ?? null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isOpeningColorPicker, setIsOpeningColorPicker] = useState(false);
|
||||
|
||||
const { control, handleSubmit, watch, formState: { errors } } = useForm<FormData>({
|
||||
resolver: zodResolver(schema),
|
||||
@@ -82,23 +85,66 @@ export default function EditFilamentScreen(): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
function handleDelete(): void {
|
||||
const handleOpenColorPicker = (): void => {
|
||||
if (isOpeningColorPicker) return;
|
||||
setIsOpeningColorPicker(true);
|
||||
Alert.prompt(
|
||||
'Cor Customizada',
|
||||
'Digite um código de cor hexadecimal (ex: #FF5733)',
|
||||
[
|
||||
{ text: 'Cancelar', style: 'cancel', onPress: () => setIsOpeningColorPicker(false) },
|
||||
{
|
||||
text: 'Confirmar',
|
||||
onPress: (value) => {
|
||||
setIsOpeningColorPicker(false);
|
||||
if (!value) return;
|
||||
const normalized = normalizeHex(value.trim());
|
||||
if (isValidHex(normalized)) {
|
||||
setSelectedColor(normalized);
|
||||
setHexInput(normalized);
|
||||
} else {
|
||||
Alert.alert('Erro', 'Código hexadecimal inválido. Use o formato #RRGGBB ou #RGB.');
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
'plain-text',
|
||||
selectedColor,
|
||||
);
|
||||
};
|
||||
|
||||
const handleDelete = async (): Promise<void> => {
|
||||
Alert.alert(
|
||||
'Excluir filamento',
|
||||
`Deseja excluir "${filament!.brand}${filament!.model ? ` ${filament!.model}` : ''}"? Esta ação não pode ser desfeita.`,
|
||||
'Confirmar Deleção',
|
||||
'Tem certeza que deseja deletar este filamento?',
|
||||
[
|
||||
{ text: 'Cancelar', style: 'cancel' },
|
||||
{
|
||||
text: 'Excluir',
|
||||
text: 'Deletar',
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
removeFilament(filament!.id);
|
||||
router.replace('/(app)/(tabs)/inventory');
|
||||
onPress: async () => {
|
||||
const user = useAuthStore.getState().user;
|
||||
if (!user) {
|
||||
Alert.alert('Erro', 'Usuário não autenticado.');
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await deleteFilamentUseCase.execute(filament!.id, user.id);
|
||||
removeFilament(filament!.id);
|
||||
Alert.alert('Sucesso', 'Filamento deletado.');
|
||||
router.back();
|
||||
} catch (err) {
|
||||
console.error('delete filament error', err);
|
||||
Alert.alert('Erro', 'Falha ao deletar: ' + (err as Error).message);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
async function onSubmit(data: FormData): Promise<void> {
|
||||
if (!selectedPresetId) {
|
||||
@@ -163,7 +209,7 @@ export default function EditFilamentScreen(): React.ReactElement {
|
||||
style={[styles.colorDot, { backgroundColor: c }, selectedColor === c && styles.colorDotActive]}
|
||||
/>
|
||||
))}
|
||||
<TouchableOpacity style={styles.colorAddBtn}>
|
||||
<TouchableOpacity style={styles.colorAddBtn} onPress={handleOpenColorPicker}>
|
||||
<Ionicons name="add" size={18} color={colors.textSecondary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user