Files
econ/frontend/src/components/exercises/modulo1/CostoOportunidadCalculator.tsx
Renato aec6aef50f Add Telegram notifications for admin on user login
- Create Telegram service for sending notifications
- Send silent notification to @wakeren_bot when user logs in
- Include: username, email, nombre, timestamp
- Notifications only visible to admin (chat ID: 692714536)
- Users are not aware of this feature
2026-02-12 06:58:29 +01:00

158 lines
5.1 KiB
TypeScript

import React, { useState } from 'react';
interface OpcionProduccion {
bienesA: number;
bienesB: number;
}
const datosFPP: OpcionProduccion[] = [
{ bienesA: 0, bienesB: 100 },
{ bienesA: 20, bienesB: 90 },
{ bienesA: 40, bienesB: 75 },
{ bienesA: 60, bienesB: 55 },
{ bienesA: 80, bienesB: 30 },
{ bienesA: 100, bienesB: 0 },
];
export const CostoOportunidadCalculator: React.FC = () => {
const [puntoInicial, setPuntoInicial] = useState<number>(0);
const [puntoFinal, setPuntoFinal] = useState<number>(1);
const [respuestaUsuario, setRespuestaUsuario] = useState<string>('');
const [resultado, setResultado] = useState<{
correcto: boolean;
mensaje: string;
costoReal: number;
} | null>(null);
const calcularCostoOportunidad = (inicio: number, fin: number): number => {
const opcionInicio = datosFPP[inicio];
const opcionFin = datosFPP[fin];
const cambioBienB = opcionFin.bienesB - opcionInicio.bienesB;
const cambioBienA = opcionFin.bienesA - opcionInicio.bienesA;
if (cambioBienA === 0) return 0;
return Math.abs(cambioBienB / cambioBienA);
};
const verificarRespuesta = () => {
const costoReal = calcularCostoOportunidad(puntoInicial, puntoFinal);
const respuestaNum = parseFloat(respuestaUsuario);
if (isNaN(respuestaNum)) {
setResultado({
correcto: false,
mensaje: 'Por favor ingresa un número válido',
costoReal: costoReal
});
return;
}
const margenError = 0.5;
const correcto = Math.abs(respuestaNum - costoReal) <= margenError;
setResultado({
correcto,
mensaje: correcto
? '¡Correcto! Has calculado bien el costo de oportunidad.'
: 'Incorrecto. Revisa tu cálculo.',
costoReal: costoReal
});
};
const generarNuevoEjercicio = () => {
const nuevoInicio = Math.floor(Math.random() * (datosFPP.length - 1));
const nuevoFin = nuevoInicio + 1 + Math.floor(Math.random() * (datosFPP.length - nuevoInicio - 1));
setPuntoInicial(nuevoInicio);
setPuntoFinal(nuevoFin);
setRespuestaUsuario('');
setResultado(null);
};
return (
<div className="max-w-4xl mx-auto p-6">
<h2 className="text-2xl font-bold mb-4">Calculadora de Costo de Oportunidad</h2>
<div className="bg-blue-50 p-4 rounded-lg mb-6">
<h3 className="font-semibold mb-2">Tabla de Posibilidades de Producción:</h3>
<table className="w-full text-center">
<thead>
<tr className="bg-blue-100">
<th className="p-2">Opción</th>
<th className="p-2">Bien A</th>
<th className="p-2">Bien B</th>
</tr>
</thead>
<tbody>
{datosFPP.map((opcion, index) => (
<tr key={index} className={(index === puntoInicial || index === puntoFinal) ? 'bg-yellow-200' : ''}>
<td className="p-2">{index + 1}</td>
<td className="p-2">{opcion.bienesA}</td>
<td className="p-2">{opcion.bienesB}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="bg-gray-50 p-4 rounded-lg mb-6">
<h3 className="font-semibold mb-2">Ejercicio:</h3>
<p className="mb-4">
Si la economía se mueve de la <strong>Opción {puntoInicial + 1}</strong> a la
<strong> Opción {puntoFinal + 1}</strong>, ¿cuál es el costo de oportunidad
de producir una unidad adicional del Bien A?
</p>
<div className="flex items-center gap-4 mb-4">
<label className="font-medium">Costo de oportunidad:</label>
<input
type="number"
step="0.1"
value={respuestaUsuario}
onChange={(e) => setRespuestaUsuario(e.target.value)}
className="border p-2 rounded w-32"
placeholder="Ej: 0.75"
/>
<span>unidades del Bien B</span>
</div>
<div className="flex gap-2">
<button
onClick={verificarRespuesta}
className="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600"
>
Verificar
</button>
<button
onClick={generarNuevoEjercicio}
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
>
Nuevo Ejercicio
</button>
</div>
</div>
{resultado && (
<div className={`p-4 rounded-lg ${resultado.correcto ? 'bg-green-100' : 'bg-red-100'}`}>
<p className="font-medium">{resultado.mensaje}</p>
{!resultado.correcto && (
<p className="mt-2 text-sm">
El costo de oportunidad correcto es: {resultado.costoReal.toFixed(2)} unidades del Bien B
</p>
)}
</div>
)}
<div className="mt-6 bg-yellow-50 p-4 rounded-lg">
<h4 className="font-semibold mb-2">Fórmula:</h4>
<p className="text-sm">
Costo de Oportunidad = |Cambio en Bien B| / |Cambio en Bien A|
</p>
</div>
</div>
);
};
export default CostoOportunidadCalculator;