Marketing packages now use localized name/description data plus seeded placeholder-

driven breakdown tables, with frontend/cards/dialog updated accordingly (database/
  migrations/2025_10_17_000001_add_description_table_to_packages.php, database/
  migrations/2025_10_17_000002_add_translation_columns_to_packages.php, database/seeders/PackageSeeder.php, app/
  Http/Controllers/MarketingController.php, resources/js/pages/marketing/Packages.tsx).
  Filament Package resource gains locale tabs, markdown editor, numeric/toggle inputs, and simplified feature
  management (app/Filament/Resources/PackageResource.php, app/Filament/Resources/PackageResource/Pages/
  CreatePackage.php, .../EditPackage.php).
  Legal pages now render markdown-backed content inside the main layout via a new controller/view route setup and
  updated footer links (app/Http/Controllers/LegalPageController.php, routes/web.php, resources/views/partials/
  footer.blade.php, resources/js/pages/legal/Show.tsx, remove old static pages).
  Translation files and shared assets updated to cover new marketing/legal strings and styling tweaks (public/
  lang/*/marketing.json, resources/lang/*/marketing.php, resources/css/app.css, resources/js/admin/components/
  LanguageSwitcher.tsx).
This commit is contained in:
Codex Agent
2025-10-17 21:20:54 +02:00
parent 25e8f0511b
commit 48a2974152
30 changed files with 1702 additions and 711 deletions

View File

@@ -5,7 +5,6 @@ namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Package;
use App\Enums\PackageType;
use Illuminate\Support\Str;
class PackageSeeder extends Seeder
{
@@ -14,106 +13,265 @@ class PackageSeeder extends Seeder
*/
public function run(): void
{
// Endcustomer Packages
Package::create([
'name' => 'Free / Test',
'slug' => 'free-package',
'type' => PackageType::ENDCUSTOMER,
'price' => 0.00,
'max_photos' => 30,
'max_guests' => 50,
'gallery_days' => 7,
'max_tasks' => 5,
'watermark_allowed' => true,
'branding_allowed' => false,
'features' => json_encode([
'basic_uploads' => true,
'limited_sharing' => true,
'no_branding' => true,
]),
]);
Package::create([
'name' => 'Starter',
'slug' => Str::slug('Starter'),
'type' => PackageType::ENDCUSTOMER,
'price' => 29.00,
'max_photos' => 200,
'max_guests' => 100,
'gallery_days' => 30,
'max_tasks' => 10,
'watermark_allowed' => true,
'branding_allowed' => false,
'features' => json_encode([
'basic_uploads' => true,
'unlimited_sharing' => true,
'no_watermark' => true,
'custom_tasks' => true,
]),
]);
Package::create([
'name' => 'Pro',
'slug' => Str::slug('Pro'),
'type' => PackageType::ENDCUSTOMER,
'price' => 79.00,
'max_photos' => 1000,
'max_guests' => 500,
'gallery_days' => 90,
'max_tasks' => 20,
'watermark_allowed' => false,
'branding_allowed' => false,
'features' => json_encode([
'basic_uploads' => true,
'unlimited_sharing' => true,
'no_watermark' => true,
'custom_tasks' => true,
'advanced_analytics' => true,
'priority_support' => true,
]),
]);
// Reseller Packages
Package::create([
'name' => 'S (Small Reseller)',
'slug' => Str::slug('S (Small Reseller)'),
'type' => PackageType::RESELLER,
'price' => 199.00,
'max_photos' => 500, // per event limit
'max_guests' => null, // unlimited
'gallery_days' => null,
'max_tasks' => null, // unlimited
'watermark_allowed' => true,
'branding_allowed' => true,
'max_events_per_year' => 5,
'expires_after' => now()->addYear(),
'features' => json_encode([
'reseller_dashboard' => true,
'custom_branding' => true,
'priority_support' => true,
]),
]);
Package::create([
'name' => 'M (Medium Reseller)',
'slug' => Str::slug('M (Medium Reseller)'),
'type' => PackageType::RESELLER,
'price' => 399.00,
'max_photos' => 1000, // per event limit
'max_guests' => null, // unlimited
'gallery_days' => null,
'max_tasks' => null, // unlimited
'watermark_allowed' => true,
'branding_allowed' => true,
'max_events_per_year' => 15,
'expires_after' => now()->addYear(),
'features' => json_encode([
'reseller_dashboard' => true,
'custom_branding' => true,
'priority_support' => true,
'advanced_reporting' => true,
]),
]);
$packages = [
[
'slug' => 'free-package',
'name' => 'Free / Test',
'name_translations' => [
'de' => 'Free / Test',
'en' => 'Free / Test',
],
'type' => PackageType::ENDCUSTOMER,
'price' => 0.00,
'max_photos' => 120,
'max_guests' => 25,
'gallery_days' => 7,
'max_tasks' => 8,
'watermark_allowed' => true,
'branding_allowed' => false,
'features' => ['basic_uploads', 'limited_sharing'],
'description' => <<<TEXT
Perfekt zum Ausprobieren: Teile erste Eindrücke mit {{max_guests}} Gästen und sammle {{max_photos}} Bilder in einer Test-Galerie, die {{gallery_duration}} online bleibt. Ideal für kleine Runden oder interne Demos.
TEXT,
'description_translations' => [
'de' => 'Perfekt zum Ausprobieren: Teile erste Eindrücke mit {{max_guests}} Gästen und sammle {{max_photos}} Bilder in einer Test-Galerie, die {{gallery_duration}} online bleibt. Ideal für kleine Runden oder interne Demos.',
'en' => 'Perfect for trying it out: share first impressions with {{max_guests}} guests and collect {{max_photos}} photos in a test gallery that stays online for {{gallery_duration}}. Ideal for small groups or internal demos.',
],
'description_table' => [
['title' => 'Fotos', 'value' => '{{max_photos}}'],
['title' => 'Gäste', 'value' => '{{max_guests}}'],
['title' => 'Aufgaben', 'value' => '{{max_tasks}} Fotoaufgaben'],
['title' => 'Galerie', 'value' => '{{gallery_duration}}'],
['title' => 'Branding', 'value' => 'Fotospiel Standard Branding'],
],
],
[
'slug' => 'starter',
'name' => 'Starter',
'name_translations' => [
'de' => 'Starter',
'en' => 'Starter',
],
'type' => PackageType::ENDCUSTOMER,
'price' => 59.00,
'max_photos' => 300,
'max_guests' => 50,
'gallery_days' => 14,
'max_tasks' => 30,
'watermark_allowed' => true,
'branding_allowed' => false,
'features' => ['basic_uploads', 'limited_sharing', 'custom_tasks'],
'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,
'description_translations' => [
'de' => '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.',
'en' => 'Ideal for birthdays, garden parties or rehearsal dinners! {{max_guests}} guests share their favourite snapshots, take on {{max_tasks}} photo challenges and enjoy gallery access for {{gallery_duration}}. {{max_photos}} photos included for all those memories.',
],
'description_table' => [
['title' => 'Fotos', 'value' => '{{max_photos}}'],
['title' => 'Gäste', 'value' => '{{max_guests}}'],
['title' => 'Aufgaben', 'value' => '{{max_tasks}} Fotoaufgaben'],
['title' => 'Galerie', 'value' => '{{gallery_duration}}'],
['title' => 'Branding', 'value' => 'Fotospiel Branding'],
],
],
[
'slug' => 'standard',
'name' => 'Standard',
'name_translations' => [
'de' => 'Standard',
'en' => 'Standard',
],
'type' => PackageType::ENDCUSTOMER,
'price' => 129.00,
'max_photos' => 1000,
'max_guests' => 150,
'gallery_days' => 30,
'max_tasks' => 100,
'watermark_allowed' => false,
'branding_allowed' => true,
'features' => ['basic_uploads', 'unlimited_sharing', 'no_watermark', 'custom_branding', 'custom_tasks'],
'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,
'description_translations' => [
'de' => '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.',
'en' => 'The all-in-one package for weddings, corporate events or anniversaries. {{max_photos}} photos, {{max_guests}} guests and {{max_tasks}} photo challenges—plus a gallery that stays online for {{gallery_duration}}. Includes your own logo or watermark.',
],
'description_table' => [
['title' => 'Fotos', 'value' => '{{max_photos}}'],
['title' => 'Gäste', 'value' => '{{max_guests}}'],
['title' => 'Aufgaben', 'value' => '{{max_tasks}} Fotoaufgaben'],
['title' => 'Galerie', 'value' => '{{gallery_duration}}'],
['title' => 'Branding', 'value' => 'Eigenes Logo & Wasserzeichen'],
],
],
[
'slug' => 'pro',
'name' => 'Premium',
'name_translations' => [
'de' => 'Premium',
'en' => 'Premium',
],
'type' => PackageType::ENDCUSTOMER,
'price' => 249.00,
'max_photos' => 3000,
'max_guests' => 500,
'gallery_days' => 180,
'max_tasks' => 200,
'watermark_allowed' => false,
'branding_allowed' => true,
'features' => ['basic_uploads', 'unlimited_sharing', 'no_watermark', 'custom_branding', 'advanced_analytics', 'live_slideshow', 'priority_support'],
'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,
'description_translations' => [
'de' => '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.',
'en' => 'The full experience for anyone who refuses to compromise. {{max_photos}} photos, {{max_guests}} guests, {{gallery_duration}} of gallery access and {{max_tasks}} challenges—no watermark, live slideshow and premium support included.',
],
'description_table' => [
['title' => 'Fotos', 'value' => '{{max_photos}}'],
['title' => 'Gäste', 'value' => '{{max_guests}}'],
['title' => 'Aufgaben', 'value' => '{{max_tasks}} Fotoaufgaben'],
['title' => 'Galerie', 'value' => '{{gallery_duration}}'],
['title' => 'Extras', 'value' => 'Live-Slideshow & Premium-Support'],
],
],
[
'slug' => 's-small-reseller',
'name' => 'Reseller S',
'name_translations' => [
'de' => 'Reseller S',
'en' => 'Reseller S',
],
'type' => PackageType::RESELLER,
'price' => 299.00,
'max_photos' => 1000,
'max_guests' => null,
'gallery_days' => 30,
'max_tasks' => null,
'watermark_allowed' => true,
'branding_allowed' => true,
'max_events_per_year' => 5,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support'],
'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,
'description_translations' => [
'de' => '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.',
'en' => 'Perfect for photographers or planners getting started with Fotospiel. Includes {{max_events_per_year}} events per year with the standard feature set—branding options included.',
],
'description_table' => [
['title' => 'Events/Jahr', 'value' => '{{max_events_per_year}} Events'],
['title' => 'Galerie', 'value' => '{{gallery_duration}}'],
['title' => 'Branding', 'value' => 'Logo & Farben pro Event'],
],
],
[
'slug' => 'm-medium-reseller',
'name' => 'Reseller M',
'name_translations' => [
'de' => 'Reseller M',
'en' => 'Reseller M',
],
'type' => PackageType::RESELLER,
'price' => 599.00,
'max_photos' => 1500,
'max_guests' => null,
'gallery_days' => 60,
'max_tasks' => null,
'watermark_allowed' => true,
'branding_allowed' => true,
'max_events_per_year' => 15,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support', 'advanced_reporting'],
'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,
'description_translations' => [
'de' => '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.',
'en' => 'Designed for professionals who regularly support weddings, corporate events or private parties. {{max_events_per_year}} events per year with branding options, extended gallery runtime and reporting included.',
],
'description_table' => [
['title' => 'Events/Jahr', 'value' => '{{max_events_per_year}} Events'],
['title' => 'Galerie', 'value' => '{{gallery_duration}}'],
['title' => 'Reporting', 'value' => 'Erweiterte Auswertungen'],
],
],
[
'slug' => 'l-large-reseller',
'name' => 'Reseller L',
'name_translations' => [
'de' => 'Reseller L',
'en' => 'Reseller L',
],
'type' => PackageType::RESELLER,
'price' => 1199.00,
'max_photos' => 3000,
'max_guests' => null,
'gallery_days' => 90,
'max_tasks' => null,
'watermark_allowed' => false,
'branding_allowed' => true,
'max_events_per_year' => 40,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support', 'advanced_reporting', 'live_slideshow'],
'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,
'description_translations' => [
'de' => '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.',
'en' => 'Ideal for agencies, photographers or event providers with a packed calendar. {{max_events_per_year}} events included, white-label branding and all premium features for maximum flexibility.',
],
'description_table' => [
['title' => 'Events/Jahr', 'value' => '{{max_events_per_year}} Events'],
['title' => 'Branding', 'value' => 'White-Label & eigene Domains'],
['title' => 'Extras', 'value' => 'Live-Slideshow & Premium-Features'],
],
],
[
'slug' => 'enterprise-unlimited',
'name' => 'Enterprise / Unlimited',
'name_translations' => [
'de' => 'Enterprise / Unlimited',
'en' => 'Enterprise / Unlimited',
],
'type' => PackageType::RESELLER,
'price' => 0.00,
'max_photos' => null,
'max_guests' => null,
'gallery_days' => null,
'max_tasks' => null,
'watermark_allowed' => false,
'branding_allowed' => true,
'max_events_per_year' => null,
'expires_after' => now()->copy()->addYear(),
'features' => ['reseller_dashboard', 'custom_branding', 'priority_support', 'advanced_reporting', 'live_slideshow', 'unlimited_sharing'],
'description' => <<<TEXT
Das Rundum-Paket für Unternehmen und Agenturen, die maximale Flexibilität brauchen. {{max_events_per_year}} Events, volles White-Label-Branding, eigene Subdomain oder App-Branding alles individuell anpassbar, inklusive persönlicher Betreuung.
TEXT,
'description_translations' => [
'de' => 'Das Rundum-Paket für Unternehmen und Agenturen, die maximale Flexibilität brauchen. {{max_events_per_year}} Events, volles White-Label-Branding, eigene Subdomain oder App-Branding alles individuell anpassbar, inklusive persönlicher Betreuung.',
'en' => 'The all-round package for enterprises and agencies needing maximum flexibility. {{max_events_per_year}} events, full white-label branding, your own subdomain or app branding—fully customisable with dedicated support.',
],
'description_table' => [
['title' => 'Events/Jahr', 'value' => '{{max_events_per_year}} Events'],
['title' => 'Branding', 'value' => 'Eigene Subdomain oder App'],
['title' => 'Support', 'value' => 'Persönliche Betreuung'],
],
],
];
foreach ($packages as $data) {
$descriptionTable = $data['description_table'] ?? [];
Package::updateOrCreate(
['slug' => $data['slug']],
array_merge($data, [
'description_table' => $descriptionTable,
])
);
}
}
}
}