Feat/neumorphism/widgets #3

Merged
paradox merged 2 commits from feat/neumorphism/widgets into test 2026-07-31 12:21:12 +02:00
10 changed files with 29 additions and 28 deletions
Showing only changes of commit aa4d0f217e - Show all commits
+1 -1
View File
@@ -22,7 +22,7 @@ const NAVIGATION_ITEMS = [
export const Sidebar: React.FC<SidebarProps> = ({ onLogout, className }) => {
return (
<Card className={cn("w-72 h-full flex flex-col p-6 shrink-0 rounded-none rounded-r-3xl", className)}>
<Card className={cn("w-60 flex flex-col p-6 shrink-0", className)}>
{/* 1. EN-TÊTE / LOGO */}
<div className="flex items-center gap-4 mb-10 px-2">
{/* Petit badge logo avec effet creusé */}
+2 -1
View File
@@ -12,7 +12,7 @@ import { NEUMORPHISM } from '@/styles/Neumorphism';
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
// 'raised' : relief neumorphique complet — dashboards, widgets isolés, peu nombreux à l'écran.
// 'flat' : bordure fine, sans ombre — listes/tables denses (perf + lisibilité).
variant?: 'raised' | 'flat';
variant?: 'raised' | 'flat'|'digged';
}
export const Card = React.forwardRef<HTMLDivElement, CardProps>(
@@ -25,6 +25,7 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
"bg-[#e8e8e8] dark:bg-[#1e293b]",
// Relief neumorphique (par défaut)
variant === 'raised' && [NEUMORPHISM.lightShadow, NEUMORPHISM.darkShadow],
variant === 'digged' && [NEUMORPHISM.insetDark, NEUMORPHISM.insetLight],
// Variante plate : pas d'ombre, juste une bordure discrète — pour tables/listes denses
variant === 'flat' && "border border-black/5 dark:border-white/10",
className
+1 -1
View File
@@ -10,7 +10,7 @@ interface PageHeaderProps {
export const PageHeader: React.FC<PageHeaderProps> = ({ title, description, children }) => {
return (
<Card className="border-slate-200 shadow-sm">
<Card>
<CardContent className="p-6 sm:px-8 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<div>
<h1 className="text-2xl font-bold text-slate-900 tracking-tight">
+9 -9
View File
@@ -1,6 +1,7 @@
import React from 'react';
import type { ManagedContract } from '@/types/ManagedContract';
import { StatusBadge } from '@/components/ui/StatusBadge';
import { Card } from './Card';
interface ServiceObjectProps {
contract: ManagedContract;
@@ -8,16 +9,15 @@ interface ServiceObjectProps {
export const ServiceObject: React.FC<ServiceObjectProps> = ({ contract }) => {
return (
<div className="p-4 bg-slate-50 rounded-lg border border-slate-100 flex justify-between items-center">
<div>
<Card variant= 'digged' className="p-4 rounded-lg border border-slate-100 flex flex-col">
<div className='flex flex-row justify-between'>
<h3 className="text-sm font-medium text-slate-900">{contract.service_name}</h3>
{contract.description && (
<p className="text-xs text-slate-500 mt-1">{contract.description}</p>
)}
{/* Fonctionne instantanément avec 'Actif', 'En déploiement', 'Suspendu' */}
<StatusBadge status={contract.status} />
</div>
{/* Fonctionne instantanément avec 'Actif', 'En déploiement', 'Suspendu' */}
<StatusBadge status={contract.status} />
</div>
{contract.description && (
<p className="text-xs text-slate-500 mt-1">{contract.description}</p>
)}
</Card>
);
};
+1 -1
View File
@@ -55,7 +55,7 @@ export const StatusBadge: React.FC<StatusBadgeProps> = ({ status, className }) =
return (
<div
className={cn(
"px-2.5 py-1 rounded-full text-xs font-semibold inline-flex items-center border transition-colors",
"px-2.5 py-1 rounded-full text-xs font-semibold inline-flex items-center border transition-colors min-w-fit max-h-fit",
config.bg,
className
)}
@@ -42,7 +42,7 @@ export const EvolutionFilterBar: React.FC<EvolutionFilterBarProps> = ({
<div className="relative min-w-60">
<Input
type="text"
sizeVariant="sm" // Format compact pour la barre de recherche
// Format compact pour la barre de recherche
placeholder="Rechercher une initiative..."
value={searchQuery}
onChange={(e) => onSearchChange(e.target.value)}
+1 -1
View File
@@ -19,7 +19,7 @@ export default function ServicesWidget() {
<p className="text-sm text-slate-500">Catalogue des contrats d'infogérance actifs</p>
</div>
<div className="flex-1 overflow-y-auto mb-6 space-y-3">
<div className="flex-1 mb-6 space-y-3">
{error && <EmptyState message={error} className="text-red-500" />}
{isLoading && !error && <Loader />}
{!isLoading && !error && contracts.length === 0 && (
+3 -3
View File
@@ -7,15 +7,15 @@ export const SupportCtaWidget: React.FC = () => {
const navigate = useNavigate();
return (
<Card className="bg-blue-900 border-blue-800 text-white shadow-sm">
<Card>
<CardContent className="p-6">
<h3 className="text-lg font-semibold mb-2">Centre de Support</h3>
<p className="text-blue-200 text-sm mb-4 leading-relaxed">
<p className="text-blue-900 text-sm mb-4 leading-relaxed">
Déclarez un incident critique ou demandez une évolution de votre infrastructure.
</p>
<Button
onClick={() => navigate('/support')}
className="w-full bg-white text-blue-900 hover:bg-slate-50 font-medium py-2.5 px-4 rounded-lg transition-colors shadow-sm"
className="w-full text-blue-900"
>
Ouvrir un ticket sécurisé
</Button>
+3 -3
View File
@@ -8,13 +8,13 @@ interface DashboardLayoutProps {
export default function DashboardLayout({ children, onLogout }: DashboardLayoutProps) {
return (
<div className="flex h-screen bg-slate-50 overflow-hidden">
<div className="h-screen w-full flex bg-[#e8e8e8] dark:bg-[#1e293b] text-slate-800 dark:text-slate-100 font-sans transition-all duration-300 ease-in-out">
{/* Intégration de la navbar extraite */}
<Sidebar onLogout={onLogout} />
<Sidebar onLogout={onLogout} className='my-4 ml-4'/>
{/* CONTENU PRINCIPAL */}
<main className="flex-1 overflow-y-auto scrollbar-hide">
<div className="p-8">
<div>
{children}
</div>
</main>
+5 -5
View File
@@ -10,8 +10,8 @@ export default function TrustCenter() {
const navigate = useNavigate();
return (
<div className="bg-slate-50 font-sans text-slate-900 relative min-h-[calc(100vh-4rem)]">
<main className="max-w-7xl mx-auto px-4 sm:px-8 py-8 space-y-6">
<div className="font-sans relative min-h-[calc(100vh-4rem)]">
<main className="max-w-7xl mx-auto px-8 sm:px-8 space-y-6 m-4">
{/* HEADER EXTRAIT */}
<PageHeader
@@ -31,8 +31,8 @@ export default function TrustCenter() {
</PageHeader>
{/* GRILLE DES WIDGETS */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6">
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6">
<div className="lg:col-span-3 space-y-6">
<UptimeWidget />
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<BackupWidget onClick={() => navigate('/backups')} />
@@ -40,7 +40,7 @@ export default function TrustCenter() {
</div>
</div>
<div className="space-y-6">
<div className="space-y-6 lg:col-span-2">
<ServicesWidget />
<SupportCtaWidget />
</div>