feat: promotions added

This commit is contained in:
2025-11-25 15:49:24 +03:30
parent cc916c30cc
commit 8e5ecd3898
4 changed files with 178 additions and 0 deletions
@@ -0,0 +1,103 @@
<?php
namespace App\Http\Controllers;
use App\Models\Promotion;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class PromotionController extends Controller
{
public function index()
{
$now = now();
$promotions = Promotion::where('is_active', true)
->where(function ($q) use ($now) {
$q->whereNull('start_at')
->orWhere('start_at', '<=', $now);
})
->where(function ($q) use ($now) {
$q->whereNull('end_at')
->orWhere('end_at', '>=', $now);
})
->orderBy('priority', 'desc')
->get();
return response()->json($promotions);
}
public function store(Request $request)
{
$data = $request->validate([
'type' => 'required|string|in:slider,action,paid_app,banner',
'title' => 'nullable|string',
'subtitle' => 'nullable|string',
'image' => 'nullable|file|image|max:2048',
'action_text' => 'nullable|string',
'url_myket' => 'nullable|string',
'url_bazzar' => 'nullable|string',
'url_google_play' => 'nullable|string',
'url_site' => 'nullable|string',
'priority' => 'nullable|integer',
'start_at' => 'nullable|date',
'end_at' => 'nullable|date',
]);
if ($request->hasFile('image')) {
$data['image'] = $request->file('image')->store('promotions', 'public');
}
$promotion = Promotion::create($data);
return response()->json($promotion, 201);
}
// UPDATE
public function update(Request $request, Promotion $promotion)
{
$data = $request->validate([
'type' => 'nullable|string|in:slider,action,paid_app,banner',
'title' => 'nullable|string',
'subtitle' => 'nullable|string',
'image' => 'nullable|file|image|max:2048',
'action_text' => 'nullable|string',
'url_myket' => 'nullable|string',
'url_bazzar' => 'nullable|string',
'url_google_play' => 'nullable|string',
'url_site' => 'nullable|string',
'is_active' => 'nullable|boolean',
'priority' => 'nullable|integer',
'start_at' => 'nullable|date',
'end_at' => 'nullable|date',
]);
if ($request->hasFile('image')) {
if ($promotion->image) {
Storage::disk('public')->delete($promotion->image);
}
$data['image'] = $request->file('image')->store('promotions', 'public');
}
$promotion->update($data);
return response()->json($promotion);
}
// DELETE
public function destroy(Promotion $promotion)
{
if ($promotion->image) {
Storage::disk('public')->delete($promotion->image);
}
$promotion->delete();
return response()->json(['message' => 'Promotion deleted']);
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Promotion extends Model
{
protected $fillable = [
'type', 'title', 'subtitle', 'image', 'action_text',
'url_myket', 'url_bazzar', 'url_google_play', 'url_site',
'is_active', 'priority', 'start_at', 'end_at'
];
protected $casts = [
'is_active' => 'boolean',
'start_at' => 'datetime',
'end_at' => 'datetime'
];
}
@@ -0,0 +1,49 @@
<?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('promotions', function (Blueprint $table) {
$table->id();
$table->string('type'); // slider, action, paid_app, banner
$table->string('title')->nullable();
$table->string('subtitle')->nullable();
$table->string('image')->nullable();
// action labels
$table->string('action_text')->nullable();
// platform-specific URLs
$table->string('url_myket')->nullable();
$table->string('url_bazzar')->nullable();
$table->string('url_google_play')->nullable();
$table->string('url_site')->nullable();
$table->boolean('is_active')->default(true);
$table->integer('priority')->default(0);
$table->timestamp('start_at')->nullable();
$table->timestamp('end_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('promotions');
}
};
+6
View File
@@ -12,6 +12,7 @@
use App\Http\Controllers\UserController; use App\Http\Controllers\UserController;
use App\Http\Controllers\WalletController; use App\Http\Controllers\WalletController;
use App\Http\Controllers\ZarinpalController; use App\Http\Controllers\ZarinpalController;
use App\Http\Controllers\PromotionController;
use App\Models\Transaction; use App\Models\Transaction;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Facades\Socialite;
@@ -94,6 +95,11 @@
Route::delete('/users/{mobile}/status', 'unsubscribeUser'); Route::delete('/users/{mobile}/status', 'unsubscribeUser');
}); });
}); });
///promotions
Route::get('/promotions', [PromotionController::class, 'index']);
Route::post('/promotions', [PromotionController::class, 'store']);
Route::post('/promotions/{promotion}', [PromotionController::class, 'update']);
Route::delete('/promotions/{promotion}', [PromotionController::class, 'destroy']);
Route::get('/asanpardakht/pay', [AsanPardakhtController::class, 'pay']); Route::get('/asanpardakht/pay', [AsanPardakhtController::class, 'pay']);
}); });