The wallet storefront listed products in creation order — its purchases and its
chip-exchange values were unsorted, unlike the admin console and the public offer.
Extract the ordering (chip packs first by rouble price, then chip-priced values
grouped hints → no-ads → combo → tournament and by chip price) into one comparator,
compareCatalogRank over a small rank key, and apply it at all three sites
(projectCatalog, projectOfferPricing, SortAdminCatalog) — so the subgroup ranking
(valueGroup) and the full order now live in one place. The rewarded "watch for
chips" CTA is a wallet-driven element rendered above the packs, so it is unaffected
and stays on top.
Also add the admin catalog active/all toggle: AdminCatalog takes includeInactive,
the console shows active products by default and ?all=1 lists archived ones too
(the detail and grant forms keep loading all products).
Tests: a storefront canonical-order unit test (reproduced the unsorted bug first);
an integration test for the active/all toggle. Existing offer/admin order tests
unchanged — behaviour preserved.
The /_gm console gains a Catalog editor — the source of truth for products.
Create / edit / archive-unarchive products, their atom composition and per-rail
prices (RUB via direct / VOTE via vk / XTR via telegram / CHIP value), and
hard-delete only a never-transacted product (an order or ledger reference forces
archive-only, backed by the FK RESTRICT). The archived flag reuses the existing
product.active. Activation revalidates the sellable shape — a pack (the chips
atom ⇒ a money price per rail, chips-only) or a value (no chips ⇒ a CHIP price);
a tournament-bearing product is composable but never sellable yet.
Backed by payments AdminCatalog / CreateProduct / UpdateProduct /
SetProductActive / DeleteProduct + a pure validateProduct.
Tests: validateProduct (pack / value / tournament / duplicate / shape); the
console editor end to end (create, edit, archive, delete-if-clean, refuse a
transacted delete).