überarbeitet: 300 neue tasks von gemini erzeugen lassen. dazu event types "Konfirmation" und "Schulabschluss" ergänzt. alles in Kollektionen gepackt und die seeder angepasst.

Des weiteren: neue Blogartikel und howto-Artikel von ChatGPT.
Das QR-Code-Canvas funktioniert nun noch besser. die Layouts sehen besser aus.
Der PaketSeeder enthält nun die Paddle Sandbox ProductIDs
This commit is contained in:
Codex Agent
2025-11-02 21:52:38 +01:00
parent 792b5dfe8b
commit 073b51e2d5
33 changed files with 3013 additions and 961 deletions

View File

@@ -116,7 +116,6 @@ This application is a Laravel application and its main Laravel ecosystems packag
- eslint (ESLINT) - v9
- prettier (PRETTIER) - v3
## Conventions
- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming.
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
@@ -426,7 +425,7 @@ Route::get('/users', function () {
## Livewire Core
- Use the `search-docs` tool to find exact version specific documentation for how to write Livewire & Livewire tests.
- Use the `php artisan make:livewire [Posts\\CreatePost]` artisan command to create new components
- Use the `php artisan make:livewire [Posts\CreatePost]` artisan command to create new components
- State should live on the server, with the UI reflecting it.
- All Livewire requests hit the Laravel backend, they're like regular HTTP requests. Always validate form data, and run authorization checks in Livewire actions.

461
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,23 +20,20 @@ class EmotionsSeeder extends Seeder
['name'=>['de'=>'Stolz','en'=>'Pride'], 'icon'=>'🏆', 'color'=>'#34d399', 'description'=>['de'=>'Triumphale Augenblicke','en'=>'Triumphal moments'], 'sort_order'=>6],
['name'=>['de'=>'Teamgeist','en'=>'Team Spirit'], 'icon'=>'🤝', 'color'=>'#38bdf8', 'description'=>['de'=>'Zusammenhalt','en'=>'Team bonding'], 'sort_order'=>7],
['name'=>['de'=>'Besinnlichkeit','en'=>'Contemplation'], 'icon'=>'🕯️', 'color'=>'#22c55e', 'description'=>['de'=>'Feierliche Stimmung','en'=>'Festive calm'], 'sort_order'=>8],
['name'=>['de'=>'Romantik','en'=>'Romance'], 'icon'=>'🌹', 'color'=>'#e11d48', 'description'=>['de'=>'Romantische Stimmung','en'=>'Romantic mood'], 'sort_order'=>9],
['name'=>['de'=>'Ekstase','en'=>'Ecstasy'], 'icon'=>'🎉', 'color'=>'#f59e0b', 'description'=>['de'=>'Pure Lebensfreude','en'=>'Pure zest for life'], 'sort_order'=>10],
];
$typeIds = EventType::pluck('id','slug');
$typeIds = EventType::pluck('id')->toArray();
foreach ($emotionData as $e) {
$emotion = Emotion::updateOrCreate(['name->de' => $e['name']['de']], $e);
// Link to types
$links = ['wedding','birthday','corporate','christmas'];
if ($e['name']['de'] === 'Teamgeist') { $links = ['corporate']; }
if ($e['name']['de'] === 'Besinnlichkeit') { $links = ['christmas']; }
foreach ($links as $slug) {
if (isset($typeIds[$slug])) {
DB::table('emotion_event_type')->updateOrInsert([
'emotion_id' => $emotion->id,
'event_type_id' => $typeIds[$slug],
], []);
}
// Link to all event types
foreach ($typeIds as $typeId) {
DB::table('emotion_event_type')->updateOrInsert([
'emotion_id' => $emotion->id,
'event_type_id' => $typeId,
], []);
}
}
}

View File

@@ -11,9 +11,11 @@ class EventTypesSeeder extends Seeder
{
$types = [
['name' => ['de'=>'Hochzeit','en'=>'Wedding'], 'slug'=>'wedding', 'icon'=>'💍'],
['name' => ['de'=>'Weihnachten','en'=>'Christmas'], 'slug'=>'christmas', 'icon'=>'🎄'],
['name' => ['de'=>'Geburtstag','en'=>'Birthday'], 'slug'=>'birthday', 'icon'=>'🎂'],
['name' => ['de'=>'Firma','en'=>'Corporate'], 'slug'=>'corporate', 'icon'=>'🏢'],
['name' => ['de'=>'Weihnachten','en'=>'Christmas'], 'slug'=>'christmas', 'icon'=>'🎄'],
['name' => ['de'=>'Konfirmation / Jugendweihe','en'=>'Confirmation'], 'slug'=>'confirmation', 'icon'=>'🕊️'],
['name' => ['de'=>'Schulabschluss','en'=>'Graduation'], 'slug'=>'graduation', 'icon'=>'🎓'],
['name' => ['de'=>'Firmenfeier','en'=>'Corporate'], 'slug'=>'corporate', 'icon'=>'🏢'],
];
foreach ($types as $t) {
EventType::updateOrCreate(['slug'=>$t['slug']], $t);

View File

@@ -31,6 +31,8 @@ class PackageSeeder extends Seeder
'watermark_allowed' => true,
'branding_allowed' => false,
'features' => ['basic_uploads', 'limited_sharing', 'custom_tasks'],
'paddle_product_id' => 'pro_01k8jcxx2g1vj9snqbga4283ej',
'paddle_price_id' => 'pri_01k8jcxx8qktxvqzzv0nkjjj27',
'description' => <<<TEXT
Ideal für Geburtstage, Gartenpartys oder Polterabende! {{max_guests}} Gäste teilen ihre besten Schnappschüsse, lösen {{max_tasks}} Fotoaufgaben und haben {{gallery_duration}} Zugriff auf die Online-Galerie. {{max_photos}} Bilder sind inklusive genug Platz für jede Menge Lieblingsmomente.
TEXT,
@@ -62,6 +64,8 @@ TEXT,
'watermark_allowed' => false,
'branding_allowed' => true,
'features' => ['basic_uploads', 'unlimited_sharing', 'no_watermark', 'custom_branding', 'custom_tasks'],
'paddle_product_id' => 'pro_01k8jcxwjv4ne8vf9pvd9bye3j',
'paddle_price_id' => 'pri_01k8jcxws51pze5xc3vj2ea0yc',
'description' => <<<TEXT
Das Rundum-Sorglos-Paket für Hochzeiten, Firmenfeiern oder Jubiläen. {{max_photos}} Bilder, {{max_guests}} Gäste und {{max_tasks}} Fotoaufgaben dazu eine Galerie, die {{gallery_duration}} online bleibt. Eigenes Logo oder Wasserzeichen inklusive.
TEXT,
@@ -93,6 +97,8 @@ TEXT,
'watermark_allowed' => false,
'branding_allowed' => true,
'features' => ['basic_uploads', 'unlimited_sharing', 'no_watermark', 'custom_branding', 'advanced_analytics', 'live_slideshow', 'priority_support'],
'paddle_product_id' => 'pro_01k8jcxvwp38gay6jj2akjg76s',
'paddle_price_id' => 'pri_01k8jcxw5sap4r306wcvc0ephy',
'description' => <<<TEXT
Das volle Erlebnis für alle, die keine Kompromisse machen wollen. {{max_photos}} Bilder, {{max_guests}} Gäste, {{gallery_duration}} Galerie-Zugang und {{max_tasks}} Aufgaben dazu kein Wasserzeichen, Live-Slideshow und Premium-Support.
TEXT,
@@ -108,6 +114,28 @@ TEXT,
['title' => 'Extras', 'value' => 'Live-Slideshow & Premium-Support'],
],
],
[
'slug' => 'premium',
'name' => 'Premium',
'name_translations' => [
'de' => 'Premium',
'en' => 'Premium',
],
'type' => PackageType::ENDCUSTOMER,
'price' => 149.00,
'max_photos' => 5000,
'max_guests' => 1000,
'gallery_days' => 180,
'max_tasks' => null,
'watermark_allowed' => true,
'branding_allowed' => false,
'features' => ['basic_uploads', 'unlimited_sharing', 'no_watermark', 'custom_branding', 'custom_tasks'],
'paddle_product_id' => 'pro_01k8jcxsmxrs45v1qvtpsepn13',
'paddle_price_id' => 'pri_01k8jcxswh74jv8vy5q7a4h70p',
'description' => null,
'description_translations' => null,
'description_table' => [],
],
[
'slug' => 's-small-reseller',
'name' => 'Reseller S',
@@ -126,6 +154,8 @@ TEXT,
'max_events_per_year' => 5,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support'],
'paddle_product_id' => 'pro_01k8jcxvax48mhmwsfydw8ha9y',
'paddle_price_id' => 'pri_01k8jcxvhe0bfasg9gg1rw70sy',
'description' => <<<TEXT
Das perfekte Paket für Fotografen oder Planer, die erste Erfahrungen mit Fotospiel sammeln wollen. Enthalten sind {{max_events_per_year}} Events pro Jahr mit Standard-Leistung Branding-Optionen inklusive.
TEXT,
@@ -157,6 +187,8 @@ TEXT,
'max_events_per_year' => 15,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support', 'advanced_reporting'],
'paddle_product_id' => 'pro_01k8jcxtrxw7jsew52jnax901q',
'paddle_price_id' => 'pri_01k8jcxv06nsgy8ym8mnfrfm5v',
'description' => <<<TEXT
Wenn du regelmäßig Hochzeiten, Firmenfeste oder private Events betreust, ist dieses Paket ideal. {{max_events_per_year}} Events pro Jahr mit Branding-Optionen, verlängerter Galerie-Laufzeit und Reporting inklusive.
TEXT,
@@ -188,6 +220,8 @@ TEXT,
'max_events_per_year' => 40,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support', 'advanced_reporting', 'live_slideshow'],
'paddle_product_id' => 'pro_01k8jcxt7gc6g6ddavmq65txzz',
'paddle_price_id' => 'pri_01k8jcxtfa07gvq43kpvpe0t8z',
'description' => <<<TEXT
Ideal für Agenturen, Fotografen oder Eventdienstleister mit vielen Veranstaltungen im Jahr. {{max_events_per_year}} Events inklusive, White-Label-Branding und alle Premium-Funktionen sorgen für maximale Flexibilität.
TEXT,
@@ -201,6 +235,30 @@ TEXT,
['title' => 'Extras', 'value' => 'Live-Slideshow & Premium-Features'],
],
],
[
'slug' => 'studio-annual',
'name' => 'Studio Jahrespaket',
'name_translations' => [
'de' => 'Studio Jahrespaket',
'en' => 'Studio Annual',
],
'type' => PackageType::RESELLER,
'price' => 1299.00,
'max_photos' => null,
'max_guests' => null,
'gallery_days' => null,
'max_tasks' => null,
'watermark_allowed' => true,
'branding_allowed' => false,
'max_events_per_year' => 24,
'expires_after' => null,
'features' => ['basic_uploads', 'unlimited_sharing', 'custom_branding'],
'paddle_product_id' => 'pro_01k8jct3gz9ks5mg6z61q6nrxb',
'paddle_price_id' => 'pri_01k8jcxsa8axwpjnybhjbcrb06',
'description' => null,
'description_translations' => null,
'description_table' => [],
],
[
'slug' => 'enterprise-unlimited',
'name' => 'Enterprise / Unlimited',

View File

@@ -7,14 +7,10 @@ use App\Models\EventType;
use App\Models\Task;
use App\Models\TaskCollection;
use Illuminate\Database\Seeder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class TaskCollectionsSeeder extends Seeder
{
private const MIN_TASKS_PER_EVENT_TYPE = 50;
public function run(): void
{
$definitions = $this->definitions();
@@ -45,395 +41,416 @@ class TaskCollectionsSeeder extends Seeder
$syncPayload[$task->id] = ['sort_order' => $sortOrder];
}
$this->ensureMinimumTasks(
$collection,
$eventType,
$syncPayload,
count($syncPayload),
self::MIN_TASKS_PER_EVENT_TYPE,
$eventTypeSlug
);
$collection->tasks()->sync($syncPayload);
$collectionMap[$eventType->id] = $collection;
}
});
$this->assignOrphanTasks($collectionMap);
}
private function definitions(): array
{
$emotions = [
'Liebe' => ['name' => ['de' => 'Liebe', 'en' => 'Love'], 'icon' => 'lucide-heart', 'color' => '#ff6b9d'],
'Freude' => ['name' => ['de' => 'Freude', 'en' => 'Joy'], 'icon' => 'lucide-smile', 'color' => '#ffd93d'],
'Rührung' => ['name' => ['de' => 'Rührung', 'en' => 'Touched'], 'icon' => 'lucide-leaf', 'color' => '#6bcf7f'],
'Nostalgie' => ['name' => ['de' => 'Nostalgie', 'en' => 'Nostalgia'], 'icon' => 'lucide-clock', 'color' => '#a78bfa'],
'Überraschung' => ['name' => ['de' => 'Überraschung', 'en' => 'Surprise'], 'icon' => 'lucide-gift', 'color' => '#fb7185'],
'Stolz' => ['name' => ['de' => 'Stolz', 'en' => 'Pride'], 'icon' => 'lucide-trophy', 'color' => '#34d399'],
'Teamgeist' => ['name' => ['de' => 'Teamgeist', 'en' => 'Team Spirit'], 'icon' => 'lucide-users', 'color' => '#38bdf8'],
'Besinnlichkeit' => ['name' => ['de' => 'Besinnlichkeit', 'en' => 'Contemplation'], 'icon' => 'lucide-candle', 'color' => '#22c55e'],
'Romantik' => ['name' => ['de' => 'Romantik', 'en' => 'Romance'], 'icon' => 'lucide-rose', 'color' => '#e11d48'],
'Ekstase' => ['name' => ['de' => 'Ekstase', 'en' => 'Ecstasy'], 'icon' => 'lucide-stars', 'color' => '#f59e0b'],
];
return [
'wedding' => [
'event_type' => [
'slug' => 'wedding',
'name' => ['de' => 'Hochzeit', 'en' => 'Wedding'],
'icon' => 'lucide-heart',
],
'event_type' => ['slug' => 'wedding', 'name' => ['de' => 'Hochzeit', 'en' => 'Wedding'], 'icon' => 'lucide-heart'],
'collection' => [
'slug' => 'wedding-classics',
'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.',
],
'slug' => 'wedding-classics-2025',
'name' => ['de' => 'Hochzeits-Aufgaben', 'en' => 'Wedding Tasks'],
'description' => ['de' => '50 Aufgaben für den schönsten Tag im Leben.', 'en' => '50 tasks for the most beautiful day of your life.'],
'is_default' => true,
'position' => 10,
],
'base_tasks' => [
$this->taskDefinition(
'wedding-first-look',
['de' => 'Erster Blick des Brautpaares festhalten', 'en' => 'Capture the couples first look'],
['de' => 'Halte den Moment fest, in dem sich Braut und Bräutigam zum ersten Mal sehen.', 'en' => 'Capture the instant when the couple sees each other for the first time.'],
['de' => 'Fotografiere die Reaktionen aus verschiedenen Blickwinkeln.', 'en' => 'Shoot reactions from multiple angles.'],
['name' => ['de' => 'Romantik', 'en' => 'Romance'], 'icon' => 'lucide-heart', 'color' => '#ec4899', 'sort_order' => 10],
'easy',
10
),
$this->taskDefinition(
'wedding-family-hug',
['de' => 'Familienumarmung organisieren', 'en' => 'Organise a family group hug'],
['de' => 'Bitte die wichtigsten Menschen, das Paar gleichzeitig zu umarmen.', 'en' => 'Ask the closest friends and family to hug the couple all at once.'],
['de' => 'Kombiniere die Umarmung mit einem Toast.', 'en' => 'Combine the hug with a heartfelt toast.'],
['name' => ['de' => 'Freude', 'en' => 'Joy'], 'icon' => 'lucide-smile', 'color' => '#f59e0b', 'sort_order' => 20],
'medium',
20
),
$this->taskDefinition(
'wedding-midnight-sparkler',
['de' => 'Mitternachtsfunkeln mit Wunderkerzen', 'en' => 'Midnight sparkler moment'],
['de' => 'Verteile Wunderkerzen und schafft ein leuchtendes Spalier für das Paar.', 'en' => 'Hand out sparklers and form a glowing aisle for the couple.'],
['de' => 'Koordiniere die Musik und kündige den Countdown an.', 'en' => 'Coordinate music and announce a countdown.'],
['name' => ['de' => 'Ekstase', 'en' => 'Euphoria'], 'icon' => 'lucide-stars', 'color' => '#6366f1', 'sort_order' => 30],
'medium',
30
),
$this->taskDefinition(
'wedding-vow-whisper',
['de' => 'Flüstert die liebsten Gelübde erneut', 'en' => 'Whisper your vows again'],
['de' => 'Lasst das Paar sich gegenseitig einen Satz aus den Gelübden zuflüstern.', 'en' => 'Let the couple whisper a favourite line from their vows to each other.'],
['de' => 'Nahaufnahme der Gesichter, während sie lächeln.', 'en' => 'Capture a close-up of the smiles while they whisper.'],
['name' => ['de' => 'Verbundenheit', 'en' => 'Connection'], 'icon' => 'lucide-infinity', 'color' => '#a855f7', 'sort_order' => 35],
'easy',
40
),
$this->taskDefinition(
'wedding-generations-portrait',
['de' => 'Generationenportrait', 'en' => 'Generations portrait'],
['de' => 'Bringe drei Generationen gleichzeitig aufs Foto vom jüngsten zum ältesten Familienmitglied.', 'en' => 'Bring three generations into a single photograph youngest to oldest.'],
['de' => 'Stellt sie gestaffelt auf einer Treppe auf.', 'en' => 'Arrange them on steps for a layered look.'],
['name' => ['de' => 'Familie', 'en' => 'Family'], 'icon' => 'lucide-users', 'color' => '#0ea5e9', 'sort_order' => 45],
'medium',
50
),
$this->taskDefinition('wedding-1', ['de' => 'Macht ein Foto mit dem Brautpaar.', 'en' => 'Take a photo with the bride and groom.'], $emotions['Freude'], 10),
$this->taskDefinition('wedding-2', ['de' => 'Stellt den Heiratsantrag nach (fragt das Brautpaar, wie er war!).', 'en' => 'Re-enact the proposal (ask the couple how it was!).'], $emotions['Romantik'], 20),
$this->taskDefinition('wedding-3', ['de' => 'Fotografiert die Eheringe aus einer kreativen Perspektive.', 'en' => 'Photograph the wedding rings from a creative perspective.'], $emotions['Liebe'], 30),
$this->taskDefinition('wedding-4', ['de' => 'Findet das Paar, das am längsten verheiratet ist, und lasst euch einen Tipp geben.', 'en' => 'Find the couple that has been married the longest and get a tip from them.'], $emotions['Nostalgie'], 40),
$this->taskDefinition('wedding-5', ['de' => 'Macht ein Foto von einer herzlichen Umarmung zwischen den Eltern des Brautpaares.', 'en' => 'Take a photo of a warm hug between the parents of the bride and groom.'], $emotions['Rührung'], 50),
$this->taskDefinition('wedding-6', ['de' => 'Bildet mit euren Händen ein Herz um das Brautpaar.', 'en' => 'Form a heart around the couple with your hands.'], $emotions['Liebe'], 60),
$this->taskDefinition('wedding-7', ['de' => 'Fotografiert den Moment, in dem die Hochzeitstorte angeschnitten wird.', 'en' => 'Photograph the moment the wedding cake is cut.'], $emotions['Freude'], 70),
$this->taskDefinition('wedding-8', ['de' => 'Macht ein Selfie mit dem Trauzeugen oder der Trauzeugin.', 'en' => 'Take a selfie with the best man or maid of honor.'], $emotions['Teamgeist'], 80),
$this->taskDefinition('wedding-9', ['de' => 'Findet jemanden mit dem gleichen Vornamen und macht ein gemeinsames Foto.', 'en' => 'Find someone with the same first name and take a photo together.'], $emotions['Überraschung'], 90),
$this->taskDefinition('wedding-10', ['de' => 'Fotografiert einen Gast, der eine Freudenträne vergießt.', 'en' => 'Photograph a guest shedding a tear of joy.'], $emotions['Rührung'], 100),
$this->taskDefinition('wedding-11', ['de' => 'Macht ein Foto, auf dem alle so hoch springen, wie sie können.', 'en' => 'Take a photo where everyone jumps as high as they can.'], $emotions['Ekstase'], 110),
$this->taskDefinition('wedding-12', ['de' => 'Findet die Großeltern des Brautpaares und macht ein Generationen-Foto.', 'en' => 'Find the grandparents of the couple and take a generation photo.'], $emotions['Liebe'], 120),
$this->taskDefinition('wedding-13', ['de' => 'Stellt eine Szene aus dem Lieblingsfilm des Brautpaares nach.', 'en' => 'Re-enact a scene from the couple\'s favorite movie.'], $emotions['Teamgeist'], 130),
$this->taskDefinition('wedding-14', ['de' => 'Macht ein Kuss-Foto mit eurem eigenen Partner.', 'en' => 'Take a kiss photo with your own partner.'], $emotions['Romantik'], 140),
$this->taskDefinition('wedding-15', ['de' => 'Fotografiert die Schuhe der Braut neben den Schuhen des Bräutigams.', 'en' => 'Photograph the bride\'s shoes next to the groom\'s shoes.'], $emotions['Romantik'], 150),
$this->taskDefinition('wedding-16', ['de' => 'Findet das jüngste und das älteste Familienmitglied auf der Feier für ein gemeinsames Bild.', 'en' => 'Find the youngest and oldest family member at the party for a photo together.'], $emotions['Nostalgie'], 160),
$this->taskDefinition('wedding-17', ['de' => 'Macht ein Foto von den Händen von drei verschiedenen Generationen.', 'en' => 'Take a photo of the hands of three different generations.'], $emotions['Rührung'], 170),
$this->taskDefinition('wedding-18', ['de' => 'Werft dem Brautpaar aus der Ferne eine Kusshand zu.', 'en' => 'Blow a kiss to the couple from a distance.'], $emotions['Liebe'], 180),
$this->taskDefinition('wedding-19', ['de' => 'Macht ein Foto mit jemandem, der heute zum ersten Mal auf einer Hochzeit ist.', 'en' => 'Take a photo with someone who is at a wedding for the first time today.'], $emotions['Überraschung'], 190),
$this->taskDefinition('wedding-20', ['de' => 'Fotografiert das Detail an der Hochzeitsdeko, das euch am besten gefällt.', 'en' => 'Photograph the detail of the wedding decoration that you like the most.'], $emotions['Besinnlichkeit'], 200),
$this->taskDefinition('wedding-21', ['de' => 'Macht ein Gruppenfoto mit allen Gästen von eurem Tisch.', 'en' => 'Take a group photo with all the guests at your table.'], $emotions['Teamgeist'], 210),
$this->taskDefinition('wedding-22', ['de' => 'Findet einen Gast mit einer besonders schicken Krawatte oder Fliege.', 'en' => 'Find a guest with a particularly fancy tie or bow tie.'], $emotions['Stolz'], 220),
$this->taskDefinition('wedding-23', ['de' => 'Tanzt mit einem Elternteil des Brautpaares und haltet den Moment fest.', 'en' => 'Dance with a parent of the couple and capture the moment.'], $emotions['Freude'], 230),
$this->taskDefinition('wedding-24', ['de' => 'Macht ein Foto, das die Aufregung kurz vor dem Ja-Wort einfängt.', 'en' => 'Take a photo that captures the excitement just before the vows.'], $emotions['Rührung'], 240),
$this->taskDefinition('wedding-25', ['de' => 'Fotografiert das Gästebuch in Aktion.', 'en' => 'Photograph the guest book in action.'], $emotions['Nostalgie'], 250),
$this->taskDefinition('wedding-26', ['de' => 'Macht ein Foto von eurem Lieblingsmoment des Tages.', 'en' => 'Take a photo of your favorite moment of the day.'], $emotions['Besinnlichkeit'], 260),
$this->taskDefinition('wedding-27', ['de' => 'Findet einen Gegenstand, der die Farbe "Blau" enthält (etwas Altes, Neues, Geliehenes, Blaues).', 'en' => 'Find an object that contains the color "blue" (something old, new, borrowed, blue).'], $emotions['Nostalgie'], 270),
$this->taskDefinition('wedding-28', ['de' => 'Macht ein Foto, auf dem ihr dem Brautpaar für die Zukunft zuprostet.', 'en' => 'Take a photo toasting to the couple\'s future.'], $emotions['Stolz'], 280),
$this->taskDefinition('wedding-29', ['de' => 'Organisiert ein "Gruppen-Herz" mit so vielen Leuten wie möglich.', 'en' => 'Organize a "group heart" with as many people as possible.'], $emotions['Teamgeist'], 290),
$this->taskDefinition('wedding-30', ['de' => 'Fotografiert einen Moment stiller Zweisamkeit des Brautpaares.', 'en' => 'Photograph a moment of quiet togetherness of the couple.'], $emotions['Romantik'], 300),
$this->taskDefinition('wedding-31', ['de' => 'Macht ein Foto mit dem DJ oder einem Mitglied der Band.', 'en' => 'Take a photo with the DJ or a member of the band.'], $emotions['Freude'], 310),
$this->taskDefinition('wedding-32', ['de' => 'Findet die Person mit dem ansteckendsten Lachen.', 'en' => 'Find the person with the most infectious laugh.'], $emotions['Freude'], 320),
$this->taskDefinition('wedding-33', ['de' => 'Fotografiert den Brautstraußwurf.', 'en' => 'Photograph the bouquet toss.'], $emotions['Überraschung'], 330),
$this->taskDefinition('wedding-34', ['de' => 'Macht ein Foto mit demjenigen, der den Brautstrauß gefangen hat.', 'en' => 'Take a photo with the person who caught the bouquet.'], $emotions['Stolz'], 340),
$this->taskDefinition('wedding-35', ['de' => 'Stellt eure beste Tanzpose zur Schau.', 'en' => 'Show off your best dance pose.'], $emotions['Ekstase'], 350),
$this->taskDefinition('wedding-36', ['de' => 'Macht ein Foto, das "Für immer und ewig" symbolisiert.', 'en' => 'Take a photo that symbolizes "forever and ever".'], $emotions['Liebe'], 360),
$this->taskDefinition('wedding-37', ['de' => 'Findet einen Gast, der die gleiche Schuhgröße hat wie ihr.', 'en' => 'Find a guest who has the same shoe size as you.'], $emotions['Überraschung'], 370),
$this->taskDefinition('wedding-38', ['de' => 'Fotografiert die leeren Tanzschuhe einer Frau, die barfuß tanzt.', 'en' => 'Photograph the empty dancing shoes of a woman dancing barefoot.'], $emotions['Ekstase'], 380),
$this->taskDefinition('wedding-39', ['de' => 'Macht ein Foto von einem Kind, das eingeschlafen ist.', 'en' => 'Take a photo of a child who has fallen asleep.'], $emotions['Rührung'], 390),
$this->taskDefinition('wedding-40', ['de' => 'Schreibt dem Brautpaar eine Botschaft auf einen Zettel und haltet sie ins Bild.', 'en' => 'Write a message to the couple on a piece of paper and hold it in the picture.'], $emotions['Liebe'], 400),
$this->taskDefinition('wedding-41', ['de' => 'Macht ein Foto mit dem "Blumenkind".', 'en' => 'Take a photo with the "flower child".'], $emotions['Freude'], 410),
$this->taskDefinition('wedding-42', ['de' => 'Fotografiert einen Moment, in dem sich das Brautpaar tief in die Augen schaut.', 'en' => 'Photograph a moment when the couple looks deep into each other\'s eyes.'], $emotions['Romantik'], 420),
$this->taskDefinition('wedding-43', ['de' => 'Findet die Person, die die weiteste Anreise hatte.', 'en' => 'Find the person who had the longest journey.'], $emotions['Stolz'], 430),
$this->taskDefinition('wedding-44', ['de' => 'Macht ein Foto, das die Freundschaft zwischen dem Bräutigam und seinem Trauzeugen zeigt.', 'en' => 'Take a photo showing the friendship between the groom and his best man.'], $emotions['Teamgeist'], 440),
$this->taskDefinition('wedding-45', ['de' => 'Fotografiert einen geheimen Moment, den nicht jeder mitbekommt.', 'en' => 'Photograph a secret moment that not everyone gets to see.'], $emotions['Besinnlichkeit'], 450),
$this->taskDefinition('wedding-46', ['de' => 'Macht ein Foto von eurem Lieblings-Teil des Hochzeitsmenüs.', 'en' => 'Take a photo of your favorite part of the wedding menu.'], $emotions['Freude'], 460),
$this->taskDefinition('wedding-47', ['de' => 'Findet einen Gast, der ein Kleid in der gleichen Farbe wie die Deko trägt.', 'en' => 'Find a guest wearing a dress the same color as the decorations.'], $emotions['Überraschung'], 470),
$this->taskDefinition('wedding-48', ['de' => 'Macht ein Foto, das die Erleichterung und Freude nach der Trauung zeigt.', 'en' => 'Take a photo showing the relief and joy after the ceremony.'], $emotions['Ekstase'], 480),
$this->taskDefinition('wedding-49', ['de' => 'Fotografiert die Geschenke für das Brautpaar.', 'en' => 'Photograph the gifts for the couple.'], $emotions['Liebe'], 490),
$this->taskDefinition('wedding-50', ['de' => 'Macht ein letztes Foto des Abends, das die Stimmung perfekt zusammenfasst.', 'en' => 'Take a final photo of the evening that perfectly summarizes the mood.'], $emotions['Nostalgie'], 500),
],
],
'birthday' => [
'event_type' => [
'slug' => 'birthday',
'name' => ['de' => 'Geburtstag', 'en' => 'Birthday'],
'icon' => 'lucide-cake',
],
'event_type' => ['slug' => 'birthday', 'name' => ['de' => 'Geburtstag', 'en' => 'Birthday'], 'icon' => 'lucide-cake'],
'collection' => [
'slug' => 'birthday-celebration',
'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,
'slug' => 'birthday-classics-2025',
'name' => ['de' => 'Geburtstags-Aufgaben', 'en' => 'Birthday Tasks'],
'description' => ['de' => '50 Aufgaben für eine unvergessliche Geburtstagsfeier.', 'en' => '50 tasks for an unforgettable birthday party.'],
'is_default' => true,
'position' => 20,
],
'base_tasks' => [
$this->taskDefinition(
'birthday-surprise-wall',
['de' => 'Überraschungswand mit Polaroids gestalten', 'en' => 'Create a surprise wall filled with instant photos'],
['de' => 'Sammle Schnappschüsse der Gäste und befestige sie als Fotowand.', 'en' => 'Collect snapshots from guests and display them as a photo wall.'],
['de' => 'Bitte jeden Gast um einen kurzen Gruß zum Bild.', 'en' => 'Invite each guest to add a short note to the photo.'],
['name' => ['de' => 'Nostalgie', 'en' => 'Nostalgia'], 'icon' => 'lucide-images', 'color' => '#f97316', 'sort_order' => 40],
'easy',
10
),
$this->taskDefinition(
'birthday-toast-circle',
['de' => 'Gratulationskreis mit kurzen Toasts', 'en' => 'Circle of toasts'],
['de' => 'Bildet einen Kreis und bittet jede Person um einen 10-Sekunden-Toast.', 'en' => 'Gather in a circle and ask each guest for a 10-second toast.'],
['de' => 'Nimm die Lautstärke nach jedem Toast auf wer jubelt am lautesten?', 'en' => 'Capture the volume of each cheer—who is the loudest?'],
['name' => ['de' => 'Dankbarkeit', 'en' => 'Gratitude'], 'icon' => 'lucide-hands', 'color' => '#22c55e', 'sort_order' => 50],
'easy',
20
),
$this->taskDefinition(
'birthday-memory-lane',
['de' => 'Memory-Lane Foto-Story', 'en' => 'Memory lane photo story'],
['de' => 'Suche drei Gegenstände, die zum Geburtstagsgast passen, und erzähle eine Mini-Story mit Fotos.', 'en' => 'Find three objects that represent the guest of honour and photograph them in a mini story.'],
['de' => 'Nutze unterschiedliche Bildausschnitte für die Story.', 'en' => 'Use different framings to tell the story.'],
['name' => ['de' => 'Erinnerung', 'en' => 'Reminiscence'], 'icon' => 'lucide-book-open', 'color' => '#6366f1', 'sort_order' => 55],
'medium',
30
),
$this->taskDefinition('birthday-1', ['de' => 'Macht ein Foto mit dem Geburtstagskind.', 'en' => 'Take a photo with the birthday person.'], $emotions['Freude'], 10),
$this->taskDefinition('birthday-2', ['de' => 'Umarme das Geburtstagskind und halte den Moment fest.', 'en' => 'Hug the birthday person and capture the moment.'], $emotions['Liebe'], 20),
$this->taskDefinition('birthday-3', ['de' => 'Macht ein Foto, auf dem ihr dem Geburtstagskind ein Ständchen singt.', 'en' => 'Take a photo of you singing "Happy Birthday" to the birthday person.'], $emotions['Freude'], 30),
$this->taskDefinition('birthday-4', ['de' => 'Fotografiert den Moment, in dem die Kerzen auf dem Kuchen ausgepustet werden.', 'en' => 'Photograph the moment the candles on the cake are blown out.'], $emotions['Stolz'], 40),
$this->taskDefinition('birthday-5', ['de' => 'Findet jemanden, der im selben Monat Geburtstag hat wie ihr.', 'en' => 'Find someone who has a birthday in the same month as you.'], $emotions['Überraschung'], 50),
$this->taskDefinition('birthday-6', ['de' => 'Macht ein Foto mit dem ältesten und dem jüngsten Gast auf der Party.', 'en' => 'Take a photo with the oldest and youngest guest at the party.'], $emotions['Nostalgie'], 60),
$this->taskDefinition('birthday-7', ['de' => 'Stellt ein Kinderfoto des Geburtstagskindes nach.', 'en' => 'Recreate a childhood photo of the birthday person.'], $emotions['Nostalgie'], 70),
$this->taskDefinition('birthday-8', ['de' => 'Macht ein Foto mit dem Geschenk, das ihr mitgebracht habt.', 'en' => 'Take a photo with the gift you brought.'], $emotions['Liebe'], 80),
$this->taskDefinition('birthday-9', ['de' => 'Fotografiert den Geschenketisch.', 'en' => 'Photograph the gift table.'], $emotions['Überraschung'], 90),
$this->taskDefinition('birthday-10', ['de' => 'Macht ein Gruppenfoto mit allen, die dem Geburtstagskind gerade am nächsten stehen.', 'en' => 'Take a group photo with everyone closest to the birthday person right now.'], $emotions['Teamgeist'], 100),
$this->taskDefinition('birthday-11', ['de' => 'Findet die Person mit dem besten Tanz-Move und fordert sie heraus.', 'en' => 'Find the person with the best dance move and challenge them.'], $emotions['Ekstase'], 110),
$this->taskDefinition('birthday-12', ['de' => 'Macht ein Foto, auf dem ihr so tut, als wärt ihr das Geburtstagskind.', 'en' => 'Take a photo pretending to be the birthday person.'], $emotions['Freude'], 120),
$this->taskDefinition('birthday-13', ['de' => 'Fotografiert einen herzhaften Lacher des Geburtstagskindes.', 'en' => 'Photograph a hearty laugh from the birthday person.'], $emotions['Freude'], 130),
$this->taskDefinition('birthday-14', ['de' => 'Macht ein Foto mit einem Familienmitglied des Geburtstagskindes.', 'en' => 'Take a photo with a family member of the birthday person.'], $emotions['Rührung'], 140),
$this->taskDefinition('birthday-15', ['de' => 'Findet einen Gegenstand, der das neue Lebensjahr symbolisiert.', 'en' => 'Find an object that symbolizes the new year of life.'], $emotions['Stolz'], 150),
$this->taskDefinition('birthday-16', ['de' => 'Macht ein Selfie mit dem Haustier des Geburtstagskindes (falls vorhanden).', 'en' => 'Take a selfie with the birthday person\'s pet (if any).'], $emotions['Liebe'], 160),
$this->taskDefinition('birthday-17', ['de' => 'Fotografiert die Dekoration, die euch am besten gefällt.', 'en' => 'Photograph the decoration you like the most.'], $emotions['Besinnlichkeit'], 170),
$this->taskDefinition('birthday-18', ['de' => 'Macht ein Foto, auf dem ihr eure beste "Überraschung!"-Miene aufsetzt.', 'en' => 'Take a photo with your best "surprise!" face.'], $emotions['Überraschung'], 180),
$this->taskDefinition('birthday-19', ['de' => 'Findet jemanden, den ihr seit über 10 Jahren nicht gesehen habt.', 'en' => 'Find someone you haven\'t seen in over 10 years.'], $emotions['Nostalgie'], 190),
$this->taskDefinition('birthday-20', ['de' => 'Prostet dem Geburtstagskind zu.', 'en' => 'Toast to the birthday person.'], $emotions['Stolz'], 200),
$this->taskDefinition('birthday-21', ['de' => 'Macht ein Foto von eurem Lieblings-Snack auf der Party.', 'en' => 'Take a photo of your favorite snack at the party.'], $emotions['Freude'], 210),
$this->taskDefinition('birthday-22', ['de' => 'Bildet mit einer Gruppe das Alter des Geburtstagskindes mit euren Körpern.', 'en' => 'Form the age of the birthday person with your bodies in a group.'], $emotions['Teamgeist'], 220),
$this->taskDefinition('birthday-23', ['de' => 'Macht ein Foto mit jemandem, der die gleiche Lieblingsfarbe hat wie das Geburtstagskind.', 'en' => 'Take a photo with someone who has the same favorite color as the birthday person.'], $emotions['Teamgeist'], 230),
$this->taskDefinition('birthday-24', ['de' => 'Fotografiert einen Moment der Ruhe, in dem das Geburtstagskind einfach nur genießt.', 'en' => 'Photograph a moment of calm where the birthday person is just enjoying themselves.'], $emotions['Besinnlichkeit'], 240),
$this->taskDefinition('birthday-25', ['de' => 'Macht ein Foto mit dem besten Freund/der besten Freundin des Geburtstagskindes.', 'en' => 'Take a photo with the birthday person\'s best friend.'], $emotions['Liebe'], 250),
$this->taskDefinition('birthday-26', ['de' => 'Findet einen Gast, der eine lustige Anekdote über das Geburtstagskind erzählen kann.', 'en' => 'Find a guest who can tell a funny anecdote about the birthday person.'], $emotions['Nostalgie'], 260),
$this->taskDefinition('birthday-27', ['de' => 'Macht ein Foto, das eure Freundschaft zum Geburtstagskind beschreibt.', 'en' => 'Take a photo that describes your friendship with the birthday person.'], $emotions['Liebe'], 270),
$this->taskDefinition('birthday-28', ['de' => 'Fotografiert die leeren Gläser nach einer Runde Anstoßen.', 'en' => 'Photograph the empty glasses after a round of toasts.'], $emotions['Ekstase'], 280),
$this->taskDefinition('birthday-29', ['de' => 'Macht ein Foto, auf dem ihr so tut, als würdet ihr ein Geschenk klauen.', 'en' => 'Take a photo pretending to steal a gift.'], $emotions['Überraschung'], 290),
$this->taskDefinition('birthday-30', ['de' => 'Findet die Person, die am lautesten singt.', 'en' => 'Find the person who sings the loudest.'], $emotions['Ekstase'], 300),
$this->taskDefinition('birthday-31', ['de' => 'Macht ein Foto von den Schuhen des Geburtstagskindes.', 'en' => 'Take a photo of the birthday person\'s shoes.'], $emotions['Stolz'], 310),
$this->taskDefinition('birthday-32', ['de' => 'Fotografiert einen Moment, in dem jemand eine rührende Rede hält.', 'en' => 'Photograph a moment when someone gives a touching speech.'], $emotions['Rührung'], 320),
$this->taskDefinition('birthday-33', ['de' => 'Macht ein Foto mit jemandem, der die gleiche Haarfarbe hat wie ihr.', 'en' => 'Take a photo with someone who has the same hair color as you.'], $emotions['Überraschung'], 330),
$this->taskDefinition('birthday-34', ['de' => 'Stellt eure "Ich habe das beste Geschenk"-Pose zur Schau.', 'en' => 'Show off your "I have the best gift" pose.'], $emotions['Stolz'], 340),
$this->taskDefinition('birthday-35', ['de' => 'Macht ein Foto, das die pure Lebensfreude einfängt.', 'en' => 'Take a photo that captures pure joy of life.'], $emotions['Ekstase'], 350),
$this->taskDefinition('birthday-36', ['de' => 'Findet einen Ort auf der Party, der eine besondere Bedeutung für das Geburtstagskind hat.', 'en' => 'Find a place at the party that has a special meaning for the birthday person.'], $emotions['Nostalgie'], 360),
$this->taskDefinition('birthday-37', ['de' => 'Macht ein Foto, das zeigt, wie sehr ihr euch auf das nächste Jahr freut.', 'en' => 'Take a photo that shows how much you are looking forward to the next year.'], $emotions['Stolz'], 370),
$this->taskDefinition('birthday-38', ['de' => 'Fotografiert die Playlist oder den DJ-Pult.', 'en' => 'Photograph the playlist or the DJ booth.'], $emotions['Freude'], 380),
$this->taskDefinition('birthday-39', ['de' => 'Macht ein Foto mit jemandem, der eine Brille trägt.', 'en' => 'Take a photo with someone who wears glasses.'], $emotions['Teamgeist'], 390),
$this->taskDefinition('birthday-40', ['de' => 'Findet einen Gast, der die gleiche Lieblingsband hat wie das Geburtstagskind.', 'en' => 'Find a guest who has the same favorite band as the birthday person.'], $emotions['Teamgeist'], 400),
$this->taskDefinition('birthday-41', ['de' => 'Macht ein Foto, das einen Insider-Witz darstellt, den nur ihr und das Geburtstagskind versteht.', 'en' => 'Take a photo that represents an inside joke that only you and the birthday person understand.'], $emotions['Nostalgie'], 410),
$this->taskDefinition('birthday-42', ['de' => 'Fotografiert einen Moment, in dem das Geburtstagskind sichtlich gerührt ist.', 'en' => 'Photograph a moment when the birthday person is visibly moved.'], $emotions['Rührung'], 420),
$this->taskDefinition('birthday-43', ['de' => 'Macht ein Foto von der Geburtstagskarte, die euch am besten gefällt.', 'en' => 'Take a photo of the birthday card you like the most.'], $emotions['Liebe'], 430),
$this->taskDefinition('birthday-44', ['de' => 'Findet die Person, die am weitesten für die Party angereist ist.', 'en' => 'Find the person who traveled the farthest for the party.'], $emotions['Stolz'], 440),
$this->taskDefinition('birthday-45', ['de' => 'Macht ein Foto, das "Party des Jahres" schreit.', 'en' => 'Take a photo that screams "Party of the Year".'], $emotions['Ekstase'], 450),
$this->taskDefinition('birthday-46', ['de' => 'Fotografiert einen Sonnenuntergang oder den Sternenhimmel während der Feier.', 'en' => 'Photograph a sunset or the starry sky during the celebration.'], $emotions['Besinnlichkeit'], 460),
$this->taskDefinition('birthday-47', ['de' => 'Macht ein Foto mit jemandem, der ein Haustier mit einem lustigen Namen hat.', 'en' => 'Take a photo with someone who has a pet with a funny name.'], $emotions['Überraschung'], 470),
$this->taskDefinition('birthday-48', ['de' => 'Stellt eine typische Pose oder Geste des Geburtstagskindes nach.', 'en' => 'Recreate a typical pose or gesture of the birthday person.'], $emotions['Freude'], 480),
$this->taskDefinition('birthday-49', ['de' => 'Macht ein Foto, das die Vorfreude auf den Kuchen zeigt.', 'en' => 'Take a photo showing the anticipation for the cake.'], $emotions['Freude'], 490),
$this->taskDefinition('birthday-50', ['de' => 'Macht ein Abschlussfoto mit dem müden, aber glücklichen Geburtstagskind am Ende des Abends.', 'en' => 'Take a final photo with the tired but happy birthday person at the end of the evening.'], $emotions['Rührung'], 500),
],
],
'christmas' => [
'event_type' => [
'slug' => 'christmas',
'name' => ['de' => 'Weihnachten', 'en' => 'Christmas'],
'icon' => 'lucide-sparkles',
],
'event_type' => ['slug' => 'christmas', 'name' => ['de' => 'Weihnachten', 'en' => 'Christmas'], 'icon' => 'lucide-sparkles'],
'collection' => [
'slug' => 'christmas-magic',
'name' => [
'de' => 'Festliche Highlights',
'en' => 'Festive Highlights',
],
'description' => [
'de' => 'Wärmende Aufgaben für Glühwein-Momente und gemeinsames Staunen.',
'en' => 'Cozy prompts for mulled wine moments and shared wonder.',
],
'is_default' => false,
'slug' => 'christmas-classics-2025',
'name' => ['de' => 'Weihnachts-Aufgaben', 'en' => 'Christmas Tasks'],
'description' => ['de' => '50 Aufgaben für eine magische Weihnachtszeit.', 'en' => '50 tasks for a magical Christmas season.'],
'is_default' => true,
'position' => 30,
],
'base_tasks' => [
$this->taskDefinition(
'christmas-light-hunt',
['de' => 'Finde das schönste Lichterdekor', 'en' => 'Spot the brightest decoration'],
['de' => 'Halte das stimmungsvollste Licht im Raum fest.', 'en' => 'Capture the coziest lights around you.'],
['de' => 'Zeige die Lichtquelle plus Reaktion eines Gastes.', 'en' => 'Show the light source together with a guest reacting to it.'],
['name' => ['de' => 'Besinnlichkeit', 'en' => 'Serenity'], 'icon' => 'lucide-candle', 'color' => '#f97316', 'sort_order' => 20],
'easy',
10
),
$this->taskDefinition(
'christmas-cookie-cheers',
['de' => 'Plätzchen-Toast', 'en' => 'Cookie cheers'],
['de' => 'Stoßt mit Lieblingsplätzchen an und haltet das gemeinsame Lachen fest.', 'en' => 'Clink your favourite cookies together and capture the laughter.'],
['de' => 'Fotografiere in einer Reihe Hände vorne, Gesichter dahinter.', 'en' => 'Frame hands with cookies in front, smiling faces behind.'],
['name' => ['de' => 'Wärme', 'en' => 'Warmth'], 'icon' => 'lucide-mug-hot', 'color' => '#ef4444', 'sort_order' => 30],
'easy',
20
),
$this->taskDefinition(
'christmas-snow-story',
['de' => 'Schneegestöber im Innenraum', 'en' => 'Indoor snow story'],
['de' => 'Nutze Deko oder Papier, um Schneeflocken zu simulieren, und halte den Zauber fest.', 'en' => 'Use props or paper to fake snow and capture the magic.'],
['de' => 'Lass die Schneeflocken im Vordergrund unscharf erscheinen.', 'en' => 'Keep the fake snow in the foreground out of focus for a dreamy look.'],
['name' => ['de' => 'Staunen', 'en' => 'Wonder'], 'icon' => 'lucide-sparkles', 'color' => '#22d3ee', 'sort_order' => 35],
'medium',
30
),
$this->taskDefinition('christmas-1', ['de' => 'Macht ein Foto mit der Person, die das festlichste Outfit trägt.', 'en' => 'Take a photo with the person wearing the most festive outfit.'], $emotions['Stolz'], 10),
$this->taskDefinition('christmas-2', ['de' => 'Fotografiert die schönste Christbaumkugel am Baum.', 'en' => 'Photograph the most beautiful Christmas ball on the tree.'], $emotions['Besinnlichkeit'], 20),
$this->taskDefinition('christmas-3', ['de' => 'Macht ein Selfie mit einer Weihnachtsmütze auf.', 'en' => 'Take a selfie with a Santa hat on.'], $emotions['Freude'], 30),
$this->taskDefinition('christmas-4', ['de' => 'Findet jemanden, der "Last Christmas" liebt (oder hasst) und diskutiert darüber.', 'en' => 'Find someone who loves (or hates) "Last Christmas" and discuss it.'], $emotions['Teamgeist'], 40),
$this->taskDefinition('christmas-5', ['de' => 'Fotografiert einen Moment heimlicher Vorfreude auf die Geschenke.', 'en' => 'Photograph a moment of secret anticipation for the gifts.'], $emotions['Überraschung'], 50),
$this->taskDefinition('christmas-6', ['de' => 'Macht ein Foto von einer herzlichen Familienumarmung.', 'en' => 'Take a photo of a warm family hug.'], $emotions['Liebe'], 60),
$this->taskDefinition('christmas-7', ['de' => 'Fotografiert die leuchtenden Augen eines Kindes beim Anblick des Baumes.', 'en' => 'Photograph the shining eyes of a child at the sight of the tree.'], $emotions['Rührung'], 70),
$this->taskDefinition('christmas-8', ['de' => 'Macht ein Foto von eurem Lieblings-Weihnachtskeks.', 'en' => 'Take a photo of your favorite Christmas cookie.'], $emotions['Freude'], 80),
$this->taskDefinition('christmas-9', ['de' => 'Findet die Person, die am meisten über einen Witz vom Weihnachtsmann lacht.', 'en' => 'Find the person who laughs the most at a joke from Santa.'], $emotions['Ekstase'], 90),
$this->taskDefinition('christmas-10', ['de' => 'Macht ein Foto, das die Wärme und Gemütlichkeit des Raumes einfängt.', 'en' => 'Take a photo that captures the warmth and coziness of the room.'], $emotions['Besinnlichkeit'], 100),
$this->taskDefinition('christmas-11', ['de' => 'Stellt eine Szene aus der Weihnachtsgeschichte oder einem Weihnachtsfilm nach.', 'en' => 'Re-enact a scene from the Christmas story or a Christmas movie.'], $emotions['Teamgeist'], 110),
$this->taskDefinition('christmas-12', ['de' => 'Macht ein Foto mit drei Generationen eurer Familie.', 'en' => 'Take a photo with three generations of your family.'], $emotions['Nostalgie'], 120),
$this->taskDefinition('christmas-13', ['de' => 'Fotografiert das unordentlichste Geschenkpapier nach dem Auspacken.', 'en' => 'Photograph the messiest wrapping paper after unwrapping.'], $emotions['Ekstase'], 130),
$this->taskDefinition('christmas-14', ['de' => 'Findet jemanden, der Socken zu Weihnachten bekommen hat und sich ehrlich freut.', 'en' => 'Find someone who got socks for Christmas and is genuinely happy about it.'], $emotions['Überraschung'], 140),
$this->taskDefinition('christmas-15', ['de' => 'Macht ein Foto, auf dem ihr so tut, als wärt ihr ein Engel auf der Baumspitze.', 'en' => 'Take a photo pretending to be an angel on top of the tree.'], $emotions['Freude'], 150),
$this->taskDefinition('christmas-16', ['de' => 'Fotografiert einen Mistelzweig in Aktion.', 'en' => 'Photograph a mistletoe in action.'], $emotions['Romantik'], 160),
$this->taskDefinition('christmas-17', ['de' => 'Macht ein Foto mit der Person, die das Essen gekocht hat, als Dankeschön.', 'en' => 'Take a photo with the person who cooked the meal as a thank you.'], $emotions['Liebe'], 170),
$this->taskDefinition('christmas-18', ['de' => 'Findet das älteste Stück Weihnachtsschmuck in der Wohnung.', 'en' => 'Find the oldest piece of Christmas decoration in the house.'], $emotions['Nostalgie'], 180),
$this->taskDefinition('christmas-19', ['de' => 'Macht ein Foto, auf dem ihr andächtig einer Weihnachtsgeschichte lauscht.', 'en' => 'Take a photo of you listening intently to a Christmas story.'], $emotions['Besinnlichkeit'], 190),
$this->taskDefinition('christmas-20', ['de' => 'Fotografiert einen Moment des gemeinsamen Singens.', 'en' => 'Photograph a moment of singing together.'], $emotions['Rührung'], 200),
$this->taskDefinition('christmas-21', ['de' => 'Macht ein Gruppenfoto, auf dem alle ihre "hässlichen Weihnachtspullover" zeigen.', 'en' => 'Take a group photo showing off everyone\'s "ugly Christmas sweaters".'], $emotions['Teamgeist'], 210),
$this->taskDefinition('christmas-22', ['de' => 'Findet jemanden, der sich über sein Geschenk am meisten gefreut hat.', 'en' => 'Find someone who was most happy about their gift.'], $emotions['Stolz'], 220),
$this->taskDefinition('christmas-23', ['de' => 'Macht ein Foto von den dampfenden Tassen mit Glühwein oder Kakao.', 'en' => 'Take a photo of the steaming mugs of mulled wine or cocoa.'], $emotions['Freude'], 230),
$this->taskDefinition('christmas-24', ['de' => 'Fotografiert einen Moment der Stille vor der Bescherung.', 'en' => 'Photograph a moment of silence before the gift-giving.'], $emotions['Besinnlichkeit'], 240),
$this->taskDefinition('christmas-25', ['de' => 'Macht ein Foto mit jemandem, der im Dezember Geburtstag hat.', 'en' => 'Take a photo with someone who has a birthday in December.'], $emotions['Überraschung'], 250),
$this->taskDefinition('christmas-26', ['de' => 'Findet das Geschenk mit der schönsten Schleife.', 'en' => 'Find the gift with the most beautiful bow.'], $emotions['Stolz'], 260),
$this->taskDefinition('christmas-27', ['de' => 'Macht ein Foto, das "Frieden auf Erden" symbolisiert.', 'en' => 'Take a photo that symbolizes "Peace on Earth".'], $emotions['Liebe'], 270),
$this->taskDefinition('christmas-28', ['de' => 'Fotografiert die leeren Teller nach dem Weihnachtsessen.', 'en' => 'Photograph the empty plates after Christmas dinner.'], $emotions['Freude'], 280),
$this->taskDefinition('christmas-29', ['de' => 'Macht ein Foto aus der Perspektive eines Geschenks unter dem Baum.', 'en' => 'Take a photo from the perspective of a gift under the tree.'], $emotions['Überraschung'], 290),
$this->taskDefinition('christmas-30', ['de' => 'Findet jemanden, der noch an den Weihnachtsmann glaubt (oder so tut als ob).', 'en' => 'Find someone who still believes in Santa Claus (or pretends to).'], $emotions['Nostalgie'], 300),
$this->taskDefinition('christmas-31', ['de' => 'Macht ein Foto, das die Aufregung beim Würfeln um Geschenke (Wichteln) zeigt.', 'en' => 'Take a photo showing the excitement of dice games for gifts (Secret Santa).'], $emotions['Ekstase'], 310),
$this->taskDefinition('christmas-32', ['de' => 'Fotografiert eine Kerze, die für jemanden brennt, der nicht hier sein kann.', 'en' => 'Photograph a candle burning for someone who cannot be here.'], $emotions['Rührung'], 320),
$this->taskDefinition('christmas-33', ['de' => 'Macht ein Foto mit eurem Lieblingsgeschenk, das ihr bekommen habt.', 'en' => 'Take a photo with your favorite gift you received.'], $emotions['Stolz'], 330),
$this->taskDefinition('christmas-34', ['de' => 'Findet die Person, die am besten "Oh Tannenbaum" singen kann.', 'en' => 'Find the person who can sing "O Christmas Tree" the best.'], $emotions['Teamgeist'], 340),
$this->taskDefinition('christmas-35', ['de' => 'Macht ein Foto, das die Magie des Schneefalls zeigt (falls es schneit).', 'en' => 'Take a photo that shows the magic of snowfall (if it is snowing).'], $emotions['Romantik'], 350),
$this->taskDefinition('christmas-36', ['de' => 'Fotografiert einen Moment, in dem alte Familiengeschichten erzählt werden.', 'en' => 'Photograph a moment when old family stories are being told.'], $emotions['Nostalgie'], 360),
$this->taskDefinition('christmas-37', ['de' => 'Macht ein Foto von jemandem, der ein Nickerchen nach dem Essen macht.', 'en' => 'Take a photo of someone taking a nap after the meal.'], $emotions['Rührung'], 370),
$this->taskDefinition('christmas-38', ['de' => 'Findet das kleinste und das größte Geschenk unter dem Baum.', 'en' => 'Find the smallest and the largest gift under the tree.'], $emotions['Überraschung'], 380),
$this->taskDefinition('christmas-39', ['de' => 'Macht ein Foto, das eure Dankbarkeit für diesen Moment ausdrückt.', 'en' => 'Take a photo that expresses your gratitude for this moment.'], $emotions['Liebe'], 390),
$this->taskDefinition('christmas-40', ['de' => 'Fotografiert die Vorbereitungen in der Küche.', 'en' => 'Photograph the preparations in the kitchen.'], $emotions['Teamgeist'], 400),
$this->taskDefinition('christmas-41', ['de' => 'Macht ein Foto, auf dem ihr versucht, heimlich vom Nachtisch zu naschen.', 'en' => 'Take a photo of you trying to secretly snack on dessert.'], $emotions['Überraschung'], 410),
$this->taskDefinition('christmas-42', ['de' => 'Findet jemanden, der alle Rentiere des Weihnachtsmanns aufzählen kann.', 'en' => 'Find someone who can name all of Santa\'s reindeer.'], $emotions['Stolz'], 420),
$this->taskDefinition('christmas-43', ['de' => 'Macht ein Foto, das die besondere Verbindung zu euren Geschwistern zeigt.', 'en' => 'Take a photo that shows the special bond with your siblings.'], $emotions['Liebe'], 430),
$this->taskDefinition('christmas-44', ['de' => 'Fotografiert den Adventskranz.', 'en' => 'Photograph the Advent wreath.'], $emotions['Besinnlichkeit'], 440),
$this->taskDefinition('christmas-45', ['de' => 'Macht ein Foto von den Fußspuren im Schnee.', 'en' => 'Take a photo of the footprints in the snow.'], $emotions['Nostalgie'], 450),
$this->taskDefinition('christmas-46', ['de' => 'Findet die Person, die am aufgeregtesten ist, einen bestimmten Film zu sehen.', 'en' => 'Find the person who is most excited to see a certain movie.'], $emotions['Ekstase'], 460),
$this->taskDefinition('christmas-47', ['de' => 'Macht ein Foto, das die Freude am Geben zeigt.', 'en' => 'Take a photo that shows the joy of giving.'], $emotions['Liebe'], 470),
$this->taskDefinition('christmas-48', ['de' => 'Fotografiert die Tischdekoration im Detail.', 'en' => 'Photograph the table decoration in detail.'], $emotions['Stolz'], 480),
$this->taskDefinition('christmas-49', ['de' => 'Macht ein Foto von einem handgemachten Geschenk.', 'en' => 'Take a photo of a handmade gift.'], $emotions['Rührung'], 490),
$this->taskDefinition('christmas-50', ['de' => 'Macht ein letztes Gruppenfoto vor dem Weihnachtsbaum, bevor die Feier endet.', 'en' => 'Take a final group photo in front of the Christmas tree before the celebration ends.'], $emotions['Nostalgie'], 500),
],
],
'corporate' => [
'event_type' => [
'slug' => 'corporate',
'name' => ['de' => 'Firma', 'en' => 'Corporate'],
'icon' => 'lucide-briefcase',
],
'confirmation' => [
'event_type' => ['slug' => 'confirmation', 'name' => ['de' => 'Konfirmation / Jugendweihe', 'en' => 'Confirmation'], 'icon' => 'lucide-dove'],
'collection' => [
'slug' => 'corporate-connect',
'name' => [
'de' => 'Team-Verbindungen',
'en' => 'Team Connections',
],
'description' => [
'de' => 'Interaktive Aufgaben für produktive Offsites und Firmenfeiern.',
'en' => 'Interactive prompts for productive offsites and company celebrations.',
],
'is_default' => false,
'slug' => 'confirmation-classics-2025',
'name' => ['de' => 'Aufgaben zur Konfirmation/Jugendweihe', 'en' => 'Confirmation Tasks'],
'description' => ['de' => '50 Aufgaben für einen denkwürdigen Tag.', 'en' => '50 tasks for a memorable day.'],
'is_default' => true,
'position' => 40,
],
'base_tasks' => [
$this->taskDefinition(
'corporate-high-five-chain',
['de' => 'High-Five-Kette starten', 'en' => 'Start a high-five chain'],
['de' => 'Platziert euch im Kreis und gebt reihum High-Fives haltet den Moment fest.', 'en' => 'Form a circle and pass on high-fives capture the energy.'],
['de' => 'Nutze Serienaufnahmen, um alle Bewegungen einzufangen.', 'en' => 'Use burst mode to catch every high-five.'],
['name' => ['de' => 'Teamgeist', 'en' => 'Team Spirit'], 'icon' => 'lucide-users', 'color' => '#0ea5e9', 'sort_order' => 10],
'easy',
10
),
$this->taskDefinition(
'corporate-goal-toast',
['de' => 'Ziele feiern', 'en' => 'Celebrate milestones'],
['de' => 'Ruft gemeinsam ein erreichte Ziel in die Kamera und haltet die Euphorie fest.', 'en' => 'Shout a recent team achievement into the camera together.'],
['de' => 'Lasst Konfetti oder Luftballons in den Rahmen fallen.', 'en' => 'Drop confetti or balloons into the frame.'],
['name' => ['de' => 'Stolz', 'en' => 'Pride'], 'icon' => 'lucide-trophy', 'color' => '#22c55e', 'sort_order' => 20],
'medium',
20
),
$this->taskDefinition(
'corporate-coffee-pose',
['de' => 'Kaffee-Powerpose', 'en' => 'Coffee power pose'],
['de' => 'Lass das Team mit Kaffeebechern posieren jede Person zeigt eine andere Emotion.', 'en' => 'Have the team pose with coffee mugs, each showing a different emotion.'],
['de' => 'Nutze eine niedrige Perspektive, um Power auszudrücken.', 'en' => 'Shoot from a low angle to emphasise power.'],
['name' => ['de' => 'Motivation', 'en' => 'Motivation'], 'icon' => 'lucide-rocket', 'color' => '#8b5cf6', 'sort_order' => 30],
'easy',
30
),
$this->taskDefinition('confirmation-1', ['de' => 'Macht ein Foto mit dem Konfirmanden / Jugendweihe-Teilnehmer.', 'en' => 'Take a photo with the confirmand / youth consecration participant.'], $emotions['Stolz'], 10),
$this->taskDefinition('confirmation-2', ['de' => 'Fotografiert die Urkunde oder das Erinnerungsdokument.', 'en' => 'Photograph the certificate or commemorative document.'], $emotions['Stolz'], 20),
$this->taskDefinition('confirmation-3', ['de' => 'Macht ein Foto mit den Paten oder Mentoren.', 'en' => 'Take a photo with the godparents or mentors.'], $emotions['Teamgeist'], 30),
$this->taskDefinition('confirmation-4', ['de' => 'Findet die Großeltern und macht ein Foto, das ihren Stolz zeigt.', 'en' => 'Find the grandparents and take a photo that shows their pride.'], $emotions['Rührung'], 40),
$this->taskDefinition('confirmation-5', ['de' => 'Fotografiert einen Moment des Nachdenkens oder Gebets in der Kirche/am Ort der Feier.', 'en' => 'Photograph a moment of reflection or prayer in the church/at the place of celebration.'], $emotions['Besinnlichkeit'], 50),
$this->taskDefinition('confirmation-6', ['de' => 'Macht ein Gruppenfoto mit allen jungen Leuten, die heute ebenfalls gefeiert werden.', 'en' => 'Take a group photo with all the young people who are also being celebrated today.'], $emotions['Teamgeist'], 60),
$this->taskDefinition('confirmation-7', ['de' => 'Fotografiert die festliche Kleidung des Hauptakteurs im Detail.', 'en' => 'Photograph the festive attire of the main character in detail.'], $emotions['Stolz'], 70),
$this->taskDefinition('confirmation-8', ['de' => 'Macht ein Foto mit einem Gast, der euch einen guten Ratschlag für die Zukunft gibt.', 'en' => 'Take a photo with a guest who gives you good advice for the future.'], $emotions['Besinnlichkeit'], 80),
$this->taskDefinition('confirmation-9', ['de' => 'Findet das schönste Blumenarrangement.', 'en' => 'Find the most beautiful flower arrangement.'], $emotions['Freude'], 90),
$this->taskDefinition('confirmation-10', ['de' => 'Macht ein Foto, das die feierliche Atmosphäre einfängt.', 'en' => 'Take a photo that captures the solemn atmosphere.'], $emotions['Besinnlichkeit'], 100),
$this->taskDefinition('confirmation-11', ['de' => 'Fotografiert den Moment des Anstoßens auf die Zukunft.', 'en' => 'Photograph the moment of toasting to the future.'], $emotions['Stolz'], 110),
$this->taskDefinition('confirmation-12', ['de' => 'Macht ein Foto mit euren Eltern, das ihre Liebe und Unterstützung zeigt.', 'en' => 'Take a photo with your parents that shows their love and support.'], $emotions['Liebe'], 120),
$this->taskDefinition('confirmation-13', ['de' => 'Findet einen Gast, der bei seiner eigenen Konfirmation/Jugendweihe dabei war und fragt nach einer Anekdote.', 'en' => 'Find a guest who was at their own confirmation/youth consecration and ask for an anecdote.'], $emotions['Nostalgie'], 130),
$this->taskDefinition('confirmation-14', ['de' => 'Fotografiert die brennenden Kerzen.', 'en' => 'Photograph the burning candles.'], $emotions['Besinnlichkeit'], 140),
$this->taskDefinition('confirmation-15', ['de' => 'Macht ein Foto, das die Aufregung und Nervosität vor dem großen Moment zeigt.', 'en' => 'Take a photo that shows the excitement and nervousness before the big moment.'], $emotions['Rührung'], 150),
$this->taskDefinition('confirmation-16', ['de' => 'Findet das Gesangbuch oder Programmheft und macht ein Foto davon.', 'en' => 'Find the hymnal or program booklet and take a photo of it.'], $emotions['Nostalgie'], 160),
$this->taskDefinition('confirmation-17', ['de' => 'Macht ein Foto mit dem Pfarrer, Redner oder Organisator der Feier.', 'en' => 'Take a photo with the pastor, speaker or organizer of the celebration.'], $emotions['Teamgeist'], 170),
$this->taskDefinition('confirmation-18', ['de' => 'Fotografiert den Geschenketisch.', 'en' => 'Photograph the gift table.'], $emotions['Überraschung'], 180),
$this->taskDefinition('confirmation-19', ['de' => 'Macht ein Foto, das die Verbindung zwischen den Generationen darstellt.', 'en' => 'Take a photo that represents the connection between generations.'], $emotions['Liebe'], 190),
$this->taskDefinition('confirmation-20', ['de' => 'Findet einen Gast, der dem Konfirmanden/Jugendweihe-Teilnehmer besonders ähnlich sieht.', 'en' => 'Find a guest who looks particularly similar to the confirmand/youth consecration participant.'], $emotions['Überraschung'], 200),
$this->taskDefinition('confirmation-21', ['de' => 'Macht ein Foto von der festlich gedeckten Tafel.', 'en' => 'Take a photo of the festively decorated table.'], $emotions['Stolz'], 210),
$this->taskDefinition('confirmation-22', ['de' => 'Fotografiert einen Moment herzlichen Lachens.', 'en' => 'Photograph a moment of hearty laughter.'], $emotions['Freude'], 220),
$this->taskDefinition('confirmation-23', ['de' => 'Macht ein Foto mit einem Freund, den ihr durch den Konfirmandenunterricht/die Vorbereitung kennengelernt habt.', 'en' => 'Take a photo with a friend you met through confirmation class/preparation.'], $emotions['Teamgeist'], 230),
$this->taskDefinition('confirmation-24', ['de' => 'Findet einen ruhigen Ort und macht ein Foto, das eure Gedanken über die Zukunft festhält.', 'en' => 'Find a quiet place and take a photo that captures your thoughts about the future.'], $emotions['Besinnlichkeit'], 240),
$this->taskDefinition('confirmation-25', ['de' => 'Macht ein Foto, das "ein neuer Lebensabschnitt beginnt" symbolisiert.', 'en' => 'Take a photo that symbolizes "a new chapter in life begins".'], $emotions['Stolz'], 250),
$this->taskDefinition('confirmation-26', ['de' => 'Fotografiert die Glückwunschkarten.', 'en' => 'Photograph the greeting cards.'], $emotions['Liebe'], 260),
$this->taskDefinition('confirmation-27', ['de' => 'Macht ein Foto mit jemandem, der ein Kreuz oder ein anderes Symbol des Tages trägt.', 'en' => 'Take a photo with someone wearing a cross or other symbol of the day.'], $emotions['Teamgeist'], 270),
$this->taskDefinition('confirmation-28', ['de' => 'Findet einen Gast, der eine besonders rührende Geschichte erzählen kann.', 'en' => 'Find a guest who can tell a particularly touching story.'], $emotions['Rührung'], 280),
$this->taskDefinition('confirmation-29', ['de' => 'Macht ein Foto von den Schuhen bereit für den neuen Weg.', 'en' => 'Take a photo of the shoes ready for the new path.'], $emotions['Stolz'], 290),
$this->taskDefinition('confirmation-30', ['de' => 'Fotografiert die Torte oder das Dessertbuffet.', 'en' => 'Photograph the cake or dessert buffet.'], $emotions['Freude'], 300),
$this->taskDefinition('confirmation-31', ['de' => 'Macht ein Foto, das die Erleichterung nach dem offiziellen Teil zeigt.', 'en' => 'Take a photo that shows the relief after the official part.'], $emotions['Ekstase'], 310),
$this->taskDefinition('confirmation-32', ['de' => 'Findet den Gast, der den weitesten Weg auf sich genommen hat.', 'en' => 'Find a guest who has traveled the farthest.'], $emotions['Stolz'], 320),
$this->taskDefinition('confirmation-33', ['de' => 'Macht ein Foto, das Dankbarkeit ausdrückt.', 'en' => 'Take a photo that expresses gratitude.'], $emotions['Liebe'], 330),
$this->taskDefinition('confirmation-34', ['de' => 'Fotografiert ein Detail der Architektur des Feierortes.', 'en' => 'Photograph a detail of the architecture of the celebration venue.'], $emotions['Besinnlichkeit'], 340),
$this->taskDefinition('confirmation-35', ['de' => 'Macht ein Foto mit euren Geschwistern.', 'en' => 'Take a photo with your siblings.'], $emotions['Liebe'], 350),
$this->taskDefinition('confirmation-36', ['de' => 'Findet jemanden, der ein altes Foto von euch als Kind dabei hat.', 'en' => 'Find someone who has an old photo of you as a child.'], $emotions['Nostalgie'], 360),
$this->taskDefinition('confirmation-37', ['de' => 'Macht ein Foto, das die Freude über ein besonderes Geschenk zeigt.', 'en' => 'Take a photo that shows the joy of a special gift.'], $emotions['Überraschung'], 370),
$this->taskDefinition('confirmation-38', ['de' => 'Fotografiert die Hände eurer Eltern, die euch halten.', 'en' => 'Photograph your parents\' hands holding you.'], $emotions['Rührung'], 380),
$this->taskDefinition('confirmation-39', ['de' => 'Macht ein Foto, auf dem ihr in den Himmel schaut und an die Zukunft denkt.', 'en' => 'Take a photo of you looking at the sky and thinking about the future.'], $emotions['Besinnlichkeit'], 390),
$this->taskDefinition('confirmation-40', ['de' => 'Findet die Person mit dem besten Ratschlag für das Erwachsenwerden.', 'en' => 'Find the person with the best advice for growing up.'], $emotions['Teamgeist'], 400),
$this->taskDefinition('confirmation-41', ['de' => 'Macht ein Foto, das die Freundschaften feiert, die euch bis hierher begleitet haben.', 'en' => 'Take a photo that celebrates the friendships that have accompanied you this far.'], $emotions['Liebe'], 410),
$this->taskDefinition('confirmation-42', ['de' => 'Fotografiert die Musikinstrumente, die gespielt werden (Orgel, Klavier etc.).', 'en' => 'Photograph the musical instruments being played (organ, piano, etc.).'], $emotions['Rührung'], 420),
$this->taskDefinition('confirmation-43', ['de' => 'Macht ein Foto von einem Lächeln, das von Herzen kommt.', 'en' => 'Take a photo of a smile that comes from the heart.'], $emotions['Freude'], 430),
$this->taskDefinition('confirmation-44', ['de' => 'Findet einen Gegenstand, der für euch persönlich diesen Tag symbolisiert.', 'en' => 'Find an object that personally symbolizes this day for you.'], $emotions['Nostalgie'], 440),
$this->taskDefinition('confirmation-45', ['de' => 'Macht ein Foto, das die Aufbruchstimmung des Tages einfängt.', 'en' => 'Take a photo that captures the spirit of optimism of the day.'], $emotions['Ekstase'], 450),
$this->taskDefinition('confirmation-46', ['de' => 'Fotografiert die Dekoration, die von der Familie selbst gemacht wurde.', 'en' => 'Photograph the decoration that was made by the family themselves.'], $emotions['Stolz'], 460),
$this->taskDefinition('confirmation-47', ['de' => 'Macht ein Foto mit der Person, die euch heute am meisten zum Lachen gebracht hat.', 'en' => 'Take a photo with the person who made you laugh the most today.'], $emotions['Freude'], 470),
$this->taskDefinition('confirmation-48', ['de' => 'Findet einen Moment, um dem Hauptakteur des Tages im Stillen alles Gute zu wünschen.', 'en' => 'Find a moment to silently wish the main character of the day all the best.'], $emotions['Liebe'], 480),
$this->taskDefinition('confirmation-49', ['de' => 'Fotografiert die leeren Plätze nach dem Ende der Zeremonie.', 'en' => 'Photograph the empty seats after the end of the ceremony.'], $emotions['Nostalgie'], 490),
$this->taskDefinition('confirmation-50', ['de' => 'Macht ein letztes Foto des Tages, das den Übergang in einen neuen Lebensabschnitt festhält.', 'en' => 'Take a final photo of the day that captures the transition to a new chapter in life.'], $emotions['Stolz'], 500),
],
],
'graduation' => [
'event_type' => ['slug' => 'graduation', 'name' => ['de' => 'Schulabschluss', 'en' => 'Graduation'], 'icon' => 'lucide-graduation-cap'],
'collection' => [
'slug' => 'graduation-classics-2025',
'name' => ['de' => 'Aufgaben zum Schulabschluss', 'en' => 'Graduation Tasks'],
'description' => ['de' => '50 Aufgaben, um das Ende der Schulzeit zu feiern.', 'en' => '50 tasks to celebrate the end of school.'],
'is_default' => true,
'position' => 50,
],
'base_tasks' => [
$this->taskDefinition('graduation-1', ['de' => 'Werft eure Hüte in die Luft!', 'en' => 'Throw your hats in the air!'], $emotions['Ekstase'], 10),
$this->taskDefinition('graduation-2', ['de' => 'Macht ein Foto mit eurem Abschlusszeugnis.', 'en' => 'Take a photo with your diploma.'], $emotions['Stolz'], 20),
$this->taskDefinition('graduation-3', ['de' => 'Umarme deine besten Schulfreunde für ein Gruppenfoto.', 'en' => 'Hug your best school friends for a group photo.'], $emotions['Liebe'], 30),
$this->taskDefinition('graduation-4', ['de' => 'Macht ein Foto mit eurem Lieblingslehrer.', 'en' => 'Take a photo with your favorite teacher.'], $emotions['Rührung'], 40),
$this->taskDefinition('graduation-5', ['de' => 'Findet eure Eltern und macht ein Foto, das ihren Stolz zeigt.', 'en' => 'Find your parents and take a photo that shows their pride.'], $emotions['Stolz'], 50),
$this->taskDefinition('graduation-6', ['de' => 'Stellt ein Foto vom ersten Schultag nach.', 'en' => 'Recreate a photo from the first day of school.'], $emotions['Nostalgie'], 60),
$this->taskDefinition('graduation-7', ['de' => 'Macht ein Foto, auf dem ihr so tut, als würdet ihr für eine Prüfung lernen.', 'en' => 'Take a photo pretending to study for an exam.'], $emotions['Nostalgie'], 70),
$this->taskDefinition('graduation-8', ['de' => 'Findet jemanden, mit dem ihr seit der Grundschule in einer Klasse wart.', 'en' => 'Find someone you have been in a class with since elementary school.'], $emotions['Nostalgie'], 80),
$this->taskDefinition('graduation-9', ['de' => 'Macht ein Foto mit eurem "Partner in Crime" aus der Schulzeit.', 'en' => 'Take a photo with your "partner in crime" from school.'], $emotions['Teamgeist'], 90),
$this->taskDefinition('graduation-10', ['de' => 'Fotografiert die Unterschrift eures Lieblingslehrers auf eurem Zeugnis oder Jahrbuch.', 'en' => 'Photograph the signature of your favorite teacher on your report card or yearbook.'], $emotions['Stolz'], 100),
$this->taskDefinition('graduation-11', ['de' => 'Macht ein Foto, das eure Pläne für die Zukunft symbolisiert (z.B. mit einem Reiseführer, einem Lehrbuch).', 'en' => 'Take a photo that symbolizes your plans for the future (e.g. with a travel guide, a textbook).'], $emotions['Besinnlichkeit'], 110),
$this->taskDefinition('graduation-12', ['de' => 'Findet die Person, die die verrücktesten Pläne nach dem Abschluss hat.', 'en' => 'Find the person with the craziest plans after graduation.'], $emotions['Überraschung'], 120),
$this->taskDefinition('graduation-13', ['de' => 'Macht ein Gruppenfoto mit eurer gesamten Clique.', 'en' => 'Take a group photo with your entire clique.'], $emotions['Teamgeist'], 130),
$this->taskDefinition('graduation-14', ['de' => 'Fotografiert einen Moment, in dem Tränen des Abschieds und der Freude fließen.', 'en' => 'Photograph a moment when tears of farewell and joy are flowing.'], $emotions['Rührung'], 140),
$this->taskDefinition('graduation-15', ['de' => 'Macht ein Foto, auf dem ihr auf die bestandenen Prüfungen anstoßt.', 'en' => 'Take a photo toasting to the passed exams.'], $emotions['Ekstase'], 150),
$this->taskDefinition('graduation-16', ['de' => 'Findet den Ort auf dem Schulgelände, an dem ihr die meiste Zeit verbracht habt.', 'en' => 'Find the place on the school grounds where you spent the most time.'], $emotions['Nostalgie'], 160),
$this->taskDefinition('graduation-17', ['de' => 'Macht ein Foto mit jemandem aus eurem Abschlussball-Komitee oder Organisationsteam.', 'en' => 'Take a photo with someone from your prom committee or organizing team.'], $emotions['Teamgeist'], 170),
$this->taskDefinition('graduation-18', ['de' => 'Fotografiert die Schuhe, die ihr auf dem Abschlussball tragt.', 'en' => 'Photograph the shoes you wear to the prom.'], $emotions['Stolz'], 180),
$this->taskDefinition('graduation-19', ['de' => 'Macht ein Foto, das die Erleichterung nach der letzten Prüfung zeigt.', 'en' => 'Take a photo that shows the relief after the last exam.'], $emotions['Ekstase'], 190),
$this->taskDefinition('graduation-20', ['de' => 'Findet jemanden, der den gleichen Studien- oder Berufswunsch hat.', 'en' => 'Find someone who has the same study or career aspirations.'], $emotions['Teamgeist'], 200),
$this->taskDefinition('graduation-21', ['de' => 'Macht ein Foto, auf dem ihr euren Eltern für ihre Unterstützung dankt.', 'en' => 'Take a photo thanking your parents for their support.'], $emotions['Liebe'], 210),
$this->taskDefinition('graduation-22', ['de' => 'Fotografiert das Cover eures Jahrbuchs.', 'en' => 'Photograph the cover of your yearbook.'], $emotions['Nostalgie'], 220),
$this->taskDefinition('graduation-23', ['de' => 'Macht ein Foto mit jemandem, den ihr erst im letzten Schuljahr richtig kennengelernt habt.', 'en' => 'Take a photo with someone you only really got to know in the last school year.'], $emotions['Überraschung'], 230),
$this->taskDefinition('graduation-24', ['de' => 'Findet die Person mit dem extravagantesten Outfit.', 'en' => 'Find the person with the most extravagant outfit.'], $emotions['Stolz'], 240),
$this->taskDefinition('graduation-25', ['de' => 'Macht ein Foto, das die Freiheit nach der Schule symbolisiert.', 'en' => 'Take a photo that symbolizes freedom after school.'], $emotions['Freude'], 250),
$this->taskDefinition('graduation-26', ['de' => 'Fotografiert einen Lehrer, der sichtlich gerührt ist.', 'en' => 'Photograph a teacher who is visibly moved.'], $emotions['Rührung'], 260),
$this->taskDefinition('graduation-27', ['de' => 'Macht ein Foto mit euren Geschwistern.', 'en' => 'Take a photo with your siblings.'], $emotions['Liebe'], 270),
$this->taskDefinition('graduation-28', ['de' => 'Findet den "Klassenclown" für ein lustiges Foto.', 'en' => 'Find the "class clown" for a funny photo.'], $emotions['Freude'], 280),
$this->taskDefinition('graduation-29', ['de' => 'Macht ein Foto, das eure Freundschaft für immer festhält.', 'en' => 'Take a photo that captures your friendship forever.'], $emotions['Liebe'], 290),
$this->taskDefinition('graduation-30', ['de' => 'Fotografiert die leere Aula oder das leere Klassenzimmer.', 'en' => 'Photograph the empty auditorium or the empty classroom.'], $emotions['Besinnlichkeit'], 300),
$this->taskDefinition('graduation-31', ['de' => 'Macht ein Foto, auf dem ihr so tut, als würdet ihr die Schule "sprengen".', 'en' => 'Take a photo pretending to "blow up" the school.'], $emotions['Ekstase'], 310),
$this->taskDefinition('graduation-32', ['de' => 'Findet jemanden, der während der Rede des Schulleiters eingeschlafen ist.', 'en' => 'Find someone who fell asleep during the principal\'s speech.'], $emotions['Überraschung'], 320),
$this->taskDefinition('graduation-33', ['de' => 'Macht ein Foto mit der Person, von der ihr am meisten abgeschrieben habt (oder umgekehrt).', 'en' => 'Take a photo with the person you copied from the most (or vice versa).'], $emotions['Teamgeist'], 330),
$this->taskDefinition('graduation-34', ['de' => 'Fotografiert die Dekoration der Abschlussfeier.', 'en' => 'Photograph the decoration of the graduation ceremony.'], $emotions['Freude'], 340),
$this->taskDefinition('graduation-35', ['de' => 'Macht ein Foto, das den Sonnenaufgang nach einer langen Partynacht zeigt.', 'en' => 'Take a photo that shows the sunrise after a long night of partying.'], $emotions['Nostalgie'], 350),
$this->taskDefinition('graduation-36', ['de' => 'Findet den Lehrer, der euch am meisten inspiriert hat.', 'en' => 'Find the teacher who inspired you the most.'], $emotions['Rührung'], 360),
$this->taskDefinition('graduation-37', ['de' => 'Macht ein Foto, das euren Traumjob darstellt.', 'en' => 'Take a photo that represents your dream job.'], $emotions['Besinnlichkeit'], 370),
$this->taskDefinition('graduation-38', ['de' => 'Fotografiert die peinlichste Tanz-Einlage des Abends.', 'en' => 'Photograph the most embarrassing dance performance of the evening.'], $emotions['Ekstase'], 380),
$this->taskDefinition('graduation-39', ['de' => 'Macht ein Foto mit jemandem, der plant, die Welt zu bereisen.', 'en' => 'Take a photo with someone who plans to travel the world.'], $emotions['Überraschung'], 390),
$this->taskDefinition('graduation-40', ['de' => 'Findet euren Sitznachbarn aus der letzten Reihe.', 'en' => 'Find your seatmate from the back row.'], $emotions['Nostalgie'], 400),
$this->taskDefinition('graduation-41', ['de' => 'Macht ein Foto, das den Moment des Abschieds von einem guten Freund festhält.', 'en' => 'Take a photo that captures the moment of saying goodbye to a good friend.'], $emotions['Rührung'], 410),
$this->taskDefinition('graduation-42', ['de' => 'Fotografiert das Buffet oder die Getränkebar.', 'en' => 'Photograph the buffet or the beverage bar.'], $emotions['Freude'], 420),
$this->taskDefinition('graduation-43', ['de' => 'Macht ein Foto, das zeigt, wie ihr eure Schulbücher "wegwerft".', 'en' => 'Take a photo that shows you "throwing away" your school books.'], $emotions['Freude'], 430),
$this->taskDefinition('graduation-44', ['de' => 'Findet jemanden, der den gleichen Notendurchschnitt hat wie ihr.', 'en' => 'Find someone who has the same grade point average as you.'], $emotions['Teamgeist'], 440),
$this->taskDefinition('graduation-45', ['de' => 'Macht ein Foto, das die Aufregung vor dem Betreten der Bühne zeigt.', 'en' => 'Take a photo that shows the excitement before going on stage.'], $emotions['Stolz'], 450),
$this->taskDefinition('graduation-46', ['de' => 'Fotografiert die stolzen Gesichter eurer Großeltern.', 'en' => 'Photograph the proud faces of your grandparents.'], $emotions['Rührung'], 460),
$this->taskDefinition('graduation-47', ['de' => 'Macht ein Foto, das "Die Welt gehört uns" schreit.', 'en' => 'Take a photo that screams "The world is ours".'], $emotions['Ekstase'], 470),
$this->taskDefinition('graduation-48', ['de' => 'Findet einen ruhigen Moment und reflektiert über die vergangene Zeit.', 'en' => 'Find a quiet moment and reflect on the past time.'], $emotions['Besinnlichkeit'], 480),
$this->taskDefinition('graduation-49', ['de' => 'Macht ein Foto mit der Person, die ihr am meisten vermissen werdet.', 'en' => 'Take a photo with the person you will miss the most.'], $emotions['Liebe'], 490),
$this->taskDefinition('graduation-50', ['de' => 'Macht ein letztes gemeinsames Foto als "Abschlussklasse von...".', 'en' => 'Take a final group photo as "Graduating Class of...".'], $emotions['Teamgeist'], 500),
],
],
'corporate' => [
'event_type' => ['slug' => 'corporate', 'name' => ['de' => 'Firma', 'en' => 'Corporate'], 'icon' => 'lucide-briefcase'],
'collection' => [
'slug' => 'corporate-classics-2025',
'name' => ['de' => 'Firmen-Aufgaben', 'en' => 'Corporate Tasks'],
'description' => ['de' => '50 Aufgaben für das nächste Firmenevent.', 'en' => '50 tasks for the next corporate event.'],
'is_default' => true,
'position' => 60,
],
'base_tasks' => [
$this->taskDefinition('corporate-1', ['de' => 'Macht ein Foto mit eurem direkten Team.', 'en' => 'Take a photo with your direct team.'], $emotions['Teamgeist'], 10),
$this->taskDefinition('corporate-2', ['de' => 'Findet den CEO oder einen hochrangigen Manager für ein Selfie.', 'en' => 'Find the CEO or a senior manager for a selfie.'], $emotions['Stolz'], 20),
$this->taskDefinition('corporate-3', ['de' => 'Macht ein Foto mit jemandem aus einer anderen Abteilung, den ihr heute kennengelernt habt.', 'en' => 'Take a photo with someone from another department that you met today.'], $emotions['Teamgeist'], 30),
$this->taskDefinition('corporate-4', ['de' => 'Fotografiert das Firmenlogo aus einer kreativen Perspektive.', 'en' => 'Photograph the company logo from a creative perspective.'], $emotions['Stolz'], 40),
$this->taskDefinition('corporate-5', ['de' => 'Macht ein Foto, auf dem ihr auf einen gemeinsamen Erfolg anstoßt.', 'en' => 'Take a photo toasting to a common success.'], $emotions['Stolz'], 50),
$this->taskDefinition('corporate-6', ['de' => 'Findet die Person, die am längsten im Unternehmen ist.', 'en' => 'Find the person who has been with the company the longest.'], $emotions['Nostalgie'], 60),
$this->taskDefinition('corporate-7', ['de' => 'Macht ein Foto mit einem neuen Mitarbeiter.', 'en' => 'Take a photo with a new employee.'], $emotions['Teamgeist'], 70),
$this->taskDefinition('corporate-8', ['de' => 'Fotografiert einen Moment intensiven Networkings.', 'en' => 'Photograph a moment of intense networking.'], $emotions['Besinnlichkeit'], 80),
$this->taskDefinition('corporate-9', ['de' => 'Macht ein Foto, das die Werte eures Unternehmens darstellt.', 'en' => 'Take a photo that represents your company\'s values.'], $emotions['Besinnlichkeit'], 90),
$this->taskDefinition('corporate-10', ['de' => 'Findet die Person mit dem lustigsten Jobtitel.', 'en' => 'Find the person with the funniest job title.'], $emotions['Überraschung'], 100),
$this->taskDefinition('corporate-11', ['de' => 'Macht ein Foto, das die gute Stimmung auf dem Event einfängt.', 'en' => 'Take a photo that captures the good mood at the event.'], $emotions['Freude'], 110),
$this->taskDefinition('corporate-12', ['de' => 'Fotografiert die Präsentation oder Rede, die euch am meisten inspiriert hat.', 'en' => 'Photograph the presentation or speech that inspired you the most.'], $emotions['Besinnlichkeit'], 120),
$this->taskDefinition('corporate-13', ['de' => 'Macht ein Foto mit eurem "Work-Buddy" oder Büro-Freund.', 'en' => 'Take a photo with your "work buddy" or office friend.'], $emotions['Liebe'], 130),
$this->taskDefinition('corporate-14', ['de' => 'Findet das Team, das einen Preis oder eine Auszeichnung gewonnen hat.', 'en' => 'Find the team that won a prize or award.'], $emotions['Stolz'], 140),
$this->taskDefinition('corporate-15', ['de' => 'Macht ein Foto, das "Innovation" symbolisiert.', 'en' => 'Take a photo that symbolizes "innovation".'], $emotions['Überraschung'], 150),
$this->taskDefinition('corporate-16', ['de' => 'Fotografiert das Buffet und stellt euren Lieblingsteller zusammen.', 'en' => 'Photograph the buffet and put together your favorite plate.'], $emotions['Freude'], 160),
$this->taskDefinition('corporate-17', ['de' => 'Macht ein Foto mit jemandem, der die gleiche Krawatte oder das gleiche Kleid trägt.', 'en' => 'Take a photo with someone wearing the same tie or dress.'], $emotions['Überraschung'], 170),
$this->taskDefinition('corporate-18', ['de' => 'Findet die Person, die für die Organisation des Events verantwortlich ist, und bedankt euch.', 'en' => 'Find the person responsible for organizing the event and thank them.'], $emotions['Teamgeist'], 180),
$this->taskDefinition('corporate-19', ['de' => 'Macht ein Foto, das die Internationalität eures Unternehmens zeigt (mit Kollegen aus verschiedenen Ländern).', 'en' => 'Take a photo that shows the internationality of your company (with colleagues from different countries).'], $emotions['Teamgeist'], 190),
$this->taskDefinition('corporate-20', ['de' => 'Fotografiert einen Moment herzhaften Lachens unter Kollegen.', 'en' => 'Photograph a moment of hearty laughter among colleagues.'], $emotions['Freude'], 200),
$this->taskDefinition('corporate-21', ['de' => 'Macht ein Foto, auf dem ihr so tut, als würdet ihr einen wichtigen Vertrag unterzeichnen.', 'en' => 'Take a photo pretending to sign an important contract.'], $emotions['Stolz'], 210),
$this->taskDefinition('corporate-22', ['de' => 'Findet die Person, die am besten tanzen kann.', 'en' => 'Find the person who can dance the best.'], $emotions['Ekstase'], 220),
$this->taskDefinition('corporate-23', ['de' => 'Macht ein Foto, das die "Work-Life-Balance" auf dem Event darstellt.', 'en' => 'Take a photo that represents the "work-life balance" at the event.'], $emotions['Freude'], 230),
$this->taskDefinition('corporate-24', ['de' => 'Fotografiert die Location oder die Dekoration, die euch am besten gefällt.', 'en' => 'Photograph the location or the decoration that you like the most.'], $emotions['Besinnlichkeit'], 240),
$this->taskDefinition('corporate-25', ['de' => 'Macht ein Foto mit eurem Mentor oder jemandem, von dem ihr viel gelernt habt.', 'en' => 'Take a photo with your mentor or someone you have learned a lot from.'], $emotions['Rührung'], 250),
$this->taskDefinition('corporate-26', ['de' => 'Findet die Person, die den weitesten Weg zum Event hatte.', 'en' => 'Find the person who had the longest way to the event.'], $emotions['Stolz'], 260),
$this->taskDefinition('corporate-27', ['de' => 'Macht ein Foto, das einen Moment der Zusammenarbeit zeigt.', 'en' => 'Take a photo that shows a moment of collaboration.'], $emotions['Teamgeist'], 270),
$this->taskDefinition('corporate-28', ['de' => 'Fotografiert die "Goodie-Bag" oder das Werbegeschenk.', 'en' => 'Photograph the "goodie bag" or the promotional gift.'], $emotions['Überraschung'], 280),
$this->taskDefinition('corporate-29', ['de' => 'Macht ein Foto mit jemandem aus dem IT-Support sie sind die wahren Helden.', 'en' => 'Take a photo with someone from IT support they are the real heroes.'], $emotions['Teamgeist'], 290),
$this->taskDefinition('corporate-30', ['de' => 'Findet die Person, die immer Kaffee für alle kocht.', 'en' => 'Find the person who always makes coffee for everyone.'], $emotions['Liebe'], 300),
$this->taskDefinition('corporate-31', ['de' => 'Macht ein Foto, das den Erfolg des letzten Quartals feiert.', 'en' => 'Take a photo that celebrates the success of the last quarter.'], $emotions['Ekstase'], 310),
$this->taskDefinition('corporate-32', ['de' => 'Fotografiert einen Moment, in dem jemand eine anerkennende Rede hält.', 'en' => 'Photograph a moment when someone gives an appreciative speech.'], $emotions['Rührung'], 320),
$this->taskDefinition('corporate-33', ['de' => 'Macht ein Foto, das die Zukunft des Unternehmens symbolisiert.', 'en' => 'Take a photo that symbolizes the future of the company.'], $emotions['Besinnlichkeit'], 330),
$this->taskDefinition('corporate-34', ['de' => 'Findet die Person, die am elegantesten gekleidet ist.', 'en' => 'Find the person who is most elegantly dressed.'], $emotions['Stolz'], 340),
$this->taskDefinition('corporate-35', ['de' => 'Macht ein Foto, das den "Feierabend"-Moment nach dem offiziellen Teil zeigt.', 'en' => 'Take a photo that shows the "end of work" moment after the official part.'], $emotions['Ekstase'], 350),
$this->taskDefinition('corporate-36', ['de' => 'Fotografiert die Visitenkarten, die ihr gesammelt habt.', 'en' => 'Photograph the business cards you have collected.'], $emotions['Nostalgie'], 360),
$this->taskDefinition('corporate-37', ['de' => 'Macht ein Foto mit jemandem, mit dem ihr nur per E-Mail kommuniziert habt und den ihr jetzt persönlich trefft.', 'en' => 'Take a photo with someone you have only communicated with via email and whom you are now meeting in person.'], $emotions['Überraschung'], 370),
$this->taskDefinition('corporate-38', ['de' => 'Findet die Person, die am meisten zum Erfolg eures letzten Projekts beigetragen hat.', 'en' => 'Find the person who contributed the most to the success of your last project.'], $emotions['Stolz'], 380),
$this->taskDefinition('corporate-39', ['de' => 'Macht ein Foto, das die entspannte Seite eures Chefs zeigt.', 'en' => 'Take a photo that shows the relaxed side of your boss.'], $emotions['Überraschung'], 390),
$this->taskDefinition('corporate-40', ['de' => 'Fotografiert die Band oder den DJ.', 'en' => 'Photograph the band or the DJ.'], $emotions['Freude'], 400),
$this->taskDefinition('corporate-41', ['de' => 'Macht ein Foto, das den Team-Zusammenhalt perfekt einfängt.', 'en' => 'Take a photo that perfectly captures team spirit.'], $emotions['Teamgeist'], 410),
$this->taskDefinition('corporate-42', ['de' => 'Findet einen ehemaligen Mitarbeiter, der zu Besuch ist.', 'en' => 'Find a former employee who is visiting.'], $emotions['Nostalgie'], 420),
$this->taskDefinition('corporate-43', ['de' => 'Macht ein Foto, das eure Motivation für das nächste Geschäftsjahr zeigt.', 'en' => 'Take a photo that shows your motivation for the next business year.'], $emotions['Stolz'], 430),
$this->taskDefinition('corporate-44', ['de' => 'Fotografiert einen Moment, in dem neue Ideen gesponnen werden.', 'en' => 'Photograph a moment when new ideas are being spun.'], $emotions['Besinnlichkeit'], 440),
$this->taskDefinition('corporate-45', ['de' => 'Macht ein Foto mit der Person, die euch heute am meisten zum Lachen gebracht hat.', 'en' => 'Take a photo with the person who made you laugh the most today.'], $emotions['Freude'], 450),
$this->taskDefinition('corporate-46', ['de' => 'Findet die "gute Seele" eurer Abteilung.', 'en' => 'Find the "good soul" of your department.'], $emotions['Liebe'], 460),
$this->taskDefinition('corporate-47', ['de' => 'Macht ein Foto, das die Erleichterung nach einer erfolgreichen Präsentation zeigt.', 'en' => 'Take a photo that shows the relief after a successful presentation.'], $emotions['Ekstase'], 470),
$this->taskDefinition('corporate-48', ['de' => 'Fotografiert einen rührenden Moment, z.B. die Verabschiedung eines langjährigen Kollegen.', 'en' => 'Photograph a touching moment, e.g. the farewell of a long-standing colleague.'], $emotions['Rührung'], 480),
$this->taskDefinition('corporate-49', ['de' => 'Macht ein Foto, das zeigt, dass eure Firma mehr als nur ein Arbeitsplatz ist.', 'en' => 'Take a photo that shows that your company is more than just a place to work.'], $emotions['Liebe'], 490),
$this->taskDefinition('corporate-50', ['de' => 'Macht ein letztes Gruppenfoto, das die Energie des Events festhält.', 'en' => 'Take a final group photo that captures the energy of the event.'], $emotions['Teamgeist'], 500),
],
],
];
}
private function autoTaskSeeds(): array
private function taskDefinition(string $slug, array $title, ?array $emotion, int $sortOrder): array
{
return [
'wedding' => [
$this->autoSeed('dancefloor',
['de' => 'Dancefloor-Glück #{n}', 'en' => 'Dancefloor joy #{n}'],
['de' => 'Fange eine wilde Tanzszene ein, die die Energie der Gäste zeigt.', 'en' => 'Capture a wild dance scene packed with guest energy.'],
['de' => 'Nutze eine lange Belichtungszeit für Lichtstreifen.', 'en' => 'Use a longer exposure to create light trails.'],
['name' => ['de' => 'Ekstase', 'en' => 'Euphoria'], 'icon' => 'lucide-stars', 'color' => '#a855f7'],
'medium'
),
$this->autoSeed('sparkler',
['de' => 'Wunderkerzen-Story #{n}', 'en' => 'Sparkler story #{n}'],
['de' => 'Erzähle die Geschichte eines funkelnden Moments mit mindestens drei Bildern.', 'en' => 'Tell the story of a sparkling moment in three frames.'],
['de' => 'Variiere zwischen Detailaufnahme, Halbtotaler und Reaktion.', 'en' => 'Mix a detail shot, a medium frame, and a reaction close-up.'],
['name' => ['de' => 'Staunen', 'en' => 'Awe'], 'icon' => 'lucide-wand', 'color' => '#f97316'],
'medium'
),
$this->autoSeed('first-dance-detail',
['de' => 'Detail beim Hochzeitstanz #{n}', 'en' => 'First-dance detail #{n}'],
['de' => 'Suche ein kleines Detail während des Hochzeitstanzes Hände, Schuhe, Accessoires.', 'en' => 'Spot a tiny detail during the first dance hands, shoes or accessories.'],
['de' => 'Nutze starkes Bokeh für den Hintergrund.', 'en' => 'Use heavy bokeh to blur the background.'],
['name' => ['de' => 'Zärtlichkeit', 'en' => 'Tenderness'], 'icon' => 'lucide-feather', 'color' => '#fb7185'],
'easy'
),
$this->autoSeed('guest-story',
['de' => 'Gästegeschichte #{n}', 'en' => 'Guest story #{n}'],
['de' => 'Dokumentiere eine Gruppe von Gästen, wie sie miteinander interagiert.', 'en' => 'Document a group of guests interacting naturally.'],
['de' => 'Fotografiere die Gruppe aus zwei Perspektiven.', 'en' => 'Capture the group from two perspectives.'],
['name' => ['de' => 'Freundschaft', 'en' => 'Friendship'], 'icon' => 'lucide-users', 'color' => '#38bdf8'],
'easy'
),
],
'birthday' => [
$this->autoSeed('candle-wish',
['de' => 'Kerzenwunsch #{n}', 'en' => 'Candle wish #{n}'],
['de' => 'Halte den Moment fest, in dem der Wunsch ausgesprochen wird.', 'en' => 'Capture the second the wish is made.'],
['de' => 'Lass das Motiv in den Kerzenlichtschein eintauchen.', 'en' => 'Bathe the scene in candlelight glow.'],
['name' => ['de' => 'Freude', 'en' => 'Joy'], 'icon' => 'lucide-sparkles', 'color' => '#facc15'],
'easy'
),
$this->autoSeed('gift-reaction',
['de' => 'Geschenk-Reaktion #{n}', 'en' => 'Gift reaction #{n}'],
['de' => 'Fange die spontanste Reaktion auf ein Geschenk ein.', 'en' => 'Capture the most spontaneous gift reaction.'],
['de' => 'Versuche eine Serienaufnahme für echte Emotionen.', 'en' => 'Use burst mode for authentic emotion.'],
['name' => ['de' => 'Überraschung', 'en' => 'Surprise'], 'icon' => 'lucide-gift', 'color' => '#f472b6'],
'easy'
),
$this->autoSeed('birthday-anthem',
['de' => 'Geburtstagshymne #{n}', 'en' => 'Birthday anthem #{n}'],
['de' => 'Dokumentiere das Mitsingen eines Liedes inklusive Stimmung im Raum.', 'en' => 'Document everyone singing a song and the overall mood.'],
['de' => 'Fokussiere auf die Person, die am lautesten singt.', 'en' => 'Focus on whoever sings the loudest.'],
['name' => ['de' => 'Lebensfreude', 'en' => 'Delight'], 'icon' => 'lucide-music', 'color' => '#60a5fa'],
'medium'
),
],
'christmas' => [
$this->autoSeed('ornament-closeup',
['de' => 'Ornament-Kunstwerk #{n}', 'en' => 'Ornament art #{n}'],
['de' => 'Inszeniere ein besonderes Ornament in Nahaufnahme.', 'en' => 'Stage a special ornament in a moody close-up.'],
['de' => 'Lass warme Lichter im Hintergrund bokeh-artig wirken.', 'en' => 'Let warm lights blur softly in the background.'],
['name' => ['de' => 'Staunen', 'en' => 'Wonder'], 'icon' => 'lucide-sparkles', 'color' => '#38bdf8'],
'easy'
),
$this->autoSeed('carol-chorus',
['de' => 'Singender Chor #{n}', 'en' => 'Carolling chorus #{n}'],
['de' => 'Zeige eine Gruppe beim Singen eines Weihnachtsliedes.', 'en' => 'Highlight a group singing a seasonal song.'],
['de' => 'Nutze eine Panorama-Aufnahme für alle Beteiligten.', 'en' => 'Use a panorama framing to include everyone.'],
['name' => ['de' => 'Gemeinschaft', 'en' => 'Togetherness'], 'icon' => 'lucide-users', 'color' => '#22c55e'],
'medium'
),
$this->autoSeed('wishlist-doodle',
['de' => 'Wunschlisten-Doodle #{n}', 'en' => 'Wishlist doodle #{n}'],
['de' => 'Fotografiere eine improvisierte Wunschliste inklusive Zeichnungen.', 'en' => 'Photograph an improvised wishlist complete with doodles.'],
['de' => 'Lege die Liste auf Holz- oder Stoffoberflächen für Wärme.', 'en' => 'Place the list on wood or fabric for extra warmth.'],
['name' => ['de' => 'Hoffnung', 'en' => 'Hope'], 'icon' => 'lucide-heart', 'color' => '#f97316'],
'easy'
),
],
'corporate' => [
$this->autoSeed('team-brainstorm',
['de' => 'Brainstorm-Blitzlicht #{n}', 'en' => 'Brainstorm spotlight #{n}'],
['de' => 'Halte eine kreative Idee auf einem Whiteboard plus das Team dahinter fest.', 'en' => 'Capture a clever whiteboard idea with the team behind it.'],
['de' => 'Arbeite mit Spiegelungen im Glas oder Bildschirm.', 'en' => 'Play with reflections on glass or screens.'],
['name' => ['de' => 'Innovation', 'en' => 'Innovation'], 'icon' => 'lucide-lightbulb', 'color' => '#facc15'],
'medium'
),
$this->autoSeed('watercooler-moment',
['de' => 'Watercooler-Moment #{n}', 'en' => 'Watercooler moment #{n}'],
['de' => 'Zeige Kollegen beim lockeren Austausch abseits des Meetings.', 'en' => 'Show teammates chatting casually away from the meeting table.'],
['de' => 'Fokussiere auf Gestik und Körpersprache.', 'en' => 'Focus on gestures and body language.'],
['name' => ['de' => 'Leichtigkeit', 'en' => 'Ease'], 'icon' => 'lucide-coffee', 'color' => '#60a5fa'],
'easy'
),
$this->autoSeed('celebration-confetti',
['de' => 'Konfetti-Erfolg #{n}', 'en' => 'Confetti success #{n}'],
['de' => 'Inszeniere einen kleinen Konfettiwurf als Symbol für Team-Erfolg.', 'en' => 'Stage a mini confetti throw to celebrate team success.'],
['de' => 'Arbeite mit schneller Verschlusszeit für eingefrorene Partikel.', 'en' => 'Use a fast shutter to freeze the confetti.'],
['name' => ['de' => 'Erfolg', 'en' => 'Success'], 'icon' => 'lucide-flag', 'color' => '#a855f7'],
'medium'
),
],
'default' => [
$this->autoSeed('story-fragments',
['de' => 'Story-Fragmente #{n}', 'en' => 'Story fragments #{n}'],
['de' => 'Finde drei kleine Details, die zusammen eine Geschichte ergeben.', 'en' => 'Find three small details that build one story.'],
['de' => 'Kombiniere Nahaufnahmen mit einem Übersichtsfoto.', 'en' => 'Combine close-ups with one establishing shot.'],
['name' => ['de' => 'Neugier', 'en' => 'Curiosity'], 'icon' => 'lucide-eye', 'color' => '#38bdf8'],
'easy'
),
],
];
}
private function taskDefinition(
string $slug,
array $title,
array $description,
array $example,
?array $emotion,
string $difficulty,
int $sortOrder
): array {
return [
'slug' => $slug,
'title' => $title,
'description' => $description,
'example' => $example,
'description' => null,
'example' => null,
'emotion' => $emotion,
'difficulty' => $difficulty,
'difficulty' => 'easy',
'sort_order' => $sortOrder,
];
}
private function autoSeed(
string $slug,
array $title,
array $description,
array $example,
?array $emotion,
string $difficulty
): array {
return [
'slug' => $slug,
'title' => $title,
'description' => $description,
'example' => $example,
'emotion' => $emotion,
'difficulty' => $difficulty,
];
}
private function upsertTask(TaskCollection $collection, EventType $eventType, array $definition, int $sortOrder): Task
{
$emotion = $this->ensureEmotion($definition['emotion'] ?? [], $eventType->id);
@@ -464,81 +481,6 @@ class TaskCollectionsSeeder extends Seeder
return $task;
}
private function ensureMinimumTasks(
TaskCollection $collection,
EventType $eventType,
array &$syncPayload,
int $existingCount,
int $minimum,
string $eventTypeSlug
): void {
$needed = $minimum - $existingCount;
if ($needed <= 0) {
return;
}
$seeds = $this->autoTaskSeeds()[$eventTypeSlug] ?? $this->autoTaskSeeds()['default'];
if (empty($seeds)) {
$seeds = $this->autoTaskSeeds()['default'];
}
$baseCount = $existingCount;
for ($i = 0; $i < $needed; $i++) {
$seed = $seeds[$i % count($seeds)];
$sequence = $baseCount + $i + 1;
$slug = Str::slug(sprintf('%s-%s-%s', $eventType->slug ?? $eventTypeSlug, $seed['slug'], $sequence));
$taskDefinition = [
'slug' => $slug,
'title' => [
'de' => str_replace('{n}', (string) $sequence, $seed['title']['de']),
'en' => str_replace('{n}', (string) $sequence, $seed['title']['en']),
],
'description' => [
'de' => str_replace('{n}', (string) $sequence, $seed['description']['de']),
'en' => str_replace('{n}', (string) $sequence, $seed['description']['en']),
],
'example' => [
'de' => str_replace('{n}', (string) $sequence, $seed['example']['de']),
'en' => str_replace('{n}', (string) $sequence, $seed['example']['en']),
],
'emotion' => $seed['emotion'] ?? null,
'difficulty' => $seed['difficulty'] ?? 'easy',
'priority' => $seed['priority'] ?? 'medium',
'sort_order' => 500 + ($sequence * 5),
];
$task = $this->upsertTask($collection, $eventType, $taskDefinition, $taskDefinition['sort_order']);
$syncPayload[$task->id] = ['sort_order' => $taskDefinition['sort_order']];
}
}
private function assignOrphanTasks(array $collectionMap): void
{
if (empty($collectionMap)) {
return;
}
Task::whereNull('collection_id')
->orderBy('id')
->chunkById(100, function ($tasks) use ($collectionMap) {
foreach ($tasks as $task) {
$collection = $collectionMap[$task->event_type_id] ?? Arr::first($collectionMap);
if (! $collection) {
continue;
}
$task->collection_id = $collection->id;
$task->save();
$collection->tasks()->syncWithoutDetaching([
$task->id => ['sort_order' => $task->sort_order ?? 0],
]);
}
});
}
protected function ensureEventType(array $definition): EventType
{
return EventType::updateOrCreate(
@@ -586,4 +528,4 @@ class TaskCollectionsSeeder extends Seeder
return $emotion;
}
}
}

21
docs/agents/codegen.md Normal file
View File

@@ -0,0 +1,21 @@
# Codegen Agent Operating Guide
## Mission & Scope
- Implement application code, tests, and supporting docs focused on scoped backlog items.
- Maintain adherence to repository guardrails from `AGENTS.md` and package-specific conventions.
## Tooling Checklist
- **Laravel Boost MCP**
- Preferred bridge for project-aware tooling. When you need the canonical Artisan command list (e.g., before running migrations, queues, or custom tasks), call `list-artisan-commands` via Boost instead of relying on manual `php artisan list`.
- Responses arrive as structured JSON, making it easy to filter or search before acting.
- Example (pseudo):
```
const commands = await tools.laravelBoost.listArtisanCommands();
```
- Use the same MCP server for other Boost capabilities (database info, logs, URL helpers) whenever a workflow can benefit from project-specific context.
- **Apply Patch Workflow**
- Default to the `apply_patch` tool for targeted edits; prefer command-line formatters such as `vendor/bin/pint --dirty` only after coding tasks.
## Operational Notes
- Keep changes focused and reversible; document significant behavior shifts in the relevant `docs/*` or PRP files when surfaces change.
- When tasks exceed scope, record follow-ups in `docs/todo/` rather than expanding the current patch set.

View File

@@ -0,0 +1,153 @@
# 10 kreative Fotoaufgaben für eure Hochzeit Ideen, die Spaß machen und Emotionen wecken
Jede Hochzeit erzählt ihre eigene Geschichte aber oft fehlen genau die Fotos, die das echte Gefühl des Tages zeigen: das spontane Lachen, die liebevollen Blicke, die kleinen Missgeschicke, die später zu euren Lieblingsmomenten werden.
Die Lösung: **Fotoaufgaben für Gäste!**
Mit etwas Planung und Humor verwandelt ihr euer Fest in ein interaktives Foto-Abenteuer. Eure Gäste werden zu aktiven Mitgestaltern und ihr bekommt eine Vielfalt an Bildern, die kein Profi allein hätte einfangen können.
In diesem Artikel findest du 10 kreative Aufgaben, praktische Tipps zur Umsetzung und erfährst, wie **unsere Fotospiel App** das Ganze kinderleicht macht.
---
## 💍 Warum Fotoaufgaben der Geheimtipp für echte Emotionen sind
Viele Hochzeitsgäste machen ohnehin Fotos aber ohne Ziel oder Struktur. Fotoaufgaben geben ihnen **einen spielerischen Anlass**, die Kamera (oder das Handy) zu zücken.
Das führt zu:
- mehr **Interaktion zwischen Gästen**,
- **authentischeren Momenten**,
- und einem Hochzeitsalbum, das vor Persönlichkeit sprüht.
Mit der **Fotospiel App** könnt ihr diese Aufgaben direkt als kleine Missionen anlegen. Gäste scannen einfach euren QR-Code, sehen die Aufgaben und laden ihre Ergebnisse hoch in Echtzeit und völlig unkompliziert.
---
## 🎯 So funktioniert das Prinzip
1. **Aufgaben anlegen** in der App oder auf kleinen Karten an den Tischen.
2. **Gäste animieren**, mitzuspielen (zum Beispiel durch Preise oder Lob).
3. **Fotos hochladen lassen** automatisch gesammelt in eurer Hochzeitsgalerie.
4. **Live-Slideshow starten** für Lacher und „Oh wie schön!“-Momente.
**Praxis-Tipp:** Starte mit 1015 Aufgaben genug für Abwechslung, aber nicht zu viele, damit kein Stress entsteht.
---
## 📸 Die 10 besten Fotoaufgaben für eure Hochzeit
Hier kommen sie charmant, witzig, emotional und garantiert gästetauglich.
---
### 1. Das glücklichste Lächeln des Tages 😄
**Aufgabe:** „Fang das schönste Lachen ein, das du heute siehst!“
Diese Aufgabe öffnet Herzen. Gäste achten plötzlich auf die Stimmung anderer und fangen ehrliche, natürliche Emotionen ein.
**Tipp:** Ideal für den Nachmittag, wenn die Stimmung aufblüht.
---
### 2. Das verrückteste Tanzfoto 💃🕺
**Aufgabe:** „Mach ein Foto vom wildesten Tänzer auf der Party!“
Sorgt für Bewegung, Spaß und jede Menge Energie in eurer Galerie.
**Praxis-Tipp:** Platziere den QR-Code in der Nähe der Tanzfläche, damit Gäste ihn direkt scannen können.
---
### 3. Der geheime Star des Abends 🌟
**Aufgabe:** „Wer ist heute der heimliche Star? Mach ein Foto von ihm oder ihr!“
Ein schöner Eisbrecher, gerade für Gäste, die sich noch nicht kennen.
**Variante:** Lass sie ein Selfie mit der Person machen doppelte Freude!
---
### 4. Das schönste Accessoire 🎀
**Aufgabe:** „Fotografiere das stylischste oder außergewöhnlichste Accessoire des Abends.“
Das können Schuhe, Krawatten, Ohrringe oder Blumen sein kleine Details, die oft übersehen werden.
**Praxis-Tipp:** Funktioniert super als Ergänzung zu professionellen Deko- oder Modefotos.
---
### 5. Der emotionalste Moment 😢❤️
**Aufgabe:** „Halte einen Moment fest, der dich berührt.“
Ergebnisse: herzerwärmende Umarmungen, Tränen, Gesten Fotos mit Seele.
**Variante:** Ideal während der Trauung oder beim Eröffnungstanz.
---
### 6. Das Brautpaar aus eurer Sicht 💑
**Aufgabe:** „Mach ein Foto vom Brautpaar so, wie du sie siehst.“
Jede Perspektive ist anders: witzig, romantisch, kreativ.
**Praxis-Tipp:** Sorgt später für eine wunderschöne Collage in der Galerie.
---
### 7. Generationenbild 👵👶
**Aufgabe:** „Fotografiere mindestens drei Generationen auf einem Bild!“
Ein Klassiker, der berührt und gleichzeitig für lustige Situationen sorgt.
**Tipp:** Funktioniert am besten am Nachmittag oder bei Gruppenfotos.
---
### 8. Das kulinarische Highlight 🍰
**Aufgabe:** „Zeig uns das leckerste Detail des Buffets oder der Torte!“
Gäste lieben es, Essen zu fotografieren. Und ihr bekommt wunderschöne Food-Fotos.
**Praxis-Tipp:** Platziere den QR-Code am Buffet, um spontane Uploads zu fördern.
---
### 9. Das lustigste Gruppenfoto 🤪
**Aufgabe:** „Sammle mindestens fünf Gäste für ein verrücktes Gruppenfoto!“
Dieser Klassiker sorgt für Bewegung, Lachen und Community-Feeling.
**Tipp:** Füge Requisiten hinzu (Hüte, Schilder, Brillen) vielleicht direkt bei der **Fotobox**.
---
### 10. Das letzte Foto des Abends 🌙
**Aufgabe:** „Mach das allerletzte Foto, bevor du gehst.“
So entsteht eine charmante Abschlussserie von müden, glücklichen, tanzenden Menschen.
**Praxis-Tipp:** Perfekt, wenn ihr später beim Durchsehen das „große Finale“ eurer Feier nacherleben wollt.
---
## 🧠 Bonus-Ideen für Extra-Spaß
- **Best-of-Wettbewerb:** Wählt am nächsten Tag das „beste Gastfoto“ vielleicht mit einem kleinen Preis.
- **Live-Anzeige:** Aktiviert in der Fotospiel App die Slideshow-Funktion, um die besten Schnappschüsse auf dem Bildschirm zu zeigen.
- **Deko-Tipp:** Gestaltet eine kleine „Foto-Challenge-Wand“ mit QR-Codes zu den Aufgaben.
**Praxis-Tipp:** Vermeide Aufgaben, die Druck erzeugen oder Gäste überfordern („Fotografiere jeden Tisch!“). Freiwilligkeit sorgt für bessere Bilder und gute Laune.
---
## 📷 Wie die Fotospiel App euch hilft
Mit der **Fotospiel App** werden all diese Aufgaben digital verwaltet und spielerisch umgesetzt:
1. Du legst jede Aufgabe als *Mission* an.
2. Gäste scannen den Event-QR-Code.
3. Sie sehen alle Aufgaben, wählen eine aus und laden ihr Bild hoch.
4. Die App speichert alles automatisch in eurer privaten Online-Galerie.
5. Ihr könnt kommentieren, liken oder die schönsten Fotos direkt herunterladen.
Keine App-Installation nötig, keine komplizierten Tools nur Spaß, Interaktion und echte Erinnerungen.
---
## 🔒 Datenschutz & Komfort
Natürlich ist Datenschutz bei Gastfotos ein sensibles Thema.
Mit unserer App bleibt alles privat:
- Nur Gäste mit Event-Zugang haben Zugriff.
- Du entscheidest, ob Fotos moderiert werden müssen.
- Nach dem Event kannst du alles löschen oder archivieren.
**Praxis-Tipp:** Weise beim Start deines Events kurz darauf hin, dass Fotos nur intern geteilt werden. So fühlen sich alle sicher.
---
## ❤️ Fazit
Fotoaufgaben sind der Geheimtipp für lebendige Hochzeitsfotos.
Sie holen alle Gäste ab, fördern Emotionen und schaffen unvergessliche Momente.
Mit etwas Kreativität, klaren Aufgaben und unserer **Fotospiel App** entsteht eine Galerie voller Leben von der Trauung bis zur letzten Tanzrunde.
👉 **Erstelle jetzt dein eigenes Hochzeits-Event in der Fotospiel App**, richte deine ersten Fotoaufgaben ein und lass deine Gäste zu den kreativsten Fotograf:innen eures großen Tages werden.

View File

@@ -0,0 +1,115 @@
# Top-Alternativen zum Hochzeitsfotografen So bekommst du echte Erinnerungen ohne Profi-Shooting
Ein professioneller Fotograf ist toll aber nicht jede Hochzeit braucht ein teures Fotoshooting. Vielleicht möchtet ihr lieber spontan, kreativ oder budgetbewusst feiern.
Gute Nachrichten: Es gibt viele Wege, großartige Hochzeitsbilder zu bekommen, ohne dass ihr ein Vermögen ausgebt.
Hier findest du **praktische Ideen, kreative Alternativen und echte Erfahrungs-Tipps**, wie du mit unserer **Fotospiel App** trotzdem eine einzigartige Hochzeitsgalerie erhältst.
---
## 💡 Warum Alternativen funktionieren
Das Wichtigste zuerst: Emotion schlägt Perfektion.
Oft sind es die spontanen, ungestellten Fotos, die euer Herz berühren nicht die inszenierten Posen.
Eure Freunde, Familie und Gäste sind mittendrin statt nur dabei.
Wenn du sie aktiv einbindest, bekommst du Bilder, die nicht nur zeigen, *wie* es aussah, sondern *wie* es sich anfühlte.
---
## 📱 1. Mach deine Gäste zu Fotograf:innen mit unserer Fotospiel App
Unsere **Fotospiel App** verwandelt deine Gäste in ein kreatives Foto-Team.
Du erstellst kleine Aufgaben sogenannte *Foto-Missionen* und verteilst sie an alle, die mitmachen möchten.
Zum Beispiel:
> „Macht ein Selfie mit dem Brautpaar!“
> „Fotografiert das schönste Lächeln auf der Tanzfläche.“
> „Zeigt uns das verrückteste Paar beim Tanzen!“
Jede Mission wird automatisch über den QR-Code gestartet.
Gäste laden ihre Fotos hoch, und du bekommst eine wachsende Galerie voller Leben und Emotionen.
**Praxis-Tipp:** Drucke QR-Codes auf Tischnummern, Getränkekarten oder das Willkommensschild. So findet jede:r den Zugang zur Galerie ohne App-Installation, ganz einfach per Scan.
---
## 🎞️ 2. Die klassische Einwegkamera Retro, charmant, unkompliziert
Einwegkameras sind wieder im Trend! Sie bringen Nostalgie auf eure Tische und sorgen für viele Überraschungsmomente.
Gäste lieben es, unbemerkt kleine Szenen einzufangen manchmal entstehen daraus die ehrlichsten Bilder des Abends.
**Praxis-Tipps:**
- Lege 12 Kameras pro Tisch bereit, am besten mit einem kleinen Schild:
> „Bitte fotografiere, was dich glücklich macht!“
- Lass die Filme nach der Feier entwickeln und digitalisieren dann kannst du sie in deine Fotospiel-Galerie hochladen.
- Mache ein Foto der Kamera *mit Tischnummer*, bevor du sie einsammelst das hilft beim Zuordnen später.
---
## 🤳 3. Fotobox & Selfie-Station Unterhaltung mit Erinnerungswert
Eine Fotobox (Photo Booth) ist die ideale Mischung aus Spaß und professionellem Look.
Gäste lieben es, dort kreativ zu werden mit Requisiten, Licht und Freunden.
Viele Boxen speichern die Fotos automatisch digital, sodass du sie später bequem in die **Fotospiel App** importieren kannst.
**Praxis-Tipps:**
- Platziere den QR-Code der App direkt neben der Fotobox.
- Richte eine kleine Deko-Ecke ein (Lichterkette, Vorhang, Blumen).
- Lass Gäste *„Challenge-Karten“* ziehen, z. B. „Mach ein Bild mit drei verschiedenen Generationen“.
So entstehen witzige, unerwartete Serien, die sonst kein Fotograf festgehalten hätte.
---
## 📸 4. Freunde mit guten Kameras einbinden
In fast jeder Clique gibt es jemanden, der gerne fotografiert.
Bitten kostet nichts und oft freuen sich Hobbyfotograf:innen, wenn sie gefragt werden.
Plane vorher gemeinsam, wer welche Momente abdeckt:
- Person A: Trauung
- Person B: Sektempfang
- Person C: Partyabend
**Praxis-Tipp:** Gib ihnen ein paar inhaltliche Hinweise, aber keine strikten Anweisungen. Authentizität schlägt Kontrolle.
---
## 🕹️ 5. Kombiniere alle Ideen zu einem Gesamtkonzept
Die wahre Magie entsteht, wenn du diese Alternativen kombinierst.
Ein mögliches Konzept:
| Bereich | Lösung | Ergebnis |
|----------|--------|-----------|
| Offizielle Fotos | 1 Stunde Profi-Fotograf | Hochwertige Paarbilder |
| Emotionale Momente | Gäste mit Fotospiel App | Spontane Perspektiven |
| Unterhaltung | Fotobox | Spaß und Dynamik |
| Nostalgie | Einwegkameras | Analoger Charme |
So entsteht ein vielseitiges Album, das nicht nur technisch gut ist, sondern euch und eure Gäste wirklich widerspiegelt.
---
## 🔒 Datenschutz & Kontrolle
Unsere **Fotospiel App** sorgt dafür, dass alle Fotos **privat und sicher** bleiben:
- Nur Gäste mit QR-Code haben Zugriff.
- Du kannst Fotos vor Veröffentlichung prüfen.
- Nach der Hochzeit kannst du die Galerie schließen oder löschen.
Das gibt dir volle Kontrolle ohne Chaos, ohne Risiko.
---
## 💬 Erfahrungsbeispiel
> „Wir hatten keinen Fotografen, nur die App, eine Fotobox und Einwegkameras das Ergebnis war unglaublich! So viele echte Momente, so viel Lachen. Wir würden es genauso wieder machen.“
> — *Lena & Tobias, Herbsthochzeit 2023*
---
## 🎯 Fazit & Call-to-Action
Du brauchst keinen Profi, um unvergessliche Fotos zu haben du brauchst Menschen, die dir am Herzen liegen, und ein gutes System, um ihre Bilder zu sammeln.
Mit einer Kombination aus **Fotospiel App**, **Fotoboxen** und **Einwegkameras** schaffst du genau das: echte Emotionen, Vielfalt und Spaß.
👉 **Starte dein Event in der Fotospiel App**, drucke deine QR-Codes und lade deine Gäste ein, Teil eurer Geschichte zu werden.
Denn das schönste Hochzeitsalbum ist das, das ihr gemeinsam gestaltet.

View File

@@ -0,0 +1,168 @@
# Datenschutz bei Eventfotos Was du wissen musst (verständlich erklärt)
Ein rauschendes Fest, fröhliche Menschen, unzählige Kameras und schon schwebt die Frage im Raum:
**Darf man das eigentlich alles fotografieren und teilen?**
Seit die DSGVO gilt, sind viele Gastgeber und Veranstalter verunsichert. Doch keine Sorge: Mit gesundem Menschenverstand, klarer Kommunikation und ein paar einfachen Regeln kannst du Erinnerungen festhalten, ohne gegen Datenschutzrecht zu verstoßen.
In diesem Artikel erfährst du, was erlaubt ist, was nicht und wie **unsere Fotospiel App** dich dabei unterstützt, Eventfotos sicher und stressfrei zu sammeln.
---
## 💡 Warum Datenschutz bei Fotos wichtig ist
Ein Foto ist mehr als ein Bild es ist ein personenbezogenes Datum.
Wer zu sehen ist, kann identifiziert werden. Deshalb gilt: Sobald du Fotos sammelst, speicherst oder veröffentlichst, musst du die Rechte der abgebildeten Personen respektieren.
Ziel der DSGVO ist nicht, Erinnerungen zu verbieten, sondern sie **bewusst** zu gestalten.
Das bedeutet: informieren, Einwilligungen respektieren, Daten sicher verwalten.
---
## ⚖️ Die rechtliche Grundlage einfach erklärt
Es gibt im Wesentlichen zwei Wege, wie Fotos auf Events rechtlich sauber sind:
### 1. **Einwilligung der abgebildeten Personen (§ 6 Abs. 1 lit. a DSGVO)**
Die klassische Zustimmung: Menschen wissen, dass fotografiert wird, und sind einverstanden.
Das kann mündlich oder schriftlich erfolgen Hauptsache, es ist nachvollziehbar.
**Praxis-Tipps:**
- Weise am Eingang oder in der Einladung darauf hin:
> „Auf dieser Veranstaltung werden Fotos gemacht, die nur privat geteilt werden.“
- Vermeide heimliches Fotografieren.
- Gib Gästen die Möglichkeit, höflich „nein“ zu sagen.
### 2. **Berechtigtes Interesse (§ 6 Abs. 1 lit. f DSGVO)**
Bei größeren Veranstaltungen ist eine individuelle Einwilligung oft unpraktisch.
Dann darf fotografiert werden, wenn das Interesse an Erinnerungsfotos **überwiegt**, z. B. bei Hochzeiten, Firmenfeiern oder Jubiläen solange niemand bloßgestellt wird.
**Praxis-Tipps:**
- Fotografiere Szenen, nicht einzelne Personen ohne Kontext.
- Verzichte auf unvorteilhafte Motive.
- Respektiere sofort, wenn jemand keine Fotos möchte.
---
## 📱 Wie die Fotospiel App Datenschutz vereinfacht
Viele Unsicherheiten entstehen durch unkontrollierte WhatsApp-Gruppen, Clouds oder Social Media.
Unsere **Fotospiel App** bietet eine strukturierte, sichere Alternative:
### 🔒 Geschlossene Events
Nur wer den QR-Code oder Einladungslink hat, kann Fotos sehen oder hochladen.
Keine öffentliche Auffindbarkeit, keine Suchmaschinen.
### 🧾 Einwilligung durch Handlung
Beim Hochladen akzeptieren Gäste automatisch, dass ihre Fotos **innerhalb des Events** geteilt werden nicht öffentlich.
### 🛡️ Serverstandort & Sicherheit
Alle Daten liegen auf Servern in Deutschland nach DSGVO-Standard.
Übertragung via HTTPS, keine versteckte Weitergabe an Dritte.
### 🧹 Löschfristen & Kontrolle
Als Veranstalter:in entscheidest du, wann Fotos gelöscht werden.
Du kannst jederzeit:
- Bilder entfernen,
- Gäste sperren,
- das gesamte Event schließen oder exportieren.
---
## 📷 Privates Event vs. öffentliches Event
| Art des Events | Beschreibung | Datenschutz-Regel |
|----------------|---------------|--------------------|
| **Privat (Hochzeit, Geburtstag)** | geschlossene Gästeliste, persönliche Atmosphäre | Einwilligung meist durch Teilnahme oder Hinweis abgedeckt |
| **Halb-öffentlich (Firmenfeier, Messe)** | Mitarbeitende, externe Partner | schriftlicher Hinweis + Moderation empfohlen |
| **Öffentlich (Festival, Straßenfest)** | frei zugänglich für alle | deutlicher Aushang + ggf. Presse- oder Veranstalterregelung |
**Praxis-Tipp:**
Bei internen Firmenfeiern reicht meist ein sichtbarer Hinweis:
> „Heute wird fotografiert die Bilder dienen der internen Erinnerung.“
Bei öffentlichen Events sollte zusätzlich auf Social-Media-Veröffentlichungen hingewiesen werden.
---
## 🧠 Häufige Irrtümer
**„Wenn ich die Fotos nicht verkaufe, ist es egal.“**
❌ Falsch. Auch private Fotos unterliegen der DSGVO, wenn sie gespeichert oder geteilt werden.
**„Ich darf alle Fotos posten, weil es meine Feier ist.“**
❌ Nein. Andere Personen haben Persönlichkeitsrechte insbesondere bei Social-Media-Uploads.
**„Ein mündliches Ja reicht nicht.“**
✅ Doch, wenn es eindeutig ist. Wichtig ist Transparenz und Respekt.
**„Kinder darf man nie fotografieren.“**
❌ Nicht ganz. Mit Zustimmung der Eltern oder im privaten Kreis ist das erlaubt.
---
## 🕹️ So machst du es richtig Schritt für Schritt
### 1. Vor dem Event
- Informiere Gäste klar („Es wird fotografiert“).
- Platziere Hinweise am Eingang, auf Einladungen und QR-Code-Schildern.
- Aktiviere in der Fotospiel App die Moderationsfunktion, falls du Fotos prüfen möchtest.
### 2. Während des Events
- Nutze QR-Codes, statt Gäste umständlich registrieren zu lassen.
- Achte darauf, dass niemand gegen seinen Willen fotografiert wird.
- Nutze die Live-Slideshow nur mit moderierten Bildern.
### 3. Nach dem Event
- Lade nur Fotos hoch, die respektvoll sind.
- Informiere Gäste, wie lange die Galerie online bleibt.
- Schließe oder lösche das Event, wenn alles gesichert ist.
**Praxis-Tipp:**
Schicke nach der Veranstaltung einen Dankeslink mit kurzer Erinnerung:
> „Unsere Galerie bleibt bis zum 30. Juni online lad gern deine Lieblingsfotos herunter.“
---
## 🧾 Mustervorlage für deinen Datenschutzhinweis
> **Fotohinweis:**
> Während dieser Veranstaltung werden Fotos gemacht und in einer privaten Galerie in der Fotospiel App gesammelt.
> Die Galerie ist nur für eingeladene Gäste zugänglich.
> Solltest du nicht fotografiert werden wollen, sprich uns bitte an.
> Verantwortlich: [Name / Veranstalter / Kontakt].
Ein solcher Hinweis reicht in 95 % der Fälle aus, um DSGVO-konform zu sein.
---
## 💬 Praxisbeispiele
> „Wir haben auf unserer Hochzeit einen klaren Hinweis am Eingang aufgestellt. Niemand hat sich gestört, und dank der Fotospiel App konnten wir alle Fotos später sicher teilen.“
> — *Tanja & Marco, Sommerhochzeit 2024*
> „Beim Sommerfest unserer Firma war der Datenschutz ein großes Thema. Die App hat das perfekt gelöst kein WhatsApp-Chaos, keine Datenlecks.“
> — *Leonie, Personalabteilung eines Mittelständlers*
---
## ✅ Checkliste: Datenschutz bei Eventfotos
- [ ] Gäste vorab informieren (Einladung oder Schild)
- [ ] App-Moderation aktivieren (optional)
- [ ] QR-Code nur an Teilnehmende weitergeben
- [ ] Keine peinlichen oder heiklen Bilder hochladen
- [ ] Löschtermin festlegen
- [ ] Galerie nach Abschluss schließen
---
## ❤️ Fazit
Datenschutz und schöne Erinnerungen schließen sich nicht aus sie ergänzen sich.
Wenn du transparent bist, respektvoll fotografierst und auf sichere Tools setzt, brauchst du keine Angst vor der DSGVO zu haben.
Unsere **Fotospiel App** macht genau das leicht:
private Galerien, kontrollierte Freigaben, sichere Speicherung in Deutschland und gleichzeitig jede Menge Spaß für dich und deine Gäste.
👉 **Starte jetzt dein eigenes Event in der Fotospiel App** und sammle Fotos sicher, einfach und datenschutzkonform.
So bleiben Erinnerungen lebendig und alle fühlen sich gut dabei.

View File

@@ -0,0 +1,156 @@
# So macht ihr euer Firmenevent unvergesslich Fotos, Spiele & Teamgeist
Ein gelungenes Firmenevent ist mehr als ein Buffet und ein paar Reden.
Es ist die Gelegenheit, das Wir-Gefühl zu stärken, neue Energie zu tanken und Erinnerungen zu schaffen, die lange nachwirken.
Doch wie entsteht aus einem „netten Abend“ ein echtes Gemeinschaftserlebnis?
Die Antwort liegt in drei Dingen: **Emotion, Interaktion und gemeinsamen Erinnerungen**.
In diesem Artikel zeige ich dir, wie ihr mit kreativen Ideen, Team-Spielen und unserer **Fotospiel App** euer nächstes Firmen- oder Teamevent unvergesslich macht.
---
## 💡 Warum Fotos auf Firmenevents mehr bewirken als jedes Präsent
Fotos sind mehr als Deko sie sind Kulturpflege.
Sie zeigen, dass Menschen Teil von etwas sind, dass Zusammenarbeit Spaß machen darf.
Ein gutes Event-Foto löst Stolz, Zugehörigkeit und Motivation aus.
Mit unserer **Fotospiel App** wird das Fotografieren zu einem Teamerlebnis:
Jede*r im Team kann mitmachen, Fotos hochladen, Challenges erfüllen und die Ergebnisse direkt in einer gemeinsamen Galerie sehen.
So entsteht aus einem Event ein spielerischer Wettbewerb voller Lächeln und Teamgeist.
---
## 🕹️ Schritt 1: Den Spaß aktiv planen
Klingt banal, aber gute Stimmung fällt selten vom Himmel.
Plane bewusst **Interaktions-Momente** ein: kleine Spiele, gemeinsame Aufgaben, kurze Challenges.
### Praxis-Tipps:
- Vermeidet zu viel Leerlauf zwischen Programmpunkten.
- Plant zwischendurch 10-minütige „Mini-Challenges“.
- Wählt Formate, die Kommunikation fördern statt Konkurrenzdruck erzeugen.
---
## 🎯 Schritt 2: Foto-Challenges einsetzen
Die Fotospiel App eignet sich perfekt für **Foto-Challenges**, die Humor und Kreativität verbinden.
So wird aus passiver Teilnahme echte Begeisterung.
Hier ein paar Ideen:
| Kategorie | Aufgabe | Ziel |
|------------|----------|------|
| **Teamspirit** | „Macht ein Gruppenfoto, auf dem jeder etwas Blaues trägt.“ | Zusammenhalt zeigen |
| **Kreativität** | „Fotografiert euer Firmenlogo aus Alltagsgegenständen.“ | Out-of-the-box-Denken fördern |
| **Kommunikation** | „Findet jemanden aus einer anderen Abteilung und macht ein Selfie zusammen.“ | Vernetzung stärken |
| **Humor** | „Das lustigste Posen-Bild des Tages!“ | Lachen garantiert |
**Praxis-Tipp:** Haltet die Aufgaben leicht verständlich. 35 Challenges reichen, um alle zu aktivieren, ohne das Event zu überfrachten.
---
## 📷 Schritt 3: So nutzt ihr die Fotospiel App optimal
1. **Event anlegen:** Titel, Ort, Datum fertig.
2. **Fotoaufgaben hinzufügen:** direkt im Dashboard.
3. **QR-Code generieren:** auf Tische, Wände oder Namensschilder drucken.
4. **Fotos einsammeln:** Gäste scannen, fotografieren, hochladen.
5. **Galerie live zeigen:** per Beamer oder Bildschirm Emotion pur!
### Bonus-Funktion:
Aktiviere den **Live-Modus**: Neue Fotos erscheinen automatisch auf dem Bildschirm.
Das motiviert alle, noch kreativer zu werden („Wow, wir sind schon im Stream!“).
---
## 🤳 Schritt 4: Kombiniert App, Fotobox & Einwegkameras
Ein Firmenevent lebt von Vielfalt.
Nutzt moderne Tools und analoge Nostalgie gleichzeitig.
- **Fotobox (Photo Booth):** Perfekt für Gruppenfotos und witzige Erinnerungen.
- **Einwegkameras:** Ideal für „Retro-Charme“ auf Betriebsfeiern oder Sommerfesten.
- **Fotospiel App:** Der digitale Hub, der alles verbindet.
**Praxis-Tipp:**
Richtet eine „Creative Corner“ ein ein dekorierter Bereich mit Requisiten und QR-Code.
Dort entstehen die lustigsten und lockersten Bilder des Abends.
---
## 💬 Schritt 5: Wettbewerb & Motivation
Gamification ist kein Modewort, sondern wirkt wirklich.
Verleiht Punkte, Likes oder kleine Preise für die besten Fotos das steigert die Teilnahmequote enorm.
Beispiele:
- „Bestes Gruppenfoto“
- „Kreativster Bildtitel“
- „Das spontanste Selfie“
Unsere **Fotospiel App** kann Fotos liken und kommentieren lassen so entsteht spielerischer Wettbewerb mit viel Humor.
---
## 🔒 Schritt 6: Datenschutz & Professionalität
Firmenfotos erfordern besondere Sensibilität.
Mit der Fotospiel App bleibt alles DSGVO-konform:
- Nur eingeladene Teilnehmer:innen haben Zugriff.
- Alle Uploads landen in einer geschützten Galerie.
- Der/die Admin entscheidet, was intern oder extern genutzt wird.
- Auf Wunsch können alle Daten nach dem Event automatisch gelöscht werden.
**Praxis-Tipp:**
Informiere Teilnehmende kurz vor Beginn („Mit dem QR-Code teilt ihr Fotos ausschließlich innerhalb unseres Teams“).
Transparenz schafft Vertrauen.
---
## 💡 Schritt 7: Nach dem Event ist vor dem Teamgeist
Ein gelungenes Event endet nicht mit dem Abbau.
Die Nachbereitung entscheidet, ob die Stimmung bleibt.
### So nutzt ihr eure Bilder danach:
- **Best-of-Slideshow** beim nächsten Meeting.
- **Mitarbeiterzeitung oder Intranet-Beitrag** mit den Highlights.
- **Wandcollage oder digitales Album** als Erinnerung.
- **Dankes-Mail** mit Galerie-Link Motivation garantiert.
**Praxis-Tipp:**
Kuratiert eine kleine Auswahl (2030 Bilder). Weniger ist oft mehr lieber Emotionen statt Masse.
---
## 🧭 Mini-Checkliste für euer Fotospiel-Event
- [ ] Event in der Fotospiel App angelegt
- [ ] 35 Fotoaufgaben vorbereitet
- [ ] QR-Codes gedruckt & verteilt
- [ ] Beamer/TV für Live-Galerie getestet
- [ ] Datenschutz-Hinweis eingebaut
- [ ] Kleine Preise für die besten Fotos vorbereitet
- [ ] Nachbereitung (Best-of-Album) geplant
---
## 💬 Erfahrungsstimme
> „Wir haben die Fotospiel App auf unserem Sommerfest genutzt plötzlich haben Leute aus Abteilungen miteinander geredet, die sonst nie Kontakt haben. Das Beste: Wir hatten in 2 Stunden über 400 Bilder und so viel Spaß!“
> — *Leonie M., HR-Managerin eines IT-Unternehmens*
---
## 🎯 Fazit & Call-to-Action
Ein Firmenevent ist keine Pflichtveranstaltung es ist eine Chance, Menschen zu verbinden.
Fotos sind der emotionale Klebstoff, der Erlebnisse festhält und Teams zusammenschweißt.
Mit **unserer Fotospiel App** könnt ihr diesen Prozess spielerisch gestalten:
Macht eure Mitarbeiter:innen zu Fotograf:innen, zeigt Ergebnisse live und schafft eine Erinnerungskultur, die motiviert.
👉 **Legt jetzt euer Event in der Fotospiel App an** und verwandelt das nächste Meeting, Sommerfest oder Kick-off in ein Erlebnis, das euer Team noch Wochen danach lächeln lässt.

View File

@@ -0,0 +1,125 @@
# Hochzeitsbilder & QRCode Die moderne Art, Erinnerungen zu sammeln und zu teilen
Du kennst das Spiel: Nach der Hochzeit hat jede*r tolle Bilder auf dem Handy doch Wochen später fehlen sie im gemeinsamen Album. Ein **QRCode** beendet dieses Chaos und macht das Teilen von Hochzeitsfotos so einfach wie einen kurzen Scan. In diesem Leitfaden zeige ich dir, wie du QRCodes **smart, datenschutzfreundlich und mit PraxisTipps** einsetzt und wie unsere **Fotospiel App** daraus ein echtes Gemeinschaftserlebnis macht.
---
## 💡 Warum QRCodes für Hochzeitsbilder unschlagbar sind
- **Sofort startklar:** Gäste scannen, laden hoch, schauen an ohne Registrierung, ohne AppInstallation.
- **Eine zentrale Galerie:** Alle Fotos landen an einem Ort sortiert und moderierbar.
- **Niedrige Hürden:** Gerade weniger technikaffine Gäste machen mit, weil es „einfach funktioniert“.
- **LiveErlebnis:** Auf Wunsch können Highlights während der Feier auf dem Bildschirm gezeigt werden das schafft Stimmung und Gesprächsanlässe.
Unsere **Fotospiel App** erstellt für jedes Event automatisch einen **persönlichen QRCode**. Du kannst ihn als Bilddatei herunterladen und auf Schilder, Tischkarten oder Displays drucken. Gäste scannen und sind sofort dabei.
---
## 🛠️ So funktionierts Schritt für Schritt (mit PraxisTipps)
### 1) Event in unserer Fotospiel App anlegen
Lege Titel, Datum und ggf. ein Titelbild fest. Aktiviere die **GästeGalerie** und entscheide, ob Uploads ohne Freigabe sichtbar sein sollen (für maximale Spontanität) oder ob du **Moderation** wünschst (für kuratierten Look).
**PraxisTipp:** Wenn du eine **LeinwandSlideshow** planst, nutze die Moderation so bleibt die Anzeige hochwertig.
### 2) QRCode erzeugen & platzieren
Lade den EventQRCode herunter. Platziere ihn:
- am **Willkommensschild** („Scan & share your moments!“),
- auf **Tischnummern** oder **Menükarten**,
- neben der **Fotobox** oder am **DJPult**,
- im **Gästebuch** („Scan mich, bevor du schreibst!“).
**PraxisTipp:** Drucke **mindestens 510 QRCodes** für mittelgroße Hochzeiten. Häng sie **in Sichtlinie** (Augenhöhe, Licht).
### 3) Gäste aktivieren mit kleinen Missionen
Erstelle in der App **Fotoaufgaben** (Gamification):
> „Macht ein Selfie mit dem Brautpaar.“
> „Fangt das herzlichste Lachen der Oma ein.“
> „Zeigt euer verrücktestes Tanzgesicht.“
**PraxisTipp:** Hänge 35 Aufgaben als **Karten** an prominente Orte (Bar, Fotobox, CandyBar). So werden auch schüchterne Gäste aktiv.
### 4) Upload & Galerie nutzen
Nach dem Scan landen Gäste in einer **mobiloptimierten Ansicht**: Fotos aufnehmen/hochladen, kurze Beschreibung (optional), senden.
**PraxisTipp:** Bitte die Trauzeug*innen, in den ersten 30 Minuten ein paar **Beispielfotos** hochzuladen. Social Proof wirkt Wunder.
### 5) LiveAnzeige für GänsehautMomente
Verbinde ein Notebook mit Beamer/TV und öffne die **LiveSlideshow**. Neue Bilder erscheinen automatisch.
**PraxisTipp:** Starte die Slideshow **erst nach der Trauung** (z.B. ab Sektempfang) und **pulte kritische Motive** via Moderation aus, falls nötig.
---
## 🔒 Datenschutz & Rechte kurz & klar
- **Private Galerie:** Das Event ist nur über **QRCode/Link** erreichbar; keine öffentliche Auffindbarkeit.
- **Kein Zwang zur Registrierung:** Gäste teilen ohne Konto weniger Reibung, mehr Teilnahme.
- **Löschoptionen:** Als Veranstalter*in kannst du Bilder entfernen oder die Galerie nach dem Event schließen.
- **Hinweistext:** Kommuniziere offen: „Mit dem Scan teilst du Fotos für unsere private Hochzeitsgalerie.“
- **Urheberrecht:** Die Rechte bleiben beim Fotografierenden; du erhältst **Nutzungsrechte** im privaten Rahmen. (Formulierungen kannst du in der AppBeschreibung ergänzen.)
**PraxisTipp:** Platziere einen **kurzen Rechtshinweis** direkt unter dem QRCode. Klare Kommunikation = weniger Fragen.
---
## 📷 QRCodes mit Fotobox & Einwegkameras kombinieren
### Fotobox (Photo Booth)
- Lasse die Fotobox **digital speichern** (USB/Cloud).
- Richte einen **AutomatikUpload** ein (oder lade gebündelt hoch).
- Platziere den QRCode **direkt an der Fotobox** so entdecken Gäste die Galerie sofort.
### Einwegkameras & Sofortbilder
- Verteile **Einwegkameras** auf den Tischen für den analognostalgischen Look.
- Fotografiere nach dem Entwickeln **die besten Abzüge** ab oder scanne sie und lade sie in die Galerie.
- **PraxisTipp:** Mache ein Foto **der Kamera mit Tischnummer**, bevor du sie einsammelst später kannst du Motive einem Tisch zuordnen („Tisch 7 hatte offenbar den meisten Spaß“).
Die Mischung aus **digital (QRCode & Smartphones)** und **analog (Einwegkameras/Sofortbilder)** erzeugt Vielfalt und Stimmung deine Galerie wirkt lebendig und zeitlos zugleich.
---
## 🧭 Checklisten (zum Abhaken)
**Vor der Hochzeit**
- [ ] Event in unserer Fotospiel App angelegt
- [ ] GalerieEinstellungen & Moderation geprüft
- [ ] QRCodes heruntergeladen & gedruckt (mind. 510)
- [ ] Fotoaufgaben formuliert (35 Stück)
- [ ] Slideshow getestet (Beamer/TV/Laptop & WLAN)
**Am Hochzeitstag**
- [ ] QRCodes gut sichtbar platziert
- [ ] Trauzeug*innen laden erste Fotos hoch
- [ ] Kurzansage vom DJ: „Scan & share your moments!“
- [ ] Moderation aktiv (falls Slideshow)
- [ ] FotoboxBilder später gesammelt hochladen
**Nach der Hochzeit**
- [ ] Highlights kuratieren & teilen
- [ ] DankesNachricht mit GalerieLink/QRCode versenden
- [ ] Galerie optional befristen/archivieren
- [ ] Bestof drucken (Fotobuch/Prints)
---
## ❓Häufige Fragen (FAQ)
**Brauchen Gäste eine App?**
Nein. QRCode scannen, Browser öffnet sich, los gehts.
**Können auch Videos hochgeladen werden?**
Ja, je nach gebuchtem Paket. Achte auf WLANQualität und Dateigrößen.
**Was, wenn jemand kein Smartphone hat?**
Andere Gäste können für die Person mitfotografieren und die Bilder hochladen.
**Wie verhindere ich unpassende Inhalte in der Slideshow?**
Aktiviere die **Moderationsfunktion** nur freigegebene Bilder erscheinen live.
**Kann ich die Galerie später herunterladen?**
Ja. Du kannst alle Bilder als **gesichertes Archiv** exportieren.
---
## 🎯 Fazit & CalltoAction
QRCodes sind die **einfachste und einladendste** Art, Hochzeitsbilder zu sammeln ohne AppHürden, ohne Chaos. In Kombination mit unserer **Fotospiel App** wird daraus ein echtes Gemeinschaftserlebnis: mit **Missionen**, **LiveSlideshow** und einer **kuratierten Galerie**, die euch noch Jahre später zum Lächeln bringt.
👉 **Starte jetzt dein Event in unserer Fotospiel App**, erstelle deinen QRCode und mach es deinen Gästen so leicht wie möglich, eure schönsten Momente zu teilen.

View File

@@ -0,0 +1,104 @@
# Hochzeitsfotografie mit kleinem Budget So bekommst du traumhafte Erinnerungen ohne Profi-Fotograf
Heiraten ist wunderschön aber teuer. Wenn du mitten in der Planung steckst, weißt du: Kleid, Location, Musik, Essen … alles summiert sich. Und dann kommt da noch der Fotograf mit seinem stolzen Preis.
Doch gute Nachrichten: **Wunderschöne Hochzeitsfotos müssen kein Luxus sein.**
Mit etwas Kreativität, liebevoller Organisation und unserer **Fotospiel App** kannst du Erinnerungen schaffen, die genauso emotional, ehrlich und einzigartig sind wie eure Liebe ganz ohne dein Budget zu sprengen.
---
## 💍 Der Zauber echter Momente
Die schönsten Hochzeitsfotos sind nicht die inszenierten, sondern die echten: das nervöse Lächeln vor dem Ja-Wort, der Stolz deiner Eltern, das ausgelassene Lachen auf der Tanzfläche.
Solche Augenblicke kann kein Fotograf planen aber deine Gäste erleben sie hautnah.
Unsere **Fotospiel App** verwandelt deine Gäste in Co-Fotografen. Jeder kann mit dem Smartphone Fotos machen, hochladen und teilen ganz einfach über einen QR-Code oder Link.
So entsteht eine Galerie voller Perspektiven, Emotionen und Liebe ohne komplizierte Technik oder zusätzliche Kosten.
---
## 📱 Schritt 1: Plane, was dir wichtig ist
Frag dich, welche Momente du unbedingt festhalten möchtest:
- Der Moment, in dem ihr euch zum ersten Mal seht?
- Das große Gruppenfoto?
- Die Feier am Abend?
Wenn du weißt, welche Erinnerungen dir am Herzen liegen, kannst du sie gezielt planen in unserer Fotospiel App etwa durch **Fotoaufgaben**, die du für deine Gäste erstellst.
> Beispiel:
> „Macht ein Selfie mit dem Brautpaar!“
> „Findet das schönste Detail in der Tischdeko!“
> „Fotografiert das verrückteste Tanzgesicht!“
Solche Aufgaben machen Spaß und sorgen ganz automatisch für viele schöne, ungezwungene Fotos.
---
## 📷 Schritt 2: Kombiniere smarte Tools App, Einwegkameras & Fotoboxen
Wenn du die Erinnerungen deiner Hochzeit möglichst vielfältig festhalten möchtest, kannst du digitale und analoge Ideen kombinieren:
### 🎞️ Einwegkameras für Nostalgie
Lege auf jedem Tisch eine oder zwei **Einwegkameras** aus.
Deine Gäste werden sie lieben und du bekommst am Ende charmante, unperfekte, aber authentische Fotos, die voller Charakter stecken.
**Praxis-Tipp:** Lass die Gäste wissen, dass sie ruhig kreativ sein dürfen. Ein kleines Schild mit „Zeig uns deinen Lieblingsmoment!“ macht oft den Unterschied.
### 🤳 Fotobox für Spaß & Gruppenbilder
Eine **Fotobox (Photo Booth)** ist die perfekte Ergänzung.
Sie sorgt für Unterhaltung, gerade später am Abend und liefert lustige, hochwertige Schnappschüsse.
Und das Beste: Du kannst die digitalen Ergebnisse direkt mit der **Fotospiel App** verknüpfen, um alle Bilder zentral zu sammeln.
So entsteht eine Mischung aus Spaßbildern, emotionalen Momenten und spontanen Handyfotos alles an einem Ort.
---
## 💡 Schritt 3: Gäste als Fotografen einbinden
Viele deiner Gäste lieben es, zu fotografieren sie müssen nur einen kleinen Anstoß bekommen.
Mit unserer App gibst du ihnen genau diesen: kleine Aufgaben, spielerische Herausforderungen oder einfach den QR-Code, um ihre Lieblingsbilder hochzuladen.
Dadurch wird deine Hochzeit zum Gemeinschaftsprojekt jeder trägt ein Stück dazu bei, dass eure Erinnerungen lebendig bleiben.
---
## 🌇 Schritt 4: Natürliches Licht & echte Emotionen
Gute Fotos entstehen nicht durch teures Equipment, sondern durch Gefühl und Licht.
Ein paar einfache Tipps helfen auch deinen Gästen, bessere Bilder zu machen:
- **Licht schlägt Blitz:** Fotos wirken schöner mit Tageslicht oder weichem Abendlicht.
- **Echte Emotionen:** Bitte um Fotos von Lachen, Umarmungen, Tanzen nicht nur Posen.
- **Details:** Blumen, Hände, Deko sie erzählen Geschichten.
- **Bewegung:** Ein Foto voller Leben ist wertvoller als zehn perfekte Standbilder.
Solche Tipps kannst du direkt als kleine Hinweise in der Fotospiel App hinterlegen.
---
## 💾 Schritt 5: Alle Fotos automatisch gesammelt
Nach dem großen Tag kommt der übliche Stress: Fotos von WhatsApp, Cloud-Links, E-Mails …
Mit der **Fotospiel App** passiert das automatisch.
Alle Gäste laden ihre Fotos direkt in eure persönliche Online-Galerie.
Du kannst sie sortieren, freigeben, herunterladen oder einfach gemeinsam ansehen ganz ohne Aufwand.
---
## ❤️ Bonus: Gemeinschaft statt Perfektion
Die schönsten Hochzeiten sind die, bei denen sich alle eingebunden fühlen.
Wenn deine Gäste fotografieren, lachen und ihre Lieblingsmomente teilen, entsteht nicht nur eine Sammlung von Bildern, sondern ein echtes Gefühl von Nähe.
Viele Paare erzählen uns später, dass sie durch die App Fotos entdeckt haben, die sie sonst nie gesehen hätten ein Kinderlachen, ein Blick, eine spontane Geste.
---
## ✨ Fazit
Du brauchst kein großes Budget für große Erinnerungen.
Mit der richtigen Mischung aus **Einwegkameras**, **Fotobox** und der **Fotospiel App** bekommst du Fotos, die genauso vielseitig und lebendig sind wie euer Tag.
Professionelle Fotografen liefern perfekte Bilder aber deine Gäste liefern Emotionen.
Und genau das macht deine Hochzeit unvergesslich.

View File

@@ -0,0 +1,191 @@
# So nutzt ihr QR-Codes auf Events kreativ Von Fotos bis Networking
QR-Codes sind längst mehr als kleine schwarz-weiße Quadrate.
Sie sind die Brücke zwischen der realen und der digitalen Welt und auf Events die **einfachste Möglichkeit, Interaktion zu schaffen**.
Ob Hochzeit, Firmenevent oder Festival: Mit einem Scan können Gäste Fotos hochladen, Feedback geben, Kontakte austauschen oder Informationen abrufen.
In diesem Artikel zeige ich dir, wie du QR-Codes kreativ nutzt mit vielen Praxis-Tipps und konkreten Ideen für den Einsatz mit **unserer Fotospiel App**.
---
## 💡 Warum QR-Codes auf Events so stark funktionieren
Ein QR-Code ist simpel, aber genial:
- **Niedrige Einstiegshürde:** Jede:r hat heute ein Smartphone.
- **Schneller Zugriff:** Keine App-Installation nötig.
- **Interaktiv:** Gäste können sofort reagieren.
- **Messbar:** Du siehst, wie viele Menschen teilnehmen.
Gerade bei Events, wo Emotionen und Dynamik zählen, ist das entscheidend.
Ein QR-Code macht aus Zuschauern aktive Mitwirkende.
---
## 🎯 1. QR-Codes für Fotos & Erinnerungen
Der Klassiker und der schönste Einsatz: Fotos sammeln!
Mit der **Fotospiel App** erzeugst du automatisch für jedes Event einen individuellen QR-Code.
Deine Gäste scannen ihn, öffnen die Eventseite und können sofort Fotos machen oder hochladen.
Kein Login, kein Aufwand nur Spaß.
### 💡 Praxis-Tipps:
- Platziere den QR-Code am **Eingang**, an **Tischen** und an der **Fotobox**.
- Füge eine kleine Anleitung hinzu:
> „Scanne mich & teile dein Lieblingsfoto!“
- Kombiniere ihn mit **Foto-Challenges** („Mach ein Selfie mit dem Brautpaar!“).
- Nutze **Live-Slideshows**, um neue Fotos sofort zu zeigen Motivation pur!
### Bonus-Idee:
Gestalte QR-Code-Schilder im Event-Design (Farbwelt, Schrift, Logo).
Das wirkt professionell und fügt sich optisch ein.
---
## 🤝 2. QR-Codes fürs Networking
Events leben von Begegnungen QR-Codes helfen, Kontakte zu knüpfen, ohne Visitenkartenchaos.
### Beispiele:
- **Digitales Namensschild:** Auf der Rückseite der Badge ein QR-Code zum LinkedIn-Profil.
- **Teamvorstellung:** Jeder QR-Code führt zu einer Mini-Seite mit Foto, Funktion und Social-Links.
- **Networking-Wand:** Gäste kleben QR-Sticker mit Kurzprofilen an eine Magnetwand so entsteht ein interaktives Kontaktnetzwerk.
**Praxis-Tipp:**
Verwende QR-Codes mit **sprechenden Kurz-URLs** (z. B. fotospiel.app/anna), damit sie auch ohne Scan erkennbar wirken.
---
## 🏆 3. Gamification & Challenges mit QR-Codes
QR-Codes sind perfekte Spielfelder für Wettbewerbe.
Mit der Fotospiel App lassen sich Aufgaben oder „Missionen“ hinterlegen, die Gäste durch Scannen aktivieren.
### Beispiele:
- „Finde den QR-Code beim Buffet und fotografiere den schönsten Teller.“
- „Scanne alle fünf versteckten Codes im Raum und sammle Punkte!“
- „Mach ein Selfie mit der Person, die denselben QR-Code gefunden hat.“
Solche Challenges fördern Interaktion und sorgen für Gesprächsstoff.
**Praxis-Tipp:**
Erstelle verschiedene QR-Codes für unterschiedliche Aufgaben.
So hast du ein Mini-Spielsystem ideal für Teamevents oder Messen.
---
## 🍸 4. QR-Codes für Feedback & Abstimmungen
Warum Umfragen auf Papier, wenns digital so einfach geht?
- **Bewertungen:** „Wie hat dir das Catering gefallen?“
- **Vorschläge:** „Was war dein Lieblingsmoment?“
- **Abstimmungen:** „Welche Band soll als Nächstes spielen?“
Du kannst diese Umfragen direkt mit Tools wie Typeform, Google Forms oder internen Feedback-Seiten verbinden.
Und: In Kombination mit Fotospiel kannst du z. B. für das **beste Foto des Abends** abstimmen lassen.
**Praxis-Tipp:**
Nutze **kurze Fragen** und **Smileys** statt langer Texte so bekommst du mehr Antworten.
---
## 📜 5. QR-Codes für Programm & Infos
Gerade bei größeren Events verlieren Gäste schnell den Überblick.
QR-Codes helfen, Struktur zu schaffen, ohne Papierberge zu drucken.
### Ideen:
- **Tagesplan:** Link zur Agenda oder Google-Sheet.
- **Lageplan:** z. B. mit Anfahrtsbeschreibung oder Saalübersicht.
- **Menükarte:** QR-Code auf der Speisekarte führt zu Allergie-Infos oder Getränkeliste.
- **Streaming-Links:** Für hybride Events oder Gäste, die nicht vor Ort sind.
**Praxis-Tipp:**
Platziere den Haupt-QR-Code an einem zentralen „Info-Board“.
Nutze ein einheitliches Design (gleiche Farbe, Symbol, Stil).
---
## 🎨 6. Kreative & dekorative Einsatzideen
Ein QR-Code muss nicht langweilig aussehen!
Er kann Teil eurer Event-Dekoration werden:
- Graviert auf Holz oder Acryl (Tischaufsteller).
- Gedruckt auf Luftballons, Postkarten oder Buttons.
- Als Sticker auf Getränkeflaschen.
- Eingebettet in Fotos oder Logos.
Ein Hingucker, der gleichzeitig Nutzen hat besonders bei Hochzeiten und Messen.
**Praxis-Tipp:**
Nutze farbige QR-Codes (z. B. schwarz-gold, weiß-rosé), solange der Kontrast hoch bleibt.
Testscans immer vor dem Druck durchführen!
---
## 📷 7. QR-Codes + Fotobox + Einwegkameras = Vielfalt
Die perfekte Kombination:
- **Fotobox:** liefert witzige Gruppenbilder.
- **Einwegkameras:** sorgen für Retro-Charme.
- **Fotospiel App:** sammelt alles digital.
Platziere QR-Codes bei der Fotobox oder direkt auf den Tischen mit Texten wie:
> „Scanne mich & lade dein Lieblingsbild hoch!“
> „Teile deine schönsten Momente mit uns!“
**Praxis-Tipp:**
Drucke QR-Codes **laminiert** Schweiß, Regen oder Getränke sind sonst ihre größten Feinde.
---
## 🧭 8. Sicherheit, Datenschutz & Vertrauen
Gerade wenn Fotos ins Spiel kommen, ist Transparenz wichtig.
Unsere **Fotospiel App** bietet:
- private, geschlossene Events (nur via QR-Code zugänglich),
- optionale Freigabe-Moderation,
- sichere Serverstandorte in Deutschland,
- automatische Löschung nach Veranstaltungsende.
**Praxis-Tipp:**
Schreibe unter jeden QR-Code kurz:
> „Scannen = Teilnahme an unserer privaten Event-Galerie (keine öffentliche Nutzung).“
So wissen Gäste, worum es geht und fühlen sich sicher.
---
## 💬 9. Beispiele aus der Praxis
> „Wir haben beim Sommerfest QR-Codes an den Getränkeflaschen angebracht jede führte zu einer anderen Fotoaufgabe. Am Ende hatten wir über 500 Bilder voller Lachen!“
> — *Thomas, Eventmanager eines Start-ups*
> „Bei unserer Hochzeit hing ein großer QR-Code am Eingang. Alle Gäste haben Fotos hochgeladen, ohne dass wir was erklären mussten.“
> — *Lena & Fabian, Herbsthochzeit 2025*
---
## 🧠 10. Checkliste für deinen QR-Code-Einsatz
- [ ] QR-Codes frühzeitig generieren
- [ ] Platzierung & Design planen
- [ ] Kurze Handlungsaufforderung („Scan mich!“) hinzufügen
- [ ] Datenschutz-Hinweis ergänzen
- [ ] Vor Ort Scans testen
- [ ] Nach dem Event: QR-Code deaktivieren oder archivieren
---
## 🎯 Fazit & Call-to-Action
QR-Codes sind die kleinen, unscheinbaren Helfer, die große Wirkung haben.
Sie machen Events interaktiv, modern und effizient und sie holen deine Gäste direkt ins Geschehen.
Mit **unserer Fotospiel App** kannst du sie noch smarter nutzen:
Ob zum Sammeln von Fotos, für Challenges oder Live-Erlebnisse ein Scan genügt, und dein Event lebt digital weiter.
👉 **Erstelle jetzt dein eigenes Event in der Fotospiel App**, generiere deinen QR-Code und mach aus deiner Veranstaltung ein Erlebnis, das verbindet.

View File

@@ -0,0 +1,102 @@
# Wann Hochzeitseinladungen verschickt werden sollten Der ultimative Leitfaden für perfektes Timing
Planung ist alles besonders bei einer Hochzeit. Zwischen Gästelisten, Location und Budget gerät das Thema **Einladungen** oft ins Hintertreffen. Doch das richtige Timing entscheidet, ob eure Liebsten kommen können oder schon verplant sind. In diesem Leitfaden erfährst du **wann** und **wie** du Einladungen am besten verschickst plus clevere **PraxisTipps**, wie du QRCodes, Fotoboxen und unsere **Fotospiel App** elegant in deine Kommunikation integrierst.
---
## ⏰ Der ideale Zeitpunkt so findest du ihn
### SavetheDate zuerst
Sobald euer Datum steht, verschickt eine **SavetheDateNachricht** digital, per Post oder sogar mit einem hübschen QRCode.
**Empfohlene Zeit:** **812 Monate vor der Hochzeit**.
Damit gebt ihr euren Gästen Planungssicherheit besonders wichtig, wenn Anreisen oder Unterkünfte nötig sind.
**PraxisTipp:** Testet mit unserer **Fotospiel App** schon jetzt die **Gästegalerie** erstellt ein MiniEvent mit einem QRCode und ladet eure Trauzeug*innen zum Probeshooting ein. So entdeckt ihr früh, wie einfach das Teilen später funktioniert.
### Einladungskarten mit Stil und Struktur
Die eigentlichen Einladungen folgen idealerweise **46 Monate vor der Feier**. Das gibt den Gästen genug Zeit, zu- oder abzusagen und eventuelle Urlaube anzupassen.
Füge unbedingt diese Informationen hinzu:
- Ort, Datum, Uhrzeit
- Dresscode (wenn gewünscht)
- Kontaktdaten für Rückfragen
- Bitte um Rückmeldung (RSVP)
- QRCode oder Link zur FotospielGalerie (optional)
**PraxisTipp:** Wenn du eine Hochzeitswebseite hast, leite den QRCode direkt dorthin. Dort kannst du später auch den Link zur FotospielGalerie einbinden.
---
## 💌 Kreative Wege, Einladungen zu verschicken
### Klassisch per Post
Karten bleiben ungeschlagen, wenn es um Emotionen geht. Der Moment, in dem man eine handgeschriebene Einladung öffnet, ist magisch. Drucke QRCodes auf Rückseiten oder als kleine Beilage sie können später für die FotoGalerie genutzt werden.
### Digital per EMail oder Messenger
Nachhaltig, schnell und budgetfreundlich. Verwende ein einheitliches Design und füge den **QRCode** als Anhang oder Bild hinzu. So können Gäste den Termin gleich speichern.
### Hybrid: Print trifft Digital
Viele Paare kombinieren: gedruckte Einladung plus digitale Ergänzung. Beispiel: Ein liebevoll gestalteter Brief mit einem QRCode, der zu eurer Hochzeitsseite führt. Dort warten alle Details und später die FotospielGalerie.
---
## 📆 BeispielZeitplan für stressfreies Versenden
| Zeitraum vor der Hochzeit | Todo | Notiz |
|---------------------------|-------|-------|
| 1210 Monate | SavetheDate versenden | Frühzeitig kommunizieren |
| 86 Monate | Gästeliste finalisieren | Adressen, EMails prüfen |
| 64 Monate | Einladungskarten verschicken | QRCodes, Website testen |
| 3 Monate | Erinnerung an offene Zusagen | Freundlich per EMail |
| 1 Monat | Finales Programm verschicken | Ort, Zeiten, Parkhinweise |
| Nach der Feier | Dankeskarten + FotospielGalerie teilen | QRCode zum Download beilegen |
**PraxisTipp:** Plane **Pufferzeiten** für Druck, Versand und Rückläufe ein besonders bei Auslandsgästen.
---
## 🧠 Häufige Fehler beim EinladungsTiming
- **Zu spät verschickt:** Gäste haben schon andere Termine.
- **Zu früh verschickt:** Einladung gerät in Vergessenheit.
- **Unklare Infos:** Fehlen Details, häufen sich Rückfragen.
- **Kein RückmeldeDatum:** Du kannst schwer kalkulieren.
- **Fehlende digitale Ergänzung:** QRCode oder Link fehlt = Kommunikationslücke.
Mit einem klaren Plan ersparst du dir unnötigen Stress und Nachfragen.
---
## 📷 BonusIdeen: Einladungen mit Fotobox, QRCodes & Fotospiel App verknüpfen
### QRCodes als Erlebnis
Platziere in der Einladung einen QRCode, der **zu einer kleinen Fotogalerie führt**. Dort könnt ihr z.B. ein MiniVideo oder eine Slideshow eurer Verlobung zeigen. Gäste lieben solche Überraschungen!
### FotoboxSchnappschüsse als Einladung
Wenn ihr bereits eine **Fotobox** gemietet habt (z.B. für den Polterabend), nutzt ein paar der besten Bilder für eure Einladungskarten. Das wirkt persönlich und sympathisch.
### FotospielGalerie nach der Feier
Nach der Hochzeit könnt ihr denselben QRCode für eure gemeinsame FotospielGalerie wiederverwenden Gäste erkennen ihn sofort. Praktisch und emotional zugleich.
---
## 💬 Stimmen aus der Praxis
> „Wir haben unsere SavetheDates 11 Monate vorher verschickt und danach kaum Absagen bekommen. Der QRCode zur Galerie war später der Hit!“
> — *Laura & Ben, Sommerhochzeit 2024*
> „Wir nutzten die Fotospiel App schon vorab, um zu testen, wie alles funktioniert das hat uns viel Sicherheit gegeben.“
> — *Nina & Paul*
Solche Rückmeldungen zeigen: Frühzeitige Planung zahlt sich aus.
---
## 🎯 Fazit & CalltoAction
Wenn du weißt, **wann** du deine Einladungen verschickst, gewinnst du Gelassenheit und deine Gäste fühlen sich gut informiert.
Plane smart, kommuniziere klar und kombiniere klassische Post mit digitalen Tools.
Mit **unserer Fotospiel App** kannst du bereits vor der Feier einen kleinen Vorgeschmack geben: Gäste scannen, teilen und erleben eure Geschichte digital. So beginnt euer gemeinsames Hochzeitsabenteuer schon lange vor dem großen Tag.
👉 **Starte jetzt dein erstes TestEvent in unserer Fotospiel App** und entdecke, wie einfach das Teilen von Erinnerungen sein kann.

View File

@@ -0,0 +1,92 @@
# Warum Gastfotos wichtig sind auch wenn du einen Profi-Fotografen hast
Dein Hochzeitstag vergeht wie im Flug. Zwischen Vorfreude, Tränen und Tanz merkst du kaum, wie viele kleine Momente an dir vorbeiziehen. Natürlich ist ein Profi-Fotograf unverzichtbar aber selbst der beste kann nicht überall gleichzeitig sein.
**Gastfotos** ergänzen das große Ganze: Sie zeigen deine Feier aus allen Perspektiven, ungefiltert, echt und emotional.
In diesem Artikel erfährst du, warum Gastfotos so wertvoll sind, wie du sie clever sammelst und wie unsere **Fotospiel App** daraus ein echtes Gemeinschaftserlebnis macht.
---
## 💍 Emotionen aus Sicht deiner Gäste
Während dein Fotograf die Trauung und das Paarshooting festhält, entdecken deine Gäste das, was du oft nicht siehst: das Lachen der Kinder, die Tränen deiner Eltern, spontane Umarmungen auf der Tanzfläche.
Diese Perspektive ist unbezahlbar sie erzählt die Geschichte **eurer Hochzeit**, nicht nur den Ablauf.
> „Wir hatten über 600 Gastfotos und genau diese zeigen die echten Gefühle des Tages.“
> — *Sophie & Lukas, Sommerhochzeit 2024*
---
## 📸 Der perfekte Mix: Profi + Gäste
Ein Profi liefert Kunstwerke, deine Gäste liefern Leben. Zusammen entsteht ein Hochzeitsalbum, das alle Facetten einfängt.
| Quelle | Stärken | Beispiele |
|--------|----------|------------|
| **Profi-Fotograf** | Perfekte Komposition, Technik, Belichtung | Paarshooting, Trauung, Details |
| **Gäste** | Spontane Emotion, Nähe, Vielfalt | Tanzfläche, Lachen, kleine Gesten |
Unsere **Fotospiel App** hilft dir, diese beiden Welten mühelos zu verbinden. Während der Fotograf seinen Job macht, können deine Gäste mitmachen Fotos hochladen, Aufgaben erfüllen und Teil des Ganzen werden.
---
## 🕹️ Mach deine Gäste zu Co-Fotografen
Viele Gäste machen ohnehin Fotos aber ohne System landen sie auf Handys, in Chats oder gehen verloren.
Mit unserer App wird das zum Spiel:
- Du erstellst kleine **Foto-Missionen**, z. B.:
> „Macht ein Selfie mit dem Brautpaar“
> „Zeigt das schönste Lächeln der Großeltern“
> „Findet das lustigste Detail auf der Tanzfläche“
- Gäste scannen den QR-Code, laden ihre Bilder hoch und werden Teil eurer Geschichte.
**Praxis-Tipp:** Platziere QR-Codes an der Bar, beim Gästebuch oder an der Fotobox überall, wo Menschen zusammenkommen. So aktivierst du möglichst viele Fotograf:innen.
---
## 🎞️ Fotobox & Einwegkameras clever einbinden
### Fotobox Spaßfaktor mit System
Eine Fotobox sorgt für lockere Stimmung und Gruppenfotos.
Kombiniere sie mit der **Fotospiel App**, indem du die digitalen Ergebnisse direkt hochlädst oder automatisch synchronisierst. So bleibt kein Schnappschuss ungesehen.
### Einwegkameras Nostalgie pur
Einwegkameras auf den Tischen sind charmant und simpel. Nach dem Entwickeln kannst du die besten Bilder abfotografieren oder einscannen und in deine Fotospiel-Galerie hochladen.
**Praxis-Tipp:** Lege eine kleine Karte daneben mit dem Text:
> „Mach ein Foto, das das Brautpaar überrascht!“
So entstehen spontane, liebevolle Aufnahmen.
---
## 🔒 Datenschutz und Kontrolle
Ein häufiges Argument gegen Gastfotos: „Was, wenn peinliche Bilder entstehen?“
Mit unserer App hast du alles im Griff:
- Du kannst **Uploads moderieren** (freigeben oder ausblenden).
- Gäste teilen ihre Fotos **nur innerhalb eures Events**.
- Nach der Feier kannst du die Galerie schließen oder exportieren.
Damit bleibt eure Privatsphäre geschützt und du entscheidest, welche Bilder ihr zeigen möchtet.
---
## 💡 Praxis-Tipps für perfekte Gastfotos
1. **Kommuniziere klar:** Sag deinen Gästen, dass du dich über Fotos freust.
2. **Verteile Aufgaben:** In der App oder auf kleinen Kärtchen so fühlen sich alle beteiligt.
3. **Starte früh:** Lass Trauzeugen und Freunde direkt nach der Trauung die ersten Fotos hochladen.
4. **Live zeigen:** Nutze die Slideshow-Funktion der App für echte Wow-Momente.
5. **Danken nicht vergessen:** Nach der Feier den Link zur Galerie als Dank teilen so fühlen sich alle wertgeschätzt.
---
## ❤️ Fazit
Ein Profi-Fotograf fängt eure Hochzeit perfekt ein aber die Seele eures Tages steckt in den Fotos eurer Gäste.
Sie zeigen Emotionen, Perspektiven und Erinnerungen, die sonst verloren gingen.
Mit **unserer Fotospiel App** kannst du diese Momente spielerisch sammeln:
Gäste fotografieren, laden hoch, lachen und du erhältst am Ende eine Galerie, die so lebendig ist wie euer Fest.
👉 **Starte dein eigenes Hochzeits-Event in der Fotospiel App** und entdecke, wie magisch Gastfotos sein können.

View File

@@ -0,0 +1,144 @@
# Wie Gäste eure schönsten Eventmomente festhalten und was du dafür tun musst
Jedes Event lebt von seinen Gästen sie sind die Energie, die Stimmung und am Ende die besten Geschichtenerzähler.
Doch während Profis meist die großen Highlights ablichten, sind es die Gäste, die die **echten Momente** einfangen: spontanes Lachen, kleine Gesten, ehrliche Emotionen.
Damit diese Schätze nicht verloren gehen, braucht es ein bisschen Organisation und ein cleveres System, um sie zu sammeln.
Hier erfährst du, wie du Gäste motivierst, aktiv zu fotografieren, und wie **unsere Fotospiel App** daraus ein unvergessliches Erlebnis für alle macht.
---
## 💫 Warum Gastfotos Gold wert sind
Egal ob Hochzeit, Geburtstag oder Firmenfeier die schönsten Bilder entstehen meist *nicht* auf Bestellung.
Deine Gäste sind überall, wo echte Emotionen passieren.
Sie fangen auf, was kein Profi gleichzeitig sehen kann: das Lächeln am Buffet, das Wiedersehen alter Freunde, die Freude beim ersten Tanz.
Diese Perspektiven sind **persönlich, authentisch und voller Leben**.
Wenn du sie geschickt sammelst, entsteht ein lebendiges Gesamtbild deines Events.
---
## 🧠 Der psychologische Trick: Motivation durch Teilhabe
Menschen fotografieren lieber, wenn sie das Gefühl haben, **Teil einer Geschichte** zu sein.
Sag deinen Gästen also nicht einfach: „Macht Fotos!“, sondern:
> „Wir wollen die schönsten Erinnerungen gemeinsam festhalten helft mit!“
Noch besser: Mach es spielerisch.
Genau das macht unsere **Fotospiel App**: Sie verwandelt Fotos in kleine Missionen, bei denen Gäste Spaß haben, kreativ werden und gleichzeitig Momente für euch festhalten.
---
## 🕹️ Schritt-für-Schritt-Anleitung für dein perfektes Gästefoto-Event
### 1. Vorbereitung der Rahmen zählt
Erstelle in der **Fotospiel App** ein Event mit kurzer Beschreibung und Titelbild.
Lege fest, ob Gäste ihre Fotos direkt sehen können oder ob du sie moderierst.
**Praxis-Tipp:** Für Hochzeiten und private Feiern wirkt Moderation beruhigend niemand muss sich sorgen, dass peinliche Schnappschüsse öffentlich werden.
### 2. QR-Codes clever platzieren
Die besten Ideen helfen nichts, wenn niemand weiß, wo er teilnehmen kann.
Drucke deinen Event-QR-Code und platziere ihn:
- am Eingang („Scan mich und werde Teil unserer Story!“)
- auf Tischen oder Getränkekarten
- neben der **Fotobox**
- am Buffet oder bei der Candy-Bar
So ist die Teilnahme kinderleicht.
### 3. Fotoaufgaben einbauen
Motivation entsteht durch Abwechslung.
Erstelle in der App kleine Missionen wie:
> „Mach ein Selfie mit dem Geburtstagskind!“
> „Fang den lustigsten Moment des Abends ein.“
> „Zeig uns das schönste Accessoire des Tages.“
Diese Aufgaben sorgen für Interaktion und brechen das Eis zwischen Gästen, die sich nicht kennen.
### 4. Live-Galerie einschalten
Einer der emotionalsten Momente: wenn Fotos live auf einer Leinwand erscheinen.
Mit unserer App kannst du eine **automatische Slideshow** aktivieren.
So wird dein Event zu einem Erlebnis, bei dem alle mitfiebern „Schau, das ist mein Bild!“
**Praxis-Tipp:** Starte die Anzeige erst nach dem Essen oder zur Party wenn alle locker sind.
### 5. Nachbereitung leicht gemacht
Nach der Feier kannst du alle Fotos als ZIP-Datei exportieren oder in einer Online-Galerie freigeben.
So bleibt nichts verloren, und alle Gäste können eure Highlights genießen.
---
## 📸 Welche Gäste machen die besten Fotos?
Jede Gästetyp hat seine Stärken und du kannst sie gezielt aktivieren:
| Typ | Motivation | Aufgabe |
|------|-------------|---------|
| **Die Kreativen** | lieben Ideen & Ästhetik | gestalte Aufgaben mit Themen („Farbe Blau“, „Detail-Foto“) |
| **Die Spaßmacher** | lieben Aufmerksamkeit | gib ihnen Challenges („Lustigstes Gruppenfoto“) |
| **Die Ruhigen** | beobachten Details | bitte um „emotionale Momente“ |
| **Kinder & Teens** | entdecken Neues | lass sie „das coolste Foto des Tages“ suchen |
**Praxis-Tipp:** Sprich in der Eröffnungsrede kurz über das Fotospiel Humor wirkt besser als Perfektionismus.
---
## 🎞️ Kombiniere Gastfotos mit anderen Quellen
### Fotobox
Eine Fotobox liefert professionelle, aber spaßige Bilder.
Verbinde sie mit der App: QR-Code daneben platzieren oder Uploads automatisch synchronisieren.
### Einwegkameras
Retro-Feeling inklusive!
Lege 12 Einwegkameras pro Tisch aus und lade die entwickelten Bilder später in die App-Galerie.
So bekommst du eine bunte Mischung aus digital und analog.
### Profi-Fotograf
Wenn du einen Fotografen hast, lass ihn die Highlights dokumentieren.
Die Gäste ergänzen mit Emotion und Nähe eine perfekte Kombination.
---
## 🔒 Datenschutz und Vertrauen
Ein sensibler Punkt, besonders bei Firmenfeiern oder großen Events: Datenschutz.
Unsere **Fotospiel App** ist DSGVO-konform und schützt Privatsphäre durch:
- **geschlossene Events:** nur mit QR-Code zugänglich
- **Moderationsoption:** du entscheidest, was sichtbar ist
- **Löschfunktionen:** auf Wunsch automatische Datenlöschung nach Eventende
**Praxis-Tipp:** Kommuniziere klar, dass die Fotos nur intern oder für das Paar/den Veranstalter bestimmt sind. Das schafft Vertrauen und steigert die Teilnahmequote.
---
## 🧭 Kleine Tipps mit großer Wirkung
- **Mach den Anfang:** Wenn Gastgeber oder Veranstalter selbst ein paar Fotos machen, folgen die anderen schneller.
- **Lob motiviert:** Zeige live die schönsten Bilder Applaus ist die beste Belohnung.
- **Haltes einfach:** Weniger Regeln = mehr Spontanität.
- **Dekoration nutzen:** Orte mit gutem Licht und Hintergrund (z. B. Blumenwand) anregen.
- **QR-Codes groß genug drucken:** Mindestens 10 cm × 10 cm sichtbar auch bei Dämmerung.
---
## 💬 Erfahrung aus der Praxis
> „Wir hatten 150 Gäste und keine Zeit, überall gleichzeitig zu sein. Dank der Fotospiel App haben wir später Momente gesehen, die wir gar nicht mitbekommen hatten vom Kinderlachen bis zum nächtlichen Lagerfeuer.“
> — *Sarah & Jonas, Sommerhochzeit 2024*
> „Bei unserem Firmenevent war es der Icebreaker! Alle waren im Wettbewerb, wer das kreativste Bild schafft.“
> — *Martin, Teamleiter Vertrieb*
---
## ❤️ Fazit & Call-to-Action
Eure Gäste sind mehr als Zuschauer sie sind die Augen und Herzen eures Events.
Wenn du sie richtig einbindest, bekommst du Fotos, die keine Kamera dieser Welt so ehrlich aufnehmen könnte.
Unsere **Fotospiel App** macht es einfach:
QR-Code scannen, Aufgaben erfüllen, Erinnerungen teilen und am Ende entsteht eine Galerie, die euer Event von innen zeigt.
👉 **Starte jetzt dein Event in der Fotospiel App** und lass deine Gäste die schönsten Momente für dich festhalten spontan, emotional und echt.

View File

@@ -0,0 +1,333 @@
# Fotospiel Aufgaben
Hier ist eine Sammlung von kreativen Foto-Aufgaben, sortiert nach Event-Typ und zugeordnet zu Emotionen.
---
## Hochzeit
1. Macht ein Foto mit dem Brautpaar. (Freude)
2. Stellt den Heiratsantrag nach (fragt das Brautpaar, wie er war!). (Romantik)
3. Fotografiert die Eheringe aus einer kreativen Perspektive. (Liebe)
4. Findet das Paar, das am längsten verheiratet ist, und lasst euch einen Tipp geben. (Nostalgie)
5. Macht ein Foto von einer herzlichen Umarmung zwischen den Eltern des Brautpaares. (Rührung)
6. Bildet mit euren Händen ein Herz um das Brautpaar. (Liebe)
7. Fotografiert den Moment, in dem die Hochzeitstorte angeschnitten wird. (Freude)
8. Macht ein Selfie mit dem Trauzeugen oder der Trauzeugin. (Teamgeist)
9. Findet jemanden mit dem gleichen Vornamen und macht ein gemeinsames Foto. (Überraschung)
10. Fotografiert einen Gast, der eine Freudenträne vergießt. (Rührung)
11. Macht ein Foto, auf dem alle so hoch springen, wie sie können. (Ekstase)
12. Findet die Großeltern des Brautpaares und macht ein Generationen-Foto. (Liebe)
13. Stellt eine Szene aus dem Lieblingsfilm des Brautpaares nach. (Teamgeist)
14. Macht ein Kuss-Foto mit eurem eigenen Partner. (Romantik)
15. Fotografiert die Schuhe der Braut neben den Schuhen des Bräutigams. (Romantik)
16. Findet das jüngste und das älteste Familienmitglied auf der Feier für ein gemeinsames Bild. (Nostalgie)
17. Macht ein Foto von den Händen von drei verschiedenen Generationen. (Rührung)
18. Werft dem Brautpaar aus der Ferne eine Kusshand zu. (Liebe)
19. Macht ein Foto mit jemandem, der heute zum ersten Mal auf einer Hochzeit ist. (Überraschung)
20. Fotografiert das Detail an der Hochzeitsdeko, das euch am besten gefällt. (Besinnlichkeit)
21. Macht ein Gruppenfoto mit allen Gästen von eurem Tisch. (Teamgeist)
22. Findet einen Gast mit einer besonders schicken Krawatte oder Fliege. (Stolz)
23. Tanzt mit einem Elternteil des Brautpaares und haltet den Moment fest. (Freude)
24. Macht ein Foto, das die Aufregung kurz vor dem Ja-Wort einfängt. (Rührung)
25. Fotografiert das Gästebuch in Aktion. (Nostalgie)
26. Macht ein Foto von eurem Lieblingsmoment des Tages. (Besinnlichkeit)
27. Findet einen Gegenstand, der die Farbe "Blau" enthält (etwas Altes, Neues, Geliehenes, Blaues). (Tradition/Nostalgie)
28. Macht ein Foto, auf dem ihr dem Brautpaar für die Zukunft zuprostet. (Stolz)
29. Organisiert ein "Gruppen-Herz" mit so vielen Leuten wie möglich. (Teamgeist)
30. Fotografiert einen Moment stiller Zweisamkeit des Brautpaares. (Romantik)
31. Macht ein Foto mit dem DJ oder einem Mitglied der Band. (Freude)
32. Findet die Person mit dem ansteckendsten Lachen. (Freude)
33. Fotografiert den Brautstraußwurf. (Überraschung)
34. Macht ein Foto mit demjenigen, der den Brautstrauß gefangen hat. (Stolz)
35. Stellt eure beste Tanzpose zur Schau. (Ekstase)
36. Macht ein Foto, das "Für immer und ewig" symbolisiert. (Liebe)
37. Findet einen Gast, der die gleiche Schuhgröße hat wie ihr. (Überraschung)
38. Fotografiert die leeren Tanzschuhe einer Frau, die barfuß tanzt. (Ekstase)
39. Macht ein Foto von einem Kind, das eingeschlafen ist. (Rührung)
40. Schreibt dem Brautpaar eine Botschaft auf einen Zettel und haltet sie ins Bild. (Liebe)
41. Macht ein Foto mit dem "Blumenkind". (Freude)
42. Fotografiert einen Moment, in dem sich das Brautpaar tief in die Augen schaut. (Romantik)
43. Findet die Person, die die weiteste Anreise hatte. (Stolz)
44. Macht ein Foto, das die Freundschaft zwischen dem Bräutigam und seinem Trauzeugen zeigt. (Teamgeist)
45. Fotografiert einen geheimen Moment, den nicht jeder mitbekommt. (Besinnlichkeit)
46. Macht ein Foto von eurem Lieblingsteil des Hochzeitsmenüs. (Freude)
47. Findet einen Gast, der ein Kleid in der gleichen Farbe wie die Deko trägt. (Überraschung)
48. Macht ein Foto, das die Erleichterung und Freude nach der Trauung zeigt. (Ekstase)
49. Fotografiert die Geschenke für das Brautpaar. (Liebe)
50. Macht ein letztes Foto des Abends, das die Stimmung perfekt zusammenfasst. (Nostalgie)
---
## Geburtstag
1. Macht ein Foto mit dem Geburtstagskind. (Freude)
2. Umarmt das Geburtstagskind und haltet den Moment fest. (Liebe)
3. Macht ein Foto, auf dem ihr dem Geburtstagskind ein Ständchen singt. (Freude)
4. Fotografiert den Moment, in dem die Kerzen auf dem Kuchen ausgepustet werden. (Stolz)
5. Findet jemanden, der im selben Monat Geburtstag hat wie ihr. (Überraschung)
6. Macht ein Foto mit dem ältesten und dem jüngsten Gast auf der Party. (Nostalgie)
7. Stellt ein Kinderfoto des Geburtstagskindes nach. (Nostalgie)
8. Macht ein Foto mit dem Geschenk, das ihr mitgebracht habt. (Liebe)
9. Fotografiert den Geschenketisch. (Überraschung)
10. Macht ein Gruppenfoto mit allen, die dem Geburtstagskind gerade am nächsten stehen. (Teamgeist)
11. Findet die Person mit dem besten Tanz-Move und fordert sie heraus. (Ekstase)
12. Macht ein Foto, auf dem ihr so tut, als wärt ihr das Geburtstagskind. (Freude)
13. Fotografiert einen herzhaften Lacher des Geburtstagskindes. (Freude)
14. Macht ein Foto mit einem Familienmitglied des Geburtstagskindes. (Rührung)
15. Findet einen Gegenstand, der das neue Lebensjahr symbolisiert. (Stolz)
16. Macht ein Selfie mit dem Haustier des Geburtstagskindes (falls vorhanden). (Liebe)
17. Fotografiert die Dekoration, die euch am besten gefällt. (Besinnlichkeit)
18. Macht ein Foto, auf dem ihr eure beste "Überraschung!"-Miene aufsetzt. (Überraschung)
19. Findet jemanden, den ihr seit über 10 Jahren nicht gesehen habt. (Nostalgie)
20. Prostet dem Geburtstagskind zu. (Stolz)
21. Macht ein Foto von eurem Lieblings-Snack auf der Party. (Freude)
22. Bildet mit einer Gruppe das Alter des Geburtstagskindes mit euren Körpern. (Teamgeist)
23. Macht ein Foto mit jemandem, der die gleiche Lieblingsfarbe hat wie das Geburtstagskind. (Teamgeist)
24. Fotografiert einen Moment der Ruhe, in dem das Geburtstagskind einfach nur genießt. (Besinnlichkeit)
25. Macht ein Foto mit dem besten Freund/der besten Freundin des Geburtstagskindes. (Liebe)
26. Findet einen Gast, der eine lustige Anekdote über das Geburtstagskind erzählen kann. (Nostalgie)
27. Macht ein Foto, das eure Freundschaft zum Geburtstagskind beschreibt. (Liebe)
28. Fotografiert die leeren Gläser nach einer Runde Anstoßen. (Ekstase)
29. Macht ein Foto, auf dem ihr so tut, als würdet ihr ein Geschenk klauen. (Überraschung)
30. Findet die Person, die am lautesten singt. (Ekstase)
31. Macht ein Foto von den Schuhen des Geburtstagskindes. (Stolz)
32. Fotografiert einen Moment, in dem jemand eine rührende Rede hält. (Rührung)
33. Macht ein Foto mit jemandem, der die gleiche Haarfarbe hat wie ihr. (Überraschung)
34. Stellt eure "Ich habe das beste Geschenk"-Pose zur Schau. (Stolz)
35. Macht ein Foto, das die pure Lebensfreude einfängt. (Ekstase)
36. Findet einen Ort auf der Party, der eine besondere Bedeutung für das Geburtstagskind hat. (Nostalgie)
37. Macht ein Foto, das zeigt, wie sehr ihr euch auf das nächste Jahr freut. (Stolz)
38. Fotografiert die Playlist oder den DJ-Pult. (Freude)
39. Macht ein Foto mit jemandem, der eine Brille trägt. (Teamgeist)
40. Findet einen Gast, der die gleiche Lieblingsband hat wie das Geburtstagskind. (Teamgeist)
41. Macht ein Foto, das einen Insider-Witz darstellt, den nur ihr und das Geburtstagskind versteht. (Nostalgie)
42. Fotografiert einen Moment, in dem das Geburtstagskind sichtlich gerührt ist. (Rührung)
43. Macht ein Foto von der Geburtstagskarte, die euch am besten gefällt. (Liebe)
44. Findet die Person, die am weitesten für die Party angereist ist. (Stolz)
45. Macht ein Foto, das "Party des Jahres" schreit. (Ekstase)
46. Fotografiert einen Sonnenuntergang oder den Sternenhimmel während der Feier. (Besinnlichkeit)
47. Macht ein Foto mit jemandem, der ein Haustier mit einem lustigen Namen hat. (Überraschung)
48. Stellt eine typische Pose oder Geste des Geburtstagskindes nach. (Freude)
49. Macht ein Foto, das die Vorfreude auf den Kuchen zeigt. (Freude)
50. Macht ein Abschlussfoto mit dem müden, aber glücklichen Geburtstagskind am Ende des Abends. (Rührung)
---
## Weihnachten
1. Macht ein Foto mit der Person, die das festlichste Outfit trägt. (Stolz)
2. Fotografiert die schönste Christbaumkugel am Baum. (Besinnlichkeit)
3. Macht ein Selfie mit einer Weihnachtsmütze auf. (Freude)
4. Findet jemanden, der "Last Christmas" liebt (oder hasst) und diskutiert darüber. (Teamgeist)
5. Fotografiert einen Moment heimlicher Vorfreude auf die Geschenke. (Überraschung)
6. Macht ein Foto von einer herzlichen Familienumarmung. (Liebe)
7. Fotografiert die leuchtenden Augen eines Kindes beim Anblick des Baumes. (Rührung)
8. Macht ein Foto von eurem Lieblings-Weihnachtskeks. (Freude)
9. Findet die Person, die am meisten über einen Witz vom Weihnachtsmann lacht. (Ekstase)
10. Macht ein Foto, das die Wärme und Gemütlichkeit des Raumes einfängt. (Besinnlichkeit)
11. Stellt eine Szene aus der Weihnachtsgeschichte oder einem Weihnachtsfilm nach. (Teamgeist)
12. Macht ein Foto mit drei Generationen eurer Familie. (Nostalgie)
13. Fotografiert das unordentlichste Geschenkpapier nach dem Auspacken. (Ekstase)
14. Findet jemanden, der Socken zu Weihnachten bekommen hat und sich ehrlich freut. (Überraschung)
15. Macht ein Foto, auf dem ihr so tut, als wärt ihr ein Engel auf der Baumspitze. (Freude)
16. Fotografiert einen Mistelzweig in Aktion. (Romantik)
17. Macht ein Foto mit der Person, die das Essen gekocht hat, als Dankeschön. (Liebe)
18. Findet das älteste Stück Weihnachtsschmuck in der Wohnung. (Nostalgie)
19. Macht ein Foto, auf dem ihr andächtig einer Weihnachtsgeschichte lauscht. (Besinnlichkeit)
20. Fotografiert einen Moment des gemeinsamen Singens. (Rührung)
21. Macht ein Gruppenfoto, auf dem alle ihre "hässlichen Weihnachtspullover" zeigen. (Teamgeist)
22. Findet jemanden, der sich über sein Geschenk am meisten gefreut hat. (Stolz)
23. Macht ein Foto von den dampfenden Tassen mit Glühwein oder Kakao. (Freude)
24. Fotografiert einen Moment der Stille vor der Bescherung. (Besinnlichkeit)
25. Macht ein Foto mit jemandem, der im Dezember Geburtstag hat. (Überraschung)
26. Findet das Geschenk mit der schönsten Schleife. (Stolz)
27. Macht ein Foto, das "Frieden auf Erden" symbolisiert. (Liebe)
28. Fotografiert die leeren Teller nach dem Weihnachtsessen. (Freude)
29. Macht ein Foto aus der Perspektive eines Geschenks unter dem Baum. (Überraschung)
30. Findet jemanden, der noch an den Weihnachtsmann glaubt (oder so tut als ob). (Nostalgie)
31. Macht ein Foto, das die Aufregung beim Würfeln um Geschenke (Wichteln) zeigt. (Ekstase)
32. Fotografiert eine Kerze, die für jemanden brennt, der nicht hier sein kann. (Rührung)
33. Macht ein Foto mit eurem Lieblingsgeschenk, das ihr bekommen habt. (Stolz)
34. Findet die Person, die am besten "Oh Tannenbaum" singen kann. (Teamgeist)
35. Macht ein Foto, das die Magie des Schneefalls zeigt (falls es schneit). (Romantik)
36. Fotografiert einen Moment, in dem alte Familiengeschichten erzählt werden. (Nostalgie)
37. Macht ein Foto von jemandem, der ein Nickerchen nach dem Essen macht. (Rührung)
38. Findet das kleinste und das größte Geschenk unter dem Baum. (Überraschung)
39. Macht ein Foto, das eure Dankbarkeit für diesen Moment ausdrückt. (Liebe)
40. Fotografiert die Vorbereitungen in der Küche. (Teamgeist)
41. Macht ein Foto, auf dem ihr versucht, heimlich vom Nachtisch zu naschen. (Überraschung)
42. Findet jemanden, der alle Rentiere des Weihnachtsmanns aufzählen kann. (Stolz)
43. Macht ein Foto, das die besondere Verbindung zu euren Geschwistern zeigt. (Liebe)
44. Fotografiert den Adventskranz. (Besinnlichkeit)
45. Macht ein Foto von den Fußspuren im Schnee. (Nostalgie)
46. Findet die Person, die am aufgeregtesten ist, einen bestimmten Film zu sehen. (Ekstase)
47. Macht ein Foto, das die Freude am Geben zeigt. (Liebe)
48. Fotografiert die Tischdekoration im Detail. (Stolz)
49. Macht ein Foto von einem handgemachten Geschenk. (Rührung)
50. Macht ein letztes Gruppenfoto vor dem Weihnachtsbaum, bevor die Feier endet. (Nostalgie)
---
## Konfirmation / Jugendweihe
1. Macht ein Foto mit dem Konfirmanden / Jugendweihe-Teilnehmer. (Stolz)
2. Fotografiert die Urkunde oder das Erinnerungsdokument. (Stolz)
3. Macht ein Foto mit den Paten oder Mentoren. (Teamgeist)
4. Findet die Großeltern und macht ein Foto, das ihren Stolz zeigt. (Rührung)
5. Fotografiert einen Moment des Nachdenkens oder Gebets in der Kirche/am Ort der Feier. (Besinnlichkeit)
6. Macht ein Gruppenfoto mit allen jungen Leuten, die heute ebenfalls gefeiert werden. (Teamgeist)
7. Fotografiert die festliche Kleidung des Hauptakteurs im Detail. (Stolz)
8. Macht ein Foto mit einem Gast, der euch einen guten Ratschlag für die Zukunft gibt. (Besinnlichkeit)
9. Findet das schönste Blumenarrangement. (Freude)
10. Macht ein Foto, das die feierliche Atmosphäre einfängt. (Besinnlichkeit)
11. Fotografiert den Moment des Anstoßens auf die Zukunft. (Stolz)
12. Macht ein Foto mit euren Eltern, das ihre Liebe und Unterstützung zeigt. (Liebe)
13. Findet einen Gast, der bei seiner eigenen Konfirmation/Jugendweihe dabei war und fragt nach einer Anekdote. (Nostalgie)
14. Fotografiert die brennenden Kerzen. (Besinnlichkeit)
15. Macht ein Foto, das die Aufregung und Nervosität vor dem großen Moment zeigt. (Rührung)
16. Findet das Gesangbuch oder Programmheft und macht ein Foto davon. (Nostalgie)
17. Macht ein Foto mit dem Pfarrer, Redner oder Organisator der Feier. (Teamgeist)
18. Fotografiert den Geschenketisch. (Überraschung)
19. Macht ein Foto, das die Verbindung zwischen den Generationen darstellt. (Liebe)
20. Findet einen Gast, der dem Konfirmanden/Jugendweihe-Teilnehmer besonders ähnlich sieht. (Überraschung)
21. Macht ein Foto von der festlich gedeckten Tafel. (Stolz)
22. Fotografiert einen Moment herzlichen Lachens. (Freude)
23. Macht ein Foto mit einem Freund, den ihr durch den Konfirmandenunterricht/die Vorbereitung kennengelernt habt. (Teamgeist)
24. Findet einen ruhigen Ort und macht ein Foto, das eure Gedanken über die Zukunft festhält. (Besinnlichkeit)
25. Macht ein Foto, das "ein neuer Lebensabschnitt beginnt" symbolisiert. (Stolz)
26. Fotografiert die Glückwunschkarten. (Liebe)
27. Macht ein Foto mit jemandem, der ein Kreuz oder ein anderes Symbol des Tages trägt. (Teamgeist)
28. Findet einen Gast, der eine besonders rührende Geschichte erzählen kann. (Rührung)
29. Macht ein Foto von den Schuhen bereit für den neuen Weg. (Stolz)
30. Fotografiert die Torte oder das Dessertbuffet. (Freude)
31. Macht ein Foto, das die Erleichterung nach dem offiziellen Teil zeigt. (Ekstase)
32. Findet einen Gast, der den weitesten Weg auf sich genommen hat. (Stolz)
33. Macht ein Foto, das Dankbarkeit ausdrückt. (Liebe)
34. Fotografiert ein Detail der Architektur des Feierortes. (Besinnlichkeit)
35. Macht ein Foto mit euren Geschwistern. (Liebe)
36. Findet jemanden, der ein altes Foto von euch als Kind dabei hat. (Nostalgie)
37. Macht ein Foto, das die Freude über ein besonderes Geschenk zeigt. (Überraschung)
38. Fotografiert die Hände eurer Eltern, die euch halten. (Rührung)
39. Macht ein Foto, auf dem ihr in den Himmel schaut und an die Zukunft denkt. (Besinnlichkeit)
40. Findet die Person mit dem besten Ratschlag für das Erwachsenwerden. (Teamgeist)
41. Macht ein Foto, das die Freundschaften feiert, die euch bis hierher begleitet haben. (Liebe)
42. Fotografiert die Musikinstrumente, die gespielt werden (Orgel, Klavier etc.). (Rührung)
43. Macht ein Foto von einem Lächeln, das von Herzen kommt. (Freude)
44. Findet einen Gegenstand, der für euch persönlich diesen Tag symbolisiert. (Nostalgie)
45. Macht ein Foto, das die Aufbruchstimmung des Tages einfängt. (Ekstase)
46. Fotografiert die Dekoration, die von der Familie selbst gemacht wurde. (Stolz)
47. Macht ein Foto mit der Person, die euch heute am meisten zum Lachen gebracht hat. (Freude)
48. Findet einen Moment, um dem Hauptakteur des Tages im Stillen alles Gute zu wünschen. (Liebe)
49. Fotografiert die leeren Plätze nach dem Ende der Zeremonie. (Nostalgie)
50. Macht ein letztes Foto des Tages, das den Übergang in einen neuen Lebensabschnitt festhält. (Stolz)
---
## Schulabschluss / Abitur
1. Werft eure Hüte in die Luft! (Ekstase)
2. Macht ein Foto mit eurem Abschlusszeugnis. (Stolz)
3. Umarme deine besten Schulfreunde für ein Gruppenfoto. (Liebe)
4. Macht ein Foto mit eurem Lieblingslehrer. (Rührung)
5. Findet eure Eltern und macht ein Foto, das ihren Stolz zeigt. (Stolz)
6. Stellt ein Foto vom ersten Schultag nach. (Nostalgie)
7. Macht ein Foto, auf dem ihr so tut, als würdet ihr für eine Prüfung lernen. (Nostalgie)
8. Findet jemanden, mit dem ihr seit der Grundschule in einer Klasse wart. (Nostalgie)
9. Macht ein Foto mit eurem "Partner in Crime" aus der Schulzeit. (Teamgeist)
10. Fotografiert die Unterschrift eures Lieblingslehrers auf eurem Zeugnis oder Jahrbuch. (Stolz)
11. Macht ein Foto, das eure Pläne für die Zukunft symbolisiert (z.B. mit einem Reiseführer, einem Lehrbuch). (Besinnlichkeit)
12. Findet die Person, die die verrücktesten Pläne nach dem Abschluss hat. (Überraschung)
13. Macht ein Gruppenfoto mit eurer gesamten Clique. (Teamgeist)
14. Fotografiert einen Moment, in dem Tränen des Abschieds und der Freude fließen. (Rührung)
15. Macht ein Foto, auf dem ihr auf die bestandenen Prüfungen anstoßt. (Ekstase)
16. Findet den Ort auf dem Schulgelände, an dem ihr die meiste Zeit verbracht habt. (Nostalgie)
17. Macht ein Foto mit jemandem aus eurem Abschlussball-Komitee oder Organisationsteam. (Teamgeist)
18. Fotografiert die Schuhe, die ihr auf dem Abschlussball tragt. (Stolz)
19. Macht ein Foto, das die Erleichterung nach der letzten Prüfung zeigt. (Ekstase)
20. Findet jemanden, der den gleichen Studien- oder Berufswunsch hat. (Teamgeist)
21. Macht ein Foto, auf dem ihr euren Eltern für ihre Unterstützung dankt. (Liebe)
22. Fotografiert das Cover eures Jahrbuchs. (Nostalgie)
23. Macht ein Foto mit jemandem, den ihr erst im letzten Schuljahr richtig kennengelernt habt. (Überraschung)
24. Findet die Person mit dem extravagantesten Outfit. (Stolz)
25. Macht ein Foto, das die Freiheit nach der Schule symbolisiert. (Freude)
26. Fotografiert einen Lehrer, der sichtlich gerührt ist. (Rührung)
27. Macht ein Foto mit euren Geschwistern. (Liebe)
28. Findet den "Klassenclown" für ein lustiges Foto. (Freude)
29. Macht ein Foto, das eure Freundschaft für immer festhält. (Liebe)
30. Fotografiert die leere Aula oder das leere Klassenzimmer. (Besinnlichkeit)
31. Macht ein Foto, auf dem ihr so tut, als würdet ihr die Schule "sprengen". (Ekstase)
32. Findet jemanden, der während der Rede des Schulleiters eingeschlafen ist. (Überraschung)
33. Macht ein Foto mit der Person, von der ihr am meisten abgeschrieben habt (oder umgekehrt). (Teamgeist)
34. Fotografiert die Dekoration der Abschlussfeier. (Freude)
35. Macht ein Foto, das den Sonnenaufgang nach einer langen Partynacht zeigt. (Nostalgie)
36. Findet den Lehrer, der euch am meisten inspiriert hat. (Rührung)
37. Macht ein Foto, das euren Traumjob darstellt. (Besinnlichkeit)
38. Fotografiert die peinlichste Tanz-Einlage des Abends. (Ekstase)
39. Macht ein Foto mit jemandem, der plant, die Welt zu bereisen. (Überraschung)
40. Findet euren Sitznachbarn aus der letzten Reihe. (Nostalgie)
41. Macht ein Foto, das den Moment des Abschieds von einem guten Freund festhält. (Rührung)
42. Fotografiert das Buffet oder die Getränkebar. (Freude)
43. Macht ein Foto, das zeigt, wie ihr eure Schulbücher "wegwerft". (Freude)
44. Findet jemanden, der den gleichen Notendurchschnitt hat wie ihr. (Teamgeist)
45. Macht ein Foto, das die Aufregung vor dem Betreten der Bühne zeigt. (Stolz)
46. Fotografiert die stolzen Gesichter eurer Großeltern. (Rührung)
47. Macht ein Foto, das "Die Welt gehört uns" schreit. (Ekstase)
48. Findet einen ruhigen Moment und reflektiert über die vergangene Zeit. (Besinnlichkeit)
49. Macht ein Foto mit der Person, die ihr am meisten vermissen werdet. (Liebe)
50. Macht ein letztes gemeinsames Foto als "Abschlussklasse von...". (Teamgeist)
---
## Corporate Event
1. Macht ein Foto mit eurem direkten Team. (Teamgeist)
2. Findet den CEO oder einen hochrangigen Manager für ein Selfie. (Stolz)
3. Macht ein Foto mit jemandem aus einer anderen Abteilung, den ihr heute kennengelernt habt. (Teamgeist)
4. Fotografiert das Firmenlogo aus einer kreativen Perspektive. (Stolz)
5. Macht ein Foto, auf dem ihr auf einen gemeinsamen Erfolg anstoßt. (Stolz)
6. Findet die Person, die am längsten im Unternehmen ist. (Nostalgie)
7. Macht ein Foto mit einem neuen Mitarbeiter (Newbie). (Teamgeist)
8. Fotografiert einen Moment intensiven Networkings. (Besinnlichkeit)
9. Macht ein Foto, das die Werte eures Unternehmens darstellt. (Besinnlichkeit)
10. Findet die Person mit dem lustigsten Jobtitel. (Überraschung)
11. Macht ein Foto, das die gute Stimmung auf dem Event einfängt. (Freude)
12. Fotografiert die Präsentation oder Rede, die euch am meisten inspiriert hat. (Besinnlichkeit)
13. Macht ein Foto mit eurem "Work-Buddy" oder Büro-Freund. (Liebe)
14. Findet das Team, das einen Preis oder eine Auszeichnung gewonnen hat. (Stolz)
15. Macht ein Foto, das "Innovation" symbolisiert. (Überraschung)
16. Fotografiert das Buffet und stellt euren Lieblingsteller zusammen. (Freude)
17. Macht ein Foto mit jemandem, der die gleiche Krawatte oder das gleiche Kleid trägt. (Überraschung)
18. Findet die Person, die für die Organisation des Events verantwortlich ist, und bedankt euch. (Teamgeist)
19. Macht ein Foto, das die Internationalität eures Unternehmens zeigt (mit Kollegen aus verschiedenen Ländern). (Teamgeist)
20. Fotografiert einen Moment herzhaften Lachens unter Kollegen. (Freude)
21. Macht ein Foto, auf dem ihr so tut, als würdet ihr einen wichtigen Vertrag unterzeichnen. (Stolz)
22. Findet die Person, die am besten tanzen kann. (Ekstase)
23. Macht ein Foto, das die "Work-Life-Balance" auf dem Event darstellt. (Freude)
24. Fotografiert die Location oder die Dekoration, die euch am besten gefällt. (Besinnlichkeit)
25. Macht ein Foto mit eurem Mentor oder jemandem, von dem ihr viel gelernt habt. (Rührung)
26. Findet die Person, die den weitesten Weg zum Event hatte. (Stolz)
27. Macht ein Foto, das einen Moment der Zusammenarbeit zeigt. (Teamgeist)
28. Fotografiert die "Goodie-Bag" oder das Werbegeschenk. (Überraschung)
29. Macht ein Foto mit jemandem aus dem IT-Support sie sind die wahren Helden. (Teamgeist)
30. Findet die Person, die immer Kaffee für alle kocht. (Liebe)
31. Macht ein Foto, das den Erfolg des letzten Quartals feiert. (Ekstase)
32. Fotografiert einen Moment, in dem jemand eine anerkennende Rede hält. (Rührung)
33. Macht ein Foto, das die Zukunft des Unternehmens symbolisiert. (Besinnlichkeit)
34. Findet die Person, die am elegantesten gekleidet ist. (Stolz)
35. Macht ein Foto, das den "Feierabend"-Moment nach dem offiziellen Teil zeigt. (Ekstase)
36. Fotografiert die Visitenkarten, die ihr gesammelt habt. (Nostalgie)
37. Macht ein Foto mit jemandem, mit dem ihr nur per E-Mail kommuniziert habt und den ihr jetzt persönlich trefft. (Überraschung)
38. Findet die Person, die am meisten zum Erfolg eures letzten Projekts beigetragen hat. (Stolz)
39. Macht ein Foto, das die entspannte Seite eures Chefs zeigt. (Überraschung)
40. Fotografiert die Band oder den DJ. (Freude)
41. Macht ein Foto, das den Team-Zusammenhalt perfekt einfängt. (Teamgeist)
42. Findet einen ehemaligen Mitarbeiter, der zu Besuch ist. (Nostalgie)
43. Macht ein Foto, das eure Motivation für das nächste Geschäftsjahr zeigt. (Stolz)
44. Fotografiert einen Moment, in dem neue Ideen gesponnen werden. (Besinnlichkeit)
45. Macht ein Foto mit der Person, die euch heute am meisten zum Lachen gebracht hat. (Freude)
46. Findet die "gute Seele" eurer Abteilung. (Liebe)
47. Macht ein Foto, das die Erleichterung nach einer erfolgreichen Präsentation zeigt. (Ekstase)
48. Fotografiert einen rührenden Moment, z.B. die Verabschiedung eines langjährigen Kollegen. (Rührung)
49. Macht ein Foto, das zeigt, dass eure Firma mehr als nur ein Arbeitsplatz ist. (Liebe)
50. Macht ein letztes Gruppenfoto, das die Energie des Events festhält. (Teamgeist)

View File

@@ -0,0 +1,270 @@
---
title: "Fotospiel Howto & Hilfecenter"
description: "Ausführliche Schritt-für-Schritt-Anleitungen, Best Practices und FAQs zur Fotospiel App."
lang: "de"
last_updated: "2025-11-02"
---
# 📚 Fotospiel So funktionierts (Howto)
Dieses Dokument bündelt alle Anleitungen für Veranstalter:innen und Gäste. Es ist so aufgebaut, dass du es direkt in deine Website/Doku übernehmen kannst.
**Inhalt**
- [1. Wie funktioniert die FotospielApp?](#1-wie-funktioniert-die-fotospiel-app)
- [2. Für welche Events eignet sich Fotospiel?](#2-für-welche-events-eignet-sich-fotospiel)
- [3. So funktioniert das Teilen und Sammeln von Gastfotos](#3-so-funktioniert-das-teilen-und-sammeln-von-gastfotos)
- [4. Was passiert mit meinen Fotos nach dem Event?](#4-was-passiert-mit-meinen-fotos-nach-dem-event)
- [5. Datenschutz & Sicherheit](#5-datenschutz--sicherheit)
- [6. So einfach ist der Start mit Fotospiel](#6-so-einfach-ist-der-start-mit-fotospiel)
- [FAQ](#faq)
> **Hinweis:** Für Integrationen mit Fotobox/DSLRBooth entsteht ein separater Leitfaden, sobald die Details final sind.
---
## 1. Wie funktioniert die FotospielApp?
**Kurz gesagt:** Du erstellst ein Event, teilst einen Link oder QRCode, und alle Gäste laden ihre Fotos direkt über den mobilen Browser in eure **gemeinsame, geschützte Galerie** hoch ohne AppInstallation.
### 1.1 Rollen & Begriffe
- **Veranstalter:in (Host):** erstellt und verwaltet das Event, teilt den QRCode/Link, moderiert Inhalte, lädt Daten herunter.
- **Gäste:** scannen den QRCode oder öffnen den Link, machen Fotos/kurze Clips und laden sie hoch; keine Registrierung notwendig.
- **Galerie:** der zentrale Ort für alle Eventfotos (optional mit LiveAnzeige auf TV/Beamer).
- **Aufgaben (optional):** kleine FotoChallenges, die für Abwechslung und Spaß sorgen („Selfie mit dem Brautpaar“, „Etwas Blaues finden“).
### 1.2 Ablauf auf einen Blick
```
[Event anlegen] → [QR/Link teilen] → [Gäste scannen] → [Fotos aufnehmen] → [Upload in Galerie] → [Ansehen/Teilen/Download]
```
### 1.3 SchrittfürSchritt
1. **Event erstellen:** Titel, Datum/Uhrzeit, Beschreibung, optional: Fotoaufgaben, Sichtbarkeits- & Moderationsregeln.
2. **Freigabe vorbereiten:** QRCode/Link generieren. Einbettung in EMails, Messenger, digitale Einladung, Druck (Tischnummern, Aufsteller).
3. **Start am Eventtag:** QRCode sichtbar platzieren (Eingang, Photobooth, Buffettisch, Leinwand). Optional: **LiveGalerie** auf TV/Beamer.
4. **Gäste uploaden:** Browser öffnen → Kamera nutzen oder vorhandene Bilder auswählen → optional Kurzkommentar hinzufügen → **Hochladen**.
5. **Moderation & Rechte:** Host kann Beiträge prüfen, ausblenden, löschen; bei Bedarf Freigabefenster/Filter aktivieren.
6. **Nach dem Event:** Bilder herunterladen (ZIP/Einzelauswahl), Galerie teilen, optional: DankesNachricht an Gäste senden.
### 1.4 Geräte & Browser
- **Unterstützt:** aktuelle iOS/AndroidBrowser (Safari, Chrome, Firefox, Edge), aktuelle DesktopBrowser.
- **Tipps:**
- Bitte **Berechtigungen** für Kamera/Fotos erlauben.
- Für ältere Geräte: Upload aus der Galerie statt LiveKamera.
- Stabile **WLAN/LTE**Verbindung empfohlen (OfflineFotos werden lokal gespeichert und können später hochgeladen werden, sobald wieder Internet besteht).
### 1.5 Features im Überblick
- **Ohne AppInstallation** (WebApp im Browser)
- **Gemeinsame Galerie** mit LiveAnsicht (optional)
- **Moderation/Filter** (vor oder nach Veröffentlichung)
- **Fotoaufgaben & Gamification** (optional)
- **Download als ZIP** und Einzelauswahl
- **Rollen & Rechte** für Host/CoHosts (optional, je nach Paket)
- **Datenschutz by Design:** keine PflichtRegistrierung für Gäste
### 1.6 Best Practices für starke Teilnahme
- QRCode **früh** und **sichtbar** platzieren (Einlass, Programmheft, Tischnummern).
- **Moderator:in/Trauzeug:innen/MC** bittet Gäste aktiv ums Mitmachen.
- **Kurze Demo**: „Kamera auf QR → Browser öffnet → Foto hochladen fertig!“
- **Belohnungen/Challenges**: kleine Preise oder Erwähnungen in der Rede.
- **Erinnerung** später am Abend + **Followup** am Folgetag mit Link.
---
## 2. Für welche Events eignet sich Fotospiel?
Fotospiel ist für jede Veranstaltung gedacht, auf der Menschen **Momente teilen** möchten. Hier ein schneller Überblick mit **Ziel**, **Empfehlungen** und **BeispielAufgaben**.
### 2.1 Hochzeiten 💍
- **Ziel:** Emotionen und Perspektiven der Gäste einfangen jenseits der klassischen Paarfotos.
- **Empfehlungen:** QRCode an den Tischen/Programmheften; Moderation durch Trauzeug:innen; LiveSlideshow beim Empfang.
- **Aufgabenideen:** „Selfie mit dem Brautpaar“, „Der schönste Tanzmove“, „Etwas Blaues“, „Bestes Gruppenfoto am Tisch 4“.
### 2.2 Geburtstage & Jubiläen 🎉
- **Ziel:** Spontane Schnappschüsse, Gratulationen, lustige Momente.
- **Empfehlungen:** QRCode als Tischaufsteller; kurzer Hinweis in der Geburtstagsrede; kleiner Preis für das kreativste Bild.
- **Aufgabenideen:** „Peinliches ThrowbackFoto nachstellen“, „Größtes Gruppenlächeln“, „GeburtstagskuchenCloseup“.
### 2.3 Firmenfeiern & Teamevents 👔
- **Ziel:** Teamgefühl, Employer Branding, authentische Einblicke.
- **Empfehlungen:** BrandingHintergrund/Photowall; live auf Displays im Foyer; Moderation über Moderator:in/HR.
- **Aufgabenideen:** „Bestes TeamSelfie“, „BehindtheScenes“, „Neues Firmengesicht kennenlernen“.
### 2.4 Vereins, Schul & Familienfeste 🧒🎭
- **Ziel:** Viele Perspektiven bündeln, Eltern/Großeltern unkompliziert einbinden.
- **Empfehlungen:** QRCode am Eingang & Aushängen; klare Hinweise zu Sichtbarkeitsregeln; Moderation bei Kinderfotos.
- **Aufgabenideen:** „FanMoment“, „Unser Team in Action“, „Bester KreativStand“.
### 2.5 Festivals, Märkte & öffentliche Events 🌈
- **Ziel:** CommunityMomente, SocialSharing, Rückblickscontent.
- **Empfehlungen:** Großformatige QRPoster, SocialMediaHinweise, Hashtags; zentrale Screens mit LiveGalerie.
- **Aufgabenideen:** „Buntestes Outfit“, „LieblingsAct“, „Geheime Ecke des Festivals“.
> **Tipp:** Passe die **Sichtbarkeit** (öffentlich/privat), **Moderation** und **Downloadrechte** pro Eventtyp an.
---
## 3. So funktioniert das Teilen und Sammeln von Gastfotos
### 3.1 Freigabe: QRCode & Link
- **QRCode drucken:** Tischnummern, Aufsteller, EinlassBadges, Plakate.
- **Digital teilen:** EMailEinladung, Messenger, EventWebsite, BeamerFolie.
- **Best Practice Textbaustein (kopierfertig):**
> *„Teile deine Fotos mit uns! Scanne einfach diesen QRCode oder öffne **{{DEINLINK}}** im Browser, mach ein Foto und lade es hoch. Kein AppDownload nötig.“*
### 3.2 UploadFlow für Gäste
1. QRCode scannen oder Link öffnen.
2. Kamera/GalerieZugriff erlauben.
3. Foto/Clip aufnehmen oder auswählen.
4. Optional Text/Sticker/Aufgabenbezug hinzufügen.
5. **Hochladen** erscheint (sofort oder nach Freigabe) in der Galerie.
### 3.3 Moderation & Freigaben (für Hosts)
- **Modus wählen:**
- *Direkte Veröffentlichung* (schnell & dynamisch) oder
- *VorabFreigabe* (sicher & kuratiert).
- **Werkzeuge:** Ausblenden/Löschen, Markierungen (Favoriten), optional: Meldungen von Gästen.
- **Tipp:** Definiere vorab klare **Hausregeln** (z.B. keine Portraits ohne Einverständnis).
### 3.4 Organisation & Struktur
- **Alben/Abschnitte:** Empfang, Trauung, Party; Keynotes, Workshops, Networking.
- **Hashtags/Tags (optional):** #tisch3, #firstdance, #teamblue.
- **Kuratiertes Bestof:** Für die Startansicht oder die LiveGalerie.
### 3.5 Teilnahmebooster
- Kurze **Ansage** (MC/Trauzeug:innen/Moderator:in).
- **Challenges** mit MiniGewinn.
- **ErinnerungsPost** in der Mitte/gegen Ende des Events.
- **Followup** am nächsten Tag: „Ladet eure Favoriten noch hoch und ladet alles als ZIP herunter.“
### 3.6 Fehlerbehebung (QuickHelp)
- **Kamera geht nicht?** Berechtigungen prüfen (Einstellungen → Browser → Kamera).
- **Upload langsam?** WLAN nutzen, kleinere Dateien wählen; später erneut versuchen.
- **Link lädt nicht?** Korrekte URL/QR testen; alternative Browser versuchen.
- **Falsches Event?** Link/QR veraltet neuen Code vom Host anfordern.
---
## 4. Was passiert mit meinen Fotos nach dem Event?
### 4.1 Lebenszyklus der Galerie
1. **Während des Events:** Uploads & LiveAnsicht (optional).
2. **Nach dem Event:** Galerie bleibt **für einen definierten Zeitraum** je nach gewähltem Paket verfügbar.
3. **Ablauf der Frist:** Galerie wird geschlossen; Inhalte werden planmäßig gelöscht.
> **Wichtig:** Die konkreten Speicherzeiträume sind **paketabhängig**. Details findest du in der **Preisübersicht** und in der **Datenschutzerklärung**.
### 4.2 Deine Möglichkeiten als Host
- **ZIPDownload** aller Medien oder gezielte Einzelauswahl.
- **Bestof erstellen:** Favoriten markieren, extern teilen (z.B. mit Dienstleistern/Gästen).
- **Manuell schließen:** Event jederzeit beenden und Galerie auf „privat“ setzen.
### 4.3 Zugriff & Sichtbarkeit
- **Privat standardmäßig:** Zugang nur über den spezifischen Link/QR.
- **Optionale Freigabe:** Du entscheidest, ob und mit wem du teilst.
- **Widerruf:** Zugänge können jederzeit entzogen werden (Link wechseln, Event schließen).
### 4.4 Rechte & Einwilligungen (Hinweis, keine Rechtsberatung)
- Als Host solltest du **Teilnehmende informieren**, dass Fotos geteilt werden können.
- Respektiere Persönlichkeitsrechte (insb. Kinder/Schutzbedürftige).
- Bei professioneller Nutzung (Marketing) **Einwilligungen** gesondert einholen.
### 4.5 Taktische Tipps nach dem Event
- **Automatisierte DankesNachricht** mit Link zur Galerie/ZIP.
- **SocialMediaTeaser** (wenn gewünscht, mit Einverständnis).
- **Nachbestellung von Prints** (falls geplant, externer Dienst).
---
## 5. Datenschutz & Sicherheit
Fotospiel setzt auf **Privacy by Design** und **Transparenz**.
### 5.1 Grundsätze
- **Keine PflichtRegistrierung** für Gäste (Zugang via Link/QR).
- **Datenverarbeitung in Deutschland/EU** (Hosting bei Hetzner).
- **Zahlungen** über **Stripe/PayPal** **keine** Speicherung von Zahlungs­mittel­daten bei Fotospiel.
- **Minimierung von Cookies** (technisch notwendige + **Matomo** für Statistik).
### 5.2 Technische & organisatorische Maßnahmen (Auszug)
- **Transportverschlüsselung (HTTPS)** für alle Verbindungen.
- **Rollen & Berechtigungen** für Host/CoHosts (wo verfügbar).
- **Moderationsfunktionen** zum Schutz vor unerwünschten Inhalten.
- **Protokollierung** sicherheitsrelevanter Vorgänge (gemäß DSGVOGrundsätzen).
- **Auftragsverarbeitung:** Es besteht ein **AVV mit dem Hoster** (Hetzner).
> **Hinweis:** Details zu Speicherfristen, Betroffenenrechten (Auskunft, Löschung, Widerspruch), Kontaktmöglichkeiten und Verantwortlichen findest du in der **Datenschutzerklärung**.
### 5.3 Empfehlungen für Veranstalter:innen
- **Informationshinweis** am Eingang/bei der Einladung: „Es können Fotos gemacht & geteilt werden.“
- **Regelwerk** für Gastuploads kommunizieren (keine sensiblen Inhalte, respektvoller Umgang).
- **Kinder & besondere Gruppen:** Einwilligungen prüfen, sensible Bereiche ggf. kennzeichnen.
- **Löschung/Moderation** aktiv nutzen, wenn Inhalte nicht geteilt werden sollen.
---
## 6. So einfach ist der Start mit Fotospiel
### 6.1 In 10 Minuten startklar
1. **Registrieren & Event anlegen** (Titel, Datum, Kurzbeschreibung).
2. **Sichtbarkeit & Moderation** wählen (direkt live vs. Freigabe).
3. **Optionale Fotoaufgaben** erstellen (38 knackige Challenges).
4. **QRCode/Link generieren** und **testen** (Eigenes Handy!).
5. **Material drucken** (Tischaufsteller, A4Poster, BeamerSlide).
6. **Testlauf** mit 23 vertrauten Personen (Upload, Galerie, Download).
7. **LiveGalerie checken** (Bildwechsel, Intervall).
8. **Kurzansage vorbereiten** (MC/Trauzeug:in/Moderator:in).
9. **WLAN/LTE prüfen** (Fallback vorbereiten).
10. **Event starten** Spaß haben & Erinnerungen sammeln!
### 6.2 Vorlagen & Textbausteine
- **Einladung per Messenger/EMail:**
> *„Teile deine Fotos mit uns! Scanne beim Event den QRCode oder öffne **{{DEINLINK}}**. Kein AppDownload nötig einfach Foto machen & hochladen. Danke fürs Mitmachen!“*
- **Ansage vor Ort (MC):**
> *„Wer Lust hat, unsere Erinnerungen festzuhalten: Nehmt euer Handy, scannt den QRCode auf den Tischen und ladet eure Lieblingsmomente hoch. Später gibts eine LiveSlideshow!“*
- **Followup am nächsten Tag:**
> *„Danke, dass ihr dabei wart! Hier ist der Link zur Galerie: **{{DEINLINK}}**. Stöbert in den Fotos und ladet euch eure Favoriten als ZIP herunter.“*
### 6.3 Checkliste (druckfertig)
- [ ] Event angelegt, Einstellungen geprüft
- [ ] QRCode/Link generiert & getestet
- [ ] Druckmaterial erstellt (Tische, Eingang, Bühne)
- [ ] WLAN/LTE gecheckt, Steckdosen/Powerbanks bereit
- [ ] Moderation festgelegt (wer prüft, wer kündigt an?)
- [ ] LiveGalerie vorbereitet (TV/Beamer, Kabel/Adapter)
- [ ] DankesNachricht/Followup vorbereitet
---
## FAQ
**Brauchen Gäste eine App?**
Nein. Die Nutzung erfolgt im **mobilen Browser** via QRCode oder Link.
**Welche Dateiformate werden unterstützt?**
Fotos (JPEG/PNG/HEIC) und je nach Paket/Version kurze Clips. Größere Dateien werden automatisch skaliert/komprimiert.
**Was, wenn das WLAN ausfällt?**
Fotos können lokal aufgenommen und **später** hochgeladen werden, sobald wieder Internet verfügbar ist.
**Kann ich Beiträge erst prüfen, bevor sie sichtbar werden?**
Ja. Aktiviere den **FreigabeModus** in den EventEinstellungen.
**Wie lange bleiben die Fotos online?**
Die **Speicherdauer ist paketabhängig**. Details siehe **Preise** und **Datenschutzerklärung**.
**Kann ich einzelne Personen vom Upload ausschließen?**
Teile den Link/QR nur mit gewünschten Gästen; du kannst Beiträge **löschen** und die **Sichtbarkeit** jederzeit anpassen.
**Gibt es eine LiveSlideshow?**
Ja, optional. Sie zeigt neue Uploads automatisch auf TV/Beamer.
**Wie lade ich alles herunter?**
Als Host kannst du alle Medien **als ZIP** exportieren oder einzelne Dateien auswählen.
---
> 💬 **Support**
> Fragen oder Feedback? Wende dich jederzeit an den Support über das Kontaktformular auf der Website.

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
http://localhost:5173

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
var i=()=>({isSticky:!1,enableSticky(){this.isSticky=this.$el.getBoundingClientRect().top>0},disableSticky(){this.isSticky=!1}});export{i as default};
var i=()=>({isSticky:!1,width:0,resizeObserver:null,boundUpdateWidth:null,init(){let e=this.$el.parentElement;e&&(this.updateWidth(),this.resizeObserver=new ResizeObserver(()=>this.updateWidth()),this.resizeObserver.observe(e),this.boundUpdateWidth=this.updateWidth.bind(this),window.addEventListener("resize",this.boundUpdateWidth))},enableSticky(){this.isSticky=this.$el.getBoundingClientRect().top>0},disableSticky(){this.isSticky=!1},updateWidth(){let e=this.$el.parentElement;if(!e)return;let t=getComputedStyle(this.$root.querySelector(".fi-ac"));this.width=e.offsetWidth+parseInt(t.marginInlineStart,10)*-1+parseInt(t.marginInlineEnd,10)*-1},destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.boundUpdateWidth&&(window.removeEventListener("resize",this.boundUpdateWidth),this.boundUpdateWidth=null)}});export{i as default};

View File

@@ -1 +1 @@
(()=>{var d=()=>({isSticky:!1,enableSticky(){this.isSticky=this.$el.getBoundingClientRect().top>0},disableSticky(){this.isSticky=!1}});var m=function(i,e,n){let t=i;if(e.startsWith("/")&&(n=!0,e=e.slice(1)),n)return e;for(;e.startsWith("../");)t=t.includes(".")?t.slice(0,t.lastIndexOf(".")):null,e=e.slice(3);return["",null,void 0].includes(t)?e:["",null,void 0].includes(e)?t:`${t}.${e}`},u=i=>{let e=Alpine.findClosest(i,n=>n.__livewire);if(!e)throw"Could not find Livewire component in DOM tree.";return e.__livewire};document.addEventListener("alpine:init",()=>{window.Alpine.data("filamentSchema",({livewireId:i})=>({handleFormValidationError(e){e.detail.livewireId===i&&this.$nextTick(()=>{let n=this.$el.querySelector("[data-validation-error]");if(!n)return;let t=n;for(;t;)t.dispatchEvent(new CustomEvent("expand")),t=t.parentNode;setTimeout(()=>n.closest("[data-field-wrapper]").scrollIntoView({behavior:"smooth",block:"start",inline:"start"}),200)})},isStateChanged(e,n){if(e===void 0)return!1;try{return JSON.stringify(e)!==JSON.stringify(n)}catch{return e!==n}}})),window.Alpine.data("filamentSchemaComponent",({path:i,containerPath:e,$wire:n})=>({$statePath:i,$get:(t,o)=>n.$get(m(e,t,o)),$set:(t,o,l,a=!1)=>n.$set(m(e,t,l),o,a),get $state(){return n.$get(i)}})),window.Alpine.data("filamentActionsSchemaComponent",d),Livewire.hook("commit",({component:i,commit:e,respond:n,succeed:t,fail:o})=>{t(({snapshot:l,effects:a})=>{a.dispatches?.forEach(r=>{if(!r.params?.awaitSchemaComponent)return;let s=Array.from(i.el.querySelectorAll(`[wire\\:partial="schema-component::${r.params.awaitSchemaComponent}"]`)).filter(c=>u(c)===i);if(s.length!==1){if(s.length>1)throw`Multiple schema components found with key [${r.params.awaitSchemaComponent}].`;window.addEventListener(`schema-component-${i.id}-${r.params.awaitSchemaComponent}-loaded`,()=>{window.dispatchEvent(new CustomEvent(r.name,{detail:r.params}))},{once:!0})}})})})});})();
(()=>{var d=()=>({isSticky:!1,width:0,resizeObserver:null,boundUpdateWidth:null,init(){let t=this.$el.parentElement;t&&(this.updateWidth(),this.resizeObserver=new ResizeObserver(()=>this.updateWidth()),this.resizeObserver.observe(t),this.boundUpdateWidth=this.updateWidth.bind(this),window.addEventListener("resize",this.boundUpdateWidth))},enableSticky(){this.isSticky=this.$el.getBoundingClientRect().top>0},disableSticky(){this.isSticky=!1},updateWidth(){let t=this.$el.parentElement;if(!t)return;let e=getComputedStyle(this.$root.querySelector(".fi-ac"));this.width=t.offsetWidth+parseInt(e.marginInlineStart,10)*-1+parseInt(e.marginInlineEnd,10)*-1},destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.boundUpdateWidth&&(window.removeEventListener("resize",this.boundUpdateWidth),this.boundUpdateWidth=null)}});var u=function(t,e,n){let i=t;if(e.startsWith("/")&&(n=!0,e=e.slice(1)),n)return e;for(;e.startsWith("../");)i=i.includes(".")?i.slice(0,i.lastIndexOf(".")):null,e=e.slice(3);return["",null,void 0].includes(i)?e:["",null,void 0].includes(e)?i:`${i}.${e}`},c=t=>{let e=Alpine.findClosest(t,n=>n.__livewire);if(!e)throw"Could not find Livewire component in DOM tree.";return e.__livewire};document.addEventListener("alpine:init",()=>{window.Alpine.data("filamentSchema",({livewireId:t})=>({handleFormValidationError(e){e.detail.livewireId===t&&this.$nextTick(()=>{let n=this.$el.querySelector("[data-validation-error]");if(!n)return;let i=n;for(;i;)i.dispatchEvent(new CustomEvent("expand")),i=i.parentNode;setTimeout(()=>n.closest("[data-field-wrapper]").scrollIntoView({behavior:"smooth",block:"start",inline:"start"}),200)})},isStateChanged(e,n){if(e===void 0)return!1;try{return JSON.stringify(e)!==JSON.stringify(n)}catch{return e!==n}}})),window.Alpine.data("filamentSchemaComponent",({path:t,containerPath:e,$wire:n})=>({$statePath:t,$get:(i,s)=>n.$get(u(e,i,s)),$set:(i,s,a,o=!1)=>n.$set(u(e,i,a),s,o),get $state(){return n.$get(t)}})),window.Alpine.data("filamentActionsSchemaComponent",d),Livewire.hook("commit",({component:t,commit:e,respond:n,succeed:i,fail:s})=>{i(({snapshot:a,effects:o})=>{o.dispatches?.forEach(r=>{if(!r.params?.awaitSchemaComponent)return;let l=Array.from(t.el.querySelectorAll(`[wire\\:partial="schema-component::${r.params.awaitSchemaComponent}"]`)).filter(h=>c(h)===t);if(l.length!==1){if(l.length>1)throw`Multiple schema components found with key [${r.params.awaitSchemaComponent}].`;window.addEventListener(`schema-component-${t.id}-${r.params.awaitSchemaComponent}-loaded`,()=>{window.dispatchEvent(new CustomEvent(r.name,{detail:r.params}))},{once:!0})}})})})});})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -169,6 +169,7 @@ export default function EventInvitesPage(): React.ReactElement {
const [copiedInviteId, setCopiedInviteId] = React.useState<number | null>(null);
const [customizerSaving, setCustomizerSaving] = React.useState(false);
const [customizerResetting, setCustomizerResetting] = React.useState(false);
const [customizerDraft, setCustomizerDraft] = React.useState<QrLayoutCustomization | null>(null);
const [searchParams, setSearchParams] = useSearchParams();
const tabParam = searchParams.get('tab');
const initialTab = tabParam === 'export' || tabParam === 'links' ? (tabParam as TabKey) : 'layout';
@@ -277,6 +278,10 @@ export default function EventInvitesPage(): React.ReactElement {
});
}, [state.invites]);
React.useEffect(() => {
setCustomizerDraft(null);
}, [selectedInviteId]);
const currentCustomization = React.useMemo(() => {
if (!selectedInvite) {
return null;
@@ -286,12 +291,14 @@ export default function EventInvitesPage(): React.ReactElement {
return raw && typeof raw === 'object' ? (raw as QrLayoutCustomization) : null;
}, [selectedInvite]);
const effectiveCustomization = customizerDraft ?? currentCustomization;
const exportLayout = React.useMemo(() => {
if (!selectedInvite || selectedInvite.layouts.length === 0) {
return null;
}
const targetId = currentCustomization?.layout_id;
const targetId = effectiveCustomization?.layout_id;
if (targetId) {
const match = selectedInvite.layouts.find((layout) => layout.id === targetId);
if (match) {
@@ -300,14 +307,14 @@ export default function EventInvitesPage(): React.ReactElement {
}
return selectedInvite.layouts[0];
}, [selectedInvite, currentCustomization?.layout_id]);
}, [selectedInvite, effectiveCustomization?.layout_id]);
const exportPreview = React.useMemo(() => {
if (!exportLayout || !selectedInvite) {
return null;
}
const customization = currentCustomization ?? null;
const customization = effectiveCustomization ?? null;
const layoutPreview = exportLayout.preview ?? {};
const backgroundColor = normalizeHexColor(customization?.background_color ?? (layoutPreview.background as string | undefined)) ?? '#F8FAFC';
@@ -370,26 +377,26 @@ export default function EventInvitesPage(): React.ReactElement {
t('invites.export.tips.default3', 'Fotografiere den gedruckten QR-Code testweise, um die Lesbarkeit zu prüfen.'),
],
};
}, [exportLayout, currentCustomization, selectedInvite, eventName, t]);
}, [exportLayout, effectiveCustomization, selectedInvite, eventName, t]);
const exportElements = React.useMemo<LayoutElement[]>(() => {
if (!exportLayout) {
return [];
}
if (currentCustomization?.mode === 'advanced' && Array.isArray(currentCustomization.elements) && currentCustomization.elements.length) {
return normalizeElements(payloadToElements(currentCustomization.elements));
if (effectiveCustomization?.mode === 'advanced' && Array.isArray(effectiveCustomization.elements) && effectiveCustomization.elements.length) {
return normalizeElements(payloadToElements(effectiveCustomization.elements));
}
const baseForm: QrLayoutCustomization = {
...currentCustomization,
...effectiveCustomization,
layout_id: exportLayout.id,
link_label: currentCustomization?.link_label ?? selectedInvite?.url ?? '',
badge_label: currentCustomization?.badge_label ?? exportLayout.badge_label ?? undefined,
instructions: ensureInstructionList(currentCustomization?.instructions, exportLayout.instructions ?? []),
instructions_heading: currentCustomization?.instructions_heading ?? exportLayout.instructions_heading ?? undefined,
logo_data_url: currentCustomization?.logo_data_url ?? undefined,
logo_url: currentCustomization?.logo_url ?? undefined,
link_label: effectiveCustomization?.link_label ?? selectedInvite?.url ?? '',
badge_label: effectiveCustomization?.badge_label ?? exportLayout.badge_label ?? undefined,
instructions: ensureInstructionList(effectiveCustomization?.instructions, exportLayout.instructions ?? []),
instructions_heading: effectiveCustomization?.instructions_heading ?? exportLayout.instructions_heading ?? undefined,
logo_data_url: effectiveCustomization?.logo_data_url ?? undefined,
logo_url: effectiveCustomization?.logo_url ?? undefined,
};
return buildDefaultElements(
@@ -398,7 +405,7 @@ export default function EventInvitesPage(): React.ReactElement {
eventName,
exportLayout.preview?.qr_size_px ?? 480
);
}, [exportLayout, currentCustomization, selectedInvite?.url, eventName]);
}, [exportLayout, effectiveCustomization, selectedInvite?.url, eventName]);
React.useEffect(() => {
if (activeTab !== 'export') {
@@ -427,12 +434,23 @@ export default function EventInvitesPage(): React.ReactElement {
[selectedInvite?.id, exportLayout?.id, exportPreview?.mode]
);
const exportLogo = currentCustomization?.logo_data_url ?? currentCustomization?.logo_url ?? null;
const exportLogo = effectiveCustomization?.logo_data_url ?? effectiveCustomization?.logo_url ?? null;
const exportQr = selectedInvite?.qr_code_data_url ?? null;
const handlePreviewSelect = React.useCallback((_id: string | null) => undefined, []);
const handlePreviewChange = React.useCallback((_id: string, _patch: Partial<LayoutElement>) => undefined, []);
const handleCustomizerDraftChange = React.useCallback((draft: QrLayoutCustomization | null) => {
setCustomizerDraft((previous) => {
const prevSignature = previous ? JSON.stringify(previous) : null;
const nextSignature = draft ? JSON.stringify(draft) : null;
if (prevSignature === nextSignature) {
return previous;
}
return draft;
});
}, []);
const inviteCountSummary = React.useMemo(() => {
const active = state.invites.filter((invite) => invite.is_active && !invite.revoked_at).length;
const total = state.invites.length;
@@ -523,6 +541,7 @@ export default function EventInvitesPage(): React.ReactElement {
...prev,
invites: prev.invites.map((invite) => (invite.id === updated.id ? updated : invite)),
}));
setCustomizerDraft(null);
} catch (error) {
if (!isAuthError(error)) {
setState((prev) => ({ ...prev, error: 'Anpassung konnte nicht gespeichert werden.' }));
@@ -547,6 +566,7 @@ export default function EventInvitesPage(): React.ReactElement {
...prev,
invites: prev.invites.map((invite) => (invite.id === updated.id ? updated : invite)),
}));
setCustomizerDraft(null);
} catch (error) {
if (!isAuthError(error)) {
setState((prev) => ({ ...prev, error: 'Anpassungen konnten nicht zurückgesetzt werden.' }));
@@ -794,6 +814,8 @@ export default function EventInvitesPage(): React.ReactElement {
onSave={handleSaveCustomization}
onReset={handleResetCustomization}
initialCustomization={currentCustomization}
draftCustomization={customizerDraft}
onDraftChange={handleCustomizerDraftChange}
/>
)}
</section>

View File

@@ -20,7 +20,6 @@ import {
UploadCloud,
} from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
@@ -44,7 +43,6 @@ import {
buildDefaultElements,
clamp,
clampElement,
elementsToPayload,
normalizeElements,
payloadToElements,
} from './invite-layout/schema';
@@ -59,6 +57,15 @@ import {
export type { QrLayoutCustomization } from './invite-layout/schema';
const ELEMENT_BINDING_FIELD: Partial<Record<string, keyof QrLayoutCustomization>> = {
headline: 'headline',
subtitle: 'subtitle',
description: 'description',
badge: 'badge_label',
link: 'link_label',
cta: 'cta_label',
};
function sanitizeColor(value: string | null | undefined): string | null {
if (!value) {
return null;
@@ -180,6 +187,8 @@ type InviteLayoutCustomizerPanelProps = {
onSave: (customization: QrLayoutCustomization) => Promise<void>;
onReset: () => Promise<void>;
initialCustomization: QrLayoutCustomization | null;
draftCustomization?: QrLayoutCustomization | null;
onDraftChange?: (draft: QrLayoutCustomization | null) => void;
};
const MAX_INSTRUCTIONS = 5;
@@ -195,6 +204,8 @@ export function InviteLayoutCustomizerPanel({
onSave,
onReset,
initialCustomization,
draftCustomization,
onDraftChange,
}: InviteLayoutCustomizerPanelProps): React.JSX.Element {
const { t } = useTranslation('management');
@@ -211,7 +222,9 @@ export function InviteLayoutCustomizerPanel({
const [availableLayouts, setAvailableLayouts] = React.useState<EventQrInviteLayout[]>(invite?.layouts ?? []);
const [layoutsLoading, setLayoutsLoading] = React.useState(false);
const [layoutsError, setLayoutsError] = React.useState<string | null>(null);
const [selectedLayoutId, setSelectedLayoutId] = React.useState<string | undefined>(initialCustomization?.layout_id ?? invite?.layouts?.[0]?.id);
const [selectedLayoutId, setSelectedLayoutId] = React.useState<string | undefined>(
draftCustomization?.layout_id ?? initialCustomization?.layout_id ?? invite?.layouts?.[0]?.id,
);
const [form, setForm] = React.useState<QrLayoutCustomization>({});
const [instructions, setInstructions] = React.useState<string[]>([]);
const [error, setError] = React.useState<string | null>(null);
@@ -220,6 +233,7 @@ export function InviteLayoutCustomizerPanel({
const [printBusy, setPrintBusy] = React.useState(false);
const [elements, setElements] = React.useState<LayoutElement[]>([]);
const [activeElementId, setActiveElementId] = React.useState<string | null>(null);
const [inspectorElementId, setInspectorElementId] = React.useState<string | null>(null);
const [showFloatingActions, setShowFloatingActions] = React.useState(false);
const [zoomScale, setZoomScale] = React.useState(1);
const [fitScale, setFitScale] = React.useState(1);
@@ -234,7 +248,18 @@ export function InviteLayoutCustomizerPanel({
const [canRedo, setCanRedo] = React.useState(false);
const designerViewportRef = React.useRef<HTMLDivElement | null>(null);
const canvasContainerRef = React.useRef<HTMLDivElement | null>(null);
const isAdvanced = true;
const draftSignatureRef = React.useRef<string | null>(null);
const activeCustomization = React.useMemo(
() => draftCustomization ?? initialCustomization ?? null,
[draftCustomization, initialCustomization],
);
const customizationSignature = React.useMemo(
() => (activeCustomization ? JSON.stringify(activeCustomization) : null),
[activeCustomization],
);
const appliedSignatureRef = React.useRef<string | null>(null);
const appliedLayoutRef = React.useRef<string | null>(null);
const appliedInviteRef = React.useRef<number | string | null>(null);
const clampZoom = React.useCallback(
(value: number) => clamp(Number.isFinite(value) ? value : 1, ZOOM_MIN, ZOOM_MAX),
@@ -269,7 +294,8 @@ export function InviteLayoutCustomizerPanel({
let baseScale = Number.isFinite(nextRaw) && nextRaw > 0 ? nextRaw : 1;
const minScale = 0.3;
baseScale = Math.max(baseScale, minScale);
const clamped = clampZoom(baseScale);
const limitedScale = Math.min(baseScale, 1);
const clamped = clampZoom(limitedScale);
fitScaleRef.current = clamped;
setFitScale((prev) => (Math.abs(prev - clamped) < 0.001 ? prev : clamped));
@@ -396,6 +422,18 @@ export function InviteLayoutCustomizerPanel({
[cloneElements, pushHistory, elementsAreEqual]
);
const selectElement = React.useCallback((id: string | null, options: { preserveInspector?: boolean } = {}) => {
setActiveElementId(id);
if (id) {
setInspectorElementId(id);
return;
}
if (!options.preserveInspector) {
setInspectorElementId(null);
}
}, []);
const handleUndo = React.useCallback(() => {
if (historyIndexRef.current <= 0) {
return;
@@ -429,9 +467,6 @@ export function InviteLayoutCustomizerPanel({
React.useEffect(() => {
formStateRef.current = form;
}, [form]);
const prevFormRef = React.useRef(form);
const initializedLayoutsRef = React.useRef<Record<string, boolean>>({});
const prevInviteRef = React.useRef<number | string | null>(null);
const activeLayout = React.useMemo(() => {
if (!availableLayouts.length) {
return null;
@@ -458,15 +493,15 @@ export function InviteLayoutCustomizerPanel({
return qrElement.width;
}
if (initialCustomization?.mode === 'advanced' && Array.isArray(initialCustomization.elements)) {
const qrElement = initialCustomization.elements.find((element) => element?.type === 'qr');
if (activeCustomization?.mode === 'advanced' && Array.isArray(activeCustomization.elements)) {
const qrElement = activeCustomization.elements.find((element) => element?.type === 'qr');
if (qrElement && typeof qrElement.width === 'number' && qrElement.width > 0) {
return qrElement.width;
}
}
return activeLayout?.preview?.qr_size_px ?? 500;
}, [elements, initialCustomization?.mode, initialCustomization?.elements, activeLayout?.preview?.qr_size_px]);
}, [elements, activeCustomization?.mode, activeCustomization?.elements, activeLayout?.preview?.qr_size_px]);
const effectiveScale = React.useMemo(() => {
if (previewMode === 'full') {
@@ -493,26 +528,6 @@ export function InviteLayoutCustomizerPanel({
[commitElements]
);
const handleResetAdvanced = React.useCallback(() => {
if (!activeLayout) {
const cleared: LayoutElement[] = [];
commitElements(() => cleared, { silent: true });
resetHistory(cleared);
setActiveElementId(null);
return;
}
const defaults = buildDefaultElements(activeLayout, formStateRef.current, eventName, activeLayoutQrSize);
if (elements.length && elementsAreEqual(elements, defaults)) {
initializedLayoutsRef.current[activeLayout.id] = true;
return;
}
commitElements(() => defaults, { silent: true });
resetHistory(defaults);
setActiveElementId(null);
initializedLayoutsRef.current[activeLayout.id] = true;
}, [activeLayout, eventName, activeLayoutQrSize, commitElements, elements, elementsAreEqual, resetHistory]);
React.useEffect(() => {
if (!invite) {
setAvailableLayouts([]);
@@ -527,12 +542,12 @@ export function InviteLayoutCustomizerPanel({
if (current && layouts.some((layout) => layout.id === current)) {
return current;
}
if (initialCustomization?.layout_id && layouts.some((layout) => layout.id === initialCustomization.layout_id)) {
return initialCustomization.layout_id;
if (activeCustomization?.layout_id && layouts.some((layout) => layout.id === activeCustomization.layout_id)) {
return activeCustomization.layout_id;
}
return layouts[0]?.id;
});
}, [invite?.id, initialCustomization?.layout_id]);
}, [invite, activeCustomization?.layout_id]);
React.useEffect(() => {
let cancelled = false;
@@ -571,8 +586,8 @@ export function InviteLayoutCustomizerPanel({
if (current && items.some((layout) => layout.id === current)) {
return current;
}
if (initialCustomization?.layout_id && items.some((layout) => layout.id === initialCustomization.layout_id)) {
return initialCustomization.layout_id;
if (activeCustomization?.layout_id && items.some((layout) => layout.id === activeCustomization.layout_id)) {
return activeCustomization.layout_id;
}
return items[0]?.id;
});
@@ -600,7 +615,7 @@ export function InviteLayoutCustomizerPanel({
return () => {
cancelled = true;
};
}, [invite, availableLayouts.length, initialCustomization?.layout_id, t]);
}, [invite, availableLayouts.length, activeCustomization?.layout_id, t]);
React.useEffect(() => {
if (!availableLayouts.length) {
@@ -611,26 +626,55 @@ export function InviteLayoutCustomizerPanel({
if (current && availableLayouts.some((layout) => layout.id === current)) {
return current;
}
if (initialCustomization?.layout_id && availableLayouts.some((layout) => layout.id === initialCustomization.layout_id)) {
return initialCustomization.layout_id;
if (activeCustomization?.layout_id && availableLayouts.some((layout) => layout.id === activeCustomization.layout_id)) {
return activeCustomization.layout_id;
}
return availableLayouts[0].id;
});
}, [availableLayouts, initialCustomization?.layout_id]);
}, [availableLayouts, activeCustomization?.layout_id]);
React.useEffect(() => {
const inviteKey = invite?.id ?? null;
const layoutId = activeLayout?.id ?? null;
const incomingSignature = customizationSignature;
if (!invite || !activeLayout) {
setForm({});
setInstructions([]);
commitElements(() => [], { silent: true });
resetHistory([]);
appliedSignatureRef.current = null;
appliedLayoutRef.current = layoutId;
appliedInviteRef.current = inviteKey;
return;
}
const reuseCustomization = initialCustomization?.layout_id === activeLayout.id;
if (
draftCustomization &&
incomingSignature &&
incomingSignature === draftSignatureRef.current &&
appliedLayoutRef.current === layoutId &&
appliedInviteRef.current === inviteKey
) {
appliedSignatureRef.current = incomingSignature;
appliedLayoutRef.current = layoutId;
appliedInviteRef.current = inviteKey;
return;
}
const baseInstructions = reuseCustomization && Array.isArray(initialCustomization?.instructions) && initialCustomization.instructions?.length
? [...(initialCustomization.instructions as string[])]
const alreadyApplied =
appliedSignatureRef.current === incomingSignature &&
appliedLayoutRef.current === layoutId &&
appliedInviteRef.current === inviteKey;
if (alreadyApplied) {
return;
}
const reuseCustomization = activeCustomization?.layout_id === activeLayout.id;
const baseInstructions = reuseCustomization && Array.isArray(activeCustomization?.instructions) && activeCustomization.instructions?.length
? [...(activeCustomization.instructions as string[])]
: ((activeLayout.instructions && activeLayout.instructions.length)
? [...activeLayout.instructions]
: [...defaultInstructions]);
@@ -639,50 +683,69 @@ export function InviteLayoutCustomizerPanel({
const newForm: QrLayoutCustomization = {
layout_id: activeLayout.id,
headline: reuseCustomization ? initialCustomization?.headline ?? eventName : eventName,
subtitle: reuseCustomization ? initialCustomization?.subtitle ?? activeLayout.subtitle ?? '' : activeLayout.subtitle ?? '',
description: reuseCustomization ? initialCustomization?.description ?? activeLayout.description ?? '' : activeLayout.description ?? '',
badge_label: reuseCustomization ? initialCustomization?.badge_label ?? t('tasks.customizer.defaults.badgeLabel') : (activeLayout.badge_label ?? t('tasks.customizer.defaults.badgeLabel')),
instructions_heading: reuseCustomization ? initialCustomization?.instructions_heading ?? t('tasks.customizer.defaults.instructionsHeading') : t('tasks.customizer.defaults.instructionsHeading'),
link_heading: reuseCustomization ? initialCustomization?.link_heading ?? t('tasks.customizer.defaults.linkHeading') : t('tasks.customizer.defaults.linkHeading'),
link_label: reuseCustomization ? initialCustomization?.link_label ?? inviteUrl : inviteUrl,
cta_label: reuseCustomization ? initialCustomization?.cta_label ?? t('tasks.customizer.defaults.ctaLabel') : (activeLayout.cta_label ?? t('tasks.customizer.defaults.ctaLabel')),
accent_color: sanitizeColor((reuseCustomization ? initialCustomization?.accent_color : activeLayout.preview?.accent) ?? null) ?? '#6366F1',
text_color: sanitizeColor((reuseCustomization ? initialCustomization?.text_color : activeLayout.preview?.text) ?? null) ?? '#111827',
background_color: sanitizeColor((reuseCustomization ? initialCustomization?.background_color : activeLayout.preview?.background) ?? null) ?? '#FFFFFF',
secondary_color: reuseCustomization ? initialCustomization?.secondary_color ?? '#1F2937' : '#1F2937',
badge_color: reuseCustomization ? initialCustomization?.badge_color ?? '#2563EB' : '#2563EB',
background_gradient: reuseCustomization ? initialCustomization?.background_gradient ?? activeLayout.preview?.background_gradient ?? null : activeLayout.preview?.background_gradient ?? null,
logo_data_url: reuseCustomization ? initialCustomization?.logo_data_url ?? initialCustomization?.logo_url ?? null : null,
mode: initialCustomization?.layout_id === activeLayout.id ? initialCustomization?.mode : 'standard',
elements: initialCustomization?.layout_id === activeLayout.id ? initialCustomization?.elements : undefined,
headline: reuseCustomization ? activeCustomization?.headline ?? eventName : eventName,
subtitle: reuseCustomization ? activeCustomization?.subtitle ?? activeLayout.subtitle ?? '' : activeLayout.subtitle ?? '',
description: reuseCustomization ? activeCustomization?.description ?? activeLayout.description ?? '' : activeLayout.description ?? '',
badge_label: reuseCustomization ? activeCustomization?.badge_label ?? t('tasks.customizer.defaults.badgeLabel') : (activeLayout.badge_label ?? t('tasks.customizer.defaults.badgeLabel')),
instructions_heading: reuseCustomization ? activeCustomization?.instructions_heading ?? t('tasks.customizer.defaults.instructionsHeading') : t('tasks.customizer.defaults.instructionsHeading'),
link_heading: reuseCustomization ? activeCustomization?.link_heading ?? t('tasks.customizer.defaults.linkHeading') : t('tasks.customizer.defaults.linkHeading'),
link_label: reuseCustomization ? activeCustomization?.link_label ?? inviteUrl : inviteUrl,
cta_label: reuseCustomization ? activeCustomization?.cta_label ?? t('tasks.customizer.defaults.ctaLabel') : (activeLayout.cta_label ?? t('tasks.customizer.defaults.ctaLabel')),
accent_color: sanitizeColor((reuseCustomization ? activeCustomization?.accent_color : activeLayout.preview?.accent) ?? null) ?? '#6366F1',
text_color: sanitizeColor((reuseCustomization ? activeCustomization?.text_color : activeLayout.preview?.text) ?? null) ?? '#111827',
background_color: sanitizeColor((reuseCustomization ? activeCustomization?.background_color : activeLayout.preview?.background) ?? null) ?? '#FFFFFF',
secondary_color: reuseCustomization ? activeCustomization?.secondary_color ?? '#1F2937' : '#1F2937',
badge_color: reuseCustomization ? activeCustomization?.badge_color ?? '#2563EB' : '#2563EB',
background_gradient: reuseCustomization ? activeCustomization?.background_gradient ?? activeLayout.preview?.background_gradient ?? null : activeLayout.preview?.background_gradient ?? null,
logo_data_url: reuseCustomization ? activeCustomization?.logo_data_url ?? activeCustomization?.logo_url ?? null : null,
mode: reuseCustomization ? activeCustomization?.mode : 'standard',
elements: reuseCustomization ? activeCustomization?.elements : undefined,
};
setForm(newForm);
setError(null);
const isCustomizedAdvanced = newForm.mode === 'advanced' && Array.isArray(newForm.elements) && newForm.elements.length > 0;
const fallbackQrSize = (() => {
if (Array.isArray(newForm.elements)) {
const qrElement = newForm.elements.find((element) => element?.type === 'qr');
if (qrElement && typeof qrElement.width === 'number' && qrElement.width > 0) {
return qrElement.width;
}
}
if (typeof activeLayout.preview?.qr_size_px === 'number' && activeLayout.preview.qr_size_px > 0) {
return activeLayout.preview.qr_size_px;
}
return 500;
})();
if (isCustomizedAdvanced) {
const initialElements = normalizeElements(payloadToElements(newForm.elements));
commitElements(() => initialElements, { silent: true });
resetHistory(initialElements);
} else {
const defaults = buildDefaultElements(activeLayout, newForm, eventName, activeLayoutQrSize);
const defaults = buildDefaultElements(activeLayout, newForm, eventName, fallbackQrSize);
commitElements(() => defaults, { silent: true });
resetHistory(defaults);
}
setActiveElementId(null);
}, [
appliedSignatureRef.current = incomingSignature ?? null;
appliedLayoutRef.current = layoutId;
appliedInviteRef.current = inviteKey;
selectElement(null);
}, [
activeLayout,
invite,
invite?.id,
initialCustomization,
activeCustomization,
draftCustomization,
customizationSignature,
defaultInstructions,
eventName,
inviteUrl,
t,
activeLayoutQrSize,
commitElements,
resetHistory,
selectElement,
]);
React.useEffect(() => {
@@ -717,79 +780,73 @@ export function InviteLayoutCustomizerPanel({
const canvasElements = React.useMemo(() => {
if (!activeLayout) {
console.debug('[Invites][CanvasElements] No active layout', {
inviteId: invite?.id ?? null,
availableLayouts: availableLayouts.length,
});
return [] as LayoutElement[];
}
console.debug('[Invites][CanvasElements] Layout preview', {
layoutId: activeLayout.id,
preview: activeLayout.preview,
});
const base = elements.length
? elements
: buildDefaultElements(activeLayout, form, eventName, activeLayoutQrSize);
console.debug('[Invites][CanvasElements] Base elements', {
layoutId: activeLayout.id,
existing: elements.length,
generated: base.length,
hasCustomization: Boolean(initialCustomization?.elements?.length),
});
return base.map((element) => ({
...element,
initial: element.initial ?? nonRemovableIds.has(element.id),
}));
}, [activeLayout, elements, form, eventName, activeLayoutQrSize, nonRemovableIds]);
// Erweiterter Log für Duplikate-Check
const idCounts = base.reduce((acc, e) => {
acc[e.id] = (acc[e.id] || 0) + 1;
return acc;
}, {} as Record<string, number>);
const duplicates = Object.entries(idCounts).filter(([_, count]) => count > 1);
if (duplicates.length > 0) {
console.warn('[Invites][CanvasElements] Duplicates detected in base', { duplicates, baseIds: base.map(e => ({ id: e.id, type: e.type, y: e.y })) });
React.useEffect(() => {
if (!onDraftChange) {
return;
}
console.debug('[Invites][CanvasElements] Base IDs overview', base.map(e => ({ id: e.id, type: e.type, y: e.y })));
const boundContent: Record<string, string | null> = {
headline: form.headline ?? eventName,
subtitle: form.subtitle ?? '',
description: form.description ?? activeLayout.description ?? '',
link: form.link_label && form.link_label.trim().length > 0 ? form.link_label : inviteUrl,
badge: form.badge_label ?? t('tasks.customizer.defaults.badgeLabel'),
cta: form.cta_label ?? t('tasks.customizer.defaults.ctaLabel'),
if (!invite || !activeLayout) {
if (draftSignatureRef.current !== null) {
draftSignatureRef.current = null;
onDraftChange(null);
}
return;
}
const serializationContext: LayoutSerializationContext = {
form,
eventName,
inviteUrl,
instructions: effectiveInstructions,
qrSize: activeLayoutQrSize,
badgeFallback: t('tasks.customizer.defaults.badgeLabel'),
logoUrl: form.logo_url ?? null,
};
return base.map((element) => {
let content = element.content ?? null;
const advancedElements = elements.length
? elements
: buildDefaultElements(activeLayout, form, eventName, activeLayoutQrSize);
if (Object.prototype.hasOwnProperty.call(boundContent, element.id)) {
content = boundContent[element.id] ?? '';
}
const draftPayload: QrLayoutCustomization = {
...form,
layout_id: activeLayout.id,
instructions: effectiveInstructions,
mode: 'advanced',
elements: serializeElements(advancedElements, serializationContext),
};
if (element.type === 'text' && (!content || content.trim().length === 0)) {
content = t('invites.customizer.defaults.textBlock', 'Neuer Textblock hier kannst du eigene Hinweise ergänzen.');
}
return {
...element,
content,
initial: element.initial ?? nonRemovableIds.has(element.id),
};
});
const sanitizedDraft = sanitizePayload(draftPayload);
const signature = JSON.stringify(sanitizedDraft);
if (signature !== draftSignatureRef.current) {
draftSignatureRef.current = signature;
onDraftChange(sanitizedDraft);
}
}, [
onDraftChange,
invite,
invite?.id,
activeLayout,
activeLayout?.id,
form,
elements,
form.headline,
form.subtitle,
form.description,
form.link_label,
form.badge_label,
form.cta_label,
effectiveInstructions,
eventName,
inviteUrl,
t,
activeLayoutQrSize,
t,
]);
const elementLabelFor = React.useCallback(
@@ -936,9 +993,9 @@ export function InviteLayoutCustomizerPanel({
next.push({ ...preset, initial: false });
return next;
});
setActiveElementId(preset.id);
selectElement(preset.id);
},
[createPresetElement, commitElements]
[createPresetElement, commitElements, selectElement]
);
const removeElement = React.useCallback(
@@ -947,22 +1004,19 @@ export function InviteLayoutCustomizerPanel({
return;
}
commitElements((current) => current.filter((item) => item.id !== id));
if (activeElementId === id) {
setActiveElementId(null);
if (activeElementId === id || inspectorElementId === id) {
selectElement(null);
}
},
[activeElementId, nonRemovableIds, commitElements]
[activeElementId, inspectorElementId, nonRemovableIds, commitElements, selectElement]
);
const updateElementContent = React.useCallback((id: string, value: string) => {
commitElements((current) => current.map((item) => (item.id === id ? { ...item, content: value } : item)));
}, [commitElements]);
const updateElementAlign = React.useCallback(
(id: string, align: 'left' | 'center' | 'right') => {
selectElement(id, { preserveInspector: true });
updateElement(id, { align });
},
[updateElement]
[selectElement, updateElement]
);
const elementTypeOrder: Record<LayoutElementType, number> = React.useMemo(
@@ -1073,63 +1127,43 @@ export function InviteLayoutCustomizerPanel({
[t]
);
React.useEffect(() => {
const previous = prevFormRef.current;
prevFormRef.current = form;
const entries = Object.entries(elementBindings) as Array<[
keyof typeof elementBindings,
{ field: keyof QrLayoutCustomization; multiline: boolean }
]>;
entries.forEach(([elementId, binding]) => {
if (!elements.some((element) => element.id === elementId)) {
const updateForm = React.useCallback(
<T extends keyof QrLayoutCustomization>(key: T, value: QrLayoutCustomization[T]) => {
setForm((prev) => ({ ...prev, [key]: value }));
const bindingEntry = Object.entries(elementBindings).find(([, binding]) => binding.field === key);
if (!bindingEntry) {
return;
}
const previousValue = previous?.[binding.field] ?? null;
const nextValue = form[binding.field] ?? null;
if (previousValue !== nextValue) {
updateElement(
elementId,
{
content: (typeof nextValue === 'string' ? nextValue : String(nextValue ?? '')) as string,
},
{ silent: true }
);
}
});
}, [form, elementBindings, elements, updateElement]);
const renderActionButtons = (mode: 'inline' | 'floating') => (
<>
<Button
type="button"
variant="outline"
onClick={() => void handleResetClick()}
disabled={resetting || saving}
className={cn('w-full sm:w-auto', mode === 'floating' ? 'sm:w-auto' : '')}
>
{resetting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <RotateCcw className="mr-2 h-4 w-4" />}
{t('invites.customizer.actions.reset', 'Zurücksetzen')}
</Button>
<Button
type="button"
disabled={saving || resetting}
onClick={() => {
if (formRef.current) {
if (typeof formRef.current.requestSubmit === 'function') {
formRef.current.requestSubmit();
} else {
formRef.current.submit();
}
}
}}
className={cn('w-full bg-gradient-to-r from-amber-500 via-orange-500 to-rose-500 text-white sm:w-auto', mode === 'floating' ? 'sm:w-auto' : '')}
>
{saving ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Save className="mr-2 h-4 w-4" />}
{t('invites.customizer.actions.save', 'Layout speichern')}
</Button>
</>
const [elementId] = bindingEntry;
selectElement(elementId, { preserveInspector: true });
commitElements(
(current) =>
current.map((el) =>
el.id === elementId ? { ...el, content: String(value ?? '') } : el
),
{ silent: true },
);
},
[commitElements, elementBindings, selectElement],
);
const updateElementContent = React.useCallback(
(id: string, value: string) => {
selectElement(id, { preserveInspector: true });
commitElements((current) => current.map((item) => (item.id === id ? { ...item, content: value } : item)));
const bindingField = ELEMENT_BINDING_FIELD[id];
if (bindingField) {
updateForm(bindingField, value);
}
},
[commitElements, selectElement, updateForm],
);
const renderElementDetail = React.useCallback(
(element: LayoutElement): React.ReactNode => {
const binding = elementBindings[element.id as keyof typeof elementBindings];
@@ -1242,9 +1276,37 @@ export function InviteLayoutCustomizerPanel({
[elementBindings, form, t, updateElement, updateElementAlign, updateElementContent, updateForm]
);
function updateForm<T extends keyof QrLayoutCustomization>(key: T, value: QrLayoutCustomization[T]) {
setForm((prev) => ({ ...prev, [key]: value }));
}
const renderActionButtons = (mode: 'inline' | 'floating') => (
<>
<Button
type="button"
variant="outline"
onClick={() => void handleResetClick()}
disabled={resetting || saving}
className={cn('w-full sm:w-auto', mode === 'floating' ? 'sm:w-auto' : '')}
>
{resetting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <RotateCcw className="mr-2 h-4 w-4" />}
{t('invites.customizer.actions.reset', 'Zurücksetzen')}
</Button>
<Button
type="button"
disabled={saving || resetting}
onClick={() => {
if (formRef.current) {
if (typeof formRef.current.requestSubmit === 'function') {
formRef.current.requestSubmit();
} else {
formRef.current.submit();
}
}
}}
className={cn('w-full bg-gradient-to-r from-amber-500 via-orange-500 to-rose-500 text-white sm:w-auto', mode === 'floating' ? 'sm:w-auto' : '')}
>
{saving ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Save className="mr-2 h-4 w-4" />}
{t('invites.customizer.actions.save', 'Layout speichern')}
</Button>
</>
);
function handleLayoutSelect(layout: EventQrInviteLayout) {
setSelectedLayoutId(layout.id);
@@ -1443,6 +1505,8 @@ export function InviteLayoutCustomizerPanel({
);
}
const highlightedElementId = activeElementId ?? inspectorElementId;
return (
<div className="space-y-4">
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
@@ -1539,7 +1603,8 @@ export function InviteLayoutCustomizerPanel({
<div className="space-y-2">
{sortedElements.map((element) => {
const Icon = elementIconFor(element);
const isSelected = element.id === activeElementId;
const isSelected = element.id === highlightedElementId;
const isInspectorVisible = element.id === inspectorElementId;
const removable = !nonRemovableIds.has(element.id);
return (
<div
@@ -1554,7 +1619,7 @@ export function InviteLayoutCustomizerPanel({
<div className="flex items-center justify-between gap-3">
<button
type="button"
onClick={() => setActiveElementId(element.id)}
onClick={() => selectElement(element.id)}
className="flex flex-1 items-center gap-3 text-left"
>
<Icon className={cn('h-4 w-4', isSelected ? 'text-primary' : 'text-muted-foreground')} />
@@ -1573,7 +1638,7 @@ export function InviteLayoutCustomizerPanel({
</Button>
) : null}
</div>
{isSelected ? renderElementDetail(element) : null}
{isInspectorVisible ? renderElementDetail(element) : null}
</div>
);
})}
@@ -1864,8 +1929,8 @@ export function InviteLayoutCustomizerPanel({
<div ref={canvasContainerRef} className="relative flex justify-center aspect-[1240/1754] mx-auto max-w-full">
<DesignerCanvas
elements={canvasElements}
selectedId={activeElementId}
onSelect={setActiveElementId}
selectedId={highlightedElementId}
onSelect={selectElement}
onChange={updateElement}
background={form.background_color ?? activeLayout.preview?.background ?? '#FFFFFF'}
gradient={form.background_gradient ?? activeLayout.preview?.background_gradient ?? null}

View File

@@ -53,6 +53,11 @@ export function DesignerCanvas({
const pendingDisposeRef = React.useRef<number | null>(null);
const pendingTimeoutRef = React.useRef<number | null>(null);
const lastRenderSignatureRef = React.useRef<string | null>(null);
const requestedSelectionRef = React.useRef<string | null>(selectedId);
React.useEffect(() => {
requestedSelectionRef.current = selectedId;
}, [selectedId]);
const destroyCanvas = React.useCallback((canvas: fabric.Canvas | null) => {
if (!canvas) {
@@ -207,13 +212,19 @@ export function DesignerCanvas({
onSelect(null);
return;
}
requestedSelectionRef.current = active.elementId ?? null;
onSelect(active.elementId);
};
const handleSelectionCleared = () => {
const handleSelectionCleared = (event?: fabric.IEvent<MouseEvent>) => {
if (readOnly) {
return;
}
const triggeredByPointer = Boolean(event?.e);
if (!triggeredByPointer && requestedSelectionRef.current) {
return;
}
requestedSelectionRef.current = null;
onSelect(null);
};