This commit is contained in:
Alejandro Gomez 2023-07-07 23:33:39 +02:00
parent 2fe390a52f
commit 31da3a0241
No known key found for this signature in database
GPG Key ID: 4DF39E566658C817
4 changed files with 194 additions and 45 deletions

134
components/Address.tsx Normal file
View File

@ -0,0 +1,134 @@
import Link from "next/link";
import { useMemo } from "react";
import { useAtom } from "jotai";
import { nip19 } from "nostr-tools";
import {
Flex,
Stack,
Heading,
Text,
Card,
CardHeader,
CardBody,
Tag,
} from "@chakra-ui/react";
import { useEvents } from "@emoji/nostr/hooks";
import { relaysAtom } from "@emoji/user/state";
import { findTag } from "@emoji/nostr/nip57";
function getEmoji(ev) {
if ([1, 30_023, 30_024].includes(ev.kind)) {
return "📝";
}
if (ev.kind === 30_311) {
return "🎥";
}
return "❔";
}
function Preview({ naddr, ev }) {
const title = useMemo(() => findTag(ev, "title"), [ev]);
const description = useMemo(() => findTag(ev, "summary"), [ev]);
const tags = useMemo(
() => ev.tags.filter((t) => t.at(0) === "t").map((t) => t.at(1)),
[ev]
);
return (
<Link href={`https://habla.news/a/${naddr}`}>
<Card variant="elevated">
<CardHeader pb={0}>
<Heading fontSize="md">
{" "}
{getEmoji(ev)} {title}
</Heading>
</CardHeader>
<CardBody>
<Stack>
{description && <Text>{description}</Text>}
{tags.length > 0 && (
<Flex gap={2} flexWrap="wrap" mt={4}>
{tags.map((t) => (
<Tag key={t}>{t}</Tag>
))}
</Flex>
)}
</Stack>
</CardBody>
</Card>
</Link>
);
}
function Stream({ naddr, ev }) {
const title = useMemo(() => findTag(ev, "title"), [ev]);
const description = useMemo(() => findTag(ev, "summary"), [ev]);
const tags = useMemo(
() => ev.tags.filter((t) => t.at(0) === "t").map((t) => t.at(1)),
[ev]
);
return (
<Link href={`https://zap.stream/${naddr}`}>
<Card variant="elevated">
<CardHeader pb={0}>
<Heading fontSize="md">
{" "}
{getEmoji(ev)} {title}
</Heading>
</CardHeader>
<CardBody>
<Stack>
{description && <Text>{description}</Text>}
{tags.length > 0 && (
<Flex gap={2} flexWrap="wrap" mt={4}>
{tags.map((t) => (
<Tag key={t}>{t}</Tag>
))}
</Flex>
)}
</Stack>
</CardBody>
</Card>
</Link>
);
}
export function Address({ a }) {
const [relays] = useAtom(relaysAtom);
const [k, pubkey, d] = useMemo(() => a.split(":"), [a]);
const naddr = useMemo(() => {
return nip19.naddrEncode({
kind: Number(k),
pubkey: pubkey,
identifier: d,
relays,
});
}, [k, pubkey, d, relays]);
const { events } = useEvents(
[
{
kinds: [Number(k)],
authors: [pubkey],
"#d": [d],
},
],
relays
);
const ev = events[0];
if (!ev) {
return null;
}
if (ev.kind === 30_311) {
return <Stream naddr={naddr} ev={ev} />;
}
if (ev.kind === 30_023) {
return <Preview naddr={naddr} ev={ev} />;
}
const alt = ev.tags.find((t) => t.at(0) === "alt");
return alt ? <Text>{alt}</Text> : <Text>Unknown event kind: {ev.kind}</Text>;
}

View File

@ -63,7 +63,7 @@ export default function CreateGoal({ showPreview = true }) {
event.tags.push(["closed_at", String(closedAt)]);
}
return event;
}, [name, closedAt, amount, url]);
}, [name, address, closedAt, amount, url]);
const handleNameChange = (event) => {
setName(event.target.value);

View File

@ -26,6 +26,7 @@ import { ExternalLinkIcon } from "@chakra-ui/icons";
import EmojiGrid from "@emoji/components/EmojiGrid";
import User from "@emoji/components/User";
import { Address } from "@emoji/components/Address";
import { GoalZaps } from "@emoji/components/GoalsZaps";
import { useEvents } from "@emoji/nostr/hooks";
import { pubkeyAtom, relaysAtom } from "@emoji/user/state";
@ -161,19 +162,19 @@ export function Goal({ goal, isDetail = false, ...rest }) {
return acc.concat([z.pubkey]);
}, []);
}, [zappers]);
const link = nevent && (
<Link href={`/e/${nevent}`}>
<Icon as={ExternalLinkIcon} boxSize={5} color="gray.500" />
</Link>
);
return (
<Card p={0} minW="320px" sx={isExpired ? { opacity: 0.8 } : {}} {...rest}>
<CardHeader>
<Stack spacing={1}>
<Flex justifyContent="space-between">
{goal.content.length > 0 && (
<Heading fontSize="lg">{goal.content}</Heading>
)}
{goal.content.length > 0 &&
(nevent ? (
<Link href={`/e/${nevent}`} shallow>
<Heading fontSize="lg">{goal.content}</Heading>
</Link>
) : (
<Heading fontSize="lg">{goal.content}</Heading>
))}
{closedAtTimestamp && !isExpired && (
<Tag>expires {formatRemainingTime(closedAtTimestamp)}</Tag>
)}
@ -181,16 +182,9 @@ export function Goal({ goal, isDetail = false, ...rest }) {
<User size="xs" fontSize="md" pubkey={goal.pubkey} />
</Stack>
</CardHeader>
<CardBody
pt={0}
cursor={nevent ? "pointer" : "auto"}
onClick={
nevent
? () => router.push(`/e/${nevent}`, undefined, { shallow: true })
: null
}
>
<CardBody pt={0} cursor={nevent ? "pointer" : "auto"}>
<Stack gap={4} my={4}>
{a && <Address a={a} />}
{url && (
<Flex align="center" gap={2}>
<Icon as={ExternalLinkIcon} boxSize={3} color="gray.500" />
@ -199,29 +193,31 @@ export function Goal({ goal, isDetail = false, ...rest }) {
</a>
</Flex>
)}
<Stack>
<Flex justifyContent="space-between">
<Text>{formatShortNumber(total)}</Text>
<Text
sx={
isAchieved
? { color: "green.500" }
: {
color: progress === 0 ? "gray.500" : "black",
}
}
>
{isAchieved
? "100"
: progress === 0
? "0"
: progress.toFixed(2)}
%
</Text>
<Text>{formatShortNumber(amount)}</Text>
</Flex>
<Progress value={progress} colorScheme="green" />
</Stack>
<Link href={`/e/${nevent}`}>
<Stack>
<Flex justifyContent="space-between">
<Text>{formatShortNumber(total)}</Text>
<Text
sx={
isAchieved
? { color: "green.500" }
: {
color: progress === 0 ? "gray.500" : "black",
}
}
>
{isAchieved
? "100"
: progress === 0
? "0"
: progress.toFixed(2)}
%
</Text>
<Text>{formatShortNumber(amount)}</Text>
</Flex>
<Progress value={progress} colorScheme="green" />
</Stack>
</Link>
</Stack>
{isDetail && (
<>

View File

@ -1,20 +1,39 @@
"use client";
import { useState, useEffect } from "react";
import { Flex } from "@chakra-ui/react";
import { Flex, Stack, Heading, Text } from "@chakra-ui/react";
import { useAtom } from "jotai";
import { GOAL } from "@emoji/nostr/const";
import { Goals } from "@emoji/components/Goals";
import { Goal, Goals } from "@emoji/components/Goals";
import { pool, useEvents } from "@emoji/nostr/hooks";
import { relaysAtom } from "@emoji/user/state";
export default function HomeContent() {
const [relays] = useAtom(relaysAtom);
const { events, eose } = useEvents([{ kinds: [GOAL] }], relays);
const { events: example } = useEvents(
[
{
kinds: [GOAL],
authors: [
"55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185",
],
limit: 1,
},
],
relays
);
const ev = example[0];
const { events, eose } = useEvents([{ kinds: [GOAL], limit: 3 }], relays);
return (
<Flex alignItems="center" justifyContent="center">
<Goals goals={events} />
<Stack>
<Heading>Zapgoals</Heading>
<Text>asfdadsffads fsda</Text>
{ev && <Goal goal={ev} />}
<Text>asfdadsffads fsda</Text>
{eose && <Goals goals={events} />}
</Stack>
</Flex>
);
}