diff --git a/src/lib/components/ChatSidebar.svelte b/src/lib/components/ChatSidebar.svelte new file mode 100644 index 0000000..21b462c --- /dev/null +++ b/src/lib/components/ChatSidebar.svelte @@ -0,0 +1,78 @@ + + + diff --git a/src/lib/components/LeftSidebar.svelte b/src/lib/components/LeftSidebar.svelte new file mode 100644 index 0000000..b303b11 --- /dev/null +++ b/src/lib/components/LeftSidebar.svelte @@ -0,0 +1,74 @@ + + + diff --git a/src/lib/components/Navbar.svelte b/src/lib/components/Navbar.svelte new file mode 100644 index 0000000..f4daf36 --- /dev/null +++ b/src/lib/components/Navbar.svelte @@ -0,0 +1,18 @@ + + +
+
+
+ {community.name[0]} +
+ {community.name} +
+ +
diff --git a/src/lib/components/Reactions.svelte b/src/lib/components/Reactions.svelte new file mode 100644 index 0000000..c554e2c --- /dev/null +++ b/src/lib/components/Reactions.svelte @@ -0,0 +1,31 @@ + + +
+ {#each reactions as r} + + {/each} + {#if zaps > 0} + + {/if} +
diff --git a/src/lib/components/Tag.svelte b/src/lib/components/Tag.svelte new file mode 100644 index 0000000..7d270dd --- /dev/null +++ b/src/lib/components/Tag.svelte @@ -0,0 +1,8 @@ + + + + {label} + diff --git a/src/lib/components/ThreadItem.svelte b/src/lib/components/ThreadItem.svelte new file mode 100644 index 0000000..9977988 --- /dev/null +++ b/src/lib/components/ThreadItem.svelte @@ -0,0 +1,76 @@ + + + + +
+
{thread.title}
+
+ by + {thread.op.author.name} + {#if thread.participants.length > 1} + and +
+ {#each thread.participants + .filter((p) => p.pubkey !== thread.op.author.pubkey) + .slice(0, 4) as p} + {p.name} + {/each} +
+ {/if} +
+
+ + +
+ {#each thread.tags as tag} + + {/each} +
+ + +
+
+ {thread.replyCount} + replies +
+ +
+ {score} + score +
+ +
+
+ {thread.participants[thread.participants.length + {thread.lastActivity} +
+ activity +
+
+
diff --git a/src/lib/mock.ts b/src/lib/mock.ts new file mode 100644 index 0000000..2bee67c --- /dev/null +++ b/src/lib/mock.ts @@ -0,0 +1,289 @@ +export type Room = { + slug: string; + name: string; + group: string; +}; + +export type Author = { + pubkey: string; + name: string; + picture: string; +}; + +export type Reaction = { + emoji: string; + count: number; +}; + +export type Post = { + id: string; + author: Author; + content: string; + createdAt: string; + reactions: Reaction[]; + zaps: number; + replies?: Post[]; +}; + +export type Thread = { + id: string; + title: string; + tags: { label: string; color: string }[]; + op: Post; + replyCount: number; + viewCount: number; + lastActivity: string; + participants: Author[]; +}; + +export const community = { + name: "My big community", + about: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", +}; + +export const rooms: Room[] = [ + { slug: "off-topics-cafe", name: "Off topics cafe", group: "Groups" }, + { slug: "proposals", name: "Proposals", group: "Groups" }, + { slug: "development", name: "Development", group: "Groups" }, + { slug: "announcements", name: "Announcements", group: "Groups" }, + { slug: "off-topics", name: "Off topics", group: "Groups" }, + { slug: "about", name: "About", group: "Resources" }, + { slug: "help-center", name: "Help center", group: "Resources" }, +]; + +const alice: Author = { + pubkey: "npub1alice", + name: "Alice", + picture: "https://api.dicebear.com/9.x/thumbs/svg?seed=alice", +}; +const bob: Author = { + pubkey: "npub1bob", + name: "Bob", + picture: "https://api.dicebear.com/9.x/thumbs/svg?seed=bob", +}; +const carol: Author = { + pubkey: "npub1carol", + name: "Carol", + picture: "https://api.dicebear.com/9.x/thumbs/svg?seed=carol", +}; +const dave: Author = { + pubkey: "npub1dave", + name: "Dave", + picture: "https://api.dicebear.com/9.x/thumbs/svg?seed=dave", +}; + +export const threads: Thread[] = [ + { + id: "1", + title: "Discussion about an interesting topic", + tags: [ + { label: "general", color: "green" }, + { label: "nostr", color: "blue" }, + ], + op: { + id: "op1", + author: alice, + content: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n\nProin vitae ex iaculis, luctus elit in, fermentum turpis. Pellentesque sagittis congue quam erat, egestas a lobortis non, molestie ut enim. Sed tempus augue sapien laoreet, sed iaculis velit dictum diam.\n\nMaecenas sollicitudin erat eu metus lacinia congue. Nunc sagittis laoreet odio.", + createdAt: "2025-01-15T10:00:00Z", + reactions: [ + { emoji: "👍", count: 14 }, + { emoji: "🎉", count: 3 }, + ], + zaps: 1200, + replies: [ + { + id: "r1", + author: bob, + content: + "Etiam efficitur ornare odio, id elementum felis interdum sit amet. Nam tincidunt justo quam, eu rhoncus lectus pellentesque id.", + createdAt: "2025-01-15T11:00:00Z", + reactions: [{ emoji: "👍", count: 5 }], + zaps: 210, + }, + { + id: "r2", + author: carol, + content: + "Maecenas sollicitudin erat eu metus lacinia congue. Nunc sagittis laoreet odio, non molestie eros.", + createdAt: "2025-01-15T12:30:00Z", + reactions: [ + { emoji: "❤️", count: 2 }, + { emoji: "😂", count: 1 }, + ], + zaps: 0, + }, + ], + }, + replyCount: 12, + viewCount: 4200, + lastActivity: "4h", + participants: [alice, bob, carol, dave], + }, + { + id: "2", + title: + "Etiam pellentesque pulvinar quam sed interdum maximus pellentesque. Nam erat, egestas a lobortis non, molestie ut enim", + tags: [{ label: "question", color: "yellow" }], + op: { + id: "op2", + author: bob, + content: + "Etiam pellentesque pulvinar quam sed interdum. Vivamus fermentum accumsan lorem.", + createdAt: "2025-01-14T09:00:00Z", + reactions: [{ emoji: "👍", count: 2 }], + zaps: 0, + }, + replyCount: 0, + viewCount: 310, + lastActivity: "1d", + participants: [bob], + }, + { + id: "3", + title: "Pellentesque sagittis cinque quam et blandum", + tags: [ + { label: "meta", color: "pink" }, + { label: "proposal", color: "blue" }, + ], + op: { + id: "op3", + author: carol, + content: + "Phasellus nec velit quis luctus maximus pellentesque. Nam erat, egestas a lobortis non, molestie ut enim.", + createdAt: "2025-01-13T14:00:00Z", + reactions: [ + { emoji: "🎉", count: 7 }, + { emoji: "👍", count: 4 }, + ], + zaps: 850, + }, + replyCount: 7, + viewCount: 890, + lastActivity: "2d", + participants: [carol, alice, dave], + }, + { + id: "4", + title: + "Nam rutrum dolor in nulla maximus pellentesque. Nam erat, egestas a lobortis non, molestie ut enim imperdiet consequat", + tags: [{ label: "general", color: "green" }], + op: { + id: "op4", + author: dave, + content: + "Nam rutrum dolor in nulla imperdiet consequat. Sed tincidunt augue a velit.", + createdAt: "2025-01-12T08:00:00Z", + reactions: [], + zaps: 0, + }, + replyCount: 3, + viewCount: 140, + lastActivity: "3d", + participants: [dave, bob], + }, + { + id: "5", + title: + "Etiam maximus pellentesque. Nam erat, egestas a lobortis non, molestie ut enim efficitur ornare odio, id elementum felis", + tags: [ + { label: "nostr", color: "blue" }, + { label: "dev", color: "green" }, + ], + op: { + id: "op5", + author: alice, + content: + "Etiam efficitur ornare odio, id elementum felis interdum sit amet. Nam tincidunt justo quam.", + createdAt: "2025-01-11T16:00:00Z", + reactions: [{ emoji: "👍", count: 11 }], + zaps: 340, + }, + replyCount: 31, + viewCount: 4100, + lastActivity: "1h", + participants: [alice, carol, bob, dave], + }, + { + id: "6", + title: "Maecenas sollicitudin erat eu metus lacinia congue", + tags: [{ label: "announcement", color: "pink" }], + op: { + id: "op6", + author: carol, + content: + "Maecenas sollicitudin erat eu metus lacinia congue. Nunc sagittis laoreet odio.", + createdAt: "2025-01-10T12:00:00Z", + reactions: [{ emoji: "🎉", count: 9 }], + zaps: 500, + }, + replyCount: 5, + viewCount: 620, + lastActivity: "4d", + participants: [carol, dave], + }, + { + id: "7", + title: "Praesent blandit bibendum lectus, nec tristique nisl", + tags: [{ label: "general", color: "green" }], + op: { + id: "op7", + author: bob, + content: + "Praesent blandit bibendum lectus, nec tristique nisl nam rutrum.", + createdAt: "2025-01-09T10:00:00Z", + reactions: [], + zaps: 0, + }, + replyCount: 0, + viewCount: 95, + lastActivity: "5d", + participants: [bob], + }, +]; + +export type ChatMessage = { + id: string; + author: Author; + content: string; + createdAt: string; +}; + +export const chatMessages: ChatMessage[] = [ + { + id: "c1", + author: alice, + content: + "Quisque sagittis quam dui, nec pulvinar velit aliquam in. Sed volutpat in.", + createdAt: "2025-01-15T13:00:00Z", + }, + { + id: "c2", + author: bob, + content: + "Vivamus fermentum accumsan lorem, laoreet molestie lectus facilisis in.", + createdAt: "2025-01-15T13:02:00Z", + }, + { + id: "c3", + author: carol, + content: + "Proin vitae ex iaculis, luctus elit in, fermentum turpis. Pellentesque sagittis congue quam.", + createdAt: "2025-01-15T13:05:00Z", + }, + { + id: "c4", + author: dave, + content: + "Mauro dui dolor, sagittis id sem nec, rhoncus consequat duis. Suspendisse dapibus mauris maximus mauris imperdiet.", + createdAt: "2025-01-15T13:08:00Z", + }, + { + id: "c5", + author: alice, + content: + "In hac habitasse platea dictumst. Nulla a quam tempor, posuere neque non, fringilla velit.", + createdAt: "2025-01-15T13:10:00Z", + }, +]; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 0d8eb03..57d0b9c 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,9 +1,38 @@ - -{@render children()} + + + + +
+ +
+ +
+ {@render children()} +
+ {#if chatEnabled} + (chatExpanded = !chatExpanded)} + /> + {/if} +
+
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index cc88df0..378804a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,2 +1,25 @@ -

Welcome to SvelteKit

-

Visit svelte.dev/docs/kit to read the documentation

+ + + + Discussions + + +
+
+

Discussions

+ +
+ +
+ {#each threads as thread} + + {/each} +
+
diff --git a/src/routes/layout.css b/src/routes/layout.css index cd67023..2620aeb 100644 --- a/src/routes/layout.css +++ b/src/routes/layout.css @@ -1,3 +1,14 @@ -@import 'tailwindcss'; +@import "tailwindcss"; @plugin '@tailwindcss/forms'; @plugin '@tailwindcss/typography'; + +html { + font-size: 16px; +} + +@theme { + --color-brand: #e32a6d; + --color-brand-hover: #c4205a; + --color-accent: #ffaf25; + --color-accent-hover: #e69e1a; +} diff --git a/src/routes/room/[slug]/+page.svelte b/src/routes/room/[slug]/+page.svelte new file mode 100644 index 0000000..954a50b --- /dev/null +++ b/src/routes/room/[slug]/+page.svelte @@ -0,0 +1,29 @@ + + + + {room?.name ?? "Room"} + + +
+
+

{room?.name ?? slug}

+ +
+ +
+ {#each threads as thread} + + {/each} +
+
diff --git a/src/routes/thread/[id]/+page.svelte b/src/routes/thread/[id]/+page.svelte new file mode 100644 index 0000000..fbd5c63 --- /dev/null +++ b/src/routes/thread/[id]/+page.svelte @@ -0,0 +1,112 @@ + + + + {thread?.title ?? "Thread"} + + +{#if thread} +
+ +
+
+

{thread.title}

+
+
+ {#each thread.tags as tag} + + {/each} +
+
+ + +
+
+ {thread.op.author.name} +
+ {thread.op.author.name} + {formatDate(thread.op.createdAt)} +
+
+
+ {#each thread.op.content.split("\n\n") as para} +

{para}

+ {/each} +
+ +
+ + + {#if thread.op.replies && thread.op.replies.length > 0} +
+

+ {thread.op.replies.length} + {thread.op.replies.length === 1 ? "reply" : "replies"} +

+ {#each thread.op.replies as reply} +
+
+ {reply.author.name} +
+ {reply.author.name} + {formatDate(reply.createdAt)} +
+
+

{reply.content}

+ +
+ {/each} +
+ {/if} + + +
+ +
+ +
+
+
+{:else} +
Thread not found.
+{/if}