Es gibt nun task collections und vordefinierte tasks für alle. Onboarding verfeinert und webseite-carousel gefixt (logging später entfernen!)
295 lines
12 KiB
PHP
295 lines
12 KiB
PHP
<?php
|
||
|
||
namespace Database\Seeders;
|
||
|
||
use App\Models\Emotion;
|
||
use App\Models\EventType;
|
||
use App\Models\Task;
|
||
use App\Models\TaskCollection;
|
||
use Illuminate\Database\Seeder;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
class TaskCollectionsSeeder extends Seeder
|
||
{
|
||
public function run(): void
|
||
{
|
||
$collections = [
|
||
[
|
||
'slug' => 'wedding-classics',
|
||
'event_type' => [
|
||
'slug' => 'wedding',
|
||
'name' => [
|
||
'de' => 'Hochzeit',
|
||
'en' => 'Wedding',
|
||
],
|
||
'icon' => 'lucide-heart',
|
||
],
|
||
'name' => [
|
||
'de' => 'Hochzeitsklassiker',
|
||
'en' => 'Wedding Classics',
|
||
],
|
||
'description' => [
|
||
'de' => 'Kuratierte Aufgaben rund um Trauung, Emotionen und besondere Momente.',
|
||
'en' => 'Curated prompts for vows, emotions, and memorable wedding highlights.',
|
||
],
|
||
'is_default' => true,
|
||
'position' => 10,
|
||
'tasks' => [
|
||
[
|
||
'slug' => 'wedding-first-look',
|
||
'title' => [
|
||
'de' => 'Erster Blick des Brautpaares festhalten',
|
||
'en' => 'Capture the couple’s first look',
|
||
],
|
||
'description' => [
|
||
'de' => 'Halte den Moment fest, in dem sich Braut und Bräutigam zum ersten Mal sehen.',
|
||
'en' => 'Capture the moment when the bride and groom see each other for the first time.',
|
||
],
|
||
'example' => [
|
||
'de' => 'Fotografiere die Reaktionen aus verschiedenen Blickwinkeln.',
|
||
'en' => 'Photograph their reactions from different angles.',
|
||
],
|
||
'emotion' => [
|
||
'name' => [
|
||
'de' => 'Romantik',
|
||
'en' => 'Romance',
|
||
],
|
||
'icon' => 'lucide-heart',
|
||
'color' => '#ec4899',
|
||
'sort_order' => 10,
|
||
],
|
||
'difficulty' => 'easy',
|
||
'sort_order' => 10,
|
||
],
|
||
[
|
||
'slug' => 'wedding-family-hug',
|
||
'title' => [
|
||
'de' => 'Familienumarmung organisieren',
|
||
'en' => 'Organise a family group hug',
|
||
],
|
||
'description' => [
|
||
'de' => 'Bitte die wichtigsten Menschen, das Paar gleichzeitig zu umarmen.',
|
||
'en' => 'Ask the closest friends and family to hug the couple at the same time.',
|
||
],
|
||
'example' => [
|
||
'de' => 'Kombiniere die Umarmung mit einem Toast.',
|
||
'en' => 'Combine the hug with a heartfelt toast.',
|
||
],
|
||
'emotion' => [
|
||
'name' => [
|
||
'de' => 'Freude',
|
||
'en' => 'Joy',
|
||
],
|
||
'icon' => 'lucide-smile',
|
||
'color' => '#f59e0b',
|
||
'sort_order' => 20,
|
||
],
|
||
'difficulty' => 'medium',
|
||
'sort_order' => 20,
|
||
],
|
||
[
|
||
'slug' => 'wedding-midnight-sparkler',
|
||
'title' => [
|
||
'de' => 'Mitternachtsfunkeln mit Wunderkerzen',
|
||
'en' => 'Midnight sparkler moment',
|
||
],
|
||
'description' => [
|
||
'de' => 'Verteile Wunderkerzen und schafft ein leuchtendes Spalier für das Paar.',
|
||
'en' => 'Hand out sparklers and form a glowing aisle for the couple.',
|
||
],
|
||
'example' => [
|
||
'de' => 'Koordiniere die Musik und kündige den Countdown an.',
|
||
'en' => 'Coordinate music and announce a countdown.',
|
||
],
|
||
'emotion' => [
|
||
'name' => [
|
||
'de' => 'Ekstase',
|
||
'en' => 'Euphoria',
|
||
],
|
||
'icon' => 'lucide-stars',
|
||
'color' => '#6366f1',
|
||
'sort_order' => 30,
|
||
],
|
||
'difficulty' => 'medium',
|
||
'sort_order' => 30,
|
||
],
|
||
],
|
||
],
|
||
[
|
||
'slug' => 'birthday-celebration',
|
||
'event_type' => [
|
||
'slug' => 'birthday',
|
||
'name' => [
|
||
'de' => 'Geburtstag',
|
||
'en' => 'Birthday',
|
||
],
|
||
'icon' => 'lucide-cake',
|
||
],
|
||
'name' => [
|
||
'de' => 'Geburtstags-Highlights',
|
||
'en' => 'Birthday Highlights',
|
||
],
|
||
'description' => [
|
||
'de' => 'Aufgaben für Überraschungen, Gratulationen und gemeinsames Feiern.',
|
||
'en' => 'Prompts covering surprises, wishes, and shared celebrations.',
|
||
],
|
||
'is_default' => false,
|
||
'position' => 20,
|
||
'tasks' => [
|
||
[
|
||
'slug' => 'birthday-surprise-wall',
|
||
'title' => [
|
||
'de' => 'Überraschungswand mit Polaroids gestalten',
|
||
'en' => 'Create a surprise wall filled with instant photos',
|
||
],
|
||
'description' => [
|
||
'de' => 'Sammle Schnappschüsse der Gäste und befestige sie als Fotowand.',
|
||
'en' => 'Collect snapshots from guests and mount them on a photo wall.',
|
||
],
|
||
'example' => [
|
||
'de' => 'Schreibe zu jedem Bild einen kurzen Gruß.',
|
||
'en' => 'Add a short message to each picture.',
|
||
],
|
||
'emotion' => [
|
||
'name' => [
|
||
'de' => 'Nostalgie',
|
||
'en' => 'Nostalgia',
|
||
],
|
||
'icon' => 'lucide-images',
|
||
'color' => '#f97316',
|
||
'sort_order' => 40,
|
||
],
|
||
'difficulty' => 'easy',
|
||
'sort_order' => 10,
|
||
],
|
||
[
|
||
'slug' => 'birthday-toast-circle',
|
||
'title' => [
|
||
'de' => 'Gratulationskreis mit kurzen Toasts',
|
||
'en' => 'Circle of toasts',
|
||
],
|
||
'description' => [
|
||
'de' => 'Bildet einen Kreis und bittet jede Person um einen 10-Sekunden-Toast.',
|
||
'en' => 'Form a circle and ask everyone for a 10-second toast.',
|
||
],
|
||
'example' => [
|
||
'de' => 'Nimm die Reaktionen als Video auf.',
|
||
'en' => 'Record the reactions on video.',
|
||
],
|
||
'emotion' => [
|
||
'name' => [
|
||
'de' => 'Dankbarkeit',
|
||
'en' => 'Gratitude',
|
||
],
|
||
'icon' => 'lucide-hands',
|
||
'color' => '#22c55e',
|
||
'sort_order' => 50,
|
||
],
|
||
'difficulty' => 'easy',
|
||
'sort_order' => 20,
|
||
],
|
||
],
|
||
],
|
||
];
|
||
|
||
DB::transaction(function () use ($collections) {
|
||
foreach ($collections as $definition) {
|
||
$eventType = $this->ensureEventType($definition['event_type']);
|
||
|
||
$collection = TaskCollection::updateOrCreate(
|
||
['slug' => $definition['slug']],
|
||
[
|
||
'tenant_id' => null,
|
||
'event_type_id' => $eventType->id,
|
||
'name_translations' => $definition['name'],
|
||
'description_translations' => $definition['description'],
|
||
'is_default' => $definition['is_default'] ?? false,
|
||
'position' => $definition['position'] ?? 0,
|
||
]
|
||
);
|
||
|
||
$syncPayload = [];
|
||
|
||
foreach ($definition['tasks'] as $taskDefinition) {
|
||
$emotion = $this->ensureEmotion($taskDefinition['emotion'] ?? [], $eventType->id);
|
||
|
||
$task = Task::updateOrCreate(
|
||
['slug' => $taskDefinition['slug']],
|
||
[
|
||
'tenant_id' => null,
|
||
'event_type_id' => $eventType->id,
|
||
'collection_id' => $collection->id,
|
||
'emotion_id' => $emotion?->id,
|
||
'title' => $taskDefinition['title'],
|
||
'description' => $taskDefinition['description'] ?? null,
|
||
'example_text' => $taskDefinition['example'] ?? null,
|
||
'difficulty' => $taskDefinition['difficulty'] ?? 'easy',
|
||
'priority' => 'medium',
|
||
'sort_order' => $taskDefinition['sort_order'] ?? 0,
|
||
'is_active' => true,
|
||
'is_completed' => false,
|
||
]
|
||
);
|
||
|
||
$syncPayload[$task->id] = ['sort_order' => $taskDefinition['sort_order'] ?? 0];
|
||
}
|
||
|
||
if (! empty($syncPayload)) {
|
||
$collection->tasks()->sync($syncPayload);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
protected function ensureEventType(array $definition): EventType
|
||
{
|
||
$payload = [
|
||
'name' => $definition['name'],
|
||
'icon' => $definition['icon'] ?? null,
|
||
];
|
||
|
||
return EventType::updateOrCreate(
|
||
['slug' => $definition['slug']],
|
||
$payload
|
||
);
|
||
}
|
||
|
||
protected function ensureEmotion(array $definition, ?int $eventTypeId): ?Emotion
|
||
{
|
||
if (empty($definition)) {
|
||
return null;
|
||
}
|
||
|
||
$query = Emotion::query();
|
||
|
||
$name = $definition['name'] ?? [];
|
||
|
||
if (isset($name['en'])) {
|
||
$query->orWhere('name->en', $name['en']);
|
||
}
|
||
|
||
if (isset($name['de'])) {
|
||
$query->orWhere('name->de', $name['de']);
|
||
}
|
||
|
||
$emotion = $query->first();
|
||
|
||
if (! $emotion) {
|
||
$emotion = Emotion::create([
|
||
'name' => $name,
|
||
'icon' => $definition['icon'] ?? 'lucide-smile',
|
||
'color' => $definition['color'] ?? '#6366f1',
|
||
'description' => $definition['description'] ?? null,
|
||
'sort_order' => $definition['sort_order'] ?? 0,
|
||
'is_active' => true,
|
||
]);
|
||
}
|
||
|
||
if ($eventTypeId && ! $emotion->eventTypes()->where('event_type_id', $eventTypeId)->exists()) {
|
||
$emotion->eventTypes()->attach($eventTypeId);
|
||
}
|
||
|
||
return $emotion;
|
||
}
|
||
}
|