161 lines
6.9 KiB
TypeScript
161 lines
6.9 KiB
TypeScript
"use client";
|
||
|
||
import { useState, useEffect } from "react";
|
||
import { Container } from "@/components/container";
|
||
import { Heading } from "@/components/heading";
|
||
import { Subheading } from "@/components/subheading";
|
||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||
import { Input } from "@/components/ui/input";
|
||
import { Label } from "@/components/ui/label";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Badge } from "@/components/badge";
|
||
import { Share2, Save, Calculator, Info, CheckCircle2 } from "lucide-react";
|
||
|
||
export function RoiCalculator() {
|
||
const [investment, setInvestment] = useState<number>(10000);
|
||
const [revenue, setRevenue] = useState<number>(15000);
|
||
const [roi, setRoi] = useState<number>(0);
|
||
const [profit, setProfit] = useState<number>(0);
|
||
const [saved, setSaved] = useState(false);
|
||
|
||
useEffect(() => {
|
||
const p = revenue - investment;
|
||
const r = investment > 0 ? (p / investment) * 100 : 0;
|
||
setProfit(p);
|
||
setRoi(r);
|
||
}, [investment, revenue]);
|
||
|
||
const handleSave = () => {
|
||
setSaved(true);
|
||
setTimeout(() => setSaved(false), 2000);
|
||
};
|
||
|
||
const handleShare = () => {
|
||
if (navigator.share) {
|
||
navigator.share({
|
||
title: 'ROI Calculation Result',
|
||
text: `My ROI is ${roi.toFixed(2)}% with a profit of $${profit.toLocaleString()}`,
|
||
url: window.location.href,
|
||
});
|
||
} else {
|
||
alert("Sharing not supported on this browser. Link copied to clipboard!");
|
||
navigator.clipboard.writeText(window.location.href);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<section className="py-12 md:py-20 bg-neutral-50/50">
|
||
<Container>
|
||
<div className="max-w-4xl mx-auto">
|
||
<div className="text-center mb-12">
|
||
<Badge className="mb-4">ROI Calculator</Badge>
|
||
<Heading>Calculate Your Return on Investment</Heading>
|
||
<Subheading className="mt-4">
|
||
Enter your investment and expected revenue to see your potential profit and ROI percentage instantly.
|
||
</Subheading>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||
{/* Inputs */}
|
||
<Card className="border-neutral-200 shadow-sm">
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2">
|
||
<Calculator className="w-5 h-5 text-blue-600" />
|
||
Input Details
|
||
</CardTitle>
|
||
<CardDescription>Enter your financial figures below</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="investment">Total Investment ($)</Label>
|
||
<Input
|
||
id="investment"
|
||
type="number"
|
||
value={investment}
|
||
onChange={(e) => setInvestment(Number(e.target.value))}
|
||
placeholder="e.g. 10000"
|
||
/>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="revenue">Total Revenue ($)</Label>
|
||
<Input
|
||
id="revenue"
|
||
type="number"
|
||
value={revenue}
|
||
onChange={(e) => setRevenue(Number(e.target.value))}
|
||
placeholder="e.g. 15000"
|
||
/>
|
||
</div>
|
||
<div className="flex gap-3 pt-4">
|
||
<Button onClick={handleSave} variant="outline" className="flex-1 gap-2">
|
||
{saved ? <CheckCircle2 className="w-4 h-4 text-green-500" /> : <Save className="w-4 h-4" />}
|
||
{saved ? "Saved" : "Save Result"}
|
||
</Button>
|
||
<Button onClick={handleShare} variant="outline" className="flex-1 gap-2">
|
||
<Share2 className="w-4 h-4" />
|
||
Share
|
||
</Button>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Results */}
|
||
<Card className="border-blue-100 bg-blue-50/30 shadow-sm">
|
||
<CardHeader>
|
||
<CardTitle className="text-blue-900">Calculation Results</CardTitle>
|
||
<CardDescription>Your financial performance summary</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-8">
|
||
<div className="text-center p-6 bg-white rounded-xl border border-blue-100 shadow-sm">
|
||
<p className="text-sm font-medium text-blue-600 uppercase tracking-wider">ROI Percentage</p>
|
||
<p className={`text-5xl font-bold mt-2 ${roi >= 0 ? 'text-green-600' : 'text-red-600'}`}>
|
||
{roi.toFixed(2)}%
|
||
</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="p-4 bg-white rounded-lg border border-neutral-100">
|
||
<p className="text-xs text-neutral-500 uppercase">Net Profit</p>
|
||
<p className={`text-xl font-bold ${profit >= 0 ? 'text-neutral-900' : 'text-red-600'}`}>
|
||
${profit.toLocaleString()}
|
||
</p>
|
||
</div>
|
||
<div className="p-4 bg-white rounded-lg border border-neutral-100">
|
||
<p className="text-xs text-neutral-500 uppercase">Multiplier</p>
|
||
<p className="text-xl font-bold text-neutral-900">
|
||
{(revenue / (investment || 1)).toFixed(2)}x
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
|
||
{/* Explanation */}
|
||
<div className="mt-12">
|
||
<Card className="border-neutral-200">
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2 text-lg">
|
||
<Info className="w-5 h-5 text-neutral-500" />
|
||
How it works
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-neutral-600 space-y-4 text-sm leading-relaxed">
|
||
<p>
|
||
Return on Investment (ROI) is a performance measure used to evaluate the efficiency or profitability of an investment. It measures the amount of return on an investment, relative to the investment’s cost.
|
||
</p>
|
||
<div className="bg-neutral-100 p-4 rounded-md font-mono text-neutral-800">
|
||
ROI = ((Net Profit) / Cost of Investment) × 100
|
||
</div>
|
||
<p>
|
||
In this calculator, <strong>Net Profit</strong> is calculated as <strong>Total Revenue - Total Investment</strong>. A positive ROI indicates that the investment has generated more money than it cost, while a negative ROI indicates a loss.
|
||
</p>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
</div>
|
||
</Container>
|
||
</section>
|
||
);
|
||
}
|