Add classified status
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {getTagValue} from "@welshman/util"
|
||||
import {getTagValue, getAddress} from "@welshman/util"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getTagValue} from "@welshman/util"
|
||||
import {getTagValue, getAddress} from "@welshman/util"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import CalendarEventActions from "@app/components/CalendarEventActions.svelte"
|
||||
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {getTagValue} from "@welshman/util"
|
||||
import {getTagValue, getAddress} from "@welshman/util"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
@@ -8,6 +8,7 @@
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import RoomName from "@app/components/RoomName.svelte"
|
||||
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
||||
import ClassifiedStatus from "@app/components/ClassifiedStatus.svelte"
|
||||
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
||||
import EventActivity from "@app/components/EventActivity.svelte"
|
||||
import EventActions from "@app/components/EventActions.svelte"
|
||||
@@ -45,7 +46,9 @@
|
||||
</Link>
|
||||
{/if}
|
||||
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
||||
<ThunkStatusOrDeleted {event} />
|
||||
<ThunkStatusOrDeleted {event}>
|
||||
<ClassifiedStatus {event} />
|
||||
</ThunkStatusOrDeleted>
|
||||
{#if showActivity}
|
||||
<EventActivity {url} {path} {event} />
|
||||
{/if}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
const {d, title, status} = fromPairs(event.tags)
|
||||
const [_, price = 0, currency = "SAT"] = getTag("price", event.tags) || []
|
||||
const images = getTagValues("image", event.tags)
|
||||
const initialValues = {d, title, status, content, price, currency, images}
|
||||
const initialValues = {d, title, status, content, price: Number(price), currency, images}
|
||||
</script>
|
||||
|
||||
<ClassifiedForm {url} {initialValues}>
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalTitle from "@lib/components/ModalTitle.svelte"
|
||||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import Modal from "@lib/components/Modal.svelte"
|
||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
@@ -125,10 +122,7 @@
|
||||
|
||||
<Modal tag="form" onsubmit={preventDefault(submit)}>
|
||||
<ModalBody>
|
||||
<ModalHeader>
|
||||
<ModalTitle>Create a Classified Listing</ModalTitle>
|
||||
<ModalSubtitle>Advertise a job, sale, or need.</ModalSubtitle>
|
||||
</ModalHeader>
|
||||
{@render header?.()}
|
||||
<div class="col-8 relative">
|
||||
<Field>
|
||||
{#snippet label()}
|
||||
@@ -198,7 +192,7 @@
|
||||
Go back
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary" disabled={loading}>
|
||||
<Spinner {loading}>Create Listing</Spinner>
|
||||
<Spinner {loading}>Save Listing</Spinner>
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {formatTimestamp} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getTagValue, getTagValues} from "@welshman/util"
|
||||
import {getTag, getAddress, getTagValue, getTagValues} from "@welshman/util"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import CurrencySymbol from "@lib/components/CurrencySymbol.svelte"
|
||||
import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte"
|
||||
import Content from "@app/components/Content.svelte"
|
||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||
@@ -20,6 +21,7 @@
|
||||
const title = getTagValue("title", event.tags)
|
||||
const h = getTagValue("h", event.tags)
|
||||
const images = getTagValues("image", event.tags)
|
||||
const [_, price = 0, currency = "SAT"] = getTag("price", event.tags) || []
|
||||
</script>
|
||||
|
||||
<Link
|
||||
@@ -27,7 +29,10 @@
|
||||
href={makeClassifiedPath(url, getAddress(event))}>
|
||||
{#if title}
|
||||
<div class="flex w-full items-center justify-between gap-2">
|
||||
<p class="text-xl">{title}</p>
|
||||
<p class="text-xl">
|
||||
{title} —
|
||||
<CurrencySymbol code={currency} />{price}
|
||||
</p>
|
||||
<p class="text-sm opacity-75">
|
||||
{formatTimestamp(event.created_at)}
|
||||
</p>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getTagValue} from "@welshman/util"
|
||||
import {ucFirst} from "@lib/util"
|
||||
|
||||
type Props = {
|
||||
event: TrustedEvent
|
||||
}
|
||||
|
||||
const {event}: Props = $props()
|
||||
|
||||
const status = getTagValue("status", event.tags)
|
||||
</script>
|
||||
|
||||
{#if status}
|
||||
<div class={cx("btn btn-xs rounded-full", {"btn-primary": status !== "active"})}>
|
||||
{ucFirst(status)}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type {ComponentProps} from "svelte"
|
||||
import {getTagValue, getTagValues} from "@welshman/util"
|
||||
import {getTag, getTagValue, getTagValues} from "@welshman/util"
|
||||
import CurrencySymbol from "@lib/components/CurrencySymbol.svelte"
|
||||
import Content from "@app/components/Content.svelte"
|
||||
import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte"
|
||||
|
||||
@@ -8,11 +9,15 @@
|
||||
|
||||
const title = getTagValue("title", props.event.tags)
|
||||
const images = getTagValues("image", props.event.tags)
|
||||
const [_, price = 0, currency = "SAT"] = getTag("price", props.event.tags) || []
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
{#if title}
|
||||
<p class="text-xl">{title}</p>
|
||||
<p class="text-xl">
|
||||
{title} —
|
||||
<CurrencySymbol code={currency} />{price}
|
||||
</p>
|
||||
{/if}
|
||||
{#if props.event.content}
|
||||
<Content {...props} />
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
{count}
|
||||
recent messages{count === 1 ? "" : "s"}
|
||||
</span>
|
||||
<Button class="btn btn-sm btn-primary" onclick={onClick}>
|
||||
<Button class="btn btn-xs rounded-full btn-primary" onclick={onClick}>
|
||||
View Conversation
|
||||
<Icon icon={AltArrowRight} />
|
||||
</Button>
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type {Snippet} from "svelte"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {PublishStatus} from "@welshman/net"
|
||||
import {deriveIsDeleted} from "@welshman/store"
|
||||
import {thunks, mergeThunks, repository} from "@welshman/app"
|
||||
import {thunks, mergeThunks, thunkHasStatus, repository} from "@welshman/app"
|
||||
import ThunkStatus from "@app/components/ThunkStatus.svelte"
|
||||
|
||||
const {event}: {event: TrustedEvent} = $props()
|
||||
type Props = {
|
||||
event: TrustedEvent
|
||||
children?: Snippet
|
||||
}
|
||||
|
||||
const {event, children}: Props = $props()
|
||||
|
||||
const deleted = deriveIsDeleted(repository, event)
|
||||
const thunk = $derived(mergeThunks($thunks.filter(t => t.event.id === event.id)))
|
||||
@@ -12,6 +19,8 @@
|
||||
|
||||
{#if $deleted}
|
||||
<div class="btn btn-error btn-xs rounded-full">Deleted</div>
|
||||
{:else if thunk}
|
||||
{:else if thunk.thunks.length > 0 && !thunkHasStatus(PublishStatus.Success, thunk)}
|
||||
<ThunkStatus {thunk} />
|
||||
{:else if children}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as nip19 from "nostr-tools/nip19"
|
||||
import {goto} from "$app/navigation"
|
||||
import {nthEq, sleep} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getAddress} from "@welshman/util"
|
||||
import {tracker, loadRelay} from "@welshman/app"
|
||||
import {scrollToEvent} from "@lib/html"
|
||||
import {identity} from "@welshman/lib"
|
||||
@@ -66,9 +67,11 @@ export const makeGoalPath = (url: string, id?: string) => makeSpacePath(url, "go
|
||||
|
||||
export const makeThreadPath = (url: string, id?: string) => makeSpacePath(url, "threads", id)
|
||||
|
||||
export const makeClassifiedPath = (url: string, address?: string) => makeSpacePath(url, "classifieds", address)
|
||||
export const makeClassifiedPath = (url: string, address?: string) =>
|
||||
makeSpacePath(url, "classifieds", address)
|
||||
|
||||
export const makeCalendarPath = (url: string, address?: string) => makeSpacePath(url, "calendar", address)
|
||||
export const makeCalendarPath = (url: string, address?: string) =>
|
||||
makeSpacePath(url, "calendar", address)
|
||||
|
||||
export const getPrimaryNavItem = ($page: Page) => $page.route?.id?.split("/")[1]
|
||||
|
||||
@@ -160,7 +163,6 @@ export const getEventPath = async (event: TrustedEvent, urls: string[]) => {
|
||||
if (parseInt(kind) === EVENT_TIME) {
|
||||
return makeCalendarPath(url, address)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
ZAP_GOAL,
|
||||
EVENT_TIME,
|
||||
COMMENT,
|
||||
getAddress,
|
||||
getTagValue,
|
||||
getTagValues,
|
||||
getIdAndAddress,
|
||||
@@ -26,6 +27,7 @@
|
||||
import SpaceMenuButton from "@app/components/SpaceMenuButton.svelte"
|
||||
import NoteItem from "@app/components/NoteItem.svelte"
|
||||
import RecentConversation from "@app/components/RecentConversation.svelte"
|
||||
import ClassifiedStatus from "@app/components/ClassifiedStatus.svelte"
|
||||
import {decodeRelay, deriveEventsForUrl, CONTENT_KINDS} from "@app/core/state"
|
||||
import {
|
||||
makeThreadPath,
|
||||
@@ -135,22 +137,31 @@
|
||||
{:else}
|
||||
<NoteItem {url} {event}>
|
||||
{#if event.kind === THREAD}
|
||||
<Link href={makeThreadPath(url, event.id)} class="btn btn-primary btn-sm">
|
||||
<Link
|
||||
href={makeThreadPath(url, event.id)}
|
||||
class="btn btn-primary btn-xs rounded-full">
|
||||
View Thread
|
||||
<Icon icon={AltArrowRight} />
|
||||
</Link>
|
||||
{:else if event.kind === CLASSIFIED}
|
||||
<Link href={makeClassifiedPath(url, getAddress(event))} class="btn btn-primary btn-sm">
|
||||
View Listing
|
||||
<Icon icon={AltArrowRight} />
|
||||
</Link>
|
||||
<div class="flex gap-2">
|
||||
<ClassifiedStatus {event} />
|
||||
<Link
|
||||
href={makeClassifiedPath(url, getAddress(event))}
|
||||
class="btn btn-primary btn-xs rounded-full">
|
||||
View Listing
|
||||
<Icon icon={AltArrowRight} />
|
||||
</Link>
|
||||
</div>
|
||||
{:else if event.kind === ZAP_GOAL}
|
||||
<Link href={makeGoalPath(url, event.id)} class="btn btn-primary btn-sm">
|
||||
<Link href={makeGoalPath(url, event.id)} class="btn btn-primary btn-xs rounded-full">
|
||||
View Goal
|
||||
<Icon icon={AltArrowRight} />
|
||||
</Link>
|
||||
{:else if event.kind === EVENT_TIME}
|
||||
<Link href={makeCalendarPath(url, getAddress(event))} class="btn btn-primary btn-sm">
|
||||
<Link
|
||||
href={makeCalendarPath(url, getAddress(event))}
|
||||
class="btn btn-primary btn-xs rounded-full">
|
||||
View Event
|
||||
<Icon icon={AltArrowRight} />
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user