Files
ihaleist/src/components/tools/VatCalculator.jsx
T

178 lines
7.8 KiB
React
Raw 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.
import React, { useState } from 'react';
import { Calculator, Copy, Check } from 'lucide-react';
export const VatCalculator = () => {
const [mode, setMode] = useState('haric'); // 'haric' (net to gross) or 'dahil' (gross to net)
const [amount, setAmount] = useState(100000);
const [vatRate, setVatRate] = useState(20); // 1, 10, 20
const [tevkifatRate, setTevkifatRate] = useState(0); // 0, 50 (5/10), 70 (7/10), 90 (9/10)
const [copied, setCopied] = useState(false);
// Calculations
let netAmount = 0;
let vatAmount = 0;
let grossAmount = 0;
let tevkifatAmount = 0;
let payableVat = 0;
if (mode === 'haric') {
netAmount = Number(amount) || 0;
vatAmount = netAmount * (vatRate / 100);
grossAmount = netAmount + vatAmount;
} else {
grossAmount = Number(amount) || 0;
netAmount = grossAmount / (1 + vatRate / 100);
vatAmount = grossAmount - netAmount;
}
if (tevkifatRate > 0) {
tevkifatAmount = vatAmount * (tevkifatRate / 100);
payableVat = vatAmount - tevkifatAmount;
} else {
payableVat = vatAmount;
}
const handleCopy = () => {
const summary = `Matrah: ₺${netAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} | KDV (%${vatRate}): ₺${vatAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} | Genel Toplam: ₺${grossAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}`;
navigator.clipboard.writeText(summary);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
<div className="max-w-3xl mx-auto my-4 space-y-4 animate-fade-in">
<div className="bg-white rounded-xl border border-slate-200 p-5 shadow-xs flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-blue-600 text-white flex items-center justify-center shadow-md">
<Calculator className="w-6 h-6" />
</div>
<div>
<h1 className="text-xl font-black text-slate-900">İhale KDV & Tevkifat Hesaplayıcı</h1>
<p className="text-xs text-slate-500">Teklif matrahından KDV dahil tutarı veya KDV dahilden net matrahı hesaplayın.</p>
</div>
</div>
</div>
<div className="bg-white rounded-2xl border border-slate-200 p-6 shadow-xs space-y-6">
{/* Mode Selector */}
<div className="grid grid-cols-2 gap-3 p-1 bg-slate-100 rounded-xl">
<button
onClick={() => setMode('haric')}
className={`py-2.5 rounded-lg text-xs font-extrabold transition-all ${
mode === 'haric' ? 'bg-white text-blue-700 shadow-2xs' : 'text-slate-600 hover:text-slate-900'
}`}
>
KDV Hariç ➔ KDV Dahil Hesapla
</button>
<button
onClick={() => setMode('dahil')}
className={`py-2.5 rounded-lg text-xs font-extrabold transition-all ${
mode === 'dahil' ? 'bg-white text-blue-700 shadow-2xs' : 'text-slate-600 hover:text-slate-900'
}`}
>
KDV Dahil ➔ Matrah Hesapla
</button>
</div>
{/* Inputs */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-xs">
<div>
<label className="block font-bold text-slate-700 mb-1.5">
{mode === 'haric' ? 'Teklif Tutarı (KDV Hariç Matrah)' : 'KDV Dahil Toplam Tutar'}
</label>
<div className="relative">
<input
type="number"
value={amount}
onChange={(e) => setAmount(e.target.value)}
className="w-full bg-slate-50 border border-slate-300 rounded-lg px-3 py-2.5 font-mono text-sm font-bold text-slate-900 focus:ring-2 focus:ring-blue-500"
/>
<span className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 font-bold">TL</span>
</div>
</div>
<div>
<label className="block font-bold text-slate-700 mb-1.5">KDV Oranı</label>
<div className="flex gap-1.5">
{[1, 10, 20].map(rate => (
<button
key={rate}
type="button"
onClick={() => setVatRate(rate)}
className={`flex-1 py-2 rounded-lg font-extrabold transition-colors border ${
vatRate === rate ? 'bg-blue-600 text-white border-blue-600' : 'bg-slate-50 text-slate-700 border-slate-300 hover:bg-slate-100'
}`}
>
%{rate}
</button>
))}
</div>
</div>
<div>
<label className="block font-bold text-slate-700 mb-1.5">Tevkifat Oranı (Varsa)</label>
<select
value={tevkifatRate}
onChange={(e) => setTevkifatRate(Number(e.target.value))}
className="w-full bg-slate-50 border border-slate-300 rounded-lg px-3 py-2.5 font-semibold text-slate-800"
>
<option value={0}>Tevkifat Yok</option>
<option value={50}>5/10 Tevkifat (%50)</option>
<option value={70}>7/10 Tevkifat (%70)</option>
<option value={90}>9/10 Tevkifat (%90)</option>
</select>
</div>
</div>
{/* Results Card */}
<div className="bg-slate-900 text-white p-6 rounded-xl space-y-4 shadow-lg">
<div className="flex items-center justify-between border-b border-slate-800 pb-3">
<span className="font-bold text-xs uppercase tracking-wider text-slate-300">Hesaplama Sonucu</span>
<button
onClick={handleCopy}
className="bg-slate-800 hover:bg-slate-700 text-blue-400 font-semibold px-3 py-1.5 rounded-lg text-xs flex items-center gap-1.5 transition-colors border border-slate-700"
>
{copied ? <Check className="w-3.5 h-3.5 text-emerald-400" /> : <Copy className="w-3.5 h-3.5" />}
<span>{copied ? 'Kopyalandı!' : 'Kopyala'}</span>
</button>
</div>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 text-xs">
<div className="bg-white/5 p-3 rounded-lg border border-white/10">
<span className="text-slate-400 font-medium block">Net Matrah (KDV Hariç)</span>
<span className="text-lg font-black text-white mt-1 block">
₺{netAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}
</span>
</div>
<div className="bg-white/5 p-3 rounded-lg border border-white/10">
<span className="text-slate-400 font-medium block">Hesaplanan KDV (%{vatRate})</span>
<span className="text-lg font-black text-amber-400 mt-1 block">
₺{vatAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}
</span>
</div>
<div className="bg-white/5 p-3 rounded-lg border border-white/10">
<span className="text-slate-400 font-medium block">Genel Toplam (KDV Dahil)</span>
<span className="text-xl font-black text-emerald-400 mt-1 block">
₺{grossAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}
</span>
</div>
</div>
{tevkifatRate > 0 && (
<div className="bg-blue-950/80 p-3.5 rounded-lg border border-blue-800 text-xs flex justify-between">
<span className="text-slate-300">Tevkifat Tutarı: <strong className="text-amber-300">₺{tevkifatAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}</strong></span>
<span className="text-slate-300">Ödenecek KDV: <strong className="text-emerald-400">₺{payableVat.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}</strong></span>
</div>
)}
</div>
</div>
</div>
);
};