Skip to content

Commit

Permalink
Merge pull request #9 from ThatNinjaGuy/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
ThatNinjaGuy committed Aug 15, 2024
2 parents 0844526 + 935202c commit a564731
Show file tree
Hide file tree
Showing 10 changed files with 408 additions and 138 deletions.
127 changes: 127 additions & 0 deletions components/CustomModal/CustomModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import React, { useState, useEffect } from "react";
import { Modal, TextInput, View } from "react-native";
import { Picker } from "@react-native-picker/picker"; // Import Picker for dropdown
import { RadioButton } from "react-native-paper"; // Import RadioButton for radio inputs
import styles from "./styles";
import { ThemedView } from "../common/ThemedView";
import ThemedButton from "../common/ThemedButton";
import { ThemedText } from "../common/ThemedText";

const CustomModal = ({ onClose, onSave, onDelete, item, schema }) => {
const initializeFormData = (schema, item) => {
return schema.reduce((acc, field) => {
acc[field.name] = item ? item[field.name] : "";
return acc;
}, {});
};

const [formData, setFormData] = useState(() =>
initializeFormData(schema, item)
);

useEffect(() => {
setFormData(initializeFormData(schema, item));
}, [item, schema]);

const handleInputChange = (name, value) => {
setFormData((prevData) => ({ ...prevData, [name]: value }));
};

const handleSave = () => {
onSave(formData);
};

const handleDelete = () => {
onDelete();
};

return (
<Modal
key={item ? item.id : "new"} // Unique key based on item
onBackdropPress={onClose}
animationIn="slideInUp"
animationOut="slideOutDown"
backdropTransitionOutTiming={0}
style={styles.modal}
transparent={true}
>
<View style={styles.modalContent}>
{schema.map((field) => {
switch (field.type) {
case "dropdown":
return (
<Picker
key={field.name}
selectedValue={formData[field.name] || ""} // Default to unselected
onValueChange={(value) =>
handleInputChange(field.name, value)
}
style={styles.dropdown}
>
<Picker.Item label="Select an option" value="" />
{field.options.map((option) => (
<Picker.Item key={option} label={option} value={option} />
))}
</Picker>
);
case "radio":
return (
<View key={field.name} style={styles.radioGroup}>
<ThemedText>{field.placeholder}</ThemedText>
{field.options.map((option) => (
<View key={option} style={styles.radioItem}>
<RadioButton
value={option}
status={
formData[field.name] === option
? "checked"
: "unchecked"
}
onPress={() => handleInputChange(field.name, option)}
/>
<ThemedText>{option}</ThemedText>
</View>
))}
</View>
);
default:
return (
<TextInput
key={field.name}
style={styles.input}
placeholder={field.placeholder}
value={formData[field.name]}
onChangeText={(value) => handleInputChange(field.name, value)}
keyboardType={field.inputMode}
/>
);
}
})}
<ThemedView style={styles.buttonContainer}>
<ThemedButton
style={[styles.button, styles.deleteButton]}
onPress={handleDelete}
>
<ThemedText style={styles.buttonText}>Delete</ThemedText>
</ThemedButton>
<ThemedButton
style={[styles.button, styles.saveButton]}
onPress={handleSave}
>
<ThemedText style={styles.buttonText}>Update</ThemedText>
</ThemedButton>
</ThemedView>
<ThemedView style={styles.buttonContainer}>
<ThemedButton
style={[styles.button, styles.cancelButton]}
onPress={onClose}
>
<ThemedText style={styles.buttonText}>Close</ThemedText>
</ThemedButton>
</ThemedView>
</View>
</Modal>
);
};

export default CustomModal;
33 changes: 33 additions & 0 deletions components/Modal/styles.js → components/CustomModal/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default StyleSheet.create({
elevation: 10,
backgroundColor: "#fff",
},
// Input fields
input: {
borderWidth: 1,
borderColor: "#ccc",
Expand All @@ -26,6 +27,38 @@ export default StyleSheet.create({
marginBottom: 15,
fontSize: 16,
},
radioGroup: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
marginBottom: 15,
padding: 10,
paddingHorizontal: 20,
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 10,
backgroundColor: "#fff",
},
radioItem: {
flexDirection: "row",
alignItems: "center",
},
radioLabel: {
marginLeft: 8,
fontSize: 16,
color: "#333",
},
dropdown: {
width: "100%",
marginBottom: 15,
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 10,
padding: 15,
backgroundColor: "#fff",
fontSize: 16,
},

buttonContainer: {
flexDirection: "row",
justifyContent: "space-between",
Expand Down
54 changes: 54 additions & 0 deletions components/FloatingLabelInput/FloatingLabelInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useState } from "react";
import { View, TextInput, Text, Animated } from "react-native";

const FloatingLabelInput = ({ label, value, onChangeText, ...props }) => {
const [isFocused, setIsFocused] = useState(false);
const animatedIsFocused = new Animated.Value(value === "" ? 0 : 1);

const handleFocus = () => setIsFocused(true);
const handleBlur = () => setIsFocused(false);

React.useEffect(() => {
Animated.timing(animatedIsFocused, {
toValue: isFocused || value !== "" ? 1 : 0,
duration: 200,
useNativeDriver: false,
}).start();
}, [isFocused, value]);

const labelStyle = {
position: "absolute",
left: 15,
top: animatedIsFocused.interpolate({
inputRange: [0, 1],
outputRange: [20, 0],
}),
fontSize: animatedIsFocused.interpolate({
inputRange: [0, 1],
outputRange: [16, 12],
}),
color: "#aaa",
};

return (
<View style={{ paddingTop: 18 }}>
<Animated.Text style={labelStyle}>{label}</Animated.Text>
<TextInput
{...props}
style={{
height: 40,
fontSize: 16,
color: "#000",
borderBottomWidth: 1,
borderBottomColor: "#ccc",
}}
onFocus={handleFocus}
onBlur={handleBlur}
onChangeText={onChangeText}
value={value}
/>
</View>
);
};

export default FloatingLabelInput;
88 changes: 0 additions & 88 deletions components/Modal/Modal.js

This file was deleted.

Loading

0 comments on commit a564731

Please sign in to comment.