Merge branch 'style/footer' into 'main'

Refactor layout and styling across components for improved responsiveness

See merge request fjmimbre/deck-of-cards!4
This commit is contained in:
alexis
2026-06-03 09:07:36 +00:00
5 changed files with 80 additions and 60 deletions
+4 -4
View File
@@ -1,11 +1,11 @@
export default function CriterionInput({ criterionName, setCriterionName, error }) {
return (
<div className="flex flex-row items-center justify-center gap-3 w-full z-30 relative mt-4">
<label className="text-sm font-bold text-slate-600 uppercase tracking-wide whitespace-nowrap">
<div className="flex flex-col sm:flex-row items-stretch sm:items-center justify-center gap-2 sm:gap-3 w-full max-w-full z-30 relative mt-4 px-1">
<label className="text-sm font-bold text-slate-600 uppercase tracking-wide text-center sm:text-left sm:whitespace-nowrap shrink-0">
Nombre del Criterio:
</label>
<div className="relative w-72">
<div className="relative w-full max-w-xs sm:max-w-none sm:w-72 mx-auto sm:mx-0">
<input
type="text"
placeholder="Ej: Calidad del código"
@@ -19,7 +19,7 @@ export default function CriterionInput({ criterionName, setCriterionName, error
/>
{error && (
<span className="absolute top-1/2 -right-18 -translate-y-1/2 text-red-500 text-xs font-semibold">
<span className="mt-1 block text-center sm:absolute sm:mt-0 sm:top-1/2 sm:-right-20 sm:-translate-y-1/2 text-red-500 text-xs font-semibold whitespace-nowrap">
Obligatorio
</span>
)}
@@ -14,14 +14,15 @@ export default function Step1BaseScale({
const [isZoomActive, setIsZoomActive] = useState(true);
const containerRef = useRef(null);
const tableRef = useRef(null);
const [dimensions, setDimensions] = useState({ container: 1000, table: 0 });
const [dimensions, setDimensions] = useState({ container: 1000, table: 0, tableHeight: 0 });
useEffect(() => {
const updateMeasurements = () => {
if (containerRef.current && tableRef.current) {
setDimensions({
container: containerRef.current.offsetWidth,
table: tableRef.current.scrollWidth
table: tableRef.current.scrollWidth,
tableHeight: tableRef.current.offsetHeight,
});
}
};
@@ -37,8 +38,13 @@ export default function Step1BaseScale({
const dynamicScale = needsZoom ? (dimensions.container / dimensions.table) * 0.95 : 1;
const currentScale = isZoomActive && needsZoom ? dynamicScale : 1;
const isScaledLayout = isZoomActive && needsZoom && currentScale < 1 && dimensions.tableHeight > 0;
const scaledViewportHeight = isScaledLayout
? dimensions.tableHeight * currentScale + 12
: undefined;
return (
<div className="w-full bg-white p-6 rounded-2xl shadow-sm border border-slate-200 flex flex-col items-center animate-fade-in relative overflow-visible">
<div className="w-full bg-white p-6 rounded-2xl shadow-sm border border-slate-200 flex flex-col items-center animate-fade-in relative overflow-x-clip">
<div className="flex justify-between items-center w-full mb-4 border-b pb-3 relative z-30">
<h2 className="text-xl font-bold text-slate-800">
@@ -60,10 +66,16 @@ export default function Step1BaseScale({
<CriterionInput criterionName={criterionName} setCriterionName={handleCriterionChange} error={errors.criterion} />
<div ref={containerRef} className={`w-full mt-2 transition-all relative ${!isZoomActive && needsZoom ? 'overflow-x-auto flex justify-start pt-4 px-4 custom-scrollbar' : 'overflow-visible flex justify-center pt-4'}`}>
<div className={`flex flex-row items-start min-w-max transition-transform duration-500 ease-out px-4 origin-top`} style={{ transform: `scale(${currentScale})`, marginBottom: isZoomActive && currentScale < 1 ? `-${(1 - currentScale) * 300}px` : '0px' }}>
<div ref={tableRef} className="flex flex-row items-start relative px-10 overflow-visible">
<div ref={containerRef} className={`w-full mt-2 transition-all relative ${!isZoomActive && needsZoom ? 'overflow-x-auto flex justify-start pt-4 px-4 pb-4 custom-scrollbar' : 'overflow-x-clip flex justify-center pt-4'}`}>
<div
className="flex w-full justify-center transition-[height] duration-500 ease-out"
style={isScaledLayout ? { height: scaledViewportHeight } : undefined}
>
<div
className="flex flex-row items-start min-w-max px-4 origin-top transition-transform duration-500 ease-out"
style={{ transform: `scale(${currentScale})` }}
>
<div ref={tableRef} className="flex flex-row items-start relative px-10 overflow-x-clip">
{levels.map((level, index) => (
<React.Fragment key={index}>
@@ -96,7 +108,7 @@ export default function Step1BaseScale({
</div>
</div>
</div>
</div>
</div>
+23 -20
View File
@@ -6,27 +6,27 @@ export default function Footer() {
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-12 gap-8 lg:gap-6">
{/* Proyecto */}
<div className="lg:col-span-4 flex flex-col">
<div className="flex items-center gap-3 mb-3">
<div className="lg:col-span-4 flex flex-col items-center text-center sm:items-start sm:text-left">
<div className="flex flex-wrap items-center justify-center gap-3 mb-3 sm:justify-start">
<span className="text-xl font-black text-slate-800 tracking-tight">Deck of Cards</span>
<span className="px-2 py-1 bg-blue-50 text-blue-700 text-[10px] font-black uppercase tracking-widest rounded-md">
Software Científico
</span>
</div>
<p className="text-sm text-slate-500 leading-relaxed max-w-sm">
Plataforma web para la elicitación de escalas de valor y construcción de conjuntos difusos interpretables (DoC-MF).
Elicitación de escalas de valor y construcción de conjuntos difusos interpretables (DoC-MF).
</p>
</div>
{/* Desarrollo */}
<div className="lg:col-span-3 flex flex-col">
<div className="lg:col-span-3 flex flex-col items-center text-center sm:items-start sm:text-left">
<h4 className="text-[10px] font-black uppercase tracking-[0.2em] text-slate-400 mb-3">Ingeniería y Desarrollo</h4>
<ul className="text-sm font-bold text-slate-700 space-y-2">
<li className="flex flex-wrap items-center gap-2">
<li className="flex flex-wrap items-center justify-center gap-2 sm:justify-start">
Alexis López Moral
<span className="text-slate-400 font-medium text-[10px] font-mono bg-slate-50 border border-slate-100 px-1.5 py-0.5 rounded">Frontend</span>
</li>
<li className="flex flex-wrap items-center gap-2">
<li className="flex flex-wrap items-center justify-center gap-2 sm:justify-start">
Mireya Cueto Garrido
<span className="text-slate-400 font-medium text-[10px] font-mono bg-slate-50 border border-slate-100 px-1.5 py-0.5 rounded">Backend</span>
</li>
@@ -34,29 +34,31 @@ export default function Footer() {
</div>
{/* Dirección Científica */}
<div className="lg:col-span-2 flex flex-col">
<div className="lg:col-span-2 flex flex-col items-center text-center sm:items-start sm:text-left">
<h4 className="text-[10px] font-black uppercase tracking-[0.2em] text-slate-400 mb-3">Dirección Científica</h4>
<p className="text-sm font-bold text-slate-700">Luis Martínez López</p>
</div>
{/* Enlaces Institucionales y Código */}
<div className="lg:col-span-3 flex flex-col gap-5 sm:items-start lg:items-end">
<div className="lg:col-span-3 flex flex-col items-center w-full sm:items-start lg:items-end">
<div className="grid grid-cols-2 gap-2.5 sm:gap-3 w-full max-w-sm sm:max-w-none lg:flex lg:flex-col lg:w-auto lg:gap-5">
{/* Universidad de Jaén */}
<a
href="https://www.ujaen.es/"
target="_blank" rel="noopener noreferrer"
className="group flex items-center gap-3 w-fit"
className="group flex items-center justify-center gap-2.5 rounded-lg border border-slate-200 bg-slate-50/50 px-3 py-2 transition-colors hover:bg-slate-100"
title="Ir a la web oficial de la Universidad de Jaén"
>
<div className="text-right border-r-2 border-slate-300 group-hover:border-blue-600 pr-3 flex flex-col justify-center h-9 transition-colors">
<span className="text-xs font-black text-slate-800 uppercase tracking-widest leading-none mb-1">Universidad</span>
<span className="text-[10px] font-bold text-slate-500 uppercase tracking-[0.3em] leading-none">de Jaén</span>
<div className="flex h-8 flex-col justify-center border-r-2 border-slate-300 pr-2.5 text-right transition-colors group-hover:border-blue-600">
<span className="mb-0.5 text-[11px] font-bold uppercase leading-none tracking-wide text-slate-800">Universidad</span>
<span className="text-[10px] font-medium uppercase leading-none tracking-[0.22em] text-slate-500">de Jaén</span>
</div>
<img
src="/uja-logo.png"
src={`${import.meta.env.BASE_URL}uja-logo.png`}
alt="Logo UJA"
className="w-9 h-9 object-contain grayscale group-hover:grayscale-0 transition-all opacity-80 group-hover:opacity-100"
className="h-7 w-7 object-contain grayscale opacity-80 transition-all group-hover:grayscale-0 group-hover:opacity-100"
/>
</a>
@@ -64,24 +66,25 @@ export default function Footer() {
<a
href="https://github.com/alexislopez-dev/deck-of-cards"
target="_blank" rel="noopener noreferrer"
className="group flex items-center gap-3 w-fit"
className="group flex items-center justify-center gap-2.5 rounded-lg border border-slate-200 bg-slate-50/50 px-3 py-2 transition-colors hover:bg-slate-100"
title="Ver código fuente en GitHub"
>
<div className="text-right border-r-2 border-slate-300 group-hover:border-slate-800 pr-3 flex flex-col justify-center h-9 transition-colors">
<span className="text-xs font-black text-slate-800 uppercase tracking-widest leading-none mb-1">Repositorio</span>
<span className="text-[10px] font-bold text-slate-500 uppercase tracking-[0.3em] leading-none">Oficial</span>
<div className="flex h-8 flex-col justify-center border-r-2 border-slate-300 pr-2.5 text-right transition-colors group-hover:border-slate-800">
<span className="mb-0.5 text-[11px] font-bold uppercase leading-none tracking-wide text-slate-800">Repositorio</span>
<span className="text-[10px] font-medium uppercase leading-none tracking-[0.22em] text-slate-500">Oficial</span>
</div>
<svg className="w-9 h-9 text-slate-400 group-hover:text-slate-800 transition-colors" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<svg className="h-7 w-7 text-slate-400 transition-colors group-hover:text-slate-800" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" />
</svg>
</a>
</div>
</div>
</div>
{/* Sub-Footer: Copyright y Referencia Científica */}
<div className="mt-6 pt-6 border-t border-slate-100 flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest whitespace-nowrap">
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest text-center">
© {new Date().getFullYear()} Deck of Cards App.
</p>
<p className="text-[10px] font-medium text-slate-400 text-center md:text-right">
@@ -3,7 +3,7 @@ import Footer from './Footer';
export default function MainLayout({ children }) {
return (
<div className="min-h-screen flex flex-col bg-slate-50 font-sans">
<div className="min-h-screen flex flex-col overflow-x-clip bg-slate-50 font-sans">
<Header />
+5
View File
@@ -3,6 +3,11 @@
/* Solo escanear código fuente; evita que Tailwind/Vite procesen Dockerfile u otros archivos en /app */
@source "./src/**/*.{js,jsx}";
html {
overflow-x: clip;
}
body {
overflow-x: clip;
overflow-y: scroll;
}