feat: add name and description fields to ListingAccount; update form, table, detail, dashboard

This commit is contained in:
thesn10
2026-06-25 20:21:28 +02:00
parent ca1c0b1cd8
commit 555598535d
16 changed files with 765 additions and 576 deletions

View File

@@ -26,6 +26,8 @@ interface FormState {
price: string
quantity: string
oracle: string
name: string
description: string
metadataUri: string
alts: AltEntry[]
resolvers: string[]
@@ -39,6 +41,8 @@ function blank(): FormState {
price: '',
quantity: '',
oracle: '',
name: '',
description: '',
metadataUri: '',
alts: [],
resolvers: [],
@@ -148,6 +152,8 @@ export function CreateListingForm({ editPk }: Props) {
: (Number(d.price) / 1e9).toString(),
quantity: String(d.quantity),
oracle: isSome(d.canonicalOracle) ? d.canonicalOracle.value : '',
name: d.name ?? '',
description: d.description ?? '',
metadataUri: d.metadataUri ?? '',
alts: d.altCurrencies.map((a) => ({
currency:
@@ -265,6 +271,8 @@ export function CreateListingForm({ editPk }: Props) {
altCurrencies,
acceptedResolvers,
quantity: quantityN,
name: form.name,
description: form.description,
metadataUri: form.metadataUri,
})
await sendTx([ix as never], [['listings'], ['listing', editPk]], 'update_listing')
@@ -278,6 +286,8 @@ export function CreateListingForm({ editPk }: Props) {
altCurrencies,
acceptedResolvers,
quantity: quantityN,
name: form.name,
description: form.description,
metadataUri: form.metadataUri,
})
await sendTx([ix as never], [['listings']], 'create_listing')
@@ -337,6 +347,16 @@ export function CreateListingForm({ editPk }: Props) {
gap: 22,
}}
>
{/* NAME + DESCRIPTION */}
<div>
<label style={LABEL}>NAME <span style={{ fontWeight: 400, textTransform: 'none' }}>(max 64 chars)</span></label>
<input value={form.name} onChange={set('name')} placeholder="e.g. Mechanical Keyboard Kit" style={INPUT} maxLength={64} />
</div>
<div>
<label style={LABEL}>DESCRIPTION <span style={{ fontWeight: 400, textTransform: 'none' }}>(max 256 chars)</span></label>
<input value={form.description} onChange={set('description')} placeholder="Short description of what you're selling" style={INPUT} maxLength={256} />
</div>
{/* CANONICAL CURRENCY */}
<div>
<label style={LABEL}>CANONICAL CURRENCY</label>

View File

@@ -168,7 +168,7 @@ export function Dashboard() {
>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontWeight: 600, fontSize: 15 }}>
Listing #{String(l.data.listingId)}
{l.data.name || `Listing #${String(l.data.listingId)}`}
</span>
<Badge color={sc.color} bg={sc.bg}>
{l.data.isActive ? 'Active' : 'Inactive'}

View File

@@ -54,14 +54,16 @@ export function ListingDetail({ pk, walletAddress, onUpdate, onClose, onPlaceOrd
LISTING ACCOUNT · #{String(d.listingId)}
</div>
<h1 style={{ margin: 0, fontSize: 26, fontWeight: 700, letterSpacing: '-.02em' }}>
{abbrev(pk)}
{d.name || abbrev(pk)}
</h1>
</div>
<Badge color={sc.color} bg={sc.bg}>{d.isActive ? 'Active' : 'Inactive'}</Badge>
</div>
{d.metadataUri && (
{(d.description || d.metadataUri) && (
<p style={{ margin: '0 0 24px', fontSize: 14, color: 'var(--mut)', maxWidth: 620, lineHeight: 1.55 }}>
<a href={d.metadataUri} target="_blank" rel="noreferrer" style={{ color: 'var(--acc2light)' }}>{d.metadataUri}</a>
{d.description || (
<a href={d.metadataUri} target="_blank" rel="noreferrer" style={{ color: 'var(--acc2light)' }}>{d.metadataUri}</a>
)}
</p>
)}
@@ -70,20 +72,22 @@ export function ListingDetail({ pk, walletAddress, onUpdate, onClose, onPlaceOrd
<div style={{ background: 'var(--bg2)', border: '1px solid var(--bd)', borderRadius: 'var(--radius)', padding: '8px 22px 16px' }}>
<div style={{ fontSize: 11, letterSpacing: '.13em', color: 'var(--mut)', fontWeight: 600, padding: '14px 0 4px' }}>ACCOUNT FIELDS</div>
<FieldRow label="Address"><MonoChip value={abbrev(pk)} onCopy={() => navigator.clipboard.writeText(pk)} /></FieldRow>
<FieldRow label="Listing ID"><span style={{ fontSize: 13.5, fontWeight: 600 }}>#{String(d.listingId)}</span></FieldRow>
<FieldRow label="Seller"><MonoChip value={abbrev(d.seller)} onCopy={() => navigator.clipboard.writeText(d.seller)} onClick={() => router.push(`/search?q=${d.seller}`)} /></FieldRow>
<FieldRow label="Price"><span style={{ fontSize: 13.5, fontWeight: 600 }}>{fmtListingPrice()}</span></FieldRow>
<FieldRow label="Currency">
<span style={{ fontFamily: 'var(--font-mono)', fontSize: 12.5 }}>
{d.canonicalCurrency.__kind === 'Sol' ? 'SOL (native)' : `SPL · ${abbrev((d.canonicalCurrency as { mint: string }).mint)}`}
<FieldRow label="Listing ID"><span style={{ fontFamily: 'var(--font-mono)', fontSize: 13 }}>#{String(d.listingId)}</span></FieldRow>
<FieldRow label="Canonical Currency">
<span style={{ fontWeight: 600, fontSize: 13 }}>
{d.canonicalCurrency.__kind === 'Sol' ? 'SOL' : `SPL · ${abbrev((d.canonicalCurrency as { mint: string }).mint)}`}
</span>
</FieldRow>
{canonicalOracleAddr && (
<FieldRow label="Oracle">
<MonoChip value={abbrev(canonicalOracleAddr)} onCopy={() => navigator.clipboard.writeText(canonicalOracleAddr)} />
</FieldRow>
)}
<FieldRow label="Price"><span style={{ fontWeight: 700, fontSize: 13.5 }}>{fmtListingPrice()}</span></FieldRow>
<FieldRow label="Canonical Oracle">
{canonicalOracleAddr
? <MonoChip value={abbrev(canonicalOracleAddr)} onCopy={() => navigator.clipboard.writeText(canonicalOracleAddr)} />
: <span style={{ fontSize: 13, color: 'var(--mut)' }}>None priced directly</span>
}
</FieldRow>
<FieldRow label="Status"><Badge color={sc.color} bg={sc.bg}>{d.isActive ? 'Active' : 'Inactive'}</Badge></FieldRow>
<FieldRow label="Bump"><span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--mut)' }}>{d.bump}</span></FieldRow>
{d.metadataUri && (
<>

View File

@@ -108,7 +108,7 @@ export function ListingsTable() {
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 600, fontSize: 14, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
{l.data.metadataUri || abbrev(l.address)}
{l.data.name || abbrev(l.address)}
</div>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--mut)', marginTop: 3 }}>
#{String(l.data.listingId)} · {abbrev(l.address)}