mirror of
https://github.com/aljazceru/hypergolic.git
synced 2025-12-18 14:04:21 +01:00
problem: not clear when someone makes a purchase
resolve https://github.com/nostrocket/hypergolic/issues/94
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
import { ndk } from '@/ndk.js';
|
import { ndk } from '@/ndk.js';
|
||||||
import { Chart } from 'flowbite-svelte';
|
import { Chart } from 'flowbite-svelte';
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
import { Toaster } from '$lib/components/ui/sonner';
|
||||||
export let data: { pubkey: string; merits: number; sats: number }[];
|
export let data: { pubkey: string; merits: number; sats: number }[];
|
||||||
|
|
||||||
let pubkeys = Array.from(data, (x) => x.pubkey);
|
let pubkeys = Array.from(data, (x) => x.pubkey);
|
||||||
@@ -130,4 +131,9 @@
|
|||||||
// </Card>
|
// </Card>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Chart options={$o} class="py-6" />
|
<div class="relative h-full w-full">
|
||||||
|
<Chart options={$o} class="py-6" />
|
||||||
|
<div class="absolute left-1/2 top-0 z-20 w-[356px] -translate-x-1/2 transform">
|
||||||
|
<Toaster position="top-center" id="purchase" duration={10000} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
48
src/components/PruchaseToast.svelte
Normal file
48
src/components/PruchaseToast.svelte
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
|
||||||
|
import { ndk } from '@/ndk';
|
||||||
|
import { unixToRelativeTime } from '@/helpers';
|
||||||
|
import { fetchEvent } from '@/event_helpers/products';
|
||||||
|
import { Product, Rocket, type ZapPurchase } from '@/event_helpers/rockets';
|
||||||
|
|
||||||
|
export let zapPurchase: ZapPurchase;
|
||||||
|
export let rocket: Rocket;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
{#if zapPurchase.ZapReceipt.content}
|
||||||
|
<div>{zapPurchase.ZapReceipt.content}</div>
|
||||||
|
{:else}
|
||||||
|
<!-- Sometimes ZapReceipt.content is empty -->
|
||||||
|
{#await fetchEvent(zapPurchase.ProductID, $ndk)}
|
||||||
|
<div>New purchase</div>
|
||||||
|
{:then product}
|
||||||
|
<div>{`Purchase of ${new Product(product).Name()} from ${rocket.Name()}.`}</div>
|
||||||
|
{/await}
|
||||||
|
{/if}
|
||||||
|
{#if zapPurchase.BuyerPubkey}
|
||||||
|
<div class="flex flex-nowrap gap-1">
|
||||||
|
<Avatar
|
||||||
|
ndk={$ndk}
|
||||||
|
pubkey={zapPurchase.BuyerPubkey}
|
||||||
|
class="h-10 w-10 flex-none rounded-full object-cover"
|
||||||
|
/>
|
||||||
|
<Name
|
||||||
|
ndk={$ndk}
|
||||||
|
pubkey={zapPurchase.BuyerPubkey}
|
||||||
|
class="hidden max-w-32 truncate p-2 md:inline-block"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if zapPurchase.Amount}
|
||||||
|
<div>
|
||||||
|
Amount: {(zapPurchase.Amount / 1000).toFixed(0)}
|
||||||
|
{(zapPurchase.Amount / 1000).toFixed(0) === '1' ? 'sat' : 'sats'}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if zapPurchase.ZapReceipt.created_at}
|
||||||
|
<div>
|
||||||
|
{unixToRelativeTime(zapPurchase.ZapReceipt.created_at * 1000)}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@@ -2,8 +2,10 @@
|
|||||||
import * as Breadcrumb from '$lib/components/ui/breadcrumb/index.js';
|
import * as Breadcrumb from '$lib/components/ui/breadcrumb/index.js';
|
||||||
import Button from '@/components/ui/button/button.svelte';
|
import Button from '@/components/ui/button/button.svelte';
|
||||||
import * as Card from '@/components/ui/card';
|
import * as Card from '@/components/ui/card';
|
||||||
|
import PurchaseToast from './PruchaseToast.svelte';
|
||||||
import { Rocket, ZapPurchase } from '@/event_helpers/rockets';
|
import { Rocket, ZapPurchase } from '@/event_helpers/rockets';
|
||||||
import { devmode } from '@/stores/session';
|
import { devmode } from '@/stores/session';
|
||||||
|
import { toast } from 'svelte-sonner';
|
||||||
import type { NDKEvent } from '@nostr-dev-kit/ndk';
|
import type { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||||
import BitcoinAssociations from './AssociatedBitcoinAddresses.svelte';
|
import BitcoinAssociations from './AssociatedBitcoinAddresses.svelte';
|
||||||
import MeritRequests from './MeritRequests.svelte';
|
import MeritRequests from './MeritRequests.svelte';
|
||||||
@@ -11,10 +13,47 @@
|
|||||||
import ProductFomo from './ProductFomo.svelte';
|
import ProductFomo from './ProductFomo.svelte';
|
||||||
import ProposedProducts from './ProposedProducts.svelte';
|
import ProposedProducts from './ProposedProducts.svelte';
|
||||||
import UpdateMission from './UpdateMission.svelte';
|
import UpdateMission from './UpdateMission.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
export let rocket: NDKEvent;
|
export let rocket: NDKEvent;
|
||||||
|
|
||||||
$: unratifiedZaps = new Map<string, ZapPurchase>();
|
$: unratifiedZaps = new Map<string, ZapPurchase>();
|
||||||
|
let lastCheckTime = Date.now() / 1000; // Current time in seconds
|
||||||
|
|
||||||
|
function checkNewZaps() {
|
||||||
|
const currentTime = Date.now() / 1000;
|
||||||
|
const recentZaps = Array.from(unratifiedZaps.values()).filter(
|
||||||
|
(zap) =>
|
||||||
|
zap.ZapReceipt.created_at &&
|
||||||
|
zap.ZapReceipt.created_at > lastCheckTime &&
|
||||||
|
zap.ZapReceipt.created_at <= currentTime
|
||||||
|
);
|
||||||
|
|
||||||
|
recentZaps.forEach((zapPurchase) => {
|
||||||
|
toast(PurchaseToast, {
|
||||||
|
componentProps: {
|
||||||
|
zapPurchase,
|
||||||
|
rocket: new Rocket(rocket)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
lastCheckTime = currentTime;
|
||||||
|
}
|
||||||
|
$: {
|
||||||
|
if (unratifiedZaps.size > 0) {
|
||||||
|
checkNewZaps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMount(() => {
|
||||||
|
lastCheckTime = Date.now() / 1000 - 30; // 30 seconds ago
|
||||||
|
});
|
||||||
|
|
||||||
|
$: lasted = Array.from(unratifiedZaps.values()).sort((a, b) => {
|
||||||
|
if (a.ZapReceipt.created_at && b.ZapReceipt.created_at) {
|
||||||
|
return b.ZapReceipt.created_at - a.ZapReceipt.created_at;
|
||||||
|
} else return 0;
|
||||||
|
})[0];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
@@ -32,6 +71,27 @@
|
|||||||
</Breadcrumb.Root>
|
</Breadcrumb.Root>
|
||||||
</header>
|
</header>
|
||||||
<main class="grid w-full flex-1 grid-cols-1 items-start gap-4 sm:grid-cols-3 md:gap-2">
|
<main class="grid w-full flex-1 grid-cols-1 items-start gap-4 sm:grid-cols-3 md:gap-2">
|
||||||
|
{#if $devmode}
|
||||||
|
<Button
|
||||||
|
on:click={() => {
|
||||||
|
if (!lasted) {
|
||||||
|
toast('unratifiedZaps is null');
|
||||||
|
} else {
|
||||||
|
console.log(lasted);
|
||||||
|
toast(PurchaseToast, {
|
||||||
|
componentProps: {
|
||||||
|
zapPurchase: lasted,
|
||||||
|
rocket: new Rocket(rocket)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
variant="outline">Popup Last Purchase Notification</Button
|
||||||
|
>
|
||||||
|
<Button variant="outline" on:click={() => console.log(Array.from(unratifiedZaps.values()))}
|
||||||
|
>print unratifiedZaps</Button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
<MeritsAndSatflow {unratifiedZaps} rocket={new Rocket(rocket)} />
|
<MeritsAndSatflow {unratifiedZaps} rocket={new Rocket(rocket)} />
|
||||||
|
|
||||||
<ProductFomo bind:unratifiedZaps rocket={new Rocket(rocket)} />
|
<ProductFomo bind:unratifiedZaps rocket={new Rocket(rocket)} />
|
||||||
|
|||||||
@@ -27,16 +27,19 @@
|
|||||||
sessionStarted = true;
|
sessionStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(()=>{getBitcoinTip();})
|
onMount(() => {
|
||||||
|
|
||||||
setInterval(function () {
|
|
||||||
getBitcoinTip();
|
getBitcoinTip();
|
||||||
}, 2* 60 * 1000);
|
});
|
||||||
|
|
||||||
|
setInterval(
|
||||||
|
function () {
|
||||||
|
getBitcoinTip();
|
||||||
|
},
|
||||||
|
2 * 60 * 1000
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModeWatcher defaultMode="dark" />
|
<ModeWatcher defaultMode="dark" />
|
||||||
<SidePanelLayout>
|
<SidePanelLayout>
|
||||||
<div slot="content"><slot></slot></div>
|
<div slot="content"><slot></slot></div>
|
||||||
</SidePanelLayout>
|
</SidePanelLayout>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user