feat: otimizacao de responsividade para celulares e tablets em todas as telas e modais

This commit is contained in:
2026-08-28 11:48:13 +00:00
parent dce4c04fa4
commit f91b513297
10 changed files with 117 additions and 115 deletions
+1 -1
View File
@@ -335,7 +335,7 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
"md:pl-68", // Push content on desktop "md:pl-68", // Push content on desktop
"pt-16 md:pt-0" // Add padding on mobile for header "pt-16 md:pt-0" // Add padding on mobile for header
)}> )}>
<div className="max-w-7xl mx-auto px-6 sm:px-10 lg:px-12 py-10 w-full animate-in fade-in slide-in-from-bottom-4 duration-500"> <div className="max-w-7xl mx-auto px-3.5 sm:px-6 md:px-8 lg:px-12 py-5 sm:py-8 md:py-10 w-full animate-in fade-in slide-in-from-bottom-4 duration-500">
{children} {children}
</div> </div>
</main> </main>
+6 -6
View File
@@ -13,15 +13,15 @@ export const Modal: React.FC<ModalProps> = ({ isOpen, onClose, title, children,
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-2.5 sm:p-4">
<div className={`bg-surface rounded-2xl shadow-[var(--shadow-premium)] w-full ${maxWidth} max-h-[90vh] flex flex-col animate-in fade-in zoom-in duration-200 border border-border/40 relative`}> <div className={`bg-surface rounded-2xl sm:rounded-3xl shadow-[var(--shadow-premium)] w-full ${maxWidth} max-h-[92vh] flex flex-col animate-in fade-in zoom-in duration-200 border border-border/40 relative overflow-hidden`}>
<div className="flex justify-between items-center p-5 border-b border-border"> <div className="flex justify-between items-center p-4 sm:p-5 border-b border-border">
<h2 className="text-xl font-bold text-text-main">{title}</h2> <h2 className="text-lg sm:text-xl font-bold text-text-main truncate pr-2">{title}</h2>
<button onClick={onClose} className="p-2 text-text-secondary hover:bg-surface-hover hover:text-text-main rounded-lg transition-colors" aria-label="Fechar modal"> <button onClick={onClose} className="p-2 text-text-secondary hover:bg-surface-hover hover:text-text-main rounded-lg transition-colors shrink-0" aria-label="Fechar modal">
<X className="w-5 h-5" /> <X className="w-5 h-5" />
</button> </button>
</div> </div>
<div className="p-6 overflow-y-auto"> <div className="p-4 sm:p-6 overflow-y-auto">
{children} {children}
</div> </div>
</div> </div>
@@ -242,7 +242,7 @@ export const CreatePaintingSchemeModal: React.FC<CreatePaintingSchemeModalProps>
required required
/> />
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Select <Select
name="type" name="type"
label="Tipo de Tinta" label="Tipo de Tinta"
@@ -259,18 +259,18 @@ export const CreatePaintingSchemeModal: React.FC<CreatePaintingSchemeModalProps>
<Input name="solidsVolume" label="Sólidos Vol. (%)" type="number" value={formData.solidsVolume} onChange={handleChange} /> <Input name="solidsVolume" label="Sólidos Vol. (%)" type="number" value={formData.solidsVolume} onChange={handleChange} />
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Input name="yieldTheoretical" label="Rendimento (m²/L)" type="number" step="0.01" value={formData.yieldTheoretical} onChange={handleChange} /> <Input name="yieldTheoretical" label="Rendimento (m²/L)" type="number" step="0.01" value={formData.yieldTheoretical} onChange={handleChange} />
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Input name="epsMin" label="EPS Mín (μm)" type="number" value={formData.epsMin} onChange={handleChange} /> <Input name="epsMin" label="EPS Mín (μm)" type="number" value={formData.epsMin} onChange={handleChange} />
<Input name="epsMax" label="EPS Máx (μm)" type="number" value={formData.epsMax} onChange={handleChange} /> <Input name="epsMax" label="EPS Máx (μm)" type="number" value={formData.epsMax} onChange={handleChange} />
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Input name="dilution" label="Diluição (%)" type="number" value={formData.dilution} onChange={handleChange} /> <Input name="dilution" label="Diluição (%)" type="number" value={formData.dilution} onChange={handleChange} />
<Input name="manufacturer" label="Fabricante" value={formData.manufacturer} onChange={handleChange} /> <Input name="manufacturer" label="Fabricante" value={formData.manufacturer} onChange={handleChange} />
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Input name="color" label="Cor (Munsell/RAL)" placeholder="Ex: N6.5 ou RAL 7035" value={formData.color} onChange={handleChange} /> <Input name="color" label="Cor (Munsell/RAL)" placeholder="Ex: N6.5 ou RAL 7035" value={formData.color} onChange={handleChange} />
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<label className="text-[10px] font-bold text-primary uppercase tracking-[0.15em] ml-1 mb-1">Cor Representativa</label> <label className="text-[10px] font-bold text-primary uppercase tracking-[0.15em] ml-1 mb-1">Cor Representativa</label>
@@ -299,9 +299,9 @@ export const CreatePaintingSchemeModal: React.FC<CreatePaintingSchemeModalProps>
/> />
</div> </div>
<div className="bg-surface-soft p-4 rounded-xl border border-border/40 mt-4"> <div className="bg-surface-soft p-3.5 sm:p-4 rounded-xl border border-border/40 mt-4">
<h3 className="text-sm font-bold text-text-main mb-3">Planejamento de Consumo (Opcional)</h3> <h3 className="text-sm font-bold text-text-main mb-3">Planejamento de Consumo (Opcional)</h3>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Select <Select
name="paintId" name="paintId"
label="Produto (Tinta)" label="Produto (Tinta)"
@@ -346,7 +346,7 @@ export const CreatePaintingSchemeModal: React.FC<CreatePaintingSchemeModalProps>
/> />
</div> </div>
</div> </div>
<div className="grid grid-cols-2 gap-4 mt-2"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4 mt-2">
<Input <Input
name="paintConsumption" name="paintConsumption"
label="Consumo Tinta (L/Kg)" label="Consumo Tinta (L/Kg)"
@@ -134,7 +134,7 @@ export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen,
<Input name="name" label="Nome do Projeto" required value={formData.name} onChange={handleChange} /> <Input name="name" label="Nome do Projeto" required value={formData.name} onChange={handleChange} />
<Input name="client" label="Cliente" required value={formData.client} onChange={handleChange} /> <Input name="client" label="Cliente" required value={formData.client} onChange={handleChange} />
<Input name="technician" label="Responsável Técnico" value={formData.technician} onChange={handleChange} /> <Input name="technician" label="Responsável Técnico" value={formData.technician} onChange={handleChange} />
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Input name="startDate" label="Início Planejado" type="date" value={formData.startDate} onChange={handleChange} /> <Input name="startDate" label="Início Planejado" type="date" value={formData.startDate} onChange={handleChange} />
<Input name="endDate" label="Fim Planejado" type="date" value={formData.endDate} onChange={handleChange} /> <Input name="endDate" label="Fim Planejado" type="date" value={formData.endDate} onChange={handleChange} />
</div> </div>
@@ -161,14 +161,14 @@ export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen,
) : ( ) : (
<div className="space-y-6 text-center py-4"> <div className="space-y-6 text-center py-4">
<div className="space-y-2"> <div className="space-y-2">
<h3 className="text-xl font-bold text-text-main">Configurar Esquema de Pintura?</h3> <h3 className="text-lg sm:text-xl font-bold text-text-main">Configurar Esquema de Pintura?</h3>
<p className="text-sm text-text-muted px-4">O projeto foi criado. Deseja adicionar um esquema de pintura agora?</p> <p className="text-xs sm:text-sm text-text-muted px-2 sm:px-4">O projeto foi criado. Deseja adicionar um esquema de pintura agora?</p>
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<button <button
onClick={() => setShowImportModal(true)} onClick={() => setShowImportModal(true)}
className="flex flex-col items-center justify-center gap-3 p-6 rounded-2xl border-2 border-dashed border-border hover:border-primary hover:bg-primary/5 transition-all group" className="flex flex-col items-center justify-center gap-3 p-4 sm:p-6 rounded-2xl border-2 border-dashed border-border hover:border-primary hover:bg-primary/5 transition-all group"
> >
<div className="p-3 rounded-full bg-surface-soft group-hover:bg-white text-primary transition-colors"> <div className="p-3 rounded-full bg-surface-soft group-hover:bg-white text-primary transition-colors">
<FileDown size={24} /> <FileDown size={24} />
+5 -5
View File
@@ -121,11 +121,11 @@ export const AdminDashboard: React.FC = () => {
</div> </div>
{/* Tabs Navigation */} {/* Tabs Navigation */}
<div className="flex p-1 bg-surface-soft rounded-xl border border-border/40 w-fit"> <div className="flex p-1 bg-surface-soft rounded-xl border border-border/40 overflow-x-auto max-w-full scrollbar-hide">
<button <button
onClick={() => setActiveTab('users')} onClick={() => setActiveTab('users')}
className={clsx( className={clsx(
"flex items-center gap-2 px-6 py-2.5 text-sm font-bold rounded-lg transition-all", "flex items-center gap-2 px-4 sm:px-6 py-2 sm:py-2.5 text-xs sm:text-sm font-bold rounded-lg transition-all shrink-0",
activeTab === 'users' activeTab === 'users'
? "bg-surface text-primary shadow-sm border border-border/40" ? "bg-surface text-primary shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -137,7 +137,7 @@ export const AdminDashboard: React.FC = () => {
<button <button
onClick={() => setActiveTab('organization')} onClick={() => setActiveTab('organization')}
className={clsx( className={clsx(
"flex items-center gap-2 px-6 py-2.5 text-sm font-bold rounded-lg transition-all", "flex items-center gap-2 px-4 sm:px-6 py-2 sm:py-2.5 text-xs sm:text-sm font-bold rounded-lg transition-all shrink-0",
activeTab === 'organization' activeTab === 'organization'
? "bg-surface text-primary shadow-sm border border-border/40" ? "bg-surface text-primary shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -149,7 +149,7 @@ export const AdminDashboard: React.FC = () => {
<button <button
onClick={() => setActiveTab('settings')} onClick={() => setActiveTab('settings')}
className={clsx( className={clsx(
"flex items-center gap-2 px-6 py-2.5 text-sm font-bold rounded-lg transition-all", "flex items-center gap-2 px-4 sm:px-6 py-2 sm:py-2.5 text-xs sm:text-sm font-bold rounded-lg transition-all shrink-0",
activeTab === 'settings' activeTab === 'settings'
? "bg-surface text-primary shadow-sm border border-border/40" ? "bg-surface text-primary shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -161,7 +161,7 @@ export const AdminDashboard: React.FC = () => {
<button <button
onClick={() => setActiveTab('backup')} onClick={() => setActiveTab('backup')}
className={clsx( className={clsx(
"flex items-center gap-2 px-6 py-2.5 text-sm font-bold rounded-lg transition-all", "flex items-center gap-2 px-4 sm:px-6 py-2 sm:py-2.5 text-xs sm:text-sm font-bold rounded-lg transition-all shrink-0",
activeTab === 'backup' activeTab === 'backup'
? "bg-surface text-primary shadow-sm border border-border/40" ? "bg-surface text-primary shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
+9 -9
View File
@@ -181,20 +181,20 @@ export const CalculatorDashboard: React.FC = () => {
}; };
return ( return (
<div className="space-y-8 animate-in fade-in duration-700"> <div className="space-y-6 sm:space-y-8 animate-in fade-in duration-700">
{/* Header */} {/* Header */}
<div className="flex flex-col md:flex-row md:items-end justify-between gap-6 pb-2"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 md:gap-6 pb-2">
<div className="space-y-4"> <div className="space-y-2">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black text-text-main tracking-tight mb-0">Ferramentas & Cálculos</h1> <h1 className="text-2xl sm:text-3xl md:text-4xl font-black text-text-main tracking-tight mb-0">Ferramentas & Cálculos</h1>
<p className="text-sm text-text-muted font-medium tracking-wide">Utilitários técnicos para pintura industrial</p> <p className="text-xs sm:text-sm text-text-muted font-medium tracking-wide">Utilitários técnicos para pintura industrial</p>
</div> </div>
</div> </div>
</div> </div>
{/* Tabs */} {/* Tabs */}
<div className="flex items-center justify-between border-b border-border/40 scrollbar-hide overflow-x-auto"> <div className="flex items-center justify-between border-b border-border/40 scrollbar-hide overflow-x-auto">
<nav className="flex space-x-10 min-w-max px-2" aria-label="Tabs"> <nav className="flex space-x-3 sm:space-x-6 md:space-x-10 min-w-max px-1" aria-label="Tabs">
{[ {[
{ id: 'conversion', label: 'Conversões', icon: ArrowRightLeft }, { id: 'conversion', label: 'Conversões', icon: ArrowRightLeft },
{ id: 'thickness', label: 'Espessura', icon: Ruler }, { id: 'thickness', label: 'Espessura', icon: Ruler },
@@ -209,7 +209,7 @@ export const CalculatorDashboard: React.FC = () => {
key={tab.id} key={tab.id}
onClick={() => setActiveTab(tab.id)} onClick={() => setActiveTab(tab.id)}
className={clsx( className={clsx(
'whitespace-nowrap py-5 px-1 border-b-2 font-bold text-xs uppercase tracking-[0.15em] flex items-center gap-3 transition-all relative', 'whitespace-nowrap py-3.5 sm:py-5 px-1 border-b-2 font-bold text-[11px] sm:text-xs uppercase tracking-[0.15em] flex items-center gap-2 sm:gap-3 transition-all relative',
active active
? 'border-primary text-primary' ? 'border-primary text-primary'
: 'border-transparent text-text-muted hover:text-text-main hover:border-border' : 'border-transparent text-text-muted hover:text-text-main hover:border-border'
@@ -230,8 +230,8 @@ export const CalculatorDashboard: React.FC = () => {
{/* 1. CONVERSION */} {/* 1. CONVERSION */}
{activeTab === 'conversion' && ( {activeTab === 'conversion' && (
<div className="max-w-2xl mx-auto space-y-6 animate-in slide-in-from-bottom-4 duration-500"> <div className="max-w-2xl mx-auto space-y-6 animate-in slide-in-from-bottom-4 duration-500">
<Card className="p-8 space-y-8 bg-surface border-border/40 shadow-soft"> <Card className="p-4 sm:p-6 md:p-8 space-y-6 sm:space-y-8 bg-surface border-border/40 shadow-soft">
<div className="flex flex-col gap-2 border-b border-border/40 pb-6"> <div className="flex flex-col gap-1 sm:gap-2 border-b border-border/40 pb-4 sm:pb-6">
<h3 className="text-xl font-bold text-text-main">Conversor de Unidades</h3> <h3 className="text-xl font-bold text-text-main">Conversor de Unidades</h3>
<p className="text-sm text-text-muted">Microns (μm) Milesimos de Polegada (mils)</p> <p className="text-sm text-text-muted">Microns (μm) Milesimos de Polegada (mils)</p>
</div> </div>
+6 -6
View File
@@ -141,11 +141,11 @@ export const DeveloperDashboard: React.FC = () => {
</div> </div>
{/* Tabs Navigation */} {/* Tabs Navigation */}
<div className="flex items-center gap-2 p-1 bg-surface-soft rounded-2xl border border-border/20 w-fit"> <div className="flex items-center gap-1.5 sm:gap-2 p-1 bg-surface-soft rounded-2xl border border-border/20 overflow-x-auto max-w-full scrollbar-hide">
<button <button
onClick={() => setActiveTab('overview')} onClick={() => setActiveTab('overview')}
className={clsx( className={clsx(
"flex items-center gap-2 px-4 py-2 text-sm font-bold rounded-xl transition-all", "flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-2 text-xs sm:text-sm font-bold rounded-xl transition-all shrink-0",
activeTab === 'overview' activeTab === 'overview'
? "bg-surface text-indigo-500 shadow-sm border border-border/40" ? "bg-surface text-indigo-500 shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -157,7 +157,7 @@ export const DeveloperDashboard: React.FC = () => {
<button <button
onClick={() => setActiveTab('organizations')} onClick={() => setActiveTab('organizations')}
className={clsx( className={clsx(
"flex items-center gap-2 px-4 py-2 text-sm font-bold rounded-xl transition-all", "flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-2 text-xs sm:text-sm font-bold rounded-xl transition-all shrink-0",
activeTab === 'organizations' activeTab === 'organizations'
? "bg-surface text-indigo-500 shadow-sm border border-border/40" ? "bg-surface text-indigo-500 shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -169,7 +169,7 @@ export const DeveloperDashboard: React.FC = () => {
<button <button
onClick={() => setActiveTab('users')} onClick={() => setActiveTab('users')}
className={clsx( className={clsx(
"flex items-center gap-2 px-4 py-2 text-sm font-bold rounded-xl transition-all", "flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-2 text-xs sm:text-sm font-bold rounded-xl transition-all shrink-0",
activeTab === 'users' activeTab === 'users'
? "bg-surface text-indigo-500 shadow-sm border border-border/40" ? "bg-surface text-indigo-500 shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -181,7 +181,7 @@ export const DeveloperDashboard: React.FC = () => {
<button <button
onClick={() => setActiveTab('branding')} onClick={() => setActiveTab('branding')}
className={clsx( className={clsx(
"flex items-center gap-2 px-4 py-2 text-sm font-bold rounded-xl transition-all", "flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-2 text-xs sm:text-sm font-bold rounded-xl transition-all shrink-0",
activeTab === 'branding' activeTab === 'branding'
? "bg-surface text-indigo-500 shadow-sm border border-border/40" ? "bg-surface text-indigo-500 shadow-sm border border-border/40"
: "text-text-muted hover:text-text-main hover:bg-surface-hover" : "text-text-muted hover:text-text-main hover:bg-surface-hover"
@@ -193,7 +193,7 @@ export const DeveloperDashboard: React.FC = () => {
</div> </div>
{/* Content Area */} {/* Content Area */}
<div className="bg-surface rounded-3xl border border-border/40 min-h-[500px] overflow-hidden"> <div className="bg-surface rounded-2xl sm:rounded-3xl border border-border/40 min-h-[450px] overflow-hidden">
{activeTab === 'overview' && ( {activeTab === 'overview' && (
<div className="p-12 flex flex-col items-center justify-center text-center h-full"> <div className="p-12 flex flex-col items-center justify-center text-center h-full">
<div className="w-16 h-16 rounded-2xl bg-indigo-500/10 flex items-center justify-center mb-6 text-indigo-500 ring-1 ring-indigo-500/20"> <div className="w-16 h-16 rounded-2xl bg-indigo-500/10 flex items-center justify-center mb-6 text-indigo-500 ring-1 ring-indigo-500/20">
+20 -20
View File
@@ -201,17 +201,17 @@ export const ProjectDetails: React.FC = () => {
return ( return (
<div className="space-y-8 animate-in fade-in duration-700"> <div className="space-y-8 animate-in fade-in duration-700">
{/* Page Header */} {/* Page Header */}
<div className="flex flex-col md:flex-row md:items-end justify-between gap-6 pb-2"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 md:gap-6 pb-2">
<div className="space-y-4"> <div className="space-y-3 sm:space-y-4">
<Link to="/projects"> <Link to="/projects">
<button className="flex items-center text-[10px] font-bold text-text-muted uppercase tracking-[0.2em] hover:text-primary transition-colors group"> <button className="flex items-center text-[10px] font-bold text-text-muted uppercase tracking-[0.2em] hover:text-primary transition-colors group">
<ArrowLeft className="w-3 h-3 mr-2 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-3 h-3 mr-2 group-hover:-translate-x-1 transition-transform" />
Voltar aos Projetos Voltar aos Projetos
</button> </button>
</Link> </Link>
<div className="flex flex-col sm:flex-row sm:items-center gap-4"> <div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
<h1 className="text-3xl md:text-4xl font-black text-text-main tracking-tight mb-0">{project.name}</h1> <h1 className="text-2xl sm:text-3xl md:text-4xl font-black text-text-main tracking-tight mb-0">{project.name}</h1>
<span className="inline-flex items-center px-3 py-1 rounded-full bg-primary/10 text-primary text-[10px] font-black uppercase tracking-widest border border-primary/20 shadow-sm shadow-primary/5"> <span className="inline-flex items-center w-fit px-3 py-1 rounded-full bg-primary/10 text-primary text-[10px] font-black uppercase tracking-widest border border-primary/20 shadow-sm shadow-primary/5">
<Activity className="w-3 h-3 mr-2" /> <Activity className="w-3 h-3 mr-2" />
Em Andamento Em Andamento
</span> </span>
@@ -221,12 +221,12 @@ export const ProjectDetails: React.FC = () => {
<div className="w-6 h-6 rounded-full bg-surface-highlight border-2 border-surface flex items-center justify-center text-[10px] font-bold">M</div> <div className="w-6 h-6 rounded-full bg-surface-highlight border-2 border-surface flex items-center justify-center text-[10px] font-bold">M</div>
<div className="w-6 h-6 rounded-full bg-primary/20 border-2 border-surface flex items-center justify-center text-[10px] font-bold text-primary">G</div> <div className="w-6 h-6 rounded-full bg-primary/20 border-2 border-surface flex items-center justify-center text-[10px] font-bold text-primary">G</div>
</div> </div>
<span className="text-sm text-text-secondary font-medium">{project.client} {project.environment}</span> <span className="text-xs sm:text-sm text-text-secondary font-medium">{project.client} {project.environment}</span>
</div> </div>
</div> </div>
{isAdmin() && ( {isAdmin() && (
<div className="flex gap-3"> <div className="flex flex-wrap sm:flex-nowrap gap-2 sm:gap-3">
<Button variant="secondary" size="sm" onClick={() => setIsEditProjectModalOpen(true)}> <Button variant="secondary" size="sm" onClick={() => setIsEditProjectModalOpen(true)}>
<Pencil className="w-4 h-4 mr-2" /> Editar Obra <Pencil className="w-4 h-4 mr-2" /> Editar Obra
</Button> </Button>
@@ -238,45 +238,45 @@ export const ProjectDetails: React.FC = () => {
</div> </div>
{/* Premium Summary Grid */} {/* Premium Summary Grid */}
<div className="relative overflow-hidden rounded-3xl bg-surface border border-border/40 shadow-soft p-8"> <div className="relative overflow-hidden rounded-2xl sm:rounded-3xl bg-surface border border-border/40 shadow-soft p-4 sm:p-6 md:p-8">
<div className="absolute top-0 right-0 p-8 opacity-5"> <div className="absolute top-0 right-0 p-8 opacity-5">
<Activity size={120} strokeWidth={1} /> <Activity size={120} strokeWidth={1} />
</div> </div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 relative z-10"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4 sm:gap-6 md:gap-8 relative z-10">
<div className="space-y-1"> <div className="space-y-1">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Data de Início</span> <span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Data de Início</span>
<p className="text-lg font-bold text-text-main">{project.startDate ? format(new Date(project.startDate), 'dd MMM, yyyy') : '-'}</p> <p className="text-sm sm:text-base md:text-lg font-bold text-text-main">{project.startDate ? format(new Date(project.startDate), 'dd MMM, yyyy') : '-'}</p>
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Previsão Término</span> <span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Previsão Término</span>
<p className="text-lg font-bold text-text-main">{project.endDate ? format(new Date(project.endDate), 'dd MMM, yyyy') : '-'}</p> <p className="text-sm sm:text-base md:text-lg font-bold text-text-main">{project.endDate ? format(new Date(project.endDate), 'dd MMM, yyyy') : '-'}</p>
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Peso da Obra (KGF)</span> <span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Peso da Obra (KGF)</span>
<p className="text-lg font-bold text-text-main"> <p className="text-sm sm:text-base md:text-lg font-bold text-text-main">
{project.weightKg ? Number(project.weightKg).toLocaleString('pt-BR') : '0'} <span className="text-sm text-text-muted">kg</span> {project.weightKg ? Number(project.weightKg).toLocaleString('pt-BR') : '0'} <span className="text-xs sm:text-sm text-text-muted">kg</span>
</p> </p>
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Evolução%</span> <span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Evolução%</span>
<p className="text-lg font-bold text-primary"> <p className="text-sm sm:text-base md:text-lg font-bold text-primary">
{project.weightKg && project.paintedWeight !== undefined {project.weightKg && project.paintedWeight !== undefined
? Math.min(Math.round((project.paintedWeight / project.weightKg) * 100), 100) ? Math.min(Math.round((project.paintedWeight / project.weightKg) * 100), 100)
: 0} : 0}
<span className="text-sm">%</span> <span className="text-xs sm:text-sm">%</span>
</p> </p>
</div> </div>
</div> </div>
<div className="mt-6 pt-6 border-t border-border/20 grid grid-cols-1 md:grid-cols-2 gap-6 relative z-10"> <div className="mt-4 sm:mt-6 pt-4 sm:pt-6 border-t border-border/20 grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6 relative z-10">
<div className="space-y-1"> <div className="space-y-1">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Localização/Amb.</span> <span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Localização/Amb.</span>
<p className="text-sm font-medium text-text-secondary">{project.environment || '-'}</p> <p className="text-xs sm:text-sm font-medium text-text-secondary">{project.environment || '-'}</p>
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Eng. Responsável</span> <span className="text-[10px] font-bold text-text-muted uppercase tracking-widest block">Eng. Responsável</span>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="w-2 h-2 rounded-full bg-blue-500"></div> <div className="w-2 h-2 rounded-full bg-blue-500"></div>
<p className="text-sm font-bold text-text-main">{project.technician || '-'}</p> <p className="text-xs sm:text-sm font-bold text-text-main">{project.technician || '-'}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -284,7 +284,7 @@ export const ProjectDetails: React.FC = () => {
{/* Navigation Tabs */} {/* Navigation Tabs */}
<div className="flex items-center justify-between border-b border-border/40 scrollbar-hide overflow-x-auto"> <div className="flex items-center justify-between border-b border-border/40 scrollbar-hide overflow-x-auto">
<nav className="flex space-x-10" aria-label="Tabs"> <nav className="flex space-x-4 sm:space-x-8 md:space-x-10 min-w-max px-1" aria-label="Tabs">
{tabs.map((tab) => { {tabs.map((tab) => {
const Icon = tab.icon; const Icon = tab.icon;
const active = activeTab === tab.id; const active = activeTab === tab.id;
@@ -293,7 +293,7 @@ export const ProjectDetails: React.FC = () => {
key={tab.id} key={tab.id}
onClick={() => setActiveTab(tab.id)} onClick={() => setActiveTab(tab.id)}
className={clsx( className={clsx(
'whitespace-nowrap py-5 px-1 border-b-2 font-bold text-xs uppercase tracking-[0.15em] flex items-center gap-3 transition-all relative', 'whitespace-nowrap py-3.5 sm:py-5 px-1 border-b-2 font-bold text-[11px] sm:text-xs uppercase tracking-[0.15em] flex items-center gap-2 sm:gap-3 transition-all relative',
active active
? 'border-primary text-primary' ? 'border-primary text-primary'
: 'border-transparent text-text-muted hover:text-text-main hover:border-border' : 'border-transparent text-text-muted hover:text-text-main hover:border-border'
+17 -17
View File
@@ -351,17 +351,17 @@ export const ProjectList: React.FC = () => {
return ( return (
<div className="space-y-10 animate-in fade-in duration-700"> <div className="space-y-10 animate-in fade-in duration-700">
{/* Page Header */} {/* Page Header */}
<div className="flex flex-col md:flex-row md:items-end justify-between gap-6"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 md:gap-6">
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-2xl bg-primary/10 flex items-center justify-center text-primary shadow-sm"> <div className="w-10 h-10 sm:w-12 sm:h-12 rounded-2xl bg-primary/10 flex items-center justify-center text-primary shadow-sm shrink-0">
<Activity className="w-6 h-6" /> <Activity className="w-5 h-5 sm:w-6 sm:h-6" />
</div> </div>
<div> <div>
<h1 className="text-3xl md:text-4xl font-black text-text-main tracking-tight mb-0"> <h1 className="text-2xl sm:text-3xl md:text-4xl font-black text-text-main tracking-tight mb-0">
{viewStatus === 'active' ? 'Gestão de Obras' : 'Obras Arquivadas'} {viewStatus === 'active' ? 'Gestão de Obras' : 'Obras Arquivadas'}
</h1> </h1>
<p className="text-sm text-text-muted font-medium tracking-wide"> <p className="text-xs sm:text-sm text-text-muted font-medium tracking-wide">
{viewStatus === 'active' {viewStatus === 'active'
? 'Monitoramento e controle de esquemas industriais' ? 'Monitoramento e controle de esquemas industriais'
: 'Histórico de projetos concluídos e arquivados'} : 'Histórico de projetos concluídos e arquivados'}
@@ -370,22 +370,22 @@ export const ProjectList: React.FC = () => {
</div> </div>
</div> </div>
<div className="flex flex-wrap items-center gap-3"> <div className="flex flex-wrap items-center gap-2 sm:gap-3">
<Button <Button
variant="secondary" variant="secondary"
onClick={() => setViewStatus(viewStatus === 'active' ? 'archived' : 'active')} onClick={() => setViewStatus(viewStatus === 'active' ? 'archived' : 'active')}
className={`shadow-sm ${viewStatus === 'archived' ? 'bg-indigo-500/10 text-indigo-500 border-indigo-500/20' : ''}`} className={`shadow-sm text-xs sm:text-sm ${viewStatus === 'archived' ? 'bg-indigo-500/10 text-indigo-500 border-indigo-500/20' : ''}`}
> >
{viewStatus === 'active' ? <Box className="w-5 h-5 mr-2" /> : <Activity className="w-5 h-5 mr-2" />} {viewStatus === 'active' ? <Box className="w-4 h-4 sm:w-5 sm:h-5 mr-1.5 sm:mr-2" /> : <Activity className="w-4 h-4 sm:w-5 sm:h-5 mr-1.5 sm:mr-2" />}
{viewStatus === 'active' ? 'Ver Arquivados' : 'Ver Ativos'} {viewStatus === 'active' ? 'Ver Arquivados' : 'Ver Ativos'}
</Button> </Button>
<div className="relative hidden lg:block group"> <div className="relative group flex-1 sm:flex-initial min-w-[140px]">
<Search className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted group-focus-within:text-primary transition-colors" /> <Search className="absolute left-3 sm:left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted group-focus-within:text-primary transition-colors" />
<input <input
type="text" type="text"
placeholder="Buscar obras..." placeholder="Buscar obras..."
className="h-12 w-48 bg-surface-soft border border-border/40 rounded-xl pl-12 pr-4 text-sm focus:ring-4 focus:ring-primary/10 focus:border-primary transition-all font-medium" className="h-10 sm:h-12 w-full sm:w-48 bg-surface-soft border border-border/40 rounded-xl pl-9 sm:pl-12 pr-3 sm:pr-4 text-xs sm:text-sm focus:ring-4 focus:ring-primary/10 focus:border-primary transition-all font-medium"
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
/> />
@@ -394,16 +394,16 @@ export const ProjectList: React.FC = () => {
<Button <Button
variant="secondary" variant="secondary"
onClick={handlePrintGeneral} onClick={handlePrintGeneral}
className="shadow-sm" className="shadow-sm text-xs sm:text-sm"
disabled={isPrintingGeneral || projects.length === 0} disabled={isPrintingGeneral || projects.length === 0}
> >
<Printer className="w-5 h-5 mr-2" /> <Printer className="w-4 h-4 sm:w-5 sm:h-5 mr-1.5 sm:mr-2" />
Relatório Geral Relatório Geral
</Button> </Button>
{isAdmin && viewStatus === 'active' && ( {isAdmin && viewStatus === 'active' && (
<Button onClick={() => { setSelectedProject(undefined); setIsModalOpen(true); }} size="md" className="shadow-primary/30"> <Button onClick={() => { setSelectedProject(undefined); setIsModalOpen(true); }} size="md" className="shadow-primary/30 text-xs sm:text-sm">
<Plus className="w-5 h-5 mr-2" /> <Plus className="w-4 h-4 sm:w-5 sm:h-5 mr-1.5 sm:mr-2" />
Novo Projeto Novo Projeto
</Button> </Button>
)} )}
@@ -412,7 +412,7 @@ export const ProjectList: React.FC = () => {
{/* Quick Stats */} {/* Quick Stats */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4"> <div className="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
{[ {[
{ {
label: viewStatus === 'active' ? 'Projetos Ativos' : 'Projetos Arquivados', label: viewStatus === 'active' ? 'Projetos Ativos' : 'Projetos Arquivados',
@@ -452,7 +452,7 @@ export const ProjectList: React.FC = () => {
<div <div
key={i} key={i}
onClick={stat.onClick} onClick={stat.onClick}
className={`p-6 bg-surface border border-border/40 rounded-2xl shadow-sm group transition-all ${stat.interactive ? 'cursor-pointer hover:border-primary/40 hover:shadow-md active:scale-95' : ''}`} className={`p-3.5 sm:p-5 md:p-6 bg-surface border border-border/40 rounded-2xl shadow-sm group transition-all ${stat.interactive ? 'cursor-pointer hover:border-primary/40 hover:shadow-md active:scale-95' : ''}`}
> >
<span className="text-[10px] font-black text-text-muted uppercase tracking-[0.2em]">{stat.label}</span> <span className="text-[10px] font-black text-text-muted uppercase tracking-[0.2em]">{stat.label}</span>
<div className="mt-2 flex items-baseline gap-2"> <div className="mt-2 flex items-baseline gap-2">
+40 -38
View File
@@ -926,25 +926,25 @@ export const YieldStudyDashboard: React.FC = () => {
</div> </div>
{/* Cards de Resumo (Estilo do Relatório de Obras) */} {/* Cards de Resumo (Estilo do Relatório de Obras) */}
<div className="grid grid-cols-4 gap-4 mb-8"> <div className="grid grid-cols-2 md:grid-cols-4 gap-3 sm:gap-4 mb-6 sm:mb-8">
<div className="border border-gray-300 rounded-xl p-4 space-y-1"> <div className="border border-gray-300 rounded-xl p-3 sm:p-4 space-y-1">
<span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Peso Total (Ton)</span> <span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Peso Total (Ton)</span>
<div className="text-xl font-black">{(selectedStudy.totalWeight || 0).toFixed(2)}</div> <div className="text-lg sm:text-xl font-black">{(selectedStudy.totalWeight || 0).toFixed(2)}</div>
<p className="text-[7px] text-gray-400 font-bold uppercase">Soma das categorias</p> <p className="text-[7px] text-gray-400 font-bold uppercase">Soma das categorias</p>
</div> </div>
<div className="border border-gray-300 rounded-xl p-4 space-y-1"> <div className="border border-gray-300 rounded-xl p-3 sm:p-4 space-y-1">
<span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Tinta Total (Peso)</span> <span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Tinta Total (Peso)</span>
<div className="text-xl font-black text-amber-600">{Math.round(selectedStudy.estimatedPaintVolume)} <span className="text-[10px]">L</span></div> <div className="text-lg sm:text-xl font-black text-amber-600">{Math.round(selectedStudy.estimatedPaintVolume)} <span className="text-[10px]">L</span></div>
<p className="text-[7px] text-gray-400 font-bold uppercase">Baseado em L/t</p> <p className="text-[7px] text-gray-400 font-bold uppercase">Baseado em L/t</p>
</div> </div>
<div className="border border-gray-300 rounded-xl p-4 space-y-1"> <div className="border border-gray-300 rounded-xl p-3 sm:p-4 space-y-1">
<span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Tinta Total (Área)</span> <span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Tinta Total (Área)</span>
<div className="text-xl font-black text-blue-600">{Math.round(selectedStudy.estimatedPaintVolumeByArea || 0)} <span className="text-[10px]">L</span></div> <div className="text-lg sm:text-xl font-black text-blue-600">{Math.round(selectedStudy.estimatedPaintVolumeByArea || 0)} <span className="text-[10px]">L</span></div>
<p className="text-[7px] text-gray-400 font-bold uppercase">Baseado em m²</p> <p className="text-[7px] text-gray-400 font-bold uppercase">Baseado em m²</p>
</div> </div>
<div className="border border-gray-300 rounded-xl p-4 space-y-1 border-black bg-gray-50"> <div className="border border-gray-300 rounded-xl p-3 sm:p-4 space-y-1 border-black bg-gray-50">
<span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Taxa Média</span> <span className="text-[8px] font-black text-gray-500 uppercase tracking-widest">Taxa Média</span>
<div className="text-xl font-black">{selectedStudy.totalWeight > 0 ? ((selectedStudy.estimatedPaintVolume || 0) / selectedStudy.totalWeight).toFixed(2) : '0.00'} <span className="text-[10px]">L/t</span></div> <div className="text-lg sm:text-xl font-black">{selectedStudy.totalWeight > 0 ? ((selectedStudy.estimatedPaintVolume || 0) / selectedStudy.totalWeight).toFixed(2) : '0.00'} <span className="text-[10px]">L/t</span></div>
<p className="text-[7px] text-gray-400 font-bold uppercase">Rendimento Global</p> <p className="text-[7px] text-gray-400 font-bold uppercase">Rendimento Global</p>
</div> </div>
</div> </div>
@@ -955,39 +955,41 @@ export const YieldStudyDashboard: React.FC = () => {
<h2 className="text-xs font-black uppercase tracking-[0.2em]">Detalhamento por Categoria</h2> <h2 className="text-xs font-black uppercase tracking-[0.2em]">Detalhamento por Categoria</h2>
<p className="text-[8px] text-gray-500 font-bold uppercase">Visão analítica por geometria, peso e área</p> <p className="text-[8px] text-gray-500 font-bold uppercase">Visão analítica por geometria, peso e área</p>
</div> </div>
<table className="w-full text-left border-collapse"> <div className="overflow-x-auto">
<thead> <table className="w-full text-left border-collapse min-w-[500px]">
<tr className="border-b-2 border-black"> <thead>
<th className="py-2 text-[9px] font-black uppercase tracking-widest">Categoria / Tipo</th> <tr className="border-b-2 border-black">
<th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-amber-600">Peso (T)</th> <th className="py-2 text-[9px] font-black uppercase tracking-widest">Categoria / Tipo</th>
<th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-blue-600">Área (m²)</th> <th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-amber-600">Peso (T)</th>
<th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-amber-600">Taxa (L/t)</th> <th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-blue-600">Área (m²)</th>
<th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-blue-600">Efic. (%)</th> <th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-amber-600">Taxa (L/t)</th>
<th className="py-2 text-[9px] font-black uppercase tracking-widest text-right">Consumo (L)</th> <th className="py-2 text-[9px] font-black uppercase tracking-widest text-center text-blue-600">Efic. (%)</th>
</tr> <th className="py-2 text-[9px] font-black uppercase tracking-widest text-right">Consumo (L)</th>
</thead>
<tbody className="divide-y divide-gray-100">
{selectedStudy.categories.map((cat, idx) => (
<tr key={cat.id || idx} className="border-b border-gray-100 italic">
<td className="py-3 pr-4">
<div className="text-[11px] font-black text-gray-800">{cat.name}</div>
</td>
<td className="py-3 text-center text-[10px] font-bold text-amber-700">{(cat.weight || 0).toFixed(2)}</td>
<td className="py-3 text-center text-[10px] font-bold text-blue-700">{cat.area ? Math.round(cat.area) : '--'}</td>
<td className="py-3 text-center text-[10px] font-bold text-amber-700">{cat.historicalYield}</td>
<td className="py-3 text-center text-[10px] font-bold text-blue-700">{cat.efficiency}%</td>
<td className="py-3 text-right">
<div className="text-[10px] font-black text-amber-700">{cat.litrosPeso} L <span className="text-[7px] uppercase font-bold text-gray-400 opacity-50">(p)</span></div>
{cat.litrosArea && <div className="text-[10px] font-black text-blue-700">{cat.litrosArea} L <span className="text-[7px] uppercase font-bold text-gray-400 opacity-50">(a)</span></div>}
</td>
</tr> </tr>
))} </thead>
</tbody> <tbody className="divide-y divide-gray-100">
</table> {selectedStudy.categories.map((cat, idx) => (
<tr key={cat.id || idx} className="border-b border-gray-100 italic">
<td className="py-3 pr-4">
<div className="text-[11px] font-black text-gray-800">{cat.name}</div>
</td>
<td className="py-3 text-center text-[10px] font-bold text-amber-700">{(cat.weight || 0).toFixed(2)}</td>
<td className="py-3 text-center text-[10px] font-bold text-blue-700">{cat.area ? Math.round(cat.area) : '--'}</td>
<td className="py-3 text-center text-[10px] font-bold text-amber-700">{cat.historicalYield}</td>
<td className="py-3 text-center text-[10px] font-bold text-blue-700">{cat.efficiency}%</td>
<td className="py-3 text-right">
<div className="text-[10px] font-black text-amber-700">{cat.litrosPeso} L <span className="text-[7px] uppercase font-bold text-gray-400 opacity-50">(p)</span></div>
{cat.litrosArea && <div className="text-[10px] font-black text-blue-700">{cat.litrosArea} L <span className="text-[7px] uppercase font-bold text-gray-400 opacity-50">(a)</span></div>}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div> </div>
{/* Parâmetros e Projeção */} {/* Parâmetros e Projeção */}
<div className="grid grid-cols-2 gap-8 mb-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-8 mb-6 sm:mb-8">
<div> <div>
<h3 className="text-[10px] font-black uppercase tracking-widest mb-4 border-b border-gray-200 pb-2">Especificações Técnicas</h3> <h3 className="text-[10px] font-black uppercase tracking-widest mb-4 border-b border-gray-200 pb-2">Especificações Técnicas</h3>
<div className="space-y-3"> <div className="space-y-3">