DONE: merge heir tab into profile tab, santize userIcNum and name, rename to malay, add stat card on user list
This commit is contained in:
@@ -269,6 +269,43 @@ class UserController extends BaseCrudController
|
||||
}
|
||||
}
|
||||
|
||||
public function stats(Request $request): JsonResponse
|
||||
{
|
||||
$this->authorize('viewAny', $this->modelClass);
|
||||
|
||||
try {
|
||||
$request->validate([
|
||||
'join_date_from' => 'nullable|date',
|
||||
'join_date_to' => 'nullable|date',
|
||||
'leave_date_from' => 'nullable|date',
|
||||
'leave_date_to' => 'nullable|date',
|
||||
]);
|
||||
|
||||
$dateFilters = array_filter([
|
||||
'join_date_from' => $request->get('join_date_from'),
|
||||
'join_date_to' => $request->get('join_date_to'),
|
||||
'leave_date_from' => $request->get('leave_date_from'),
|
||||
'leave_date_to' => $request->get('leave_date_to'),
|
||||
]);
|
||||
|
||||
$stats = $this->userService->getListStats(
|
||||
$request->get('search', ''),
|
||||
$request->get('status', ''),
|
||||
$dateFilters
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $stats,
|
||||
'message' => 'User stats retrieved successfully.',
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
Log::error("Error fetching {$this->resourceNamePlural} stats: ".$e->getMessage());
|
||||
|
||||
return $this->errorResponse('Failed to retrieve user stats.', 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function restore(string $id): JsonResponse
|
||||
{
|
||||
$this->authorize('restore', $this->modelClass);
|
||||
|
||||
@@ -55,6 +55,17 @@ interface UserRepositoryInterface
|
||||
string $sortOrder = 'desc'
|
||||
);
|
||||
|
||||
/**
|
||||
* Get stats for the Users list (filtered).
|
||||
*
|
||||
* @return array{total: int, joined_this_month: int}
|
||||
*/
|
||||
public function getListStats(
|
||||
string $search = '',
|
||||
string $status = '',
|
||||
array $dateFilters = []
|
||||
): array;
|
||||
|
||||
/**
|
||||
* Find soft-deleted User by ID
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Modules\User\Repositories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Modules\Auth\Entities\User;
|
||||
use Modules\User\Repositories\Contracts\UserRepositoryInterface;
|
||||
|
||||
@@ -85,7 +86,18 @@ class UserRepository implements UserRepositoryInterface
|
||||
|
||||
$query = User::excludeDevelopersUnlessDeveloper()
|
||||
->with([
|
||||
'roles:id,name,guard_name'
|
||||
'roles:id,name,guard_name',
|
||||
'employments' => function ($q) {
|
||||
$q->select([
|
||||
'id',
|
||||
'user_id',
|
||||
'company_name',
|
||||
'is_current',
|
||||
'start_date',
|
||||
])
|
||||
->orderByDesc('is_current')
|
||||
->orderByDesc('start_date');
|
||||
},
|
||||
])
|
||||
->orderBy($sortBy, $sortOrder);
|
||||
|
||||
@@ -129,6 +141,17 @@ class UserRepository implements UserRepositoryInterface
|
||||
->excludeDevelopersUnlessDeveloper()
|
||||
->with([
|
||||
'roles:id,name,guard_name',
|
||||
'employments' => function ($q) {
|
||||
$q->select([
|
||||
'id',
|
||||
'user_id',
|
||||
'company_name',
|
||||
'is_current',
|
||||
'start_date',
|
||||
])
|
||||
->orderByDesc('is_current')
|
||||
->orderByDesc('start_date');
|
||||
},
|
||||
])
|
||||
->orderBy($sortBy, $sortOrder);
|
||||
|
||||
@@ -141,6 +164,36 @@ class UserRepository implements UserRepositoryInterface
|
||||
return $query->paginate($perPage);
|
||||
}
|
||||
|
||||
public function getListStats(
|
||||
string $search = '',
|
||||
string $status = '',
|
||||
array $dateFilters = []
|
||||
): array {
|
||||
$baseQuery = User::excludeDevelopersUnlessDeveloper();
|
||||
|
||||
$this->applySearch($baseQuery, $search);
|
||||
|
||||
if (! empty($status)) {
|
||||
$baseQuery->where('status', $status);
|
||||
}
|
||||
|
||||
$this->applyDateRangeFilters($baseQuery, $dateFilters);
|
||||
|
||||
$total = (int) (clone $baseQuery)->count();
|
||||
|
||||
$monthStart = Carbon::now()->startOfMonth()->toDateString();
|
||||
$monthEnd = Carbon::now()->endOfMonth()->toDateString();
|
||||
$joinedThisMonth = (int) (clone $baseQuery)
|
||||
->whereDate('join_date', '>=', $monthStart)
|
||||
->whereDate('join_date', '<=', $monthEnd)
|
||||
->count();
|
||||
|
||||
return [
|
||||
'total' => $total,
|
||||
'joined_this_month' => $joinedThisMonth,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Users with their relationships and search
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ Route::prefix('v1/public')->group(function () {
|
||||
|
||||
Route::middleware(['auth:sanctum', 'single.session'])->prefix('v1')->group(function () {
|
||||
Route::get('users/deleted', [UserController::class, 'deletedIndex'])->name('users.deleted.index');
|
||||
Route::get('users/stats', [UserController::class, 'stats'])->name('users.stats');
|
||||
Route::post('users/{id}/restore', [UserController::class, 'restore'])->name('users.restore');
|
||||
Route::apiResource('users', UserController::class)->names('user');
|
||||
Route::apiResource('addresses', AddressController::class)->names('address');
|
||||
|
||||
@@ -50,6 +50,14 @@ class UserService
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{total: int, joined_this_month: int}
|
||||
*/
|
||||
public function getListStats(string $search, string $status, array $dateFilters = []): array
|
||||
{
|
||||
return $this->repository->getListStats($search, $status, $dateFilters);
|
||||
}
|
||||
|
||||
public function restoreUser(string $id): ?User
|
||||
{
|
||||
if (! $this->repository->restore($id)) {
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Modules\User\Transformers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\User\Transformers\EmploymentResource;
|
||||
|
||||
class UserListResource extends JsonResource
|
||||
{
|
||||
@@ -31,6 +32,7 @@ class UserListResource extends JsonResource
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
'deleted_at' => $this->deleted_at,
|
||||
'employments' => EmploymentResource::collection($this->whenLoaded('employments')),
|
||||
'roles' => $this->roles->map(function ($role) {
|
||||
return [
|
||||
'id' => $role->id,
|
||||
|
||||
Reference in New Issue
Block a user