b6af682381
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 23s
CI / ui (pull_request) Has been skipped
CI / conformance (pull_request) Successful in 11s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m49s
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.
46 lines
3.1 KiB
Go Template
46 lines
3.1 KiB
Go Template
{{define "content" -}}
|
||
<h1>Product catalog</h1>
|
||
{{with .Data}}
|
||
<p class="note">A <strong>pack</strong> funds chips (a money price per rail — RUB via direct, VOTE via vk, XTR via telegram); a <strong>value</strong> buys benefits with chips (a CHIP price). Archived products are hidden from players but still credit an in-flight payment and can be granted. A product with transactions can only be archived, not deleted. Amounts are in minor units (RUB kopecks; VOTE/XTR/CHIP whole). The <code>tournament</code> atom is not sellable yet — keep such a product archived.</p>
|
||
<section class="panel"><h2>Add product</h2>
|
||
<form class="form col" method="post" action="/_gm/catalog">
|
||
<label>Title <input type="text" name="title" maxlength="120" required></label>
|
||
<fieldset><legend>Atoms (quantity; blank = none)</legend>
|
||
<label>Chips <input type="number" name="chips" min="0"></label>
|
||
<label>Hints <input type="number" name="hints" min="0"></label>
|
||
<label>No-ads days <input type="number" name="noads" min="0"></label>
|
||
<label>Tournament <input type="number" name="tournament" min="0"></label>
|
||
</fieldset>
|
||
<fieldset><legend>Prices (minor units; blank = none)</legend>
|
||
<label>RUB — direct (kopecks) <input type="number" name="price_rub" min="0"></label>
|
||
<label>VOTE — vk <input type="number" name="price_vote" min="0"></label>
|
||
<label>XTR — telegram <input type="number" name="price_star" min="0"></label>
|
||
<label>CHIP — value <input type="number" name="price_chip" min="0"></label>
|
||
</fieldset>
|
||
<label><input type="checkbox" name="active" value="true"> Active (on sale)</label>
|
||
<div><button type="submit">Add</button></div>
|
||
</form>
|
||
</section>
|
||
<section class="panel"><h2>Products</h2>
|
||
<p class="note">Showing {{if .ShowAll}}<strong>all</strong> products (active + archived) — <a href="/_gm/catalog">active only</a>{{else}}<strong>active</strong> products — <a href="/_gm/catalog?all=1">show all (incl. archived)</a>{{end}}.</p>
|
||
<table class="list">
|
||
<thead><tr><th>Title</th><th>Status</th><th>Atoms</th><th>Prices</th><th></th></tr></thead>
|
||
<tbody>
|
||
{{range .Products}}
|
||
<tr>
|
||
<td><a href="/_gm/catalog/{{.ID}}">{{.Title}}</a></td>
|
||
<td>{{if .Active}}<span class="ok">active</span>{{else}}<span class="warn">archived</span>{{end}}{{if .Transacted}} <span class="pill">transacted</span>{{end}}</td>
|
||
<td>{{range .Atoms}}<code>{{.Atom}}×{{.Quantity}}</code> {{end}}</td>
|
||
<td>{{range .Prices}}<code>{{.Currency}}{{if .Method}}/{{.Method}}{{end}} {{.Amount}}</code> {{end}}</td>
|
||
<td class="row-actions">
|
||
<form class="form" method="post" action="/_gm/catalog/{{.ID}}/archive"><input type="hidden" name="active" value="{{if .Active}}false{{else}}true{{end}}"><button type="submit">{{if .Active}}Archive{{else}}Unarchive{{end}}</button></form>
|
||
{{if not .Transacted}}<form class="form" method="post" action="/_gm/catalog/{{.ID}}/delete" onsubmit="return confirm('Delete this product? It has never been transacted, so this is safe and permanent.')"><button type="submit">Delete</button></form>{{end}}
|
||
</td>
|
||
</tr>
|
||
{{else}}<tr><td colspan="5"><span class="note">no products</span></td></tr>{{end}}
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
{{end}}
|
||
{{- end}}
|