diff --git a/src/app/components/ClassifiedActions.svelte b/src/app/components/ClassifiedActions.svelte new file mode 100644 index 000000000..b8605a889 --- /dev/null +++ b/src/app/components/ClassifiedActions.svelte @@ -0,0 +1,45 @@ + + +
+ {#if h && showRoom} + + Posted in # + + {/if} + + + {#if showActivity} + + {/if} + +
diff --git a/src/app/components/ClassifiedCreate.svelte b/src/app/components/ClassifiedCreate.svelte new file mode 100644 index 000000000..bf0c44677 --- /dev/null +++ b/src/app/components/ClassifiedCreate.svelte @@ -0,0 +1,149 @@ + + + + + + Create a Classified Listing + Advertise a job, sale, or need. + +
+ + {#snippet label()} +

Title*

+ {/snippet} + {#snippet input()} + + {/snippet} +
+ + {#snippet label()} +

Description*

+ {/snippet} + {#snippet input()} +
+ +
+ {/snippet} +
+ + {#snippet label()} +

Price*

+ {/snippet} + {#snippet input()} + todo: value and search select inline + {/snippet} +
+ + {#snippet label()} +

Images

+ {/snippet} + {#snippet input()} + todo: attach multiple images + {/snippet} +
+ +
+
+ + + + +
diff --git a/src/app/components/ClassifiedItem.svelte b/src/app/components/ClassifiedItem.svelte new file mode 100644 index 000000000..60ddddbba --- /dev/null +++ b/src/app/components/ClassifiedItem.svelte @@ -0,0 +1,49 @@ + + + + {#if title} +
+

{title}

+

+ {formatTimestamp(event.created_at)} +

+
+ {:else} + + {/if} + +
+ + Posted by + + {#if h} + in + {/if} + + +
+ diff --git a/src/app/components/CommentActions.svelte b/src/app/components/CommentActions.svelte index 6cffc5d59..c13d24244 100644 --- a/src/app/components/CommentActions.svelte +++ b/src/app/components/CommentActions.svelte @@ -5,19 +5,20 @@ import EventActivity from "@app/components/EventActivity.svelte" import EventActions from "@app/components/EventActions.svelte" import {publishDelete, publishReaction, canEnforceNip70} from "@app/core/commands" - import {makeThreadPath} from "@app/util/routes" + import {makeSpacePath} from "@app/util/routes" interface Props { - url: any - event: any + url: string + event: TrustedEvent + segment: string showActivity?: boolean } - const {url, event, showActivity = false}: Props = $props() + const {url, event, segment, showActivity = false}: Props = $props() const shouldProtect = canEnforceNip70(url) - const path = makeThreadPath(url, event.id) + const path = makeSpacePath(url, segment, event.id) const deleteReaction = async (event: TrustedEvent) => publishDelete({relays: [url], event, protect: await shouldProtect}) diff --git a/src/app/components/ComposeMenu.svelte b/src/app/components/ComposeMenu.svelte index 26ec76a03..990728dec 100644 --- a/src/app/components/ComposeMenu.svelte +++ b/src/app/components/ComposeMenu.svelte @@ -3,11 +3,13 @@ import CalendarMinimalistic from "@assets/icons/calendar-minimalistic.svg?dataurl" import StarFallMinimalistic from "@assets/icons/star-fall-minimalistic.svg?dataurl" import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl" + import CaseMinimalistic from "@assets/icons/case-minimalistic.svg?dataurl" import Button from "@lib/components/Button.svelte" import Icon from "@lib/components/Icon.svelte" import {pushModal} from "@app/util/modal" import CalendarEventCreate from "@app/components/CalendarEventCreate.svelte" import ThreadCreate from "@app/components/ThreadCreate.svelte" + import ClassifiedCreate from "@app/components/ClassifiedCreate.svelte" import GoalCreate from "@app/components/GoalCreate.svelte" type Props = { @@ -24,6 +26,8 @@ const createThread = () => pushModal(ThreadCreate, {url, h}) + const createClassified = () => pushModal(ClassifiedCreate, {url, h}) + let ul: Element onMount(() => { @@ -35,13 +39,19 @@
  • +
  • +
  • +
  • diff --git a/src/app/components/EventInfo.svelte b/src/app/components/EventInfo.svelte index 783b71aa7..59773f8b0 100644 --- a/src/app/components/EventInfo.svelte +++ b/src/app/components/EventInfo.svelte @@ -14,6 +14,7 @@ import Modal from "@lib/components/Modal.svelte" import ModalBody from "@lib/components/ModalBody.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte" + import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import {clip} from "@app/util/toast" @@ -106,6 +107,8 @@

    - + + + diff --git a/src/app/components/NoteContent.svelte b/src/app/components/NoteContent.svelte index dc8597764..09d5ab13b 100644 --- a/src/app/components/NoteContent.svelte +++ b/src/app/components/NoteContent.svelte @@ -1,8 +1,9 @@ + +
    + {#if title} +

    {title}

    + {/if} + {#if props.event.content} + + {/if} +
    diff --git a/src/app/components/NoteContentMinimal.svelte b/src/app/components/NoteContentMinimal.svelte index 179b478dc..7a1a5e8a9 100644 --- a/src/app/components/NoteContentMinimal.svelte +++ b/src/app/components/NoteContentMinimal.svelte @@ -1,8 +1,9 @@ + +{#if title} + {title} +{/if} +{#if props.event.content} + +{/if} diff --git a/src/app/components/RoomCompose.svelte b/src/app/components/RoomCompose.svelte index 915b193f1..5f47549f0 100644 --- a/src/app/components/RoomCompose.svelte +++ b/src/app/components/RoomCompose.svelte @@ -131,8 +131,7 @@
    + +
    + {/snippet} + + + + {#each items as event (event.id)} +
    + +
    + {/each} +

    + + {#if loading} + Looking for listingss... + {:else if items.length === 0} + No classified listings found. + {:else} + That's all! + {/if} + +

    +
    diff --git a/src/routes/spaces/[relay]/classifieds/[id]/+page.svelte b/src/routes/spaces/[relay]/classifieds/[id]/+page.svelte new file mode 100644 index 000000000..97caa0886 --- /dev/null +++ b/src/routes/spaces/[relay]/classifieds/[id]/+page.svelte @@ -0,0 +1,124 @@ + + + + {#snippet icon()} +
    + +
    + {/snippet} + {#snippet title()} +

    {getTagValue("title", $event?.tags || []) || ""}

    + {/snippet} + {#snippet action()} +
    + +
    + {/snippet} +
    + + + {#if $event} +
    + +
    + + +
    +
    + {#if !showAll && $replies.length > 4} +
    + +
    + {/if} + {#each $replies.slice(0, showAll ? undefined : 4) as reply (reply.id)} + +
    + + +
    +
    + {/each} +
    + {#if showReply} + + {:else} +
    + +
    + {/if} + {:else} + {#await sleep(5000)} + Loading listing... + {:then} +

    Failed to load classified listing.

    + {/await} + {/if} +
    diff --git a/src/routes/spaces/[relay]/goals/[id]/+page.svelte b/src/routes/spaces/[relay]/goals/[id]/+page.svelte index 358865b70..12167d2b6 100644 --- a/src/routes/spaces/[relay]/goals/[id]/+page.svelte +++ b/src/routes/spaces/[relay]/goals/[id]/+page.svelte @@ -102,7 +102,7 @@
    - +
    {/each} diff --git a/src/routes/spaces/[relay]/recent/+page.svelte b/src/routes/spaces/[relay]/recent/+page.svelte index a85f0f32c..d85bb612f 100644 --- a/src/routes/spaces/[relay]/recent/+page.svelte +++ b/src/routes/spaces/[relay]/recent/+page.svelte @@ -6,6 +6,7 @@ import { MESSAGE, THREAD, + CLASSIFIED, ZAP_GOAL, EVENT_TIME, COMMENT, @@ -26,7 +27,12 @@ import NoteItem from "@app/components/NoteItem.svelte" import RecentConversation from "@app/components/RecentConversation.svelte" import {decodeRelay, deriveEventsForUrl, CONTENT_KINDS} from "@app/core/state" - import {makeThreadPath, makeCalendarPath, makeGoalPath} from "@app/util/routes" + import { + makeThreadPath, + makeClassifiedPath, + makeCalendarPath, + makeGoalPath, + } from "@app/util/routes" const url = decodeRelay($page.params.relay!) const since = ago(MONTH) @@ -133,6 +139,11 @@ View Thread + {:else if event.kind === CLASSIFIED} + + View Listing + + {:else if event.kind === ZAP_GOAL} View Goal diff --git a/src/routes/spaces/[relay]/threads/[id]/+page.svelte b/src/routes/spaces/[relay]/threads/[id]/+page.svelte index d84d12f77..b6ba0d240 100644 --- a/src/routes/spaces/[relay]/threads/[id]/+page.svelte +++ b/src/routes/spaces/[relay]/threads/[id]/+page.svelte @@ -99,7 +99,7 @@
    - +
    {/each}