mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig-portal.git
synced 2025-12-11 06:46:47 +00:00
recurring meetup events
This commit is contained in:
96
app/Http/Controllers/Api/MeetupController.php
Normal file
96
app/Http/Controllers/Api/MeetupController.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\meetup;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MeetupController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$myMeetupIds = User::query()->find($request->input('user_id'))->meetups->pluck('id');
|
||||
|
||||
return Meetup::query()
|
||||
->select('id', 'name', 'city_id')
|
||||
->with([
|
||||
'city',
|
||||
])
|
||||
->whereIn('id', $myMeetupIds->toArray())
|
||||
->orderBy('name')
|
||||
->when(
|
||||
$request->search,
|
||||
fn(Builder $query) => $query
|
||||
->where('name', 'like', "%{$request->search}%")
|
||||
->orWhereHas('city',
|
||||
fn(Builder $query) => $query->where('cities.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 (Meetup $meetup) {
|
||||
$meetup->profile_image = $meetup->getFirstMediaUrl('logo', 'thumb');
|
||||
|
||||
return $meetup;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\meetup $meetup
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(meetup $meetup)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\meetup $meetup
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, meetup $meetup)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\meetup $meetup
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(meetup $meetup)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
128
app/Http/Livewire/Meetup/Form/MeetupEventForm.php
Normal file
128
app/Http/Livewire/Meetup/Form/MeetupEventForm.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup\Form;
|
||||
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Support\Carbon;
|
||||
use Livewire\Component;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class MeetupEventForm extends Component
|
||||
{
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
public ?MeetupEvent $meetupEvent = null;
|
||||
|
||||
public bool $recurring = false;
|
||||
public int $repetitions = 52;
|
||||
public array $series = [];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'meetupEvent.meetup_id' => 'required',
|
||||
'meetupEvent.start' => 'required',
|
||||
'meetupEvent.location' => 'string|nullable',
|
||||
'meetupEvent.description' => 'string|nullable',
|
||||
'meetupEvent.link' => 'string|url|nullable',
|
||||
|
||||
'series.*.start' => 'required',
|
||||
|
||||
'recurring' => 'bool',
|
||||
'repetitions' => 'numeric|min:1',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->meetupEvent) {
|
||||
$this->meetupEvent = new MeetupEvent(
|
||||
[
|
||||
'start' => now()
|
||||
->startOfDay()
|
||||
->addHours(17),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedMeetupEventStart($value)
|
||||
{
|
||||
if ($this->recurring) {
|
||||
$this->updatedRecurring(true);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedRecurring($value)
|
||||
{
|
||||
if ($value && $this->meetupEvent->start) {
|
||||
$this->series = [];
|
||||
for ($i = 0; $i < $this->repetitions; $i++) {
|
||||
$this->series[] = [
|
||||
'start' => $this->meetupEvent->start->addWeeks($i + 1)
|
||||
->toDateTimeString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedRepetitions($value)
|
||||
{
|
||||
if ($this->recurring) {
|
||||
$this->updatedRecurring(true);
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
if (!$this->meetupEvent->id) {
|
||||
$hasAppointmentsOnThisDate = MeetupEvent::query()
|
||||
->where('meetup_id', $this->meetupEvent->meetup_id)
|
||||
->where('start', '>', Carbon::parse($this->meetupEvent->start)
|
||||
->startOfDay())
|
||||
->where('start', '<', Carbon::parse($this->meetupEvent->start)
|
||||
->endOfDay())
|
||||
->exists();
|
||||
if ($hasAppointmentsOnThisDate) {
|
||||
$this->notification()
|
||||
->warning(__('There is already an event on this date. Please choose another date or delete the existing events.'));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->meetupEvent->save();
|
||||
|
||||
if (!$this->meetupEvent->id && $this->recurring) {
|
||||
foreach ($this->series as $event) {
|
||||
$hasAppointmentsOnThisDate = MeetupEvent::query()
|
||||
->where('meetup_id', $this->meetupEvent->meetup_id)
|
||||
->where('start', '>', Carbon::parse($event['start'])
|
||||
->startOfDay())
|
||||
->where('start', '<', Carbon::parse($event['start'])
|
||||
->endOfDay())
|
||||
->exists();
|
||||
|
||||
if ($hasAppointmentsOnThisDate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->meetupEvent->replicate()
|
||||
->fill($event)
|
||||
->saveQuietly();
|
||||
}
|
||||
}
|
||||
|
||||
$this->notification()
|
||||
->success(__('Event saved successfully.'));
|
||||
|
||||
return to_route('meetup.table.meetupEvent', ['country' => $this->country]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.form.meetup-event-form');
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,14 @@ class MeetupEventTable extends DataTableComponent
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10);
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.meetup_events.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
@@ -53,7 +60,7 @@ class MeetupEventTable extends DataTableComponent
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
$columns = [
|
||||
Column::make(__('Meetup'), 'meetup.name')
|
||||
->format(
|
||||
fn($value, $row, Column $column) => view('columns.meetup_events.name')
|
||||
@@ -72,12 +79,22 @@ class MeetupEventTable extends DataTableComponent
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Link'), 'link')
|
||||
Column::make(__('Link'))
|
||||
->label(
|
||||
fn($row, Column $column) => view('columns.meetup_events.link')
|
||||
->withRow($row)
|
||||
),
|
||||
];
|
||||
|
||||
$adminColumns = auth()->check() ? [
|
||||
Column::make(__('Actions'))
|
||||
->label(
|
||||
fn($row, Column $column) => view('columns.meetup_events.manage')
|
||||
->withRow($row)
|
||||
),
|
||||
] : [];
|
||||
|
||||
return array_merge($columns, $adminColumns);
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Observers;
|
||||
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Traits\TwitterTrait;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class MeetupEventObserver
|
||||
{
|
||||
@@ -18,23 +19,27 @@ class MeetupEventObserver
|
||||
*/
|
||||
public function created(MeetupEvent $meetupEvent)
|
||||
{
|
||||
if (config('feeds.services.twitterAccountId')) {
|
||||
$this->setNewAccessToken(1);
|
||||
try {
|
||||
if (config('feeds.services.twitterAccountId')) {
|
||||
$this->setNewAccessToken(1);
|
||||
|
||||
$meetupName = $meetupEvent->meetup->name;
|
||||
if ($meetupEvent->meetup->twitter_username) {
|
||||
$meetupName .= ' @'.$meetupEvent->meetup->twitter_username;
|
||||
$meetupName = $meetupEvent->meetup->name;
|
||||
if ($meetupEvent->meetup->twitter_username) {
|
||||
$meetupName .= ' @'.$meetupEvent->meetup->twitter_username;
|
||||
}
|
||||
|
||||
$text = sprintf("%s hat einen neuen Termin eingestellt:\n\n%s\n\n%s\n\n%s\n\n#Bitcoin #Meetup #Einundzwanzig #gesundesgeld",
|
||||
$meetupName,
|
||||
$meetupEvent->start->asDateTime(),
|
||||
$meetupEvent->location,
|
||||
url()->route('meetup.event.landing',
|
||||
['country' => 'de', 'meetup' => $meetupEvent->id]),
|
||||
);
|
||||
|
||||
$this->postTweet($text);
|
||||
}
|
||||
|
||||
$text = sprintf("%s hat einen neuen Termin eingestellt:\n\n%s\n\n%s\n\n%s\n\n#Bitcoin #Meetup #Einundzwanzig #gesundesgeld",
|
||||
$meetupName,
|
||||
$meetupEvent->start->asDateTime(),
|
||||
$meetupEvent->location,
|
||||
url()->route('meetup.event.landing',
|
||||
['country' => 'de', 'meetup' => $meetupEvent->id]),
|
||||
);
|
||||
|
||||
$this->postTweet($text);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,17 @@ class Carbon extends CarbonImmutable
|
||||
->format('H:i');
|
||||
}
|
||||
|
||||
public function asDayNameAndMonthName(): string
|
||||
{
|
||||
$dt = $this->timezone(config('app.user-timezone'))->locale('de');
|
||||
return sprintf("%s, %s. week of %s [%s]",
|
||||
$dt->dayName,
|
||||
$dt->weekNumberInMonth,
|
||||
$dt->monthName,
|
||||
$dt->timezoneAbbreviatedName
|
||||
);
|
||||
}
|
||||
|
||||
public function asDateTime(): string
|
||||
{
|
||||
$dt = $this->timezone(config('app.user-timezone'))->locale('de');
|
||||
|
||||
Reference in New Issue
Block a user