problem: can't see how many products ar remaining

This commit is contained in:
gsovereignty
2024-08-16 17:32:40 +08:00
parent 4cb488ea68
commit 7d1d5e35c5
11 changed files with 163 additions and 69 deletions

View File

@@ -3,8 +3,17 @@
import { page } from '$app/stores';
import { Badge } from '@/components/ui/badge';
import Separator from '@/components/ui/separator/separator.svelte';
import { currentUser } from '@/stores/session';
import { GitBranch, HelpCircle, Mail, Package, Pyramid, Rocket, Users } from 'lucide-svelte';
import { currentUser, devmode } from '@/stores/session';
import {
Code,
GitBranch,
HelpCircle,
Mail,
Package,
Pyramid,
Rocket,
Users
} from 'lucide-svelte';
import { GitAltBrand, TelegramBrand } from 'svelte-awesome-icons';
let iconClass = 'h-5 w-5 md:h-4 md:w-4';
@@ -57,4 +66,16 @@
<HelpCircle class={iconClass} />
Help
</a>
<Separator class="my-2" />
<Separator class="dark:bg-slate-700" />
<a
href="#"
class={getClass('dev')}
on:click={() => {
devmode.update((dm) => {
return !dm;
});
}}
>
<Code class={iconClass} />
Toggle Dev Mode
</a>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import * as Card from '@/components/ui/card';
import * as Table from '@/components/ui/table';
import { Rocket } from '@/event_helpers/rockets';
import { Rocket, ZapPurchase } from '@/event_helpers/rockets';
import { writable } from 'svelte/store';
import Pie from './Pie.svelte';
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
@@ -9,7 +9,7 @@
import NumberIncrement from '@components/ui/number-increment';
export let rocket: Rocket;
export let unratifiedZaps: Map<string, number>;
export let unratifiedZaps: Map<string, ZapPurchase>;
let unratifiedZapsAmount = 0;
let dataLoaded = false;
@@ -17,7 +17,7 @@
$: {
unratifiedZapsAmount = 0;
for (let [_, a] of unratifiedZaps) {
unratifiedZapsAmount += a / 1000;
unratifiedZapsAmount += a.Amount / 1000;
}
unratifiedZapsAmount = unratifiedZapsAmount;
}

View File

@@ -1,27 +1,26 @@
<script lang="ts">
import { buttonVariants } from '$lib/components/ui/button/index.js';
import { Button, buttonVariants } from '$lib/components/ui/button/index.js';
import * as Dialog from '$lib/components/ui/dialog/index.js';
import * as Alert from '@/components/ui/alert';
import { Input } from '$lib/components/ui/input';
import { Button } from '$lib/components/ui/button/index.js';
import * as Alert from '@/components/ui/alert';
import type { Product, Rocket, RocketProduct } from '@/event_helpers/rockets';
import { formatSats } from '@/helpers';
import { ndk } from '@/ndk';
import { currentUser } from '@/stores/session';
import { NDKZap } from '@nostr-dev-kit/ndk';
import { Terminal } from 'lucide-svelte';
import { requestProvider } from 'webln';
import QrCodeSvg from './QrCodeSvg.svelte';
import CopyButton from './CopyButton.svelte';
import type { Product, Rocket, RocketProduct } from '@/event_helpers/rockets';
import { formatSats } from '@/helpers';
import { Spinner } from 'flowbite-svelte';
import { CheckCircleOutline } from 'flowbite-svelte-icons';
import { tweened, type Tweened } from 'svelte/motion';
import { Terminal } from 'lucide-svelte';
import { cubicOut } from 'svelte/easing';
import { fade, fly } from 'svelte/transition';
import { tweened } from 'svelte/motion';
import { requestProvider } from 'webln';
import CopyButton from './CopyButton.svelte';
import QrCodeSvg from './QrCodeSvg.svelte';
export let product: Product;
export let rocketProduct: RocketProduct | undefined;
export let rocket: Rocket;
export let disabled = false;
let invoice: string | null;
let paymentInitiated: boolean;
@@ -37,7 +36,7 @@
zappedUser: rocket.Event.author
});
invoice = await z.createZapRequest(
rocketProduct.Price * 1000,
rocketProduct.Price() * 1000,
`Purchase of ${product.Name()} from ${rocket.Event.dTag}`,
[['product', product.ID()]]
);
@@ -83,12 +82,16 @@
{#if rocketProduct}
<Dialog.Root bind:open>
<Dialog.Trigger class={buttonVariants({ variant: 'default' })}>
{#if open}
<Spinner class="me-2" color="white" size={4} /> Confirming...
{:else}
Buy Now for {formatSats(rocketProduct.Price)}
{/if}
<Dialog.Trigger>
<Button {disabled}>
{#if open}
<Spinner class="me-2" color="white" size={4} /> Confirming...
{:else if !disabled}
Buy Now for {formatSats(rocketProduct.Price())}
{:else if disabled}
Out of Stock!
{/if}
</Button>
</Dialog.Trigger>
<Dialog.Content class="sm:max-w-[425px]">
@@ -104,9 +107,9 @@
</Alert.Root>
{/if}
<Dialog.Description
>Pay {rocketProduct.Price === 1
? `${rocketProduct.Price} sat`
: `${rocketProduct.Price} sats`} now with Lightning</Dialog.Description
>Pay {rocketProduct.Price() === 1
? `${rocketProduct.Price()} sat`
: `${rocketProduct.Price()} sats`} now with Lightning</Dialog.Description
>
</Dialog.Header>
{#if invoice}

View File

@@ -1,11 +1,43 @@
<script lang="ts">
import * as Card from '$lib/components/ui/card/index.js';
import { Product, Rocket } from '@/event_helpers/rockets';
import {
Product as ProductEvent,
Rocket,
RocketProduct,
ZapPurchase
} from '@/event_helpers/rockets';
import AddProductToRocket from './AddProductToRocket.svelte';
import PayNow from './PayNow.svelte';
import { onMount } from 'svelte';
import { devmode } from '@/stores/session';
export let product: Product;
export let product: ProductEvent;
export let rocket: Rocket;
export let unratifiedZaps: Map<string, ZapPurchase> | undefined = undefined;
let productFromRocket = rocket.Products().get(product.ID());
onMount(() => {
if (!product.Validate()) {
throw new Error('this should not happen');
}
});
function remainingProducts(product: RocketProduct, zaps?: Map<string, ZapPurchase>): number {
let numberOfPurchases = 0;
if (zaps) {
for (let [_, zap] of zaps) {
if (zap.ProductID == product.ID()) {
numberOfPurchases++;
}
}
}
let remaining = product.MaxPurchases() - numberOfPurchases;
if (remaining < 0) {
remaining = 0;
}
return remaining;
}
</script>
{#if product.Validate()}
@@ -34,18 +66,30 @@
<img src={product.CoverImage()} alt="cover" class="aspect-square object-cover" />
</div>
{/if}
<Card.Footer class="flex items-center justify-center pt-2">
{#if !rocket.Products().get(product.ID())}
<Card.Footer class="flex flex-col items-center justify-center pt-2">
{#if !rocket.Products().get(product.ID()) && !productFromRocket}
<AddProductToRocket {product} {rocket} />
{:else}
<PayNow {product} rocketProduct={rocket.Products().get(product.ID())} {rocket} />
{:else if productFromRocket}
{#if productFromRocket.MaxPurchases() && unratifiedZaps}
<div class="flex flex-nowrap">
{remainingProducts(productFromRocket, unratifiedZaps)} available
</div>
{/if}
<PayNow
disabled={productFromRocket.MaxPurchases() > 0 &&
remainingProducts(productFromRocket, unratifiedZaps) == 0}
{product}
rocketProduct={rocket.Products().get(product.ID())}
{rocket}
/>
{/if}
<a
href="#"
on:click={() => {
console.log(product);
}}>print to console</a
>
{#if $devmode}
<a
href="#"
on:click={() => {
console.log(product);
}}>print to console</a
>{/if}
</Card.Footer>
</Card.Root>
{/if}

View File

@@ -3,10 +3,11 @@
import { ndk } from '@/ndk';
import ProductCard from './ProductCard.svelte';
import { fetchEvent } from '@/event_helpers/products';
import { Product, type Rocket } from '@/event_helpers/rockets';
import { Product, ZapPurchase, type Rocket } from '@/event_helpers/rockets';
export let productID: string | undefined = undefined;
export let rocket: Rocket;
export let product: Product | undefined = undefined;
export let unratifiedZaps: Map<string, ZapPurchase> | undefined = undefined;
onMount(() => {
if (!product && productID) {
@@ -16,7 +17,7 @@
</script>
{#if product}
<ProductCard {rocket} {product}>
<ProductCard {unratifiedZaps} {rocket} {product}>
<slot />
</ProductCard>
{/if}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import * as Card from '$lib/components/ui/card/index.js';
import { Product, Rocket } from '@/event_helpers/rockets';
import { Product, Rocket, ZapPurchase } from '@/event_helpers/rockets';
import { fetchEvent } from '@/event_helpers/products';
import { ndk } from '@/ndk';
import { derived, writable } from 'svelte/store';
@@ -9,7 +9,7 @@
import CreateMeritRequest from './CreateMeritRequest.svelte';
export let rocket: Rocket;
export let unratifiedZaps: Map<string, number>;
export let unratifiedZaps: Map<string, ZapPurchase>;
let products = writable(new Map<string, Product>());
@@ -28,7 +28,6 @@
let groups = derived(products, ($products) => {
let productGroups = new Map<string, Map<string, Product>>();
for (let [id, p] of $products) {
console.log(p.Group());
if (!productGroups.get(p.Group())) {
productGroups.set(p.Group(), new Map());
}

View File

@@ -3,16 +3,16 @@
import ProductPurchases from './ProductPurchases.svelte';
import * as Pagination from '@/components/ui/pagination';
import { ChevronLeft, ChevronRight } from 'lucide-svelte';
import { Product, Rocket } from '@/event_helpers/rockets';
import { Product, Rocket, ZapPurchase } from '@/event_helpers/rockets';
export let rocket: Rocket;
export let products: Product[];
export let unratifiedZaps: Map<string, number> | undefined = undefined;
export let unratifiedZaps: Map<string, ZapPurchase> | undefined = undefined;
</script>
<Pagination.Root count={products.length} perPage={1} siblingCount={1} let:pages let:currentPage>
{#if currentPage}
<ProductCardFromId {rocket} product={products[currentPage - 1]}>
<ProductCardFromId {unratifiedZaps} {rocket} product={products[currentPage - 1]}>
{#if unratifiedZaps}
<ProductPurchases bind:unratifiedZaps {rocket} {products} />
{/if}

View File

@@ -11,7 +11,7 @@
//export let products: Product[];
export let rocket: Rocket;
export let unratifiedZaps: Map<string, number>;
export let unratifiedZaps: Map<string, ZapPurchase>;
let zaps = $ndk.storeSubscribe(
[{ '#a': [`31108:${rocket.Event.author.pubkey}:${rocket.Event.dTag}`], kinds: [9735] }],
@@ -85,7 +85,7 @@
validatedZapsNotInRocket.subscribe((zaps) => {
for (let [_, z] of zaps) {
unratifiedZaps.set(z.ZapReceipt.id, z.Amount);
unratifiedZaps.set(z.ZapReceipt.id, z);
}
unratifiedZaps = unratifiedZaps;
});

View File

@@ -2,7 +2,7 @@
import * as Breadcrumb from '$lib/components/ui/breadcrumb/index.js';
import Button from '@/components/ui/button/button.svelte';
import * as Card from '@/components/ui/card';
import { Rocket } from '@/event_helpers/rockets';
import { Rocket, ZapPurchase } from '@/event_helpers/rockets';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import BitcoinAssociations from './AssociatedBitcoinAddresses.svelte';
import MeritRequests from './MeritRequests.svelte';
@@ -14,7 +14,7 @@
export let rocket: NDKEvent;
$: unratifiedZaps = new Map<string, number>();
$: unratifiedZaps = new Map<string, ZapPurchase>();
</script>
<div class="flex flex-col gap-4">