feat: Add notification services for Email, Telegram, and WhatsApp
- Implement EmailNotifier for sending batch and test notifications via email. - Implement TelegramNotifier for sending batch and test notifications via Telegram. - Implement WahaNotifier for sending batch and test notifications via WhatsApp using WAHA API. - Create migration for client_categories table and update clients table to include category_id. - Create migration for notification_settings table to manage notification configurations. - Add ClientCategorySeeder to populate default client categories. - Create manifest.json for PWA support. - Implement service worker (sw.js) for caching static assets and offline support. - Add edit event view for modifying scheduled events. - Create search results view for displaying search queries. - Develop notification settings view for configuring notification channels and triggers.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('client_categories', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('slug')->unique();
|
||||
$table->unsignedBigInteger('parent_id')->nullable();
|
||||
$table->string('icon')->default('🏷️');
|
||||
$table->string('color')->default('#FFB7C5');
|
||||
$table->string('description')->nullable();
|
||||
$table->boolean('is_system')->default(false);
|
||||
$table->unsignedInteger('sort_order')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('parent_id')
|
||||
->references('id')
|
||||
->on('client_categories')
|
||||
->onDelete('set null');
|
||||
});
|
||||
|
||||
// Add category_id to clients table
|
||||
Schema::table('clients', function (Blueprint $table): void {
|
||||
$table->unsignedBigInteger('category_id')->nullable()->after('status');
|
||||
$table->foreign('category_id')
|
||||
->references('id')
|
||||
->on('client_categories')
|
||||
->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('clients', function (Blueprint $table): void {
|
||||
$table->dropForeign(['category_id']);
|
||||
$table->dropColumn('category_id');
|
||||
});
|
||||
|
||||
Schema::dropIfExists('client_categories');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('notification_settings', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->string('name'); // e.g. "My Telegram Bot"
|
||||
$table->string('channel'); // email | telegram | whatsapp
|
||||
$table->json('config'); // channel-specific credentials
|
||||
$table->json('triggers')->nullable(); // array: upcoming_event, invoice_due, content_due
|
||||
$table->boolean('is_enabled')->default(true);
|
||||
$table->integer('notify_before_hours')->default(24); // hours before event to notify
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('notification_settings');
|
||||
}
|
||||
};
|
||||
89
database/seeders/ClientCategorySeeder.php
Normal file
89
database/seeders/ClientCategorySeeder.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\ClientCategory;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class ClientCategorySeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$categories = [
|
||||
['name' => 'Food & Beverages', 'icon' => '🍔', 'color' => '#FFD5B8', 'children' => [
|
||||
['name' => 'Food', 'icon' => '🍱', 'color' => '#FFD5B8'],
|
||||
['name' => 'Beverages', 'icon' => '🥤', 'color' => '#FFD5B8'],
|
||||
['name' => 'Restaurant & Café', 'icon' => '☕', 'color' => '#FFD5B8'],
|
||||
['name' => 'Snacks & Treats', 'icon' => '🍪', 'color' => '#FFD5B8'],
|
||||
]],
|
||||
['name' => 'Fashion', 'icon' => '👗', 'color' => '#FFB7C5', 'children' => [
|
||||
['name' => 'Clothing', 'icon' => '👕', 'color' => '#FFB7C5'],
|
||||
['name' => 'Accessories', 'icon' => '💍', 'color' => '#FFB7C5'],
|
||||
['name' => 'Shoes & Footwear', 'icon' => '👠', 'color' => '#FFB7C5'],
|
||||
['name' => 'Bags & Luggage', 'icon' => '👜', 'color' => '#FFB7C5'],
|
||||
]],
|
||||
['name' => 'Beauty & Skincare', 'icon' => '💄', 'color' => '#E8D5F5', 'children' => [
|
||||
['name' => 'Skincare', 'icon' => '🧴', 'color' => '#E8D5F5'],
|
||||
['name' => 'Makeup', 'icon' => '💋', 'color' => '#E8D5F5'],
|
||||
['name' => 'Hair Care', 'icon' => '💇', 'color' => '#E8D5F5'],
|
||||
['name' => 'Fragrance', 'icon' => '🌸', 'color' => '#E8D5F5'],
|
||||
]],
|
||||
['name' => 'Technology', 'icon' => '💻', 'color' => '#AEC6CF', 'children' => [
|
||||
['name' => 'Consumer Electronics', 'icon' => '📱', 'color' => '#AEC6CF'],
|
||||
['name' => 'Apps & Software', 'icon' => '🖥️', 'color' => '#AEC6CF'],
|
||||
['name' => 'Gaming', 'icon' => '🎮', 'color' => '#AEC6CF'],
|
||||
['name' => 'Smart Home', 'icon' => '🏠', 'color' => '#AEC6CF'],
|
||||
]],
|
||||
['name' => 'Health & Wellness', 'icon' => '💪', 'color' => '#B5EAD7', 'children' => [
|
||||
['name' => 'Fitness', 'icon' => '🏋️', 'color' => '#B5EAD7'],
|
||||
['name' => 'Supplements', 'icon' => '💊', 'color' => '#B5EAD7'],
|
||||
['name' => 'Mental Health', 'icon' => '🧘', 'color' => '#B5EAD7'],
|
||||
]],
|
||||
['name' => 'Lifestyle', 'icon' => '🌿', 'color' => '#FDFD96', 'children' => [
|
||||
['name' => 'Travel', 'icon' => '✈️', 'color' => '#FDFD96'],
|
||||
['name' => 'Home & Living', 'icon' => '🛋️', 'color' => '#FDFD96'],
|
||||
['name' => 'Pets', 'icon' => '🐾', 'color' => '#FDFD96'],
|
||||
['name' => 'Parenting', 'icon' => '👶', 'color' => '#FDFD96'],
|
||||
]],
|
||||
['name' => 'Entertainment', 'icon' => '🎬', 'color' => '#AEC6CF', 'children' => [
|
||||
['name' => 'Movies & TV', 'icon' => '🎥', 'color' => '#AEC6CF'],
|
||||
['name' => 'Music', 'icon' => '🎵', 'color' => '#AEC6CF'],
|
||||
['name' => 'Sports', 'icon' => '⚽', 'color' => '#AEC6CF'],
|
||||
['name' => 'Gaming & Esports', 'icon' => '🕹️', 'color' => '#AEC6CF'],
|
||||
]],
|
||||
['name' => 'Finance', 'icon' => '💰', 'color' => '#FDFD96', 'children' => [
|
||||
['name' => 'Banking', 'icon' => '🏦', 'color' => '#FDFD96'],
|
||||
['name' => 'Insurance', 'icon' => '🛡️', 'color' => '#FDFD96'],
|
||||
['name' => 'Investment', 'icon' => '📈', 'color' => '#FDFD96'],
|
||||
]],
|
||||
['name' => 'Education', 'icon' => '📚', 'color' => '#B5EAD7', 'children' => [
|
||||
['name' => 'Online Courses', 'icon' => '🎓', 'color' => '#B5EAD7'],
|
||||
['name' => 'Kids Education', 'icon' => '🧒', 'color' => '#B5EAD7'],
|
||||
]],
|
||||
['name' => 'Other', 'icon' => '🏷️', 'color' => '#E5E7EB', 'children' => []],
|
||||
];
|
||||
|
||||
foreach ($categories as $i => $data) {
|
||||
$parent = ClientCategory::create([
|
||||
'name' => $data['name'],
|
||||
'icon' => $data['icon'],
|
||||
'color' => $data['color'],
|
||||
'is_system' => true,
|
||||
'sort_order' => $i,
|
||||
]);
|
||||
|
||||
foreach ($data['children'] as $j => $child) {
|
||||
ClientCategory::create([
|
||||
'name' => $child['name'],
|
||||
'icon' => $child['icon'],
|
||||
'color' => $child['color'],
|
||||
'parent_id' => $parent->id,
|
||||
'is_system' => true,
|
||||
'sort_order' => $j,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,5 +21,9 @@ class DatabaseSeeder extends Seeder
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
$this->call([
|
||||
ClientCategorySeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user