windows/components/Calculator.vue

267 lines
6.2 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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: 20px;
box-sizing: border-box;
min-height: 400px; /* Ensure minimum height for all buttons */
}
.display {
background: #1a1a1a;
border: 2px solid #333;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
min-height: 55px;
display: flex;
align-items: center;
justify-content: flex-end;
flex-shrink: 0; /* Prevent display from shrinking */
}
.display-value {
color: #00ff00;
font-family: 'Courier New', monospace;
font-size: 20px;
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;
min-height: 300px; /* Ensure enough space for all button rows */
}
.btn {
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: all 0.15s ease;
display: flex;
align-items: center;
justify-content: center;
min-height: 48px;
max-height: 65px;
}
.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>