feat(api): add AI text-to-deck generation, wallet deposit structure, and profile/notification endpoints

Fills the gaps between the admin panel screens and the backend: a full
free-text + slide-count + language -> AI-generated presentation flow with
new slide-cloning logic in TemplateFillService, a "my presentations" list
endpoint, a swappable payment-gateway structure for wallet top-ups (fake
driver for now), and avatar upload / public-profile toggle / account
deletion / password change / notification preference endpoints.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-29 01:36:17 +03:30
parent fe2090a5af
commit 46ae711a20
42 changed files with 1632 additions and 44 deletions

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('templates', function (Blueprint $table) {
$table->boolean('is_ai_enabled')->default(false)->after('is_active');
$table->unsignedInteger('ai_repeatable_slide_number')->nullable()->after('is_ai_enabled');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('templates', function (Blueprint $table) {
$table->dropColumn(['is_ai_enabled', 'ai_repeatable_slide_number']);
});
}
};

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('template_generations', function (Blueprint $table) {
$table->string('source')->default('template')->after('template_id');
$table->string('title')->nullable()->after('source');
$table->string('language')->nullable()->after('title');
$table->unsignedInteger('slide_count')->nullable()->after('language');
$table->longText('source_text')->nullable()->after('slide_count');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('template_generations', function (Blueprint $table) {
$table->dropColumn(['source', 'title', 'language', 'slide_count', 'source_text']);
});
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('avatar_path')->nullable()->after('mobile');
$table->boolean('is_public')->default(false)->after('avatar_path');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['avatar_path', 'is_public']);
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('template_keys', function (Blueprint $table) {
$table->boolean('is_repeatable')->default(false)->after('is_required');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('template_keys', function (Blueprint $table) {
$table->dropColumn('is_repeatable');
});
}
};

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('wallet_deposits', function (Blueprint $table) {
$table->id();
$table->foreignId('wallet_id')->constrained()->cascadeOnDelete();
$table->unsignedBigInteger('amount');
$table->string('status')->default('pending');
$table->string('gateway');
$table->string('reference_id')->nullable();
$table->json('meta')->nullable();
$table->timestamps();
$table->index(['wallet_id', 'status']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('wallet_deposits');
}
};

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('notification_preferences', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->unique()->constrained()->cascadeOnDelete();
$table->boolean('comment_on_presentation')->default(true);
$table->boolean('form_reply')->default(false);
$table->boolean('new_follower')->default(false);
$table->boolean('news_announcements')->default(false);
$table->boolean('weekly_product_updates')->default(true);
$table->boolean('weekly_blog_digest')->default(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('notification_preferences');
}
};