From f73e51343a001268fc26b1d1c95049f8d053fc61 Mon Sep 17 00:00:00 2001 From: Winston Hsiao <96440583+Winston-Hsiao@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:09:23 -0500 Subject: [PATCH] Added extensive logging for listing creation and improved various UIs (#597) --- .../listing/ListingRegisterRobot.tsx | 8 +- .../components/listing/ListingRenderer.tsx | 2 +- frontend/src/components/pages/CreateSell.tsx | 58 +++--- .../src/components/pages/SellerDashboard.tsx | 26 ++- store/app/routers/listings.py | 192 ++++++++---------- 5 files changed, 143 insertions(+), 143 deletions(-) diff --git a/frontend/src/components/listing/ListingRegisterRobot.tsx b/frontend/src/components/listing/ListingRegisterRobot.tsx index 8c1d96f6..eb2fe9d8 100644 --- a/frontend/src/components/listing/ListingRegisterRobot.tsx +++ b/frontend/src/components/listing/ListingRegisterRobot.tsx @@ -13,9 +13,9 @@ const ListingRegisterRobot = ({ listingId }: Props) => { const [isRegisterModalOpen, setIsRegisterModalOpen] = useState(false); return ( -
+
+

+ You can interact with your registered robots in the terminal. +

+ setIsRegisterModalOpen(false)} diff --git a/frontend/src/components/listing/ListingRenderer.tsx b/frontend/src/components/listing/ListingRenderer.tsx index 06632362..26ba0a39 100644 --- a/frontend/src/components/listing/ListingRenderer.tsx +++ b/frontend/src/components/listing/ListingRenderer.tsx @@ -41,7 +41,7 @@ const ListingRenderer = ({ listing }: { listing: ListingResponse }) => { const isForSale = priceAmount && stripeProductId && inventoryType; return ( -
+
{/* Main content area - flex column on mobile, row on desktop */}
{ }); }; - const onSubmit = async ({ - name, - description, - slug, - price_amount, - currency, - inventory_type, - inventory_quantity, - preorder_release_date, - is_reservation, - reservation_deposit_amount, - }: SellListingType) => { + const onSubmit = async (data: SellListingType) => { + console.log("Submitting data:", data); setIsSubmitting(true); const formData = new FormData(); - formData.append("name", name); - formData.append("description", description || ""); - formData.append("slug", slug || slugify(name)); + formData.append("name", data.name); + formData.append("description", data.description || ""); + formData.append("slug", data.slug || slugify(data.name)); formData.append( "price_amount", - price_amount ? convertToCents(price_amount).toString() : "", + data.price_amount ? convertToCents(data.price_amount).toString() : "", + ); + formData.append("currency", data.currency); + formData.append("inventory_type", data.inventory_type); + formData.append( + "inventory_quantity", + data.inventory_quantity?.toString() || "", ); - formData.append("currency", currency); - formData.append("inventory_type", inventory_type); - formData.append("inventory_quantity", inventory_quantity?.toString() || ""); formData.append( "preorder_release_date", - preorder_release_date?.toString() || "", + data.preorder_release_date?.toString() || "", ); - formData.append("is_reservation", is_reservation?.toString() || ""); + formData.append("is_reservation", data.is_reservation?.toString() || ""); formData.append( "reservation_deposit_amount", - reservation_deposit_amount - ? convertToCents(reservation_deposit_amount).toString() + data.reservation_deposit_amount + ? convertToCents(data.reservation_deposit_amount).toString() : "", ); @@ -260,10 +253,19 @@ const CreateSell = () => { }); try { - // @ts-expect-error Server accepts FormData but TypeScript doesn't recognize it - const { data: responseData } = await auth.client.POST("/listings/add", { - body: formData, - } as { body: FormData }); + const { data: responseData, error } = await auth.client.POST( + "/listings/add", + // @ts-expect-error Server accepts FormData but TypeScript doesn't recognize it + { + body: formData, + } as { body: FormData }, + ); + + if (error) { + console.error("Server error:", error.detail); + addErrorAlert(`Failed to create listing: ${error.detail}`); + return; + } if (responseData && responseData.username && responseData.slug) { addAlert("New listing was created successfully", "success"); @@ -277,8 +279,8 @@ const CreateSell = () => { throw new Error("Invalid response data"); } } catch (error) { - addErrorAlert("Failed to create listing"); console.error("Error creating listing:", error); + addErrorAlert("Failed to create listing"); } finally { setIsSubmitting(false); } diff --git a/frontend/src/components/pages/SellerDashboard.tsx b/frontend/src/components/pages/SellerDashboard.tsx index b0d02725..287f4569 100644 --- a/frontend/src/components/pages/SellerDashboard.tsx +++ b/frontend/src/components/pages/SellerDashboard.tsx @@ -5,6 +5,8 @@ import { useAuthentication } from "@/hooks/useAuth"; import ROUTES from "@/lib/types/routes"; import { Check } from "lucide-react"; +import { Button } from "../ui/button"; + export default function SellerDashboard() { const navigate = useNavigate(); const auth = useAuthentication(); @@ -52,14 +54,22 @@ export default function SellerDashboard() {
- - Open Stripe Dashboard - +
+ + + Open Stripe Dashboard + +
diff --git a/store/app/routers/listings.py b/store/app/routers/listings.py index 9163f326..55ffe3aa 100644 --- a/store/app/routers/listings.py +++ b/store/app/routers/listings.py @@ -287,124 +287,108 @@ async def add_listing( reservation_deposit_amount: int | None = Form(None), photos: List[UploadFile] = File(None), ) -> NewListingResponse: - logger.info(f"Received {len(photos) if photos else 0} photos") - - # Initialize Stripe-related variables - stripe_product_id = None - stripe_price_id = None - deposit_price_id = None - - # Validate the input - if price_amount is not None and price_amount <= 0: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Price amount must be greater than 0", - ) - - if inventory_type == "finite" and (inventory_quantity is None or inventory_quantity <= 0): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Finite inventory requires a positive quantity", - ) - - if inventory_type == "preorder" and not preorder_release_date: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Preorder requires a release date", - ) - - if is_reservation and (not reservation_deposit_amount or reservation_deposit_amount <= 0): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Reservations require a deposit amount", - ) + try: + logger.info("Starting to process add listing request") - if is_reservation and ( - not price_amount or not reservation_deposit_amount or price_amount <= reservation_deposit_amount - ): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Full price must be greater than deposit amount", - ) + # Initialize variables + stripe_product_id = None + stripe_price_id = None + deposit_price_id = None # Initialize here - # Create Stripe product if price is set - if price_amount is not None and user.stripe_connect_account_id: - try: - product = stripe.Product.create( - name=name, - description=description or "", - metadata={ - "user_id": user.id, - }, - stripe_account=user.stripe_connect_account_id, + # Validation checks + if price_amount is not None and price_amount <= 0: + logger.error("Validation failed: Price amount must be greater than 0") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Price amount must be greater than 0", ) - price = stripe.Price.create( - product=product.id, - currency=currency, - unit_amount=price_amount, - metadata={ - "inventory_quantity": str(inventory_quantity) if inventory_type == "finite" else "", - "preorder_release_date": str(preorder_release_date) if inventory_type == "preorder" else "", - }, - stripe_account=user.stripe_connect_account_id, - ) + # Create Stripe product if price is set + if price_amount is not None and user.stripe_connect_account_id: + try: + product = stripe.Product.create( + name=name, + description=description or "", + metadata={ + "user_id": user.id, + }, + stripe_account=user.stripe_connect_account_id, + ) - if is_reservation and reservation_deposit_amount: - deposit_price = stripe.Price.create( + price = stripe.Price.create( product=product.id, currency=currency, - unit_amount=reservation_deposit_amount, - metadata={"is_deposit": "true"}, + unit_amount=price_amount, + metadata={ + "inventory_quantity": str(inventory_quantity) if inventory_type == "finite" else "", + "preorder_release_date": str(preorder_release_date) if inventory_type == "preorder" else "", + }, stripe_account=user.stripe_connect_account_id, ) - deposit_price_id = deposit_price.id - - stripe_product_id = product.id - stripe_price_id = price.id - except stripe.StripeError as e: - logger.error(f"Stripe error: {str(e)}") - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=f"Error creating Stripe product: {str(e)}", - ) + if is_reservation and reservation_deposit_amount: + deposit_price = stripe.Price.create( + product=product.id, + currency=currency, + unit_amount=reservation_deposit_amount, + metadata={"is_deposit": "true"}, + stripe_account=user.stripe_connect_account_id, + ) + deposit_price_id = deposit_price.id - # Create the listing - listing = Listing.create( - name=name, - description=description or "", - child_ids=child_ids.split(",") if child_ids else [], - slug=slug, - user_id=user.id, - price_amount=price_amount, - currency=currency, - inventory_type=inventory_type, - inventory_quantity=inventory_quantity, - preorder_release_date=preorder_release_date, - is_reservation=is_reservation, - reservation_deposit_amount=reservation_deposit_amount, - stripe_product_id=stripe_product_id, - stripe_price_id=stripe_price_id, - stripe_deposit_price_id=deposit_price_id, - ) + stripe_product_id = product.id + stripe_price_id = price.id - await crud.add_listing(listing) - - # Handle photo uploads - if photos: - for photo in photos: - if photo.filename: - await crud.upload_artifact( - name=photo.filename, - file=photo, - listing=listing, - artifact_type="image", + except stripe.StripeError as e: + logger.error(f"Stripe error: {str(e)}") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Error creating Stripe product: {str(e)}", ) - else: - logger.warning("Skipping photo upload due to missing filename") - return NewListingResponse(listing_id=listing.id, username=user.username, slug=slug) + # Create the listing + listing = Listing.create( + name=name, + description=description or "", + child_ids=child_ids.split(",") if child_ids else [], + slug=slug, + user_id=user.id, + price_amount=price_amount, + currency=currency, + inventory_type=inventory_type, + inventory_quantity=inventory_quantity, + preorder_release_date=preorder_release_date, + is_reservation=is_reservation, + reservation_deposit_amount=reservation_deposit_amount, + stripe_product_id=stripe_product_id, + stripe_price_id=stripe_price_id, + stripe_deposit_price_id=deposit_price_id, + ) + + await crud.add_listing(listing) + logger.info("Listing created successfully") + + # Handle photo uploads + if photos: + for photo in photos: + if photo.filename: + await crud.upload_artifact( + name=photo.filename, + file=photo, + listing=listing, + artifact_type="image", + ) + else: + logger.warning("Skipping photo upload due to missing filename") + + return NewListingResponse(listing_id=listing.id, username=user.username, slug=slug) + + except HTTPException as e: + logger.error(f"HTTPException: {e.detail}") + raise + except Exception as e: + logger.error(f"Unexpected error: {str(e)}") + raise HTTPException(status_code=500, detail="Internal server error") @router.delete("/delete/{listing_id}", response_model=bool)