refactor(ui): move system badge to dedicated column and update Badge styles

This commit is contained in:
2026-04-22 15:02:10 -04:00
parent e00ec4bddb
commit 96c8352dcf
3 changed files with 15 additions and 167 deletions
+10 -4
View File
@@ -24,14 +24,13 @@ const RolesPageClient = () => {
style={{ backgroundColor: role.color || '#6b7280' }}
/>
<div>
<div className="text-sm font-medium text-neutral-900 dark:text-white">{role.name}</div>
<div className="text-sm font-medium text-neutral-900 dark:text-white">
{role.name}
</div>
{role.description && (
<div className="text-xs text-neutral-500 dark:text-gray-400">{role.description}</div>
)}
</div>
{role.is_system && (
<Badge variant="default" size="sm">Système</Badge>
)}
</div>
),
skeleton: { height: 'h-4', width: '60%' }
@@ -54,6 +53,13 @@ const RolesPageClient = () => {
),
skeleton: { height: 'h-4', width: '40px' }
},
{
key: 'is_system',
label: 'Système',
sortable: false,
render: (role) => role.is_system ? <Badge variant="default" size="sm">système</Badge> : null,
skeleton: { height: 'h-4', width: '60px' }
},
{
key: 'actions',
label: '',
+5 -5
View File
@@ -5,14 +5,14 @@ import React from 'react';
const Badge = ({
children,
variant = 'default',
size = 'md',
size = 'sm',
className = '',
...props
}) => {
const baseClassName = 'inline-flex items-center font-medium border';
const baseClassName = 'inline-flex items-center font-medium border font-ibm-plex-mono';
const variants = {
default: 'bg-neutral-200/80 text-neutral-700 border-neutral-300 dark:bg-neutral-500/10 dark:text-neutral-400 dark:border-neutral-500/20',
default: 'bg-neutral-100 text-neutral-700 border-neutral-200 dark:bg-neutral-500/10 dark:text-neutral-400 dark:border-neutral-500/20',
primary: 'bg-blue-100 text-blue-700 border-blue-200 dark:bg-blue-500/10 dark:text-blue-400 dark:border-blue-500/20',
success: 'bg-green-100 text-green-700 border-green-200 dark:bg-green-500/10 dark:text-green-400 dark:border-green-500/20',
warning: 'bg-yellow-100 text-yellow-700 border-yellow-200 dark:bg-yellow-500/10 dark:text-yellow-400 dark:border-yellow-500/20',
@@ -24,8 +24,8 @@ const Badge = ({
};
const sizes = {
sm: 'px-2 py-0.5 rounded-lg text-[12px]',
md: 'px-2.5 py-0.5 rounded-lg text-[12px]',
sm: 'px-[8px] py-[2px] rounded-lg text-[11px]',
md: 'px-[8px] py-[2px] rounded-lg text-[11px]',
lg: 'px-3 py-1 rounded-lg text-xs'
};
-158
View File
@@ -1,158 +0,0 @@
'use client';
import React from 'react';
import Button from './Button';
import { Skeleton } from './LoadingState';
const Pagination = ({
currentPage = 1,
totalPages = 1,
onPageChange,
onLimitChange,
limit = 20,
total = 0,
loading = false,
showPerPage = true,
showStats = true,
className = '',
...props
}) => {
// Generate page numbers with ellipsis
const getPageNumbers = () => {
const pages = [];
const delta = 2;
if (totalPages > 0) pages.push(1);
if (currentPage - delta > 2) pages.push('...');
for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) {
pages.push(i);
}
if (currentPage + delta < totalPages - 1) pages.push('...');
if (totalPages > 1) pages.push(totalPages);
return pages;
};
const PaginationButton = ({ onClick, disabled, children, isActive = false }) => (
<button
onClick={onClick}
disabled={disabled || loading}
className={`px-2 py-1 text-xs font-medium rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${
isActive
? 'bg-neutral-900 text-white border border-neutral-900 dark:bg-white dark:text-black dark:border-white'
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-700/30 hover:text-neutral-900 dark:hover:text-white'
}`}
>
{children}
</button>
);
if (totalPages <= 1 && !showPerPage && !loading) return null;
const from = total > 0 ? (currentPage - 1) * limit + 1 : 0;
const to = Math.min(currentPage * limit, total);
return (
<div className={`px-6 py-3 border-t border-neutral-200 dark:border-neutral-700/30 ${className}`} {...props}>
<div className="flex items-center justify-between gap-4">
{/* Per Page Selector */}
{showPerPage ? (
<div className="flex items-center gap-2 shrink-0">
{loading ? (
<Skeleton height="h-7" width="90px" />
) : (
<>
<span className="text-xs text-neutral-500 dark:text-neutral-400">Afficher</span>
<select
value={limit}
onChange={(e) => onLimitChange?.(Number(e.target.value))}
disabled={loading}
className="h-7 px-2 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700/50 rounded-md text-xs text-neutral-900 dark:text-white focus:outline-none focus:border-neutral-400 dark:focus:border-neutral-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
<option value={10}>10</option>
<option value={20}>20</option>
<option value={50}>50</option>
<option value={100}>100</option>
</select>
</>
)}
</div>
) : <div />}
{/* Pagination Controls */}
<div className="flex items-center gap-1">
{loading ? (
<>
<Skeleton height="h-7" width="64px" />
<div className="hidden sm:flex items-center gap-1">
{Array.from({ length: 3 }).map((_, i) => (
<Skeleton key={i} height="h-7" width="28px" />
))}
</div>
<Skeleton height="h-7" width="56px" />
</>
) : (
<>
{totalPages > 1 && (
<Button
variant="ghost"
size="sm"
onClick={() => onPageChange(currentPage - 1)}
disabled={currentPage === 1}
>
Précédent
</Button>
)}
{totalPages > 1 && (
<div className="hidden sm:flex items-center gap-1">
{getPageNumbers().map((page, index) => (
<React.Fragment key={index}>
{page === '...' ? (
<span className="px-2 text-xs text-neutral-400 dark:text-neutral-500"></span>
) : (
<PaginationButton
onClick={() => onPageChange(page)}
isActive={currentPage === page}
>
{page}
</PaginationButton>
)}
</React.Fragment>
))}
</div>
)}
{totalPages > 1 && (
<Button
variant="ghost"
size="sm"
onClick={() => onPageChange(currentPage + 1)}
disabled={currentPage === totalPages}
>
Suivant
</Button>
)}
</>
)}
</div>
{/* Stats */}
{showStats ? (
<div className="text-xs text-neutral-400 dark:text-neutral-500 shrink-0 text-right">
{loading ? (
<Skeleton height="h-4" width="100px" />
) : (
`${from}${to} sur ${total}`
)}
</div>
) : <div />}
</div>
</div>
);
};
export default Pagination;