package store import ( "context" "fmt" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgxpool" ) // Item is the projection of an items row. type Item struct { ID uuid.UUID `json:"id"` ListID uuid.UUID `json:"list_id"` Name string `json:"name"` Quantity *string `json:"quantity,omitempty"` Checked bool `json:"checked"` SortOrder *int `json:"sort_order,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"deleted_at,omitempty"` HLCTS int64 `json:"hlc_ts"` ClientID *uuid.UUID `json:"client_id,omitempty"` CheckedAt *time.Time `json:"checked_at,omitempty"` } // ItemStore provides read access to the items projection. type ItemStore struct { pool *pgxpool.Pool } // NewItemStore creates an ItemStore backed by the given pool. func NewItemStore(pool *pgxpool.Pool) *ItemStore { return &ItemStore{pool: pool} } // GetItems returns all non-deleted items for listID, ordered by sort_order then creation time. func (s *ItemStore) GetItems(ctx context.Context, listID uuid.UUID) ([]Item, error) { rows, err := s.pool.Query(ctx, ` SELECT id, list_id, name, quantity, checked, sort_order, created_at, updated_at, hlc_ts, client_id, checked_at FROM items WHERE list_id = $1 AND deleted_at IS NULL ORDER BY sort_order ASC NULLS LAST, created_at ASC`, listID, ) if err != nil { return nil, fmt.Errorf("itemstore: get items: %w", err) } defer rows.Close() var items []Item for rows.Next() { var it Item if err := rows.Scan( &it.ID, &it.ListID, &it.Name, &it.Quantity, &it.Checked, &it.SortOrder, &it.CreatedAt, &it.UpdatedAt, &it.HLCTS, &it.ClientID, &it.CheckedAt, ); err != nil { return nil, fmt.Errorf("itemstore: scan item row: %w", err) } items = append(items, it) } return items, rows.Err() }