Skip to content

Commit

Permalink
implementation of agent notifications resource and API
Browse files Browse the repository at this point in the history
  • Loading branch information
kyagie committed Mar 15, 2024
1 parent f079489 commit 50ec842
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 1 deletion.
121 changes: 121 additions & 0 deletions app/Filament/Resources/AgentNotificationResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

namespace App\Filament\Resources;

use App\Filament\Resources\AgentNotificationResource\Pages;
use App\Filament\Resources\AgentNotificationResource\RelationManagers;
use App\Models\Agent;
use App\Models\AgentNotification;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;

class AgentNotificationResource extends Resource
{
protected static ?string $model = AgentNotification::class;

protected static ?string $navigationIcon = 'heroicon-o-bell-alert';

protected static ?string $navigationGroup = 'Operations';

protected static ?int $navigationSort = 2;

public static function form(Form $form): Form
{
return $form
->schema([
// Forms\Components\Select::make('agent_id')
// ->searchable()
// ->relationship('agent', 'name')
// ->preload()
// ->required(),
Forms\Components\Select::make('agent_id')
->label('Agent')
->searchable()
->getSearchResultsUsing(
fn (string $search) => Agent::active()
->where('name', 'like', '%' . $search . '%')
->orWhere('phone_number', 'like', '%' . $search . '%')
->limit(10)->pluck('name', 'id')->toArray()
)
->getOptionLabelUsing(fn ($value) =>
Agent::find($value)->name . ' - ' . Agent::find($value)->phone_number
)
->helperText('Search for active agents with name or phone number(256...).'),
Forms\Components\TextInput::make('title')
->required()
->maxLength(255)
->columnSpanFull(),
Forms\Components\Textarea::make('message')
->required()
->columnSpanFull(),

]);
}

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('agent.name')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('title')
->label('Content')
->description(
fn (AgentNotification $record): string => $record->message
)
->searchable(),
Tables\Columns\TextColumn::make('user.name')
->label('Sent by')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('read_at')
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('deleted_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])->defaultSort('created_at', 'desc')
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}

public static function getRelations(): array
{
return [
//
];
}

public static function getPages(): array
{
return [
'index' => Pages\ListAgentNotifications::route('/'),
'create' => Pages\CreateAgentNotification::route('/create'),
'edit' => Pages\EditAgentNotification::route('/{record}/edit'),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Filament\Resources\AgentNotificationResource\Pages;

use App\Filament\Resources\AgentNotificationResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;

class CreateAgentNotification extends CreateRecord
{
protected static string $resource = AgentNotificationResource::class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Filament\Resources\AgentNotificationResource\Pages;

use App\Filament\Resources\AgentNotificationResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;

class EditAgentNotification extends EditRecord
{
protected static string $resource = AgentNotificationResource::class;

protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Filament\Resources\AgentNotificationResource\Pages;

use App\Filament\Resources\AgentNotificationResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;

class ListAgentNotifications extends ListRecords
{
protected static string $resource = AgentNotificationResource::class;

protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
2 changes: 1 addition & 1 deletion app/Filament/Resources/BillboardResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static function form(Form $form): Form
fn (string $search) => Agent::withDistricts()
->where('name', 'like', '%' . $search . '%')
->orWhere('phone_number', 'like', '%' . $search . '%')
->limit(50)->pluck('name', 'id')->toArray()
->limit(10)->pluck('name', 'id')->toArray()
)
->getOptionLabelUsing(fn ($value) =>
Agent::find($value)->name . ' - ' . Agent::find($value)->phone_number
Expand Down
56 changes: 56 additions & 0 deletions app/Http/Controllers/AgentNotificationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\AgentNotification;
use App\Models\Agent;

class AgentNotificationController extends Controller
{
//

public function agentNotifications(Request $request)
{
$agent = Agent::find($request->user()->agent_id);

if ($agent) {
return response()->json([
'notifications' => $agent->notifications()
->latest()
->get(),
'unread' => $agent->notifications()
->unread()
->count(),
]);
} else {
return response()->json([
'message' => 'Agent not found'
], 404);
}
}

public function markAsRead(Request $request)
{
$request->validate([
'ids' => 'required|array',
]);

$agent = Agent::find($request->user()->agent_id);

if ($agent) {
$agent->notifications()
->whereIn('id', $request->ids)
->update(['read_at' => now()]);

return response()->json([
'message' => 'Notifications marked as read'
]);
} else {
return response()->json([
'message' => 'Agent not found'
], 404);
}

}
}
6 changes: 6 additions & 0 deletions app/Models/Agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Models\Billboard;
use App\Models\AgentDistrict;
use App\Models\Device;
use App\Models\AgentNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
Expand Down Expand Up @@ -57,4 +58,9 @@ public function devices()
{
return $this->hasMany(Device::class);
}

public function notifications()
{
return $this->hasMany(AgentNotification::class);
}
}
69 changes: 69 additions & 0 deletions app/Models/AgentNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace App\Models;

use App\Models\Agent;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class AgentNotification extends Model
{
use HasFactory, SoftDeletes;

//Set user_id on creating
public static function boot()
{
parent::boot();
static::creating(function ($notification) {
$notification->user_id = auth()->id();
});
}

protected $fillable = [
'agent_id',
'user_id',
'title',
'message',
'read_at',
];

protected $hidden = [
'created_at',
'updated_at',
'deleted_at',
'user_id',
// 'agent_id',
];

protected $casts = [
'data' => 'array',
'read_at' => 'datetime',
'created_at' => 'datetime',
];

protected $appends = [
'created_at_human',
];

public function getCreatedAtHumanAttribute()
{
return $this->created_at->diffForHumans();
}

public function agent()
{
return $this->belongsTo(Agent::class);
}

public function user()
{
return $this->belongsTo(User::class);
}

public function scopeUnread($query)
{
return $query->whereNull('read_at');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?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('agent_notifications', function (Blueprint $table) {
$table->id();
$table->foreignId('agent_id')->constrained('agents');
$table->foreignId('user_id')->nullable()->constrained('users');
$table->string('title');
$table->text('message');
$table->timestamp('read_at')->nullable();
$table->softDeletes($column = 'deleted_at', $precision = 0);
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('agent_notifications');
}
};
10 changes: 10 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use App\Http\Controllers\AgentController;
use App\Http\Controllers\AgentDistrictController;
use App\Http\Controllers\AgentNotificationController;
use App\Http\Controllers\BillboardController;
use App\Http\Controllers\OneTimePasswordController;
use App\Http\Controllers\DeviceController;
Expand Down Expand Up @@ -55,6 +56,15 @@ function () {
}
);

Route::controller(AgentNotificationController::class)
->middleware('auth:sanctum')
->group(
function () {
Route::get('/agent/notifications', 'agentNotifications');
Route::patch('/agent/notifications/mark-as-read', 'markAsRead');
}
);

Route::controller(OneTimePasswordController::class)->group(
function () {
Route::post('/otp', 'sendOtp');
Expand Down

0 comments on commit 50ec842

Please sign in to comment.