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