Index Home Page - Zanegerous/CopperToGold GitHub Wiki
``# Home Page This is where most of our functions are contained as most of the functionality is located here.
The start of the file has permission request in order to manage the camera
if (!permission.granted) {
return (
<View className="flex-1">
<Text className="bg-black text-white rounded-md text-center text-2xl top-5 w-8/12" style={{ fontSize: scale(24) }}>We need your permission to show the camera</Text>
<Button onPress={requestPermission} title="grant permission" />
</View>
);
}
const saveItem = async (item: EbayItem) => {
const cleanTitle = item.title.replace(/[^a-zA-Z0-9]/g, "_");
const saveRef = `users/${userUID}/savedItems/${cleanTitle}`
const itemRef = dbRef(database, saveRef);
try {
await set(itemRef, {
title: item.title,
price: item.price,
image: item.image,
condition: item.condition,
id: item.id
});
console.log('saved Item: ', item.title)
} catch (error: any) {
console.error("Save Error: ", error);
}
}
const deleteSavedItem = async (item: EbayItem) => {
const cleanTitle = item.title.replace(/[^a-zA-Z0-9]/g, "_");
const saveRef = dbRef(database, `users/${userUID}/savedItems/${cleanTitle}`);
try {
await remove(saveRef);
console.log('Removed Item: ', item.title)
} catch (error: any) {
console.error("Delete Error: ", error);
}
}
Formatting for the result box, which formats the search results recieved into something our scrollview can use.
const RenderResultItem = ({ item }: { item: EbayItem }) => {
const [resultModal, setResultModal] = useState(false);
const soldPageLink = `https://www.ebay.com/sch/i.html?_nkw=${item.title}&_sacat=0&_from=R40&LH_Sold=1&LH_Complete=1&rt=nc&LH_BIN=1`
const [saveState, setSaveState] = useState(false);
const [soldPageModal, setSoldPageModal] = useState(false);
const textSettings = ' color-white'; // space needed at start
return (
<View className="bg-slate-600 flex-1 border-black rounded-md border-spacing-4 border-2 mb-4 mr-5 ml-5 w-2/5">
<TouchableOpacity
onPress={() => { setResultModal(true) }}
className=""
>
{/*This is the outside image*/}
<Image
source={{ uri: item.image }}
className="h-48 m-1 rounded-lg"
resizeMode='contain'
/>
<Text className="text-center color-blue-900 font-semibold m-2 rounded-lg bg-zinc-400 text-sm">{item.title}</Text>
<Text className="text-left text-l ml-1 text-white">Listed Price: ${item.price.value}</Text>
<Text className="text-left ml-1 text-white">Condition: {item.condition}</Text>
</TouchableOpacity>
{/* Zoom up modal */}
<Modal visible={resultModal} onRequestClose={() => { setResultModal(false) }} animationType='fade'>
<View className="bg-blue-dark-200 flex-1">
<View className="flex-row justify-between items-center">
<TouchableOpacity className=" px-1 mt-4 ml-2 "
onPress={() => {
setResultModal(false)
}}>
<Icon name={'arrow-circle-o-left'} color={'orange'} size={50} />
</TouchableOpacity>
<TouchableOpacity onPress={() => {
if (saveState == false) {
saveItem(item);
setSaveState(true);
} else {
deleteSavedItem(item);
setSaveState(false);
}
}}
className="mt-4 mr-2 "
>
<Icon name={'star'} size={50} color={saveState ? 'yellow' : 'grey'} />
</TouchableOpacity>
</View>
<Text className={"text-center font-bold text-3xl bg-blue-dark-100 w-auto m-1 rounded-xl border-black border-2 mb-2 mt-2" + textSettings}>{item.title}</Text>
<Image
source={{ uri: item.image }}
className="w-11/12 h-1/2 m-1 rounded-lg self-center bg-slate-600"
resizeMode='contain'
/>
<Text className={"text-left text-3xl ml-4 mt-6" + textSettings}>Listing Price: ${item.price.value}</Text>
<Text className={"text-left text-3xl ml-4" + textSettings}>Condition: {item.condition}</Text>
<View className="flex-row absolute bottom-2 justify-center content-center w-full">
<TouchableOpacity onPress={() => setSoldPageModal(true)} className="bg-orange-400 rounded-lg border-2 border-black justify-center w-2/5 self-center h-16" >
<Text className={"text-center text-2xl justify-center" + textSettings}>See Sold Items</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => { setText(item.title); handleSearch(); setResultModal(false) }} className="bg-orange-400 m-2 rounded-lg border-2 border-black w-1/2 justify-center self-center h-16" >
<Text className={"text-center text-2xl" + textSettings}>Search This Item</Text>
</TouchableOpacity>
</View>
<View className="w-full h-2/3 self-center p-5">
<Modal visible={soldPageModal} animationType='slide' onRequestClose={() => { setSoldPageModal(false) }}>
<View className="bg-blue-dark-100">
<TouchableOpacity className=" self-left px-1 mt-2 mb-2 ml-2 "
onPress={() => {
setSoldPageModal(false)
}}>
<Icon name={'arrow-circle-o-left'} color={'orange'} size={50} />
</TouchableOpacity>
</View>
<WebView
source={{ uri: soldPageLink }}
scalesPageToFit={true}
/>
</Modal>
</View>
</View>
</Modal>
</View>
)
};
Takes the image from the camera and determines what text is located in it, returning the text and placing it in the search bar for the user to edit before searching
const takePictureText = async (camera: { takePictureAsync: () => any } | null) => {
try {
if (camera != null) {
const apiKey = ''; // hidden for security reasons will be moved to back end
const photo = await camera.takePictureAsync();
const urifetch = await fetch(photo.uri);
const blob = await urifetch.blob();
const storage = getStorage();
const dateUploadTime = Date.now()
// upload the image ref
const folderLocation = `user/${getUserID()}/temp/${dateUploadTime}.jpg`
const imageRef = storageRef(storage, folderLocation);
await uploadBytes(imageRef, blob);
const firebaseUrl = await getDownloadURL(imageRef);
const endpointUrl = `https://api.apilayer.com/image_to_text/url?url=${encodeURIComponent(firebaseUrl)}`;
const response = await axios.get(endpointUrl, {
headers: {
apiKey: apiKey,
},
});
const text = response.data.all_text;
// remove it once done.
await deleteObject(imageRef);
return text;
}
} catch (error) {
console.error('Error: ', error);
return 'Error'
}
};
There is also search settings which can be changed so that it is able to define what type of stuff you
<View className={settingWrapper}>
<Text style={{ fontSize: scale(16) }} className={buttonText}>
Item Condition: {
itemCondition === 'all' ? 'All' :
itemCondition === '1000' ? 'New' :
itemCondition === '3000' ? 'Used' :
itemCondition === '7000' ? 'Parts' : 'All'
}
</Text>
<Picker
selectedValue={itemCondition}
onValueChange={(value) => setItemCondition(value)}
style={{
height: 40,
width: '20%',
backgroundColor: '#fff',
borderRadius: 5,
textAlign: 'center',
}}
>
{itemConditionOptions.map((option) => (
<Picker.Item key={option.value} label={option.label} value={option.value} />
))}
</Picker>
</View>
This is the formatting for the history bar, located on the home page. currently not functional on the result page due to personal preference.
This function converts and compares the results from the text search aswell as the image result, returning what exists in both lists.
this function converts a given image uri into base64 format to be utilized.
When the camera scans a barcode, then this function will set the text to the scanned barcode and search it.
This function gets the current cameraview and captures the image, then it searches the image through ebay.
This function takes in a base64 image string, then sending it to be searched on ebay, also managing the loading icon.
This function calls the text variable, then sending it to be searched on ebay, also managing the loading icon.
sets the sold view to showcase sold items
Animation to open the search bar and modify modal variables
Animation to close the search bar and modify modal variables
Logic to update the search history, setting it up to 10 values.
If text exists this handles the text search
Takes in a list of Ebay items and calculates the average based on the length and price.
const getAvgPrice = (list: EbayItem[] | null): number => {
if (list == null || list.length == 0) {
return 0;
} else {
const total = list.reduce((sum, item) => sum + parseFloat(item.price.value), 0);
const avg = total / list.length
return parseFloat(avg.toFixed(2));
}
};
Added all the i18n text translation for english to spanish to all text in the index.
<View className="bg-slate-600 flex-1 border-black rounded-md border-spacing-4 border-2 mb-4 mr-5 ml-5 w-2/5">
<TouchableOpacity
onPress={() => { setResultModal(true) }}
className=""
>
{/*This is the outside image*/}
<Image
source={{ uri: item.image }}
className="h-48 m-1 rounded-lg"
resizeMode='contain'
/>
<Text className="text-center color-blue-900 font-semibold m-2 rounded-lg bg-zinc-400 text-sm">{item.title}</Text>
<Text className="text-left text-l ml-1 text-white">{t("PriceListed")}: ${item.price.value}</Text>
<Text className="text-left ml-1 text-white">{t("ItemConditioning")}: {item.condition}</Text>
</TouchableOpacity>
This is the formatting for all of the code, managing and calling functions in order to manage the home/index page