bitcoin event front end forms added

This commit is contained in:
HolgerHatGarKeineNode
2023-02-25 13:05:33 +01:00
parent 3f5881eff8
commit be7092c0a7
14 changed files with 533 additions and 42 deletions

View File

@@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Lecturer;
use App\Models\Venue;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
class VenueController extends Controller
{
/**
* Display a listing of the resource.
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
return Venue::query()
->with(['city:id,name,country_id', 'city.country:id,name,code'])
->select('id', 'name', 'city_id')
->orderBy('name')
->when(
$request->search,
fn(Builder $query) => $query
->where('name', 'ilike', "%{$request->search}%")
)
->when(
$request->exists('selected'),
fn(Builder $query) => $query->whereIn('id',
$request->input('selected', [])),
fn(Builder $query) => $query->limit(10)
)
->get()
->map(function (Venue $venue) {
$venue->flag = asset('vendor/blade-country-flags/4x3-'.$venue->city->country->code.'.svg');
return $venue;
});
}
/**
* Store a newly created resource in storage.
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
* @return \Illuminate\Http\Response
*/
public function show(Lecturer $lecturer)
{
//
}
/**
* Update the specified resource in storage.
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Lecturer $lecturer)
{
//
}
/**
* Remove the specified resource from storage.
* @return \Illuminate\Http\Response
*/
public function destroy(Lecturer $lecturer)
{
//
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace App\Http\Livewire\BitcoinEvent\Form;
use App\Models\BitcoinEvent;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\WithFileUploads;
use WireUi\Traits\Actions;
class BitcoinEventForm extends Component
{
use WithFileUploads;
use Actions;
public string $country;
public ?BitcoinEvent $bitcoinEvent = null;
public $image;
public ?string $fromUrl = '';
protected $queryString = [
'fromUrl' => [
'except' => null,
],
];
public function rules()
{
return [
'image' => [Rule::requiredIf(!$this->bitcoinEvent->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
'bitcoinEvent.venue_id' => 'required',
'bitcoinEvent.from' => 'required',
'bitcoinEvent.to' => 'required',
'bitcoinEvent.title' => 'required',
'bitcoinEvent.description' => 'required',
'bitcoinEvent.link' => 'required|url',
'bitcoinEvent.show_worldwide' => 'bool',
];
}
public function mount()
{
if (!$this->bitcoinEvent) {
$this->bitcoinEvent = new BitcoinEvent(
[
'description' => '',
'show_worldwide' => true,
]
);
} elseif (!auth()
->user()
->can('update', $this->bitcoinEvent)) {
abort(403);
}
if (!$this->fromUrl) {
$this->fromUrl = url()->previous();
}
}
public function submit()
{
$this->validate();
$this->bitcoinEvent->save();
if ($this->image) {
$this->bitcoinEvent->addMedia($this->image)
->toMediaCollection('logo');
}
return redirect($this->fromUrl);
}
public function render()
{
return view('livewire.bitcoin-event.form.bitcoin-event-form');
}
}

View File

@@ -35,7 +35,14 @@ class BitcoinEventTable extends DataTableComponent
]; ];
}) })
->setColumnSelectStatus(false) ->setColumnSelectStatus(false)
->setPerPage(10); ->setPerPage(10)
->setConfigurableAreas([
'toolbar-left-end' => [
'columns.bitcoin_events.areas.toolbar-left-end', [
'country' => $this->country,
],
],
]);
} }
public function filters(): array public function filters(): array

View File

@@ -0,0 +1,71 @@
<?php
namespace App\Http\Livewire\Venue\Form;
use App\Models\Venue;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\WithFileUploads;
use WireUi\Traits\Actions;
class VenueForm extends Component
{
use WithFileUploads;
use Actions;
public string $country;
public ?Venue $venue = null;
public $images;
public ?string $fromUrl = '';
protected $queryString = ['fromUrl' => ['except' => '']];
public function rules()
{
return [
'images.*' => [Rule::requiredIf(!$this->venue->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
'venue.city_id' => 'required',
'venue.name' => 'required',
'venue.street' => 'required',
];
}
public function mount()
{
if (!$this->venue) {
$this->venue = new Venue();
} elseif (!auth()
->user()
->can('update', $this->venue)) {
abort(403);
}
if (!$this->fromUrl) {
$this->fromUrl = url()->previous();
}
}
public function submit()
{
$this->validate();
$this->venue->save();
if (count($this->images) > 0) {
foreach ($this->images as $item) {
$this->venue->addMedia($item)
->toMediaCollection('images');
}
}
return redirect($this->fromUrl);
}
public function render()
{
return view('livewire.venue.form.venue-form');
}
}

View File

@@ -15,6 +15,15 @@ trait NostrTrait
{ {
public function publishOnNostr($model, $text): array public function publishOnNostr($model, $text): array
{ {
if (app()->environment('local')) {
return [
'success' => true,
'output' => 'local',
'exitCode' => 0,
'errorOutput' => ''
];
}
//noscl publish "Good morning!" //noscl publish "Good morning!"
$result = Process::timeout(60 * 5) $result = Process::timeout(60 * 5)
->run('noscl publish "'.$text.'"'); ->run('noscl publish "'.$text.'"');

View File

@@ -0,0 +1,6 @@
<div class="w-full mb-4 md:w-auto md:mb-0">
<x-button :href="route('bitcoinEvent.form', ['country' => $country, 'bitcoinEvent' => null])">
<i class="fa fa-thin fa-plus"></i>
{{ __('Register event') }}
</x-button>
</div>

View File

@@ -0,0 +1,129 @@
<div class="container p-4 mx-auto bg-21gray my-2">
<div class="pb-5 flex flex-row justify-between">
<h3 class="text-lg font-medium leading-6 text-gray-200">{{ __('Bitcoin Event') }}</h3>
<div class="flex flex-row space-x-2 items-center">
<div>
@if($bitcoinEvent->id)
<x-button negative wire:click="deleteMe">
<i class="fa fa-thin fa-trash"></i>
{{ __('Delete') }}
</x-button>
@endif
</div>
<div>
<x-button :href="$fromUrl">
<i class="fa fa-thin fa-arrow-left"></i>
{{ __('Back') }}
</x-button>
</div>
</div>
</div>
<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="__('Logo')">
<div class="py-4">
@if ($image)
<div class="text-gray-200">{{ __('Preview') }}:</div>
<img class="h-48 object-contain" src="{{ $image->temporaryUrl() }}">
@endif
@if ($bitcoinEvent->getFirstMediaUrl('logo'))
<div class="text-gray-200">{{ __('Current picture') }}:</div>
<img class="h-48 object-contain" src="{{ $bitcoinEvent->getFirstMediaUrl('logo') }}">
@endif
</div>
<input class="text-gray-200" type="file" wire:model="image">
@error('image') <span class="text-red-500">{{ $message }}</span> @enderror
</x-input.group>
<x-input.group :for="md5('venue_id')">
<x-slot name="label">
<div class="flex flex-row space-x-4 items-center">
<div>
{{ __('Venue') }}
</div>
<x-button xs href="{{ route('venue.form') }}">
<i class="fa fa-thin fa-plus"></i>
{{ __('Create venue') }}
</x-button>
</div>
</x-slot>
<x-select
autocomplete="off"
wire:model.debounce="bitcoinEvent.venue_id"
:placeholder="__('Venue')"
:async-data="[
'api' => route('api.venues.index'),
'method' => 'GET', // default is GET
]"
:template="[
'name' => 'user-option',
'config' => ['src' => 'flag']
]"
option-label="name"
option-value="id"
option-description="city.name"
/>
</x-input.group>
<x-input.group :for="md5('bitcoinEvent.from')" :label="__('Start')">
<x-datetime-picker
:clearable="false"
time-format="24"
timezone="UTC"
user-timezone="{{ config('app.user-timezone') }}"
autocomplete="off"
wire:model.debounce="bitcoinEvent.from"
display-format="DD-MM-YYYY HH:mm"
:placeholder="__('Start')"/>
</x-input.group>
<x-input.group :for="md5('bitcoinEvent.to')" :label="__('To')">
<x-datetime-picker
:clearable="false"
time-format="24"
timezone="UTC"
user-timezone="{{ config('app.user-timezone') }}"
autocomplete="off"
wire:model.debounce="bitcoinEvent.to"
display-format="DD-MM-YYYY HH:mm"
:placeholder="__('To')"/>
</x-input.group>
<x-input.group :for="md5('bitcoinEvent.title')" :label="__('Title')">
<x-input autocomplete="off" wire:model.debounce="bitcoinEvent.title"
:placeholder="__('Title')"/>
</x-input.group>
<x-input.group :for="md5('bitcoinEvent.description')" :label="__('Description')">
<div
class="text-amber-500 text-xs py-2">{{ __('For images in Markdown, please use eg. Imgur or another provider.') }}</div>
<x-input.simple-mde wire:model.defer="bitcoinEvent.description"/>
@error('bitcoinEvent.description') <span class="text-red-500 py-2">{{ $message }}</span> @enderror
</x-input.group>
<x-input.group :for="md5('bitcoinEvent.link')" :label="__('Link')">
<x-input autocomplete="off" wire:model.debounce="bitcoinEvent.link"
:placeholder="__('Link')"/>
</x-input.group>
<x-input.group :for="md5('bitcoinEvent.show_worldwide')" :label="__('Show worldwide')">
<x-toggle lg autocomplete="off" wire:model.debounce="bitcoinEvent.show_worldwide"
:placeholder="__('Show worldwide')"/>
<p class="text-xs py-2 text-gray-200">{{ __('If checked, the event will be shown everywhere.') }}</p>
</x-input.group>
<x-input.group :for="md5('action')" :label="__('Action')">
<x-button primary wire:click="submit">
<i class="fa fa-thin fa-save"></i>
{{ __('Save') }}
</x-button>
</x-input.group>
</div>
</div>
</form>
</div>

View File

@@ -23,12 +23,10 @@
{{ __('Author') }} {{ __('Author') }}
</div> </div>
<div x-data="{currentUrl: window.location.href}"> <div x-data="{currentUrl: window.location.href}">
<a x-bind:href="'/content-creator/form/?fromUrl='+currentUrl"> <x-button xs :href="route('contentCreator.form')">
<x-button xs>
<i class="fa fa-thin fa-plus"></i> <i class="fa fa-thin fa-plus"></i>
{{ __('Create new author') }} {{ __('Create new author') }}
</x-button> </x-button>
</a>
</div> </div>
</div> </div>
</x-slot> </x-slot>

View File

@@ -55,7 +55,7 @@
<div> <div>
{{ __('City/Area') }} {{ __('City/Area') }}
</div> </div>
<x-button xs :href="route('city.form')" target="_blank"> <x-button xs :href="route('city.form')">
<i class="fa fa-thin fa-plus"></i> <i class="fa fa-thin fa-plus"></i>
{{ __('New City') }} {{ __('New City') }}
</x-button> </x-button>

View File

@@ -0,0 +1,94 @@
<div class="container p-4 mx-auto bg-21gray my-2">
<div class="pb-5 flex flex-row justify-between">
<h3 class="text-lg font-medium leading-6 text-gray-200">{{ __('Venue') }}</h3>
<div class="flex flex-row space-x-2 items-center">
<div>
@if($venue->id)
<x-button negative wire:click="deleteMe">
<i class="fa fa-thin fa-trash"></i>
{{ __('Delete') }}
</x-button>
@endif
</div>
<div>
<x-button :href="$fromUrl">
<i class="fa fa-thin fa-arrow-left"></i>
{{ __('Back') }}
</x-button>
</div>
</div>
</div>
<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="__('Images')">
<div class="py-4">
@if ($images)
<div class="grid grid-cols-4 gap-1">
@foreach($images as $image)
<div>
<div class="text-gray-200">{{ __('Preview') }}:</div>
<img class="h-48 object-contain" src="{{ $image->temporaryUrl() }}">
</div>
@endforeach
</div>
@endif
{{--@if ($venue->getFirstMediaUrl('images'))
<div class="text-gray-200">{{ __('Current picture') }}:</div>
<img class="h-48 object-contain" src="{{ $venue->getFirstMediaUrl('logo') }}">
@endif--}}
</div>
<input class="text-gray-200" type="file" multiple wire:model="images">
</x-input.group>
<x-input.group :for="md5('city_id')">
<x-slot name="label">
<div class="flex flex-row space-x-4 items-center">
<div>
{{ __('City') }}
</div>
<x-button xs href="{{ route('city.form') }}">
<i class="fa fa-thin fa-plus"></i>
{{ __('New City') }}
</x-button>
</div>
</x-slot>
<x-select
:clearable="false"
autocomplete="off"
wire:model.debounce="venue.city_id"
:placeholder="__('City/Area')"
:async-data="[
'api' => route('api.cities.index'),
'method' => 'GET', // default is GET
]"
option-label="name"
option-value="id"
option-description="country.name"
/>
</x-input.group>
<x-input.group :for="md5('venue.name')" :label="__('Name')">
<x-input autocomplete="off" wire:model.debounce="venue.name"
:placeholder="__('Name')"/>
</x-input.group>
<x-input.group :for="md5('venue.street')" :label="__('Address')">
<x-input autocomplete="off" wire:model.debounce="venue.street"
:placeholder="__('Address')"/>
</x-input.group>
<x-input.group :for="md5('action')" :label="__('Action')">
<x-button primary wire:click="submit">
<i class="fa fa-thin fa-save"></i>
{{ __('Save') }}
</x-button>
</x-input.group>
</div>
</div>
</form>
</div>

View File

@@ -28,15 +28,6 @@
</div> </div>
@endif @endif
@if(str(request()->route()->getName())->contains('bitcoinEvent.'))
<div>
<x-button xs amber href="/nova/resources/bitcoin-events" target="_blank">
<i class="fa fa-thin fa-plus"></i>
{{ __('Register event') }}
</x-button>
</div>
@endif
<div> <div>
<x-button xs amber href="{{ route('profile.show') }}" <x-button xs amber href="{{ route('profile.show') }}"
:active="request()->routeIs('profile.show')"> :active="request()->routeIs('profile.show')">

View File

@@ -30,6 +30,7 @@ Route::middleware([])
Route::resource('meetup', \App\Http\Controllers\Api\MeetupController::class); Route::resource('meetup', \App\Http\Controllers\Api\MeetupController::class);
Route::resource('lecturers', \App\Http\Controllers\Api\LecturerController::class); Route::resource('lecturers', \App\Http\Controllers\Api\LecturerController::class);
Route::resource('cities', \App\Http\Controllers\Api\CityController::class); Route::resource('cities', \App\Http\Controllers\Api\CityController::class);
Route::resource('venues', \App\Http\Controllers\Api\VenueController::class);
Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class); Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class);
Route::get('meetups', function () { Route::get('meetups', function () {
return \App\Models\Meetup::query() return \App\Models\Meetup::query()

View File

@@ -1,7 +1,6 @@
<?php <?php
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Facades\Socialite;
Route::middleware([]) Route::middleware([])
@@ -9,7 +8,8 @@ Route::middleware([])
->name('welcome'); ->name('welcome');
Route::get('/img/{path}', \App\Http\Controllers\ImageController::class) Route::get('/img/{path}', \App\Http\Controllers\ImageController::class)
->where('path', '.*')->name('img'); ->where('path', '.*')
->name('img');
Route::get('auth/auth47', \App\Http\Livewire\Auth\Auth47Component::class) Route::get('auth/auth47', \App\Http\Livewire\Auth\Auth47Component::class)
->name('auth.auth47'); ->name('auth.auth47');
@@ -52,6 +52,32 @@ Route::middleware([
->name('form'); ->name('form');
}); });
/*
* Bitcoin Event
* */
Route::middleware([
'auth',
])
->as('bitcoinEvent.')
->prefix('/bitcoin-event')
->group(function () {
Route::get('/form/{bitcoinEvent?}', \App\Http\Livewire\BitcoinEvent\Form\BitcoinEventForm::class)
->name('form');
});
/*
* Venue
* */
Route::middleware([
'auth',
])
->as('venue.')
->prefix('/venue')
->group(function () {
Route::get('/form/{venue?}', \App\Http\Livewire\Venue\Form\VenueForm::class)
->name('form');
});
/* /*
* Cities * Cities
* */ * */