diff --git a/internal/domains/accounts/mocks.go b/internal/domains/accounts/mocks.go index b2eacfd..f5421c9 100644 --- a/internal/domains/accounts/mocks.go +++ b/internal/domains/accounts/mocks.go @@ -365,6 +365,41 @@ func (db *Store) UpdateMockListing(ctx context.Context, listing MockListing) err return nil } +func (db *Store) DeleteMockListing(ctx context.Context, ids AccountShopListingIDs) error { + _, listingTableName, err := getMockShopAndListingsTableNames(ids.Platform) + if err != nil { + return err + } + + tag, err := db.db.Exec( + ctx, + fmt.Sprintf( + ` + DELETE FROM + %s + WHERE + account_id = @account_id + AND shop_id = @shop_id + AND listing_id = @listing_id + `, + listingTableName, + ), + pgx.NamedArgs{ + "account_id": ids.AccountID, + "shop_id": ids.ShopID, + "listing_id": ids.ListingID, + }, + ) + if err != nil { + return fmt.Errorf("failed to perform query: %w", err) + } + if tag.RowsAffected() == 0 { + return fmt.Errorf("%w: listing not found", consts.ErrNotFound) + } + + return nil +} + func (db *Store) ListMockListingsForShop(ctx context.Context, acctID int64, platform Platform, shopID string) ([]MockListing, error) { shopTableName, listingsTableName, err := getMockShopAndListingsTableNames(platform) if err != nil { diff --git a/internal/domains/accounts/store_with_context.go b/internal/domains/accounts/store_with_context.go index 58dcb59..e9f43dd 100644 --- a/internal/domains/accounts/store_with_context.go +++ b/internal/domains/accounts/store_with_context.go @@ -72,6 +72,10 @@ func (v_ctx *StoreWithContext) UpdateMockListing(listing MockListing) error { return v_ctx.Store.UpdateMockListing(v_ctx.ctx, listing) } +func (v_ctx *StoreWithContext) DeleteMockListing(ids AccountShopListingIDs) error { + return v_ctx.Store.DeleteMockListing(v_ctx.ctx, ids) +} + func (v_ctx *StoreWithContext) ListMockListingsForShop(acctID int64, platform Platform, shopID string) ([]MockListing, error) { return v_ctx.Store.ListMockListingsForShop(v_ctx.ctx, acctID, platform, shopID) } diff --git a/internal/server/api/accounts/router.go b/internal/server/api/accounts/router.go index c196f23..05d5402 100644 --- a/internal/server/api/accounts/router.go +++ b/internal/server/api/accounts/router.go @@ -44,6 +44,7 @@ func Routes( mockShops := platformGroup.Group("/shops/mocks/:shop-id") mockShops.POST("/listings", response.Handler(as.addMockListing)) mockShops.PUT("/listings/:listing-id", response.Handler(as.updateMockListing)) + mockShops.DELETE("/listings/:listing-id", response.Handler(as.deleteMockListing)) syncGroups := r.Group("/:acctID/inventory/sync-groups") syncGroups.POST("", pub.Publish("/:acctID/inventory/sync-groups"), response.Handler(as.saveNewSyncGroup)) @@ -344,12 +345,43 @@ func (s *accountSubrouter) updateMockListing(c *gin.Context) (response.Response, }, ) if err != nil { - return nil, fmt.Errorf("failed to update new listing: %w", err) + return nil, fmt.Errorf("failed to update listing: %w", err) } return response.StatusOK(), nil } +// DELETE /:acctID/platforms/:platform/shops/mocks/:shop-id/listings/:listing-id +func (s *accountSubrouter) deleteMockListing(c *gin.Context) (response.Response, error) { + acctID := auth.GetIdentity(c).Account.AccountID + + var ( + platform accounts.Platform + shopID string + listingID string + ) + + err := param.Path("platform", param.Platform(&platform)). + Path("shop-id", param.Text(&shopID)). + Path("listing-id", param.Text(&listingID)). + Unmarshal(c) + if err != nil { + return nil, err + } + + err = s.accts.DeleteMockListing( + c, + accounts.NewAccountIDs(acctID). + ShopID(platform, shopID). + ListingID(listingID), + ) + if err != nil { + return nil, fmt.Errorf("failed to delete listing: %w", err) + } + + return response.StatusNoContent(), nil +} + func lowerSnakeCase(s accounts.Platform) string { return strings.ToLower(strings.Join(strings.Split(string(s), " "), "_")) } diff --git a/internal/server/response/write.go b/internal/server/response/write.go index f62c98a..3cc0f9b 100644 --- a/internal/server/response/write.go +++ b/internal/server/response/write.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "ruben/inventory2/internal/consts" "github.com/gin-gonic/gin" ) @@ -46,11 +47,23 @@ func HandleErrors(c *gin.Context) { } } if !ok { - var err error + var ( + err error + status int + statusFound bool + ) for _, e := range c.Errors { err = errors.Join(err, e) + if !statusFound { + status, statusFound = mapErrorConstantsToStatus(e) + } } - c.String(http.StatusInternalServerError, err.Error()) + + if !statusFound { + status = http.StatusInternalServerError + } + + c.String(status, err.Error()) return } @@ -131,3 +144,24 @@ func GetStatusFromError(err error) int { return status } + +func mapErrorConstantsToStatus(err error) (int, bool) { + for { + switch err { + case consts.ErrBadRequest: + return http.StatusBadRequest, true + case consts.ErrNotFound: + return http.StatusNotFound, true + case consts.ErrConflict: + return http.StatusConflict, true + default: + werr, ok := err.(interface { + Unwrap() error + }) + if !ok { + return 0, false + } + err = werr.Unwrap() + } + } +} diff --git a/styles/index.css b/styles/index.css index 60d3a4e..d99a0be 100644 --- a/styles/index.css +++ b/styles/index.css @@ -536,6 +536,9 @@ .italic { font-style: italic; } + .no-underline { + text-decoration-line: none; + } .underline { text-decoration-line: underline; } @@ -764,6 +767,13 @@ } } } + .hover\:no-underline { + &:hover { + @media (hover: hover) { + text-decoration-line: none; + } + } + } .hover\:underline { &:hover { @media (hover: hover) { diff --git a/templates/pages/accounts/{acctID.int64}/platforms/{platform}/shops/mocks/{shopID}/index.html.tmpl b/templates/pages/accounts/{acctID.int64}/platforms/{platform}/shops/mocks/{shopID}/index.html.tmpl index 4846e00..4de97a6 100644 --- a/templates/pages/accounts/{acctID.int64}/platforms/{platform}/shops/mocks/{shopID}/index.html.tmpl +++ b/templates/pages/accounts/{acctID.int64}/platforms/{platform}/shops/mocks/{shopID}/index.html.tmpl @@ -297,9 +297,12 @@ id="listing-{{$listing.ListingID}}" class=" p-[1em] - grid grid-cols-[max-content_1fr] gap-x-[1em] bg-card rounded-lg + + flex + flex-col + items-stretch " _=" on click @@ -318,33 +321,50 @@ remove .border from me " > - - Name: - - - {{ $listing.Name }} - +
| + Name: + | ++ {{ $listing.Name }} + | +
|---|---|
| + SKU: + | ++ {{ $listing.SKU }} + | +
| + Description: + | ++ {{ $listing.Description }} + | +
| + Count: + | ++ {{ $listing.Count }} + | +