1const e=`import { useState, useEffect } from 'react'; 2import { Calculator, TrendingDown, TrendingUp, CheckCircle, DollarSign, AlertTriangle, Calendar, Download } from 'lucide-react'; 3import EmbedLayout from './EmbedLayout'; 4import { supabase } from '../../lib/supabase'; 5import { useSection } from '../../hooks/usePageSections'; 6 7const STATES = [ 8 'Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Delaware', 9 'Florida','Georgia','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas','Kentucky', 10 'Louisiana','Maine','Maryland','Massachusetts','Michigan','Minnesota','Mississippi', 11 'Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','New Mexico', 12 'New York','North Carolina','North Dakota','Ohio','Oklahoma','Oregon','Pennsylvania', 13 'Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah','Vermont', 14 'Virginia','Washington','West Virginia','Wisconsin','Wyoming' 15]; 16 17type SectionKey = 'hero' | 'form' | 'results' | 'contact' | 'all'; 18 19interface Props { 20 only?: SectionKey; 21} 22 23const SavingsCalculatorEmbed = ({ only = 'all' }: Props) => { 24 const { section: heroSection } = useSection('savings-calculator', 'hero'); 25 const { section: formSection } = useSection('savings-calculator', 'form'); 26 const { section: resultsSection } = useSection('savings-calculator', 'results'); 27 const { section: contactSection } = useSection('savings-calculator', 'contact'); 28 29 const hero = heroSection?.content ?? {}; 30 const form = formSection?.content ?? {}; 31 const res = resultsSection?.content ?? {}; 32 const contact = contactSection?.content ?? {}; 33 34 const [formData, setFormData] = useState({ 35 agencyType: '', state: '', monthlyClaims: '', averageClaimValue: '', 36 denialRate: '', billingModel: '', useRCMSoftware: '', 37 name: '', email: '', phone: '', preferredTime: '' 38 }); 39 const [showResults, setShowResults] = useState(false); 40 const [showContactForm, setShowContactForm] = useState(false); 41 const [assumptions, setAssumptions] = useState({ targetDenialRate: 2.0, efficiencyGain: 25.0 }); 42 43 useEffect(() => { 44 (async () => { 45 const { data } = await supabase.from('calculator_assumptions').select('name, value').eq('is_active', true); 46 if (data) { 47 const map: Record<string, number> = {}; 48 data.forEach((r: any) => { map[r.name] = Number(r.value); }); 49 setAssumptions({ 50 targetDenialRate: map['target_denial_rate'] ?? 2.0, 51 efficiencyGain: map['efficiency_gain'] ?? 25.0, 52 }); 53 } 54 })(); 55 }, []); 56 57 const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => { 58 setFormData(prev => ({ ...prev, [e.target.name]: e.target.value })); 59 }; 60 61 const calculate = () => { 62 const claims = parseFloat(formData.monthlyClaims) || 0; 63 const avgValue = parseFloat(formData.averageClaimValue) || 0; 64 const denialRate = parseFloat(formData.denialRate) || 0; 65 const monthlyRevenue = claims * avgValue; 66 const currentDenialLoss = monthlyRevenue * (denialRate / 100); 67 const pmbDenialLoss = monthlyRevenue * (assumptions.targetDenialRate / 100); 68 const efficiencyGains = monthlyRevenue * 0.15 * (assumptions.efficiencyGain / 100); 69 const totalSavings = currentDenialLoss - pmbDenialLoss + efficiencyGains; 70 return { 71 monthlyRevenue, 72 currentDenialLoss, 73 totalSavings: Math.max(0, totalSavings), 74 annualSavings: Math.max(0, totalSavings * 12), 75 }; 76 }; 77 78 const results = showResults ? calculate() : null; 79 const themeColor = hero.theme_color || '#1d4ed8'; 80 const agencyTypes = form.agency_types ?? [ 81 { value: 'physician', label: 'Physician Practice' }, 82 { value: 'home-health', label: 'Home Health Agency' }, 83 { value: 'hospice', label: 'Hospice Agency' }, 84 { value: 'hospital', label: 'Hospital' }, 85 { value: 'other', label: 'Other' }, 86 ]; 87 const billingModels = form.billing_models ?? [ 88 { value: 'in-house', label: 'In-House' }, 89 { value: 'outsourced', label: 'Outsourced' }, 90 { value: 'hybrid', label: 'Hybrid' }, 91 ]; 92 const rcmOptions = form.rcm_options ?? [ 93 { value: 'yes', label: 'Yes' }, 94 { value: 'no', label: 'No' }, 95 ]; 96 97 if (only === 'hero') { 98 return ( 99 <EmbedLayout embedKey="savings-calculator-hero"> 100 <section className="text-white py-16" style={{ background: \`linear-gradient(135deg, \${theme
100Color}, \${adjustColor(themeColor, -30)})\` }}> 101 <div className="max-w-4xl mx-auto px-4 text-center"> 102 <div className="w-16 h-16 bg-[#fdc010] rounded-full flex items-center justify-center mx-auto mb-6"> 103 <Calculator className="w-8 h-8 text-black" /> 104 </div> 105 <h1 className="text-4xl lg:text-5xl font-bold mb-4">{hero.headline || 'How Much Are You Losing Each Month?'}</h1> 106 <p className="text-xl text-white/90 max-w-2xl mx-auto">{hero.subheadline || ''}</p> 107 </div> 108 </section> 109 </EmbedLayout> 110 ); 111 } 112 113 if (only === 'results') { 114 const mockResults = calculate(); 115 return ( 116 <EmbedLayout embedKey="savings-calculator-results"> 117 <div className="bg-gray-50 py-12"> 118 <div className="max-w-2xl mx-auto px-4 space-y-6"> 119 <div className="bg-white rounded-2xl shadow-lg p-8"> 120 <h3 className="text-2xl font-bold text-gray-900 mb-6">{res.heading || "Here's What You Might Be Leaving on the Table..."}</h3> 121 <div className="space-y-4"> 122 <ResultCard icon={TrendingDown} label={res.loss_label || 'Monthly Revenue Loss'} sublabel={res.loss_sublabel} value={mockResults.currentDenialLoss} color="red" /> 123 <ResultCard icon={TrendingUp} label={res.savings_label || 'Potential Monthly Savings'} sublabel={res.savings_sublabel} value={mockResults.totalSavings} color="green" /> 124 <ResultCard icon={DollarSign} label={res.annual_label || 'Annual Savings Potential'} sublabel={res.annual_sublabel} value={mockResults.annualSavings} color="blue" /> 125 </div> 126 </div> 127 <div className="bg-white rounded-2xl shadow-lg p-8"> 128 <h4 className="text-lg font-semibold text-gray-900 mb-4">{res.how_we_calculate_heading || 'How We Calculate Your Savings'}</h4> 129 <div className="space-y-3 text-sm text-gray-600"> 130 <div className="flex items-center space-x-2"><CheckCircle className="w-4 h-4 text-green-500" /><span>Reduce denial rates to ~{assumptions.targetDenialRate}%</span></div> 131 <div className="flex items-center space-x-2"><CheckCircle className="w-4 h-4 text-green-500" /><span>Improve staff efficiency by {assumptions.efficiencyGain}%</span></div> 132 {(res.calculation_bullets ?? []).map((b: string, i: number) => ( 133 <div key={i} className="flex items-center space-x-2"><CheckCircle className="w-4 h-4 text-green-500" /><span>{b}</span></div> 134 ))} 135 </div> 136 </div> 137 <div className="bg-orange-50 border border-orange-200 rounded-lg p-4"> 138 <div className="flex items-start space-x-2"> 139 <AlertTriangle className="w-5 h-5 text-orange-600 mt-0.5 flex-shrink-0" /> 140 <div className="text-sm text-orange-800"><strong>Disclaimer:</strong> {res.disclaimer || 'This is a general estimate based on industry averages.'}</div> 141 </div> 142 </div> 143 </div> 144 </div> 145 </EmbedLayout> 146 ); 147 } 148 149 if (only === 'contact') { 150 return ( 151 <EmbedLayout embedKey="savings-calculator-contact"> 152 <div className="bg-gray-50 py-12"> 153 <div className="max-w-2xl mx-auto px-4"> 154 <div className="bg-white rounded-2xl shadow-lg p-8"> 155 <h2 className="text-2xl font-bold text-gray-900 mb-4 text-center">{contact.heading || 'Schedule Your Free Consultation'}</h2> 156 <p className="text-gray-600 text-center mb-8">{contact.description || "Let's discuss a customized solution for your practice."}</p> 157 <form onSubmit={(e) => { e.preventDefault(); alert('Thank you! We\\'ll contact you within 24 hours.'); }} className="space-y-4"> 158 <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> 159 <Field label="Full Name" required><input type="text" name="name" required value={formData.name} onChange={handleChange} className="field-input" /></Field> 160 <Field label="Email" required><input type="email" name="email" required value={formData.email} onChange={handleChange} className="field-input" /></Field> 161 </div> 162 <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> 163 <Field label="Phone" required><input type="tel" name="phone" required value={formData.phone} onChange={handleChange} className="field-input" /></Field> 164 <Field label="Preferred Time"> 165 <select name="preferredTime" value={formData.preferredTime} onChange={handleChange} className="field-input"> 166 <option value="">Select time</option> 167 {(contact.preferred_times ?? []).map((t: any) => <option key={t.value} value={t.value}>{t.label}</option>)} 168 </select> 169 </Field> 170 </div> 171 <button type="submit" className="w-full bg-gradient-to-r from-[#fdc010] to-[#e6ac0e] text-black px-6 py-4 rounded-lg font-semibold text-lg hover:from-[#e6ac0e] hover:to-[#cc9a0c] transition-all flex items-center justify-center space-x-2"> 172 <Calendar className="w-5 h-5" /><span>{contact.button_text || 'Schedule My Free Consultation'}</span> 173 </button> 174 </form> 175 <p className="text-sm text-gray-500 text-center mt-6">{contact.confirmation_message || ''}</p> 176 </div> 177 </div> 178 </div> 179 <style>{\`.field-input{width:100%;padding:0.625rem 0.75rem;border:1px solid #d1d5db;border-radius:0.5rem;font-size:0.875rem}.field-input:focus{outline:none;border-color:\${themeColor};
179box-shadow:0 0 0 2px \${themeColor}33}\`}</style> 180 </EmbedLayout> 181 ); 182 } 183 184 if (only === 'form') { 185 return ( 186 <EmbedLayout embedKey="savings-calculator-form"> 187 <div className="bg-gray-50 py-12"> 188 <div className="max-w-xl mx-auto px-4"> 189 <div className="bg-white rounded-2xl shadow-lg p-8"> 190 <h2 className="text-2xl font-bold text-gray-900 mb-6">{form.title || 'Revenue Loss Calculator'}</h2> 191 {!showResults ? ( 192 <form onSubmit={(e) => { e.preventDefault(); setShowResults(true); }} className="space-y-5"> 193 <Field label="Agency Type" required> 194 <select name="agencyType" required value={formData.agencyType} onChange={handleChange} className="field-input"> 195 <option value="">Select your agency type</option> 196 {agencyTypes.map((t: any) => <option key={t.value} value={t.value}>{t.label}</option>)} 197 </select> 198 </Field> 199 <Field label="State" required> 200 <select name="state" required value={formData.state} onChange={handleChange} className="field-input"> 201 <option value="">Select your state</option> 202 {STATES.map(s => <option key={s} value={s}>{s}</option>)} 203 </select> 204 </Field> 205 <div className="grid grid-cols-2 gap-4"> 206 <Field label="Monthly Claims" required> 207 <input type="number" name="monthlyClaims" required min="1" value={formData.monthlyClaims} onChange={handleChange} placeholder={form.claims_placeholder || '500'} className="field-input" /> 208 </Field> 209 <Field label="Avg Claim Value" required> 210 <div className="relative"> 211 <DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4" /> 212 <input type="number" name="averageClaimValue" required min="1" step="0.01" value={formData.averageClaimValue} onChange={handleChange} placeholder={form.claim_value_placeholder || '150.00'} className="field-input pl-9" /> 213 </div> 214 </Field> 215 </div> 216 <Field label="Current Denial Rate (%)" required hint={form.denial_rate_hint || 'Industry average is 5-15%'}> 217 <input type="number" name="denialRate" required min="0" max="100" step="0.1" value={formData.denialRate} onChange={handleChange} placeholder="8.5" className="field-input" /> 218 </Field> 219 <div className="grid grid-cols-2 gap-4"> 220 <Field label="Billing Model" required> 221 <select name="billingModel" required value={formData.billingModel} onChange={handleChange} className="field-input"> 222 <option value="">Select model</option> 223 {billingModels.map((m: any) => <option key={m.value} value={m.value}>{m.label}</option>)} 224 </select> 225 </Field> 226 <Field label="Use RCM Software?" required> 227 <select name="useRCMSoftware" required value={formData.useRCMSoftware} onChange={handleChange} className="field-input"> 228 <option value="">Select option</option> 229 {rcmOptions.map((o: any) => <option key={o.value} value={o.value}>{o.label}</option>)} 230 </select> 231 </Field> 232 </div> 233 <button type="submit" className="w-full bg-gradient-to-r from-[#fdc010] to-[#e6ac0e] text-black px-6 py-4 rounded-lg font-semibold text-lg hover:from-[#e6ac0e] hover:to-[#cc9a0c] transition-all transform hover:scale-105 shadow-lg"> 234 {form.button_text || 'Calculate My Potential Savings'} 235 </button> 236 </form> 237 ) : ( 238 <div className="space-y-4"> 239 <ResultCard icon={TrendingDown} label={res.loss_label || 'Monthly Revenue Loss'} sublabel={res.loss_sublabel} value={results!.currentDenialLoss} color="red" /> 240 <ResultCard icon={TrendingUp} label={res.savings_label || 'Potential Monthly Savings'} sublabel={res.savings_sublabel} value={results!.totalSavings} color="green" /> 241 <ResultCard icon={DollarSign} label={res.annual_label || 'Annual Savings Potential'} sublabel={res.annual_sublabel} value={results!.annualSavings} color="blue" /> 242 <button onClick={() => setShowResults(false)} className="text-sm text-gray-500 underline">Start over</button> 243 </div> 244 )} 245 </div> 246 </div> 247 </div> 248 <style>{\`.field-input{width:100%;padding:0.625rem 0.75rem;border:1px solid #d1d5db;border-radius:0.5rem;font-size:0.875rem}.field-input:focus{outline:none;border-color:\${themeColor};
248box-shadow:0 0 0 2px \${themeColor}33}\`}</style> 249 </EmbedLayout> 250 ); 251 } 252 253 return ( 254 <EmbedLayout embedKey="savings-calculator"> 255 <div className="min-h-screen bg-gray-50"> 256 <section className="text-white py-16" style={{ background: \`linear-gradient(135deg, \${themeColor}, \${adjustColor(themeColor, -30)})\` }}> 257 <div className="max-w-4xl mx-auto px-4 text-center"> 258 <div className="w-16 h-16 bg-[#fdc010] rounded-full flex items-center justify-center mx-auto mb-6"> 259 <Calculator className="w-8 h-8 text-black" /> 260 </div> 261 <h1 className="text-4xl lg:text-5xl font-bold mb-4">{hero.headline || 'How Much Are You Losing Each Month?'}</h1> 262 <p className="text-xl text-white/90 max-w-2xl mx-auto">{hero.subheadline || ''}</p> 263 </div> 264 </section> 265 266 <div className="max-w-4xl mx-auto px-4 py-12"> 267 {!showContactForm ? ( 268 <div className="grid grid-cols-1 lg:grid-cols-2 gap-12"> 269 <div className="bg-white rounded-2xl shadow-lg p-8"> 270 <h2 className="text-2xl font-bold text-gray-900 mb-6">{form.title || 'Revenue Loss Calculator'}</h2> 271 <form onSubmit={(e) => { e.preventDefault(); setShowResults(true); }} className="space-y-5"> 272 <Field label="Agency Type" required> 273 <select name="agencyType" required value={formData.agencyType} onChange={handleChange} className="field-input"> 274 <option value="">Select your agency type</option> 275 {agencyTypes.map((t: any) => <option key={t.value} value={t.value}>{t.label}</option>)} 276 </select> 277 </Field> 278 <Field label="State" required> 279 <select name="state" required value={formData.state} onChange={handleChange} className="field-input"> 280 <option value="">Select your state</option> 281 {STATES.map(s => <option key={s} value={s}>{s}</option>)} 282 </select> 283 </Field> 284 <div className="grid grid-cols-2 gap-4"> 285 <Field label="Monthly Claims" required> 286 <input type="number" name="monthlyClaims" required min="1" value={formData.monthlyClaims} onChange={handleChange} placeholder={form.claims_placeholder || '500'} className="field-input" /> 287 </Field> 288 <Field label="Avg Claim Value" required> 289 <div className="relative"> 290 <DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4" /> 291 <input type="number" name="averageClaimValue" required min="1" step="0.01" value={formData.averageClaimValue} onChange={handleChange} placeholder={form.claim_value_placeholder || '150.00'} className="field-input pl-9" /> 292 </div> 293 </Field> 294 </div> 295 <Field label="Current Denial Rate (%)" required hint={form.denial_rate_hint || 'Industry average is 5-15%'}> 296 <input type="number" name="denialRate" required min="0" max="100" step="0.1" value={formData.denialRate} onChange={handleChange} placeholder="8.5" className="field-input" /> 297 </Field> 298 <div className="grid grid-cols-2 gap-4"> 299 <Field label="Billing Model" required> 300 <select name="billingModel" required value={formData.billingModel} onChange={handleChange} className="field-input"> 301 <option value="">Select model</option> 302 {billingModels.map((m: any) => <option key={m.value} value={m.value}>{m.label}</option>)} 303 </select> 304 </Field> 305 <Field label="Use RCM Software?" required> 306 <select name="useRCMSoftware" required value={formData.useRCMSoftware} onChange={handleChange} className="field-input"> 307 <option value="">Select option</option> 308 {rcmOptions.map((o: any) => <option key={o.value} value={o.value}>{o.label}</option>)} 309 </select> 310 </Field> 311 </div> 312 <button type="submit" className="w-full bg-gradient-to-r from-[#fdc010] to-[#e6ac0e] text-black px-6 py-4 rounded-lg font-semibold text-lg hover:from-[#e6ac0e] hover:to-[#cc9a0c] transition-all transform hover:scale-105 shadow-lg"> 313 {form.button_text || 'Calculate My Potential Savings'} 314 </button> 315 </form> 316 </div> 317 318 <div className="space-y-6"> 319 {!showResults ? ( 320 <div className="bg-white rounded-2xl shadow-lg p-8 text-center"> 321 <div className="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4"> 322 <TrendingUp className="w-8 h-8 text-gray-400" /> 323 </div> 324 <h3 className="text-xl font-semibold text-gray-900 mb-2">Your Results Will Appear Here</h3> 325 <p className="text-gray-600">Fill out the form to see your potential savings with PMB's expert billing services.</p> 326 </div> 327 ) : ( 328 <div className="space-y-6"> 329 <div className="bg-white rounded-2xl shadow-lg p-8"> 330 <h3 className="text-2xl font-bold text-gray-900 mb-6">{res.heading || "Here's What You Might Be Leaving on the Table..."}</h3> 331 <div className="space-y-4"> 332 <ResultCard icon={TrendingDown} label={res.loss_label || 'Monthly Revenue Loss'} sublabel={res.loss_sublabel} value={results!.currentDenialLoss} color="red" /> 333 <ResultCard icon={TrendingUp} label={res.savings_label || 'Potential Monthly Savings'} sublabel={res.savings_sublabel} value={results!.totalSavings} color="green" /> 334 <ResultCard icon={DollarSign} label={res.annual_label || 'Annual Savings Potential'} sublabel={res.annual_sublabel} value={results!.annualSavings} color="blue" /> 335 </div> 336 </div> 337 338 <div className="bg-white rounded-2xl shadow-lg p-8"> 339 <h4 className="text-lg font-semibold text-gray-900 mb-4">{res.how_we_calculate_heading || 'How We Calculate Your Savings'}</h4> 340 <div className="space-y-3 text-sm text-gray-600"> 341 <div className="flex items-center space-x-2"><CheckCircle className="w-4 h-4 text-green-500" /><span>Reduce denial rates from {formData.denialRate}% to ~{assumptions.targetDenialRate}%</span></div> 342 <div className="flex items-center space-x-2"><CheckCircle className="w-4 h-4 text-green-500" /><span>Improve staff efficiency by {assumptions.efficiencyGain}%</span></div> 343 {(res.calculation_bullets ?? []).map((b: string, i: number) => ( 344 <div key={i} className="flex items-center space-x-2"><CheckCircle className="w-4 h-4 text-green-500" /><span>{b}</span></div> 345 ))} 346 </div> 347 </div> 348 349 <div className="text-white rounded-2xl p-8 text-center" style={{ background: \`linear-gradient(135deg, \${theme
349Color}, \${adjustColor(themeColor, -30)})\` }}> 350 <h4 className="text-xl font-bold mb-2">{res.cta_heading || 'Ready to Capture This Lost Revenue?'}</h4> 351 <p className="text-white/90 mb-6">{res.cta_description}</p> 352 <button onClick={() => setShowContactForm(true)} className="bg-gradient-to-r from-[#fdc010] to-[#e6ac0e] text-black px-8 py-3 rounded-lg font-semibold hover:from-[#e6ac0e] hover:to-[#cc9a0c] transition-all transform hover:scale-105 shadow-lg"> 353 {res.cta_button_text || 'Schedule a Free Consultation'} 354 </button> 355 </div> 356 </div> 357 )} 358 359 <div className="bg-orange-50 border border-orange-200 rounded-lg p-4"> 360 <div className="flex items-start space-x-2"> 361 <AlertTriangle className="w-5 h-5 text-orange-600 mt-0.5 flex-shrink-0" /> 362 <div className="text-sm text-orange-800"><strong>Disclaimer:</strong> {res.disclaimer || 'This is a general estimate based on industry averages.'}</div> 363 </div> 364 </div> 365 </div> 366 </div> 367 ) : ( 368 <div className="max-w-2xl mx-auto bg-white rounded-2xl shadow-lg p-8"> 369 <h2 className="text-2xl font-bold text-gray-900 mb-4 text-center">{contact.heading || 'Schedule Your Free Consultation'}</h2> 370 <p className="text-gray-600 text-center mb-8"> 371 Based on your potential savings of <strong>\${results?.totalSavings.toLocaleString()}/month</strong>, let's discuss a customized solution for your practice. 372 </p> 373 <form onSubmit={(e) => { e.preventDefault(); alert('Thank you! We\\'ll contact you within 24 hours.'); }} className="space-y-4"> 374 <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> 375 <Field label="Full Name" required><input type="text" name="name" required value={formData.name} onChange={handleChange} className="field-input" /></Field> 376 <Field label="Email" required><input type="email" name="email" required value={formData.email} onChange={handleChange} className="field-input" /></Field> 377 </div> 378 <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> 379 <Field label="Phone" required><input type="tel" name="phone" required value={formData.phone} onChange={handleChange} className="field-input" /></Field> 380 <Field label="Preferred Time"> 381 <select name="preferredTime" value={formData.preferredTime} onChange={handleChange} className="field-input"> 382 <option value="">Select time</option> 383 {(contact.preferred_times ?? []).map((t: any) => <option key={t.value} value={t.value}>{t.label}</option>)} 384 </select> 385 </Field> 386 </div> 387 <button type="submit" className="w-full bg-gradient-to-r from-[#fdc010] to-[#e6ac0e] text-black px-6 py-4 rounded-lg font-semibold text-lg hover:from-[#e6ac0e] hover:to-[#cc9a0c] transition-all flex items-center justify-center space-x-2"> 388 <Calendar className="w-5 h-5" /><span>{contact.button_text || 'Schedule My Free Consultation'}</span> 389 </button> 390 </form> 391 <p className="text-sm text-gray-500 text-center mt-6">{contact.confirmation_message || ''}</p> 392 </div> 393 )} 394 </div> 395 </div> 396 397 <style>{\` 398 .field-input { 399 width: 100%; 400 padding: 0.625rem 0.75rem; 401 border: 1px solid #d1d5db; 402 border-radius: 0.5rem; 403 font-size: 0.875rem; 404 transition: border-color 0.15s, box-shadow 0.15s; 405 } 406 .field-input:focus { 407 outline: none; 408 border-color: \${themeColor}; 409 box-shadow: 0 0 0 2px \${themeColor}33; 410 } 411 \`}</style> 412 </EmbedLayout> 413 ); 414}; 415 416function Field({ label, required, hint, children }: { label: string; required?: boolean; hint?: string; children: React.ReactNode }) { 417 return ( 418 <div> 419 <label className="block text-sm font-medium text-gray-700 mb-1">{label}{required && ' *'}</label> 420 {children} 421 {hint && <p className="text-xs text-gray-500 mt-1">{hint}</p>} 422 </div> 423 ); 424} 425 426function ResultCard({ icon: Icon, label, sublabel, value, color }: { icon: any; label: string; sublabel?: string; value: number; color: string }) { 427 const colors: Record<string, string> = { 428 red: 'bg-red-50 border-red-200 text-red-700', 429 green: 'bg-green-50 border-green-200 text-green-700', 430 blue: 'bg-blue-50 border-blue-200 text-blue-700', 431 }; 432 const valueColors: Record<string, string> = { red: 'text-red-600', green: 'text-green-600', blue: 'text-blue-600' }; 433 434 return ( 435 <div className={\`border rounded-lg p-4 \${colors[color]}\`}> 436 <div className="flex items-center space-x-2 mb-1"> 437 <Icon className="w-5 h-5" />
438 <span className="font-semibold text-sm">{label}</span> 439 </div> 440 <div className={\`text-3xl font-bold \${valueColors[color]}\`}>\${value.toLocaleString()}</div> 441 {sublabel && <p className="text-xs mt-1 opacity-80">{sublabel}</p>} 442 </div> 443 ); 444} 445 446function adjustColor(hex: string, amount: number): string { 447 const num = parseInt(hex.replace('#', ''), 16); 448 const r = Math.max(0, Math.min(255, ((num >> 16) & 0xff) + amount)); 449 const g = Math.max(0, Math.min(255, ((num >> 8) & 0xff) + amount)); 450 const b = Math.max(0, Math.min(255, (num & 0xff) + amount)); 451 return \`#\${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}\`; 452} 453 454export default SavingsCalculatorEmbed; 455`;export{e as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.