This commit is contained in:
@s.roertgen 2025-04-30 22:39:25 +02:00
parent 34781e8c29
commit 1878d82fad
7 changed files with 218 additions and 252 deletions

29
package-lock.json generated
View file

@ -774,37 +774,16 @@
} }
}, },
"node_modules/@nostr-dev-kit/ndk-svelte": { "node_modules/@nostr-dev-kit/ndk-svelte": {
"version": "2.4.10", "version": "2.4.11",
"resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk-svelte/-/ndk-svelte-2.4.10.tgz", "resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk-svelte/-/ndk-svelte-2.4.11.tgz",
"integrity": "sha512-meBNrgcVXqM/VFPO8LykhiSncMbqvfMWqbtRF4SOsLwDMbK7IigRKtuUUJoHvalEn+3OB2TZYp/FV9EIMHQ00w==", "integrity": "sha512-HCHFVQJ0lJBaGmMooJzmUhpTCATMtssbZsyYDLs729xl2xO//fOOGkiV3IUePhk0nKS85TfalP0aCXouQG/XMQ==",
"dependencies": { "dependencies": {
"@nostr-dev-kit/ndk": "2.14.4" "@nostr-dev-kit/ndk": "2.14.5"
}, },
"peerDependencies": { "peerDependencies": {
"svelte": "*" "svelte": "*"
} }
}, },
"node_modules/@nostr-dev-kit/ndk-svelte/node_modules/@nostr-dev-kit/ndk": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk/-/ndk-2.14.4.tgz",
"integrity": "sha512-mh7IoKvzDXoh6PJNyvrNVAMm6Zor1xyEKjnVfXQ11WTDXCwOA8Ksff1qxVQOn7u6ZlxlZN4wHBeUwWswuD9FSA==",
"dependencies": {
"@noble/curves": "^1.6.0",
"@noble/hashes": "^1.5.0",
"@noble/secp256k1": "^2.1.0",
"@scure/base": "^1.1.9",
"debug": "^4.3.6",
"light-bolt11-decoder": "^3.2.0",
"tseep": "^1.3.1",
"typescript-lru-cache": "^2"
},
"engines": {
"node": ">=16"
},
"peerDependencies": {
"nostr-tools": "^2"
}
},
"node_modules/@polka/url": { "node_modules/@polka/url": {
"version": "1.0.0-next.29", "version": "1.0.0-next.29",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",

View file

@ -3,17 +3,14 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { NDKEvent } from '@nostr-dev-kit/ndk'; import { NDKEvent } from '@nostr-dev-kit/ndk';
import { ndk, ndkReady, user } from '$lib/stores'; import { ndk } from '$lib/stores';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { login } from '$lib';
import { Carta, Markdown, MarkdownEditor } from 'carta-md'; import { Carta, Markdown, MarkdownEditor } from 'carta-md';
import 'carta-md/default.css'; /* Default theme */ import 'carta-md/default.css'; /* Default theme */
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import { Confetti } from "svelte-confetti" import { Confetti } from 'svelte-confetti';
console.log("show reactions", showReactions, event)
console.log('show reactions', showReactions, event);
// Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input) // Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input)
let carta = new Carta({ let carta = new Carta({
@ -21,7 +18,7 @@
}); });
let reactions = writable([]); let reactions = writable([]);
let reacted = writable(window.localStorage.getItem(event.id)); let reacted = writable(window.localStorage.getItem(event.id));
let reaction = writable({}) let reaction = writable({});
let clicked = writable(false); let clicked = writable(false);
async function sendReaction() { async function sendReaction() {
@ -31,28 +28,28 @@
tags: [['e', event.id]] tags: [['e', event.id]]
}); });
await reactionEvent.publish(); await reactionEvent.publish();
$reaction = reactionEvent; $reaction = reactionEvent;
const r = await $ndk.fetchEvents({ kinds: [7], '#e': [event.id] }); const r = await $ndk.fetchEvents({ kinds: [7], '#e': [event.id] });
console.log('r', r); console.log('r', r);
$reactions = Array.from(r); $reactions = Array.from(r);
window.localStorage.setItem(event.id, 'true'); window.localStorage.setItem(event.id, 'true');
$reacted = true; $reacted = 'true';
$clicked = true $clicked = true;
} }
async function deleteVote() { async function deleteVote() {
const deletionEvent = new NDKEvent($ndk, { const deletionEvent = new NDKEvent($ndk, {
kind: 5, kind: 5,
content: "User deleted vote", content: 'User deleted vote',
tags: [ tags: [
["e", event.id], ['e', event.id],
["k", 7] ['k', 7]
] ]
}) });
await deletionEvent.publish() await deletionEvent.publish();
window.localStorage.removeItem(event.id) window.localStorage.removeItem(event.id);
$reacted = false $reacted = 'false';
} }
onMount(async () => { onMount(async () => {
const r = await $ndk.fetchEvents({ kinds: [7], '#e': [event.id] }); const r = await $ndk.fetchEvents({ kinds: [7], '#e': [event.id] });
@ -65,12 +62,12 @@
<Markdown {carta} value={event.content} /> <Markdown {carta} value={event.content} />
{/key} {/key}
<div class="flex gap-2 reactions"> <div class="reactions flex gap-2">
{#if $reacted} {#if $reacted}
<span>👍 {$reactions.length}</span> <span>👍 {$reactions.length}</span>
<span class="thanks">Danke für deinen Vote!</span> <span class="thanks">Danke für deinen Vote!</span>
<!-- <button onclick={() => deleteVote()} class="btn">Vote zurückziehen</button> --> <!-- <button onclick={() => deleteVote()} class="btn">Vote zurückziehen</button> -->
{:else if showReactions === "true"} {:else if showReactions === 'true'}
<button onclick={() => sendReaction()} class="like">👍</button> <button onclick={() => sendReaction()} class="like">👍</button>
<span>{$reactions.length}</span> <span>{$reactions.length}</span>
{/if} {/if}
@ -79,19 +76,20 @@
{/if} {/if}
</div> </div>
</div> </div>
<style> <style>
.like { .like {
cursor: pointer; cursor: pointer;
} }
.reactions { .reactions {
padding-top: 10px; padding-top: 10px;
align-items: center; align-items: center;
} }
.thanks { .thanks {
color: #777; color: #777;
} }
.comment { .comment {
border-radius: 20px; border-radius: 20px;
border-color: #ccc; border-color: #ccc;
} }
</style> </style>

View file

@ -1,15 +1,12 @@
import { NDKNip07Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk"; import { NDKNip07Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { ndk as ndkStore, user as userStore } from "$lib/stores"; import { ndk } from "$lib/stores";
import { get } from "svelte/store"; import { get } from "svelte/store";
export async function login() { export async function login() {
let ndk = get(ndkStore)
let user = get(userStore)
if (window.nostr) { if (window.nostr) {
const signer = new NDKNip07Signer(); const signer = new NDKNip07Signer();
ndk.signer = signer; get(ndk).signer = signer;
const signedUser = await signer.user(); signer.user();
userStore.set(signedUser)
} else { } else {
console.log("no extension") console.log("no extension")
const storedPrivateKey = window.localStorage.getItem('nostrPrivateKey'); const storedPrivateKey = window.localStorage.getItem('nostrPrivateKey');
@ -17,24 +14,20 @@ export async function login() {
const privateKey = JSON.parse(storedPrivateKey); const privateKey = JSON.parse(storedPrivateKey);
console.log("stored private key", privateKey) console.log("stored private key", privateKey)
const signer = new NDKPrivateKeySigner(privateKey); const signer = new NDKPrivateKeySigner(privateKey);
const signedUser = await signer.user(); ndk.update((ndk) => {
userStore.set(signedUser) ndk.signer = signer;
ndk.signer = signer; return ndk;
console.log("ndk signer", ndk) });
ndkStore.set(ndk) // get(ndk).signer = signer;
signer.user();
} else { } else {
console.log('No private key found, generating a new one...'); console.log('No private key found, generating a new one...');
const privateKey = NDKPrivateKeySigner.generate(); const privateKey = NDKPrivateKeySigner.generate();
const signer = new NDKPrivateKeySigner(privateKey.privateKey); const signer = new NDKPrivateKeySigner(privateKey.privateKey);
console.log('Generated Private Key:', privateKey); console.log('Generated Private Key:', privateKey);
signer.user();
const signedUser = await signer.user();
userStore.set(signedUser)
window.localStorage.setItem('nostrPrivateKey', JSON.stringify(privateKey.privateKey)); window.localStorage.setItem('nostrPrivateKey', JSON.stringify(privateKey.privateKey));
ndk.signer = signer; get(ndk).signer = signer;
console.log("ndk signer", ndk)
ndkStore.set(ndk)
} }
} }
} }

View file

@ -1,27 +1,21 @@
import NDKSvelte from "@nostr-dev-kit/ndk-svelte"; import NDKSvelte from "@nostr-dev-kit/ndk-svelte";
import { writable, derived } from "svelte/store"; import { writable, derived } from "svelte/store";
import { NDKNip07Signer } from "@nostr-dev-kit/ndk"; import { NDKUser } from "@nostr-dev-kit/ndk";
export let connected = writable(false); export let connected = writable(false);
export const ndk = writable(new NDKSvelte()); const _ndk = new NDKSvelte({
explicitRelayUrls: [
'wss://relay-rpi.edufeed.org'
],
});
export const ndkReady = derived(ndk, $ndk => $ndk !== null); export const ndk = writable(_ndk)
export async function initializeNDK() { export const user = derived(ndk, $ndk => {
const signer = new NDKNip07Signer console.log("updating user")
const ndkInstance = new NDKSvelte({ if ($ndk.signer !== undefined) {
explicitRelayUrls: [ return new NDKUser($ndk.signer);
'wss://relay-rpi.edufeed.org' }
], return undefined;
}); });
await ndkInstance.connect();
// ndkInstance.signer = signer;
ndk.set(ndkInstance);
return ndkInstance;
}
export const user = writable(null);

View file

@ -1,22 +1,19 @@
<script> <script>
import '../app.css'; import '../app.css';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { NDKNip07Signer } from '@nostr-dev-kit/ndk'; import { ndk, connected } from '$lib/stores';
import NDKSvelte from '@nostr-dev-kit/ndk-svelte/svelte5';
import { ndk, connected, initializeNDK } from '$lib/stores';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import { login } from '$lib'; import { login } from '$lib';
let { children } = $props(); let { children } = $props();
onMount(async () => { onMount(async () => {
const nip07signer = new NDKNip07Signer();
if (browser) { if (browser) {
try { try {
await initializeNDK(); await login()
await $ndk.connect();
console.log('NDK initialized successfully'); console.log('NDK initialized successfully');
connected.set(true); connected.set(true);
await login()
} catch (error) { } catch (error) {
console.error('Failed to initialize NDK:', error); console.error('Failed to initialize NDK:', error);
} }

View file

@ -1,24 +1,23 @@
<script> <script>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { ndk, connected, user, ndkReady } from '$lib/stores'; import { ndk, connected, user } from '$lib/stores';
import { NDKEvent, NDKNip07Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk'; import { NDKEvent } from '@nostr-dev-kit/ndk';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import QRCode from 'qrcode'; import QRCode from 'qrcode';
import { login } from '$lib'; import { login } from '$lib';
import { Carta, MarkdownEditor } from 'carta-md'; import { Carta, MarkdownEditor } from 'carta-md';
import 'carta-md/default.css'; /* Default theme */ import 'carta-md/default.css'; /* Default theme */
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import { Confetti } from "svelte-confetti" import { Confetti } from 'svelte-confetti';
// Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input) // Create a new instance of Carta (you might also want to add a sanitizer if you're processing user input)
let carta = new Carta({ let carta = new Carta({
sanitizer: DOMPurify.sanitize sanitizer: DOMPurify.sanitize
}); });
let question = writable(''); let question = writable('');
let questionId = writable(''); ; let questionId = writable('');
let questionShortId = 0; let questionShortId = 0;
let qrCodeUrl = writable(''); let qrCodeUrl = writable('');
let timer = 0;
let votingEnabled = false; let votingEnabled = false;
let sessionId = ''; let sessionId = '';
let event = writable(); let event = writable();
@ -27,13 +26,13 @@
console.log('join ' + sessionId); console.log('join ' + sessionId);
const filter = { const filter = {
kinds: [1342], kinds: [1342],
'#d': [sessionId + ''], // filter by `d` tag '#d': [sessionId + ''] // filter by `d` tag
}; };
console.log(filter) console.log(filter);
const question = await $ndk.fetchEvent(filter); const question = await $ndk.fetchEvent(filter);
console.log('question', question); console.log('question', question);
goto('/q/' + question.id); goto('/q/' + question.id);
login() login();
} }
async function postQuestion() { async function postQuestion() {
questionShortId = 10000000 + Math.floor(Math.random() * 90000000); questionShortId = 10000000 + Math.floor(Math.random() * 90000000);
@ -43,39 +42,20 @@
tags: [['d', questionShortId + '']] tags: [['d', questionShortId + '']]
}); });
await $event.publishReplaceable(); await $event.publishReplaceable();
console.log("event id", $event.id) console.log('event id', $event.id);
$questionId = `${$event.kind}:${$event.pubkey}:${$event.dTag}`; $questionId = `${$event.kind}:${$event.pubkey}:${$event.dTag}`;
$qrCodeUrl = await QRCode.toDataURL(`${window.location.origin}/q/${$questionId}`, { $qrCodeUrl = await QRCode.toDataURL(`${window.location.origin}/q/${$questionId}`, {
width: 800, width: 800
}); });
} }
function startTimer() {
const interval = setInterval(() => {
if (timer > 0) {
timer--;
} else {
clearInterval(interval);
votingEnabled = true;
}
}, 1000);
}
$effect(() => {
if ($ndkReady) {
if ($ndk.activeUser) {
console.log('User:', $user);
} else {
login();
}
}
});
</script> </script>
<div class="main-layout"> <div class="main-layout">
<img src="logo.png" alt="" class="logo"> <img src="logo.png" alt="" class="logo" />
{#if !$user} {#if $ndk?.signer === undefined}
<div class="login"><button class="btn btn-primary" onclick={() => login()}>Login</button></div> <div class="login">
<button class="btn btn-primary" onclick={login}>Login</button>
</div>
{/if} {/if}
{#if !$questionId} {#if !$questionId}
@ -84,7 +64,9 @@
{#if $connected} {#if $connected}
<div class="join"> <div class="join">
<input type="number" class="border p-2" placeholder="12345678" bind:value={sessionId} /> <input type="number" class="border p-2" placeholder="12345678" bind:value={sessionId} />
<button class="btn btn-primary rounded" onclick={() => joinSession()}> Teilnehmen </button> <button class="btn btn-primary rounded" onclick={() => joinSession()}>
Teilnehmen
</button>
</div> </div>
{/if} {/if}
</div> </div>
@ -93,23 +75,36 @@
<div class="mx-auto p-4"> <div class="mx-auto p-4">
<h1 class="mb-4 text-2xl font-bold">Eine Ideensammlung starten</h1> <h1 class="mb-4 text-2xl font-bold">Eine Ideensammlung starten</h1>
{#if $connected} {#if $connected}
{#key $questionId} {#key $questionId}
{#if $questionId === ''} {#if $questionId === ''}
<div class="flex flex-col justify-center items-center"> <div class="flex flex-col items-center justify-center">
<MarkdownEditor bind:value={$question} {carta} /> <MarkdownEditor bind:value={$question} {carta} />
<div><button class="btn btn-primary rounded mt-5" onclick={postQuestion}> Starten </button></div> <div>
</div> <button class="btn btn-primary mt-5 rounded" onclick={postQuestion}> Starten </button>
{:else} </div>
<div class="qr-share mt-4"> </div>
<h2 class="text-xl font-bold">Diese Sammlung teilen</h2> {:else}
<h3 class="text-center short-id">{questionShortId}</h3> <div class="qr-share mt-4">
<div class="flex justify-center"><Confetti amount="600" size="15" cone x={[-4.5, 4.5]} y={[-1.5, 1.5]} delay={[0, 1000]} /></div> <h2 class="text-xl font-bold">Diese Sammlung teilen</h2>
<img src={$qrCodeUrl} alt="QR Code" class="mt-2" /> <h3 class="short-id text-center">{questionShortId}</h3>
<p class="mb-1 text-center">Diesen QR-Code oder Link teilen:</p> <div class="flex justify-center">
<p class="text-center mb-2 text-xl"> <Confetti
<a href={`/q/${$questionId}`}>{`${window.location.origin}/q/`}<span class="font-bold">{questionShortId}</span></a> amount="600"
</p> size="15"
<!-- cone
x={[-4.5, 4.5]}
y={[-1.5, 1.5]}
delay={[0, 1000]}
/>
</div>
<img src={$qrCodeUrl} alt="QR Code" class="mt-2" />
<p class="mb-1 text-center">Diesen QR-Code oder Link teilen:</p>
<p class="mb-2 text-center text-xl">
<a href={`/q/${$questionId}`}
>{`${window.location.origin}/q/`}<span class="font-bold">{questionShortId}</span></a
>
</p>
<!--
<div class="mt-4"> <div class="mt-4">
<label for="timer" class="mb-2 block">Set Timer (seconds):</label> <label for="timer" class="mb-2 block">Set Timer (seconds):</label>
<input type="number" id="timer" class="rounded border p-2" bind:value={timer} /> <input type="number" id="timer" class="rounded border p-2" bind:value={timer} />
@ -118,48 +113,48 @@
</button> </button>
</div> </div>
--> -->
</div> </div>
{/if} {/if}
{#if votingEnabled} {#if votingEnabled}
<div class="mt-4"> <div class="mt-4">
<h2 class="text-xl font-bold">Abstimmung ist jetzt aktiv!</h2> <h2 class="text-xl font-bold">Abstimmung ist jetzt aktiv!</h2>
<p>Es können jetzt Stimmen abgegeben werden.</p> <p>Es können jetzt Stimmen abgegeben werden.</p>
</div> </div>
{/if} {/if}
{/key} {/key}
{/if} {/if}
</div> </div>
</div> </div>
<style> <style>
:global(.carta-input) { :global(.carta-input) {
height: 150px !important; height: 150px !important;
}
:global(.carta-editor) {
width: 100% !important;
} }
:global(.carta-editor) {
width: 100% !important;
}
input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button { input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none; -webkit-appearance: none;
margin: 0; margin: 0;
} }
.short-id { .short-id {
font-size: 60px; font-size: 60px;
} }
.qr-share img { .qr-share img {
width: 100%; width: 100%;
border: 3px solid #eee; border: 3px solid #eee;
} }
.login { .login {
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
.logo { .logo {
display: flex; display: flex;
margin: 0 auto; margin: 0 auto;
max-width: 250px; max-width: 250px;
border-radius: 50%; border-radius: 50%;
} }
.main-layout { .main-layout {
margin: auto; margin: auto;

View file

@ -1,13 +1,13 @@
<script> <script>
import { Confetti } from 'svelte-confetti'; import { onDestroy } from 'svelte';
/** @type {import('./$types').PageProps} */ /** @type {import('./$types').PageProps} */
let { data } = $props(); let { data } = $props();
import Comment from '$lib/components/Comment.svelte'; import Comment from '$lib/components/Comment.svelte';
import { ndk, ndkReady, user } from '$lib/stores'; import { ndk, user } from '$lib/stores';
import { NDKEvent } from '@nostr-dev-kit/ndk'; import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
import { writable } from 'svelte/store'; import { derived, writable } from 'svelte/store';
import { Carta, Markdown, MarkdownEditor } from 'carta-md'; import { Carta, Markdown, MarkdownEditor } from 'carta-md';
import 'carta-md/default.css'; /* Default theme */ import 'carta-md/default.css'; /* Default theme */
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
@ -16,6 +16,7 @@
let carta = new Carta({ let carta = new Carta({
sanitizer: DOMPurify.sanitize sanitizer: DOMPurify.sanitize
}); });
function submitComment() { function submitComment() {
if (!$comment) { if (!$comment) {
return; return;
@ -24,61 +25,71 @@
const commentEvent = new NDKEvent($ndk, { const commentEvent = new NDKEvent($ndk, {
kind: 2222, kind: 2222,
content: $comment, content: $comment,
tags: [['E', data.id]] tags: [['A', data.id]]
}); });
commentEvent.publish(); commentEvent.publish();
comment.set(''); comment.set('');
setTimeout(() => submit.set(false), 3000);
}
/**
* Filters an array of objects to keep only unique objects based on their id property
* @param {Array} array - The array of objects to filter
* @returns {Array} - A new array containing only unique objects by id
*/
function getUniqueById(array) {
// Create a Map to track unique objects by their id
const uniqueMap = new Map();
// Loop through the array and add each object to the map with its id as the key
// This automatically overrides any previous entries with the same id
array.forEach((item) => {
if (item && item.id !== undefined) {
uniqueMap.set(item.id, item);
}
});
// Convert the Map values back to an array
return Array.from(uniqueMap.values());
} }
let comment = writable(''); let comment = writable('');
let submit = writable(false); let submit = writable(false);
let comments = writable([]);
let question = writable();
const [kind, pubkey, d] = data.id.split(':'); const [kind, pubkey, d] = data.id.split(':');
const showReactions = writable(false); const showReactions = writable('false');
const comments = writable([]);
let commentStore = $ndk.storeSubscribe(
{ kinds: [2222], '#A': [data.id] },
{
onEvent: (event) => {
console.log('Event received', event);
$comments = [event, ...$comments];
},
onEose: () => console.log('Subscription EOSE reached'),
closeOnEose: false,
autoStart: true
}
);
commentStore.ref();
let questionStore = $ndk.storeSubscribe({ kinds: [Number(kind)], authors: [pubkey], '#d': [d] });
questionStore.ref();
let question = derived(
[questionStore],
([$questionStore]) => {
if ($questionStore.length === 0) {
return null;
}
$questionStore.sort((a, b) => {
return b.created_at - a.created_at;
});
const reactionTag = $questionStore[0].tags.find((t) => t[0] === 'reactions');
if (reactionTag && reactionTag[1] === 'true') {
console.log('reactions enabled');
$showReactions = 'true';
}
console.log('question', $questionStore[0]);
return $questionStore[0];
},
null
);
onDestroy(() => {
commentStore.unsubscribe();
questionStore.unsubscribe();
});
$effect(() => { $effect(() => {
if ($ndkReady) { if ($ndk.signer) {
console.log('ndk ready'); console.log('got a signer');
const sub = $ndk.subscribe({ kinds: [2222], '#E': [data.id] }); console.log('start subscription');
sub.on('event', (event) => { commentStore.startSubscription();
console.log(event);
const unique = getUniqueById([...$comments, event]);
$comments = [...unique];
console.log(`${event.content}`);
});
const questionSub = $ndk.subscribe({ kinds: [Number(kind)], authors: [pubkey], '#d': [d] }); questionStore.startSubscription();
questionSub.on('event', (event) => { console.log('comment store', $commentStore);
$question = event;
if ($question?.tags.find((t) => t[0] === 'reactions')[1] === 'true') {
console.log('reactions enabled');
$showReactions = 'true';
}
});
} }
console.log('user', $user);
}); });
async function startReactions(event) { async function startReactions(event) {
@ -93,35 +104,34 @@
</script> </script>
<div class="main-layout mx-auto flex w-3/4 flex-col items-center justify-center"> <div class="main-layout mx-auto flex w-3/4 flex-col items-center justify-center">
{#if $question} {#key $question?.pubkey}
{#if $question.pubkey === $user.pubkey && $showReactions === false} {#if $question}
<button class="btn btn-primary mb-4" onclick={() => startReactions($question)} {#if $user && $question?.pubkey === $user?.pubkey && $showReactions === "false"}
>Reaktionen/Voting aktivieren</button <button class="btn btn-primary mb-4" onclick={() => startReactions($question)}
> >Reaktionen/Voting aktivieren</button
{/if} >
<div class="question mb-4 w-full rounded border p-4 text-xl">
<h2 class="text-xl font-bold">Frage / Thema:</h2>
<Markdown {carta} value={$question.content} />
</div>
<div class="mb-2 flex w-full flex-col items-center justify-center gap-2">
<h1 class="pt-15 text-xl font-bold">Meine Idee hinzufügen</h1>
<MarkdownEditor bind:value={$comment} {carta} />
<button class="btn btn-primary mt-5 mb-10" onclick={() => submitComment()}>Hinzufügen</button>
{#if $submit === true}
<div class="flex justify-center"><Confetti amount="50"} /></div>
{/if} {/if}
</div> <div class="question mb-4 w-full rounded border p-4 text-xl">
{:else} <h2 class="text-xl font-bold">Frage / Thema:</h2>
<p>Loading...</p> <Markdown {carta} value={$question.content} />
{/if} </div>
<div class="mb-2 flex w-full flex-col items-center justify-center gap-2">
<h1 class="pt-15 text-xl font-bold">Meine Idee hinzufügen</h1>
<MarkdownEditor bind:value={$comment} {carta} />
<button class="btn btn-primary mt-5 mb-10" onclick={() => submitComment()}
>Hinzufügen</button
>
</div>
{:else}
<p>Loading...</p>
{/if}
{/key}
<div class="mx-auto flex w-full flex-col items-center justify-center gap-5"> <div class="mx-auto flex w-full flex-col items-center justify-center gap-5">
{#key $showReactions} {#each $commentStore as event}
{#each $comments.sort((a, b) => b.created_at - a.created_at) as event} <Comment {event} showReactions={$showReactions} />
<Comment event={event} showReactions={$showReactions} /> {/each}
{/each}
{/key}
</div> </div>
</div> </div>