Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions database/factories/WallOfLoveSubmissionFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\WallOfLoveSubmission>
*/
class WallOfLoveSubmissionFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'user_id' => \App\Models\User::factory(),
'name' => fake()->name(),
'company' => fake()->optional(0.7)->company(),
'photo_path' => null, // Photos are optional and would need real files
'url' => fake()->optional(0.6)->url(),
'testimonial' => fake()->optional(0.8)->paragraph(3),
'approved_at' => null,
'approved_by' => null,
];
}

/**
* Indicate that the submission is approved.
*/
public function approved(): static
{
return $this->state(fn (array $attributes) => [
'approved_at' => fake()->dateTimeBetween('-30 days', 'now'),
'approved_by' => \App\Models\User::factory(),
]);
}

/**
* Indicate that the submission is pending.
*/
public function pending(): static
{
return $this->state(fn (array $attributes) => [
'approved_at' => null,
'approved_by' => null,
]);
}
}
65 changes: 65 additions & 0 deletions database/seeders/WallOfLoveSubmissionSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class WallOfLoveSubmissionSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Get existing users or create new ones
$existingUsers = \App\Models\User::query()
->whereHas('licenses', function ($query) {
$query->where('created_at', '<', '2025-06-01');
})
->get();

// If we have existing early adopter users, use them
if ($existingUsers->count() >= 5) {
$users = $existingUsers;
} else {
// Create some users with simple licenses (without subscription_item_id)
$users = \App\Models\User::factory()
->count(10)
->create()
->each(function ($user) {
// Give each user an early adopter license (before June 1st, 2025)
\App\Models\License::factory()->create([
'user_id' => $user->id,
'subscription_item_id' => null, // Skip the subscription item relationship
'created_at' => fake()->dateTimeBetween('2024-01-01', '2025-05-31'),
'updated_at' => fake()->dateTimeBetween('2024-01-01', '2025-05-31'),
]);
});
}

// Get or create an admin user for approvals
$admin = \App\Models\User::query()
->where('email', '[email protected]')
->first() ?? \App\Models\User::factory()->create([
'name' => 'Admin User',
'email' => '[email protected]',
]);

// Create approved submissions (will be displayed on the wall of love page)
\App\Models\WallOfLoveSubmission::factory()
->count(15)
->approved()
->create([
'user_id' => fn () => $users->random()->id,
'approved_by' => $admin->id,
]);

// Create pending submissions (waiting for approval)
\App\Models\WallOfLoveSubmission::factory()
->count(5)
->pending()
->create([
'user_id' => fn () => $users->random()->id,
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
'url' => '',
'image' => '',
'featured' => false,
'hasUserImage' => false,
])

<article
class="group mt-3 inline-block break-inside-avoid overflow-hidden rounded-2xl text-center opacity-0 transition duration-300 ease-out will-change-transform hover:scale-102 xl:mt-5"
class="group w-full break-inside-avoid overflow-hidden rounded-2xl text-center transition duration-300 ease-out will-change-transform not-last:mb-3 hover:scale-102 xl:not-last:mb-5"
itemscope
>
<figure class="grid">
Expand All @@ -32,7 +33,7 @@ class="capitalize transition duration-300 ease-out will-change-transform group-h
</h3>
<p
@class([
'opacity-50',
'truncate opacity-50',
'text-sm' => $featured,
'text-xs' => ! $featured,
])
Expand All @@ -53,9 +54,10 @@ class="capitalize transition duration-300 ease-out will-change-transform group-h
decoding="async"
itemprop="image"
@class([
'relative z-10 self-center justify-self-center object-cover brightness-80 transition duration-300 [grid-area:1/-1] group-hover:brightness-100',
'relative z-10 w-full self-center justify-self-center object-cover brightness-80 transition duration-300 [grid-area:1/-1] group-hover:brightness-100',
'aspect-[1/1.3] xl:aspect-[1/1.5]' => $featured,
'aspect-square max-h-50 grayscale group-hover:grayscale-0 xl:max-h-none' => ! $featured,
'aspect-square max-h-50 xl:max-h-none' => ! $featured,
'grayscale-50 dark:brightness-50' => ! $hasUserImage,
])
/>

Expand Down
73 changes: 30 additions & 43 deletions resources/views/wall-of-love.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,50 +116,32 @@ class="mx-auto mt-5 max-w-2xl text-center text-base/relaxed text-gray-600 sm:tex
->inRandomOrder()
->get();

// Check if any submissions have user-uploaded images
$hasAnyUserImages = $approvedSubmissions->contains(fn ($s) => ! empty($s->photo_path));

// Convert approved submissions to the format expected by the component
$earlyAdopters = $approvedSubmissions->map(function ($submission) {
return [
'name' => $submission->name,
'title' => $submission->company,
'url' => $submission->url,
'image' => $submission->photo_path
? asset('storage/' . $submission->photo_path)
: 'https://avatars.laravel.cloud/' . rand(1, 70) . '?vibe=' . array_rand(['ocean', 'crystal', 'bubble', 'forest', 'sunset']),
'featured' => rand(0, 4) === 0, // Randomly feature about 20% of submissions
'testimonial' => $submission->testimonial,
];
})->toArray();
$earlyAdopters = $approvedSubmissions
->map(function ($submission) use ($hasAnyUserImages) {
$hasUserImage = ! empty($submission->photo_path);

return [
'name' => $submission->name,
'title' => $submission->company,
'url' => $submission->url,
'image' => $hasUserImage
? asset('storage/' . $submission->photo_path)
: 'https://avatars.laravel.cloud/' . rand(1, 70) . '?vibe=' . array_rand(['ocean', 'stealth', 'bubble', 'ice']),
'hasUserImage' => $hasUserImage,
// Only allow featured if has user image (unless no submissions have images)
'featured' => ($hasAnyUserImages ? $hasUserImage : true) && rand(0, 4) === 0,
'testimonial' => $submission->testimonial,
];
})
->toArray();
@endphp

@if(count($earlyAdopters) > 0)
@if (count($earlyAdopters) > 0)
<div
x-init="
() => {
motion.inView($el, (element) => {
const children = Array.from($el.children)

children.forEach((child, i) => {
const range = 20 // px
const xFrom = (Math.random() * 2 - 1) * range
const yFrom = (Math.random() * 2 - 1) * range

motion.animate(
child,
{
x: [xFrom, 0],
y: [yFrom, 0],
opacity: [0, 1],
},
{
duration: 0.7,
ease: motion.backOut,
delay: i * 0.06,
},
)
})
})
}
"
class="relative z-10 mt-10 grid place-items-center 2xs:block 2xs:columns-[10rem] xl:columns-[12rem]"
>
@foreach ($earlyAdopters as $adopter)
Expand All @@ -169,14 +151,19 @@ class="relative z-10 mt-10 grid place-items-center 2xs:block 2xs:columns-[10rem]
:url="$adopter['url'] ?? null"
:title="$adopter['title'] ?? null"
:featured="$adopter['featured'] ?? false"
:hasUserImage="$adopter['hasUserImage'] ?? false"
/>
@endforeach
</div>
@else
<div class="relative z-10 mt-10 text-center">
<div class="bg-white dark:bg-gray-800/50 backdrop-blur-sm rounded-2xl p-8 mx-auto max-w-md border border-gray-200 dark:border-gray-700">
<div class="text-6xl mb-4">🚀</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2">
<div
class="mx-auto max-w-md rounded-2xl border border-gray-200 bg-white p-8 backdrop-blur-sm dark:border-gray-700 dark:bg-gray-800/50"
>
<div class="mb-4 text-6xl">🚀</div>
<h3
class="mb-2 text-xl font-semibold text-gray-900 dark:text-white"
>
Coming Soon!
</h3>
<p class="text-gray-600 dark:text-gray-400">
Expand Down
Loading