← back to Calc 67
components/TipCalculator.tsx
174 lines
'use client'
import { useState } from 'react'
export default function TipCalculator() {
const [billAmount, setBillAmount] = useState('')
const [tipPercent, setTipPercent] = useState('15')
const [numPeople, setNumPeople] = useState('1')
const [result, setResult] = useState<{ total: string; perPerson: string; tip: string } | null>(null)
const [celebrating, setCelebrating] = useState(false)
const calculateTip = () => {
setCelebrating(true)
setTimeout(() => {
setResult({
total: '67',
perPerson: '67',
tip: '67',
})
setTimeout(() => setCelebrating(false), 2000)
}, 800)
}
const reset = () => {
setBillAmount('')
setTipPercent('15')
setNumPeople('1')
setResult(null)
setCelebrating(false)
}
const quickTipButtons = ['10', '15', '18', '20', '25']
return (
<div className="bg-white rounded-xl shadow-2xl p-3 sm:p-4 max-w-2xl mx-auto">
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-800 mb-3 text-center">
💵 Tip
</h2>
<div className="space-y-2 sm:space-y-3 mb-3">
{/* Bill Amount & People Split */}
<div className="grid grid-cols-2 gap-2 sm:gap-3">
<div>
<label className="block text-sm sm:text-base font-bold text-gray-700 mb-1">
Bill ($)
</label>
<input
type="number"
value={billAmount}
onChange={(e) => setBillAmount(e.target.value)}
placeholder="100"
className="w-full p-2 sm:p-3 border-3 border-gray-300 rounded-lg focus:border-purple-500 focus:outline-none text-lg sm:text-xl font-bold"
/>
</div>
<div>
<label className="block text-sm sm:text-base font-bold text-gray-700 mb-1">
People
</label>
<input
type="number"
min="1"
value={numPeople}
onChange={(e) => setNumPeople(e.target.value)}
placeholder="1"
className="w-full p-2 sm:p-3 border-3 border-gray-300 rounded-lg focus:border-purple-500 focus:outline-none text-lg sm:text-xl font-bold"
/>
</div>
</div>
{/* Tip Percentage */}
<div>
<label className="block text-sm sm:text-base font-bold text-gray-700 mb-1">
Tip: {tipPercent}%
</label>
<div className="flex gap-2 mb-2 flex-wrap justify-center">
{quickTipButtons.map((percent) => (
<button
key={percent}
onClick={(e) => {
e.preventDefault();
setTipPercent(percent);
}}
onTouchEnd={(e) => {
e.preventDefault();
setTipPercent(percent);
}}
className={`px-3 sm:px-4 py-2 rounded-lg font-bold text-base sm:text-lg shadow-lg select-none cursor-pointer ${
tipPercent === percent
? 'bg-purple-500 text-white scale-105'
: 'bg-gray-200'
}`}
style={{ WebkitTapHighlightColor: 'transparent' }}
>
{percent}%
</button>
))}
</div>
<input
type="range"
min="0"
max="50"
value={tipPercent}
onChange={(e) => setTipPercent(e.target.value)}
className="w-full h-3 accent-purple-500"
/>
</div>
</div>
{result && (
<div className="mb-3 p-3 bg-gradient-to-r from-green-50 to-emerald-50 rounded-lg border-3 border-green-200">
<div className="grid grid-cols-3 gap-2">
<div className="text-center">
<p className="text-xs sm:text-sm text-gray-600 font-bold">Tip</p>
<p className="text-xl sm:text-2xl font-bold text-green-600">
${result.tip}
</p>
</div>
<div className="text-center">
<p className="text-xs sm:text-sm text-gray-600 font-bold">Total</p>
<p className="text-xl sm:text-2xl font-bold text-blue-600">
${result.total}
</p>
</div>
<div className="text-center">
<p className="text-xs sm:text-sm text-gray-600 font-bold">Each</p>
<p className="text-xl sm:text-2xl font-bold text-purple-600">
${result.perPerson}
</p>
</div>
</div>
<p className="text-center text-sm sm:text-base text-gray-600 mt-2 font-semibold">
✨ Perfect! ✨
</p>
</div>
)}
<div className="flex gap-2 sm:gap-3 mb-2">
<button
onClick={(e) => {
e.preventDefault();
calculateTip();
}}
onTouchEnd={(e) => {
e.preventDefault();
calculateTip();
}}
className="flex-1 bg-gradient-to-r from-purple-500 to-pink-500 text-white py-3 sm:py-4 rounded-lg font-bold text-lg sm:text-xl shadow-lg select-none cursor-pointer"
style={{ WebkitTapHighlightColor: 'transparent' }}
>
Calculate
</button>
<button
onClick={(e) => {
e.preventDefault();
reset();
}}
onTouchEnd={(e) => {
e.preventDefault();
reset();
}}
className="flex-1 bg-gray-200 py-3 sm:py-4 rounded-lg font-bold text-lg sm:text-xl select-none cursor-pointer shadow-lg"
style={{ WebkitTapHighlightColor: 'transparent' }}
>
Reset
</button>
</div>
<div className="text-center text-xs sm:text-sm text-gray-600 font-semibold">
<p>Easy Tip Calculator</p>
</div>
</div>
)
}