Added dynamic filtering

This commit is contained in:
Charles 2025-10-27 15:57:14 +01:00
parent ec3fc7f5ca
commit a219f0f067
2 changed files with 42 additions and 8 deletions

View File

@ -113,6 +113,7 @@ export default class extends Controller {
const first = (s) => (typeof s === "string" && s.length ? s.trim()[0].toUpperCase() : "");
const initials = `${first(data.name)}${first(data.prenom)}`;
// wrapper is for centering and circle clipping
const wrapper = document.createElement("div");
wrapper.className = "avatar-wrapper";
// same size for both cases
@ -282,7 +283,7 @@ export default class extends Controller {
}];
const tabulator = new Tabulator("#tabulator-userList", {
langs: TABULATOR_FR_LANG,
locale: "fr", //'en' for English, 'fr' for French (en is default, no need to include it)
locale: "fr",
ajaxURL: "/user/data",
ajaxConfig: "GET",
pagination: true,
@ -295,9 +296,26 @@ export default class extends Controller {
ajaxSorting: true,
ajaxFiltering: true,
rowHeight: 60,
layout: "fitColumns", // activate French
filterMode: "remote",
// Add this to send filter data
ajaxURLGenerator: function(url, config, params) {
let queryParams = new URLSearchParams();
queryParams.append('page', params.page || 1);
queryParams.append('size', params.size || 10);
// Add filters
if (params.filter) {
params.filter.forEach(filter => {
queryParams.append(`filter[${filter.field}]`, filter.value);
});
}
return `${url}?${queryParams.toString()}`;
},
rowHeight: 60,
layout: "fitColumns",
columns
});
};

View File

@ -393,11 +393,29 @@ class UserController extends AbstractController
$page = max(1, (int)$request->query->get('page', 1));
$size = max(1, (int)$request->query->get('size', 10));
// Get filter parameters
$filters = $request->query->all('filter', []);
$repo = $this->userRepository;
// Base query: keep your constraints intact (isDeleted=false, isActive=true)
// Base query
$qb = $repo->createQueryBuilder('u')
->where('u.isDeleted = :del')->setParameter('del', false);
// Apply filters
if (!empty($filters['name'])) {
$qb->andWhere('u.surname LIKE :name')
->setParameter('name', '%' . $filters['name'] . '%');
}
if (!empty($filters['prenom'])) {
$qb->andWhere('u.name LIKE :prenom')
->setParameter('prenom', '%' . $filters['prenom'] . '%');
}
if (!empty($filters['email'])) {
$qb->andWhere('u.email LIKE :email')
->setParameter('email', '%' . $filters['email'] . '%');
}
$countQb = clone $qb;
$total = (int)$countQb->select('COUNT(u.id)')->getQuery()->getSingleScalarResult();
@ -405,7 +423,7 @@ class UserController extends AbstractController
$offset = ($page - 1) * $size;
$rows = $qb->setFirstResult($offset)->setMaxResults($size)->getQuery()->getResult();
// Map to array (keep isConnected)
// Map to array
$data = array_map(function (User $user) {
return [
'id' => $user->getId(),
@ -419,15 +437,13 @@ class UserController extends AbstractController
];
}, $rows);
// Match organizations response shape
$lastPage = (int)ceil($total / $size);
return $this->json([
'data' => $data,
'last_page' => $lastPage,
'total' => $total, // optional but handy
'total' => $total,
]);
}
#[Route(path: '/indexTest', name: 'indexTest', methods: ['GET'])]