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)
|
->setColumnSelectStatus(false)
|
||||||
->setPerPage(10);
|
->setPerPage(10)
|
||||||
|
->setConfigurableAreas([
|
||||||
|
'toolbar-left-end' => [
|
||||||
|
'columns.meetup_events.areas.toolbar-left-end', [
|
||||||
|
'country' => $this->country,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function filters(): array
|
public function filters(): array
|
||||||
@@ -53,7 +60,7 @@ class MeetupEventTable extends DataTableComponent
|
|||||||
|
|
||||||
public function columns(): array
|
public function columns(): array
|
||||||
{
|
{
|
||||||
return [
|
$columns = [
|
||||||
Column::make(__('Meetup'), 'meetup.name')
|
Column::make(__('Meetup'), 'meetup.name')
|
||||||
->format(
|
->format(
|
||||||
fn($value, $row, Column $column) => view('columns.meetup_events.name')
|
fn($value, $row, Column $column) => view('columns.meetup_events.name')
|
||||||
@@ -72,12 +79,22 @@ class MeetupEventTable extends DataTableComponent
|
|||||||
)
|
)
|
||||||
->sortable()
|
->sortable()
|
||||||
->collapseOnMobile(),
|
->collapseOnMobile(),
|
||||||
Column::make(__('Link'), 'link')
|
Column::make(__('Link'))
|
||||||
->label(
|
->label(
|
||||||
fn($row, Column $column) => view('columns.meetup_events.link')
|
fn($row, Column $column) => view('columns.meetup_events.link')
|
||||||
->withRow($row)
|
->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
|
public function builder(): Builder
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Observers;
|
|||||||
|
|
||||||
use App\Models\MeetupEvent;
|
use App\Models\MeetupEvent;
|
||||||
use App\Traits\TwitterTrait;
|
use App\Traits\TwitterTrait;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class MeetupEventObserver
|
class MeetupEventObserver
|
||||||
{
|
{
|
||||||
@@ -18,6 +19,7 @@ class MeetupEventObserver
|
|||||||
*/
|
*/
|
||||||
public function created(MeetupEvent $meetupEvent)
|
public function created(MeetupEvent $meetupEvent)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
if (config('feeds.services.twitterAccountId')) {
|
if (config('feeds.services.twitterAccountId')) {
|
||||||
$this->setNewAccessToken(1);
|
$this->setNewAccessToken(1);
|
||||||
|
|
||||||
@@ -36,6 +38,9 @@ class MeetupEventObserver
|
|||||||
|
|
||||||
$this->postTweet($text);
|
$this->postTweet($text);
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ class Carbon extends CarbonImmutable
|
|||||||
->format('H:i');
|
->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
|
public function asDateTime(): string
|
||||||
{
|
{
|
||||||
$dt = $this->timezone(config('app.user-timezone'))->locale('de');
|
$dt = $this->timezone(config('app.user-timezone'))->locale('de');
|
||||||
|
|||||||
@@ -711,5 +711,12 @@
|
|||||||
"Unfortunately I cannot come": "Leider kann ich doch nicht kommen",
|
"Unfortunately I cannot come": "Leider kann ich doch nicht kommen",
|
||||||
"Link to participate": "Link zur Teilnahme",
|
"Link to participate": "Link zur Teilnahme",
|
||||||
"Copied!": "Kopiert!",
|
"Copied!": "Kopiert!",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "Zum Beispiel ein Link zu einer Location auf Google Maps oder ein Link zu einer Website. (nicht dein Telegram-Gruppen-Link)"
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "Zum Beispiel ein Link zu einer Location auf Google Maps oder ein Link zu einer Website. (nicht dein Telegram-Gruppen-Link)",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "Es gibt bereits einen Termin an diesem Datum. Bitte wähle ein anderes Datum oder lösche die bestehenden Termine.",
|
||||||
|
"Event saved successfully.": "Termin erfolgreich gespeichert.",
|
||||||
|
"no authorization": "keine Berechtigung",
|
||||||
|
"Recurring appointment": "Wiederkehrender Termin",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "Die Termine werden in der Datenbank als neue Einträge angelegt. Bitte sei vorsichtig mit dieser Funktion, sonst musst du alle Termine, ändern oder löschen, wenn du einen Fehler machst.",
|
||||||
|
"Number of repetitions": "Anzahl der Wiederholungen",
|
||||||
|
"Recurring appointments": "Wiederkehrende Termine"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -706,5 +706,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -706,5 +706,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -707,5 +707,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -707,5 +707,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -707,5 +707,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -707,5 +707,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -707,5 +707,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -707,5 +707,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -681,5 +681,12 @@
|
|||||||
"Unfortunately I cannot come": "",
|
"Unfortunately I cannot come": "",
|
||||||
"Link to participate": "",
|
"Link to participate": "",
|
||||||
"Copied!": "",
|
"Copied!": "",
|
||||||
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": ""
|
"For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)": "",
|
||||||
|
"There is already an event on this date. Please choose another date or delete the existing events.": "",
|
||||||
|
"Event saved successfully.": "",
|
||||||
|
"no authorization": "",
|
||||||
|
"Recurring appointment": "",
|
||||||
|
"The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.": "",
|
||||||
|
"Number of repetitions": "",
|
||||||
|
"Recurring appointments": ""
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="w-full mb-4 md:w-auto md:mb-0">
|
||||||
|
<x-button :href="route('meetup.event.form', ['country' => $country, 'meetupEvent' => null])">
|
||||||
|
<i class="fa fa-thin fa-plus"></i>
|
||||||
|
{{ __('Register Meetup date') }}
|
||||||
|
</x-button>
|
||||||
|
</div>
|
||||||
16
resources/views/columns/meetup_events/manage.blade.php
Normal file
16
resources/views/columns/meetup_events/manage.blade.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="flex flex-col space-y-1">
|
||||||
|
<div>
|
||||||
|
@if(auth()->user()->can('update', $row))
|
||||||
|
<x-button
|
||||||
|
primary
|
||||||
|
xs
|
||||||
|
:href="route('meetup.event.form', ['country' => $row->meetup->city->country, 'meetupEvent' => $row])"
|
||||||
|
>
|
||||||
|
<i class="fa fa-thin fa-edit mr-2"></i>
|
||||||
|
{{ __('Edit') }}
|
||||||
|
</x-button>
|
||||||
|
@else
|
||||||
|
<x-badge>{{ __('no authorization') }}</x-badge>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -5,5 +5,4 @@
|
|||||||
{{ $row->name }}
|
{{ $row->name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
13
resources/views/components/input/group.blade.php
Normal file
13
resources/views/components/input/group.blade.php
Normal 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>
|
||||||
105
resources/views/livewire/meetup/form/meetup-event-form.blade.php
Normal file
105
resources/views/livewire/meetup/form/meetup-event-form.blade.php
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<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">{{ __('Meetup Event') }}</h3>
|
||||||
|
<div>
|
||||||
|
<x-button :href="route('meetup.table.meetupEvent', ['country' => $country])">{{ __('Back') }}</x-button>
|
||||||
|
</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('meetup_id')" :label="__('Meetup')">
|
||||||
|
<x-select
|
||||||
|
autocomplete="off"
|
||||||
|
wire:model.debounce="meetupEvent.meetup_id"
|
||||||
|
:placeholder="__('Meetup')"
|
||||||
|
:async-data="[
|
||||||
|
'api' => route('api.meetup.index'),
|
||||||
|
'method' => 'GET', // default is GET
|
||||||
|
'params' => ['user_id' => auth()->id()], // default is []
|
||||||
|
]"
|
||||||
|
:template="[
|
||||||
|
'name' => 'user-option',
|
||||||
|
'config' => ['src' => 'profile_image']
|
||||||
|
]"
|
||||||
|
option-label="name"
|
||||||
|
option-value="id"
|
||||||
|
option-description="city.name"
|
||||||
|
/>
|
||||||
|
</x-input.group>
|
||||||
|
|
||||||
|
<x-input.group :for="md5('meetupEvent.start')" :label="__('Start')">
|
||||||
|
<x-datetime-picker
|
||||||
|
:clearable="false"
|
||||||
|
time-format="24"
|
||||||
|
timezone="UTC"
|
||||||
|
user-timezone="{{ config('app.user-timezone') }}"
|
||||||
|
autocomplete="off"
|
||||||
|
wire:model.debounce="meetupEvent.start"
|
||||||
|
display-format="DD-MM-YYYY HH:mm"
|
||||||
|
:placeholder="__('Start')"/>
|
||||||
|
</x-input.group>
|
||||||
|
|
||||||
|
@if(!$meetupEvent->id)
|
||||||
|
<x-input.group :for="md5('recurring')" :label="__('Recurring appointment')">
|
||||||
|
<x-toggle :label="__('Recurring appointment')" wire:model="recurring"/>
|
||||||
|
<p class="text-xs text-amber-400 py-2">{{ __('The recurring appointments are created in the database as new entries. Please be careful with this function, otherwise you will have to change or delete all the appointments you have created manually if you make an error.') }}</p>
|
||||||
|
</x-input.group>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($recurring)
|
||||||
|
<x-input.group :for="md5('repetitions')" :label="__('Number of repetitions')">
|
||||||
|
<x-input type="number" autocomplete="off" wire:model.debounce="repetitions"
|
||||||
|
:placeholder="__('Number of repetitions')"/>
|
||||||
|
</x-input.group>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-input.group :for="md5('meetupEvent.location')" :label="__('Location')">
|
||||||
|
<x-input autocomplete="off" wire:model.debounce="meetupEvent.location"
|
||||||
|
:placeholder="__('Location')"/>
|
||||||
|
</x-input.group>
|
||||||
|
|
||||||
|
<x-input.group :for="md5('meetupEvent.description')" :label="__('Description')">
|
||||||
|
<x-textarea autocomplete="off" wire:model.debounce="meetupEvent.description"
|
||||||
|
:placeholder="__('Description')"/>
|
||||||
|
</x-input.group>
|
||||||
|
|
||||||
|
<x-input.group :for="md5('meetupEvent.link')" :label="__('Link')">
|
||||||
|
<x-input type="url" autocomplete="off" wire:model.debounce="meetupEvent.link"
|
||||||
|
:placeholder="__('Link')"
|
||||||
|
:hint="__('For example, a link to a location on Google Maps or a link to a website. (not your Telegram group link)')"/>
|
||||||
|
</x-input.group>
|
||||||
|
|
||||||
|
<x-input.group :for="md5('grid')" :label="__('Recurring appointments')">
|
||||||
|
@if($meetupEvent->start && $recurring)
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
||||||
|
@for($i = 0; $i < $repetitions; $i++)
|
||||||
|
<x-datetime-picker wire:key="event_{{ $i }}"
|
||||||
|
:label="\App\Support\Carbon::parse($series[$i]['start'])->asDayNameAndMonthName()"
|
||||||
|
:clearable="false"
|
||||||
|
time-format="24"
|
||||||
|
timezone="UTC"
|
||||||
|
user-timezone="{{ config('app.user-timezone') }}"
|
||||||
|
autocomplete="off"
|
||||||
|
wire:model.debounce="series.{{ $i }}.start"
|
||||||
|
display-format="DD-MM-YYYY HH:mm"
|
||||||
|
:placeholder="__('Start')"/>
|
||||||
|
@endfor
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</x-input.group>
|
||||||
|
|
||||||
|
<x-input.group :for="md5('meetupEvent.link')" :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>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</x-button>
|
</x-button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<x-button xs amber href="/nova/resources/meetup-events" target="_blank">
|
<x-button xs amber :href="route('meetup.event.form', ['country' => $country ?? 'de'])">
|
||||||
<i class="fa fa-thin fa-plus"></i>
|
<i class="fa fa-thin fa-plus"></i>
|
||||||
{{ __('Register Meetup date') }}
|
{{ __('Register Meetup date') }}
|
||||||
</x-button>
|
</x-button>
|
||||||
|
|||||||
@@ -27,11 +27,7 @@ Route::middleware([])
|
|||||||
->as('api.')
|
->as('api.')
|
||||||
->group(function () {
|
->group(function () {
|
||||||
Route::resource('countries', \App\Http\Controllers\Api\CountryController::class);
|
Route::resource('countries', \App\Http\Controllers\Api\CountryController::class);
|
||||||
});
|
Route::resource('meetup', \App\Http\Controllers\Api\MeetupController::class);
|
||||||
|
|
||||||
Route::middleware([])
|
|
||||||
->as('api.')
|
|
||||||
->group(function () {
|
|
||||||
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()
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ Route::middleware([])
|
|||||||
Route::get('overview', \App\Http\Livewire\Meetup\MeetupTable::class)
|
Route::get('overview', \App\Http\Livewire\Meetup\MeetupTable::class)
|
||||||
->name('table.meetup');
|
->name('table.meetup');
|
||||||
|
|
||||||
|
Route::get('/meetup-events/form/{meetupEvent?}', \App\Http\Livewire\Meetup\Form\MeetupEventForm::class)
|
||||||
|
->name('event.form')
|
||||||
|
->middleware('needMeetup');
|
||||||
|
|
||||||
Route::get('/meetup-events/l/{meetupEvent}', \App\Http\Livewire\Meetup\LandingPageEvent::class)
|
Route::get('/meetup-events/l/{meetupEvent}', \App\Http\Livewire\Meetup\LandingPageEvent::class)
|
||||||
->name('event.landing');
|
->name('event.landing');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user