diff --git a/app/Livewire/Association/Election/Show.php b/app/Livewire/Association/Election/Show.php deleted file mode 100644 index 19d4ee9..0000000 --- a/app/Livewire/Association/Election/Show.php +++ /dev/null @@ -1,325 +0,0 @@ - ['icon' => 'fa-crown', 'title' => 'Präsidium'], - 'board' => ['icon' => 'fa-users', 'title' => 'Vizepräsidium'], - ]; - - protected $listeners = [ - 'nostrLoggedIn' => 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - 'echo:votes,.newVote' => 'handleNewVote', - ]; - - #[Computed] - public function loadedEvents(): array - { - return collect($this->events) - ->map(function ($event) { - $profile = Profile::query() - ->where('pubkey', $event['pubkey']) - ->first() - ?->toArray(); - $votedFor = Profile::query() - ->where('pubkey', str($event['content'])->before(',')->toString()) - ->first() - ?->toArray(); - - return [ - 'id' => $event['id'], - 'kind' => $event['kind'], - 'content' => $event['content'], - 'pubkey' => $event['pubkey'], - 'tags' => $event['tags'], - 'created_at' => $event['created_at'], - 'profile' => $profile, - 'votedFor' => $votedFor, - 'type' => str($event['content'])->after(',')->toString(), - ]; - }) - ->sortByDesc('created_at') - ->unique(fn ($event) => $event['pubkey'].$event['type']) - ->values() - ->toArray(); - } - - #[Computed] - public function loadedBoardEvents(): array - { - return collect($this->boardEvents) - ->map(function ($event) { - $profile = Profile::query() - ->where('pubkey', $event['pubkey']) - ->first() - ?->toArray(); - $votedFor = Profile::query() - ->where('pubkey', str($event['content'])->before(',')->toString()) - ->first() - ?->toArray(); - - return [ - 'id' => $event['id'], - 'kind' => $event['kind'], - 'content' => $event['content'], - 'pubkey' => $event['pubkey'], - 'tags' => $event['tags'], - 'created_at' => $event['created_at'], - 'profile' => $profile, - 'votedFor' => $votedFor, - 'type' => str($event['content'])->after(',')->toString(), - ]; - }) - ->sortByDesc('created_at') - ->values() - ->toArray(); - } - - #[Computed] - public function electionConfig(): array - { - $loadedEvents = $this->loadedEvents(); - - return collect(json_decode($this->election->candidates, true, 512, JSON_THROW_ON_ERROR)) - ->map(function ($c) use ($loadedEvents) { - $candidates = Profile::query() - ->whereIn('pubkey', $c['c']) - ->get() - ->map(function ($p) use ($loadedEvents, $c) { - $votedClass = ' bg-green-500/20 text-green-700'; - $notVotedClass = ' bg-gray-500/20 text-gray-100'; - $hasVoted = $loadedEvents - ->filter(fn ($e) => $e['type'] === $c['type'] && $e['pubkey'] === $this->currentPubkey) - ->firstWhere('votedFor.pubkey', $p->pubkey); - - return [ - 'pubkey' => $p->pubkey, - 'name' => $p->name, - 'picture' => $p->picture, - 'votedClass' => $hasVoted ? $votedClass : $notVotedClass, - ]; - }); - - return [ - 'type' => $c['type'], - 'c' => $c['c'], - 'candidates' => $candidates, - ]; - }) - ->toArray(); - } - - #[Computed] - public function electionConfigBoard(): array - { - $loadedBoardEvents = $this->loadedBoardEvents(); - - return collect(json_decode($this->election->candidates, true, 512, JSON_THROW_ON_ERROR)) - ->map(function ($c) use ($loadedBoardEvents) { - $candidates = Profile::query() - ->whereIn('pubkey', $c['c']) - ->get() - ->map(function ($p) use ($loadedBoardEvents, $c) { - $votedClass = ' bg-green-500/20 text-green-700'; - $notVotedClass = ' bg-gray-500/20 text-gray-100'; - $hasVoted = $loadedBoardEvents - ->filter(fn ($e) => $e['type'] === $c['type'] && $e['pubkey'] === $this->currentPubkey) - ->firstWhere('votedFor.pubkey', $p->pubkey); - - return [ - 'pubkey' => $p->pubkey, - 'name' => $p->name, - 'picture' => $p->picture, - 'votedClass' => $hasVoted ? $votedClass : $notVotedClass, - 'hasVoted' => $hasVoted, - ]; - }); - - return [ - 'type' => $c['type'], - 'c' => $c['c'], - 'candidates' => $candidates, - ]; - }) - ->toArray(); - } - - public function mount(Election $election): void - { - $this->election = $election; - $this->plebs = EinundzwanzigPleb::query() - ->with(['profile']) - ->whereIn('association_status', [3, 4]) - ->orderBy('association_status', 'desc') - ->get() - ->toArray(); - $this->loadEvents(); - $this->loadBoardEvents(); - if ($this->election->end_time?->isPast() || ! config('services.voting')) { - $this->isNotClosed = false; - } - } - - public function updatedSearch($value): void - { - $this->plebs = EinundzwanzigPleb::query() - ->with(['profile']) - ->whereIn('association_status', [3, 4]) - ->where(fn ($query) => $query - ->where('pubkey', 'like', "%$value%") - ->orWhereHas('profile', fn ($query) => $query->where('name', 'ilike', "%$value%"))) - ->orderBy('association_status', 'desc') - ->get() - ->toArray(); - } - - public function handleNostrLoggedIn($pubkey): void - { - NostrAuth::login($pubkey); - $this->currentPubkey = $pubkey; - $this->currentPleb = EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); - $logPubkeys = [ - '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033', - '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279', - ]; - if (in_array($this->currentPubkey, $logPubkeys, true)) { - $this->showLog = true; - $this->isAllowed = true; - } - } - - public function handleNostrLoggedOut(): void - { - $this->isAllowed = false; - $this->currentPubkey = null; - $this->currentPleb = null; - } - - public function handleNewVote(): void - { - $this->loadEvents(); - $this->loadBoardEvents(); - } - - public function loadEvents(): void - { - $this->events = $this->loadNostrEvents([32122]); - } - - public function loadBoardEvents(): void - { - $this->boardEvents = $this->loadNostrEvents([2121]); - } - - public function loadNostrEvents($kinds): array - { - $subscription = new Subscription; - $subscriptionId = $subscription->setId(); - $filter = new Filter; - $filter->setKinds($kinds); - $requestMessage = new RequestMessage($subscriptionId, [$filter]); - $relaySet = new RelaySet; - $relaySet->setRelays([new Relay(config('services.relay'))]); - $request = new Request($relaySet, $requestMessage); - $response = $request->send(); - - return collect($response[config('services.relay')]) - ->map(function ($event) { - if (! isset($event->event)) { - return false; - } - - return [ - 'id' => $event->event->id, - 'kind' => $event->event->kind, - 'content' => $event->event->content, - 'pubkey' => $event->event->pubkey, - 'tags' => $event->event->tags, - 'created_at' => $event->event->created_at, - ]; - }) - ->filter() - ->toArray(); - } - - public function vote($pubkey, $type, $board = false): void - { - if ($this->election->end_time?->isPast()) { - $this->isNotClosed = false; - - return; - } - $note = new NostrEvent; - $note->setKind($board ? 2121 : 32122); - if (! $board) { - $dTag = sprintf('%s,%s,%s', $this->currentPleb->pubkey, date('Y'), $type); - $note->setTags([['d', $dTag]]); - } - $note->setContent("$pubkey,$type"); - $this->signThisEvent = $note->toJson(); - } - - public function checkElection(): void - { - if ($this->election->end_time?->isPast()) { - $this->isNotClosed = false; - } - } - - public function signEvent($event): void - { - $note = new NostrEvent; - $note->setId($event['id']); - $note->setSignature($event['sig']); - $note->setKind($event['kind']); - $note->setContent($event['content']); - $note->setPublicKey($event['pubkey']); - $note->setTags($event['tags']); - $note->setCreatedAt($event['created_at']); - $eventMessage = new EventMessage($note); - $relay = new Relay(config('services.relay')); - $relay->setMessage($eventMessage); - $relay->send(); - \App\Support\Broadcast::on('votes')->as('newVote')->sendNow(); - } -} diff --git a/app/Livewire/Association/News/Index.php b/app/Livewire/Association/News/Index.php deleted file mode 100644 index 64e1664..0000000 --- a/app/Livewire/Association/News/Index.php +++ /dev/null @@ -1,122 +0,0 @@ - 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - ]; - - public function mount(): void - { - if (NostrAuth::check()) { - $this->currentPubkey = NostrAuth::pubkey(); - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first(); - if (in_array($this->currentPleb->npub, config('einundzwanzig.config.current_board'), true)) { - $this->canEdit = true; - } - $this->isAllowed = true; - } - $this->refreshNews(); - } - - public function refreshNews(): void - { - $this->news = Notification::query() - ->orderBy('created_at', 'desc') - ->get(); - } - - public function handleNostrLoggedIn($pubkey): void - { - NostrAuth::login($pubkey); - $this->currentPubkey = $pubkey; - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); - if (in_array($this->currentPleb->npub, config('einundzwanzig.config.current_board'), true)) { - $this->canEdit = true; - } - $this->isAllowed = true; - } - - public function handleNostrLoggedOut(): void - { - $this->isAllowed = false; - $this->currentPubkey = null; - $this->currentPleb = null; - } - - public function save(): void - { - $this->form->validate(); - - $this->validate([ - 'file' => 'required|file|mimes:pdf|max:1024', - ]); - - $notification = Notification::query() - ->orderBy('created_at', 'desc') - ->create([ - 'einundzwanzig_pleb_id' => $this->currentPleb->id, - 'category' => $this->form->category, - 'name' => $this->form->name, - 'description' => $this->form->description, - ]); - - $notification - ->addMedia($this->file->getRealPath()) - ->usingName($this->file->getClientOriginalName()) - ->toMediaCollection('pdf'); - - $this->form->reset(); - $this->file = null; - - $this->refreshNews(); - } - - public function delete($id): void - { - $notification = new WireNotification($this); - $notification->confirm([ - 'title' => 'Post löschen', - 'message' => 'Bist du sicher, dass du diesen Post löschen möchtest?', - 'accept' => [ - 'label' => 'Ja, löschen', - 'method' => 'deleteNow', - 'params' => $id, - ], - ]); - } - - public function deleteNow($id): void - { - $notification = Notification::query()->find($id); - $notification->delete(); - $this->refreshNews(); - } -} diff --git a/app/Livewire/Association/Profile.php b/app/Livewire/Association/Profile.php deleted file mode 100644 index 19288fe..0000000 --- a/app/Livewire/Association/Profile.php +++ /dev/null @@ -1,304 +0,0 @@ - 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - ]; - - public function mount(): void - { - if (NostrAuth::check()) { - $this->currentPubkey = NostrAuth::pubkey(); - $this->currentPleb = EinundzwanzigPleb::query() - ->with([ - 'paymentEvents' => fn ($query) => $query->where('year', date('Y')), - ]) - ->where('pubkey', $this->currentPubkey)->first(); - $this->email = $this->currentPleb->email; - $this->no = $this->currentPleb->no_email; - $this->showEmail = ! $this->no; - if ($this->currentPleb->association_status === AssociationStatus::ACTIVE) { - $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; - } - if ($this->currentPleb->paymentEvents->count() < 1) { - $this->createPaymentEvent(); - $this->currentPleb->load('paymentEvents'); - } - $this->loadEvents(); - $this->listenForPayment(); - } - } - - public function handleNostrLoggedIn($pubkey): void - { - NostrAuth::login($pubkey); - - $this->currentPubkey = $pubkey; - $this->currentPleb = EinundzwanzigPleb::query() - ->with([ - 'paymentEvents' => fn ($query) => $query->where('year', date('Y')), - ]) - ->where('pubkey', $pubkey)->first(); - $this->email = $this->currentPleb->email; - $this->no = $this->currentPleb->no_email; - $this->showEmail = ! $this->no; - if ($this->currentPleb->association_status === AssociationStatus::ACTIVE) { - $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; - } - if ($this->currentPleb->paymentEvents->count() < 1) { - $this->createPaymentEvent(); - $this->currentPleb->load('paymentEvents'); - } - $this->loadEvents(); - $this->listenForPayment(); - } - - public function handleNostrLoggedOut(): void - { - NostrAuth::logout(); - - $this->currentPubkey = null; - $this->currentPleb = null; - $this->yearsPaid = []; - $this->events = []; - $this->payments = []; - $this->qrCode = null; - $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; - $this->currentYearIsPaid = false; - } - - public function updatedNo(): void - { - $this->showEmail = ! $this->no; - $this->currentPleb->update([ - 'no_email' => $this->no, - ]); - } - - public function updatedFax(): void - { - $this->js('alert("Markus Turm wird sich per Fax melden!")'); - } - - public function saveEmail(): void - { - $this->validate([ - 'email' => 'required|email', - ]); - $this->currentPleb->update([ - 'email' => $this->email, - ]); - $notification = new Notification($this); - $notification->success('E-Mail Adresse gespeichert.'); - } - - public function pay($comment): \Illuminate\Http\RedirectResponse - { - $paymentEvent = $this->currentPleb - ->paymentEvents() - ->where('year', date('Y')) - ->first(); - if ($paymentEvent->btc_pay_invoice) { - return redirect('https://pay.einundzwanzig.space/i/'.$paymentEvent->btc_pay_invoice); - } - try { - $response = \Illuminate\Support\Facades\Http::withHeaders([ - 'Authorization' => 'token '.config('services.btc_pay.api_key'), - ])->post( - 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices', - [ - 'amount' => $this->amountToPay, - 'metadata' => [ - 'orderId' => $comment, - 'orderUrl' => url()->route('association.profile'), - 'itemDesc' => 'Mitgliedsbeitrag '.date('Y').' von nostr:'.$this->currentPleb->npub, - 'posData' => [ - 'event' => $paymentEvent->event_id, - 'pubkey' => $this->currentPleb->pubkey, - 'npub' => $this->currentPleb->npub, - ], - ], - 'checkout' => [ - 'expirationMinutes' => 60 * 24, - 'redirectURL' => url()->route('association.profile'), - 'redirectAutomatically' => true, - 'defaultLanguage' => 'de', - ], - ], - )->throw(); - $paymentEvent->btc_pay_invoice = $response->json()['id']; - $paymentEvent->save(); - - return redirect($response->json()['checkoutLink']); - } catch (\Exception $e) { - $notification = new Notification($this); - $notification->error( - 'Fehler beim Erstellen der Rechnung. Bitte versuche es später erneut: '.$e->getMessage(), - ); - } - } - - public function listenForPayment(): void - { - $paymentEvent = $this->currentPleb - ->paymentEvents() - ->where('year', date('Y')) - ->first(); - if ($paymentEvent->btc_pay_invoice) { - $response = \Illuminate\Support\Facades\Http::withHeaders([ - 'Authorization' => 'token '.config('services.btc_pay.api_key'), - ]) - ->get( - 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices/'.$paymentEvent->btc_pay_invoice, - ); - if ($response->json()['status'] === 'Expired') { - $paymentEvent->btc_pay_invoice = null; - $paymentEvent->paid = false; - $paymentEvent->save(); - } - if ($response->json()['status'] === 'Settled') { - $paymentEvent->paid = true; - $paymentEvent->save(); - $this->currentYearIsPaid = true; - } - } - if ($paymentEvent->paid) { - $this->currentYearIsPaid = true; - } - $paymentEvent = $paymentEvent->refresh(); - $this->payments = $this->currentPleb - ->paymentEvents() - ->where('paid', true) - ->get(); - } - - public function save($type): void - { - $this->form->validate(); - if (! $this->form->check) { - $this->js('alert("Du musst den Statuten zustimmen.")'); - - return; - } - - $this->currentPleb - ->update([ - 'association_status' => $type, - ]); - } - - public function createPaymentEvent(): void - { - $note = new NostrEvent; - $note->setKind(32121); - $note->setContent( - 'Dieses Event dient der Zahlung des Mitgliedsbeitrags für das Jahr '.date( - 'Y', - ).'. Bitte bezahle den Betrag von '.number_format($this->amountToPay, 0, ',', '.').' Satoshis.', - ); - $note->setTags([ - ['d', $this->currentPleb->pubkey.','.date('Y')], - ['zap', 'daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6', config('services.relay'), '1'], - ]); - $signer = new Sign; - $signer->signEvent($note, config('services.nostr')); - - $eventMessage = new EventMessage($note); - - $relayUrl = config('services.relay'); - $relay = new Relay($relayUrl); - $relay->setMessage($eventMessage); - $result = $relay->send(); - - $this->currentPleb->paymentEvents()->create([ - 'year' => date('Y'), - 'event_id' => $result->eventId, - 'amount' => $this->amountToPay, - ]); - } - - public function loadEvents(): void - { - $subscription = new Subscription; - $subscriptionId = $subscription->setId(); - - $filter1 = new Filter; - $filter1->setKinds([32121]); - $filter1->setAuthors(['daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6']); - $filters = [$filter1]; - - $requestMessage = new RequestMessage($subscriptionId, $filters); - - $relays = [ - new Relay(config('services.relay')), - ]; - $relaySet = new RelaySet; - $relaySet->setRelays($relays); - - $request = new Request($relaySet, $requestMessage); - $response = $request->send(); - - $this->events = collect($response[config('services.relay')]) - ->map(function ($event) { - if (! isset($event->event)) { - return false; - } - - return [ - 'id' => $event->event->id, - 'kind' => $event->event->kind, - 'content' => $event->event->content, - 'pubkey' => $event->event->pubkey, - 'tags' => $event->event->tags, - 'created_at' => $event->event->created_at, - ]; - }) - ->filter() - ->unique('id') - ->toArray(); - } -} diff --git a/app/Livewire/Association/ProjectSupport/Form/Create.php b/app/Livewire/Association/ProjectSupport/Form/Create.php deleted file mode 100644 index 96c4f7c..0000000 --- a/app/Livewire/Association/ProjectSupport/Form/Create.php +++ /dev/null @@ -1,70 +0,0 @@ - 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - ]; - - public function mount(): void - { - if (NostrAuth::check()) { - $this->currentPubkey = NostrAuth::pubkey(); - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first(); - $this->isAllowed = true; - } - } - - public function handleNostrLoggedIn($pubkey): void - { - NostrAuth::login($pubkey); - $this->currentPubkey = $pubkey; - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); - $this->isAllowed = true; - } - - public function handleNostrLoggedOut(): void - { - $this->isAllowed = false; - $this->currentPubkey = null; - $this->currentPleb = null; - } - - public function save(): \Illuminate\Http\RedirectResponse - { - $this->form->validate(); - - $projectProposal = \App\Models\ProjectProposal::query()->create([ - ...$this->form->all(), - 'einundzwanzig_pleb_id' => $this->currentPleb->id, - ]); - if ($this->image) { - $this->validate([ - 'image' => 'image|max:1024', - ]); - $projectProposal - ->addMedia($this->image->getRealPath()) - ->toMediaCollection('main'); - } - - return redirect()->route('association.projectSupport'); - } -} diff --git a/app/Livewire/Association/ProjectSupport/Form/Edit.php b/app/Livewire/Association/ProjectSupport/Form/Edit.php deleted file mode 100644 index 781c3b6..0000000 --- a/app/Livewire/Association/ProjectSupport/Form/Edit.php +++ /dev/null @@ -1,75 +0,0 @@ - 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - ]; - - public function mount(ProjectProposal $projectProposal): void - { - if (NostrAuth::check()) { - $this->currentPubkey = NostrAuth::pubkey(); - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first(); - $this->isAllowed = true; - $this->form->fill($projectProposal->toArray()); - $this->projectProposal = $projectProposal; - $this->image = $projectProposal->getFirstMedia('main'); - } - } - - public function handleNostrLoggedIn($pubkey): void - { - NostrAuth::login($pubkey); - $this->currentPubkey = $pubkey; - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); - $this->isAllowed = true; - } - - public function handleNostrLoggedOut(): void - { - $this->isAllowed = false; - $this->currentPubkey = null; - $this->currentPleb = null; - } - - public function save(): \Illuminate\Http\RedirectResponse - { - $this->form->validate(); - if ($this->image && method_exists($this->image, 'temporaryUrl')) { - $this->validate([ - 'image' => 'nullable|image|max:1024', - ]); - $this->projectProposal - ->addMedia($this->image->getRealPath()) - ->toMediaCollection('main'); - } - - $this->projectProposal->update([ - ...$this->form->except('id', 'slug'), - ]); - - return redirect()->route('association.projectSupport'); - } -} diff --git a/app/Livewire/Association/ProjectSupport/Index.php b/app/Livewire/Association/ProjectSupport/Index.php deleted file mode 100644 index 4c64dc1..0000000 --- a/app/Livewire/Association/ProjectSupport/Index.php +++ /dev/null @@ -1,102 +0,0 @@ - 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - ]; - - public function mount(): void - { - $this->loadProjects(); - if (NostrAuth::check()) { - $this->currentPubkey = NostrAuth::pubkey(); - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first(); - $this->isAllowed = true; - } - } - - public function updatedSearch(): void - { - $this->loadProjects(); - } - - public function loadProjects(): void - { - $this->projects = ProjectProposal::query() - ->with([ - 'einundzwanzigPleb.profile', - 'votes', - ]) - ->where(function ($query) { - $query - ->where('name', 'ilike', '%'.$this->search.'%') - ->orWhere('description', 'ilike', '%'.$this->search.'%') - ->orWhereHas('einundzwanzigPleb.profile', function ($q) { - $q->where('name', 'ilike', '%'.$this->search.'%'); - }); - }) - ->orderBy('created_at', 'desc') - ->get(); - } - - public function handleNostrLoggedIn($pubkey): void - { - NostrAuth::login($pubkey); - $this->currentPubkey = $pubkey; - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); - $this->isAllowed = true; - } - - public function handleNostrLoggedOut(): void - { - $this->isAllowed = false; - $this->currentPubkey = null; - $this->currentPleb = null; - } - - public function confirmDelete($id): void - { - $notification = new Notification($this); - $notification->confirm([ - 'title' => 'Projektunterstützung löschen', - 'message' => 'Bist du sicher, dass du diese Projektunterstützung löschen möchtest?', - 'accept' => [ - 'label' => 'Ja, löschen', - 'method' => 'delete', - 'params' => $id, - ], - ]); - } - - public function setFilter($filter): void - { - $this->activeFilter = $filter; - } - - public function delete($id): void - { - ProjectProposal::query()->findOrFail($id)->delete(); - $this->loadProjects(); - } -} diff --git a/app/Livewire/Association/ProjectSupport/Show.php b/app/Livewire/Association/ProjectSupport/Show.php deleted file mode 100644 index 0dab2d1..0000000 --- a/app/Livewire/Association/ProjectSupport/Show.php +++ /dev/null @@ -1,109 +0,0 @@ - 'handleNostrLoggedIn', - 'nostrLoggedOut' => 'handleNostrLoggedOut', - ]; - - public function mount(ProjectProposal $projectProposal): void - { - $this->projectProposal = $projectProposal; - if (NostrAuth::check()) { - $this->currentPubkey = NostrAuth::pubkey(); - $this->handleNostrLoggedIn($this->currentPubkey); - } - $this->boardVotes = $this->getBoardVotes(); - $this->otherVotes = $this->getOtherVotes(); - } - - public function handleNostrLoggedIn($pubkey): void - { - $this->currentPubkey = $pubkey; - $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); - $this->isAllowed = true; - $this->ownVoteExists = Vote::query() - ->where('project_proposal_id', $this->projectProposal->id) - ->where('einundzwanzig_pleb_id', $this->currentPleb->id) - ->exists(); - } - - public function handleNostrLoggedOut(): void - { - $this->isAllowed = false; - $this->currentPubkey = null; - $this->currentPleb = null; - } - - public function getBoardVotes(): \Illuminate\Database\Eloquent\Collection - { - return Vote::query() - ->where('project_proposal_id', $this->projectProposal->id) - ->whereHas('einundzwanzigPleb', fn ($q) => $q->whereIn('npub', config('einundzwanzig.config.current_board'))) - ->get(); - } - - public function getOtherVotes(): \Illuminate\Database\Eloquent\Collection - { - return Vote::query() - ->where('project_proposal_id', $this->projectProposal->id) - ->whereDoesntHave( - 'einundzwanzigPleb', - fn ($q) => $q->whereIn('npub', config('einundzwanzig.config.current_board')) - ) - ->get(); - } - - public function approve(): void - { - Vote::query()->updateOrCreate([ - 'project_proposal_id' => $this->projectProposal->id, - 'einundzwanzig_pleb_id' => $this->currentPleb->id, - ], [ - 'value' => true, - ]); - $this->form->reset(); - $this->ownVoteExists = true; - $this->boardVotes = $this->getBoardVotes(); - $this->otherVotes = $this->getOtherVotes(); - } - - public function notApprove(): void - { - $this->form->validate(); - - Vote::query()->updateOrCreate([ - 'project_proposal_id' => $this->projectProposal->id, - 'einundzwanzig_pleb_id' => $this->currentPleb->id, - ], [ - 'value' => false, - ]); - $this->form->reset(); - $this->ownVoteExists = true; - } -} diff --git a/app/Livewire/Changelog.php b/app/Livewire/Changelog.php deleted file mode 100644 index 8104dcc..0000000 --- a/app/Livewire/Changelog.php +++ /dev/null @@ -1,31 +0,0 @@ -run(); - $output = $process->getOutput(); - $lines = explode("\n", trim($output)); - $entries = []; - - foreach ($lines as $line) { - [$hash, $message, $author, $date] = explode('|', $line); - $entries[] = [ - 'hash' => $hash, - 'message' => $message, - 'author' => $author, - 'date' => $date, - ]; - } - $this->entries = $entries; - } -} diff --git a/app/Livewire/EinundzwanzigFeed/Index.php b/app/Livewire/EinundzwanzigFeed/Index.php deleted file mode 100644 index 595d6ba..0000000 --- a/app/Livewire/EinundzwanzigFeed/Index.php +++ /dev/null @@ -1,51 +0,0 @@ -events = Event::query() - ->where('type', 'root') - ->orderBy('created_at', 'desc') - ->with([ - 'renderedEvent', - ]) - ->get() - ->toArray(); - } - - public function hydrate(): void - { - if ($this->newEvents) { - $this->loadMore(); - } - } - - #[Rule('echo:events,.newEvents')] - public function updated(): void - { - $this->newEvents = true; - } - - public function loadMore(): void - { - $this->newEvents = false; - $this->events = Event::query() - ->where('type', 'root') - ->orderBy('created_at', 'desc') - ->with([ - 'renderedEvent', - ]) - ->get() - ->toArray(); - } -} diff --git a/app/Livewire/Meetups/Grid.php b/app/Livewire/Meetups/Grid.php deleted file mode 100644 index 5eef74c..0000000 --- a/app/Livewire/Meetups/Grid.php +++ /dev/null @@ -1,10 +0,0 @@ -loadEvents(); - } - - public function loadEvents(): void - { - $subscription = new Subscription; - $subscriptionId = $subscription->setId(); - - $filter1 = new Filter; - $filter1->setKinds([31924]); - $filter1->setLimit(25); - $filters = [$filter1]; - - $requestMessage = new RequestMessage($subscriptionId, $filters); - - $relays = [ - new Relay('ws://nostream:8008'), - ]; - $relaySet = new RelaySet; - $relaySet->setRelays($relays); - - $request = new Request($relaySet, $requestMessage); - $response = $request->send(); - - $this->events = collect($response['ws://nostream:8008']) - ->map(function ($event) { - if (! isset($event->event)) { - return false; - } - - return [ - 'id' => $event->event->id, - 'kind' => $event->event->kind, - 'content' => $event->event->content, - 'pubkey' => $event->event->pubkey, - 'tags' => $event->event->tags, - 'created_at' => $event->event->created_at, - ]; - }) - ->filter() - ->toArray(); - } - - public function save(): void - { - $note = new NostrEvent; - $note->setContent($this->description); - $note->setKind(31924); - $note->setTags([ - ['d', str()->uuid()->toString()], - ['title', $this->title], - ]); - $this->signThisEvent = $note->toJson(); - } - - public function signEvent($event): void - { - $note = new NostrEvent; - $note->setId($event['id']); - $note->setSignature($event['sig']); - $note->setKind($event['kind']); - $note->setContent($event['content']); - $note->setPublicKey($event['pubkey']); - $note->setTags($event['tags']); - $note->setCreatedAt($event['created_at']); - $eventMessage = new EventMessage($note); - $relayUrl = 'ws://nostream:8008'; - $relay = new Relay($relayUrl); - $relay->setMessage($eventMessage); - $relay->send(); - - $this->title = ''; - $this->description = ''; - $this->loadEvents(); - } -} diff --git a/app/Livewire/Meetups/Table.php b/app/Livewire/Meetups/Table.php deleted file mode 100644 index 0685fbd..0000000 --- a/app/Livewire/Meetups/Table.php +++ /dev/null @@ -1,10 +0,0 @@ -markers = []; - } - - public function filterByMarker($id): void - { - // - } -} diff --git a/app/Livewire/Welcome.php b/app/Livewire/Welcome.php deleted file mode 100644 index 403d86c..0000000 --- a/app/Livewire/Welcome.php +++ /dev/null @@ -1,10 +0,0 @@ -filter() ->toArray(); } -} +}; +?> + +
+ @php + $positions = [ + 'presidency' => ['icon' => 'fa-crown', 'title' => 'Präsidium'], + 'board' => ['icon' => 'fa-users', 'title' => 'Vorstandsmitglieder'], + ]; + @endphp + + @if($isAllowed) + +
+ + +
+ + +
+

+ Wahl des Vorstands {{ $election->year }} +

+
+ +
+ + @php + $president = $positions['presidency']; + $board = $positions['board']; + @endphp + + +
+
+
+

{{ $president['title'] }} +

+
+
+ + +
+
+
+
+

{{ $board['title'] }} +

+
+
+ + +
+
+
+ +
+ + @else +
+
+
+

Mitglieder

+

+ Du bist nicht berechtigt, Mitglieder zu bearbeiten. +

+
+
+
+ @endif +
diff --git a/app/Livewire/Association/Election/Index.php b/resources/views/components/association/election/⚡index.blade.php similarity index 56% rename from app/Livewire/Association/Election/Index.php rename to resources/views/components/association/election/⚡index.blade.php index eb4c3be..feac298 100644 --- a/app/Livewire/Association/Election/Index.php +++ b/resources/views/components/association/election/⚡index.blade.php @@ -1,14 +1,14 @@ candidates = $election['candidates']; $electionModel->save(); } -} +}; +?> + +
+ @if($isAllowed) +
+ @foreach($elections as $election) +
+
+ {{ $election['year'] }} +
+
+ +
+
+ +
+
+ @endforeach +
+ @else +
+
+
+

Einstellungen

+

+ Du bist nicht berechtigt, die Einstellungen zu bearbeiten. +

+
+
+
+ @endif +
diff --git a/resources/views/livewire/association/election/show.blade.php b/resources/views/components/association/election/⚡show.blade.php similarity index 54% rename from resources/views/livewire/association/election/show.blade.php rename to resources/views/components/association/election/⚡show.blade.php index 732b96a..e32dfa1 100644 --- a/resources/views/livewire/association/election/show.blade.php +++ b/resources/views/components/association/election/⚡show.blade.php @@ -1,148 +1,476 @@ - -
- @if($isAllowed) -
+ -
-
+use App\Models\Election; +use App\Models\EinundzwanzigPleb; +use App\Models\Profile; +use App\Support\NostrAuth; +use Livewire\Attributes\Computed; +use Livewire\Component; +use swentel\nostr\Event\Event as NostrEvent; +use swentel\nostr\Filter\Filter; +use swentel\nostr\Message\EventMessage; +use swentel\nostr\Message\RequestMessage; +use swentel\nostr\Relay\Relay; +use swentel\nostr\Relay\RelaySet; +use swentel\nostr\Request\Request; +use swentel\nostr\Subscription\Subscription; - -
- -
-
-
- -
- -
- +new class extends Component { + public bool $isAllowed = false; + + public bool $showLog = false; + + public ?string $currentPubkey = null; + + public ?EinundzwanzigPleb $currentPleb = null; + + public array $events = []; + + public array $boardEvents = []; + + public Election $election; + + public array $plebs = []; + + public string $search = ''; + + public string $signThisEvent = ''; + + public bool $isNotClosed = true; + + public array $positions = [ + 'presidency' => ['icon' => 'fa-crown', 'title' => 'Präsidium'], + 'board' => ['icon' => 'fa-users', 'title' => 'Vizepräsidium'], + ]; + + protected $listeners = [ + 'nostrLoggedIn' => 'handleNostrLoggedIn', + 'nostrLoggedOut' => 'handleNostrLoggedOut', + 'echo:votes,.newVote' => 'handleNewVote', + ]; + + #[Computed] + public function loadedEvents(): array + { + return collect($this->events) + ->map(function ($event) { + $profile = Profile::query() + ->where('pubkey', $event['pubkey']) + ->first() + ?->toArray(); + $votedFor = Profile::query() + ->where('pubkey', str($event['content'])->before(',')->toString()) + ->first() + ?->toArray(); + + return [ + 'id' => $event['id'], + 'kind' => $event['kind'], + 'content' => $event['content'], + 'pubkey' => $event['pubkey'], + 'tags' => $event['tags'], + 'created_at' => $event['created_at'], + 'profile' => $profile, + 'votedFor' => $votedFor, + 'type' => str($event['content'])->after(',')->toString(), + ]; + }) + ->sortByDesc('created_at') + ->unique(fn ($event) => $event['pubkey'].$event['type']) + ->values() + ->toArray(); + } + + #[Computed] + public function loadedBoardEvents(): array + { + return collect($this->boardEvents) + ->map(function ($event) { + $profile = Profile::query() + ->where('pubkey', $event['pubkey']) + ->first() + ?->toArray(); + $votedFor = Profile::query() + ->where('pubkey', str($event['content'])->before(',')->toString()) + ->first() + ?->toArray(); + + return [ + 'id' => $event['id'], + 'kind' => $event['kind'], + 'content' => $event['content'], + 'pubkey' => $event['pubkey'], + 'tags' => $event['tags'], + 'created_at' => $event['created_at'], + 'profile' => $profile, + 'votedFor' => $votedFor, + 'type' => str($event['content'])->after(',')->toString(), + ]; + }) + ->sortByDesc('created_at') + ->values() + ->toArray(); + } + + #[Computed] + public function electionConfig(): array + { + $loadedEvents = $this->loadedEvents(); + + return collect(json_decode($this->election->candidates, true, 512, JSON_THROW_ON_ERROR)) + ->map(function ($c) use ($loadedEvents) { + $candidates = Profile::query() + ->whereIn('pubkey', $c['c']) + ->get() + ->map(function ($p) use ($loadedEvents, $c) { + $votedClass = ' bg-green-500/20 text-green-700'; + $notVotedClass = ' bg-gray-500/20 text-gray-100'; + $hasVoted = $loadedEvents + ->filter(fn ($e) => $e['type'] === $c['type'] && $e['pubkey'] === $this->currentPubkey) + ->firstWhere('votedFor.pubkey', $p->pubkey); + + return [ + 'pubkey' => $p->pubkey, + 'name' => $p->name, + 'picture' => $p->picture, + 'votedClass' => $hasVoted ? $votedClass : $notVotedClass, + ]; + }); + + return [ + 'type' => $c['type'], + 'c' => $c['c'], + 'candidates' => $candidates, + ]; + }) + ->toArray(); + } + + #[Computed] + public function electionConfigBoard(): array + { + $loadedBoardEvents = $this->loadedBoardEvents(); + + return collect(json_decode($this->election->candidates, true, 512, JSON_THROW_ON_ERROR)) + ->map(function ($c) use ($loadedBoardEvents) { + $candidates = Profile::query() + ->whereIn('pubkey', $c['c']) + ->get() + ->map(function ($p) use ($loadedBoardEvents, $c) { + $votedClass = ' bg-green-500/20 text-green-700'; + $notVotedClass = ' bg-gray-500/20 text-gray-100'; + $hasVoted = $loadedBoardEvents + ->filter(fn ($e) => $e['type'] === $c['type'] && $e['pubkey'] === $this->currentPubkey) + ->firstWhere('votedFor.pubkey', $p->pubkey); + + return [ + 'pubkey' => $p->pubkey, + 'name' => $p->name, + 'picture' => $p->picture, + 'votedClass' => $hasVoted ? $votedClass : $notVotedClass, + 'hasVoted' => $hasVoted, + ]; + }); + + return [ + 'type' => $c['type'], + 'c' => $c['c'], + 'candidates' => $candidates, + ]; + }) + ->toArray(); + } + + public function mount(Election $election): void + { + $this->election = $election; + $this->plebs = EinundzwanzigPleb::query() + ->with(['profile']) + ->whereIn('association_status', [3, 4]) + ->orderBy('association_status', 'desc') + ->get() + ->toArray(); + $this->loadEvents(); + $this->loadBoardEvents(); + if ($this->election->end_time?->isPast() || ! config('services.voting')) { + $this->isNotClosed = false; + } + } + + public function updatedSearch($value): void + { + $this->plebs = EinundzwanzigPleb::query() + ->with(['profile']) + ->whereIn('association_status', [3, 4]) + ->where(fn ($query) => $query + ->where('pubkey', 'like', "%$value%") + ->orWhereHas('profile', fn ($query) => $query->where('name', 'ilike', "%$value%"))) + ->orderBy('association_status', 'desc') + ->get() + ->toArray(); + } + + public function handleNostrLoggedIn($pubkey): void + { + NostrAuth::login($pubkey); + $this->currentPubkey = $pubkey; + $this->currentPleb = EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); + $logPubkeys = [ + '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033', + '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279', + ]; + if (in_array($this->currentPubkey, $logPubkeys, true)) { + $this->showLog = true; + $this->isAllowed = true; + } + } + + public function handleNostrLoggedOut(): void + { + $this->isAllowed = false; + $this->currentPubkey = null; + $this->currentPleb = null; + } + + public function handleNewVote(): void + { + $this->loadEvents(); + $this->loadBoardEvents(); + } + + public function loadEvents(): void + { + $this->events = $this->loadNostrEvents([32122]); + } + + public function loadBoardEvents(): void + { + $this->boardEvents = $this->loadNostrEvents([2121]); + } + + public function loadNostrEvents($kinds): array + { + $subscription = new Subscription; + $subscriptionId = $subscription->setId(); + $filter = new Filter; + $filter->setKinds($kinds); + $requestMessage = new RequestMessage($subscriptionId, [$filter]); + $relaySet = new RelaySet; + $relaySet->setRelays([new Relay(config('services.relay'))]); + $request = new Request($relaySet, $requestMessage); + $response = $request->send(); + + return collect($response[config('services.relay')]) + ->map(function ($event) { + if (! isset($event->event)) { + return false; + } + + return [ + 'id' => $event->event->id, + 'kind' => $event->event->kind, + 'content' => $event->event->content, + 'pubkey' => $event->event->pubkey, + 'tags' => $event->event->tags, + 'created_at' => $event->event->created_at, + ]; + }) + ->filter() + ->toArray(); + } + + public function vote($pubkey, $type, $board = false): void + { + if ($this->election->end_time?->isPast()) { + $this->isNotClosed = false; + + return; + } + $note = new NostrEvent; + $note->setKind($board ? 2121 : 32122); + if (! $board) { + $dTag = sprintf('%s,%s,%s', $this->currentPleb->pubkey, date('Y'), $type); + $note->setTags([['d', $dTag]]); + } + $note->setContent("$pubkey,$type"); + $this->signThisEvent = $note->toJson(); + } + + public function checkElection(): void + { + if ($this->election->end_time?->isPast()) { + $this->isNotClosed = false; + } + } + + public function signEvent($event): void + { + $note = new NostrEvent; + $note->setId($event['id']); + $note->setSignature($event['sig']); + $note->setKind($event['kind']); + $note->setContent($event['content']); + $note->setPublicKey($event['pubkey']); + $note->setTags($event['tags']); + $note->setCreatedAt($event['created_at']); + $eventMessage = new EventMessage($note); + $relay = new Relay(config('services.relay')); + $relay->setMessage($eventMessage); + $relay->send(); + \App\Support\Broadcast::on('votes')->as('newVote')->sendNow(); + } + + public function render() + { + return view('livewire.association.election.show') + ->layout('layouts.app') + ->with([ + 'seo' => new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'Wahlen ' . $this->election->year, description: 'Wahlen des Vereins im Jahr ' . $this->election->year) + ]); + } +}; +?> + +
+ @if($isAllowed) +
+ + +
+
+ + +
+ +
+
+
+ +
+ +
- -
- -
- - - -
- -
-
- Plebs -
-
    - @foreach($plebs as $pleb) -
  • -
    - A -
    -
    -
    - {{ $pleb['profile']['name'] ?? $pleb['pubkey'] }} -
    -
    - -
    +
    + +
    + +
    + + + +
    + +
    +
    + Plebs +
    +
      + @foreach($plebs as $pleb) +
    • +
      + A +
      +
      +
      + {{ $pleb['profile']['name'] ?? $pleb['pubkey'] }}
      -
      -
      - @foreach($positions as $name => $p) - @php - $votedResult = $this->loadedEvents->filter(fn ($e) => $e['pubkey'] === $pleb['pubkey'])->firstWhere('type', $name); - @endphp -
      - @if($votedResult) - - @endif -
      - @endforeach -
      +
      + +
      +
      +
      +
      + @foreach($positions as $name => $p) + @php + $votedResult = $this->loadedEvents->filter(fn ($e) => $e['pubkey'] === $pleb['pubkey'])->firstWhere('type', $name); + @endphp +
      + @if($votedResult) + + @endif +
      + @endforeach
      -
    • - @endforeach -
    -
    +
    +
  • + @endforeach +
-
+
@@ -441,4 +769,3 @@ @endif
- diff --git a/app/Livewire/Association/Members/Admin.php b/resources/views/components/association/members/⚡admin.blade.php similarity index 71% rename from app/Livewire/Association/Members/Admin.php rename to resources/views/components/association/members/⚡admin.blade.php index 3935a3a..5df7a79 100644 --- a/app/Livewire/Association/Members/Admin.php +++ b/resources/views/components/association/members/⚡admin.blade.php @@ -1,13 +1,10 @@ isAllowed = true; } } -} + + public function render() + { + return view('livewire.association.members.admin') + ->layout('layouts.app') + ->title(__('Mitglieder')); + } +}; +?> + +
+ @if($isAllowed) +
+ +
+ @else +
+
+
+

Mitglieder

+

+ Du bist nicht berechtigt, Mitglieder zu bearbeiten. +

+
+
+
+ @endif +
diff --git a/resources/views/livewire/association/project-support/form/create.blade.php b/resources/views/components/association/project-support/form/⚡create.blade.php similarity index 100% rename from resources/views/livewire/association/project-support/form/create.blade.php rename to resources/views/components/association/project-support/form/⚡create.blade.php diff --git a/resources/views/livewire/association/project-support/form/edit.blade.php b/resources/views/components/association/project-support/form/⚡edit.blade.php similarity index 100% rename from resources/views/livewire/association/project-support/form/edit.blade.php rename to resources/views/components/association/project-support/form/⚡edit.blade.php diff --git a/resources/views/livewire/association/project-support/index.blade.php b/resources/views/components/association/project-support/⚡index.blade.php similarity index 58% rename from resources/views/livewire/association/project-support/index.blade.php rename to resources/views/components/association/project-support/⚡index.blade.php index 6e14900..da296cf 100644 --- a/resources/views/livewire/association/project-support/index.blade.php +++ b/resources/views/components/association/project-support/⚡index.blade.php @@ -1,7 +1,114 @@ - -
+ 'handleNostrLoggedIn', + 'nostrLoggedOut' => 'handleNostrLoggedOut', + ]; + + public function mount(): void + { + $this->loadProjects(); + if (NostrAuth::check()) { + $this->currentPubkey = NostrAuth::pubkey(); + $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first(); + $this->isAllowed = true; + } + } + + public function updatedSearch(): void + { + $this->loadProjects(); + } + + public function loadProjects(): void + { + $this->projects = ProjectProposal::query() + ->with([ + 'einundzwanzigPleb.profile', + 'votes', + ]) + ->where(function ($query) { + $query + ->where('name', 'ilike', '%'.$this->search.'%') + ->orWhere('description', 'ilike', '%'.$this->search.'%') + ->orWhereHas('einundzwanzigPleb.profile', function ($q) { + $q->where('name', 'ilike', '%'.$this->search.'%'); + }); + }) + ->orderBy('created_at', 'desc') + ->get(); + } + + public function handleNostrLoggedIn($pubkey): void + { + NostrAuth::login($pubkey); + $this->currentPubkey = $pubkey; + $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first(); + $this->isAllowed = true; + } + + public function handleNostrLoggedOut(): void + { + $this->isAllowed = false; + $this->currentPubkey = null; + $this->currentPleb = null; + } + + public function confirmDelete($id): void + { + $notification = new Notification($this); + $notification->confirm([ + 'title' => 'Projektunterstützung löschen', + 'message' => 'Bist du sicher, dass du diese Projektunterstützung löschen möchtest?', + 'accept' => [ + 'label' => 'Ja, löschen', + 'method' => 'delete', + 'params' => $id, + ], + ]); + } + + public function setFilter($filter): void + { + $this->activeFilter = $filter; + } + + public function delete($id): void + { + ProjectProposal::query()->findOrFail($id)->delete(); + $this->loadProjects(); + } + + public function render() + { + return view('livewire.association.project-support') + ->layout('layouts.app') + ->with([ + 'seo' => new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'Projekt Unterstützungen', description: 'Einundzwanzig Projektunterstützungen') + ]); + } +}; +?> + +
@@ -72,4 +179,3 @@
- diff --git a/resources/views/livewire/association/project-support/show.blade.php b/resources/views/components/association/project-support/⚡show.blade.php similarity index 100% rename from resources/views/livewire/association/project-support/show.blade.php rename to resources/views/components/association/project-support/⚡show.blade.php diff --git a/resources/views/livewire/association/news/index.blade.php b/resources/views/components/association/⚡news.blade.php similarity index 100% rename from resources/views/livewire/association/news/index.blade.php rename to resources/views/components/association/⚡news.blade.php diff --git a/resources/views/livewire/association/profile.blade.php b/resources/views/components/association/⚡profile.blade.php similarity index 75% rename from resources/views/livewire/association/profile.blade.php rename to resources/views/components/association/⚡profile.blade.php index ef209a5..c70481d 100644 --- a/resources/views/livewire/association/profile.blade.php +++ b/resources/views/components/association/⚡profile.blade.php @@ -1,6 +1,312 @@ - + 'handleNostrLoggedIn', + 'nostrLoggedOut' => 'handleNostrLoggedOut', + ]; + + public function mount(): void + { + if (NostrAuth::check()) { + $this->currentPubkey = NostrAuth::pubkey(); + $this->currentPleb = EinundzwanzigPleb::query() + ->with([ + 'paymentEvents' => fn ($query) => $query->where('year', date('Y')), + ]) + ->where('pubkey', $this->currentPubkey)->first(); + if ($this->currentPleb) { + $this->email = $this->currentPleb->email; + $this->showEmail = ! $this->no; + if ($this->currentPleb->association_status === AssociationStatus::ACTIVE) { + $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; + } + if ($this->currentPleb->paymentEvents->count() < 1) { + $this->createPaymentEvent(); + $this->currentPleb->load('paymentEvents'); + } + $this->loadEvents(); + $this->listenForPayment(); + } + } + } + + public function handleNostrLoggedIn($pubkey): void + { + NostrAuth::login($pubkey); + + $this->currentPubkey = $pubkey; + $this->currentPleb = EinundzwanzigPleb::query() + ->with([ + 'paymentEvents' => fn ($query) => $query->where('year', date('Y')), + ]) + ->where('pubkey', $pubkey)->first(); + $this->email = $this->currentPleb->email; + $this->no = $this->currentPleb->no_email; + $this->showEmail = ! $this->no; + if ($this->currentPleb->association_status === AssociationStatus::ACTIVE) { + $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; + } + if ($this->currentPleb->paymentEvents->count() < 1) { + $this->createPaymentEvent(); + $this->currentPleb->load('paymentEvents'); + } + $this->loadEvents(); + $this->listenForPayment(); + } + + public function handleNostrLoggedOut(): void + { + NostrAuth::logout(); + + $this->currentPubkey = null; + $this->currentPleb = null; + $this->yearsPaid = []; + $this->events = []; + $this->payments = []; + $this->qrCode = null; + $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; + $this->currentYearIsPaid = false; + } + + public function updatedNo(): void + { + $this->showEmail = ! $this->no; + $this->currentPleb->update([ + 'no_email' => $this->no, + ]); + } + + public function updatedFax(): void + { + $this->js('alert("Markus Turm wird sich per Fax melden!")'); + } + + public function saveEmail(): void + { + $this->validate([ + 'email' => 'required|email', + ]); + $this->currentPleb->update([ + 'email' => $this->email, + ]); + $notification = new Notification($this); + $notification->success('E-Mail Adresse gespeichert.'); + } + + public function pay($comment): \Illuminate\Http\RedirectResponse + { + $paymentEvent = $this->currentPleb + ->paymentEvents() + ->where('year', date('Y')) + ->first(); + if ($paymentEvent->btc_pay_invoice) { + return redirect('https://pay.einundzwanzig.space/i/'.$paymentEvent->btc_pay_invoice); + } + try { + $response = \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => 'token '.config('services.btc_pay.api_key'), + ])->post( + 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices', + [ + 'amount' => $this->amountToPay, + 'metadata' => [ + 'orderId' => $comment, + 'orderUrl' => url()->route('association.profile'), + 'itemDesc' => 'Mitgliedsbeitrag '.date('Y').' von nostr:'.$this->currentPleb->npub, + 'posData' => [ + 'event' => $paymentEvent->event_id, + 'pubkey' => $this->currentPleb->pubkey, + 'npub' => $this->currentPleb->npub, + ], + ], + 'checkout' => [ + 'expirationMinutes' => 60 * 24, + 'redirectURL' => url()->route('association.profile'), + 'redirectAutomatically' => true, + 'defaultLanguage' => 'de', + ], + ], + )->throw(); + $paymentEvent->btc_pay_invoice = $response->json()['id']; + $paymentEvent->save(); + + return redirect($response->json()['checkoutLink']); + } catch (\Exception $e) { + $notification = new Notification($this); + $notification->error( + 'Fehler beim Erstellen der Rechnung. Bitte versuche es später erneut: '.$e->getMessage(), + ); + + return redirect()->route('association.profile'); + } + } + + public function listenForPayment(): void + { + $paymentEvent = $this->currentPleb + ->paymentEvents() + ->where('year', date('Y')) + ->first(); + if ($paymentEvent->btc_pay_invoice) { + $response = \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => 'token '.config('services.btc_pay.api_key'), + ]) + ->get( + 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices/'.$paymentEvent->btc_pay_invoice, + ); + if ($response->json()['status'] === 'Expired') { + $paymentEvent->btc_pay_invoice = null; + $paymentEvent->paid = false; + $paymentEvent->save(); + } + if ($response->json()['status'] === 'Settled') { + $paymentEvent->paid = true; + $paymentEvent->save(); + $this->currentYearIsPaid = true; + } + } + if ($paymentEvent->paid) { + $this->currentYearIsPaid = true; + } + $paymentEvent = $paymentEvent->refresh(); + $this->payments = $this->currentPleb + ->paymentEvents() + ->where('paid', true) + ->get(); + } + + public function save($type): void + { + $this->form->validate(); + if (! $this->form->check) { + $this->js('alert("Du musst den Statuten zustimmen.")'); + + return; + } + + $this->currentPleb + ->update([ + 'association_status' => $type, + ]); + } + + public function createPaymentEvent(): void + { + $note = new NostrEvent; + $note->setKind(32121); + $note->setContent( + 'Dieses Event dient der Zahlung des Mitgliedsbeitrags für das Jahr '.date( + 'Y', + ).'. Bitte bezahle den Betrag von '.number_format($this->amountToPay, 0, ',', '.').' Satoshis.', + ); + $note->setTags([ + ['d', $this->currentPleb->pubkey.','.date('Y')], + ['zap', 'daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6', config('services.relay'), '1'], + ]); + $signer = new Sign; + $signer->signEvent($note, config('services.nostr')); + + $eventMessage = new EventMessage($note); + + $relayUrl = config('services.relay'); + $relay = new Relay($relayUrl); + $relay->setMessage($eventMessage); + $result = $relay->send(); + + $this->currentPleb->paymentEvents()->create([ + 'year' => date('Y'), + 'event_id' => $result->eventId, + 'amount' => $this->amountToPay, + ]); + } + + public function loadEvents(): void + { + $subscription = new Subscription; + $subscriptionId = $subscription->setId(); + + $filter1 = new Filter; + $filter1->setKinds([32121]); + $filter1->setAuthors(['daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6']); + $filters = [$filter1]; + + $requestMessage = new RequestMessage($subscriptionId, $filters); + + $relays = [ + new Relay(config('services.relay')), + ]; + $relaySet = new RelaySet; + $relaySet->setRelays($relays); + + $request = new Request($relaySet, $requestMessage); + $response = $request->send(); + + $this->events = collect($response[config('services.relay')]) + ->map(function ($event) { + if (! isset($event->event)) { + return false; + } + + return [ + 'id' => $event->event->id, + 'kind' => $event->event->kind, + 'content' => $event->event->content, + 'pubkey' => $event->event->pubkey, + 'tags' => $event->event->tags, + 'created_at' => $event->event->created_at, + ]; + }) + ->filter() + ->unique('id') + ->toArray(); + } +} +?> + +
@@ -327,16 +633,16 @@
@else - @if($currentYearIsPaid) -
-
- - aktuelles Jahr bezahlt -
+ @if($currentYearIsPaid) +
+
+ + aktuelles Jahr bezahlt
- @endif +
+ @endif @endif
@else @@ -424,4 +730,4 @@
-
+
diff --git a/resources/views/livewire/einundzwanzig-feed/index.blade.php b/resources/views/components/einundzwanzig-feed/⚡index.blade.php similarity index 100% rename from resources/views/livewire/einundzwanzig-feed/index.blade.php rename to resources/views/components/einundzwanzig-feed/⚡index.blade.php diff --git a/resources/views/livewire/layout/sidebar.blade.php b/resources/views/components/layout/⚡sidebar.blade.php similarity index 100% rename from resources/views/livewire/layout/sidebar.blade.php rename to resources/views/components/layout/⚡sidebar.blade.php diff --git a/resources/views/components/layouts/navigation/association.blade.php b/resources/views/components/layouts/navigation/association.blade.php index d9cff5b..999dfd0 100644 --- a/resources/views/components/layouts/navigation/association.blade.php +++ b/resources/views/components/layouts/navigation/association.blade.php @@ -6,9 +6,9 @@ Verein