Skip to content

Commit

Permalink
feat: build an outfit works
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaajia committed Dec 19, 2024
1 parent fb3f8dd commit 6f9139d
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 58 deletions.
79 changes: 48 additions & 31 deletions src/components/OutfitMakerComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
if (typeof global === 'undefined') {

Check failure on line 1 in src/components/OutfitMakerComponent.tsx

View workflow job for this annotation

GitHub Actions / deploy

Cannot find name 'global'.
window.global = window;

Check failure on line 2 in src/components/OutfitMakerComponent.tsx

View workflow job for this annotation

GitHub Actions / deploy

Property 'global' does not exist on type 'Window & typeof globalThis'.
}

import {
Box,
VStack,
Expand Down Expand Up @@ -51,34 +55,39 @@ export default function OutfitMakerComponent() {
const [isLoading, setIsLoading] = useState(false);
const toast = useToast();

const userId = 1; // Replace with actual user ID
const userId = 1;

useEffect(() => {
loadItemsByCategory();
loadSavedOutfits();
}, [selectedCategory]);
}, [selectedCategory.id]);

useEffect(() => {
if (showSavedOutfits) {
loadSavedOutfits();
}
}, [showSavedOutfits]);

const loadItemsByCategory = async () => {
try {
const items = await fetchItemsByCategory(selectedCategory.id, userId);
setAvailableItems(items);
if (Array.isArray(items)) {
setAvailableItems(items);
}
} catch (error) {
toast.show({
description: "Failed to load items",
variant: "solid",
});
console.error('Error loading items:', error);
setAvailableItems([]);
}
};

const loadSavedOutfits = async () => {
try {
const outfits = await fetchSavedOutfits(userId);
setSavedOutfits(outfits);
if (Array.isArray(outfits)) {
setSavedOutfits(outfits);
}
} catch (error) {
toast.show({
description: "Failed to load outfits",
variant: "solid",
});
console.error('Error loading outfits:', error);
setSavedOutfits([]);
}
};

Expand Down Expand Up @@ -112,8 +121,12 @@ export default function OutfitMakerComponent() {
setSelectedItems([]);
setOutfitName("");
setShowSaveModal(false);
loadSavedOutfits();

if (showSavedOutfits) {
await loadSavedOutfits();
}
} catch (error) {
console.error('Error saving outfit:', error);
toast.show({
description: "Failed to save outfit",
variant: "solid",
Expand All @@ -125,15 +138,14 @@ export default function OutfitMakerComponent() {

const handleDeleteOutfit = async (outfitId: number) => {
try {
const success = await deleteOutfit(outfitId);
if (success) {
toast.show({
description: "Outfit deleted successfully",
variant: "solid",
});
loadSavedOutfits();
}
await deleteOutfit(outfitId);
toast.show({
description: "Outfit deleted successfully",
variant: "solid",
});
await loadSavedOutfits();
} catch (error) {
console.error('Error deleting outfit:', error);
toast.show({
description: "Failed to delete outfit",
variant: "solid",
Expand All @@ -142,7 +154,18 @@ export default function OutfitMakerComponent() {
};

const handleAddItem = (item: ClothingItem) => {
if (selectedItems.length >= 6 || selectedItems.some(selected => selected.item_id === item.item_id)) {
if (selectedItems.length >= 6) {
toast.show({
description: "Maximum 6 items allowed",
variant: "solid",
});
return;
}
if (selectedItems.some(selected => selected.item_id === item.item_id)) {
toast.show({
description: "Item already selected",
variant: "solid",
});
return;
}
setSelectedItems(prev => [...prev, item]);
Expand All @@ -155,12 +178,10 @@ export default function OutfitMakerComponent() {
return (
<Box flex={1} bg="#E6E5DC" safeArea alignItems="center" pb="80px">
<VStack space={4} w="100%" maxW="400px" px={4} alignItems="center">
{/* Title */}
<Text fontSize="xl" fontWeight="bold" color="#395D51" textAlign="center" mt={4}>
OUTFIT MAKER
</Text>

{/* Category Selection */}
<ScrollView horizontal showsHorizontalScrollIndicator={false} w="100%">
<HStack space={3} py={2}>
{categories.map((category) => (
Expand Down Expand Up @@ -188,7 +209,6 @@ export default function OutfitMakerComponent() {
</HStack>
</ScrollView>

{/* Available Items */}
<Box w="100%" minH="150px">
<Text color="#395D51" fontSize="lg" fontWeight="semibold" mb={2}>
AVAILABLE {selectedCategory.name}
Expand Down Expand Up @@ -225,7 +245,6 @@ export default function OutfitMakerComponent() {
</ScrollView>
</Box>

{/* Selected Items */}
{selectedItems.length > 0 && (
<Box w="100%" minH="150px">
<Text color="#395D51" fontSize="lg" fontWeight="semibold" mb={2}>
Expand Down Expand Up @@ -272,7 +291,6 @@ export default function OutfitMakerComponent() {
</Box>
)}

{/* Action Buttons */}
<HStack space={4} w="100%" justifyContent="center" mt={4}>
<ButtonComponent
onPress={() => setShowSaveModal(true)}
Expand All @@ -286,7 +304,6 @@ export default function OutfitMakerComponent() {
/>
</HStack>

{/* Save Modal */}
<Modal isOpen={showSaveModal} onClose={() => setShowSaveModal(false)}>
<Modal.Content bg="#E6E5DC">
<Modal.CloseButton />
Expand Down Expand Up @@ -330,12 +347,12 @@ export default function OutfitMakerComponent() {
<ButtonComponent
onPress={handleSaveOutfit}
label="SAVE"
isLoading={isLoading}

Check failure on line 350 in src/components/OutfitMakerComponent.tsx

View workflow job for this annotation

GitHub Actions / deploy

Type '{ onPress: () => Promise<void>; label: string; isLoading: boolean; }' is not assignable to type 'IntrinsicAttributes & ButtonComponentProps'.
/>
</Modal.Footer>
</Modal.Content>
</Modal>

{/* View Saved Outfits Modal */}
<Modal isOpen={showSavedOutfits} onClose={() => setShowSavedOutfits(false)} size="full">
<Modal.Content bg="#E6E5DC">
<Modal.CloseButton />
Expand Down Expand Up @@ -387,7 +404,7 @@ export default function OutfitMakerComponent() {
>
<Image
source={{ uri: item.clothing_items.photo_link }}
alt={item.clothing_items.item_desc}
alt={item.item_desc}

Check failure on line 407 in src/components/OutfitMakerComponent.tsx

View workflow job for this annotation

GitHub Actions / deploy

Property 'item_desc' does not exist on type '{ clothing_items: ClothingItem; }'.
size="md"
/>
<Text fontSize="xs" mt={1} color="#395D51">
Expand Down
111 changes: 84 additions & 27 deletions src/functions/outfitDatabaseFunctions.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,74 @@
import supabase from "../utils/supbaseClient";

// Fetch all items for a specific category
interface ClothingItem {
item_id: number;
item_desc: string;
photo_link: string;
category_id: number;
}

interface OutfitItem {
clothing_items: ClothingItem;
}

interface SavedOutfit {

Check failure on line 14 in src/functions/outfitDatabaseFunctions.tsx

View workflow job for this annotation

GitHub Actions / deploy

'SavedOutfit' is declared but never used.
outfit_id: number;
outfit_name: string;
outfit_items: OutfitItem[];
}

export const fetchItemsByCategory = async (categoryId: number, userId: number) => {
try {
console.log('Fetching items for category:', categoryId, 'and user:', userId);
const { data, error } = await supabase
.from('clothing_items')
.select('item_id, item_desc, photo_link, category_id')
.select('*')
.eq('category_id', categoryId)
.eq('user_id', userId);

if (error) throw error;
if (error) {
console.error('Supabase error:', error);
throw error;
}

console.log('Fetched items:', data);
return data || [];
} catch (error) {
console.error('Error fetching items:', error);
return [];
console.error('Error in fetchItemsByCategory:', error);
throw error;
}
};

// Save a new outfit
export const saveOutfit = async (
userId: number,
outfitName: string,
itemIds: number[]
) => {
try {
// First, create the outfit
console.log('Saving outfit:', { userId, outfitName, itemIds });

const { data: outfitData, error: outfitError } = await supabase
.from('outfits')
.insert([
{ user_id: userId, outfit_name: outfitName }
{
user_id: userId,
outfit_name: outfitName
}
])
.select('outfit_id')
.select()
.single();

if (outfitError) throw outfitError;
if (outfitError) {
console.error('Error creating outfit:', outfitError);
throw outfitError;
}

if (!outfitData) {
throw new Error('No outfit data returned after insert');
}

console.log('Created outfit:', outfitData);

// Then, create outfit_items entries
const outfitItems = itemIds.map(itemId => ({
outfit_id: outfitData.outfit_id,
item_id: itemId
Expand All @@ -45,20 +78,27 @@ export const saveOutfit = async (
.from('outfit_items')
.insert(outfitItems);

if (itemsError) throw itemsError;
if (itemsError) {
console.error('Error creating outfit items:', itemsError);
await supabase
.from('outfits')
.delete()
.eq('outfit_id', outfitData.outfit_id);
throw itemsError;
}

return outfitData.outfit_id;
return true;
} catch (error) {
console.error('Error saving outfit:', error);
return null;
console.error('Error in saveOutfit:', error);
throw error;
}
};

// Fetch saved outfits with their items
export const fetchSavedOutfits = async (userId: number) => {
try {
// First get all outfits for the user
const { data: outfits, error: outfitsError } = await supabase
console.log('Fetching outfits for user:', userId);

const { data, error } = await supabase
.from('outfits')
.select(`
outfit_id,
Expand All @@ -72,29 +112,46 @@ export const fetchSavedOutfits = async (userId: number) => {
)
)
`)
.eq('user_id', userId);
.eq('user_id', userId)
.order('created_at', { ascending: false });

if (error) {
console.error('Error fetching outfits:', error);
throw error;
}

if (outfitsError) throw outfitsError;
console.log('Raw outfits data:', data);

return outfits || [];
const transformedOutfits = data?.map(outfit => ({
...outfit,
outfit_items: outfit.outfit_items.filter(item => item.clothing_items !== null)
})) || [];

console.log('Transformed outfits:', transformedOutfits);
return transformedOutfits;
} catch (error) {
console.error('Error fetching outfits:', error);
return [];
console.error('Error in fetchSavedOutfits:', error);
throw error;
}
};

// Delete an outfit
export const deleteOutfit = async (outfitId: number) => {
try {
console.log('Deleting outfit:', outfitId);

const { error } = await supabase
.from('outfits')
.delete()
.eq('outfit_id', outfitId);

if (error) throw error;
if (error) {
console.error('Error deleting outfit:', error);
throw error;
}

return true;
} catch (error) {
console.error('Error deleting outfit:', error);
return false;
console.error('Error in deleteOutfit:', error);
throw error;
}
};

0 comments on commit 6f9139d

Please sign in to comment.