Initial import
This commit is contained in:
commit
657b6ecd75
9
.env.example
Normal file
9
.env.example
Normal file
@ -0,0 +1,9 @@
|
||||
# GEMINI_API_KEY: Required for Gemini AI API calls.
|
||||
# AI Studio automatically injects this at runtime from user secrets.
|
||||
# Users configure this via the Secrets panel in the AI Studio UI.
|
||||
GEMINI_API_KEY="MY_GEMINI_API_KEY"
|
||||
|
||||
# APP_URL: The URL where this applet is hosted.
|
||||
# AI Studio automatically injects this at runtime with the Cloud Run service URL.
|
||||
# Used for self-referential links, OAuth callbacks, and API endpoints.
|
||||
APP_URL="MY_APP_URL"
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
node_modules/
|
||||
build/
|
||||
dist/
|
||||
coverage/
|
||||
.DS_Store
|
||||
*.log
|
||||
.env*
|
||||
!.env.example
|
||||
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
<div align="center">
|
||||
<img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
|
||||
</div>
|
||||
|
||||
# Run and deploy your AI Studio app
|
||||
|
||||
This contains everything you need to run your app locally.
|
||||
|
||||
View your app in AI Studio: https://ai.studio/apps/aa0a996b-c612-43f6-a22a-d2d9e6b595df
|
||||
|
||||
## Run Locally
|
||||
|
||||
**Prerequisites:** Node.js
|
||||
|
||||
|
||||
1. Install dependencies:
|
||||
`npm install`
|
||||
2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
|
||||
3. Run the app:
|
||||
`npm run dev`
|
||||
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>My Google AI Studio App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
5
metadata.json
Normal file
5
metadata.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Generali Central Life Insurance Portal",
|
||||
"description": "A comprehensive portal for exploring life insurance plans, understanding benefits, and generating custom benefit illustrations.",
|
||||
"requestFramePermissions": []
|
||||
}
|
||||
0
package-lock.json
generated
Normal file
0
package-lock.json
generated
Normal file
35
package.json
Normal file
35
package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "react-example",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --port=3000 --host=0.0.0.0",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"clean": "rm -rf dist",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google/genai": "^1.29.0",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"@vitejs/plugin-react": "^5.0.4",
|
||||
"lucide-react": "^0.546.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"vite": "^6.2.0",
|
||||
"express": "^4.21.2",
|
||||
"dotenv": "^17.2.3",
|
||||
"better-sqlite3": "^12.4.1",
|
||||
"motion": "^12.23.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.14.0",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"tailwindcss": "^4.1.14",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "~5.8.2",
|
||||
"vite": "^6.2.0",
|
||||
"@types/express": "^4.17.21"
|
||||
}
|
||||
}
|
||||
623
src/App.tsx
Normal file
623
src/App.tsx
Normal file
@ -0,0 +1,623 @@
|
||||
/**
|
||||
* @license
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import {
|
||||
ShieldCheck,
|
||||
TrendingUp,
|
||||
Clock,
|
||||
HeartPulse,
|
||||
ChevronRight,
|
||||
Info,
|
||||
Calculator,
|
||||
ArrowRight,
|
||||
CheckCircle2,
|
||||
FileText,
|
||||
User,
|
||||
Mail,
|
||||
Phone,
|
||||
Calendar
|
||||
} from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'motion/react';
|
||||
|
||||
// --- Types ---
|
||||
|
||||
type PlanType = 'money-back' | 'long-term-income';
|
||||
|
||||
interface QuoteData {
|
||||
name: string;
|
||||
age: number;
|
||||
gender: 'male' | 'female';
|
||||
planType: PlanType;
|
||||
sumAssured: number;
|
||||
policyTerm: number;
|
||||
premiumTerm: number;
|
||||
}
|
||||
|
||||
// --- Components ---
|
||||
|
||||
const Navbar = () => (
|
||||
<nav className="sticky top-0 z-50 bg-white/80 backdrop-blur-md border-b border-zinc-100">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-16 h-16 bg-white-600 rounded-lg flex items-center justify-center">
|
||||
<img src="https://image2url.com/r2/default/images/1772810627562-124d437f-8175-4a8a-a696-76d7573a2b3e.png" alt="image" />
|
||||
</div>
|
||||
<span className="font-bold text-xl tracking-tight text-zinc-900">Generali Central</span>
|
||||
</div>
|
||||
<div className="hidden md:flex items-center gap-8 text-sm font-medium text-zinc-600">
|
||||
<a href="#plans" className="hover:text-red-600 transition-colors">Plans</a>
|
||||
<a href="#explanations" className="hover:text-red-600 transition-colors">How it Works</a>
|
||||
{/* <a href="#calculator" className="hover:text-red-600 transition-colors">Calculator</a> */}
|
||||
<button className="bg-red-600 text-white px-5 py-2 rounded-full hover:bg-red-700 transition-all shadow-sm">
|
||||
<a href="#contact" className="transition-colors">Contact Advisor</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
||||
const Hero = () => (
|
||||
<section className="relative py-20 overflow-hidden bg-zinc-50">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
>
|
||||
<span className="inline-block px-3 py-1 bg-red-50 text-red-600 text-xs font-bold uppercase tracking-widest rounded-full mb-6">
|
||||
Secure Your Future
|
||||
</span>
|
||||
<h1 className="text-5xl lg:text-6xl font-bold text-zinc-900 leading-[1.1] mb-6">
|
||||
Protection that <br />
|
||||
<span className="text-red-600">Grows with You.</span>
|
||||
</h1>
|
||||
<p className="text-lg text-zinc-600 mb-8 max-w-lg leading-relaxed">
|
||||
Explore our range of Individual, Non-Linked, Non-Participating Savings Life Insurance Plans designed to provide both security and guaranteed returns.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<a href="#calculator" className="bg-zinc-900 text-white px-8 py-4 rounded-xl font-semibold flex items-center gap-2 hover:bg-zinc-800 transition-all shadow-lg shadow-zinc-200">
|
||||
Get a Quote <ArrowRight className="w-4 h-4" />
|
||||
</a>
|
||||
<a href="#plans" className="bg-white text-zinc-900 border border-zinc-200 px-8 py-4 rounded-xl font-semibold hover:bg-zinc-50 transition-all">
|
||||
View Plans
|
||||
</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.2 }}
|
||||
className="relative"
|
||||
>
|
||||
<div className="aspect-square rounded-3xl overflow-hidden shadow-2xl">
|
||||
<img
|
||||
src="https://picsum.photos/seed/insurance/800/800"
|
||||
alt="Family Security"
|
||||
className="w-full h-full object-cover"
|
||||
referrerPolicy="no-referrer"
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute -bottom-6 -left-6 bg-white p-6 rounded-2xl shadow-xl border border-zinc-100 max-w-[240px]">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="p-2 bg-emerald-50 rounded-lg">
|
||||
<TrendingUp className="text-emerald-600 w-5 h-5" />
|
||||
</div>
|
||||
<span className="font-bold text-zinc-900">Guaranteed Returns</span>
|
||||
</div>
|
||||
<p className="text-xs text-zinc-500">Fixed payouts and maturity benefits to ensure your financial goals are met.</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
const PlanExplanation = () => (
|
||||
<section id="explanations" className="py-24 bg-white">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold text-zinc-900 mb-4">Understanding Your Policy</h2>
|
||||
<p className="text-zinc-500 max-w-2xl mx-auto">Insurance can be complex. We break down the key terms from your benefit illustration so you can make an informed choice.</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{[
|
||||
{
|
||||
title: "Sum Assured",
|
||||
desc: "The fixed amount guaranteed to be paid to the nominee in case of the life assured's death during the policy term.",
|
||||
icon: ShieldCheck,
|
||||
color: "bg-blue-50 text-blue-600"
|
||||
},
|
||||
{
|
||||
title: "Annualized Premium",
|
||||
desc: "The premium amount payable in a year, excluding taxes, rider premiums, and underwriting extra premiums.",
|
||||
icon: Clock,
|
||||
color: "bg-purple-50 text-purple-600"
|
||||
},
|
||||
{
|
||||
title: "Guaranteed Additions",
|
||||
desc: "Additional amounts added to your policy benefits, typically accruing after a certain number of policy years.",
|
||||
icon: TrendingUp,
|
||||
color: "bg-emerald-50 text-emerald-600"
|
||||
},
|
||||
{
|
||||
title: "Survival Benefit",
|
||||
desc: "Periodic payouts made to you during the policy term if the life assured survives to specified dates.",
|
||||
icon: HeartPulse,
|
||||
color: "bg-red-50 text-red-600"
|
||||
},
|
||||
{
|
||||
title: "GSV vs SSV",
|
||||
desc: "GSV (Guaranteed Surrender Value) is the minimum guaranteed amount if you cancel. SSV (Special Surrender Value) is often higher but not guaranteed.",
|
||||
icon: Info,
|
||||
color: "bg-amber-50 text-amber-600"
|
||||
},
|
||||
{
|
||||
title: "Rider Benefits",
|
||||
desc: "Optional add-ons like 'Accidental Death Benefit' that provide extra protection for a small additional premium.",
|
||||
icon: CheckCircle2,
|
||||
color: "bg-zinc-50 text-zinc-600"
|
||||
}
|
||||
].map((item, idx) => (
|
||||
<motion.div
|
||||
key={idx}
|
||||
whileHover={{ y: -5 }}
|
||||
className="p-8 rounded-2xl border border-zinc-100 bg-zinc-50/50 hover:bg-white hover:shadow-xl hover:shadow-zinc-200/50 transition-all"
|
||||
>
|
||||
<div className={`w-12 h-12 ${item.color} rounded-xl flex items-center justify-center mb-6`}>
|
||||
<item.icon className="w-6 h-6" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-zinc-900 mb-3">{item.title}</h3>
|
||||
<p className="text-zinc-600 text-sm leading-relaxed">{item.desc}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
const QuoteForm = () => {
|
||||
const [formData, setFormData] = useState<QuoteData>({
|
||||
name: '',
|
||||
age: 30,
|
||||
gender: 'male',
|
||||
planType: 'money-back',
|
||||
sumAssured: 1000000,
|
||||
policyTerm: 20,
|
||||
premiumTerm: 20
|
||||
});
|
||||
|
||||
const [isCalculated, setIsCalculated] = useState(false);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsCalculated(true);
|
||||
};
|
||||
|
||||
const illustration = useMemo(() => {
|
||||
if (!isCalculated) return null;
|
||||
|
||||
// Simplified logic based on PDF data
|
||||
const annualPremium = formData.sumAssured * 0.1; // Roughly 10% for 10L sum assured
|
||||
const years = Array.from({ length: formData.policyTerm }, (_, i) => i + 1);
|
||||
|
||||
return years.map(year => {
|
||||
const isPayoutYear = formData.planType === 'money-back' && year % 5 === 0 && year < formData.policyTerm;
|
||||
const survivalBenefit = isPayoutYear ? formData.sumAssured * 0.11 : 0;
|
||||
const guaranteedAddition = year >= 8 ? annualPremium * 0.838 : 0;
|
||||
const deathBenefit = formData.sumAssured + (year >= 8 ? guaranteedAddition * (year - 7) : 0);
|
||||
|
||||
return {
|
||||
year,
|
||||
premium: annualPremium,
|
||||
survivalBenefit,
|
||||
guaranteedAddition,
|
||||
deathBenefit,
|
||||
surrenderValue: annualPremium * year * (year / formData.policyTerm) * 0.6 // Mock curve
|
||||
};
|
||||
});
|
||||
}, [isCalculated, formData]);
|
||||
|
||||
return (
|
||||
<section id="calculator" className="py-24 bg-zinc-50">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid lg:grid-cols-5 gap-12">
|
||||
|
||||
{/* Form Side */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-white p-8 rounded-3xl shadow-xl border border-zinc-100">
|
||||
<div className="flex items-center gap-3 mb-8">
|
||||
<div className="p-2 bg-red-50 rounded-lg">
|
||||
<Calculator className="text-red-600 w-6 h-6" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-zinc-900">Illustration Builder</h2>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2 flex items-center gap-2">
|
||||
<User className="w-4 h-4 text-zinc-400" /> Full Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 focus:border-red-500 transition-all outline-none"
|
||||
placeholder="e.g. Harmanjeet Singh"
|
||||
value={formData.name}
|
||||
onChange={e => setFormData({...formData, name: e.target.value})}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2 flex items-center gap-2">
|
||||
<Calendar className="w-4 h-4 text-zinc-400" /> Age
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="18" max="65"
|
||||
className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 transition-all outline-none"
|
||||
value={formData.age}
|
||||
onChange={e => setFormData({...formData, age: parseInt(e.target.value)})}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Gender</label>
|
||||
<select
|
||||
className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 transition-all outline-none"
|
||||
value={formData.gender}
|
||||
onChange={e => setFormData({...formData, gender: e.target.value as any})}
|
||||
>
|
||||
<option value="male">Male</option>
|
||||
<option value="female">Female</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Select Plan</label>
|
||||
<div className="grid grid-cols-1 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setFormData({...formData, planType: 'money-back'})}
|
||||
className={`p-4 rounded-xl border-2 text-left transition-all ${formData.planType === 'money-back' ? 'border-red-600 bg-red-50/50' : 'border-zinc-100 hover:border-zinc-200'}`}
|
||||
>
|
||||
<div className="font-bold text-zinc-900">Money Back Super Plan</div>
|
||||
<div className="text-xs text-zinc-500">Periodic survival benefits + Maturity</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setFormData({...formData, planType: 'long-term-income'})}
|
||||
className={`p-4 rounded-xl border-2 text-left transition-all ${formData.planType === 'long-term-income' ? 'border-red-600 bg-red-50/50' : 'border-zinc-100 hover:border-zinc-200'}`}
|
||||
>
|
||||
<div className="font-bold text-zinc-900">Long Term Income Plan</div>
|
||||
<div className="text-xs text-zinc-500">Regular income stream for up to 50 years</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Sum Assured (₹)</label>
|
||||
<input
|
||||
type="range"
|
||||
min="500000" max="5000000" step="100000"
|
||||
className="w-full h-2 bg-zinc-200 rounded-lg appearance-none cursor-pointer accent-red-600"
|
||||
value={formData.sumAssured}
|
||||
onChange={e => setFormData({...formData, sumAssured: parseInt(e.target.value)})}
|
||||
/>
|
||||
<div className="flex justify-between mt-2 text-sm font-bold text-zinc-900">
|
||||
<span>₹5L</span>
|
||||
<span className="text-red-600">₹{(formData.sumAssured / 100000).toFixed(1)}L</span>
|
||||
<span>₹50L</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-red-600 text-white py-4 rounded-xl font-bold text-lg hover:bg-red-700 transition-all shadow-lg shadow-red-200 flex items-center justify-center gap-2"
|
||||
>
|
||||
Generate Illustration <ChevronRight className="w-5 h-5" />
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Results Side */}
|
||||
<div className="lg:col-span-3">
|
||||
<AnimatePresence mode="wait">
|
||||
{!isCalculated ? (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="h-full flex flex-col items-center justify-center text-center p-12 border-2 border-dashed border-zinc-200 rounded-3xl bg-white/50"
|
||||
>
|
||||
<div className="w-20 h-20 bg-zinc-100 rounded-full flex items-center justify-center mb-6">
|
||||
<FileText className="w-10 h-10 text-zinc-300" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold text-zinc-400">Ready to See Your Benefits?</h3>
|
||||
<p className="text-zinc-400 max-w-xs mt-2">Fill out the form to generate a detailed year-by-year benefit illustration.</p>
|
||||
</motion.div>
|
||||
) : (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="space-y-6"
|
||||
>
|
||||
<div className="bg-zinc-900 text-white p-8 rounded-3xl shadow-xl">
|
||||
<div className="flex justify-between items-start mb-8">
|
||||
<div>
|
||||
<h3 className="text-zinc-400 text-xs font-bold uppercase tracking-widest mb-1">Illustration Summary</h3>
|
||||
<div className="text-2xl font-bold">{formData.name || 'Valued Customer'}</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-zinc-400 text-xs font-bold uppercase tracking-widest mb-1">Plan Type</div>
|
||||
<div className="font-bold text-red-400">{formData.planType === 'money-back' ? 'Money Back Super' : 'Long Term Income'}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="bg-white/5 p-4 rounded-2xl">
|
||||
<div className="text-zinc-500 text-[10px] uppercase font-bold mb-1">Sum Assured</div>
|
||||
<div className="text-lg font-bold">₹{(formData.sumAssured / 100000).toFixed(1)}L</div>
|
||||
</div>
|
||||
<div className="bg-white/5 p-4 rounded-2xl">
|
||||
<div className="text-zinc-500 text-[10px] uppercase font-bold mb-1">Annual Premium</div>
|
||||
<div className="text-lg font-bold">₹{(formData.sumAssured * 0.1 / 1000).toFixed(0)}K</div>
|
||||
</div>
|
||||
<div className="bg-white/5 p-4 rounded-2xl">
|
||||
<div className="text-zinc-500 text-[10px] uppercase font-bold mb-1">Policy Term</div>
|
||||
<div className="text-lg font-bold">{formData.policyTerm} Yrs</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-3xl shadow-xl border border-zinc-100 overflow-hidden">
|
||||
<div className="p-6 border-b border-zinc-100 flex justify-between items-center">
|
||||
<h4 className="font-bold text-zinc-900">Yearly Benefit Projection</h4>
|
||||
<span className="text-[10px] bg-emerald-50 text-emerald-600 px-2 py-1 rounded-full font-bold uppercase">Guaranteed Values</span>
|
||||
</div>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-left text-sm">
|
||||
<thead>
|
||||
<tr className="bg-zinc-50 text-zinc-500 font-bold uppercase text-[10px] tracking-wider">
|
||||
<th className="px-6 py-4">Year</th>
|
||||
<th className="px-6 py-4">Premium</th>
|
||||
<th className="px-6 py-4">Survival Benefit</th>
|
||||
<th className="px-6 py-4">Death Benefit</th>
|
||||
<th className="px-6 py-4 text-right">Surrender Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-zinc-50">
|
||||
{illustration?.slice(0, 10).map((row) => (
|
||||
<tr key={row.year} className="hover:bg-zinc-50/50 transition-colors">
|
||||
<td className="px-6 py-4 font-bold text-zinc-900">{row.year}</td>
|
||||
<td className="px-6 py-4 text-zinc-600">₹{row.premium.toLocaleString()}</td>
|
||||
<td className="px-6 py-4">
|
||||
{row.survivalBenefit > 0 ? (
|
||||
<span className="text-emerald-600 font-bold">₹{row.survivalBenefit.toLocaleString()}</span>
|
||||
) : (
|
||||
<span className="text-zinc-300">—</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-6 py-4 font-medium text-zinc-900">₹{row.deathBenefit.toLocaleString()}</td>
|
||||
<td className="px-6 py-4 text-right font-mono text-zinc-500">₹{row.surrenderValue.toLocaleString(undefined, { maximumFractionDigits: 0 })}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="p-4 bg-zinc-50 text-center">
|
||||
<button className="text-red-600 text-xs font-bold hover:underline">View Full 20-Year Illustration</button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
const Footer = () => (
|
||||
<footer className="bg-zinc-900 text-white py-12">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid md:grid-cols-4 gap-12 mb-12">
|
||||
<div className="col-span-2">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<div className="w-8 h-8 bg-red-600 rounded-lg flex items-center justify-center">
|
||||
<ShieldCheck className="text-white w-5 h-5" />
|
||||
</div>
|
||||
<span className="font-bold text-xl tracking-tight">Generali Central</span>
|
||||
</div>
|
||||
<p className="text-zinc-500 max-w-sm text-sm leading-relaxed">
|
||||
Generali Central Life Insurance Company Limited (Formerly known as Future Generali India Life Insurance Company Limited).
|
||||
Registered Office: Unit 801 and 802, 8th floor, Tower C, Embassy 247 Park, L.B.S. Marg, Vikhroli (W), Mumbai – 400083.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-bold mb-6 text-sm uppercase tracking-widest text-zinc-400">Quick Links</h4>
|
||||
<ul className="space-y-4 text-sm text-zinc-500">
|
||||
<li><a href="#" className="hover:text-white transition-colors">About Us</a></li>
|
||||
<li><a href="#" className="hover:text-white transition-colors">Claims Process</a></li>
|
||||
<li><a href="#" className="hover:text-white transition-colors">Privacy Policy</a></li>
|
||||
<li><a href="#" className="hover:text-white transition-colors">Terms & Conditions</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-bold mb-6 text-sm uppercase tracking-widest text-zinc-400">Contact</h4>
|
||||
<ul className="space-y-4 text-sm text-zinc-500">
|
||||
<li className="flex items-center gap-3"><Mail className="w-4 h-4" /> care@generalicentral.com</li>
|
||||
<li className="flex items-center gap-3"><Phone className="w-4 h-4" /> 1800 102 2355</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-12 border-t border-white/5 text-center text-xs text-zinc-600">
|
||||
<p>© 2026 Generali Central Life Insurance Company Limited. IRDAI Regn. No.: 133 | CIN: U66010MH2006PLC165288</p>
|
||||
<p className="mt-2 italic">Insurance is the subject matter of solicitation. For more details on risk factors, terms and conditions, please read sales brochure carefully before concluding a sale.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<div className="min-h-screen bg-white font-sans selection:bg-red-100 selection:text-red-900">
|
||||
<Navbar />
|
||||
<main>
|
||||
<Hero />
|
||||
|
||||
{/* Quick Stats */}
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 -mt-12 relative z-20">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
{[
|
||||
{ label: "Claims Ratio", value: "98.4%", icon: ShieldCheck },
|
||||
{ label: "Happy Families", value: "2.5M+", icon: User },
|
||||
{ label: "Solvency Ratio", value: "1.92", icon: TrendingUp },
|
||||
{ label: "Support", value: "24/7", icon: Phone },
|
||||
].map((stat, i) => (
|
||||
<div key={i} className="bg-white p-6 rounded-2xl shadow-xl border border-zinc-100 flex flex-col items-center text-center">
|
||||
<stat.icon className="w-6 h-6 text-red-600 mb-3" />
|
||||
<div className="text-2xl font-bold text-zinc-900">{stat.value}</div>
|
||||
<div className="text-[10px] font-bold text-zinc-400 uppercase tracking-widest">{stat.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PlanExplanation />
|
||||
|
||||
{/* Plan Comparison Section */}
|
||||
<section id="plans" className="py-24 bg-zinc-900 text-white overflow-hidden">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-col md:flex-row justify-between items-end mb-16 gap-8">
|
||||
<div className="max-w-xl">
|
||||
<h2 className="text-4xl font-bold mb-4">Choose Your Shield</h2>
|
||||
<p className="text-zinc-400">Whether you need periodic payouts or a long-term income stream, we have the right plan for your life's milestones.</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="w-12 h-12 rounded-full border border-white/10 flex items-center justify-center text-zinc-500">01</div>
|
||||
<div className="w-12 h-12 rounded-full border border-white/10 flex items-center justify-center text-zinc-500">02</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div className="group relative p-10 rounded-3xl bg-white/5 border border-white/10 hover:bg-white/10 transition-all cursor-pointer overflow-hidden">
|
||||
<div className="absolute top-0 right-0 p-8 opacity-10 group-hover:opacity-20 transition-opacity">
|
||||
<TrendingUp className="w-32 h-32" />
|
||||
</div>
|
||||
<span className="text-red-400 text-xs font-bold uppercase tracking-widest mb-4 block">Best for Milestones</span>
|
||||
<h3 className="text-3xl font-bold mb-6">Money Back Super Plan</h3>
|
||||
<ul className="space-y-4 mb-10 text-zinc-400">
|
||||
<li className="flex items-center gap-3"><CheckCircle2 className="w-5 h-5 text-emerald-500" /> Guaranteed Survival Benefits every 5 years</li>
|
||||
<li className="flex items-center gap-3"><CheckCircle2 className="w-5 h-5 text-emerald-500" /> Accrued Guaranteed Additions</li>
|
||||
<li className="flex items-center gap-3"><CheckCircle2 className="w-5 h-5 text-emerald-500" /> Life cover for the entire policy term</li>
|
||||
</ul>
|
||||
{/*<button className="w-full py-4 rounded-xl bg-white text-zinc-900 font-bold hover:bg-zinc-100 transition-colors">Explore Plan</button>*/}
|
||||
</div>
|
||||
|
||||
<div className="group relative p-10 rounded-3xl bg-white/5 border border-white/10 hover:bg-white/10 transition-all cursor-pointer overflow-hidden">
|
||||
<div className="absolute top-0 right-0 p-8 opacity-10 group-hover:opacity-20 transition-opacity">
|
||||
<Clock className="w-32 h-32" />
|
||||
</div>
|
||||
<span className="text-red-400 text-xs font-bold uppercase tracking-widest mb-4 block">Best for Retirement</span>
|
||||
<h3 className="text-3xl font-bold mb-6">Long Term Income Plan</h3>
|
||||
<ul className="space-y-4 mb-10 text-zinc-400">
|
||||
<li className="flex items-center gap-3"><CheckCircle2 className="w-5 h-5 text-emerald-500" /> Regular income for up to 50 years</li>
|
||||
<li className="flex items-center gap-3"><CheckCircle2 className="w-5 h-5 text-emerald-500" /> Immediate or Deferred income options</li>
|
||||
<li className="flex items-center gap-3"><CheckCircle2 className="w-5 h-5 text-emerald-500" /> Maturity benefit equal to Sum Assured</li>
|
||||
</ul>
|
||||
{/*<button className="w-full py-4 rounded-xl bg-white text-zinc-900 font-bold hover:bg-zinc-100 transition-colors">Explore Plan</button>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="contact" className="py-24 bg-zinc-50 border-t border-zinc-100">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="bg-white rounded-[2rem] shadow-2xl overflow-hidden flex flex-col md:flex-row">
|
||||
<div className="md:w-1/2 bg-red-600 p-12 text-white flex flex-col justify-center">
|
||||
<h2 className="text-4xl font-bold mb-6">Talk to an Expert</h2>
|
||||
<p className="text-red-100 mb-8 leading-relaxed">
|
||||
Our certified financial advisors are ready to help you customize a plan that perfectly fits your family's needs and budget.
|
||||
</p>
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-white/10 rounded-xl flex items-center justify-center">
|
||||
<Phone className="w-6 h-6" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs font-bold uppercase tracking-widest text-red-200">Call Us</div>
|
||||
<div className="text-xl font-bold">1800 102 2355</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-white/10 rounded-xl flex items-center justify-center">
|
||||
<Mail className="w-6 h-6" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs font-bold uppercase tracking-widest text-red-200">Email Us</div>
|
||||
<div className="text-xl font-bold">care@generalicentral.com</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="md:w-1/2 p-12">
|
||||
<form className="space-y-6">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">First Name</label>
|
||||
<input type="text" className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 outline-none transition-all" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Last Name</label>
|
||||
<input type="text" className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 outline-none transition-all" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Email Address</label>
|
||||
<input type="email" className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 outline-none transition-all" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Phone Number</label>
|
||||
<input type="tel" className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 outline-none transition-all" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-zinc-700 mb-2">Your Message</label>
|
||||
<textarea rows={4} className="w-full px-4 py-3 rounded-xl border border-zinc-200 focus:ring-2 focus:ring-red-500 outline-none transition-all resize-none"></textarea>
|
||||
</div>
|
||||
<button type="button" className="w-full bg-zinc-900 text-white py-4 rounded-xl font-bold hover:bg-zinc-800 transition-all shadow-lg shadow-zinc-200">
|
||||
Send Message
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/* <QuoteForm> */}
|
||||
|
||||
{/* Trust Section */}
|
||||
{/*<section className="py-24 bg-white">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-zinc-400 text-xs font-bold uppercase tracking-widest mb-12">Trusted by Industry Leaders</h2>
|
||||
<div className="flex flex-wrap justify-center items-center gap-12 opacity-30 grayscale">
|
||||
<div className="text-2xl font-black italic">GENERALI</div>
|
||||
<div className="text-2xl font-black italic">FUTURE GROUP</div>
|
||||
<div className="text-2xl font-black italic">CENTRAL BANK</div>
|
||||
<div className="text-2xl font-black italic">IRDAI</div>
|
||||
</div>
|
||||
</div>
|
||||
</section> */}
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
1
src/index.css
Normal file
1
src/index.css
Normal file
@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
10
src/main.tsx
Normal file
10
src/main.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import {StrictMode} from 'react';
|
||||
import {createRoot} from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
import './index.css';
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
);
|
||||
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": false,
|
||||
"module": "ESNext",
|
||||
"lib": [
|
||||
"ES2022",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"allowJs": true,
|
||||
"jsx": "react-jsx",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
},
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||
24
vite.config.ts
Normal file
24
vite.config.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import path from 'path';
|
||||
import {defineConfig, loadEnv} from 'vite';
|
||||
|
||||
export default defineConfig(({mode}) => {
|
||||
const env = loadEnv(mode, '.', '');
|
||||
return {
|
||||
plugins: [react(), tailwindcss()],
|
||||
define: {
|
||||
'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY),
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, '.'),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
// HMR is disabled in AI Studio via DISABLE_HMR env var.
|
||||
// Do not modifyâfile watching is disabled to prevent flickering during agent edits.
|
||||
hmr: process.env.DISABLE_HMR !== 'true',
|
||||
},
|
||||
};
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user