problem: can't view merit request detail

This commit is contained in:
gsovereignty
2024-07-14 14:50:16 +08:00
parent 26e8aee158
commit fc87a03408
6 changed files with 216 additions and 47 deletions

View File

@@ -0,0 +1,36 @@
<script lang="ts">
import * as Card from '$lib/components/ui/card/index.js';
import type { MeritRequest } from '@/event_helpers/merits';
import { ndk } from '@/ndk';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
export let merit:MeritRequest;
export let rocket:NDKEvent;
</script>
<Card.Root class="m-2">
<Card.Header>
<Card.Title>{merit.Problem()}</Card.Title>
<Card.Description>
<div class="flex flex-nowrap">
<Avatar
ndk={$ndk}
pubkey={merit.Pubkey}
class="h-10 w-10 flex-none rounded-full object-cover"
/>
<Name
ndk={$ndk}
pubkey={merit.Pubkey}
class="hidden max-w-32 truncate p-2 md:inline-block"
/>
</div>
</Card.Description>
</Card.Header>
<Card.Content></Card.Content>
<Card.Footer class="flex justify-between">
VOTE YES VOTE NO
</Card.Footer>
</Card.Root>

View File

@@ -0,0 +1,38 @@
<script lang="ts">
import { base } from '$app/paths';
import * as Breadcrumb from '$lib/components/ui/breadcrumb/index.js';
import type { MeritRequest } from '@/event_helpers/merits';
import { getRocketURL } from '@/helpers';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import MeritCard from './MeritCard.svelte';
export let rocket: NDKEvent;
export let merit: MeritRequest;
</script>
<div class="flex flex-col sm:gap-4">
<header class="flex items-center">
<Breadcrumb.Root class="flex">
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href={`${base}/rockets/${getRocketURL(rocket)}`}
>{rocket.getMatchingTags('d')[0][1]}</Breadcrumb.Link
>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href={`${base}/rockets/${getRocketURL(rocket)}`}>Merit Requests</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Page>{merit.Problem()}</Breadcrumb.Page>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
</header>
<main
class="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-2 lg:grid-cols-3 xl:grid-cols-3"
>
<MeritCard {rocket} {merit} />
</main>
</div>

View File

@@ -1,13 +1,14 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import * as Card from '@/components/ui/card';
import * as Table from '@/components/ui/table';
import { MeritRequest } from '@/event_helpers/merits';
import { ZapPurchase, type RocketProduct } from '@/event_helpers/rockets';
import { unixToRelativeTime } from '@/helpers';
import { ndk } from '@/ndk';
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
import { onDestroy, onMount } from 'svelte';
import { onDestroy } from 'svelte';
import { derived } from 'svelte/store';
export let rocket: NDKEvent;
@@ -23,14 +24,11 @@
_merits?.unsubscribe();
});
let merits = derived(_merits, ($merits) => {
let map = new Map<string, MeritRequest>();
for (let z of $merits) {
let meritRequest = new MeritRequest(z);
if (meritRequest.Valid(rocket)) {
if (meritRequest.BasicValidation()) {
map.set(meritRequest.ID, meritRequest);
}
}
@@ -43,19 +41,17 @@
<Card.Root class="sm:col-span-3">
<Card.Header class="px-7">
<Card.Title>Merit Requests</Card.Title>
<Card.Description
>Merit Requests</Card.Description
>
<Card.Description>Merit Requests</Card.Description>
</Card.Header>
<Card.Content>
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head>Contributor</Table.Head>
<Table.Head class="hidden md:table-cell text-left">Problem</Table.Head>
<Table.Head class="hidden text-left md:table-cell">Problem</Table.Head>
<Table.Head class="table-cell">Amount (Sats)</Table.Head>
<Table.Head class="table-cell">Merits</Table.Head>
<Table.Head class="hidden md:table-cell text-right">When</Table.Head>
<Table.Head class="hidden text-right md:table-cell">When</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
@@ -63,8 +59,9 @@
<Table.Row
on:click={() => {
console.log(merit.Request.rawEvent());
goto(`${base}/rockets/merits/${merit.ID}`);
}}
class="bg-accent cursor-pointer"
class="cursor-pointer bg-accent"
>
<Table.Cell>
<div class="flex flex-nowrap">
@@ -76,16 +73,14 @@
<Name
ndk={$ndk}
pubkey={merit.Pubkey}
class="hidden md:inline-block max-w-32 truncate p-2"
class="hidden max-w-32 truncate p-2 md:inline-block"
/>
</div>
</Table.Cell>
<Table.Cell class="hidden md:table-cell text-left"
>{merit.Problem()}</Table.Cell
>
<Table.Cell class="hidden text-left md:table-cell">{merit.Problem()}</Table.Cell>
<Table.Cell class="table-cell">{merit.Sats}</Table.Cell>
<Table.Cell class="table-cell">{merit.Merits}</Table.Cell>
<Table.Cell class="hidden md:table-cell text-right"
<Table.Cell class="hidden text-right md:table-cell"
>{unixToRelativeTime(merit.TimeStamp * 1000)}</Table.Cell
>
</Table.Row>

View File

@@ -1,5 +1,5 @@
import type { NDKEvent } from "@nostr-dev-kit/ndk";
import { getNumberFromTag } from "./rockets";
import type { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
import { getNumberFromTag } from './rockets';
export class MeritRequest {
ID: string;
@@ -8,33 +8,52 @@ export class MeritRequest {
Request: NDKEvent;
Pubkey: string;
TimeStamp: number;
Problem():string {
let _problem = ""
RocketTag: string | undefined; //31108:<pubkey>:<dtag>
Problem(): string {
let _problem = '';
//todo: handle 1971 problem tracker event tags somehow
for (let problem of this.Request.getMatchingTags("problem")) {
for (let problem of this.Request.getMatchingTags('problem')) {
if (problem && problem.length > 2) {
_problem = problem[2]
_problem = problem[2];
}
}
return _problem
return _problem;
}
IncludedInRocketState(rocket: NDKEvent): boolean {
return true
return true;
}
Valid(rocket: NDKEvent): boolean {
//todo: validate pubkey is in WoT
BasicValidation(): boolean {
//todo: make a ValidateAgainstRocket and check that pubkey is in WoT
let valid = true;
if (!(this.ID.length == 64 && this.Merits > 0 && this.Pubkey.length == 64 && this.TimeStamp && this.RocketTag)) {
valid = false
}
return valid;
}
RocketFilter():NDKFilter {
if (!this.BasicValidation()) {
return {}
}
return { '#d': [this.RocketTag?.split(":")[2]!], authors: [this.RocketTag?.split(":")[1]!], kinds: [31108 as number] }
}
constructor(request: NDKEvent) {
this.Request = request;
this.ID = request.id;
this.Pubkey = request.pubkey
this.Pubkey = request.pubkey;
if (this.Request.created_at) {
this.TimeStamp = this.Request.created_at
this.TimeStamp = this.Request.created_at;
}
for (let tag of this.Request.getMatchingTags('a')) {
if (tag && tag.length > 1) {
if (tag[1].split(':') && tag[1].split(':').length == 3) {
if ((tag[1].split(':')[0] = '31108')) {
this.RocketTag = tag[1];
}
}
}
}
this.Sats = getNumberFromTag("sats", request)
this.Merits = getNumberFromTag("merits", request)
this.Sats = getNumberFromTag('sats', request);
this.Merits = getNumberFromTag('merits', request);
}
}

View File

@@ -10,7 +10,6 @@
import ProductCard from '../../../components/ProductCard.svelte';
import ProductsForRocket from '../../../components/ProductsForRocket.svelte';
import RocketDashboard from '../../../components/RocketDashboard.svelte';
import Todo from '../../../components/Todo.svelte';
//flow if we only have a d-tag: fetch all 31108's with this d-tag, sort by WoT, put Nostrocket Name Service one at the top. Dedupe same rocket (same state, shadows) from multiple users, just show them all as everyone agreeing.
//second pass: fetch ignition event for each, rebuild current state and validate all proofs, compute votepower and display only the states with > 50%.

View File

@@ -0,0 +1,82 @@
<script lang="ts">
import { page } from '$app/stores';
import { MeritRequest } from '@/event_helpers/merits';
import { ndk } from '@/ndk';
import { NDKEvent } from '@nostr-dev-kit/ndk';
import type { ExtendedBaseType, NDKEventStore } from '@nostr-dev-kit/ndk-svelte';
import { onDestroy } from 'svelte';
import { derived, type Readable } from 'svelte/store';
import Heading from '../../../../components/Heading.svelte';
import MeritRequestDashboard from '../../../../components/MeritRequestDashboard.svelte';
let meritRequestID = $page.params.merit;
let meritRequest:MeritRequest | undefined;
$: {
if (meritRequestID.length == 64 && !meritRequest) {
$ndk.fetchEvent(meritRequestID).then(e=>{
if (e) {
meritRequest = new MeritRequest(e)
}
})
}
}
let rocketEvents: NDKEventStore<NDKEvent> | undefined;
let latestRocketEvent: Readable<ExtendedBaseType<NDKEvent> | undefined>;
onDestroy(() => {
rocketEvents?.unsubscribe();
});
$: {
if (meritRequest && meritRequest.BasicValidation()) {
//the user wants the latest valid state of this rocket
rocketEvents = $ndk.storeSubscribe(
[
meritRequest.RocketFilter()
],
{ subId: meritRequest.RocketTag!.split(":")[2] }
);
}
}
$: {
if (rocketEvents) {
latestRocketEvent = derived(rocketEvents, ($events) => {
if (rocketEvents) {
let sorted = $events.filter((e) => {
return e.kind == 31108;
});
sorted = sorted.toSorted((a, b) => {
return a.created_at - b.created_at;
});
return sorted[0];
}
return undefined;
});
if ($latestRocketEvent) {
}
}
}
//todo: check that this zap is not already included in the payment JSON for the product
//todo: list purchases on the rocket page (from product tags, as well as zap receipts that aren't yet included). Deduct total products available if not 0.
//todo: make the page flash or something and show each time someone buys the product.
//todo: split this out so that we can consume it for the payment page too (so that we know if there are really products left or they're all sold)
//todo: make store of all purchases (in rocket and zaps), sort by timestamp and render with profile of buyer
//todo: handle shadow events (fetch the shadowed event and render it instead)
</script>
{#if latestRocketEvent && $latestRocketEvent && meritRequest}
<MeritRequestDashboard rocket={$latestRocketEvent} merit={meritRequest} />
{:else}
<Heading title="Fetching events for this Merit Request" />
Merit Request ID: {$page.params.merit} <br />
{/if}