Files
econ/frontend/src/components/exercises/modulo1/CostoOportunidadCotidiano.tsx
2026-03-31 01:28:28 -03:00

247 lines
9.4 KiB
TypeScript

import { useState } from 'react';
interface CostoOportunidadCotidianoProps {
ejercicioId: string;
onComplete?: (puntuacion: number) => void;
}
interface Situacion {
id: number;
titulo: string;
descripcion: string;
decision: string;
opciones: string[];
costoOportunidadCorrecto: string;
explicacion: string;
}
const situaciones: Situacion[] = [
{
id: 1,
titulo: "Tiempo libre",
descripcion: "Tienes 3 horas libres un sábado por la tarde.",
decision: "Decides estudiar para un examen importante.",
opciones: [
"El tiempo que podrías haber pasado con amigos",
"Las calificaciones del examen",
"El dinero ahorrado",
"La comida que no comiste"
],
costoOportunidadCorrecto: "El tiempo que podrías haber pasado con amigos",
explicacion: "El costo de oportunidad es lo que sacrificas: el tiempo con amigos que elegiste no hacer."
},
{
id: 2,
titulo: "Compra de tecnología",
descripcion: "Tienes $1,000 ahorrados.",
decision: "Compras una laptop nueva para trabajar.",
opciones: [
"El dinero que gastaste",
"El dinero que podrías haber invertido",
"La laptop misma",
"Las especificaciones técnicas"
],
costoOportunidadCorrecto: "El dinero que podrías haber invertido",
explicacion: "Al gastar en la laptop, sacrificas la oportunidad de invertir ese dinero y obtener rendimientos."
},
{
id: 3,
titulo: "Carrera profesional",
descripcion: "Terminas la universidad con dos ofertas de trabajo.",
decision: "Aceptas el trabajo en una startup con menor salario inicial.",
opciones: [
"El salario más alto de la otra oferta",
"La experiencia en la startup",
"Tu título universitario",
"El tiempo de búsqueda"
],
costoOportunidadCorrecto: "El salario más alto de la otra oferta",
explicacion: "Al elegir la startup, renuncias al salario más alto que ofrecía la otra empresa."
},
{
id: 4,
titulo: "Vacaciones",
descripcion: "Tienes dos semanas de vacaciones este verano.",
decision: "Viajas a Europa en lugar de quedarte trabajando.",
opciones: [
"Las fotos que tomarás",
"El dinero que gastarás en el viaje",
"El dinero que podrías haber ganado trabajando",
"La experiencia cultural"
],
costoOportunidadCorrecto: "El dinero que podrías haber ganado trabajando",
explicacion: "El costo de oportunidad incluye los ingresos que sacrificas al no trabajar esas semanas."
}
];
export function CostoOportunidadCotidiano({ ejercicioId: _ejercicioId, onComplete }: CostoOportunidadCotidianoProps) {
const [respuestas, setRespuestas] = useState<{[key: number]: string}>({});
const [mostrarExplicacion, setMostrarExplicacion] = useState<{[key: number]: boolean}>({});
const [completado, setCompletado] = useState(false);
const handleSeleccion = (situacionId: number, opcion: string) => {
setRespuestas(prev => ({ ...prev, [situacionId]: opcion }));
};
const handleValidar = () => {
const nuevasExplicaciones: {[key: number]: boolean} = {};
let correctas = 0;
situaciones.forEach(situacion => {
nuevasExplicaciones[situacion.id] = true;
if (respuestas[situacion.id] === situacion.costoOportunidadCorrecto) {
correctas++;
}
});
setMostrarExplicacion(nuevasExplicaciones);
if (correctas === situaciones.length && !completado) {
setCompletado(true);
if (onComplete) {
onComplete(100);
}
}
};
const handleReset = () => {
setRespuestas({});
setMostrarExplicacion({});
setCompletado(false);
};
const correctas = situaciones.filter(s => respuestas[s.id] === s.costoOportunidadCorrecto).length;
return (
<div className="w-full max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-6">
<div className="mb-6">
<h3 className="text-xl font-semibold text-gray-900">Costo de Oportunidad en Decisiones Cotidianas</h3>
<p className="text-sm text-gray-500 mt-1">
Identifica el costo de oportunidad en cada situación de la vida real.
</p>
</div>
<div className="bg-amber-50 border border-amber-200 rounded-lg p-4 mb-6">
<p className="text-amber-800 text-sm">
<strong>Recuerda:</strong> El costo de oportunidad es el valor de la mejor alternativa a la que renuncias
al tomar una decisión. No es lo que gastas, sino lo que sacrificas.
</p>
</div>
<div className="space-y-6">
{situaciones.map((situacion, index) => (
<div
key={situacion.id}
className="border border-gray-200 rounded-lg p-5 hover:shadow-md transition-shadow"
>
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center text-blue-600 font-bold">
{index + 1}
</div>
<div className="flex-grow">
<h4 className="font-semibold text-gray-900 text-lg">{situacion.titulo}</h4>
<p className="text-gray-600 mt-1">{situacion.descripcion}</p>
<p className="text-blue-700 font-medium mt-2">Decisión: {situacion.decision}</p>
<div className="mt-4">
<p className="text-sm font-medium text-gray-700 mb-3">
¿Cuál es el costo de oportunidad?
</p>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{situacion.opciones.map((opcion) => {
const isSelected = respuestas[situacion.id] === opcion;
const isCorrect = opcion === situacion.costoOportunidadCorrecto;
const showResult = mostrarExplicacion[situacion.id];
let buttonClass = 'border border-gray-300 bg-white text-gray-700 hover:bg-gray-50';
if (showResult) {
if (isCorrect) {
buttonClass = 'border-green-500 bg-green-50 text-green-800';
} else if (isSelected && !isCorrect) {
buttonClass = 'border-red-500 bg-red-50 text-red-800';
} else {
buttonClass = 'border-gray-200 bg-gray-50 text-gray-400';
}
} else if (isSelected) {
buttonClass = 'border-blue-500 bg-blue-50 text-blue-800';
}
return (
<button
key={opcion}
onClick={() => !showResult && handleSeleccion(situacion.id, opcion)}
disabled={showResult}
className={`p-3 rounded-lg text-left text-sm transition-all ${buttonClass}`}
>
{opcion}
{showResult && isCorrect && (
<span className="ml-2 text-green-600 font-bold"></span>
)}
</button>
);
})}
</div>
</div>
{mostrarExplicacion[situacion.id] && (
<div className={`mt-4 p-4 rounded-lg ${
respuestas[situacion.id] === situacion.costoOportunidadCorrecto
? 'bg-green-50 border border-green-200'
: 'bg-amber-50 border border-amber-200'
}`}>
<p className={`text-sm font-medium ${
respuestas[situacion.id] === situacion.costoOportunidadCorrecto
? 'text-green-800'
: 'text-amber-800'
}`}>
{respuestas[situacion.id] === situacion.costoOportunidadCorrecto
? '¡Correcto!'
: 'Respuesta correcta:'}
</p>
<p className={`text-sm mt-1 ${
respuestas[situacion.id] === situacion.costoOportunidadCorrecto
? 'text-green-700'
: 'text-amber-700'
}`}>
{situacion.explicacion}
</p>
</div>
)}
</div>
</div>
</div>
))}
</div>
<div className="mt-6 flex gap-3">
<button
onClick={handleValidar}
disabled={completado || Object.keys(respuestas).length < situaciones.length}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-400 transition-colors"
>
Validar Respuestas
</button>
<button
onClick={handleReset}
className="px-6 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
>
Reiniciar
</button>
</div>
{completado && (
<div className="mt-6 bg-green-100 border border-green-300 rounded-lg p-4 text-center">
<p className="text-green-800 font-semibold">¡Excelente comprensión!</p>
<p className="text-green-700 text-2xl font-bold mt-1">100 puntos</p>
<p className="text-green-700 text-sm mt-2">
Has identificado correctamente todos los costos de oportunidad.
</p>
</div>
)}
</div>
);
}
export default CostoOportunidadCotidiano;