🗑️ Remove election-related blade files no longer in use

This commit is contained in:
HolgerHatGarKeineNode
2026-01-17 23:26:05 +01:00
parent 220680ab3a
commit 0abbe69868
58 changed files with 4839 additions and 2930 deletions

View File

@@ -0,0 +1,74 @@
<div>
<?php
$positions = [
'presidency' => ['icon' => 'fa-crown', 'title' => 'Präsidium'],
'board' => ['icon' => 'fa-users', 'title' => 'Vorstandsmitglieder'],
];
?>
<?php if ($isAllowed): ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto" x-data="electionAdminCharts()">
<!-- Dashboard actions -->
<div class="sm:flex sm:justify-between sm:items-center mb-8">
<!-- Left: Title -->
<div class="mb-4 sm:mb-0">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
Wahl des Vorstands <?php echo e($election->year); ?>
</h1>
</div>
</div>
<?php
$president = $positions['presidency'];
$board = $positions['board'];
?>
<!-- Cards -->
<div class="grid gap-y-4">
<div wire:key="presidency" wire:ignore
class="flex flex-col bg-white dark:bg-gray-800 shadow-sm rounded-xl">
<header class="px-5 py-4 border-b border-gray-100 dark:border-gray-700/60">
<h2 class="font-semibold text-gray-800 dark:text-gray-100"><i
class="fa-sharp-duotone fa-solid <?php echo e($president['icon']); ?> w-5 h-5 fill-current text-white mr-4"></i><?php echo e($president['title']); ?>
</h2>
</header>
<div class="grow">
<!-- Change the height attribute to adjust the chart height -->
<canvas x-ref="chart_presidency" width="724" height="288"
style="display: block; box-sizing: border-box; height: 288px; width: 724px;"></canvas>
</div>
</div>
<div wire:key="board" wire:ignore
class="flex flex-col bg-white dark:bg-gray-800 shadow-sm rounded-xl">
<header class="px-5 py-4 border-b border-gray-100 dark:border-gray-700/60">
<h2 class="font-semibold text-gray-800 dark:text-gray-100"><i
class="fa-sharp-duotone fa-solid <?php echo e($board['icon']); ?> w-5 h-5 fill-current text-white mr-4"></i><?php echo e($board['title']); ?>
</h2>
</header>
<div class="grow">
<!-- Change the height attribute to adjust the chart height -->
<canvas x-ref="chart_board" width="724" height="288"
style="display: block; box-sizing: border-box; height: 288px; width: 724px;"></canvas>
</div>
</div>
</div>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">Mitglieder</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, Mitglieder zu bearbeiten.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,33 @@
<x-layouts.app title="{{ __('Wahlen') }}">
<div>
<?php if($isAllowed): ?>
<div class="relative flex h-full">
<?php foreach($elections as $election): ?>
<div class="w-full sm:w-1/3 p-4">
<div class="shadow-lg rounded-lg overflow-hidden">
<?php echo e($election['year']); ?>
</div>
<div class="shadow-lg rounded-lg overflow-hidden">
<x-textarea wire:model="elections.<?php echo e($loop->index); ?>.candidates" rows="25"
label="candidates" placeholder=""/>
</div>
<div class="py-2">
<x-button label="Speichern" wire:click="saveElection(<?php echo e($loop->index); ?>)"/>
</div>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">Einstellungen</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Einstellungen zu bearbeiten.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,562 @@
<x-layouts.app
:seo="new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'Wahlen ' . $election->year, description: 'Wahlen des Vereins im Jahr ' . $election->year)"
>
<div>
<?php if($isAllowed): ?>
<div x-cloak class="relative flex h-full" x-data="nostrApp(@this)"
wire:poll.600000ms="checkElection">
<?php
$positions = [
'presidency' => ['icon' => 'fa-crown', 'title' => 'Präsidium'],
'board' => ['icon' => 'fa-users', 'title' => 'Vizepräsidium'],
];
$loadedEvents = collect($events)
->map(function($event) {
$profile = \App\Models\Profile::query()
->where('pubkey', $event['pubkey'])
->first()
?->toArray();
$votedFor = \App\Models\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();
$loadedBoardEvents = collect($boardEvents)
->map(function($event) {
$profile = \App\Models\Profile::query()
->where('pubkey', $event['pubkey'])
->first()
?->toArray();
$votedFor = \App\Models\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();
?>
<!-- Inbox sidebar -->
<div id="inbox-sidebar"
class="absolute z-20 top-0 bottom-0 w-full md:w-auto md:static md:top-auto md:bottom-auto -mr-px md:translate-x-0 transition-transform duration-200 ease-in-out"
:class="inboxSidebarOpen ? 'translate-x-0' : '-translate-x-full'">
<div
class="sticky top-16 bg-white dark:bg-[#1B1B1B] overflow-x-hidden overflow-y-auto no-scrollbar shrink-0 border-r border-gray-200 dark:border-gray-700/60 md:w-[18rem] xl:w-[20rem] h-[calc(100dvh-64px)]">
<!-- #Marketing group -->
<div>
<!-- Group header -->
<div class="sticky top-0 z-10">
<div
class="flex items-center bg-white dark:bg-[#1B1B1B] border-b border-gray-200 dark:border-gray-700/60 px-5 h-16">
<div class="w-full flex items-center justify-between">
<!-- Channel menu -->
<div class="relative" x-data="{ open: false }">
<button class="grow flex items-center truncate" aria-haspopup="true"
@click.prevent="open = !open" :aria-expanded="open">
<div class="truncate">
<span
class="font-semibold text-gray-800 dark:text-gray-100">2024</span>
</div>
<svg
class="w-3 h-3 shrink-0 ml-1 fill-current text-gray-400 dark:text-gray-500"
viewBox="0 0 12 12">
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z"/>
</svg>
</button>
<div
class="origin-top-right z-10 absolute top-full left-0 min-w-60 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700/60 py-1.5 rounded-lg shadow-lg overflow-hidden mt-1"
@click.outside="open = false" @keydown.escape.window="open = false"
x-show="open"
x-transition:enter="transition ease-out duration-200 transform"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-out duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
x-cloak>
<ul>
<li>
<a class="font-medium text-sm text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-gray-200 block py-1.5 px-3"
href="#0" @click="open = false" @focus="open = true"
@focusout="open = false">
<div class="flex items-center justify-between">
<div class="grow flex items-center truncate">
<div class="truncate">2024</div>
</div>
<svg
class="w-3 h-3 shrink-0 fill-current text-orange-500 ml-1"
viewBox="0 0 12 12">
<path
d="M10.28 1.28L3.989 7.575 1.695 5.28A1 1 0 00.28 6.695l3 3a1 1 0 001.414 0l7-7A1 1 0 0010.28 1.28z"/>
</svg>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Group body -->
<div class="px-5 py-4">
<!-- Search form -->
<form class="relative">
<label for="inbox-search" class="sr-only">Search</label>
<input
wire:model.live.debounce="search"
id="inbox-search" class="form-input w-full pl-9 bg-white dark:bg-gray-800"
type="search" placeholder="Suche…"/>
<button class="absolute inset-0 right-auto group" type="submit" aria-label="Search">
<svg
class="shrink-0 fill-current text-gray-400 dark:text-gray-500 group-hover:text-gray-500 dark:group-hover:text-gray-400 ml-3 mr-2"
width="16" height="16" viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg">
<path
d="M7 14c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7zM7 2C4.243 2 2 4.243 2 7s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5z"/>
<path
d="M15.707 14.293L13.314 11.9a8.019 8.019 0 01-1.414 1.414l2.393 2.393a.997.997 0 001.414 0 .999.999 0 000-1.414z"/>
</svg>
</button>
</form>
<!-- Inbox -->
<div class="mt-4">
<div class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase mb-3">
Plebs
</div>
<ul class="mb-6">
<?php foreach($plebs as $pleb): ?>
<li class="-mx-2">
<div class="flex w-full p-2 rounded text-left">
<img class="w-8 h-8 rounded-full mr-2 bg-black"
src="<?php echo e($pleb['profile']['picture'] ?? 'https://robohash.org/test'); ?>"
onerror="this.onerror=null; this.src='https://robohash.org/test';"
width="32"
height="32"
alt="A"/>
<div class="grow truncate">
<div class="flex items-center justify-between mb-1.5">
<div class="truncate">
<span
class="text-sm font-semibold text-gray-800 dark:text-gray-100 truncate"><?php echo e($pleb['profile']['name'] ?? $pleb['pubkey']); ?></span>
</div>
<div class="text-xs text-gray-500 font-medium">
<x-badge
color="<?php echo e(\App\Enums\AssociationStatus::from($pleb['association_status'])->color()); ?>"
label="<?php echo e(\App\Enums\AssociationStatus::from($pleb['association_status'])->label()); ?>"/>
</div>
</div>
<div
class="text-xs font-medium text-gray-800 dark:text-gray-100 truncate mb-0.5">
<div class="flex items-center space-x-2 h-5">
<?php foreach($positions as $name => $p): ?>
<?php
$votedResult = $loadedEvents->filter(fn ($e) => $e['pubkey'] === $pleb['pubkey'])->firstWhere('type', $name);
?>
<div class="flex space-x-2"
wire:key="p_<?php echo e($name); ?>">
<?php if($votedResult): ?>
<i class="fa-sharp-duotone fa-solid <?php echo e($p['icon']); ?> w-4 h-4 fill-current text-green-500"></i>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Inbox body -->
<?php if($currentPubkey): ?>
<?php
$electionConfig = collect(json_decode($election->candidates, true, 512, JSON_THROW_ON_ERROR))
->map(function ($c) use ($loadedEvents, $currentPubkey) {
$candidates = \App\Models\Profile::query()
->whereIn('pubkey', $c['c'])
->get()
->map(function ($p) use ($loadedEvents, $c, $currentPubkey) {
$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'] === $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,
];
});
$electionConfigBoard = collect(json_decode($election->candidates, true, 512, JSON_THROW_ON_ERROR))
->map(function ($c) use ($loadedBoardEvents, $currentPubkey) {
$candidates = \App\Models\Profile::query()
->whereIn('pubkey', $c['c'])
->get()
->map(function ($p) use ($loadedBoardEvents, $c, $currentPubkey) {
$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'] === $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,
];
});
?>
<div class="grow flex flex-col md:translate-x-0 transition-transform duration-300 ease-in-out"
:class="inboxSidebarOpen ? 'translate-x-1/3' : 'translate-x-0'">
<!-- Header -->
<div class="sticky top-16">
<div
class="flex items-center justify-between before:absolute before:inset-0 before:backdrop-blur-md before:bg-gray-50/90 dark:before:bg-[#1B1B1B]/90 before:-z-10 border-b border-gray-200 dark:border-gray-700/60 px-4 sm:px-6 md:px-5 h-16">
<div
class="flex flex-col space-y-2 sm:space-y-0 sm:flex-row justify-between items-center w-full">
<div>
<?php if($isNotClosed): ?>
<x-badge success
label="Die Wahl ist geöffnet bis zum <?php echo e($election->end_time?->timezone('Europe/Berlin')->format('d.m.Y H:i')); ?>"/>
<?php else: ?>
<x-badge negative label="Die Wahl ist geschlossen"/>
<?php endif; ?>
</div>
<div>
<x-button secondary
:href="route('association.election.admin', ['election' => $election])"
label="Wahl-Admin"/>
</div>
</div>
</div>
</div>
<!-- Body -->
<div class="grow px-4 sm:px-6 md:px-5 py-4">
<!-- Mail subject -->
<header class="sm:flex sm:items-start space-x-4 mb-4">
<h1 class="text-xl leading-snug text-gray-800 dark:text-gray-100 font-bold mb-1 sm:mb-0 ml-2">
Wahlen
</h1>
<button
class="text-xs inline-flex font-bold bg-amber-500/20 text-sky-700 rounded-full text-center px-2.5 py-1 whitespace-nowrap">
2024
</button>
</header>
<!-- Messages box -->
<div
class="shadow-sm rounded-xl px-6 divide-y divide-gray-200 dark:divide-gray-700/60">
<!-- Mail -->
<div class="py-6">
<h1 class="text-xl leading-snug text-gray-800 dark:text-gray-100 font-bold mb-1 sm:mb-0 ml-2">
Wahl des Präsidiums
</h1>
<?php
$president = $positions['presidency'];
$board = $positions['board'];
?>
<div class="grid sm:grid-cols-2 gap-6">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl">
<div class="flex flex-col h-full p-5">
<header>
<div class="flex items-center justify-between">
<i class="fa-sharp-duotone fa-solid <?php echo e($president['icon']); ?> w-9 h-9 fill-current text-white"></i>
</div>
</header>
<div class="grow mt-2">
<div
class="inline-flex text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white mb-1">
<h2 class="text-xl leading-snug font-semibold"><?php echo e($president['title']); ?></h2>
</div>
<div class="text-sm">
<?php
$votedResult = $loadedEvents->filter(fn ($event) => $event['pubkey'] === $currentPubkey)->firstWhere('type', 'presidency');
?>
<?php if($votedResult): ?>
<span>Du hast "<?php echo e($votedResult['votedFor']['name'] ?? 'error'); ?>" gewählt</span>
<?php else: ?>
<span>Wähle deinen Kandidaten für das Präsidium.</span>
<?php endif; ?>
</div>
</div>
<footer class="mt-5">
<div class="grid sm:grid-cols-2 gap-2">
<?php foreach($electionConfig->firstWhere('type', 'presidency')['candidates'] ?? [] as $c): ?>
<div
<?php if($isNotClosed): ?>wire:click="vote('<?php echo e($c['pubkey']); ?>', 'presidency')"
<?php endif; ?>
class="<?php echo e($c['votedClass']); ?> cursor-pointer text-xs inline-flex font-medium rounded-full text-center px-2.5 py-1">
<div class="flex items-center">
<img class="w-6 h-6 rounded-full mr-2 bg-black"
src="<?php echo e($c['picture'] ?? 'https://robohash.org/' . $c['pubkey']); ?>"
onerror="this.onerror=null; this.src='https://robohash.org/<?php echo e($c['pubkey']); ?>';"
width="24" height="24"
alt="<?php echo e($c['name']); ?>"/>
<?php echo e($c['name']); ?>
</div>
</div>
<?php endforeach; ?>
</div>
</footer>
</div>
</div>
</div>
<h1 class="mt-6 text-xl leading-snug text-gray-800 dark:text-gray-100 font-bold mb-1 sm:mb-0 ml-2">
Wahl der übrigen Vorstandsmitglieder
</h1>
<div class="grid gap-6">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl">
<div class="flex flex-col h-full p-5">
<div class="grow mt-2">
<div class="text-sm">
<span>Klicke auf den Kandidaten, um seine Position als Vorstandsmitglied zu bestätigen.</span>
</div>
</div>
<footer class="mt-5">
<div class="grid sm:grid-cols-4 gap-2">
<?php foreach($electionConfigBoard->firstWhere('type', 'board')['candidates'] ?? [] as $c): ?>
<div
<?php if($isNotClosed && !$c['hasVoted']): ?>wire:click="vote('<?php echo e($c['pubkey']); ?>', 'board', true)"
<?php endif; ?>
class="<?php echo e($c['votedClass']); ?> cursor-pointer text-xs inline-flex font-medium rounded-full text-center px-2.5 py-1">
<div class="flex items-center">
<img class="w-6 h-6 rounded-full mr-2 bg-black"
src="<?php echo e($c['picture'] ?? 'https://robohash.org/' . $c['pubkey']); ?>"
onerror="this.onerror=null; this.src='https://robohash.org/<?php echo e($c['pubkey']); ?>';"
width="24" height="24"
alt="<?php echo e($c['name']); ?>"/>
<?php echo e($c['name']); ?>
</div>
</div>
<?php endforeach; ?>
</div>
</footer>
</div>
</div>
</div>
</div>
</div>
<!-- Log events -->
<div x-cloak x-show="showLog" class="mt-6 hidden sm:block">
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-xl mb-8">
<header class="px-5 py-4">
<h2 class="font-semibold text-gray-800 dark:text-gray-100">Präsidium Log <span
class="text-gray-400 dark:text-gray-500 font-medium"><?php echo e($loadedEvents->count()); ?></span>
</h2>
</header>
<div>
<!-- Table -->
<div class="overflow-x-auto">
<table
class="table-auto w-full dark:text-gray-300 divide-y divide-gray-100 dark:divide-gray-700/60">
<!-- Table header -->
<thead
class="text-xs uppercase text-gray-500 dark:text-gray-400 bg-gray-50 dark:bg-gray-900/20 border-t border-gray-100 dark:border-gray-700/60">
<tr>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">ID</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Kind</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Pubkey</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Created At</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Voted For</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Type</div>
</th>
</tr>
</thead>
<!-- Table body -->
<tbody class="text-sm">
<?php foreach($loadedEvents as $event): ?>
<tr>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div
class="font-medium"><?php echo e(\Illuminate\Support\Str::limit($event['id'], 10)); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['kind']); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['profile']['name'] ?? ''); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['created_at']); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['votedFor']['name'] ?? ''); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['type']); ?></div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div x-cloak x-show="showLog" class="mt-6 hidden sm:block">
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-xl mb-8">
<header class="px-5 py-4">
<h2 class="font-semibold text-gray-800 dark:text-gray-100">Board Log <span
class="text-gray-400 dark:text-gray-500 font-medium"><?php echo e($loadedBoardEvents->count()); ?></span>
</h2>
</header>
<div>
<!-- Table -->
<div class="overflow-x-auto">
<table
class="table-auto w-full dark:text-gray-300 divide-y divide-gray-100 dark:divide-gray-700/60">
<!-- Table header -->
<thead
class="text-xs uppercase text-gray-500 dark:text-gray-400 bg-gray-50 dark:bg-gray-900/20 border-t border-gray-100 dark:border-gray-700/60">
<tr>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">ID</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Kind</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Pubkey</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Created At</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Voted For</div>
</th>
<th class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div class="font-semibold text-left">Type</div>
</th>
</tr>
</thead>
<!-- Table body -->
<tbody class="text-sm">
<?php foreach($loadedBoardEvents as $event): ?>
<tr>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div
class="font-medium"><?php echo e(\Illuminate\Support\Str::limit($event['id'], 10)); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['kind']); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['profile']['name'] ?? ''); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['created_at']); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['votedFor']['name'] ?? ''); ?></div>
</td>
<td class="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
<div><?php echo e($event['type']); ?></div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">Wahlen</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Wahlen einzusehen.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,20 @@
<x-layouts.app title="{{ __('Mitglieder') }}">
<div>
<?php if($isAllowed): ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<livewire:einundzwanzig-pleb-table/>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">Mitglieder</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, Mitglieder zu bearbeiten.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,217 @@
<x-layouts.app
:seo="new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'News', description: 'Die News des Vereins.')"
>
<div>
<?php if($isAllowed): ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 md:py-0 w-full max-w-9xl mx-auto">
<div class="xl:flex">
<!-- Left + Middle content -->
<div class="md:flex flex-1">
<!-- Left content -->
<div class="w-full md:w-60 mb-8 md:mb-0">
<div
class="md:sticky md:top-16 md:h-[calc(100dvh-64px)] md:overflow-x-hidden md:overflow-y-auto no-scrollbar">
<div class="md:py-8">
<div class="flex justify-between items-center md:block">
<!-- Title -->
<header class="mb-6">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
News</h1>
</header>
</div>
<!-- Links -->
<div
class="flex flex-nowrap overflow-x-scroll no-scrollbar md:block md:overflow-auto px-4 md:space-y-3 -mx-4">
<!-- Group 1 -->
<div>
<div
class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase mb-3 md:sr-only">
Menu
</div>
<ul class="flex flex-nowrap md:block mr-3 md:mr-0">
<?php foreach(\App\Enums\NewsCategory::selectOptions() as $category): ?>
<li class="mr-0.5 md:mr-0 md:mb-0.5"
wire:key="category_<?php echo e($category['value']); ?>">
<div
class="flex items-center px-2.5 py-2 rounded-lg whitespace-nowrap bg-white dark:bg-gray-800">
<i class="fa-sharp-duotone fa-solid fa-<?php echo e($category['icon']); ?> shrink-0 fill-current text-amber-500 mr-2"></i>
<span
class="text-sm font-medium text-amber-500"><?php echo e($category['label']); ?></span>
</div>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Middle content -->
<div class="flex-1 md:ml-8 xl:mx-4 2xl:mx-8">
<div class="md:py-8">
<div class="space-y-2">
<?php $__empty_1 = true; ?>
<?php foreach($news as $post): ?>
<?php $__empty_1 = false; ?>
<article wire:key="post_<?php echo e($post->id); ?>"
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<div class="flex flex-start space-x-4">
<!-- Avatar -->
<div class="shrink-0 mt-1.5">
<img class="w-8 h-8 rounded-full"
src="<?php echo e($post->einundzwanzigPleb->profile?->picture ?? asset('einundzwanzig-alpha.jpg')); ?>"
width="32" height="32"
alt="<?php echo e($post->einundzwanzigPleb->profile?->name); ?>">
</div>
<!-- Content -->
<div class="grow">
<!-- Title -->
<h2 class="font-semibold text-gray-800 dark:text-gray-100 mb-2">
<?php echo e($post->name); ?>
</h2>
<p class="mb-6">
<?php echo e($post->description); ?>
</p>
<!-- Footer -->
<footer class="flex flex-wrap text-sm">
<div
class="flex items-center after:block after:content-['·'] last:after:content-[''] after:text-sm after:text-gray-400 dark:after:text-gray-600 after:px-2">
<div
class="font-medium text-amber-500 hover:text-amber-600 dark:hover:text-amber-400">
<div class="flex items-center">
<svg class="mr-2 fill-current" width="16"
height="16"
xmlns="http://www.w3.org/2000/svg">
<path
d="M15.686 5.708 10.291.313c-.4-.4-.999-.4-1.399 0s-.4 1 0 1.399l.6.6-6.794 3.696-1-1C1.299 4.61.7 4.61.3 5.009c-.4.4-.4 1 0 1.4l1.498 1.498 2.398 2.398L.6 14.001 2 15.4l3.696-3.697L9.692 15.7c.5.5 1.199.2 1.398 0 .4-.4.4-1 0-1.4l-.999-.998 3.697-6.695.6.6c.599.6 1.199.2 1.398 0 .3-.4.3-1.1-.1-1.499Zm-7.193 6.095L4.196 7.507l6.695-3.697 1.298 1.299-3.696 6.694Z"></path>
</svg>
<?php echo e($post->einundzwanzigPleb->profile->name); ?>
</div>
</div>
</div>
<div
class="flex items-center after:block after:content-['·'] last:after:content-[''] after:text-sm after:text-gray-400 dark:after:text-gray-600 after:px-2">
<span
class="text-gray-500"><?php echo e($post->created_at->format('d.m.Y')); ?></span>
</div>
</footer>
</div>
</div>
<div class="mt-2 flex justify-end w-full space-x-2">
<x-button
xs
target="_blank"
:href="url()->temporarySignedRoute('dl', now()->addMinutes(30), ['media' => $post->getFirstMedia('pdf')])"
label="Öffnen"
primary icon="cloud-arrow-down"/>
<?php if($canEdit): ?>
<x-button
xs
wire:click="delete(<?php echo e($post->id); ?>)"
label="Löschen"
negative icon="trash"/>
<?php endif; ?>
</div>
</article>
<?php endforeach; ?>
<?php if($__empty_1): ?>
<article class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<p>Keine News vorhanden.</p>
</article>
<?php endif; ?>
</div>
</div>
</div>
</div>
<!-- Right content -->
<div class="w-full mt-8 sm:mt-0 xl:w-72">
<div
class="lg:sticky lg:top-16 lg:h-[calc(100dvh-64px)] lg:overflow-x-hidden lg:overflow-y-auto no-scrollbar">
<div class="md:py-8">
<!-- Blocks -->
<div class="space-y-4">
<?php if($canEdit): ?>
<div class="bg-white dark:bg-gray-800 p-4 rounded-xl">
<div
class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase mb-4">
News anlegen
</div>
<div class="mt-4 flex flex-col space-y-2">
<div>
<input class="text-gray-200" type="file" wire:model="file">
<?php $__errorArgs = ['file'];
$__bag = $errors->getBag($__errorProps ?? 'default');
if ($__bag->has($__errorArgs)) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs); ?>
<span class="text-red-500"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div>
<x-native-select
wire:model="form.category"
label="Kategorie"
placeholder="Wähle Kategorie"
:options="\App\Enums\NewsCategory::selectOptions()"
option-label="label" option-value="value"
/>
</div>
<div>
<x-input label="Titel" wire:model="form.name"/>
</div>
<div>
<x-textarea
description="optional"
label="Beschreibung" wire:model="form.description"/>
</div>
<button
wire:click="save"
class="btn-sm w-full bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 text-gray-800 dark:text-gray-300">
Hinzufügen
</button>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">
News
</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die News einzusehen.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,426 @@
<x-layouts.app
:seo="new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'Mitgliedschaft', description: 'Einundzwanzig ist, was du draus machst.')"
>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<!-- Page header -->
<div class="mb-8">
<!-- Title -->
<h1 class="text-2xl md:text-3xl text-[#1B1B1B] dark:text-gray-100 font-bold">
Einundzwanzig ist, was du draus machst
</h1>
</div>
<div class="bg-white dark:bg-[#1B1B1B] shadow-sm rounded-xl mb-8">
<div class="flex flex-col md:flex-row md:-mr-px">
<!-- Sidebar -->
<div
class="flex flex-nowrap overflow-x-scroll no-scrollbar md:block md:overflow-auto px-3 py-6 border-b md:border-b-0 md:border-r border-gray-200 dark:border-gray-700/60 min-w-60 md:space-y-3">
<!-- Group 1 -->
<div>
<div class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase mb-3">
Meine Mitgliedschaft
</div>
<ul class="flex flex-nowrap md:block mr-3 md:mr-0">
<li class="mr-0.5 md:mr-0 md:mb-0.5">
<a class="flex items-center px-2.5 py-2 rounded-lg whitespace-nowrap bg-[linear-gradient(135deg,var(--tw-gradient-stops))] from-orange-500/[0.12] dark:from-orange-500/[0.24] to-orange-500/[0.04]"
href="#0">
<i class="fa-sharp-duotone fa-solid fa-id-card-clip shrink-0 fill-current text-orange-400 mr-2"></i>
<span
class="text-sm font-medium text-orange-500 dark:text-orange-400">Status</span>
</a>
</li>
</ul>
</div>
</div>
<!-- Panel -->
<div class="grow">
<!-- Panel body -->
<div class="p-6 space-y-6">
<h2 class="sm:text-2xl text-[#1B1B1B] dark:text-gray-100 font-bold mb-5">Aktueller Status</h2>
<section>
@if(!$currentPleb)
<div class="space-y-2 mb-12">
<div class="flex justify-between items-center mb-4">
<div class="text-xl text-gray-500 dark:text-gray-400 italic">Empfohlene Nostr
Login und Signer-Apps
</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-xl px-5 py-4">
<div
class="md:flex justify-between items-center space-y-4 md:space-y-0 space-x-2">
<!-- Left side -->
<div class="flex items-start space-x-3 md:space-x-4">
<div>
<a class="inline-flex font-semibold text-gray-800 dark:text-gray-100"
href="https://github.com/greenart7c3/Amber">
Amber
</a>
<div class="text-sm">Perfekt für mobile Android Geräte. Eine App, in
der man alle Keys/nsecs verwalten kann.
</div>
</div>
</div>
<!-- Right side -->
<div class="flex items-center space-x-4 pl-10 md:pl-0">
<div
class="text-xs inline-flex font-medium bg-green-500/20 text-green-700 rounded-full text-center px-2.5 py-1">
Android
</div>
</div>
</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-xl px-5 py-4">
<div
class="md:flex justify-between items-center space-y-4 md:space-y-0 space-x-2">
<!-- Left side -->
<div class="flex items-start space-x-3 md:space-x-4">
<div>
<a class="inline-flex font-semibold text-gray-800 dark:text-gray-100"
href="https://addons.mozilla.org/en-US/firefox/addon/alby/">
Alby - Bitcoin Lightning Wallet & Nostr
</a>
<div class="text-sm">
Browser-Erweiterung in die man seinen Key/nsec eingeben kann.
Pro Alby-Konto ein nsec.
</div>
</div>
</div>
<!-- Right side -->
<div class="flex items-center space-x-4 pl-10 md:pl-0">
<div
class="text-xs inline-flex font-medium bg-yellow-500/20 text-yellow-700 rounded-full text-center px-2.5 py-1">
Browser Chrome/Firefox
</div>
</div>
</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-xl px-5 py-4">
<div
class="md:flex justify-between items-center space-y-4 md:space-y-0 space-x-2">
<!-- Left side -->
<div class="flex items-start space-x-3 md:space-x-4">
<div>
<a class="inline-flex font-semibold text-gray-800 dark:text-gray-100"
href="https://chromewebstore.google.com/detail/nos2x/kpgefcfmnafjgpblomihpgmejjdanjjp">
nos2x
</a>
<div class="text-sm">
Browser-Erweiterung für Chrome Browser. Multi-Key fähig.
</div>
</div>
</div>
<!-- Right side -->
<div class="flex items-center space-x-4 pl-10 md:pl-0">
<div
class="text-xs inline-flex font-medium bg-red-500/20 text-red-700 rounded-full text-center px-2.5 py-1">
Browser Chrome
</div>
</div>
</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-xl px-5 py-4">
<div
class="md:flex justify-between items-center space-y-4 md:space-y-0 space-x-2">
<!-- Left side -->
<div class="flex items-start space-x-3 md:space-x-4">
<div>
<a class="inline-flex font-semibold text-gray-800 dark:text-gray-100"
href="https://addons.mozilla.org/en-US/firefox/addon/nos2x-fox/">
nos2x-fox
</a>
<div class="text-sm">
Browser-Erweiterung für Firefox Browser. Multi-Key fähig.
</div>
</div>
</div>
<!-- Right side -->
<div class="flex items-center space-x-4 pl-10 md:pl-0">
<div
class="text-xs inline-flex font-medium bg-amber-500/20 text-amber-700 rounded-full text-center px-2.5 py-1">
Browser Firefox
</div>
</div>
</div>
</div>
</div>
@endif
<div class="flex flex-wrap space-y-2 sm:space-y-0 items-center justify-between">
<template x-if="$store.nostr.user">
<div class="flex items">
<img class="w-12 h-12 rounded-full"
x-bind:src="$store.nostr.user.picture || '{{ asset('apple-touch-icon.png') }}'"
alt="Avatar">
<div class="ml-4">
<h3 class="w-48 sm:w-full truncate text-lg leading-snug text-[#1B1B1B] dark:text-gray-100 font-bold"
x-text="$store.nostr.user.display_name"></h3>
<div
class="w-48 sm:w-full truncate text-sm text-gray-500 dark:text-gray-400"
x-text="$store.nostr.user.name"></div>
</div>
</div>
</template>
@if($currentPubkey && $currentPleb->association_status->value < 2)
<div
class="inline-flex min-w-80 px-4 py-2 rounded-lg text-sm bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-100">
<div class="flex w-full justify-between items-start">
<div class="flex">
<svg class="shrink-0 fill-current text-green-500 mt-[3px] mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z"></path>
</svg>
<div>Profil in der Datenbank vorhanden.</div>
</div>
</div>
</div>
@endif
</div>
</section>
<section>
@if($currentPubkey && !$currentPleb->application_for && $currentPleb->association_status->value < 2)
<h3 class="text-xl leading-snug text-[#1B1B1B] dark:text-gray-100 font-bold mb-1">
Einundzwanzig Mitglied werden
</h3>
<h4 class="text-xs leading-snug text-[#1B1B1B] dark:text-gray-100 font-italic mb-1">
Nur Personen können Mitglied werden und zahlen 21.000 Satoshis im Jahr.<br>
<a href="https://einundzwanzig.space/verein/" class="text-amber-500">Firmen melden
sich bitte direkt an den Vorstand.</a>
</h4>
<div class="sm:flex sm:items-center space-y-4 sm:space-y-0 sm:space-x-4 mt-5">
<div class="sm:w-1/2 flex flex-col space-y-2">
<div class="flex items-center space-x-2">
<div>
<x-checkbox wire:model="form.check"
label="Ich stimme den Vereins-Statuten zu"/>
</div>
<div>
<a href="https://einundzwanzig.space/verein/" target="_blank"
class="text-amber-500">Statuten</a>
</div>
</div>
<x-button label="Mit deinem aktuellen Nostr-Profil Mitglied werden"
wire:click="save({{ AssociationStatus::PASSIVE() }})"/>
</div>
</div>
@endif
@if($currentPubkey)
<div
class="mt-6 inline-flex flex-col w-full px-4 py-2 rounded-lg text-sm bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-400">
<div class="flex w-full justify-between items-start">
<div class="flex w-full">
<svg class="shrink-0 fill-current text-yellow-500 mt-[3px] mr-3"
width="16"
height="16" viewBox="0 0 16 16">
<path
d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z"></path>
</svg>
<div class="w-full">
<div
class="w-full font-medium text-gray-800 dark:text-gray-100 mb-1">
Falls du möchtest, kannst du hier eine E-Mail Adresse
hinterlegen,
damit der Verein dich darüber informieren kann, wenn es
Neuigkeiten
gibt.<br><br>
Am besten eine anynomisierte E-Mail Adresse verwenden. Wir
sichern
diese Adresse AES-256 verschlüsselt in der Datenbank ab.
</div>
<div
class="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2 text-amber-500">
<x-toggle xl warning
wire:model.live="no"
label="NEIN">
<x-slot name="description">
<span class="py-2 text-amber-500">Ich informiere mich selbst in der News Sektion und gebe keine E-Mail Adresse raus.</span>
</x-slot>
</x-toggle>
</div>
@if($showEmail)
<div wire:key="showEmail"
class="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2">
<x-input wire:model.live.debounce="fax" label="Fax-Nummer"/>
<x-input wire:model.live.debounce="email"
label="E-Mail Adresse"/>
</div>
<div wire:key="showSave" class="flex space-x-2 mt-2">
<x-button wire:click="saveEmail" label="Speichern"/>
</div>
@endif
</div>
</div>
</div>
</div>
@endif
</section>
<section>
@if($currentPleb && $currentPleb->association_status->value > 1)
<div class="flex flex-col space-y-4">
<div
class="inline-flex flex-col w-full max-w-lg px-4 py-2 rounded-lg text-sm bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-400">
<div class="flex w-full justify-between items-start">
<div class="flex">
<svg class="shrink-0 fill-current text-green-500 mt-[3px] mr-3"
width="16"
height="16" viewBox="0 0 16 16">
<path
d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z"></path>
</svg>
<div>
<div class="font-medium text-gray-800 dark:text-gray-100 mb-1">
Du bist derzeit ein Mitglied des Vereins.
</div>
</div>
</div>
</div>
</div>
</div>
@endif
</section>
<section>
@if($currentPleb && $currentPleb->association_status->value > 1)
<div
class="inline-flex flex-col w-full px-4 py-2 rounded-lg text-sm bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-400">
<div class="flex w-full justify-between items-start">
<div class="flex">
<svg class="shrink-0 fill-current text-yellow-500 mt-[3px] mr-3" width="16"
height="16" viewBox="0 0 16 16">
<path
d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z"></path>
</svg>
<div>
<div
class="font-medium text-gray-800 dark:text-gray-100 mb-1 space-y-2">
<p>Nostr Event für die Zahlung des
Mitgliedsbeitrags: <span
class="break-all">{{ $currentPleb->paymentEvents->last()->event_id }}</span>
</p>
<div>
@php
// latest event by created_at field of $events
$latestEvent = collect($events)->sortByDesc('created_at')->first();
@endphp
@if(isset($latestEvent))
<p>{{ $latestEvent['content'] }}</p>
<div class="mt-8">
@if(!$currentYearIsPaid)
<div class="flex justify-center">
<button
wire:click="pay('{{ date('Y') }}:{{ $currentPubkey }}')"
class="btn text-2xl dark:bg-gray-800 border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 text-green-500"
>
<i class="fa-sharp-duotone fa-solid fa-bolt-lightning mr-2"></i>
Pay {{ $amountToPay }} Sats
</button>
</div>
@else
@if($currentYearIsPaid)
<div class="flex sm:justify-center">
<div
class="btn sm:text-2xl dark:bg-gray-800 border-gray-200 dark:border-gray-700/60 text-green-500"
>
<i class="fa-sharp-duotone fa-solid fa-check-circle mr-2"></i>
aktuelles Jahr bezahlt
</div>
</div>
@endif
@endif
</div>
@else
<div class="flex sm:justify-center">
<button
class="btn dark:bg-gray-800 border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 text-amber-500"
>
<i class="fa-sharp-duotone fa-solid fa-user-helmet-safety mr-2"></i>
Unser Nostr-Relay konnte derzeit nicht erreicht
werden, um eine Zahlung zu initialisieren. Bitte
versuche es später noch einmal.
</button>
</div>
@endif
</div>
<section>
<h3 class="text-xl leading-snug text-gray-800 dark:text-gray-100 font-bold mb-1">
bisherige Zahlungen</h3>
<!-- Table -->
<table class="table-auto w-full dark:text-gray-400">
<!-- Table header -->
<thead
class="text-xs uppercase text-gray-400 dark:text-gray-500">
<tr class="flex flex-wrap md:table-row md:flex-no-wrap">
<th class="w-full hidden md:w-auto md:table-cell py-2">
<div class="font-semibold text-left">Satoshis</div>
</th>
<th class="w-full hidden md:w-auto md:table-cell py-2">
<div class="font-semibold text-left">Jahr</div>
</th>
<th class="w-full hidden md:w-auto md:table-cell py-2">
<div class="font-semibold text-left">Event-ID</div>
</th>
<th class="w-full hidden md:w-auto md:table-cell py-2">
<div class="font-semibold text-left">Quittung</div>
</th>
</tr>
</thead>
<!-- Table body -->
<tbody class="text-sm">
@foreach($payments as $payment)
<tr class="flex flex-wrap md:table-row md:flex-no-wrap border-b border-gray-200 dark:border-gray-700/60 py-2 md:py-0">
<td class="w-full block md:w-auto md:table-cell py-0.5 md:py-2">
<div
class="text-left font-medium text-gray-800 dark:text-gray-100">
<span class="sm:hidden">Sats:</span>
{{ $payment->amount }}
</div>
</td>
<td class="w-full block md:w-auto md:table-cell py-0.5 md:py-2">
<div
class="text-left"><span
class="sm:hidden">Jahr:</span>{{ $payment->year }}
</div>
</td>
<td class="w-full block md:w-auto md:table-cell py-0.5 md:py-2">
<div
class="text-left font-medium break-all">{{ $payment->event_id }}</div>
</td>
<td class="w-full block md:w-auto md:table-cell py-0.5 md:py-2">
@if($payment->btc_pay_invoice)
<x-button target="_blank" xs
label="Quittung"
href="https://pay.einundzwanzig.space/i/{{ $payment->btc_pay_invoice }}/receipt"/>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</section>
</div>
</div>
</div>
</div>
</div>
@endif
</section>
</div>
</div>
</div>
</div>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,102 @@
<x-layouts.app title="Neuer Vorschlag für eine Unterstützung">
<div>
<?php if($isAllowed): ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<form class="space-y-8 divide-y divide-gray-700 pb-24">
<div class="space-y-8 divide-y divide-gray-700 sm:space-y-5">
<div class="mt-6 sm:mt-5 space-y-6 sm:space-y-5">
<x-input.group :for=" md5('image')" :label="__('Bild')">
<div class="py-4">
<?php if ($image && method_exists($image, 'temporaryUrl') && str($image->getMimeType())->contains(['image/jpeg','image/jpg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp'])): ?>
<div class="text-gray-200">{{ __('Preview') }}:</div>
<img class="h-48 object-contain" src="<?php echo e($image->temporaryUrl()); ?>">
<?php endif; ?>
<?php if (isset($projectProposal) && $projectProposal->getFirstMediaUrl('main')): ?>
<div class="text-gray-200">{{ __('Current picture') }}:</div>
<img class="h-48 object-contain"
src="<?php echo e($projectProposal->getFirstMediaUrl('main')); ?>">
<?php endif; ?>
</div>
<input class="text-gray-200" type="file" wire:model="image">
<?php $__errorArgs = ['image'];
$__bag = $errors->getBag($__errorProps ?? 'default');
if ($__bag->has($__errorArgs)) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs); ?>
<span class="text-red-500"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</x-input.group>
<x-input.group :for="md5('form.name')" :label="__('Name')">
<x-input autocomplete="off" wire:model.debounce="form.name"
:placeholder="__('Name')"/>
</x-input.group>
<x-input.group :for="md5('form.website')" :label="__('Webseite des Projekts')">
<x-input autocomplete="off" wire:model.debounce="form.website"
:placeholder="__('Website')"
description="Eine valide URL beginnt immer mit https://"
/>
</x-input.group>
<x-input.group :for="md5('form.name')" :label="__('Beabsichtigte Unterstützung in Sats')">
<x-input type="number" autocomplete="off" wire:model.debounce="form.support_in_sats"
:placeholder="__('Beabsichtigte Unterstützung in Sats')"/>
</x-input.group>
<x-input.group :for="md5('form.description')">
<x-slot name="label">
<div>
<?php echo e(__('Beschreibung')); ?>
</div>
<div
class="text-amber-500 text-xs py-2"><?php echo e(__('Bitte verfasse einen ausführlichen und verständlichen Antragstext, damit die Abstimmung über eine mögliche Förderung erfolgen kann.')); ?></div>
</x-slot>
<div
class="text-amber-500 text-xs py-2"><?php echo e(__('Für Bilder in Markdown verwende bitte z.B. Imgur oder einen anderen Anbieter.')); ?></div>
<x-input.simple-mde model="form.description"/>
<?php $__errorArgs = ['form.description'];
$__bag = $errors->getBag($__errorProps ?? 'default');
if ($__bag->has($__errorArgs)) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs); ?>
<span class="text-red-500 py-2"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</x-input.group>
<x-input.group :for="md5('save')" label="">
<x-button secondary :href="route('association.projectSupport')">
<i class="fa fa-thin fa-arrow-left"></i>
<?php echo e(__('Zurück')); ?>
</x-button>
<x-button primary wire:click="save">
<i class="fa fa-thin fa-save"></i>
<?php echo e(__('Save')); ?>
</x-button>
</x-input.group>
</div>
</div>
</form>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">
Projekt-Unterstützung</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projekt-Unterstützungen zu bearbeiten.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,111 @@
<x-layouts.app title="<?php echo e($projectProposal->name); ?>">
<div>
<?php if($isAllowed): ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<form class="space-y-8 divide-y divide-gray-700 pb-24">
<div class="space-y-8 divide-y divide-gray-700 sm:space-y-5">
<div class="mt-6 sm:mt-5 space-y-6 sm:space-y-5">
<x-input.group :for=" md5('image')" :label="__('Bild')">
<div class="py-4">
<?php if ($image && method_exists($image, 'temporaryUrl') && str($image->getMimeType())->contains(['image/jpeg','image/jpg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp'])): ?>
<div class="text-gray-200">{{ __('Preview') }}:</div>
<img class="h-48 object-contain" src="<?php echo e($image->temporaryUrl()); ?>">
<?php endif; ?>
<?php if (isset($projectProposal) && $projectProposal->getFirstMediaUrl('main')): ?>
<div class="text-gray-200">{{ __('Current picture') }}:</div>
<img class="h-48 object-contain"
src="<?php echo e($projectProposal->getFirstMediaUrl('main')); ?>">
<?php endif; ?>
</div>
<input class="text-gray-200" type="file" wire:model="image">
<?php $__errorArgs = ['image'];
$__bag = $errors->getBag($__errorProps ?? 'default');
if ($__bag->has($__errorArgs)) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs); ?>
<span class="text-red-500"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</x-input.group>
<x-input.group :for="md5('form.name')" :label="__('Name')">
<x-input autocomplete="off" wire:model.debounce="form.name"
:placeholder="__('Name')"/>
</x-input.group>
<x-input.group :for="md5('form.website')" :label="__('Webseite des Projekts')">
<x-input autocomplete="off" wire:model.debounce="form.website"
:placeholder="__('Website')"
description="Eine valide URL beginnt immer mit https://"
/>
</x-input.group>
<x-input.group :for="md5('form.name')" :label="__('Beabsichtigte Unterstützung in Sats')">
<x-input type="number" autocomplete="off" wire:model.debounce="form.support_in_sats"
:placeholder="__('Beabsichtigte Unterstützung in Sats')"/>
</x-input.group>
<x-input.group :for="md5('form.accepted')" :label="__('Wurde angenommen')">
<x-checkbox autocomplete="off" wire:model.debounce="form.accepted"/>
</x-input.group>
<x-input.group :for="md5('form.sats_paid')" :label="__('Letztendlich bezahlte Satoshis')">
<x-input autocomplete="off" wire:model.debounce="form.sats_paid"
:placeholder="__('Satoshi-Anzahl')"/>
</x-input.group>
<x-input.group :for="md5('form.description')">
<x-slot name="label">
<div>
<?php echo e(__('Beschreibung')); ?>
</div>
<div
class="text-amber-500 text-xs py-2"><?php echo e(__('Bitte verfasse einen ausführlichen und verständlichen Antragstext, damit die Abstimmung über eine mögliche Förderung erfolgen kann.')); ?></div>
</x-slot>
<div
class="text-amber-500 text-xs py-2"><?php echo e(__('Für Bilder in Markdown verwende bitte z.B. Imgur oder einen anderen Anbieter.')); ?></div>
<x-input.simple-mde model="form.description"/>
<?php $__errorArgs = ['form.description'];
$__bag = $errors->getBag($__errorProps ?? 'default');
if ($__bag->has($__errorArgs)) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs); ?>
<span class="text-red-500 py-2"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</x-input.group>
<x-input.group :for="md5('save')" label="">
<x-button secondary :href="route('association.projectSupport')">
<i class="fa fa-thin fa-arrow-left"></i>
<?php echo e(__('Zurück')); ?>
</x-button>
<x-button primary wire:click="save">
<i class="fa fa-thin fa-save"></i>
<?php echo e(__('Speichern')); ?>
</x-button>
</x-input.group>
</div>
</div>
</form>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">
Projekt-Unterstützung</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projekt-Unterstützungen zu bearbeiten.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,75 @@
<x-layouts.app
:seo="new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'Projekt Unterstützungen', description: 'Einundzwanzig Projektunterstützungen')"
>
<div>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<!-- Page header -->
<div class="sm:flex sm:justify-between sm:items-center mb-5">
<!-- Left: Title -->
<div class="mb-4 sm:mb-0">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
Einundzwanzig Projektunterstützungen
</h1>
</div>
<!-- Right: Actions -->
<div class="grid grid-cols-1 sm:grid-cols-2 justify-start sm:justify-end gap-2">
<!-- Search form -->
<form class="relative">
<x-input type="search" wire:model.live.debounce="search"
placeholder="Suche"/>
</form>
<!-- Add meetup button -->
@if($currentPleb && $currentPleb->association_status->value > 1 && $currentPleb->paymentEvents()->where('year', date('Y'))->where('paid', true)->exists())
<x-button :href="route('association.projectSupport.create')" icon="plus"
label="Projekt einreichen"/>
@endif
</div>
</div>
<!-- Filters -->
<div class="mb-5">
<ul class="flex flex-wrap -m-1">
<li class="m-1">
<button wire:click="setFilter('all')"
class="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border @if($activeFilter === 'all') border-transparent shadow-sm bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-800 @else border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 shadow-sm bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 @endif transition">
Alle
</button>
</li>
<li class="m-1">
<button wire:click="setFilter('new')"
class="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border @if($activeFilter === 'new') border-transparent shadow-sm bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-800 @else border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 shadow-sm bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 @endif transition">
Neu
</button>
</li>
<li class="m-1">
<button wire:click="setFilter('supported')"
class="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border @if($activeFilter === 'supported') border-transparent shadow-sm bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-800 @else border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 shadow-sm bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 @endif transition">
Unterstützt
</button>
</li>
<li class="m-1">
<button wire:click="setFilter('rejected')"
class="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border @if($activeFilter === 'rejected') border-transparent shadow-sm bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-800 @else border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 shadow-sm bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 @endif transition">
Abgelehnt
</button>
</li>
</ul>
</div>
<div class="text-sm text-gray-500 dark:text-gray-400 italic mb-4">{{ $projects->count() }} Projekte</div>
<!-- Content -->
<div class="grid xl:grid-cols-2 gap-6 mb-8">
@foreach($this->projects as $project)
<x-project-card :project="$project" :currentPleb="$currentPleb" :section="$activeFilter"/>
@endforeach
</div>
</div>
</div>
</x-layouts.app>

View File

@@ -0,0 +1,157 @@
<x-layouts.app
:seo="new SEOData(title: 'Unterstützung für: ' . $projectProposal->name, description: $projectProposal->accepted ? 'Wurde mit ' . number_format($projectProposal->sats_paid, 0, ',', '.') . ' Satoshis unterstützt!' :str($projectProposal->description)->limit(100, '...', true), image: $projectProposal->getFirstMediaUrl('main'))">
<div>
<?php if($projectProposal->accepted || $isAllowed): ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full">
<!-- Page content -->
<div class="max-w-5xl mx-auto flex flex-col lg:flex-row lg:space-x-8 xl:space-x-16">
<!-- Content -->
<div>
<div class="mb-6">
<a class="btn-sm px-3 bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700/60 hover:border-gray-300 dark:hover:border-gray-600 text-gray-800 dark:text-gray-300"
href="<?php echo e(route('association.projectSupport')); ?>"
>
<svg class="fill-current text-gray-400 dark:text-gray-500 mr-2" width="7" height="12"
viewBox="0 0 7 12">
<path d="M5.4.6 6.8 2l-4 4 4 4-1.4 1.4L0 6z"></path>
</svg>
<span>Zurück zur Übersicht</span>
</a>
</div>
<div class="text-sm font-semibold text-violet-500 uppercase mb-2">
<?php echo e($projectProposal->created_at->translatedFormat('d.m.Y')); ?>
</div>
<header class="mb-4">
<!-- Title -->
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold mb-2">
<?php echo e($projectProposal->name); ?>
</h1>
<x-markdown>
<?php echo $projectProposal->description; ?>
</x-markdown>
</header>
<div class="space-y-3 sm:flex sm:items-center sm:justify-between sm:space-y-0 mb-6">
<!-- Author -->
<div class="flex items-center sm:mr-4">
<a class="block mr-2 shrink-0" href="#0">
<img class="rounded-full"
src="<?php echo e($projectProposal->einundzwanzigPleb->profile?->picture ?? asset('einundzwanzig-alpha.jpg')); ?>"
width="32" height="32" alt="User 04">
</a>
<div class="text-sm whitespace-nowrap">Eingereicht von
<div
class="font-semibold text-gray-800 dark:text-gray-100"><?php echo e($projectProposal->einundzwanzigPleb?->profile->name ?? str($projectProposal->einundzwanzigPleb->npub)->limit(32)); ?></div>
</div>
</div>
<!-- Right side -->
<div class="flex flex-wrap items-center sm:justify-end space-x-2">
<!-- Tags -->
<div
class="text-xs inline-flex items-center font-medium border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-400 rounded-full text-center px-2.5 py-1">
<a target="_blank" href="<?php echo e($projectProposal->website); ?>"><span>Webseite</span></a>
</div>
<div
class="text-xs inline-flex font-medium uppercase bg-green-500/20 text-green-700 rounded-full text-center px-2.5 py-1">
<?php echo e(number_format($projectProposal->support_in_sats, 0, ',', '.')); ?> Sats
</div>
</div>
</div>
<figure class="mb-6">
<img class="rounded-sm h-48" src="<?php echo e($projectProposal->getFirstMediaUrl('main')); ?>"
alt="Picture">
</figure>
<hr class="my-6 border-t border-gray-100 dark:border-gray-700/60">
</div>
<?php if($isAllowed && !$projectProposal->accepted): ?>
<!-- Sidebar -->
<div class="space-y-4">
<!-- 1st block -->
<div class="bg-white dark:bg-gray-800 p-5 shadow-sm rounded-xl lg:w-72 xl:w-80">
<?php if(!$ownVoteExists): ?>
<div class="space-y-2">
<button
wire:click="approve"
class="btn w-full bg-gray-900 text-gray-100 hover:bg-gray-800 dark:bg-gray-100 dark:text-gray-800 dark:hover:bg-white">
<i class="fill-current shrink-0 fa-sharp-duotone fa-solid fa-thumbs-up"></i>
<span class="ml-1">Zustimmen</span>
</button>
<button
wire:click="notApprove"
class="btn w-full bg-red-900 text-red-100 hover:bg-red-800 dark:bg-red-100 dark:text-red-800 dark:hover:bg-red-400">
<i class="fill-current shrink-0 fa-sharp-duotone fa-solid fa-thumbs-down"></i>
<span class="ml-1">Ablehnen</span>
</button>
</div>
<?php else: ?>
<div class="space-y-2">
<p>Du hast bereits abgestimmt.</p>
</div>
<?php endif; ?>
</div>
<!-- 2nd block -->
<div class="bg-white dark:bg-gray-800 p-5 shadow-sm rounded-xl lg:w-72 xl:w-80">
<div class="flex justify-between space-x-1 mb-5">
<div class="text-sm text-gray-800 dark:text-gray-100 font-semibold">
Zustimmungen des Vorstands (<?php echo e(count($boardVotes->where('value', 1))); ?>)
</div>
</div>
</div>
<!-- 2nd block -->
<div class="bg-white dark:bg-gray-800 p-5 shadow-sm rounded-xl lg:w-72 xl:w-80">
<div class="flex justify-between space-x-1 mb-5">
<div class="text-sm text-gray-800 dark:text-gray-100 font-semibold">
Ablehnungen des Vorstands (<?php echo e(count($boardVotes->where('value', 0))); ?>)
</div>
</div>
</div>
<!-- 3rd block -->
<div class="bg-white dark:bg-gray-800 p-5 shadow-sm rounded-xl lg:w-72 xl:w-80">
<div class="flex justify-between space-x-1 mb-5">
<div class="text-sm text-gray-800 dark:text-gray-100 font-semibold">
Zustimmungen der übrigen Mitglieder (<?php echo e(count($otherVotes->where('value', 1))); ?>)
</div>
</div>
</div>
<!-- 3rd block -->
<div class="bg-white dark:bg-gray-800 p-5 shadow-sm rounded-xl lg:w-72 xl:w-80">
<div class="flex justify-between space-x-1 mb-5">
<div class="text-sm text-gray-800 dark:text-gray-100 font-semibold">
Ablehnungen der übrigen Mitglieder (<?php echo e(count($otherVotes->where('value', 0))); ?>)
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php else: ?>
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="bg-white dark:bg-[#1B1B1B] shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">
Projekt-Unterstützung
</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projekt-Unterstützungen einzusehen.
</p>
</div>
</div>
</div>
<?php endif; ?>
</div>
</x-layouts.app>