From a3ae872e9d39a7612fa78836ee6c716762a23e23 Mon Sep 17 00:00:00 2001 From: Angel Beltran Date: Tue, 17 Feb 2026 19:35:12 -0700 Subject: [PATCH] updated mock sync group accordions: editing state; cancel editing --- domains/accounts/accounts.go | 32 ++++- server/api/accounts/router.go | 25 +++- styles/index.css | 27 ++++ .../{syncGroupID.int64}/list-item.html.tmpl | 123 +++++++++++++++--- .../{acctID.int64}/inventory/mock.html.tmpl | 1 - 5 files changed, 185 insertions(+), 23 deletions(-) diff --git a/domains/accounts/accounts.go b/domains/accounts/accounts.go index d6e89e9..3224a5f 100644 --- a/domains/accounts/accounts.go +++ b/domains/accounts/accounts.go @@ -501,7 +501,7 @@ func (db *Store) DeleteMockSyncGroup(ctx context.Context, acctID, syncGroupID in return nil } -func (db *Store) StartEditingMockSyncGroup(ctx context.Context, acctID, syncGroupID int64) (int64, bool, error) { +func (db *Store) StartEditingMockSyncGroup(ctx context.Context, acctID, syncGroupID int64) (prevSyncGroupID int64, prevSyncGroupExists bool, err error) { rows, err := db.db.Query( ctx, ` @@ -561,6 +561,36 @@ func (db *Store) StartEditingMockSyncGroup(ctx context.Context, acctID, syncGrou return v.Int64, v.Valid, nil } +func (db *Store) CancelEditingOfMockSyncGroupForAccount(ctx context.Context, acctID int64) (prevSyncGroupID int64, prevSyncGroupExists bool, err error) { + rows, err := db.db.Query( + ctx, + ` + DELETE FROM + mock.sync_group_editing + WHERE + account_id = @account_id + RETURNING + sync_group_id + `, + pgx.NamedArgs{ + "account_id": acctID, + }, + ) + if err != nil { + return 0, false, fmt.Errorf("failed to perform query: %w", err) + } + + prevSyncGroupID, err = pgx.CollectExactlyOneRow(rows, pgx.RowTo[int64]) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return 0, false, nil + } + return 0, false, fmt.Errorf("failed to scan rows: %w", err) + } + + return prevSyncGroupID, true, nil +} + func (db *Store) MockSyncGroupIsBeingEdited(ctx context.Context, acctID, syncGroupID int64) (bool, error) { rows, err := db.db.Query( ctx, diff --git a/server/api/accounts/router.go b/server/api/accounts/router.go index ea2c6e0..d43a12c 100644 --- a/server/api/accounts/router.go +++ b/server/api/accounts/router.go @@ -59,6 +59,7 @@ func Routes( mockSyncGroups.POST("", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.saveNewMockSyncGroup)) mockSyncGroups.DELETE("/:syncGroupID", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.deleteMockSyncGroup)) mockSyncGroups.PUT("/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/editing"), response.Handler(as.selectMockSyncGroupForEditing)) + mockSyncGroups.DELETE("/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/editing"), response.Handler(as.cancelMockSyncGroupEdits)) mockDraftListings := mockSyncGroups.Group("/draft/listings", pub.Publish("/:acctID/inventory/sync-groups/mock/draft/listings")) mockDraftListings.POST("", response.Handler(as.createMockSyncGroupListingDraft)) @@ -552,7 +553,7 @@ func (s *accountSubrouter) selectMockSyncGroupForEditing(c *gin.Context) (respon prevSyncGroupID, ok, err := s.accts.StartEditingMockSyncGroup(ctx, acctID, syncGroupID) if err != nil { - return nil, response.Errorf("failed to save new mock sync group: %w", response.ErrorFromConstant(err)) + return nil, response.Errorf("failed to start editing mock sync group: %w", response.ErrorFromConstant(err)) } // emit events indicating sync groups being edited and no longer being edited @@ -570,6 +571,28 @@ func (s *accountSubrouter) selectMockSyncGroupForEditing(c *gin.Context) (respon return response.StatusOK(), nil } +// DELETE /:acctID/inventory/sync-groups/mock/editing +func (s *accountSubrouter) cancelMockSyncGroupEdits(c *gin.Context) (response.Response, error) { + r := c.Request + ctx := r.Context() + acctID := auth.GetIdentity(ctx).Account.AccountID + + prevSyncGroupID, deleted, err := s.accts.CancelEditingOfMockSyncGroupForAccount(ctx, acctID) + if err != nil { + return nil, response.Errorf("failed to stop editing mock sync group: %w", response.ErrorFromConstant(err)) + } + + // emit events indicating sync groups being edited and no longer being edited + if deleted { + evt := fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d", acctID, prevSyncGroupID) + if err := s.pub.Push(c, acctID, evt); err != nil { + s.log.Errorf("failed to publish mock sync group editing events: %v", err) + } + } + + return response.StatusOK(), nil +} + func lowerSnakeCase(s accounts.Platform) string { return strings.ToLower(strings.Join(strings.Split(string(s), " "), "_")) } diff --git a/styles/index.css b/styles/index.css index 2f7066b..7f52acb 100644 --- a/styles/index.css +++ b/styles/index.css @@ -363,9 +363,15 @@ .my-\[0\.5em\] { margin-block: 0.5em; } + .my-\[1em\] { + margin-block: 1em; + } .my-\[1rem\] { margin-block: 1rem; } + .mt-\[0\.5em\] { + margin-top: 0.5em; + } .mt-\[0\.25em\] { margin-top: 0.25em; } @@ -378,9 +384,18 @@ .mt-\[3em\] { margin-top: 3em; } + .mb-\[-0\.5em\] { + margin-bottom: -0.5em; + } + .mb-\[-1em\] { + margin-bottom: -1em; + } .mb-\[0\.5em\] { margin-bottom: 0.5em; } + .mb-\[0\] { + margin-bottom: 0; + } .mb-\[1\.25rem\] { margin-bottom: 1.25rem; } @@ -459,6 +474,9 @@ .flex-grow { flex-grow: 1; } + .flex-grow-\[1\] { + flex-grow: 1; + } .grow { flex-grow: 1; } @@ -589,12 +607,21 @@ .bg-accent { background-color: var(--accent); } + .bg-accent-secondary { + background-color: var(--accent-secondary); + } .bg-background { background-color: var(--background); } .bg-card { background-color: var(--card); } + .bg-foreground { + background-color: var(--foreground); + } + .bg-primary { + background-color: var(--primary); + } .p-\[0\.5em\] { padding: 0.5em; } diff --git a/templates/components/accounts/{acctID.int64}/inventory/sync-groups/mock/{syncGroupID.int64}/list-item.html.tmpl b/templates/components/accounts/{acctID.int64}/inventory/sync-groups/mock/{syncGroupID.int64}/list-item.html.tmpl index 858513d..1ee3fbe 100644 --- a/templates/components/accounts/{acctID.int64}/inventory/sync-groups/mock/{syncGroupID.int64}/list-item.html.tmpl +++ b/templates/components/accounts/{acctID.int64}/inventory/sync-groups/mock/{syncGroupID.int64}/list-item.html.tmpl @@ -2,10 +2,9 @@ {{- $syncGroupID := .PathParams.syncGroupID }} {{- $acctID := .PathParams.acctID }} -{{- $open := false }} -{{- if .Request }} - {{- $open = eq (.Request.URL.Query.Get "open") "true" }} -{{- end }} +{{- $isBeingEditing := .Accounts.MockSyncGroupIsBeingEdited $acctID $syncGroupID }} + +{{- $open := or $isBeingEditing (and .Request (eq (.Request.URL.Query.Get "open") "true")) }} {{- $grp := .SyncGroup }} {{- if not $grp }} @@ -29,10 +28,21 @@ {{- end }} - {{- define "sync-group-accordion-body" }} + {{- define "sync-group-accordion-editing-header" }} +
+

+ {{ .Group.Name }} +

+
+ Editing +
+
+ {{- end }} + + {{- define "sync-group-accordion-static-body" }} {{- $acctID := .Identity.Account.AccountID }} {{- $syncGroupID := .Group.SyncGroupID }} - +
@@ -71,34 +81,107 @@
-
- {{- $isBeingEditing := .Accounts.MockSyncGroupIsBeingEdited $acctID $syncGroupID }} - {{- if not $isBeingEditing }} - {{- component "button" - "Class" "mt-[1em]" - "Text" "Edit Group" - "HXPut" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID) - "HXVals" (printf `js:{"syncGroupID":%d}` $syncGroupID) - "HXSwap" "none" - }} - {{- end }} +
+ {{- component "button" + "Class" "mt-[1em]" + "Text" "Edit" + "HXPut" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID) + "HXVals" (printf `js:{"syncGroupID":%d}` $syncGroupID) + "HXSwap" "none" + }} {{- component "button" "Class" "mt-[1em]" - "Text" "Delete Group" + "Text" "Delete" "HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/%d" $acctID $syncGroupID) "HXSwap" "none" }}
{{- end }} + {{- define "sync-group-accordion-form-body" }} + {{- $acctID := .Identity.Account.AccountID }} + {{- $syncGroupID := .Group.SyncGroupID }} +
+ + + + + + + + + + + {{- $dot := . }} + {{- range $listing := .Group.Listings }} + + {{- $val := $dot.Accounts.GetMockListing $acctID $listing.Platform $listing.ShopID $listing.ListingID }} + + + + + + {{- end }} + +
+ Name + + SKU + + Description + + Count +
+ {{ $val.Name }} + + {{ $val.SKU }} + + {{ $val.Description }} + + {{ $val.Count }} +
+ +
+ {{/* TODO: implement saving */}} + {{- component "button" + "Class" "mt-[1em]" + "Text" "Save" + "HXSwap" "none" + }} + + {{- component "button" + "Class" "mt-[1em]" + "Text" "Cancel" + "HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID) + "HXSwap" "none" + }} +
+
+ {{- end }} + + {{- $accordionHeader := "sync-group-accordion-header" }} + {{- $accordionBody := "sync-group-accordion-static-body" }} + {{- $summaryClass := "" }} + {{- if $isBeingEditing }} + {{- $accordionBody = "sync-group-accordion-form-body" }} + {{- $accordionHeader = "sync-group-accordion-editing-header" }} + {{- $summaryClass = "bg-accent-secondary" }} + {{- end }} {{ component "accordion" "Name" "sync-group-page" "Open" $open "GroupName" "sync-group" "Group" $grp "Smooth" false - "#accordion-header" "sync-group-accordion-header" - "#accordion-body" "sync-group-accordion-body" + "SummaryClass" $summaryClass + "#accordion-header" $accordionHeader + "#accordion-body" $accordionBody }} diff --git a/templates/pages/accounts/{acctID.int64}/inventory/mock.html.tmpl b/templates/pages/accounts/{acctID.int64}/inventory/mock.html.tmpl index 858dd61..ae9fc5b 100644 --- a/templates/pages/accounts/{acctID.int64}/inventory/mock.html.tmpl +++ b/templates/pages/accounts/{acctID.int64}/inventory/mock.html.tmpl @@ -47,7 +47,6 @@ > {{ component "accordion" "Name" "sync-group-page" - "Open" true "Class" ` mx-[1em] mb-[1em]