From 351c9047a9563b30539e9208ae2537defaf11c16 Mon Sep 17 00:00:00 2001 From: Benjamin Takats Date: Wed, 7 Dec 2022 18:16:07 +0100 Subject: [PATCH] proximity search for book cases --- .../Commands/OpenBooks/SyncOpenBooks.php | 4 +- .../Livewire/Frontend/CommentBookCase.php | 39 +++-- app/Http/Livewire/Tables/BookCaseTable.php | 76 ++++++--- app/Http/Livewire/Tables/CityTable.php | 18 ++ app/Models/BookCase.php | 42 ++++- ...2_12_06_222651_create_book_cases_table.php | 8 +- lang/de.json | 2 +- .../book_cases/oranged-pilled.blade.php | 8 +- .../views/columns/cities/action.blade.php | 15 +- resources/views/layouts/app.blade.php | 1 + resources/views/layouts/guest.blade.php | 1 + .../frontend/comment-book-case.blade.php | 159 +++++++++++++++++- .../frontend/search-book-case.blade.php | 48 +----- .../modals/book_cases/orange_pill.blade.php | 25 ++- 14 files changed, 331 insertions(+), 115 deletions(-) diff --git a/app/Console/Commands/OpenBooks/SyncOpenBooks.php b/app/Console/Commands/OpenBooks/SyncOpenBooks.php index 225bff59..38142d47 100644 --- a/app/Console/Commands/OpenBooks/SyncOpenBooks.php +++ b/app/Console/Commands/OpenBooks/SyncOpenBooks.php @@ -35,8 +35,8 @@ class SyncOpenBooks extends Command ], [ 'title' => $case['title'], - 'lat' => (float)$case['lat'], - 'lon' => (float)$case['lon'], + 'latitude' => (float)$case['lat'], + 'longitude' => (float)$case['lon'], 'address' => $case['address'], 'type' => $case['type'], 'open' => $case['open'], diff --git a/app/Http/Livewire/Frontend/CommentBookCase.php b/app/Http/Livewire/Frontend/CommentBookCase.php index 004fe365..f56341f3 100644 --- a/app/Http/Livewire/Frontend/CommentBookCase.php +++ b/app/Http/Livewire/Frontend/CommentBookCase.php @@ -4,9 +4,14 @@ namespace App\Http\Livewire\Frontend; use App\Models\BookCase; use Livewire\Component; +use Livewire\WithFileUploads; class CommentBookCase extends Component { + use WithFileUploads; + + public $photo; + public string $c = 'de'; public BookCase $bookCase; @@ -16,28 +21,26 @@ class CommentBookCase extends Component return view('livewire.frontend.comment-book-case'); } + public function save() + { + $this->validate([ + 'photo' => 'image|max:4096', // 4MB Max + ]); + + $this->bookCase + ->addMedia($this->photo) + ->toMediaCollection('images'); + + return to_route('comment.bookcase', ['bookCase' => $this->bookCase->id]); + } + protected function url_to_absolute($url) { - // Determine request protocol - $request_protocol = $request_protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); - // If dealing with a Protocol Relative URL - if (stripos($url, '//') === 0) { + if (str($url)->contains('http')) { return $url; } - // If dealing with a Root-Relative URL - if (stripos($url, '/') === 0) { - return $request_protocol.'://'.$_SERVER['HTTP_HOST'].$url; + if (!str($url)->contains('http')) { + return str($url)->prepend('https://'); } - // If dealing with an Absolute URL, just return it as-is - if (stripos($url, 'http') === 0) { - return $url; - } - // If dealing with a relative URL, - // and attempt to handle double dot notation ".." - do { - $url = preg_replace('/[^\/]+\/\.\.\//', '', $url, 1, $count); - } while ($count); - // Return the absolute version of a Relative URL - return $request_protocol.'://'.$_SERVER['HTTP_HOST'].'/'.$url; } } diff --git a/app/Http/Livewire/Tables/BookCaseTable.php b/app/Http/Livewire/Tables/BookCaseTable.php index 7d3bf84e..00eb53a0 100644 --- a/app/Http/Livewire/Tables/BookCaseTable.php +++ b/app/Http/Livewire/Tables/BookCaseTable.php @@ -3,16 +3,23 @@ namespace App\Http\Livewire\Tables; use App\Models\BookCase; +use App\Models\OrangePill; +use Illuminate\Database\Eloquent\Builder; use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\Views\Column; +use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter; +use WireUi\Traits\Actions; class BookCaseTable extends DataTableComponent { + use Actions; + public bool $viewingModal = false; public $currentModal; public array $orangepill = [ - 'amount' => 1, - 'date' => null, + 'amount' => 1, + 'date' => null, + 'comment' => '', ]; protected $model = BookCase::class; @@ -37,12 +44,27 @@ class BookCaseTable extends DataTableComponent ->setPerPage(50); } + + public function filters(): array + { + return [ + TextFilter::make('By IDs', 'byids') + ->filter(function (Builder $builder, string $value) { + $builder->whereIn('id', str($value)->explode(',')); + }), + ]; + } + public function columns(): array { return [ Column::make("Name", "title") ->sortable() - ->searchable(), + ->searchable( + function (Builder $query, $searchTerm) { + $query->where('title', 'ilike', '%'.$searchTerm.'%'); + } + ), Column::make("Adresse", "address") ->sortable() ->searchable(), @@ -61,27 +83,20 @@ class BookCaseTable extends DataTableComponent private function url_to_absolute($url) { - // Determine request protocol - $request_protocol = $request_protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); - // If dealing with a Protocol Relative URL - if (stripos($url, '//') === 0) { + if (str($url)->contains('http')) { return $url; } - // If dealing with a Root-Relative URL - if (stripos($url, '/') === 0) { - return $request_protocol.'://'.$_SERVER['HTTP_HOST'].$url; + if (!str($url)->contains('http')) { + return str($url)->prepend('https://'); } - // If dealing with an Absolute URL, just return it as-is - if (stripos($url, 'http') === 0) { - return $url; - } - // If dealing with a relative URL, - // and attempt to handle double dot notation ".." - do { - $url = preg_replace('/[^\/]+\/\.\.\//', '', $url, 1, $count); - } while ($count); - // Return the absolute version of a Relative URL - return $request_protocol.'://'.$_SERVER['HTTP_HOST'].'/'.$url; + } + + public function builder(): Builder + { + return BookCase::query() + ->withCount([ + 'orangePills', + ]); } public function viewHistoryModal($modelId): void @@ -90,6 +105,25 @@ class BookCaseTable extends DataTableComponent $this->currentModal = BookCase::findOrFail($modelId); } + public function submit(): void + { + $this->validate([ + 'orangepill.amount' => 'required|numeric', + 'orangepill.date' => 'required|date', + ]); + $orangePill = OrangePill::create([ + 'user_id' => auth()->id(), + 'book_case_id' => $this->currentModal->id, + 'amount' => $this->orangepill['amount'], + 'date' => $this->orangepill['date'], + ]); + if ($this->orangepill['comment']) { + $this->currentModal->comment($this->orangepill['comment']); + } + $this->resetModal(); + $this->emit('refreshDatatable'); + } + public function resetModal(): void { $this->reset('viewingModal', 'currentModal'); diff --git a/app/Http/Livewire/Tables/CityTable.php b/app/Http/Livewire/Tables/CityTable.php index e5658b1f..f9bdaa58 100644 --- a/app/Http/Livewire/Tables/CityTable.php +++ b/app/Http/Livewire/Tables/CityTable.php @@ -2,6 +2,7 @@ namespace App\Http\Livewire\Tables; +use App\Models\BookCase; use App\Models\City; use Illuminate\Database\Eloquent\Builder; use Rappasoft\LaravelLivewireTables\DataTableComponent; @@ -87,4 +88,21 @@ class CityTable extends DataTableComponent ] ]); } + + public function proximitySearchForBookCases($id) + { + $city = City::query() + ->find($id); + $query = BookCase::radius($city->latitude, $city->longitude, 5); + return to_route('search.bookcases', [ + '#table', + 'country' => $this->country, + 'table' => [ + 'filters' => [ + 'byids' => $query->pluck('id') + ->implode(',') + ], + ] + ]); + } } diff --git a/app/Models/BookCase.php b/app/Models/BookCase.php index e89591ee..3d1430f5 100644 --- a/app/Models/BookCase.php +++ b/app/Models/BookCase.php @@ -2,35 +2,63 @@ namespace App\Models; +use Akuechler\Geoly; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; use Spatie\Comments\Models\Concerns\HasComments; +use Spatie\Image\Manipulations; +use Spatie\MediaLibrary\HasMedia; +use Spatie\MediaLibrary\InteractsWithMedia; +use Spatie\MediaLibrary\MediaCollections\Models\Media; -class BookCase extends Model +class BookCase extends Model implements HasMedia { use HasFactory; use HasComments; + use InteractsWithMedia; + use Geoly; /** * The attributes that aren't mass assignable. - * * @var array */ protected $guarded = []; /** * The attributes that should be cast to native types. - * * @var array */ protected $casts = [ - 'id' => 'integer', - 'lat' => 'double', - 'lon' => 'array', - 'digital' => 'boolean', + 'id' => 'integer', + 'lat' => 'double', + 'lon' => 'array', + 'digital' => 'boolean', 'deactivated' => 'boolean', ]; + public function registerMediaConversions(Media $media = null): void + { + $this + ->addMediaConversion('preview') + ->fit(Manipulations::FIT_CROP, 300, 300) + ->nonQueued(); + $this->addMediaConversion('thumb') + ->fit(Manipulations::FIT_CROP, 130, 130) + ->width(130) + ->height(130); + } + + public function registerMediaCollections(): void + { + $this->addMediaCollection('images'); + } + + public function orangePills(): HasMany + { + return $this->hasMany(OrangePill::class); + } + /* * This string will be used in notifications on what a new comment * was made. diff --git a/database/migrations/2022_12_06_222651_create_book_cases_table.php b/database/migrations/2022_12_06_222651_create_book_cases_table.php index 6b72d9b1..b43a0cae 100644 --- a/database/migrations/2022_12_06_222651_create_book_cases_table.php +++ b/database/migrations/2022_12_06_222651_create_book_cases_table.php @@ -14,13 +14,9 @@ class CreateBookCasesTable extends Migration { Schema::create('book_cases', function (Blueprint $table) { $table->id(); - $table->boolean('orange_pilled') - ->default(false); - $table->unsignedInteger('orange_pilled_amount') - ->default(0); $table->string('title'); - $table->double('lat'); - $table->double('lon'); + $table->double('latitude'); + $table->double('longitude'); $table->text('address') ->nullable(); $table->string('type'); diff --git a/lang/de.json b/lang/de.json index dea854bd..97405972 100644 --- a/lang/de.json +++ b/lang/de.json @@ -1,5 +1,5 @@ { - "Orange Pill Book Case": "Bücher-Schrank wurde orange pilled.", + "Orange Pill Book Case": "Wie viele Bitcoin-Bücher hast du hinzu gefügt?", "Book": "Buch", "Article": "Artikel", "Markdown Article": "Interner Artikel", diff --git a/resources/views/columns/book_cases/oranged-pilled.blade.php b/resources/views/columns/book_cases/oranged-pilled.blade.php index ef82e0fd..baddf64b 100644 --- a/resources/views/columns/book_cases/oranged-pilled.blade.php +++ b/resources/views/columns/book_cases/oranged-pilled.blade.php @@ -1,14 +1,14 @@
@auth - @if($row->orange_pilled) + @if($row->orange_pills_count > 0) @endif - @if(!$row->orange_pilled) + @if($row->orange_pills_count < 1) @endif
- 💊 Orange Pill Now - Kommentare + 💊 Orange Pill Now + Details
@else
diff --git a/resources/views/columns/cities/action.blade.php b/resources/views/columns/cities/action.blade.php index 89101821..4a15945d 100644 --- a/resources/views/columns/cities/action.blade.php +++ b/resources/views/columns/cities/action.blade.php @@ -1 +1,14 @@ -Umkreis-Suche {{ $row->name }} (100km) +
+
+ + + Umkreis-Suche Kurs-Termin {{ $row->name }}(100km) + +
+
+ + + Umkreis-Suche Bücher-Schrank {{ $row->name }} (5km) + +
+
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 839a22a3..4a645df2 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -9,6 +9,7 @@ @googlefonts + @mapscripts diff --git a/resources/views/layouts/guest.blade.php b/resources/views/layouts/guest.blade.php index 2c2c44d3..fc8e9060 100644 --- a/resources/views/layouts/guest.blade.php +++ b/resources/views/layouts/guest.blade.php @@ -9,6 +9,7 @@ @googlefonts + @vite(['resources/css/app.css', 'resources/js/app.js']) diff --git a/resources/views/livewire/frontend/comment-book-case.blade.php b/resources/views/livewire/frontend/comment-book-case.blade.php index 006075c1..97289b4c 100644 --- a/resources/views/livewire/frontend/comment-book-case.blade.php +++ b/resources/views/livewire/frontend/comment-book-case.blade.php @@ -74,12 +74,12 @@
+ class="relative flex items-center space-x-3 rounded-lg border border-gray-300 bg-white px-6 py-5 shadow-sm"> {{--
--}}
-
+

Name

{{ $bookCase->title }}

Link

@@ -89,20 +89,165 @@

Adresse

{{ $bookCase->address }}

+

Art

+

{{ $bookCase->type }}

+

Geöffnet

+

{{ $bookCase->open }}

+

Kontakt

+

{{ $bookCase->contact }}

+

Information

+

{{ $bookCase->comment }}

+ +

Neues Foto hochladen

+ +
+
+ + @error('photo') {{ $message }} @enderror + Hochladen +
+
+ + @if($bookCase->getMedia('images')->count() > 0) +
+
+ + + + + + + +
    + + @foreach($bookCase->getMedia('images') as $image) +
  • + + placeholder image + + + +
  • + @endforeach + +
+ + + +
+
+ @endif
-
+
@map([ - 'lat' => $bookCase->lat, - 'lng' => $bookCase->lon, + 'lat' => $bookCase->latitude, + 'lng' => $bookCase->longitude, 'zoom' => 24, 'markers' => [ [ 'title' => $bookCase->title, - 'lat' => $bookCase->lat, - 'lng' => $bookCase->lon, + 'lat' => $bookCase->latitude, + 'lng' => $bookCase->longitude, 'url' => 'https://gonoware.com', 'icon' => asset('img/btc-logo-6219386_1280.png'), 'icon_size' => [42, 42], diff --git a/resources/views/livewire/frontend/search-book-case.blade.php b/resources/views/livewire/frontend/search-book-case.blade.php index 436fafee..44aff99e 100644 --- a/resources/views/livewire/frontend/search-book-case.blade.php +++ b/resources/views/livewire/frontend/search-book-case.blade.php @@ -1,15 +1,4 @@
- - {{-- HEADER --}}
@@ -58,7 +47,7 @@
@endauth
-
+
@@ -75,41 +64,6 @@

{{-- TEXT --}}

-
diff --git a/resources/views/modals/book_cases/orange_pill.blade.php b/resources/views/modals/book_cases/orange_pill.blade.php index e1d89d5c..50d6d198 100644 --- a/resources/views/modals/book_cases/orange_pill.blade.php +++ b/resources/views/modals/book_cases/orange_pill.blade.php @@ -6,7 +6,27 @@ -
+
+ +
+
+

Bisher waren hier

+
+
    + @foreach($currentModal?->orangePills ?? [] as $orangePill) +
  • + +
    +

    + {{ $orangePill->user->name }} hat am {{ $orangePill->date->asDateTime() }} {{ $orangePill->amount }} Bitcoin-Bücher hinzugefügt +

    +
    +
  • + @endforeach + +
+
+
+ @lang('Close') + + 💊 @lang('Orange Pill Now')