263 lines
6.0 KiB
Vue
263 lines
6.0 KiB
Vue
<script setup lang="ts">
|
||
import { ref, computed } from 'vue';
|
||
|
||
// Calculator state
|
||
const display = ref('0');
|
||
const previousValue = ref<number | null>(null);
|
||
const operation = ref<string | null>(null);
|
||
const waitingForNewValue = ref(false);
|
||
|
||
// Calculator logic
|
||
function inputNumber(num: string) {
|
||
if (waitingForNewValue.value) {
|
||
display.value = num;
|
||
waitingForNewValue.value = false;
|
||
} else {
|
||
display.value = display.value === '0' ? num : display.value + num;
|
||
}
|
||
}
|
||
|
||
function inputDecimal() {
|
||
if (waitingForNewValue.value) {
|
||
display.value = '0.';
|
||
waitingForNewValue.value = false;
|
||
} else if (display.value.indexOf('.') === -1) {
|
||
display.value += '.';
|
||
}
|
||
}
|
||
|
||
function clear() {
|
||
display.value = '0';
|
||
previousValue.value = null;
|
||
operation.value = null;
|
||
waitingForNewValue.value = false;
|
||
}
|
||
|
||
function performOperation(nextOperation: string) {
|
||
const inputValue = parseFloat(display.value);
|
||
|
||
if (previousValue.value === null) {
|
||
previousValue.value = inputValue;
|
||
} else if (operation.value) {
|
||
const currentValue = previousValue.value || 0;
|
||
const newValue = calculate(currentValue, inputValue, operation.value);
|
||
|
||
display.value = String(newValue);
|
||
previousValue.value = newValue;
|
||
}
|
||
|
||
waitingForNewValue.value = true;
|
||
operation.value = nextOperation;
|
||
}
|
||
|
||
function calculate(firstValue: number, secondValue: number, operation: string): number {
|
||
switch (operation) {
|
||
case '+': return firstValue + secondValue;
|
||
case '-': return firstValue - secondValue;
|
||
case '×': return firstValue * secondValue;
|
||
case '÷': return secondValue !== 0 ? firstValue / secondValue : 0;
|
||
default: return secondValue;
|
||
}
|
||
}
|
||
|
||
function equals() {
|
||
const inputValue = parseFloat(display.value);
|
||
|
||
if (previousValue.value !== null && operation.value) {
|
||
const newValue = calculate(previousValue.value, inputValue, operation.value);
|
||
display.value = String(newValue);
|
||
previousValue.value = null;
|
||
operation.value = null;
|
||
waitingForNewValue.value = true;
|
||
}
|
||
}
|
||
|
||
// Format display value
|
||
const formattedDisplay = computed(() => {
|
||
const value = parseFloat(display.value);
|
||
if (isNaN(value)) return '0';
|
||
|
||
// Handle very large or very small numbers
|
||
if (Math.abs(value) > 999999999 || (Math.abs(value) < 0.000001 && value !== 0)) {
|
||
return value.toExponential(6);
|
||
}
|
||
|
||
// Format with appropriate decimal places
|
||
return value.toLocaleString('en-US', {
|
||
maximumFractionDigits: 8,
|
||
minimumFractionDigits: 0
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="calculator">
|
||
<div class="display">
|
||
<div class="display-value">{{ formattedDisplay }}</div>
|
||
</div>
|
||
|
||
<div class="buttons">
|
||
<!-- Row 1 -->
|
||
<button @click="clear" class="btn btn-function">C</button>
|
||
<button @click="clear" class="btn btn-function">CE</button>
|
||
<button @click="performOperation('÷')" class="btn btn-operator">÷</button>
|
||
<button @click="performOperation('×')" class="btn btn-operator">×</button>
|
||
|
||
<!-- Row 2 -->
|
||
<button @click="inputNumber('7')" class="btn btn-number">7</button>
|
||
<button @click="inputNumber('8')" class="btn btn-number">8</button>
|
||
<button @click="inputNumber('9')" class="btn btn-number">9</button>
|
||
<button @click="performOperation('-')" class="btn btn-operator">−</button>
|
||
|
||
<!-- Row 3 -->
|
||
<button @click="inputNumber('4')" class="btn btn-number">4</button>
|
||
<button @click="inputNumber('5')" class="btn btn-number">5</button>
|
||
<button @click="inputNumber('6')" class="btn btn-number">6</button>
|
||
<button @click="performOperation('+')" class="btn btn-operator">+</button>
|
||
|
||
<!-- Row 4 -->
|
||
<button @click="inputNumber('1')" class="btn btn-number">1</button>
|
||
<button @click="inputNumber('2')" class="btn btn-number">2</button>
|
||
<button @click="inputNumber('3')" class="btn btn-number">3</button>
|
||
<button @click="equals" class="btn btn-equals" rowspan="2">=</button>
|
||
|
||
<!-- Row 5 -->
|
||
<button @click="inputNumber('0')" class="btn btn-number btn-zero">0</button>
|
||
<button @click="inputDecimal" class="btn btn-number">.</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.calculator {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: var(--window-background);
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 16px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.display {
|
||
background: #1a1a1a;
|
||
border: 2px solid #333;
|
||
border-radius: 8px;
|
||
padding: 16px;
|
||
margin-bottom: 16px;
|
||
min-height: 60px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.display-value {
|
||
color: #00ff00;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
text-align: right;
|
||
word-break: break-all;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.buttons {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 8px;
|
||
flex: 1;
|
||
}
|
||
|
||
.btn {
|
||
border: none;
|
||
border-radius: 8px;
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 50px;
|
||
}
|
||
|
||
.btn:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.btn:active {
|
||
transform: translateY(0);
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.btn-number {
|
||
background: #4a4a4a;
|
||
color: white;
|
||
}
|
||
|
||
.btn-number:hover {
|
||
background: #5a5a5a;
|
||
}
|
||
|
||
.btn-operator {
|
||
background: #ff9500;
|
||
color: white;
|
||
}
|
||
|
||
.btn-operator:hover {
|
||
background: #ffad33;
|
||
}
|
||
|
||
.btn-function {
|
||
background: #a6a6a6;
|
||
color: black;
|
||
}
|
||
|
||
.btn-function:hover {
|
||
background: #b6b6b6;
|
||
}
|
||
|
||
.btn-equals {
|
||
background: #ff9500;
|
||
color: white;
|
||
grid-row: span 2;
|
||
}
|
||
|
||
.btn-equals:hover {
|
||
background: #ffad33;
|
||
}
|
||
|
||
.btn-zero {
|
||
grid-column: span 2;
|
||
}
|
||
|
||
/* Dark theme adjustments */
|
||
.theme-light .display {
|
||
background: #f0f0f0;
|
||
border-color: #ccc;
|
||
}
|
||
|
||
.theme-light .display-value {
|
||
color: #333;
|
||
}
|
||
|
||
.theme-light .btn-number {
|
||
background: #e0e0e0;
|
||
color: #333;
|
||
}
|
||
|
||
.theme-light .btn-number:hover {
|
||
background: #d0d0d0;
|
||
}
|
||
|
||
.theme-light .btn-function {
|
||
background: #c0c0c0;
|
||
color: #333;
|
||
}
|
||
|
||
.theme-light .btn-function:hover {
|
||
background: #b0b0b0;
|
||
}
|
||
</style>
|