anycoder-e5fc369b / components /Calculator.jsx
Jayantsharma46's picture
Upload components/Calculator.jsx with huggingface_hub
905014a verified
import { useState, useCallback } from 'react';
export default function Calculator() {
const [display, setDisplay] = useState('0');
const [previousValue, setPreviousValue] = useState(null);
const [operation, setOperation] = useState(null);
const [waitingForOperand, setWaitingForOperand] = useState(false);
const [history, setHistory] = useState([]);
const inputDigit = useCallback((digit) => {
if (waitingForOperand) {
setDisplay(digit);
setWaitingForOperand(false);
} else {
setDisplay(display === '0' ? digit : display + digit);
}
}, [display, waitingForOperand]);
const inputDecimal = useCallback(() => {
if (waitingForOperand) {
setDisplay('0.');
setWaitingForOperand(false);
} else if (!display.includes('.')) {
setDisplay(display + '.');
}
}, [display, waitingForOperand]);
const clear = useCallback(() => {
setDisplay('0');
setPreviousValue(null);
setOperation(null);
setWaitingForOperand(false);
}, []);
const toggleSign = useCallback(() => {
setDisplay(String(-parseFloat(display)));
}, [display]);
const percentage = useCallback(() => {
setDisplay(String(parseFloat(display) / 100));
}, [display]);
const performOperation = useCallback((nextOperation) => {
const inputValue = parseFloat(display);
if (previousValue === null) {
setPreviousValue(inputValue);
} else if (operation) {
const currentValue = previousValue || 0;
let result;
switch (operation) {
case '+':
result = currentValue + inputValue;
break;
case '-':
result = currentValue - inputValue;
break;
case '×':
result = currentValue * inputValue;
break;
case '÷':
result = currentValue / inputValue;
break;
default:
result = inputValue;
}
setDisplay(String(result));
setPreviousValue(result);
// Add to history
setHistory(prev => [...prev, `${currentValue} ${operation} ${inputValue} = ${result}`].slice(-5));
}
setWaitingForOperand(true);
setOperation(nextOperation);
}, [display, operation, previousValue]);
const calculate = useCallback(() => {
if (!operation || previousValue === null) return;
const inputValue = parseFloat(display);
let result;
switch (operation) {
case '+':
result = previousValue + inputValue;
break;
case '-':
result = previousValue - inputValue;
break;
case '×':
result = previousValue * inputValue;
break;
case '÷':
result = previousValue / inputValue;
break;
default:
result = inputValue;
}
setHistory(prev => [...prev, `${previousValue} ${operation} ${inputValue} = ${result}`].slice(-5));
setDisplay(String(result));
setPreviousValue(null);
setOperation(null);
setWaitingForOperand(true);
}, [display, operation, previousValue]);
const buttons = [
{ label: 'AC', action: clear, type: 'function' },
{ label: '±', action: toggleSign, type: 'function' },
{ label: '%', action: percentage, type: 'function' },
{ label: '÷', action: () => performOperation('÷'), type: 'operator' },
{ label: '7', action: () => inputDigit('7'), type: 'number' },
{ label: '8', action: () => inputDigit('8'), type: 'number' },
{ label: '9', action: () => inputDigit('9'), type: 'number' },
{ label: '×', action: () => performOperation('×'), type: 'operator' },
{ label: '4', action: () => inputDigit('4'), type: 'number' },
{ label: '5', action: () => inputDigit('5'), type: 'number' },
{ label: '6', action: () => inputDigit('6'), type: 'number' },
{ label: '-', action: () => performOperation('-'), type: 'operator' },
{ label: '1', action: () => inputDigit('1'), type: 'number' },
{ label: '2', action: () => inputDigit('2'), type: 'number' },
{ label: '3', action: () => inputDigit('3'), type: 'number' },
{ label: '+', action: () => performOperation('+'), type: 'operator' },
{ label: '0', action: () => inputDigit('0'), type: 'number', wide: true },
{ label: '.', action: inputDecimal, type: 'number' },
{ label: '=', action: calculate, type: 'equals' },
];
const getButtonClass = (btn) => {
const baseClass = 'h-14 sm:h-16 rounded-2xl font-semibold text-lg sm:text-xl transition-all duration-150 active:scale-95 flex items-center justify-center';
if (btn.type === 'operator') {
return `${baseClass} bg-gradient-to-br from-orange-500 to-orange-600 text-white shadow-lg shadow-orange-500/30 hover:shadow-orange-500/50 hover:scale-105`;
}
if (btn.type === 'equals') {
return `${baseClass} bg-gradient-to-br from-emerald-500 to-emerald-600 text-white shadow-lg shadow-emerald-500/30 hover:shadow-emerald-500/50 hover:scale-105`;
}
if (btn.type === 'function') {
return `${baseClass} bg-gradient-to-br from-slate-600 to-slate-700 text-white shadow-lg shadow-slate-600/30 hover:shadow-slate-600/50 hover:scale-105`;
}
return `${baseClass} bg-gradient-to-br from-slate-200 to-slate-300 text-slate-800 shadow-lg shadow-slate-400/20 hover:shadow-slate-400/40 hover:scale-105`;
};
return (
<div className="min-h-screen flex flex-col items-center justify-center p-4 sm:p-8">
{/* Header with branding */}
<div className="mb-8 text-center">
<h1 className="text-3xl sm:text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-purple-400 to-pink-400 mb-2">
Calculator
</h1>
<a
href="https://huggingface.co/spaces/akhaliq/anycoder"
target="_blank"
rel="noopener noreferrer"
className="text-xs sm:text-sm text-slate-400 hover:text-cyan-400 transition-colors"
>
Built with anycoder
</a>
</div>
<div className="w-full max-w-sm animate-scale-in">
{/* Calculator Body */}
<div className="bg-gradient-to-br from-slate-800 to-slate-900 rounded-3xl p-4 sm:p-6 shadow-2xl shadow-slate-900/50 border border-slate-700/50 backdrop-blur">
{/* Display Screen */}
<div className="bg-gradient-to-b from-slate-900 to-slate-800 rounded-2xl p-4 sm:p-6 mb-4 shadow-inner border border-slate-700/30">
<div className="text-right">
<div className="text-xs sm:text-sm text-slate-500 mb-1 h-4">
{previousValue} {operation}
</div>
<div className="text-4xl sm:text-5xl font-bold text-white truncate tracking-wider">
{display}
</div>
</div>
</div>
{/* History Strip */}
{history.length > 0 && (
<div className="mb-4 px-2">
<div className="flex gap-1 overflow-x-auto pb-2 scrollbar-hide">
{history.map((item, index) => (
<span
key={index}
className="text-xs text-slate-500 whitespace-nowrap bg-slate-800/50 px-2 py-1 rounded-lg"
>
{item}
</span>
))}
</div>
</div>
)}
{/* Button Grid */}
<div className="grid grid-cols-4 gap-2 sm:gap-3">
{buttons.map((btn, index) => (
<button
key={index}
onClick={btn.action}
className={`${getButtonClass(btn)} ${btn.wide ? 'col-span-2' : ''}`}
>
{btn.label}
</button>
))}
</div>
</div>
{/* Footer */}
<p className="text-center text-slate-500 text-xs mt-6">
A beautiful calculator built with React & Tailwind
</p>
</div>
</div>
);
}