diff --git a/app/Helpers/Global/user_access_helpers.php b/app/Helpers/Global/user_access_helpers.php
index 6a663bc..aeef54b 100644
--- a/app/Helpers/Global/user_access_helpers.php
+++ b/app/Helpers/Global/user_access_helpers.php
@@ -11,8 +11,8 @@ function user_is_master_admin(?User $user)
return false;
}
- $emails = ['autopilotshorts@gmail.com', 'team@autopilotshorts.com', 'charles@exastellar.com'];
- $user_id = 1;
+ $emails = ['autopilotshorts@gmail.com', 'team@autopilotshorts.com', 'charles@exastellar.com', 'charlesteh90@gmail.com'];
+ $user_id = 0;
if ($user->id == $user_id) {
return true;
diff --git a/app/Http/Controllers/AdminBackgroundGenerationController.php b/app/Http/Controllers/AdminBackgroundGenerationController.php
new file mode 100644
index 0000000..37093e4
--- /dev/null
+++ b/app/Http/Controllers/AdminBackgroundGenerationController.php
@@ -0,0 +1,191 @@
+whereIn('list_type', ['residential', 'commercial'])
+ ->inRandomOrder()
+ ->first();
+
+ return Inertia::render('admin/background-gen', [
+ 'pendingMedia' => $pendingMedia,
+ ]);
+ }
+
+ public function generate(Request $request)
+ {
+ $request->validate([
+ 'prompt' => 'required|string|max:1000',
+ 'media_id' => 'required|exists:background_medias,id',
+ ]);
+
+ $prompt = $request->input('prompt');
+
+ // Call Replicate API
+ $replicateResponse = $this->callReplicateAPI($prompt);
+
+ if (! $replicateResponse || ! isset($replicateResponse['urls']['get'])) {
+ return response()->json(['error' => 'Failed to start generation'], 500);
+ }
+
+ // Poll for result
+ $result = $this->pollReplicateResult($replicateResponse['urls']['get']);
+
+ if (! $result || ! isset($result['output'][0])) {
+ return response()->json(['error' => 'Generation failed or timed out'], 500);
+ }
+
+ return response()->json([
+ 'success' => true,
+ 'image_url' => $result['output'][0],
+ ]);
+ }
+
+ public function delete($id)
+ {
+ try {
+ $media = BackgroundMedia::where('id', $id)
+ ->where('status', 'pending_media')
+ ->first();
+
+ if (! $media) {
+ return response()->json([
+ 'success' => false,
+ 'error' => 'Pending media not found or already processed',
+ ], 404);
+ }
+
+ $media->delete();
+
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Media deleted successfully',
+ ]);
+ } catch (\Exception $e) {
+ \Log::error('Error deleting pending media: '.$e->getMessage());
+
+ return response()->json([
+ 'success' => false,
+ 'error' => 'An error occurred while deleting the media',
+ ], 500);
+ }
+ }
+
+ public function save(Request $request)
+ {
+ $request->validate([
+ 'media_id' => 'required|exists:background_medias,id',
+ 'image_url' => 'required|url',
+ 'prompt' => 'required|string',
+ ]);
+
+ $backgroundMedia = BackgroundMedia::findOrFail($request->input('media_id'));
+
+ // try {
+ // Use MediaEngine to download and store the image
+ $media = \App\Helpers\FirstParty\MediaEngine\MediaEngine::addMedia(
+ 'system-i',
+ 'image',
+ 'system_uploaded',
+ 'replicate',
+ null,
+ $request->input('image_url'),
+ 'download'
+ );
+
+ // Update the background media record
+ $backgroundMedia->update([
+ 'status' => 'completed',
+ 'media_uuid' => $media->uuid,
+ 'media_url' => \App\Helpers\FirstParty\MediaEngine\MediaEngine::getMediaCloudUrl($media),
+ 'prompt' => $request->input('prompt'),
+ ]);
+
+ return response()->json(['success' => true]);
+ // } catch (\Exception $e) {
+ // return response()->json(['error' => 'Failed to save media: ' . $e->getMessage()], 500);
+ // }
+ }
+
+ private function callReplicateAPI($prompt)
+ {
+ $apiToken = config('services.replicate.api_token');
+
+ $data = [
+ 'input' => [
+ 'prompt' => $prompt,
+ 'go_fast' => true,
+ 'megapixels' => '1',
+ 'num_outputs' => 1,
+ 'aspect_ratio' => '1:1',
+ 'output_format' => 'webp',
+ 'output_quality' => 80,
+ 'num_inference_steps' => 4,
+ ],
+ ];
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions');
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ 'Authorization: Bearer '.$apiToken,
+ 'Content-Type: application/json',
+ 'Prefer: wait',
+ ]);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+ $response = curl_exec($ch);
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+ if ($httpCode !== 201) {
+ return false;
+ }
+
+ return json_decode($response, true);
+ }
+
+ private function pollReplicateResult($getUrl)
+ {
+ $maxAttempts = 30; // 5 minutes max (30 * 10 seconds)
+ $attempt = 0;
+
+ while ($attempt < $maxAttempts) {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $getUrl);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ 'Authorization: Bearer '.config('services.replicate.api_token'),
+ ]);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+ $response = curl_exec($ch);
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+ if ($httpCode === 200) {
+ $result = json_decode($response, true);
+
+ if ($result['status'] === 'succeeded' && isset($result['output'][0])) {
+ return $result;
+ } elseif ($result['status'] === 'failed') {
+ return false;
+ }
+ }
+
+ $attempt++;
+ sleep(3); // Wait 10 seconds before next poll
+ }
+
+ return false; // Timeout
+ }
+}
diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php
index db903e8..ea87cde 100644
--- a/app/Http/Controllers/Auth/RegisteredUserController.php
+++ b/app/Http/Controllers/Auth/RegisteredUserController.php
@@ -31,13 +31,11 @@ public function create(): Response
public function store(Request $request): RedirectResponse
{
$request->validate([
- 'name' => 'required|string|max:255',
'email' => 'required|string|lowercase|email|max:255|unique:'.User::class,
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
- 'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
diff --git a/app/Http/Controllers/FrontMediaController.php b/app/Http/Controllers/FrontMediaController.php
index 50b6a6c..c36437e 100644
--- a/app/Http/Controllers/FrontMediaController.php
+++ b/app/Http/Controllers/FrontMediaController.php
@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
+use App\Models\BackgroundMedia;
use App\Models\MemeMedia;
use Illuminate\Http\Request;
@@ -22,7 +23,7 @@ public function memes(Request $request)
public function background(Request $request)
{
- $backgrounds = MemeMedia::where('type', 'image')->where('sub_type', 'background')->take('30')->inRandomOrder()->get();
+ $backgrounds = BackgroundMedia::where('status', 'completed')->take('30')->inRandomOrder()->get();
return response()->json([
'success' => [
diff --git a/app/Models/BackgroundMedia.php b/app/Models/BackgroundMedia.php
index 08778e5..75fe36d 100644
--- a/app/Models/BackgroundMedia.php
+++ b/app/Models/BackgroundMedia.php
@@ -44,5 +44,6 @@ class BackgroundMedia extends Model
'media_uuid',
'media_url',
'embedding',
+ 'prompt',
];
}
diff --git a/config/platform/media.php b/config/platform/media.php
index f36837a..b3a5c65 100644
--- a/config/platform/media.php
+++ b/config/platform/media.php
@@ -49,4 +49,16 @@
'description' => 'Audios uploaded by user.',
'is_system' => false,
],
+ 'system-i' => [
+ 'owner_type' => 'system',
+ 'location' => '/system-i/',
+ 'prefix' => 'si_',
+ 'postfix' => '',
+ 'extension' => 'png',
+ 'mime' => 'image/png',
+ 'media_type' => 'image',
+ 'name' => 'System Images',
+ 'description' => 'Images uploaded by system.',
+ 'is_system' => true,
+ ],
];
diff --git a/config/services.php b/config/services.php
index 27a3617..31c2972 100644
--- a/config/services.php
+++ b/config/services.php
@@ -35,4 +35,8 @@
],
],
+ 'replicate' => [
+ 'api_token' => env('REPLICATE_API_TOKEN'),
+ ],
+
];
diff --git a/database/migrations/2025_06_13_053140_create_background_medias_table.php b/database/migrations/2025_06_13_053140_create_background_medias_table.php
index f587644..6a93b34 100644
--- a/database/migrations/2025_06_13_053140_create_background_medias_table.php
+++ b/database/migrations/2025_06_13_053140_create_background_medias_table.php
@@ -16,6 +16,7 @@ public function up(): void
$table->string('list_type');
$table->enum('area', ['interior', 'exterior']);
$table->string('location_name');
+ $table->text('prompt')->nullable();
$table->enum('status', ['pending_media', 'completed'])->default('pending_media');
$table->uuid('media_uuid')->nullable();
$table->string('media_url')->nullable();
diff --git a/resources/js/components/app-logo.tsx b/resources/js/components/app-logo.tsx
index 7c5919d..4144e2e 100644
--- a/resources/js/components/app-logo.tsx
+++ b/resources/js/components/app-logo.tsx
@@ -1,4 +1,3 @@
-
export default function AppLogo() {
return (
<>
@@ -6,7 +5,7 @@ export default function AppLogo() {
+ There are no pending media records to process. All background generation tasks have been completed. +
+ +Generating image...
+No image generated yet
+Click Generate to create an image
+