import React,{useState,useEffect} from 'react';import{createRoot}from'react-dom/client';import{Wallet,ArrowLeftRight,CalendarClock,PiggyBank,ChartNoAxesCombined,LayoutDashboard,Settings,Plus,Trash2,Download,Heart,Flower2,Sparkles,X}from'lucide-react';import './style.css';
const key='petal-data',today=()=>new Date().toISOString().slice(0,10),cash=n=>new Intl.NumberFormat('en-IN',{style:'currency',currency:'INR',maximumFractionDigits:0}).format(+n||0),cats=['Food','Bills','Travel','Shopping','Health','Home','EMI','Entertainment','Salary','Freelance','Other'],blank=()=>({tx:[],emis:[],budgets:[],goals:[]});function load(){try{return JSON.parse(localStorage.getItem(key))||blank()}catch{return blank()}}
function App(){const[d,S]=useState(load),[page,P]=useState('Overview'),[modal,M]=useState(''),[toast,T]=useState(''),[dark,D]=useState(false),[month,Q]=useState(today().slice(0,7)),[search,F]=useState(''),[form,G]=useState({title:'',amount:'',type:'expense',category:'Food',date:today(),method:'UPI',lender:'',name:'',dueDay:'10',total:'',remaining:'',limit:'',target:'',saved:'0'});useEffect(()=>localStorage.setItem(key,JSON.stringify(d)),[d]);useEffect(()=>{if(toast){let t=setTimeout(()=>T(''),2200);return()=>clearTimeout(t)}},[toast]);const set=(k,v)=>S(x=>({...x,[k]:v})),mt=d.tx.filter(x=>x.date?.slice(0,7)===month),inc=mt.filter(x=>x.type==='income').reduce((a,x)=>a+ +x.amount,0),out=mt.filter(x=>x.type==='expense').reduce((a,x)=>a+ +x.amount,0),bal=d.tx.reduce((a,x)=>a+(x.type==='income'?1:-1)* +x.amount,0),emi=d.emis.filter(x=>x.status!=='Closed').reduce((a,x)=>a+ +x.amount,0);const add=()=>M(page==='EMI tracker'?'emi':page==='Budgets'?'budget':page==='Savings goals'?'goal':'tx'),save=e=>{e.preventDefault();let item={...form,id:crypto.randomUUID()};if(modal==='tx'){if(+form.amount<=0)return;item.amount=+form.amount;set('tx',[item,...d.tx])}if(modal==='emi'){item.amount=+form.amount;item.dueDay=+form.dueDay;item.total=+form.total;item.remaining=+form.remaining;item.status='Active';set('emis',[item,...d.emis])}if(modal==='budget'){item.limit=+form.limit;set('budgets',[...d.budgets.filter(x=>x.category!==form.category),item])}if(modal==='goal'){item.target=+form.target;item.saved=+form.saved;set('goals',[...d.goals,item])}M('');T('Saved with love ✿');G({...form,title:'',amount:'',lender:'',name:'',limit:'',target:''})},del=(k,id)=>{set(k,d[k].filter(x=>x.id!==id));T('Removed')},exporter=()=>{let a=document.createElement('a');a.href=URL.createObjectURL(new Blob([JSON.stringify(d,null,2)],{type:'application/json'}));a.download='petal-backup.json';a.click()};const field=(label,k,type='text',required=false)=><label>{label}<input type={type} value={form[k]} required={required} onChange={e=>G({...form,[k]:e.target.value})}/></label>,select=(label,k,opts)=><label>{label}<select value={form[k]} onChange={e=>G({...form,[k]:e.target.value})}>{opts.map(x=><option key={x}>{x}</option>)}</select></label>;return <div className={dark?'app dark':'app'}><aside><div className="brand"><Flower2/> <b>petal</b><small>your money garden</small></div><div className="profile">🌷 <span><b>My little space</b><small>Personal finances</small></span></div>{[['Overview',LayoutDashboard],['Transactions',ArrowLeftRight],['EMI tracker',CalendarClock],['Budgets',ChartNoAxesCombined],['Savings goals',PiggyBank],['Settings',Settings]].map(([n,I])=><button className={page===n?'active':''} onClick={()=>P(n)} key={n}><I size={17}/>{n}</button>)}<div className="quote">♡<b>Little steps add up</b><p>Every rupee you track is a little win.</p>✿　♡　✿</div></aside><main><header>My space　/　<b>{page}</b><span>● Your own little budget</span></header><article>{page==='Overview'?<><section className="hero"><small><Sparkles size={13}/> A FRESH LITTLE START</small><h1>Your money, <em>your magic.</em> ♡</h1><p>A gentle look at your finances. One step at a time.</p><div>🌷</div></section><section className="section"><div><h2>Your overview ✿</h2><p>Here's how your money is blooming this month.</p></div><input type="month" value={month} onChange={e=>Q(e.target.value)}/></section><div className="stats">{[['Total balance',cash(bal),Wallet,'All recorded time'],['Income this month',cash(inc),Heart,'Money coming in'],['Spent this month',cash(out),ArrowLeftRight,'Money going out'],['Monthly EMI load',cash(emi),CalendarClock,'Active instalments']].map(([l,v,I,n])=><section className="stat" key={l}><I/><small>{l}</small><b>{v}</b><p>{n}</p></section>)}</div><div className="grid"><section className="panel"><h3>Recent little moves ✿</h3><p>Your latest money activity</p><Transactions rows={d.tx.slice(0,6)} del={id=>del('tx',id)}/><button className="link" onClick={()=>P('Transactions')}>See all transactions →</button></section><section className="panel"><h3>Monthly budgets ♡</h3><p>Gentle guides for your spending</p>{d.budgets.map(b=><div className="budget" key={b.id}>{b.category}<b>{cash(mt.filter(t=>t.category===b.category&&t.type==='expense').reduce((a,t)=>a+ +t.amount,0))} / {cash(b.limit)}</b><div className="bar"><i style={{width:Math.min(100,100*out?100*mt.filter(t=>t.category===b.category&&t.type==='expense').reduce((a,t)=>a+ +t.amount,0)/b.limit:0)+'%'}}/></div></div>)}<button className="link" onClick={()=>P('Budgets')}>Manage budgets →</button></section></div></>:null}
{page==='Transactions'&&<><Title title="Your transactions" sub="Every little rupee has a story." add={add}/><section className="panel"><input className="search" placeholder="Search transactions…" value={search} onChange={e=>F(e.target.value)}/><Transactions rows={d.tx.filter(x=>(x.title+x.category).toLowerCase().includes(search.toLowerCase()))} del={id=>del('tx',id)}/></section></>}
{page==='EMI tracker'&&<><Title title="EMI tracker" sub="Your instalments in one calm place." add={add}/><div className="cards">{d.emis.map(x=><section className="panel" key={x.id}><button className="delete" onClick={()=>del('emis',x.id)}><Trash2 size={15}/></button><small>{x.lender}</small><h3>{x.name||'Loan EMI'}</h3><h2>{cash(x.amount)} / month</h2><p>Due on {x.dueDay}th · {x.remaining} payments left</p><div className="bar"><i style={{width:(x.total?100*(x.total-x.remaining)/x.total:0)+'%'}}/></div><button className="link" onClick={()=>{set('emis',d.emis.map(y=>y.id===x.id?{...y,remaining:Math.max(0,y.remaining-1),status:y.remaining<=1?'Closed':'Active'}:y));T('Payment marked ✿')}}>Mark payment paid</button></section>)}</div></>}
{page==='Budgets'&&<><Title title="Monthly budgets" sub="Soft boundaries for your spending." add={add}/><div className="cards">{d.budgets.map(b=>{let s=mt.filter(t=>t.type==='expense'&&t.category===b.category).reduce((a,t)=>a+ +t.amount,0);return <section className="panel" key={b.id}><button className="delete" onClick={()=>del('budgets',b.id)}><Trash2 size={15}/></button><h3>{b.category}</h3><h2>{cash(s)} <small>of {cash(b.limit)}</small></h2><div className="bar"><i style={{width:Math.min(100,s/b.limit*100)+'%'}}/></div><p>{cash(Math.max(0,b.limit-s))} left</p></section>})}</div></>}
{page==='Savings goals'&&<><Title title="Little dreams" sub="Tiny steps take you somewhere wonderful." add={add}/><div className="cards">{d.goals.map(g=><section className="panel" key={g.id}><button className="delete" onClick={()=>del('goals',g.id)}><Trash2 size={15}/></button><h3>✿ {g.title}</h3><h2>{cash(g.saved)} <small>of {cash(g.target)}</small></h2><div className="bar"><i style={{width:Math.min(100,g.saved/g.target*100)+'%'}}/></div><button className="link" onClick={()=>{let n=prompt('How much did you save?');if(n&&+n>0)set('goals',d.goals.map(x=>x.id===g.id?{...x,saved:+x.saved + +n}:x))}}>+ Add savings</button></section>)}</div></>}
{page==='Settings'&&<><Title title="Your settings" sub="Your space, your rules."/><section className="panel"><h3>Personalise your space</h3><p>Soft night mode</p><button className="primary" onClick={()=>D(!dark)}>{dark?'Turn light mode on':'Turn night mode on'}</button></section><section className="panel"><h3>Your data</h3><p>Everything stays in this browser. Keep a backup somewhere safe.</p><button className="primary" onClick={exporter}><Download size={15}/> Export backup (.json)</button><label className="primary upload">Restore backup<input type="file" accept="application/json" onChange={e=>{let r=new FileReader();r.onload=()=>{try{setData(JSON.parse(r.result));T('Backup restored')}catch{T('Invalid backup')}};if(e.target.files[0])r.readAsText(e.target.files[0])}}/></label><p>♡ Nothing is sent to a server.</p><button className="danger" onClick={()=>{if(confirm('Clear all records?'))setData(blank())}}>Clear all data</button></section></>}
</article><footer>Made with ♡ and a little hope ✿</footer></main><button className="float" onClick={add}><Plus size={18}/> Add {page==='EMI tracker'?'EMI':page==='Budgets'?'budget':page==='Savings goals'?'goal':'transaction'}</button>
{modal&&<div className="overlay" onMouseDown={e=>e.target===e.currentTarget&&M('')}><form className="modal" onSubmit={save}><div className="modalhead"><div><small>A LITTLE UPDATE</small><h2>{({tx:'Add transaction',emi:'Add an EMI',budget:'Set a budget',goal:'Create a savings goal'})[modal]}</h2></div><button type="button" onClick={()=>M('')}><X/></button></div>{modal==='tx'&&<><div className="seg"><button type="button" className={form.type==='expense'?'sel':''} onClick={()=>G({...form,type:'expense',category:'Food'})}>Expense</button><button type="button" className={form.type==='income'?'sel':''} onClick={()=>G({...form,type:'income',category:'Salary'})}>Income</button></div>{field('What was it?','title','text',true)}<div className="row">{field('Amount (₹)','amount','number',true)}{select('Category','category',cats)}</div><div className="row">{field('Date','date','date',true)}{select('Payment method','method',['UPI','Cash','Debit card','Credit card','Bank transfer','Other'])}</div></>}{modal==='emi'&&<>{field('Lender','lender','text',true)}{field('Loan name','name') }<div className="row">{field('Monthly EMI (₹)','amount','number',true)}{field('Due day','dueDay','number',true)}</div><div className="row">{field('Total instalments','total','number',true)}{field('Remaining instalments','remaining','number',true)}</div></>}{modal==='budget'&&<>{select('Category','category',cats.filter(x=>!['Salary','Freelance'].includes(x)))}{field('Monthly limit (₹)','limit','number',true)}</>}{modal==='goal'&&<>{field('What are you saving for?','title','text',true)}<div className="row">{field('Target amount (₹)','target','number',true)}{field('Already saved (₹)','saved','number')}</div></>}<button className="primary full">Save with love ♡</button></form></div>}{toast&&<div className="toast">✿　{toast}</div>}</div>}
function Title({title,sub,add}){return <div className="pagetitle"><div><small><Sparkles size={13}/> YOUR LITTLE MONEY GARDEN</small><h1>{title} ♡</h1><p>{sub}</p></div>{add&&<button className="primary desktop" onClick={add}><Plus size={16}/> Add new</button>}</div>}
function Transactions({rows,del}){return <div className="tablewrap"><table><thead><tr><th>TRANSACTION</th><th>CATEGORY</th><th>DATE</th><th>AMOUNT</th><th/></tr></thead><tbody>{rows.map(t=><tr key={t.id}><td><b>{t.title}</b><small className="sub">{t.method}</small></td><td>{t.category}</td><td>{t.date}</td><td className={t.type}>{t.type==='income'?'+':'−'}{cash(t.amount)}</td><td><button className="delete" onClick={()=>del(t.id)}><Trash2 size={14}/></button></td></tr>)}{!rows.length&&<tr><td colSpan="5">No transactions yet. Add your first little money move 🌷</td></tr>}</tbody></table></div>}
createRoot(document.getElementById('root')).render(<App/>);