Add reusable Blade components for inputs and layouts: FilePond, navigation groups, and notification buttons

This commit is contained in:
HolgerHatGarKeineNode
2026-01-18 13:23:20 +01:00
parent 22c8ad3588
commit 30e78711c9
33 changed files with 1853 additions and 349 deletions

View File

@@ -10,6 +10,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
- php - 8.3.29
- laravel/framework (LARAVEL) - v12
- laravel/nightwatch (NIGHTWATCH) - v1
- laravel/prompts (PROMPTS) - v0
- laravel/reverb (REVERB) - v1
- laravel/sail (SAIL) - v1
@@ -18,7 +19,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
- laravel/pint (PINT) - v1
- pestphp/pest (PEST) - v3
- phpunit/phpunit (PHPUNIT) - v11
- laravel-echo (ECHO) - v1
- laravel-echo (ECHO) - v2
- tailwindcss (TAILWINDCSS) - v3
## Conventions

View File

@@ -10,6 +10,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
- php - 8.3.29
- laravel/framework (LARAVEL) - v12
- laravel/nightwatch (NIGHTWATCH) - v1
- laravel/prompts (PROMPTS) - v0
- laravel/reverb (REVERB) - v1
- laravel/sail (SAIL) - v1
@@ -18,7 +19,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
- laravel/pint (PINT) - v1
- pestphp/pest (PEST) - v3
- phpunit/phpunit (PHPUNIT) - v11
- laravel-echo (ECHO) - v1
- laravel-echo (ECHO) - v2
- tailwindcss (TAILWINDCSS) - v3
## Conventions

View File

@@ -10,6 +10,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
- php - 8.3.29
- laravel/framework (LARAVEL) - v12
- laravel/nightwatch (NIGHTWATCH) - v1
- laravel/prompts (PROMPTS) - v0
- laravel/reverb (REVERB) - v1
- laravel/sail (SAIL) - v1
@@ -18,7 +19,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
- laravel/pint (PINT) - v1
- pestphp/pest (PEST) - v3
- phpunit/phpunit (PHPUNIT) - v11
- laravel-echo (ECHO) - v1
- laravel-echo (ECHO) - v2
- tailwindcss (TAILWINDCSS) - v3
## Conventions

View File

@@ -13,6 +13,7 @@
"archtechx/enums": "^1.1",
"calebporzio/sushi": "^2.5",
"laravel/framework": "^12.0",
"laravel/nightwatch": "^1.22",
"laravel/reverb": "^1.0",
"laravel/sail": "^1.31",
"laravel/tinker": "^2.9",

96
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2c65490e6b7a44170109685c7d29bf07",
"content-hash": "7ce22785474454dbae00168baafb6ccf",
"packages": [
{
"name": "akuechler/laravel-geoly",
@@ -2041,6 +2041,100 @@
},
"time": "2026-01-13T15:29:06+00:00"
},
{
"name": "laravel/nightwatch",
"version": "v1.22.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/nightwatch.git",
"reference": "a6ef3f6bccc81e69e17e4f67992c1a3ab6a85110"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/nightwatch/zipball/a6ef3f6bccc81e69e17e4f67992c1a3ab6a85110",
"reference": "a6ef3f6bccc81e69e17e4f67992c1a3ab6a85110",
"shasum": ""
},
"require": {
"ext-zlib": "*",
"guzzlehttp/promises": "^2.0",
"laravel/framework": "^10.0|^11.0|^12.0",
"monolog/monolog": "^3.6",
"nesbot/carbon": "^2.0|^3.0",
"php": "^8.2",
"psr/http-message": "^1.0|^2.0",
"psr/log": "^1.0|^2.0|^3.0",
"ramsey/uuid": "^4.0",
"symfony/console": "^6.0|^7.0",
"symfony/http-foundation": "^6.0|^7.0",
"symfony/polyfill-php84": "^1.29"
},
"require-dev": {
"aws/aws-sdk-php": "^3.349",
"ext-pcntl": "*",
"ext-pdo": "*",
"guzzlehttp/guzzle": "^7.0",
"guzzlehttp/psr7": "^2.0",
"laravel/horizon": "^5.4",
"laravel/pint": "1.21.0",
"laravel/vapor-core": "^2.38.2",
"livewire/livewire": "^2.0|^3.0",
"mockery/mockery": "^1.0",
"mongodb/laravel-mongodb": "^4.0|^5.0",
"orchestra/testbench": "^8.0|^9.0|^10.0",
"orchestra/testbench-core": "^8.0|^9.0|^10.0",
"orchestra/workbench": "^8.0|^9.0|^10.0",
"phpstan/phpstan": "^1.0",
"phpunit/phpunit": "^10.0|^11.0|^12.0",
"singlestoredb/singlestoredb-laravel": "^1.0|^2.0",
"spatie/laravel-ignition": "^2.0",
"symfony/mailer": "^6.0|^7.0",
"symfony/mime": "^6.0|^7.0",
"symfony/var-dumper": "^6.0|^7.0"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Nightwatch": "Laravel\\Nightwatch\\Facades\\Nightwatch"
},
"providers": [
"Laravel\\Nightwatch\\NightwatchServiceProvider"
]
}
},
"autoload": {
"files": [
"agent/helpers.php"
],
"psr-4": {
"Laravel\\Nightwatch\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The official Laravel Nightwatch package.",
"homepage": "https://nightwatch.laravel.com",
"keywords": [
"Insights",
"laravel",
"monitoring"
],
"support": {
"docs": "https://nightwatch.laravel.com/docs",
"issues": "https://github.com/laravel/nightwatch/issues",
"source": "https://github.com/laravel/nightwatch"
},
"time": "2026-01-15T04:53:20+00:00"
},
{
"name": "laravel/prompts",
"version": "v0.3.10",

View File

@@ -70,7 +70,7 @@ return [
'make_command' => [
'type' => 'sfc', // Options: 'sfc', 'mfc', 'class'
'emoji' => true, // Options: true, false
'emoji' => false, // Options: true, false
'with' => [
'js' => false,
'css' => false,

View File

@@ -0,0 +1,60 @@
<div class="p-4">
@if($row->application_text )
<div class="px-4 py-2 rounded-lg text-sm bg-violet-100 text-gray-700">
<div class="flex w-full justify-between items-start">
<div class="flex">
<svg class="shrink-0 fill-current text-violet-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-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z"></path>
</svg>
<div>{{ $row->application_text }}</div>
</div>
</div>
</div>
@endif
<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 block 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>
</tr>
</thead>
<!-- Table body -->
<tbody class="text-sm">
@foreach($row->paymentEvents 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">{{ $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">{{ $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">{{ $payment->event_id }}</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</section>
</div>

View File

@@ -0,0 +1,30 @@
<div
wire:ignore
x-data
x-init="
FilePond.registerPlugin(
FilePondPluginImagePreview,
FilePondPluginImageExifOrientation,
FilePondPluginFileValidateSize,
FilePondPluginImageEdit
);
FilePond.setOptions({
labelIdle: '{{ 'Drag & Drop Deiner Dateien oder <span class="filepond--label-action"> in Ordner suchen </span>' }}',
allowMultiple: {{ isset($attributes['multiple']) ? 'true' : 'false' }},
server: {
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
@this.upload('{{ $attributes['wire:model'] }}', file, load, error, progress)
},
revert: (filename, load) => {
@this.removeUpload('{{ $attributes['wire:model'] }}', filename, load)
},
load: (source, load, error, progress, abort, headers) => {
@this.load('{{ $attributes['wire:model'] }}', load, error, progress, abort, headers)
},
},
});
FilePond.create($refs.input);
"
>
<input type="file" x-ref="input" name="{{ $attributes['name'] }}">
</div>

View File

@@ -0,0 +1,13 @@
@props([
'for',
'label',
])
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-700 sm:pt-5">
<label for="{{ $for }}"
class="block text-sm font-medium text-gray-100 sm:mt-px sm:pt-2">
{{ $label }}
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
{{ $slot }}
</div>
</div>

View File

@@ -0,0 +1,53 @@
<div
wire:ignore
x-data="{
value: $wire.entangle('{{ $model }}'),
init() {
this.$nextTick(() => {
setTimeout(() => {
let editor = new EasyMDE({
element: this.$refs.editor,
lineNumbers: true,
uploadImage: false,
spellChecker: false,
showIcons: [
'heading',
'heading-smaller',
'heading-bigger',
'heading-1',
'heading-2',
'heading-3',
'code',
'table',
'quote',
'strikethrough',
'unordered-list',
'ordered-list',
'clean-block',
'horizontal-rule',
'undo',
'redo',
//'upload-image',
],
});
editor.value(this.value);
editor.codemirror.on('change', () => {
this.value = editor.value();
});
}, 100); // Adjust the delay as needed
});
},
}"
class="w-full"
>
<div class="prose max-w-none">
<textarea x-ref="editor"></textarea>
</div>
<style>
.EasyMDEContainer {
background-color: white;
}
</style>
</div>

View File

@@ -0,0 +1,89 @@
<?php
use Livewire\Component;
new class extends Component {
public $currentRoute = '';
public function mount(): void
{
$currentLivewireRouteName = request()->route()->getName();
$this->currentRoute = $currentLivewireRouteName;
}
};
?>
<div class="min-w-fit">
@php
$isCurrentRouteClass = 'pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0 bg-[linear-gradient(135deg,var(--tw-gradient-stops))] from-orange-500/[0.12] dark:from-orange-500/[0.24] to-orange-500/[0.04]';
$isNotCurrentRouteClass = 'pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0';
$isCurrentSubItem = 'block text-orange-500 transition truncate';
$isNotCurrentSubItem = 'block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate';
@endphp
<!-- Sidebar backdrop (mobile only) -->
<div
class="fixed inset-0 bg-gray-900 bg-opacity-30 z-40 lg:hidden lg:z-auto transition-opacity duration-200"
:class="sidebarOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'"
aria-hidden="true"
x-cloak
></div>
<!-- Sidebar -->
<div
id="sidebar"
class="flex flex-col absolute z-40 left-0 top-0 lg:static lg:left-auto lg:top-auto lg:translate-x-0 h-[100dvh] overflow-y-scroll lg:overflow-y-auto no-scrollbar w-64 lg:w-20 lg:sidebar-expanded:!w-64 2xl:!w-64 shrink-0 bg-white dark:bg-[#222222] shadow-sm rounded-r-2xl p-4 transition-all duration-200 ease-in-out"
:class="sidebarOpen ? 'translate-x-0' : '-translate-x-64'"
@click.outside="sidebarOpen = false"
@keydown.escape.window="sidebarOpen = false"
x-cloak="lg"
>
<!-- Sidebar header -->
<div class="flex justify-between mb-10 pr-3 sm:px-2">
<!-- Close button -->
<button class="lg:hidden text-gray-500 hover:text-gray-400" @click.stop="sidebarOpen = !sidebarOpen"
aria-controls="sidebar" :aria-expanded="sidebarOpen">
<span class="sr-only">Close sidebar</span>
<svg class="w-6 h-6 fill-current" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M10.7 18.7l1.4-1.4L7.8 13H20v-2H7.8l4.3-4.3-1.4-1.4L4 12z"/>
</svg>
</button>
<!-- Logo -->
<img class="w-6 h-6" src="{{ asset('einundzwanzig-alpha.jpg') }}" alt="Logo">
</div>
@php
$activeLinkGroupClass = ' bg-[linear-gradient(135deg,var(--tw-gradient-stops))] from-amber-500/[0.12] dark:from-amber-500/[0.24] to-amber-500/[0.04]';
$activeItemClass = 'block text-amber-500 transition truncate';
@endphp
<!-- Links -->
<div class="space-y-8">
{{--@include('components.layouts.navigation.meetups')--}}
@include('components.layouts.navigation.association')
{{--@include('components.layouts.navigation.events')
@include('components.layouts.navigation.courses')
@include('components.layouts.navigation.nostr')
@include('components.layouts.navigation.legacy')--}}
@include('components.layouts.navigation.admin')
</div>
<!-- Expand / collapse button -->
<div class="pt-3 hidden lg:inline-flex 2xl:hidden justify-end mt-auto">
<div class="w-12 pl-4 pr-3 py-2">
<button
class="text-gray-400 hover:text-gray-500 dark:text-gray-500 dark:hover:text-gray-400 transition-colors"
@click="sidebarExpanded = !sidebarExpanded">
<span class="sr-only">Expand / collapse sidebar</span>
<svg class="shrink-0 fill-current text-gray-400 dark:text-gray-500 sidebar-expanded:rotate-180"
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path
d="M15 16a1 1 0 0 1-1-1V1a1 1 0 1 1 2 0v14a1 1 0 0 1-1 1ZM8.586 7H1a1 1 0 1 0 0 2h7.586l-2.793 2.793a1 1 0 1 0 1.414 1.414l4.5-4.5A.997.997 0 0 0 12 8.01M11.924 7.617a.997.997 0 0 0-.217-.324l-4.5-4.5a1 1 0 0 0-1.414 1.414L8.586 7M12 7.99a.996.996 0 0 0-.076-.373Z"/>
</svg>
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,197 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{!! seo($seo ?? null) !!}
<title>{{ $title ?? 'Page Title' }}</title>
@livewireStyles
@wireUiScripts
@stack('scripts')
@vite(['resources/js/app.js','resources/css/app.css'])
@googlefonts
<script src="https://kit.fontawesome.com/866fd3d0ab.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
@include('components.layouts.partials.styles')
</head>
<body
class="font-sans antialiased bg-gray-100 dark:bg-[#222222] text-gray-600 dark:text-gray-400"
:class="{ 'sidebar-expanded': sidebarExpanded }"
x-data="{ sidebarOpen: false, sidebarExpanded: localStorage.getItem('sidebar-expanded') == 'true', inboxSidebarOpen: false }"
x-init="$watch('sidebarExpanded', value => localStorage.setItem('sidebar-expanded', value))"
>
<x-dialog />
<x-notifications />
<script>
if (localStorage.getItem('sidebar-expanded') == 'true') {
document.querySelector('body').classList.add('sidebar-expanded');
} else {
document.querySelector('body').classList.remove('sidebar-expanded');
}
</script>
<div x-data="nostrLogin"
class="flex h-[100dvh] overflow-hidden">
<livewire:layout.sidebar/>
<div
class="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
<!-- Site header -->
<header
class="sticky top-0 before:absolute before:inset-0 before:backdrop-blur-md before:bg-white/90 dark:before:bg-[#222222]/90 lg:before:bg-[#222222]/90 dark:lg:before:bg-[#222222]/90 before:-z-10 max-lg:shadow-sm z-30">
<div class="px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16 lg:border-b border-gray-200 dark:border-gray-700/60">
<!-- Header: Left side -->
<div class="flex">
<!-- Hamburger button -->
<button
class="text-gray-500 hover:text-gray-600 dark:hover:text-gray-400 lg:hidden"
@click.stop="sidebarOpen = !sidebarOpen"
aria-controls="sidebar"
:aria-expanded="sidebarOpen"
>
<span class="sr-only">Open sidebar</span>
<svg class="w-6 h-6 fill-current" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="4" y="5" width="16" height="2"/>
<rect x="4" y="11" width="16" height="2"/>
<rect x="4" y="17" width="16" height="2"/>
</svg>
</button>
</div>
<!-- Header: Right side -->
<div class="flex items-center space-x-3">
{{--@include('components.layouts.partials.search-button')--}}
{{--@include('components.layouts.partials.notification-buttons')--}}
@if(\App\Support\NostrAuth::check())
<form method="post" action="{{ route('logout') }}"
@submit="$dispatch('nostrLoggedOut')">
@csrf
<x-button secondary label="Logout" type="submit"/>
</form>
@else
<x-button wire:key="loginBtn" label="Mit Nostr verbinden" @click="openNostrLogin"
x-show="!$store.nostr.user"/>
@endif
<!-- Info button -->
<div class="relative inline-flex" x-data="{ open: false }">
<button
class="w-8 h-8 flex items-center justify-center hover:bg-[#1B1B1B] lg:hover:bg-[#1B1B1B] dark:hover:bg-[#1B1B1B]/50 dark:lg:hover:bg-[#1B1B1B] rounded-full"
:class="{ 'bg-gray-200 dark:bg-[#1B1B1B]': open }"
aria-haspopup="true"
@click.prevent="open = !open"
:aria-expanded="open"
>
<span class="sr-only">Info</span>
<svg class="fill-current text-gray-500/80 dark:text-gray-400/80" width="16" height="16"
viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path
d="M9 7.5a1 1 0 1 0-2 0v4a1 1 0 1 0 2 0v-4ZM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"/>
<path fill-rule="evenodd"
d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16Zm6-8A6 6 0 1 1 2 8a6 6 0 0 1 12 0Z"/>
</svg>
</button>
<div
class="origin-top-right z-10 absolute top-full right-0 min-w-44 bg-white dark:bg-[#1B1B1B] border border-gray-200 dark:border-[#1B1B1B]/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
>
<div
class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase pt-1.5 pb-2 px-3">
Information
</div>
<ul>
<li>
<a class="font-medium text-sm text-amber-500 hover:text-amber-600 dark:hover:text-amber-400 flex items-center py-1 px-3"
target="_blank"
href="https://gitworkshop.dev/r/naddr1qvzqqqrhnypzqzklvar4enzu53t06vpzu3h465nwkzhk9p9ls4y5crwhs3lnu5pnqy88wumn8ghj7mn0wvhxcmmv9uqpxetfde6kuer6wasku7nfvukkummnw3eqdgsn8w/issues"
@click="open = false" @focus="open = true"
@focusout="open = false">
<i class="fa-sharp-duotone fa-solid fa-code w-3 h-3 fill-current text-amber-500 shrink-0 mr-2"></i>
<span>Issues/Feedback</span>
</a>
</li>
<li>
<a class="font-medium text-sm text-amber-500 hover:text-amber-600 dark:hover:text-amber-400 flex items-center py-1 px-3"
href="{{ route('changelog') }}" @click="open = false" @focus="open = true"
@focusout="open = false">
<i class="fa-sharp-duotone fa-solid fa-code w-3 h-3 fill-current text-amber-500 shrink-0 mr-2"></i>
<span>Changelog</span>
</a>
</li>
<li>
<a class="font-medium text-sm text-amber-500 hover:text-amber-600 dark:hover:text-amber-400 flex items-center py-1 px-3"
href="https://github.com/HolgerHatGarKeineNode/einundzwanzig-nostr"
target="_blank" @click="open = false" @focus="open = true"
@focusout="open = false">
<i class="fa-brands fa-github w-3 h-3 fill-current text-amber-500 shrink-0 mr-2"></i>
<span>Github</span>
</a>
</li>
<li>
<a class="font-medium text-sm text-amber-500 hover:text-amber-600 dark:hover:text-amber-400 flex items-center py-1 px-3"
href="https://einundzwanzig.space/kontakt/" target="_blank"
@click="open = false" @focus="open = true"
@focusout="open = false">
<i class="fa-sharp-duotone fa-solid fa-info w-3 h-3 fill-current text-amber-500 shrink-0 mr-2"></i>
<span>Impressum</span>
</a>
</li>
</ul>
</div>
</div>
{{--@include('components.layouts.partials.dark-mode-toggle')--}}
<!-- Divider -->
{{--<hr class="w-px h-6 bg-gray-200 dark:bg-gray-700/60 border-none"/>--}}
{{--@include('components.layouts.partials.user-button')--}}
</div>
</div>
</div>
</header>
<main class="grow">
{{ $slot }}
</main>
</div>
</div>
@livewireScriptConfig
<script>
window.wnjParams = {
position: 'bottom',
// The only accepted value is 'bottom', default is top
accent: 'orange',
// Supported values: cyan (default), green, purple, red, orange, neutral, stone
startHidden: false,
// If the host page has a button that call `getPublicKey` to start a
// login procedure, the minimized widget can be hidden until connected
compactMode: false,
// Show the minimized widget in a compact form
disableOverflowFix: false,
// If the host page on mobile has an horizontal scrolling, the floating
// element/modal are pushed to the extreme right/bottom and exit the
// viewport. A style is injected in the html/body elements fix this.
// This option permit to disable this default behavior
}
</script>
<script src="{{ asset('dist/window.nostr.min.js.js') }}"></script>
</body>
</html>

View File

@@ -0,0 +1,30 @@
<!-- Admin group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Admin-Bereich</span>
</h3>
<ul class="mt-3">
{{--<li class="{{ $currentRoute === 'association.elections' ? $isCurrentRouteClass : $isNotCurrentRouteClass }}">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="{{ route('association.elections') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-booth-curtain h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Einstellungen</span>
</div>
</a>
</li>--}}
<li class="{{ $currentRoute === 'association.members.admin' ? $isCurrentRouteClass : $isNotCurrentRouteClass }}">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="{{ route('association.members.admin') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-users h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Mitglieder</span>
</div>
</a>
</li>
</ul>
</div>

View File

@@ -0,0 +1,50 @@
<!-- Association group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Verein</span>
</h3>
<ul class="mt-3">
<li class="{{ $currentRoute === 'association.news' ? $isCurrentRouteClass : $isNotCurrentRouteClass }}">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="{{ route('association.news') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-rss h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">News</span>
</div>
</a>
</li>
<li class="{{ $currentRoute === 'association.profile' ? $isCurrentRouteClass : $isNotCurrentRouteClass }}">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="{{ route('association.profile') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-id-card-clip h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Meine Mitgliedschaft</span>
</div>
</a>
</li>
{{--<li class="{{ $currentRoute === 'association.election' ? $isCurrentRouteClass : $isNotCurrentRouteClass }}">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="{{ route('association.election', ['election' => date('Y')]) }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-check-to-slot h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Vorstands-Wahlen</span>
</div>
</a>
</li>--}}
<li class="{{ $currentRoute === 'association.projectSupport' ? $isCurrentRouteClass : $isNotCurrentRouteClass }}">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="{{ route('association.projectSupport') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-hand-heart h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Projekt-Unterstützungen</span>
</div>
</a>
</li>
</ul>
</div>

View File

@@ -0,0 +1,88 @@
<!-- Courses group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Courses</span>
</h3>
<ul class="mt-3">
<!-- Browse -->
<li class="pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0"
x-data="{ open: false }">
<a class="block text-gray-800 dark:text-gray-100 truncate transition" href="#0"
@click.prevent="open = !open; sidebarExpanded = true">
<div class="flex items-center justify-between">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-graduation-cap h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Browse</span>
</div>
<!-- Icon -->
<div
class="flex shrink-0 ml-2 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">
<svg class="w-3 h-3 shrink-0 ml-1 fill-current text-gray-400 dark:text-gray-500"
:class="open ? 'rotate-180' : 'rotate-0'" viewBox="0 0 12 12">
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z"/>
</svg>
</div>
</div>
</a>
<div class="lg:hidden lg:sidebar-expanded:block 2xl:block">
<ul class="pl-8 mt-1" :class="open ? '!block' : 'hidden'">
<li class="mb-1 last:mb-0">
<a class="block text-amber-500 transition truncate" href="index.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Main</span>
</a>
</li>
<li class="mb-1 last:mb-0">
<a class="block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate"
href="analytics.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Analytics</span>
</a>
</li>
<li class="mb-1 last:mb-0">
<a class="block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate"
href="fintech.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Fintech</span>
</a>
</li>
</ul>
</div>
</li>
<!-- Manage -->
<li class="pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0" x-data="{ open: false }">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="#0" @click.prevent="open = !open; sidebarExpanded = true">
<div class="flex items-center justify-between">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-pencil h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Manage</span>
</div>
<!-- Icon -->
<div
class="flex shrink-0 ml-2 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">
<svg class="w-3 h-3 shrink-0 ml-1 fill-current text-gray-400 dark:text-gray-500"
:class="open ? 'rotate-180' : 'rotate-0'" viewBox="0 0 12 12">
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z"/>
</svg>
</div>
</div>
</a>
<div class="lg:hidden lg:sidebar-expanded:block 2xl:block">
<ul class="pl-8 mt-1 hidden" :class="open ? '!block' : 'hidden'">
<li class="mb-1 last:mb-0">
<a class="block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate"
href="customers.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Manage cities</span>
</a>
</li>
</ul>
</div>
</li>
</ul>
</div>

View File

@@ -0,0 +1,88 @@
<!-- Events group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Events</span>
</h3>
<ul class="mt-3">
<!-- Browse -->
<li class="pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0"
x-data="{ open: false }">
<a class="block text-gray-800 dark:text-gray-100 truncate transition" href="#0"
@click.prevent="open = !open; sidebarExpanded = true">
<div class="flex items-center justify-between">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-calendar h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Browse</span>
</div>
<!-- Icon -->
<div
class="flex shrink-0 ml-2 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">
<svg class="w-3 h-3 shrink-0 ml-1 fill-current text-gray-400 dark:text-gray-500"
:class="open ? 'rotate-180' : 'rotate-0'" viewBox="0 0 12 12">
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z"/>
</svg>
</div>
</div>
</a>
<div class="lg:hidden lg:sidebar-expanded:block 2xl:block">
<ul class="pl-8 mt-1" :class="open ? '!block' : 'hidden'">
<li class="mb-1 last:mb-0">
<a class="block text-amber-500 transition truncate" href="index.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Main</span>
</a>
</li>
<li class="mb-1 last:mb-0">
<a class="block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate"
href="analytics.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Analytics</span>
</a>
</li>
<li class="mb-1 last:mb-0">
<a class="block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate"
href="fintech.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Fintech</span>
</a>
</li>
</ul>
</div>
</li>
<!-- Manage -->
<li class="pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0" x-data="{ open: false }">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition"
href="#0" @click.prevent="open = !open; sidebarExpanded = true">
<div class="flex items-center justify-between">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-pencil h-4 w-4"></i>
<span
class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Manage</span>
</div>
<!-- Icon -->
<div
class="flex shrink-0 ml-2 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">
<svg class="w-3 h-3 shrink-0 ml-1 fill-current text-gray-400 dark:text-gray-500"
:class="open ? 'rotate-180' : 'rotate-0'" viewBox="0 0 12 12">
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z"/>
</svg>
</div>
</div>
</a>
<div class="lg:hidden lg:sidebar-expanded:block 2xl:block">
<ul class="pl-8 mt-1 hidden" :class="open ? '!block' : 'hidden'">
<li class="mb-1 last:mb-0">
<a class="block text-gray-500/90 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition truncate"
href="customers.html">
<span
class="text-sm font-medium lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Manage cities</span>
</a>
</li>
</ul>
</div>
</li>
</ul>
</div>

View File

@@ -0,0 +1,11 @@
<!-- Legacy group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Legacy</span>
</h3>
<ul class="mt-3">
</ul>
</div>

View File

@@ -0,0 +1,26 @@
<!-- Meetups group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Meetups</span>
</h3>
<ul class="mt-3">
<li class="pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition" href="{{ route('meetups.worldmap') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-map h-4 w-4"></i>
<span class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">World Map</span>
</div>
</a>
</li>
<li class="pl-4 pr-3 py-2 rounded-lg mb-0.5 last:mb-0">
<a class="block text-gray-800 dark:text-gray-100 hover:text-gray-900 dark:hover:text-white truncate transition" href="{{ route('meetups.grid') }}">
<div class="flex items-center">
<i class="fa-sharp-duotone fa-solid fa-handshake-angle h-4 w-4"></i>
<span class="text-sm font-medium ml-4 lg:opacity-0 lg:sidebar-expanded:opacity-100 2xl:opacity-100 duration-200">Alle Meetups</span>
</div>
</a>
</li>
</ul>
</div>

View File

@@ -0,0 +1,11 @@
<!-- Nostr group -->
<div>
<h3 class="text-xs uppercase text-gray-400 dark:text-gray-500 font-semibold pl-3">
<span class="hidden lg:block lg:sidebar-expanded:hidden 2xl:hidden text-center w-6"
aria-hidden="true">•••</span>
<span class="lg:hidden lg:sidebar-expanded:block 2xl:block">Nostr</span>
</h3>
<ul class="mt-3">
</ul>
</div>

View File

@@ -0,0 +1,22 @@
<div>
<input type="checkbox" name="light-switch" id="light-switch" class="light-switch sr-only"/>
<label
class="flex items-center justify-center cursor-pointer w-8 h-8 hover:bg-gray-100 lg:hover:bg-gray-200 dark:hover:bg-gray-700/50 dark:lg:hover:bg-gray-800 rounded-full"
for="light-switch">
<svg class="dark:hidden fill-current text-gray-500/80 dark:text-gray-400/80" width="16"
height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0a1 1 0 0 1 1 1v.5a1 1 0 1 1-2 0V1a1 1 0 0 1 1-1Z"/>
<path d="M12 8a4 4 0 1 1-8 0 4 4 0 0 1 8 0Zm-4 2a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z"/>
<path
d="M13.657 3.757a1 1 0 0 0-1.414-1.414l-.354.354a1 1 0 0 0 1.414 1.414l.354-.354ZM13.5 8a1 1 0 0 1 1-1h.5a1 1 0 1 1 0 2h-.5a1 1 0 0 1-1-1ZM13.303 11.889a1 1 0 0 0-1.414 1.414l.354.354a1 1 0 0 0 1.414-1.414l-.354-.354ZM8 13.5a1 1 0 0 1 1 1v.5a1 1 0 1 1-2 0v-.5a1 1 0 0 1 1-1ZM4.111 13.303a1 1 0 1 0-1.414-1.414l-.354.354a1 1 0 1 0 1.414 1.414l.354-.354ZM0 8a1 1 0 0 1 1-1h.5a1 1 0 0 1 0 2H1a1 1 0 0 1-1-1ZM3.757 2.343a1 1 0 1 0-1.414 1.414l.354.354A1 1 0 1 0 4.11 2.697l-.354-.354Z"/>
</svg>
<svg class="hidden dark:block fill-current text-gray-500/80 dark:text-gray-400/80"
width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path
d="M11.875 4.375a.625.625 0 1 0 1.25 0c.001-.69.56-1.249 1.25-1.25a.625.625 0 1 0 0-1.25 1.252 1.252 0 0 1-1.25-1.25.625.625 0 1 0-1.25 0 1.252 1.252 0 0 1-1.25 1.25.625.625 0 1 0 0 1.25c.69.001 1.249.56 1.25 1.25Z"/>
<path
d="M7.019 1.985a1.55 1.55 0 0 0-.483-1.36 1.44 1.44 0 0 0-1.53-.277C2.056 1.553 0 4.5 0 7.9 0 12.352 3.648 16 8.1 16c3.407 0 6.246-2.058 7.51-4.963a1.446 1.446 0 0 0-.25-1.55 1.554 1.554 0 0 0-1.372-.502c-4.01.552-7.539-2.987-6.97-7ZM2 7.9C2 5.64 3.193 3.664 4.961 2.6 4.82 7.245 8.72 11.158 13.36 11.04 12.265 12.822 10.341 14 8.1 14 4.752 14 2 11.248 2 7.9Z"/>
</svg>
<span class="sr-only">Switch to light / dark version</span>
</label>
</div>

View File

@@ -0,0 +1,64 @@
<div class="relative inline-flex" x-data="{ open: false }">
<button
class="w-8 h-8 flex items-center justify-center hover:bg-gray-100 lg:hover:bg-gray-200 dark:hover:bg-gray-700/50 dark:lg:hover:bg-gray-800 rounded-full"
:class="{ 'bg-gray-200 dark:bg-gray-800': open }"
aria-haspopup="true"
@click.prevent="open = !open"
:aria-expanded="open"
>
<span class="sr-only">Notifications</span>
<svg class="fill-current text-gray-500/80 dark:text-gray-400/80" width="16" height="16"
viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path
d="M7 0a7 7 0 0 0-7 7c0 1.202.308 2.33.84 3.316l-.789 2.368a1 1 0 0 0 1.265 1.265l2.595-.865a1 1 0 0 0-.632-1.898l-.698.233.3-.9a1 1 0 0 0-.104-.85A4.97 4.97 0 0 1 2 7a5 5 0 0 1 5-5 4.99 4.99 0 0 1 4.093 2.135 1 1 0 1 0 1.638-1.148A6.99 6.99 0 0 0 7 0Z"/>
<path
d="M11 6a5 5 0 0 0 0 10c.807 0 1.567-.194 2.24-.533l1.444.482a1 1 0 0 0 1.265-1.265l-.482-1.444A4.962 4.962 0 0 0 16 11a5 5 0 0 0-5-5Zm-3 5a3 3 0 0 1 6 0c0 .588-.171 1.134-.466 1.6a1 1 0 0 0-.115.82 1 1 0 0 0-.82.114A2.973 2.973 0 0 1 11 14a3 3 0 0 1-3-3Z"/>
</svg>
<div
class="absolute top-0 right-0 w-2.5 h-2.5 bg-red-500 border-2 border-gray-100 dark:border-gray-900 rounded-full"></div>
</button>
<div
class="origin-top-right z-10 absolute top-full right-0 -mr-48 sm:mr-0 min-w-80 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
>
<div
class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase pt-1.5 pb-2 px-4">
Notifications
</div>
<ul>
<li class="border-b border-gray-200 dark:border-gray-700/60 last:border-0">
<a class="block py-2 px-4 hover:bg-gray-50 dark:hover:bg-gray-700/20" href="#0"
@click="open = false" @focus="open = true" @focusout="open = false">
<span class="block text-sm mb-2">📣 <span
class="font-medium text-gray-800 dark:text-gray-100">Edit your information in a swipe</span> Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.</span>
<span class="block text-xs font-medium text-gray-400 dark:text-gray-500">Feb 12, 2024</span>
</a>
</li>
<li class="border-b border-gray-200 dark:border-gray-700/60 last:border-0">
<a class="block py-2 px-4 hover:bg-gray-50 dark:hover:bg-gray-700/20" href="#0"
@click="open = false" @focus="open = true" @focusout="open = false">
<span class="block text-sm mb-2">📣 <span
class="font-medium text-gray-800 dark:text-gray-100">Edit your information in a swipe</span> Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.</span>
<span class="block text-xs font-medium text-gray-400 dark:text-gray-500">Feb 9, 2024</span>
</a>
</li>
<li class="border-b border-gray-200 dark:border-gray-700/60 last:border-0">
<a class="block py-2 px-4 hover:bg-gray-50 dark:hover:bg-gray-700/20" href="#0"
@click="open = false" @focus="open = true" @focusout="open = false">
<span class="block text-sm mb-2">🚀<span
class="font-medium text-gray-800 dark:text-gray-100">Say goodbye to paper receipts!</span> Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.</span>
<span class="block text-xs font-medium text-gray-400 dark:text-gray-500">Jan 24, 2024</span>
</a>
</li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,201 @@
<!-- Search button -->
<div x-data="{ searchOpen: false }">
<!-- Button -->
<button
class="w-8 h-8 flex items-center justify-center hover:bg-gray-100 lg:hover:bg-gray-200 dark:hover:bg-gray-700/50 dark:lg:hover:bg-gray-800 rounded-full"
:class="{ 'bg-gray-200 dark:bg-gray-800': searchOpen }"
@click.prevent="searchOpen = true;if (searchOpen) $nextTick(()=>{$refs.searchInput.focus();});"
aria-controls="search-modal"
>
<span class="sr-only">Search</span>
<svg class="fill-current text-gray-500/80 dark:text-gray-400/80" 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="m13.314 11.9 2.393 2.393a.999.999 0 1 1-1.414 1.414L11.9 13.314a8.019 8.019 0 0 0 1.414-1.414Z"/>
</svg>
</button>
<!-- Modal backdrop -->
<div
class="fixed inset-0 bg-gray-900 bg-opacity-30 z-50 transition-opacity"
x-show="searchOpen"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-out duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
aria-hidden="true"
x-cloak
></div>
<!-- Modal dialog -->
<div
id="search-modal"
class="fixed inset-0 z-50 overflow-hidden flex items-start top-20 mb-4 justify-center px-4 sm:px-6"
role="dialog"
aria-modal="true"
x-show="searchOpen"
x-transition:enter="transition ease-in-out duration-200"
x-transition:enter-start="opacity-0 translate-y-4"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in-out duration-200"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-4"
x-cloak
>
<div
class="bg-white dark:bg-gray-800 border border-transparent dark:border-gray-700/60 overflow-auto max-w-2xl w-full max-h-full rounded-lg shadow-lg"
@click.outside="searchOpen = false"
@keydown.escape.window="searchOpen = false"
>
<!-- Search form -->
<form class="border-b border-gray-200 dark:border-gray-700/60">
<div class="relative">
<label for="modal-search" class="sr-only">Search</label>
<input id="modal-search"
class="w-full dark:text-gray-300 bg-white dark:bg-gray-800 border-0 focus:ring-transparent placeholder-gray-400 dark:placeholder-gray-500 appearance-none py-3 pl-10 pr-4"
type="search" placeholder="Search Anything…" x-ref="searchInput"/>
<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-4 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>
</div>
</form>
<div class="py-4 px-2">
<!-- Recent searches -->
<div class="mb-3 last:mb-0">
<div
class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase px-2 mb-2">
Recent searches
</div>
<ul class="text-sm">
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z"/>
</svg>
<span>Form Builder - 23 hours on-demand video</span>
</a>
</li>
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z"/>
</svg>
<span>Access Mosaic on mobile and TV</span>
</a>
</li>
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z"/>
</svg>
<span>Product Update - Q4 2024</span>
</a>
</li>
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z"/>
</svg>
<span>Master Digital Marketing Strategy course</span>
</a>
</li>
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z"/>
</svg>
<span>Dedicated forms for products</span>
</a>
</li>
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z"/>
</svg>
<span>Product Update - Q4 2024</span>
</a>
</li>
</ul>
</div>
<!-- Recent pages -->
<div class="mb-3 last:mb-0">
<div
class="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase px-2 mb-2">
Recent pages
</div>
<ul class="text-sm">
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M14 0H2c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h8l5-5V1c0-.6-.4-1-1-1zM3 2h10v8H9v4H3V2z"/>
</svg>
<span><span class="font-medium">Messages</span> - <span
class="text-gray-600 dark:text-gray-400">Conversation / / Mike Mills</span></span>
</a>
</li>
<li>
<a class="flex items-center p-2 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700/20 rounded-lg"
href="#0" @click="searchOpen = false" @focus="searchOpen = true"
@focusout="searchOpen = false">
<svg
class="fill-current text-gray-400 dark:text-gray-500 shrink-0 mr-3"
width="16" height="16" viewBox="0 0 16 16">
<path
d="M14 0H2c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h8l5-5V1c0-.6-.4-1-1-1zM3 2h10v8H9v4H3V2z"/>
</svg>
<span><span class="font-medium">Messages</span> - <span
class="text-gray-600 dark:text-gray-400">Conversation / / Eva Patrick</span></span>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<style>
/**/
</style>

View File

@@ -0,0 +1,49 @@
<div class="relative inline-flex" x-data="{ open: false }">
<button
class="inline-flex justify-center items-center group"
aria-haspopup="true"
@click.prevent="open = !open"
:aria-expanded="open"
>
<img class="w-8 h-8 rounded-full" src="./images/user-avatar-32.png" width="32"
height="32" alt="User"/>
<div class="flex items-center truncate">
<span
class="truncate ml-2 text-sm font-medium text-gray-600 dark:text-gray-100 group-hover:text-gray-800 dark:group-hover:text-white">Acme Inc.</span>
<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>
</div>
</button>
<div
class="origin-top-right z-10 absolute top-full right-0 min-w-44 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
>
<div class="pt-0.5 pb-2 px-3 mb-1 border-b border-gray-200 dark:border-gray-700/60">
<div class="font-medium text-gray-800 dark:text-gray-100">Acme Inc.</div>
<div class="text-xs text-gray-500 dark:text-gray-400 italic">Administrator</div>
</div>
<ul>
<li>
<a class="font-medium text-sm text-violet-500 hover:text-violet-600 dark:hover:text-violet-400 flex items-center py-1 px-3"
href="settings.html" @click="open = false" @focus="open = true"
@focusout="open = false">Settings</a>
</li>
<li>
<a class="font-medium text-sm text-violet-500 hover:text-violet-600 dark:hover:text-violet-400 flex items-center py-1 px-3"
href="signin.html" @click="open = false" @focus="open = true"
@focusout="open = false">Sign Out</a>
</li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,124 @@
@props(['project', 'currentPleb', 'section' => 'all'])
@php
$boardVotes = $project->votes->filter(function ($vote) {
return in_array($vote->einundzwanzigPleb->npub, config('einundzwanzig.config.current_board'));
});
$approveCount = $boardVotes->where('value', 1)->count();
$disapproveCount = $boardVotes->where('value', 0)->count();
$shouldDisplay = match($section) {
'all' => true,
'new' => $approveCount < 3,
'supported' => $project->sats_paid > 0,
'rejected' => $disapproveCount >= 3,
'approved' => ($approveCount === 3 || $disapproveCount !== 3),
default => true,
};
@endphp
@if($shouldDisplay)
<article
wire:key="project_{{ $project->id }}"
class="flex bg-white dark:bg-gray-800 shadow-sm rounded-xl overflow-hidden">
<!-- Image -->
@if(!$project->sats_paid)
<a class="relative block w-24 sm:w-56 xl:sidebar-expanded:w-40 2xl:sidebar-expanded:w-56 shrink-0"
href="{{ route('association.projectSupport.item', ['projectProposal' => $project]) }}">
<img class="absolute object-cover object-center w-full h-full"
src="{{ $project->getFirstMediaUrl('main') }}" alt="Meetup 01">
<button class="absolute top-0 right-0 mt-4 mr-4">
<img class="rounded-full h-8 w-8"
src="{{ $project->einundzwanzigPleb->profile?->picture ?? asset('einundzwanzig-alpha.jpg') }}"
alt="">
</button>
</a>
@else
<div
class="relative block w-24 sm:w-56 xl:sidebar-expanded:w-40 2xl:sidebar-expanded:w-56 shrink-0"
href="{{ route('association.projectSupport.item', ['projectProposal' => $project]) }}">
<img class="absolute object-cover object-center w-full h-full"
src="{{ $project->getFirstMediaUrl('main') }}" alt="Meetup 01">
<button class="absolute top-0 right-0 mt-4 mr-4">
<img class="rounded-full h-8 w-8"
src="{{ $project->einundzwanzigPleb->profile?->picture ?? asset('einundzwanzig-alpha.jpg') }}"
alt="">
</button>
</div>
@endif
<!-- Content -->
<div class="grow p-5 flex flex-col">
<div class="grow">
<div class="text-sm font-semibold text-amber-500 uppercase mb-2">
Eingereicht von: {{ $project->einundzwanzigPleb->profile?->name ?? str($project->einundzwanzigPleb->npub)->limit(32) }}
</div>
<div class="inline-flex mb-2">
<h3 class="text-lg font-bold text-gray-800 dark:text-gray-100">
{{ $project->name }}
</h3>
</div>
<div class="text-sm line-clamp-1 sm:line-clamp-3">
{!! strip_tags($project->description) !!}
</div>
</div>
<!-- Footer -->
<div class="flex justify-between items-center mt-3">
<!-- Tag -->
<div
class="text-xs inline-flex items-center font-bold border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-200 rounded-full text-center px-2.5 py-1">
<span>{{ number_format($project->support_in_sats, 0, ',', '.') }} Sats</span>
</div>
<div
class="text-xs inline-flex items-center font-bold border border-gray-200 dark:border-gray-700/60 text-gray-600 dark:text-gray-200 rounded-full text-center px-2.5 py-1">
<a href="{{ $project->website }}" target="_blank">Webseite</a>
</div>
<!-- Avatars -->
@if($project->votes->where('value', true)->count() > 0)
<div class="hidden sm:flex items-center space-x-2">
<div class="text-xs font-medium text-gray-400 dark:text-gray-300 italic">
Anzahl der Unterstützer:
+{{ $project->votes->where('value', true)->count() }}
</div>
</div>
@endif
</div>
<div
class="flex flex-col sm:flex-row justify-between items-center mt-3 space-y-2 sm:space-y-0">
@if(
($currentPleb && $currentPleb->id === $project->einundzwanzig_pleb_id)
|| ($currentPleb && in_array($currentPleb->npub, config('einundzwanzig.config.current_board'), true))
)
<x-button
icon="trash"
xs
negative
wire:click="confirmDelete({{ $project->id }})"
label="Löschen"/>
<x-button
icon="pencil"
xs
secondary
:href="route('association.projectSupport.edit', ['projectProposal' => $project])"
label="Editieren"/>
@endif
@if(($currentPleb && $currentPleb->association_status->value > 2) || $project->accepted)
<x-button
icon="folder-open"
xs
:href="route('association.projectSupport.item', ['projectProposal' => $project])"
label="Öffnen"/>
@endif
</div>
<div class="py-2">
@if($project->sats_paid)
<div
class="text-sm inline-flex font-medium bg-green-500/20 text-green-700 rounded-full text-center px-2.5 py-1">
Wurde mit {{ number_format($project->sats_paid, 0, ',', '.') }} Sats
unterstützt
</div>
@endif
</div>
</div>
</article>
@endif

View File

@@ -6,8 +6,6 @@ use App\Support\NostrAuth;
use Livewire\Component;
new class extends Component {
public $layout = 'layouts.app';
public $title = __('Wahlen');
public bool $isAllowed = false;

View File

@@ -320,14 +320,6 @@ new class extends Component {
\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)
]);
}
};
?>

View File

@@ -61,12 +61,6 @@ new class extends Component {
}
}
public function render()
{
return view('livewire.association.members.admin')
->layout('layouts.app')
->title(__('Mitglieder'));
}
};
?>

View File

@@ -1,207 +1,303 @@
<x-layouts.app
:seo="new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'News', description: 'Die News des Vereins.')"
>
<div>
@if($isAllowed)
<div class="px-4 sm:px-6 lg:px-8 py-8 md:py-0 w-full max-w-9xl mx-auto">
<?php
<div class="xl:flex">
use App\Enums\NewsCategory;
use App\Models\Notification;
use App\Support\NostrAuth;
use Illuminate\Support\Collection;
use Livewire\Component;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\WithFileUploads;
<!-- Left + Middle content -->
<div class="md:flex flex-1">
new
#[Layout('layouts.app')]
#[Title('News')]
class extends Component {
use WithFileUploads;
<!-- 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">
public Collection|array $news = [];
<div class="flex justify-between items-center md:block">
public array $form = [
'category' => '',
'name' => '',
'description' => '',
];
<!-- Title -->
<header class="mb-6">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
News</h1>
</header>
public mixed $file;
</div>
public bool $isAllowed = false;
<!-- 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">
@foreach(\App\Enums\NewsCategory::selectOptions() as $category)
<li class="mr-0.5 md:mr-0 md:mb-0.5"
wire:key="category_{{ $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-{{ $category['icon'] }} shrink-0 fill-current text-amber-500 mr-2"></i>
<span
class="text-sm font-medium text-amber-500">{{ $category['label'] }}</span>
</div>
</li>
@endforeach
</ul>
public bool $canEdit = false;
public function mount(): void
{
if (NostrAuth::check()) {
$currentPubkey = NostrAuth::pubkey();
$currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $currentPubkey)->first();
if ($currentPleb && $currentPleb->association_status->value > 1 && $currentPleb->paymentEvents()->where('year',
date('Y'))->where('paid', true)->exists()) {
$this->isAllowed = true;
}
if ($currentPleb && $currentPleb->association_status->value > 2) {
$this->canEdit = true;
}
$this->news = \App\Models\Notification::query()
->with(['einundzwanzigPleb.profile'])
->latest()
->get();
}
}
public function save(): void
{
$this->validate([
'file' => 'required|file|mimes:pdf',
'form.category' => 'required|string|in:'.implode(',', NewsCategory::values()),
'form.name' => 'required|string|max:255',
'form.description' => 'nullable|string',
]);
$currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', NostrAuth::pubkey())->first();
$news = Notification::query()->create([
'name' => $this->form['name'],
'description' => $this->form['description'] ?? null,
'category' => $this->form['category'],
'einundzwanzig_pleb_id' => $currentPleb->id,
]);
if ($this->file) {
$news
->addMedia($this->file)
->toMediaCollection('pdf');
}
$this->reset(['form', 'file']);
$this->news = \App\Models\Notification::query()
->with(['einundzwanzigPleb.profile'])
->latest()
->get();
}
public function delete(int $id): void
{
$news = Notification::query()->find($id);
if ($news) {
$news->delete();
}
$this->news = \App\Models\Notification::query()
->with(['einundzwanzigPleb.profile'])
->latest()
->get();
}
};
?>
<div>
@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">
@foreach(\App\Enums\NewsCategory::selectOptions() as $category)
<li class="mr-0.5 md:mr-0 md:mb-0.5"
wire:key="category_{{ $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-{{ $category['icon'] }} shrink-0 fill-current text-amber-500 mr-2"></i>
<span
class="text-sm font-medium text-amber-500">{{ $category['label'] }}</span>
</div>
</li>
@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">
<!-- 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">
@forelse($news as $post)
<article wire:key="post_{{ $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="{{ $post->einundzwanzigPleb->profile?->picture ?? asset('einundzwanzig-alpha.jpg') }}"
width="32" height="32"
alt="{{ $post->einundzwanzigPleb->profile?->name }}">
</div>
<!-- Content -->
<div class="grow">
<!-- Title -->
<h2 class="font-semibold text-gray-800 dark:text-gray-100 mb-2">
{{ $post->name }}
</h2>
<p class="mb-6">
{{ $post->description }}
</p>
<!-- Footer -->
<footer class="flex flex-wrap text-sm">
<div class="space-y-2">
@forelse($news as $post)
<article wire:key="post_{{ $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="{{ $post->einundzwanzigPleb->profile?->picture ?? asset('einundzwanzig-alpha.jpg') }}"
width="32" height="32"
alt="{{ $post->einundzwanzigPleb->profile?->name }}">
</div>
<!-- Content -->
<div class="grow">
<!-- Title -->
<h2 class="font-semibold text-gray-800 dark:text-gray-100 mb-2">
{{ $post->name }}
</h2>
<p class="mb-6">
{{ $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="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>
{{ $post->einundzwanzigPleb->profile->name }}
</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>
{{ $post->einundzwanzigPleb->profile->name }}
</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">
</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">{{ $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"/>
@if($canEdit)
<x-button
xs
wire:click="delete({{ $post->id }})"
wire:loading.attr="disabled"
label="Löschen"
negative icon="trash"/>
@endif
</div>
</article>
@empty
<article class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<p>Keine News vorhanden.</p>
</article>
@endforelse
</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">
@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 wire:dirty>
<input class="text-gray-200" type="file" wire:model="file">
@error('file')
<span class="text-red-500">{{ $message }}</span>
@enderror
</div>
<div wire:dirty>
<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 wire:dirty>
<x-input label="Titel" wire:model="form.name"/>
</div>
<div wire:dirty>
<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>
</footer>
</div>
</div>
@endif
</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"/>
@if($canEdit)
<x-button
xs
wire:click="delete({{ $post->id }})"
wire:loading.attr="disabled"
label="Löschen"
negative icon="trash"/>
@endif
</div>
</article>
@empty
<article class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<p>Keine News vorhanden.</p>
</article>
@endforelse
</div>
</div>
</div>
</div>
</div>
@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>
<!-- 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">
@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 wire:dirty>
<input class="text-gray-200" type="file" wire:model="file">
@error('file')
<span class="text-red-500">{{ $message }}</span>
@enderror
</div>
<div wire:dirty>
<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 wire:dirty>
<x-input label="Titel" wire:model="form.name"/>
</div>
<div wire:dirty>
<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>
@endif
</div>
</div>
</div>
</div>
</div>
@endif
</div>
</x-layouts.app>
</div>
@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>
@endif
</div>

View File

@@ -1,4 +1,53 @@
<x-layouts.app title="{{ __('Projektförderung anlegen') }}">
<?php
use App\Models\ProjectProposal;
use App\Support\NostrAuth;
use Livewire\Component;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
new
#[Layout('layouts.app')]
#[Title('Projektförderung anlegen')]
class extends Component {
public array $form = [
'name' => '',
'description' => '',
];
public bool $isAllowed = false;
public function mount(): void
{
if (NostrAuth::check()) {
$currentPubkey = NostrAuth::pubkey();
$currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $currentPubkey)->first();
if ($currentPleb && $currentPleb->association_status->value > 1 && $currentPleb->paymentEvents()->where('year', date('Y'))->where('paid', true)->exists()) {
$this->isAllowed = true;
}
}
}
public function save(): void
{
$this->validate([
'form.name' => 'required|string|max:255',
'form.description' => 'required|string',
]);
ProjectProposal::query()->create([
'name' => $this->form['name'],
'description' => $this->form['description'],
'einundzwanzig_pleb_id' => \App\Models\EinundzwanzigPleb::query()->where('pubkey', NostrAuth::pubkey())->first()->id,
]);
$this->redirectRoute('association.projectSupport');
}
};
?>
<x-layouts.app>
<div>
@if($isAllowed)
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">

View File

@@ -1,74 +1,128 @@
<x-layouts.app title="{{ __('Projektförderung bearbeiten') }}">
<div>
@if($isAllowed)
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div
class="flex flex-col md:flex-row items-center mb-6 space-y-4 md:space-y-0 md:space-x-4">
<div class="flex items-center justify-between w-full">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
Projektförderung bearbeiten
</h1>
</div>
</div>
<?php
<div class="md:flex">
<!-- Left column -->
<div class="w-full md:w-60 mb-4 md:mb-0">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Formular
</h2>
<div class="space-y-4">
<div wire:dirty>
<x-input label="Name" wire:model="form.name"/>
@error('form.name')
<span class="text-red-500">{{ $message }}</span>
@enderror
</div>
<div wire:dirty>
<x-textarea label="Beschreibung" wire:model="form.description"/>
@error('form.description')
<span class="text-red-500">{{ $message }}</span>
@enderror
</div>
<button
wire:click="update"
wire:loading.attr="disabled"
class="w-full btn-sm 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">
Speichern
</button>
</div>
</div>
</div>
use App\Models\ProjectProposal;
use App\Support\NostrAuth;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
<!-- Right column -->
<div class="flex-1 md:ml-8">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Information
</h2>
<p class="text-sm text-gray-800 dark:text-gray-100">
Bearbeite die Projektförderung und speichere deine Änderungen.
</p>
</div>
</div>
new
#[Layout('layouts.app')]
#[Title('Projektförderung bearbeiten')]
class extends Component {
public ProjectProposal $project;
public array $form = [
'name' => '',
'description' => '',
];
public bool $isAllowed = false;
public function mount(ProjectProposal $project): void
{
$this->project = $project;
if (NostrAuth::check()) {
$currentPubkey = NostrAuth::pubkey();
$currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $currentPubkey)->first();
if ($currentPleb && $currentPleb->id === $project->einundzwanzig_pleb_id) {
$this->isAllowed = true;
$this->form = [
'name' => $project->name,
'description' => $project->description,
];
}
}
}
public function update(): void
{
$this->validate([
'form.name' => 'required|string|max:255',
'form.description' => 'required|string',
]);
$this->project->update([
'name' => $this->form['name'],
'description' => $this->form['description'],
]);
$this->redirectRoute('association.projectSupport.item', $this->project);
}
};
?>
<div>
@if($isAllowed)
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div
class="flex flex-col md:flex-row items-center mb-6 space-y-4 md:space-y-0 md:space-x-4">
<div class="flex items-center justify-between w-full">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
Projektförderung bearbeiten
</h1>
</div>
</div>
@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">
Projektförderung
</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projektförderung zu bearbeiten.
<div class="md:flex">
<!-- Left column -->
<div class="w-full md:w-60 mb-4 md:mb-0">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Formular
</h2>
<div class="space-y-4">
<div wire:dirty>
<x-input label="Name" wire:model="form.name"/>
@error('form.name')
<span class="text-red-500">{{ $message }}</span>
@enderror
</div>
<div wire:dirty>
<x-textarea label="Beschreibung" wire:model="form.description"/>
@error('form.description')
<span class="text-red-500">{{ $message }}</span>
@enderror
</div>
<button
wire:click="update"
wire:loading.attr="disabled"
class="w-full btn-sm 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">
Speichern
</button>
</div>
</div>
</div>
<!-- Right column -->
<div class="flex-1 md:ml-8">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Information
</h2>
<p class="text-sm text-gray-800 dark:text-gray-100">
Bearbeite die Projektförderung und speichere deine Änderungen.
</p>
</div>
</div>
</div>
@endif
</div>
</x-layouts.app>
</div>
@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">
Projektförderung
</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projektförderung zu bearbeiten.
</p>
</div>
</div>
</div>
@endif
</div>

View File

@@ -97,14 +97,6 @@ new class extends Component {
$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')
]);
}
};
?>

View File

@@ -1,85 +1,107 @@
<x-layouts.app
:seo="new \RalphJSmit\Laravel\SEO\Support\SEOData(title: 'Projektförderung ' . $project->name, description: $project->description)"
>
<div>
@if($isAllowed)
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div
class="flex flex-col md:flex-row items-center mb-6 space-y-4 md:space-y-0 md:space-x-4">
<div class="flex items-center justify-between w-full">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
{{ $project->name }}
</h1>
<div>
@if($project->status === 'pending')
<x-badge info label="Pending"/>
@elseif($project->status === 'active')
<x-badge success label="Active"/>
@else
<x-badge neutral label="Archiviert"/>
@endif
</div>
</div>
</div>
<?php
<div class="md:flex">
<!-- Left column -->
<div class="w-full md:w-60 mb-4 md:mb-0">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Details
</h2>
<dl class="space-y-3">
<div>
<dt class="text-xs font-semibold text-gray-500 uppercase mb-1">Status</dt>
<dd class="text-sm text-gray-800 dark:text-gray-100">
@if($project->status === 'pending')
Ausstehend
@elseif($project->status === 'active')
Aktiv
@else
Archiviert
@endif
</dd>
</div>
<div>
<dt class="text-xs font-semibold text-gray-500 uppercase mb-1">Erstellt am</dt>
<dd class="text-sm text-gray-800 dark:text-gray-100">
{{ $project->created_at->format('d.m.Y') }}
</dd>
</div>
</dl>
</div>
</div>
use App\Models\ProjectProposal;
use App\Support\NostrAuth;
use Livewire\Component;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
<!-- Right column -->
<div class="flex-1 md:ml-8">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Beschreibung
</h2>
<p class="text-sm text-gray-800 dark:text-gray-100">
{{ $project->description ?? 'Keine Beschreibung' }}
</p>
</div>
new
#[Layout('layouts.app')]
#[Title('Projektförderung ')]
class extends Component {
public ProjectProposal $project;
public bool $isAllowed = false;
public function mount(ProjectProposal $project): void
{
$this->project = $project;
if (NostrAuth::check()) {
$this->isAllowed = true;
}
}
};
?>
<div>
@if($isAllowed)
<div class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div
class="flex flex-col md:flex-row items-center mb-6 space-y-4 md:space-y-0 md:space-x-4">
<div class="flex items-center justify-between w-full">
<h1 class="text-2xl md:text-3xl text-gray-800 dark:text-gray-100 font-bold">
{{ $project->name }}
</h1>
<div>
@if($project->status === 'pending')
<x-badge info label="Pending"/>
@elseif($project->status === 'active')
<x-badge success label="Active"/>
@else
<x-badge neutral label="Archiviert"/>
@endif
</div>
</div>
</div>
@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">
Projektförderung
</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projektförderung einzusehen.
<div class="md:flex">
<!-- Left column -->
<div class="w-full md:w-60 mb-4 md:mb-0">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Details
</h2>
<dl class="space-y-3">
<div>
<dt class="text-xs font-semibold text-gray-500 uppercase mb-1">Status</dt>
<dd class="text-sm text-gray-800 dark:text-gray-100">
@if($project->status === 'pending')
Ausstehend
@elseif($project->status === 'active')
Aktiv
@else
Archiviert
@endif
</dd>
</div>
<div>
<dt class="text-xs font-semibold text-gray-500 uppercase mb-1">Erstellt am</dt>
<dd class="text-sm text-gray-800 dark:text-gray-100">
{{ $project->created_at->format('d.m.Y') }}
</dd>
</div>
</dl>
</div>
</div>
<!-- Right column -->
<div class="flex-1 md:ml-8">
<div
class="bg-white dark:bg-gray-800 shadow-sm rounded-xl p-5">
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100 mb-4">
Beschreibung
</h2>
<p class="text-sm text-gray-800 dark:text-gray-100">
{{ $project->description ?? 'Keine Beschreibung' }}
</p>
</div>
</div>
</div>
@endif
</div>
</x-layouts.app>
</div>
@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">
Projektförderung
</h3>
<p class="mt-1 max-w">
Du bist nicht berechtigt, die Projektförderung einzusehen.
</p>
</div>
</div>
</div>
@endif
</div>