- Fix all 12 no-explicit-any (NPool, NostrEvent[], LabProfile, structural Cluster type, explicit SkateSpot cast) -> 0 remaining - Remove unused imports/vars across 48 files (manual + a verified codemod for unused import specifiers only); tsc + tests + boot smoke all green - Warning backlog: 182 -> 76 (remaining: ~55 no-unused-vars locals, 14 react-hooks/exhaustive-deps, 7 react-refresh) - AGENTS.md baseline updated
52 lines
2 KiB
TypeScript
52 lines
2 KiB
TypeScript
import { useQueryClient } from '@tanstack/react-query';
|
|
import { useNostrPublish } from '@/hooks/useNostrPublish';
|
|
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
|
import { MARKETPLACE_ITEM_KIND } from '@/lib/types';
|
|
import type { NostrEvent } from '@nostrify/nostrify';
|
|
|
|
/**
|
|
* Flip a NIP-99 gear listing's status (active ⇄ sold).
|
|
*
|
|
* A listing (kind 30402) is addressable, so re-publishing REPLACES the whole
|
|
* tag set. We therefore start from the original event's tags and change ONLY
|
|
* the `status` tag — every other tag (title, price, images, size, spot `a`
|
|
* ref, geohash, expiration, published_at, category `t` tags…) is carried
|
|
* through untouched. Rebuilding from scratch here would wipe the listing's
|
|
* photos and price, so we deliberately don't.
|
|
*/
|
|
export function useMarkListingSold() {
|
|
const { mutateAsync: createEvent, isPending } = useNostrPublish();
|
|
const { user } = useCurrentUser();
|
|
const queryClient = useQueryClient();
|
|
|
|
const mutate = async ({
|
|
event,
|
|
status,
|
|
}: {
|
|
/** The original listing event. */
|
|
event: NostrEvent;
|
|
/** New status — 'sold' to mark sold, 'active' to relist. */
|
|
status: 'sold' | 'active';
|
|
}) => {
|
|
if (!user) throw new Error('You must be logged in.');
|
|
if (user.pubkey !== event.pubkey) throw new Error('You can only update your own listing.');
|
|
if (event.kind !== MARKETPLACE_ITEM_KIND) throw new Error('Not a gear listing.');
|
|
|
|
// Preserve every tag except `status`, then set the new status.
|
|
const tags = event.tags.filter(([name]) => name !== 'status');
|
|
tags.push(['status', status]);
|
|
|
|
await createEvent({
|
|
kind: MARKETPLACE_ITEM_KIND,
|
|
content: event.content,
|
|
tags,
|
|
});
|
|
|
|
// Refresh marketplace + seller views so the badge updates immediately.
|
|
queryClient.invalidateQueries();
|
|
};
|
|
|
|
return { markSold: (event: NostrEvent) => mutate({ event, status: 'sold' }),
|
|
relist: (event: NostrEvent) => mutate({ event, status: 'active' }),
|
|
isPending };
|
|
}
|