From 6640a2d8caa3f1a90c78253d3b5518d5f4f58c40 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 20 Apr 2021 02:12:07 -0700 Subject: [PATCH] Can save outfits with items --- src/app/WardrobePage/ItemsPanel.js | 5 +-- src/server/types/Outfit.js | 54 +++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/app/WardrobePage/ItemsPanel.js b/src/app/WardrobePage/ItemsPanel.js index 16d504a..d80ad94 100644 --- a/src/app/WardrobePage/ItemsPanel.js +++ b/src/app/WardrobePage/ItemsPanel.js @@ -263,10 +263,7 @@ function useOutfitSaving(outfitState) { isLoggedIn && (!isSaved || outfitState.creator?.id === currentUserId) && // TODO: Add support for updating outfits - !isSaved && - // TODO: Add support for outfits with items - outfitState.wornItemIds.length === 0 && - outfitState.closetedItemIds.length === 0; + !isSaved; const [sendSaveOutfitMutation, { loading: isSaving }] = useMutation( gql` diff --git a/src/server/types/Outfit.js b/src/server/types/Outfit.js index 38d52c4..2c11232 100644 --- a/src/server/types/Outfit.js +++ b/src/server/types/Outfit.js @@ -131,10 +131,6 @@ const resolvers = { throw new Error("TODO: Add support for updating existing outfits"); } - if (wornItemIds.length > 0 || closetedItemIds.length > 0) { - throw new Error("TODO: Add support for outfits with items"); - } - // Get the base name of the provided name: trim it, and strip any "(1)" // suffixes. const baseName = (rawName || "Untitled outfit").replace( @@ -182,15 +178,49 @@ const resolvers = { ); } - const [result] = await db.execute( - ` - INSERT INTO outfits (name, pet_state_id, user_id, created_at, updated_at) - VALUES (?, ?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()); - `, - [name, petState.id, currentUserId] - ); + // Save the outfit, and its item_outfit_relationships rows, in a + // transaction. + await db.beginTransaction(); + let newOutfitId; + try { + const [result] = await db.execute( + ` + INSERT INTO outfits + (name, pet_state_id, user_id, created_at, updated_at) + VALUES (?, ?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()); + `, + [name, petState.id, currentUserId] + ); + newOutfitId = String(result.insertId); + + if (wornItemIds.length > 0 || closetedItemIds.length > 0) { + const itemRowPlaceholders = [ + [...wornItemIds, ...closetedItemIds].map( + (_) => `(?, ?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP())` + ), + ].join(", "); + const itemRowValues = [ + ...wornItemIds.map((itemId) => [newOutfitId, itemId, true]), + ...closetedItemIds.map((itemId) => [newOutfitId, itemId, false]), + ].flat(); + await db.execute( + // TODO: When we start saving existing outfits, we'll need a delete + // here too, or some other sync mechanism. + ` + INSERT INTO item_outfit_relationships + (outfit_id, item_id, is_worn, created_at, updated_at) + VALUES ${itemRowPlaceholders}; + `, + itemRowValues + ); + } + + await db.commit(); + } catch (e) { + await db.rollback(); + throw e; + } - const newOutfitId = String(result.insertId); console.log(`Saved outfit ${newOutfitId}`); return { id: newOutfitId };