Walrus blob · mainnet
import { c as le, x as Me, b as Le, d as $e, i as Fe, r as n, j as e, X as Te, $ as ze, a as Ee, a0 as Be, D as Ye, y as De, k as Oe, L as We, z as _e, M as Je, Y as Ne, a1 as ve } from "./index-Cm465GGl.js";
import { C as Ve } from "./circle-alert-86Djp9hZ.js";
import { S as Ge } from "./save-BQDNXVgc.js";
import { R as Ke } from "./refresh-cw-jNuxS7sV.js";
import { T as He } from "./trash-2-DiVy2pHs.js";
import { N as P } from "./NumberField-D-mNULUc.js";
import { I as Ue } from "./info-Bn0rT5aa.js";
import { T as qe } from "./table-BDLqs792.js";
import { C as Se } from "./chevron-right-ts98H3uv.js";
/**
* @license lucide-react v0.469.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const Xe = le("Bookmark", [["path", { d: "m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z", key: "1fy3hk" }]]);
/**
* @license lucide-react v0.469.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const Qe = le("CreditCard", [["rect", { width: "20", height: "14", x: "2", y: "5", rx: "2", key: "ynyp8z" }], ["line", { x1: "2", x2: "22", y1: "10", y2: "10", key: "1b3vmo" }]]);
/**
* @license lucide-react v0.469.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const Ze = le("Rocket", [["path", { d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z", key: "m3kijz" }], ["path", { d: "m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z", key: "1fmvmk" }], ["path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0", key: "1f8sc4" }], ["path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5", key: "qeys4" }]]);
/**
* @license lucide-react v0.469.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const et = le("Target", [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }], ["circle", { cx: "12", cy: "12", r: "6", key: "1vlfrh" }], ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }]]);
function Z(t) {
const { principal: r, annualRate: a, years: i, bonusRatio: s, startBalance: c = r, startMonthIndex: N = 1, customMonthlyPayment: C, customBonusPayment: p } = t, g = i * 12, d = a / 100 / 12, l = a / 100 / 2, j = r * (s / 100), v = r - j;
let o = 0;
v > 0 && g > 0 && (o = d > 0 ? Math.floor(v * d * Math.pow(1 + d, g) / (Math.pow(1 + d, g) - 1)) : Math.floor(v / g));
let L = 0;
const w = i * 2;
j > 0 && w > 0 && (L = l > 0 ? Math.floor(j * l * Math.pow(1 + l, w) / (Math.pow(1 + l, w) - 1)) : Math.floor(j / w));
const h = C !== void 0 ? C : o, R = p !== void 0 ? p : L, x = [];
let m = c * (1 - s / 100), y = c * (s / 100), k = 0, A = 0, M = N;
const J = g * 2;
for (; m + y > 0 && A < J; ) {
const q = Math.floor((M - 1) / 12), X = (M - 1) % 12 + 1, V = X === 6 || X === 12;
let W = 0, Y = 0;
if (m > 0) {
const $ = Math.floor(m * d), Q = h - $, T = Math.min(Q, m);
m -= T, W += $, Y += T;
}
if (V && y > 0) {
const $ = Math.floor(y * l), Q = R - $, T = Math.min(Q, y);
y -= T, W += $, Y += T;
}
m < 0.01 && (m = 0), y < 0.01 && (y = 0);
const ee = m + y, F = Y + W;
(F > 0 || ee > 0) && (x.push({ monthIndex: M, year: q + 1, month: X, payment: F, principal: Y, interest: W, balance: ee, isBonusMonth: V }), k += W, A++), M++;
}
const U = c + k;
return { monthlyPayment: h, bonusPayment: R, totalPayment: U, totalInterest: k, interestRatio: U > 0 ? k / U * 100 : 0, yearlyPayment: h * 12 + R * 2, schedule: x, totalMonths: A };
}
function tt(t, r, a, i) {
const s = Z(t);
if (r >= s.schedule.length || s.schedule.length === 0) return { base: s, new: s, prepayEventRowIndex: -1 };
const c = s.schedule.findIndex((h) => h.monthIndex === r);
if (c === -1) return { base: s, new: s, prepayEventRowIndex: -1 };
const N = c > 0 ? Math.floor(s.schedule[c - 1].balance) : t.principal, C = Math.min(a, N), p = N - C, g = s.schedule.slice(0, c), d = g.reduce((h, R) => h + R.interest, 0);
let l;
if (p <= 0) l = { monthlyPayment: 0, bonusPayment: 0, totalPayment: 0, totalInterest: 0, interestRatio: 0, yearlyPayment: 0, schedule: [], totalMonths: 0 };
else if (i === "shorten") l = Z({ ...t, startBalance: p, startMonthIndex: r, customMonthlyPayment: s.monthlyPayment, customBonusPayment: s.bonusPayment });
else {
const R = (s.totalMonths - c) / 12;
l = Z({ ...t, principal: p, years: R, startBalance: p, startMonthIndex: r });
}
const j = { monthIndex: r, year: Math.floor((r - 1) / 12) + 1, month: (r - 1) % 12 + 1, payment: C, principal: C, interest: 0, balance: p, isBonusMonth: false }, v = [...g, j, ...l.schedule], o = d + l.totalInterest, L = t.principal + o, w = { monthlyPayment: l.monthlyPayment || s.monthlyPayment, bonusPayment: l.bonusPayment || s.bonusPayment, totalPayment: L, totalInterest: o, interestRatio: o / L * 100, yearlyPayment: l.yearlyPayment || s.yearlyPayment, schedule: v, totalMonths: v.length, savedInterest: Math.max(0, s.totalInterest - o), shortenedMonths: Math.max(0, s.totalMonths - v.length + 1) };
return { base: s, new: w, prepayEventRowIndex: c };
}
function at(t, r, a, i, s) {
const c = Z(t), N = c.schedule.findIndex((w) => w.monthIndex === r);
if (N === -1 || N >= c.schedule.length) return { base: c, new: c, savedInterest: 0 };
const C = N > 0 ? c.schedule[N - 1].balance : t.principal, p = c.schedule.slice(0, N), g = p.reduce((w, h) => w + h.interest, 0), d = C + s, l = Z({ principal: d, annualRate: a, years: i, bonusRatio: 0, startMonthIndex: r }), j = [...p, ...l.schedule], v = g + l.totalInterest, o = t.principal - C + l.totalPayment, L = { monthlyPayment: l.monthlyPayment, bonusPayment: 0, totalPayment: o, totalInterest: v + s, interestRatio: (v + s) / o * 100, yearlyPayment: l.yearlyPayment, schedule: j, totalMonths: j.length };
return { base: c, new: L, savedInterest: c.totalPayment - o };
}
const we = "loan_scenarios", Ce = "loan_scenarios_v1", st = 2160 * 60 * 60 * 1e3, rt = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 9);
function nt() {
try {
const t = localStorage.getItem(Me(Ce));
if (!t) return [];
const r = JSON.parse(t);
return Array.isArray(r) ? he(r) : [];
} catch {
return [];
}
}
function lt(t) {
try {
localStorage.setItem(Me(Ce), JSON.stringify(t));
} catch {
}
}
function me(t) {
if (typeof t.updatedAtMs == "number" && Number.isFinite(t.updatedAtMs)) return t;
const r = t.createdAt ? Date.parse(t.createdAt) : 0;
return { ...t, updatedAtMs: Number.isFinite(r) ? r : 0 };
}
function he(t, r = Date.now()) {
return t.filter((a) => a && typeof a.id == "string").map(me).filter((a) => !a.deleted || r - (a.deletedAtMs ?? r) < st);
}
function ot(t, r) {
const a = /* @__PURE__ */ new Map();
for (const i of t) a.set(i.id, me(i));
for (const i of r) {
const s = me(i), c = a.get(s.id);
(!c || (s.updatedAtMs ?? 0) > (c.updatedAtMs ?? 0)) && a.set(s.id, s);
}
return he([...a.values()]);
}
function ne(t) {
return JSON.stringify([...t].sort((r, a) => r.id < a.id ? -1 : r.id > a.id ? 1 : 0));
}
function it() {
const { currentUserAddress: t } = Le(), { syncToWalrus: r } = $e(), { restoreNamespace: a } = Fe(), [i, s] = n.useState(() => nt()), [c, N] = n.useState("idle"), [C, p] = n.useState(null), g = n.useRef(i);
g.current = i, n.useEffect(() => {
lt(i);
}, [i]);
const d = n.useRef({ count: 0, timer: null }), l = n.useCallback(async (x) => {
if (t) {
N("syncing");
try {
const m = { version: 1, scenarios: x, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
await r({ payload: m, appNamespace: we }), N("synced"), p(Date.now()), d.current.count = 0, d.current.timer && (window.clearTimeout(d.current.timer), d.current.timer = null);
} catch (m) {
if (N("error"), console.warn("[loan] sync failed", m), d.current.timer && window.clearTimeout(d.current.timer), d.current.count < 3) {
const y = 3e4 * 2 ** d.current.count;
d.current.count += 1, d.current.timer = window.setTimeout(() => {
j.current(g.current);
}, y);
}
}
}
}, [t, r]), j = n.useRef(l);
j.current = l;
const v = n.useCallback(async () => {
if (t) try {
const x = await a(we);
if (!x || !Array.isArray(x.scenarios)) {
g.current.filter((A) => !A.deleted).length > 0 && l(g.current);
return;
}
const m = g.current, y = ot(m, x.scenarios), k = he(x.scenarios);
ne(y) !== ne(m) && s(y), ne(y) !== ne(k) && l(y);
} catch (x) {
console.warn("[loan] restore failed", x);
}
}, [t, a, l]), o = n.useRef(v);
o.current = v, n.useEffect(() => {
if (!t) return;
o.current();
const x = () => {
document.hidden || o.current();
};
return window.addEventListener("focus", x), document.addEventListener("visibilitychange", x), () => {
window.removeEventListener("focus", x), document.removeEventListener("visibilitychange", x);
};
}, [t]);
const L = n.useCallback((x, m) => {
const y = Date.now(), k = { id: rt(), name: x.trim() || "\u7121\u984C\u306E\u30B7\u30CA\u30EA\u30AA", createdAt: (/* @__PURE__ */ new Date()).toISOString(), updatedAtMs: y, params: m }, A = [k, ...g.current];
return s(A), l(A), k.id;
}, [l]), w = n.useCallback((x, m, y) => {
const k = Date.now(), A = g.current.map((M) => M.id === x ? { ...M, params: m, name: (y == null ? void 0 : y.trim()) || M.name, updatedAtMs: k } : M);
s(A), l(A);
}, [l]), h = n.useCallback((x) => {
const m = Date.now(), y = g.current.map((k) => k.id === x ? { ...k, deleted: true, deletedAtMs: m, updatedAtMs: m } : k);
s(y), l(y);
}, [l]);
return { scenarios: i.filter((x) => !x.deleted).sort((x, m) => m.updatedAtMs - x.updatedAtMs), saveScenario: L, updateScenario: w, removeScenario: h, isLoggedIn: !!t, syncPhase: c, lastSyncedAt: C };
}
const ct = (t) => new Intl.NumberFormat("ja-JP").format(Math.round(t));
function dt({ isOpen: t, onClose: r, scenarios: a, defaultName: i, onSave: s, onUpdate: c, onDelete: N, onLoad: C, isLoggedIn: p, syncPhase: g, lastSyncedAt: d }) {
const [l, j] = n.useState("");
if (!t) return null;
const v = () => {
s(l.trim() || i), j("");
};
return e.jsx("div", { className: "fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/40 backdrop-blur-sm", onClick: r, children: e.jsxs("div", { className: "bg-white dark:bg-gray-900 w-full sm:max-w-lg sm:rounded-2xl rounded-t-2xl shadow-2xl border border-gray-200 dark:border-gray-800 max-h-[88vh] flex flex-col", onClick: (o) => o.stopPropagation(), children: [e.jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-100 dark:border-gray-800", children: [e.jsx("h2", { className: "text-lg font-bold text-gray-900 dark:text-gray-100", children: "\u6761\u4EF6\u306E\u4FDD\u5B58\u30FB\u547C\u3073\u51FA\u3057" }), e.jsx("button", { onClick: r, className: "p-1.5 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors", children: e.jsx(Te, { size: 20 }) })] }), e.jsx("div", { className: "px-5 pt-3", children: p ? e.jsx("div", { className: "flex items-center gap-1.5 text-[12px] font-medium", children: g === "syncing" ? e.jsxs("span", { className: "flex items-center gap-1 text-blue-600 dark:text-blue-300", children: [e.jsx(Ee, { size: 13, className: "animate-spin" }), " \u540C\u671F\u4E2D\u2026"] }) : g === "error" ? e.jsxs("span", { className: "flex items-center gap-1 text-red-500", children: [e.jsx(Ve, { size: 13 }), " \u540C\u671F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF08\u6B21\u56DE\u518D\u8A66\u884C\uFF09"] }) : e.jsxs("span", { className: "flex items-center gap-1 text-emerald-600 dark:text-emerald-400", title: d ? `\u6700\u7D42\u540C\u671F: ${new Date(d).toLocaleTimeString("ja-JP")}` : "", children: [e.jsx(Be, { size: 13 }), " \u7AEF\u672B\u9593\u3067\u540C\u671F\u4E2D"] }) }) : e.jsxs("div", { className: "flex items-start gap-2 text-[12px] text-gray-500 dark:text-gray-400 bg-gray-50 dark:bg-gray-800/50 rounded-lg px-3 py-2", children: [e.jsx(ze, { size: 15, className: "mt-0.5 shrink-0" }), e.jsxs("span", { children: ["\u672A\u30ED\u30B0\u30A4\u30F3\uFF1A\u3053\u306E\u7AEF\u672B\u306B\u306E\u307F\u4FDD\u5B58\u3055\u308C\u307E\u3059\u3002", e.jsx("br", { className: "hidden sm:block" }), "\u4ED6\u306E\u7AEF\u672B\u3068\u540C\u671F\u3059\u308B\u306B\u306F\u3001\u30DB\u30FC\u30E0\u304B\u3089\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044\u3002"] })] }) }), e.jsxs("div", { className: "px-5 py-3", children: [e.jsxs("div", { className: "flex items-center gap-2", children: [e.jsx("input", { type: "text", value: l, onChange: (o) => j(o.target.value), onKeyDown: (o) => o.key === "Enter" && v(), placeholder: i, className: "flex-1 text-[15px] bg-gray-50 dark:bg-gray-800 rounded-lg px-3 py-2.5 text-gray-900 dark:text-gray-100 placeholder:text-gray-400 outline-none focus:ring-2 focus:ring-blue-500/40" }), e.jsxs("button", { onClick: v, className: "flex items-center gap-1.5 px-4 py-2.5 bg-blue-500 text-white rounded-lg font-semibold text-[15px] active:bg-blue-600 transition-colors shrink-0", children: [e.jsx(Ge, { size: 16 }), " \u4FDD\u5B58"] })] }), e.jsx("p", { className: "text-[11px] text-gray-400 mt-1.5 px-0.5", children: "\u73FE\u5728\u306E\u5165\u529B\u6761\u4EF6\uFF08\u57FA\u672C\u30FB\u7E70\u4E0A\u30FB\u501F\u63DB\u30FB\u53CE\u652F\uFF09\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002" })] }), e.jsx("div", { className: "flex-1 overflow-y-auto px-5 pb-2 min-h-[80px]", children: a.length === 0 ? e.jsx("p", { className: "text-center text-sm text-gray-400 dark:text-gray-500 py-8", children: "\u4FDD\u5B58\u3055\u308C\u305F\u6761\u4EF6\u306F\u307E\u3060\u3042\u308A\u307E\u305B\u3093" }) : e.jsx("div", { className: "space-y-2", children: a.map((o) => e.jsx("div", { className: "border border-gray-200 dark:border-gray-700 rounded-xl p-3 bg-white dark:bg-gray-800/40", children: e.jsxs("div", { className: "flex items-start justify-between gap-2", children: [e.jsxs("div", { className: "min-w-0 flex-1", children: [e.jsx("div", { className: "font-semibold text-[15px] text-gray-900 dark:text-gray-100 truncate", children: o.name }), e.jsxs("div", { className: "text-[12px] text-gray-500 dark:text-gray-400 mt-0.5", children: ["\u501F\u5165 \xA5", ct(o.params.loanAmount), " / ", o.params.interestRate, "% / ", o.params.loanTermYears, "\u5E74"] }), e.jsx("div", { className: "text-[10px] text-gray-400 mt-0.5", children: new Date(o.updatedAtMs).toLocaleString("ja-JP", { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit" }) })] }), e.jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [e.jsxs("button", { onClick: () => {
C(o), r();
}, title: "\u3053\u306E\u6761\u4EF6\u3092\u8AAD\u307F\u8FBC\u3080", className: "flex items-center gap-1 px-2.5 py-1.5 rounded-lg bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-300 text-[13px] font-medium active:scale-95 transition-transform", children: [e.jsx(Ye, { size: 14 }), " \u547C\u51FA"] }), e.jsx("button", { onClick: () => c(o.id, o.name), title: "\u73FE\u5728\u306E\u5165\u529B\u3067\u4E0A\u66F8\u304D\u4FDD\u5B58", className: "p-1.5 rounded-lg text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700", children: e.jsx(Ke, { size: 15 }) }), e.jsx("button", { onClick: () => N(o.id), title: "\u524A\u9664", className: "p-1.5 rounded-lg text-gray-300 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20", children: e.jsx(He, { size: 15 }) })] })] }) }, o.id)) }) }), e.jsx("div", { className: "px-5 py-3 border-t border-gray-100 dark:border-gray-800", children: e.jsx("p", { className: "text-[10.5px] leading-relaxed text-gray-400 dark:text-gray-500", children: "\u203B \u8A08\u7B97\u7D50\u679C\u30FB\u4FDD\u5B58\u5185\u5BB9\u306F\u6982\u7B97\u3067\u3042\u308A\u3001\u6B63\u78BA\u6027\u30FB\u6700\u65B0\u6027\u3092\u4FDD\u8A3C\u3059\u308B\u3082\u306E\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u91D1\u878D\u30FB\u7A0E\u52D9\u30FB\u6CD5\u5F8B\u4E0A\u306E\u52A9\u8A00\u3067\u306F\u306A\u304F\u3001\u5B9F\u969B\u306E\u501F\u5165\u6761\u4EF6\u306F\u91D1\u878D\u6A5F\u95A2\u30FB\u5C02\u9580\u5BB6\u306B\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002\u4FDD\u5B58\u30C7\u30FC\u30BF\u306F\u7AEF\u672B\u5074\u3067\u6697\u53F7\u5316\u306E\u3046\u3048\u4FDD\u5B58\u3055\u308C\u3001\u305D\u306E\u7BA1\u7406\u306F\u5229\u7528\u8005\u3054\u81EA\u8EAB\u306E\u8CAC\u4EFB\u3068\u306A\u308A\u307E\u3059\u3002\u672C\u30C4\u30FC\u30EB\u306E\u5229\u7528\u306B\u3088\u308A\u751F\u3058\u305F\u3044\u304B\u306A\u308B\u640D\u5BB3\u306B\u3064\u3044\u3066\u3082\u63D0\u4F9B\u8005\u306F\u8CAC\u4EFB\u3092\u8CA0\u3044\u307E\u305B\u3093\uFF08\u8A73\u7D30\u306F\u5229\u7528\u898F\u7D04\u3092\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\uFF09\u3002" }) })] }) });
}
const B = ({ title: t, children: r, className: a = "" }) => e.jsxs("div", { className: `mb-6 ${a}`, children: [t && e.jsx("h2", { className: "px-4 mb-2 text-xs font-semibold text-gray-500 uppercase tracking-wider", children: t }), e.jsx("div", { className: "bg-white dark:bg-gray-900 border-y sm:border-x sm:rounded-xl border-gray-200 dark:border-gray-800 overflow-hidden", children: e.jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-800 ml-4", children: r }) })] }), S = ({ label: t, value: r, input: a, hasArrow: i = true, valueColor: s = "text-gray-500 dark:text-gray-400", onClick: c }) => e.jsxs("div", { className: `flex justify-between items-center py-3 pr-4 bg-white dark:bg-gray-900 min-h-[44px] ${c ? "cursor-pointer active:bg-gray-50 dark:active:bg-gray-800 transition-colors" : ""}`, onClick: c, children: [e.jsx("label", { className: "text-[17px] text-gray-900 dark:text-gray-100 whitespace-nowrap mr-4", children: t }), e.jsxs("div", { className: "flex items-center flex-1 justify-end", children: [a || e.jsx("span", { className: `text-[17px] ${s} truncate`, children: r }), i && !a && e.jsx(Se, { size: 20, className: "ml-2 text-gray-300 dark:text-gray-600 flex-shrink-0" })] })] }), xe = ({ options: t, selected: r, onChange: a }) => e.jsx("div", { className: "flex p-1 bg-gray-200 dark:bg-gray-800 rounded-lg mx-4 mb-4", children: t.map((i) => e.jsxs("button", { onClick: () => a(i.id), className: `flex-1 py-1.5 text-sm font-medium rounded-md transition-all flex items-center justify-center gap-1.5 ${r === i.id ? "bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm" : "text-gray-500 hover:text-gray-700 dark:text-gray-400"}`, children: [i.icon && e.jsx(i.icon, { size: 16 }), i.label] }, i.id)) }), b = (t) => new Intl.NumberFormat("ja-JP").format(Math.round(t));
function jt() {
const { theme: t, toggleTheme: r } = De(), [a, i] = n.useState("conditions"), [s, c] = n.useState("summary"), [N, C] = n.useState("prepay"), [p, g] = n.useState(3e7), [d, l] = n.useState(1.45), [j, v] = n.useState(35), [o, L] = n.useState(0), w = n.useMemo(() => ({ principal: p, annualRate: d, years: j, bonusRatio: o }), [p, d, j, o]), h = n.useMemo(() => Z(w), [w]), [R, x] = n.useState(10), [m, y] = n.useState(5e6), [k, A] = n.useState("shorten"), M = n.useMemo(() => tt(w, R * 12, m, k), [w, R, m, k]), [J, U] = n.useState(10), [q, X] = n.useState(0.8), [V, W] = n.useState(25), [Y, ee] = n.useState(5e5), F = n.useMemo(() => at(w, J * 12, q, V, Y), [w, J, q, V, Y]), [$, Q] = n.useState(0), [T, ue] = n.useState(0), [te, pe] = n.useState(0), [D, oe] = n.useState("rate"), [ae, se] = n.useState(5), [re, ge] = n.useState(0), _ = it(), [Pe, ye] = n.useState(false), be = () => ({ loanAmount: p, interestRate: d, loanTermYears: j, bonusRatio: o, prepayYear: R, prepayAmount: m, prepayType: k, refiYear: J, refiNewRate: q, refiNewYears: V, refiFee: Y, rent: $, mngFee: T, resFee: te, pmFeeMode: D, pmFeeInput: ae, taxYearly: re }), Ae = (f) => {
const u = f.params;
g(u.loanAmount), l(u.interestRate), v(u.loanTermYears), L(u.bonusRatio), x(u.prepayYear), y(u.prepayAmount), A(u.prepayType), U(u.refiYear), X(u.refiNewRate), W(u.refiNewYears), ee(u.refiFee), Q(u.rent), ue(u.mngFee), pe(u.resFee), oe(u.pmFeeMode), se(u.pmFeeInput), ge(u.taxYearly);
}, Re = `\u501F\u5165${b(p)}\u5186\u30FB${d}%\u30FB${j}\u5E74`, z = n.useMemo(() => {
const f = h.monthlyPayment + h.bonusPayment * 2 / 12, u = Math.floor(D === "rate" ? $ * (ae / 100) * 1.1 : ae), G = Math.floor(re / 12), K = f + T + te + u + G, O = Math.floor($ - K), I = O * 12;
return { monthlyLoanPayment: Math.floor(f), pmFeeActual: u, taxMonthly: G, monthlyExpense: Math.floor(K), monthlyCf: O, annualCf: I };
}, [h, $, T, te, D, ae, re]);
n.useEffect(() => {
t === "dark" ? document.documentElement.classList.add("dark") : document.documentElement.classList.remove("dark");
}, [t]);
const fe = e.jsxs("div", { className: "animate-in fade-in duration-300", children: [e.jsx("div", { className: "px-4 py-4 md:py-2", children: e.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "\u57FA\u672C\u9805\u76EE\u3092\u8A2D\u5B9A\u3059\u308B\u3060\u3051\u3067\u8A66\u7B97\u30FB\u6BD4\u8F03\u304C\u3067\u304D\u307E\u3059\u3002" }) }), e.jsxs(B, { title: "\u57FA\u672C\u6761\u4EF6", children: [e.jsx(S, { label: "\u501F\u5165\u91D1\u984D\u5408\u8A08", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: p, onChange: g, group: true, placeholder: "30,000,000", ariaLabel: "\u501F\u5165\u91D1\u984D\u5408\u8A08", className: "w-36 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "\u5186" })] }), hasArrow: false }), e.jsx(S, { label: "\u91D1\u5229 (\u56FA\u5B9A)", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: d, onChange: l, decimals: true, placeholder: "1.45", ariaLabel: "\u91D1\u5229", className: "w-20 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "%" })] }), hasArrow: false }), e.jsx(S, { label: "\u671F\u9593", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: j, onChange: v, min: 1, max: 50, placeholder: "35", ariaLabel: "\u671F\u9593\uFF08\u5E74\uFF09", className: "w-16 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsxs("span", { className: "ml-1 text-[17px] text-gray-400 whitespace-nowrap", children: ["\u5E74 (", j * 12, "\u56DE)"] })] }), hasArrow: false })] }), e.jsx(B, { title: "\u8A73\u7D30\u8A2D\u5B9A", children: e.jsx(S, { label: "\u30DC\u30FC\u30CA\u30B9\u8FD4\u6E08\u5272\u5408", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: o, onChange: L, min: 0, max: 50, placeholder: "0", ariaLabel: "\u30DC\u30FC\u30CA\u30B9\u8FD4\u6E08\u5272\u5408", className: "w-16 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "%" })] }), hasArrow: false }) }), e.jsx("div", { className: "px-4 mt-4 mb-2", children: e.jsx("p", { className: "text-[11px] leading-relaxed text-gray-400 dark:text-gray-500", children: "\u203B \u8A08\u7B97\u7D50\u679C\u306F\u6982\u7B97\uFF08\u53C2\u8003\u5024\uFF09\u3067\u3059\u3002\u91D1\u878D\u30FB\u7A0E\u52D9\u30FB\u6CD5\u5F8B\u4E0A\u306E\u52A9\u8A00\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u5B9F\u969B\u306E\u501F\u5165\u6761\u4EF6\u30FB\u91D1\u5229\u30FB\u7A0E\u984D\u7B49\u306F\u91D1\u878D\u6A5F\u95A2\u3084\u5C02\u9580\u5BB6\u306B\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002\u672C\u30C4\u30FC\u30EB\u306E\u5229\u7528\u306B\u3088\u308A\u751F\u3058\u305F\u640D\u5BB3\u306B\u3064\u3044\u3066\u63D0\u4F9B\u8005\u306F\u8CAC\u4EFB\u3092\u8CA0\u3044\u307E\u305B\u3093\u3002" }) }), e.jsx("div", { className: "px-4 mt-4 mb-6 md:hidden", children: e.jsx("button", { onClick: () => i("results"), className: "w-full py-3.5 bg-blue-500 text-white rounded-xl font-semibold text-[17px] active:bg-blue-600 transition-colors shadow-sm", children: "\u8A66\u7B97\u7D50\u679C\u3092\u898B\u308B" }) })] }), ie = (f, u, G) => {
const K = f.schedule, O = u == null ? void 0 : u.schedule, I = Math.max(f.totalMonths, (u == null ? void 0 : u.totalMonths) || 0);
return I === 0 ? null : e.jsxs("div", { className: "p-4", children: [e.jsxs("div", { className: "h-64 w-full relative", children: [e.jsxs("svg", { viewBox: "0 0 100 100", preserveAspectRatio: "none", className: "w-full h-full overflow-visible", children: [e.jsxs("defs", { children: [e.jsxs("linearGradient", { id: "baseFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [e.jsx("stop", { offset: "0%", stopColor: "#9ca3af", stopOpacity: "0.4" }), e.jsx("stop", { offset: "100%", stopColor: "#9ca3af", stopOpacity: "0.0" })] }), e.jsxs("linearGradient", { id: "newFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [e.jsx("stop", { offset: "0%", stopColor: "#3b82f6", stopOpacity: "0.5" }), e.jsx("stop", { offset: "100%", stopColor: "#3b82f6", stopOpacity: "0.1" })] })] }), [0, 25, 50, 75, 100].map((E) => e.jsx("line", { x1: "0", y1: E, x2: "100", y2: E, stroke: "currentColor", strokeWidth: "0.5", className: "text-gray-200 dark:text-gray-800" }, `grid-${E}`)), K.length > 0 && e.jsx("polygon", { fill: "url(#baseFill)", points: `0,100 ${K.map((E, H) => {
const ce = H / I * 100, de = 100 - E.balance / p * 100;
return `${ce},${de}`;
}).join(" ")} ${(K.length - 1) / I * 100},100` }), e.jsx("polyline", { fill: "none", stroke: "#9ca3af", strokeWidth: "1.5", strokeDasharray: u ? "4,4" : "0", points: K.map((E, H) => `${H / I * 100},${100 - Math.max(0, E.balance / p * 100)}`).join(" ") }), O && O.length > 0 && e.jsx("polygon", { fill: "url(#newFill)", points: `0,100 ${O.map((E, H) => {
const ce = H / I * 100, de = 100 - E.balance / p * 100;
return `${ce},${de}`;
}).join(" ")} ${(O.length - 1) / I * 100},100` }), O && e.jsx("polyline", { fill: "none", stroke: "#3b82f6", strokeWidth: "2.5", points: O.map((E, H) => `${H / I * 100},${100 - Math.max(0, E.balance / p * 100)}`).join(" ") }), G !== void 0 && G > 0 && e.jsx("line", { x1: G / I * 100, y1: "0", x2: G / I * 100, y2: "100", stroke: "#f59e0b", strokeWidth: "1.5", strokeDasharray: "3,3" })] }), e.jsxs("div", { className: "flex justify-between text-[10px] text-gray-400 mt-2 border-t border-gray-200 dark:border-gray-800 pt-1", children: [e.jsx("span", { children: "\u958B\u59CB" }), e.jsxs("span", { children: [Math.floor(I / 2 / 12), "\u5E74"] }), e.jsxs("span", { children: [Math.ceil(I / 12), "\u5E74"] })] })] }), e.jsxs("div", { className: "flex justify-center space-x-6 mt-6", children: [e.jsxs("div", { className: "flex items-center", children: [e.jsx("div", { className: "w-4 h-1 bg-gray-400 mr-2 rounded" }), e.jsx("span", { className: "text-xs text-gray-500", children: "\u57FA\u672C\u30D7\u30E9\u30F3" })] }), u && e.jsxs("div", { className: "flex items-center", children: [e.jsx("div", { className: "w-4 h-1 bg-blue-500 mr-2 rounded" }), e.jsx("span", { className: "text-xs font-medium text-gray-900 dark:text-gray-100", children: "\u65B0\u30D7\u30E9\u30F3\u60F3\u5B9A" })] })] })] });
}, Ie = e.jsxs("div", { className: "animate-in fade-in", children: [e.jsxs(B, { title: "\u53CE\u652F\u30B7\u30DF\u30E5\u30EC\u30FC\u30B7\u30E7\u30F3\uFF08\u4E0D\u52D5\u7523\u6295\u8CC7\uFF09", children: [e.jsx(S, { label: "\u8CC3\u6599\u53CE\u5165\uFF08\u6708\u984D\uFF09", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: $, onChange: Q, group: true, placeholder: "100,000", ariaLabel: "\u8CC3\u6599\u53CE\u5165\uFF08\u6708\u984D\uFF09", className: "w-28 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "\u5186" })] }), hasArrow: false }), e.jsx(S, { label: "\u7BA1\u7406\u8CBB\uFF08\u6708\u984D\uFF09", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: T, onChange: ue, group: true, placeholder: "10,000", ariaLabel: "\u7BA1\u7406\u8CBB\uFF08\u6708\u984D\uFF09", className: "w-28 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "\u5186" })] }), hasArrow: false }), e.jsx(S, { label: "\u4FEE\u7E55\u7A4D\u7ACB\u91D1\uFF08\u6708\u984D\uFF09", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: te, onChange: pe, group: true, placeholder: "5,000", ariaLabel: "\u4FEE\u7E55\u7A4D\u7ACB\u91D1\uFF08\u6708\u984D\uFF09", className: "w-28 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "\u5186" })] }), hasArrow: false }), e.jsxs("div", { className: "py-3 pr-4 bg-white dark:bg-gray-900", children: [e.jsx("div", { className: "flex justify-between items-center mb-2", children: e.jsx("label", { className: "text-[17px] text-gray-900 dark:text-gray-100", children: "\u8CC3\u8CB8\u7BA1\u7406Fee\uFF08\u6708\u984D\uFF09" }) }), e.jsxs("div", { className: "flex items-center gap-3 justify-end", children: [e.jsxs("div", { className: "flex p-0.5 bg-gray-200 dark:bg-gray-800 rounded-lg", children: [e.jsx("button", { onClick: () => {
oe("rate"), se(5);
}, className: `px-3 py-1 text-xs font-medium rounded-md transition-all ${D === "rate" ? "bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm" : "text-gray-500"}`, children: "\u7387 (%)" }), e.jsx("button", { onClick: () => {
oe("amount"), se(0);
}, className: `px-3 py-1 text-xs font-medium rounded-md transition-all ${D === "amount" ? "bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm" : "text-gray-500"}`, children: "\u5B9F\u984D (\u5186)" })] }), e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: ae, onChange: se, group: D === "amount", decimals: D === "rate", placeholder: D === "rate" ? "5" : "5,000", ariaLabel: "\u8CC3\u8CB8\u7BA1\u7406Fee\uFF08\u6708\u984D\uFF09", className: "w-20 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: D === "rate" ? "%" : "\u5186" })] })] }), D === "rate" && $ > 0 && e.jsxs("p", { className: "text-[11px] text-gray-400 dark:text-gray-500 text-right mt-1 pr-0", children: ["\u5B9F\u984D: \xA5", b(z.pmFeeActual), "/\u6708\uFF08\u6D88\u8CBB\u7A0E\u8FBC\uFF09"] })] }), e.jsx(S, { label: "\u56FA\u90FD\u7A0E\uFF08\u5E74\u984D\uFF09", input: e.jsxs("div", { className: "flex items-center", children: [e.jsx(P, { value: re, onChange: ge, group: true, placeholder: "60,000", ariaLabel: "\u56FA\u90FD\u7A0E\uFF08\u5E74\u984D\uFF09", className: "w-28 text-right bg-transparent border-none p-0 focus:ring-0 text-[17px] text-blue-500 font-medium outline-none placeholder-gray-300 dark:placeholder-gray-600" }), e.jsx("span", { className: "ml-1 text-[17px] text-gray-400", children: "\u5186" })] }), hasArrow: false })] }), e.jsxs(B, { title: "\u30AD\u30E3\u30C3\u30B7\u30E5\u30D5\u30ED\u30FC\u8A66\u7B97\u7D50\u679C", children: [e.jsxs("div", { className: "px-4 py-5 border-b border-gray-100 dark:border-gray-800", children: [e.jsx("div", { className: "text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1", children: "\u6708\u3005\u53CE\u652F" }), e.jsxs("div", { className: `text-4xl font-bold tracking-tight ${z.monthlyCf < 0 ? "text-rose-500" : "text-emerald-600 dark:text-emerald-400"}`, children: [z.monthlyCf < 0 ? "\u2212" : "+", "\xA5", b(Math.abs(z.monthlyCf))] })] }), e.jsxs("div", { className: "px-4 py-4 border-b border-gray-100 dark:border-gray-800 flex justify-between items-center", children: [e.jsx("span", { className: "text-[15px] text-gray-600 dark:text-gray-300", children: "\u5E74\u9593\u53CE\On-chain registration not yet visible.
The aggregator served this blob, but we couldn't locate a matching BlobRegistered event in our scan window. It may not be certified yet, or live further back than we paged.
Lifecycle data is unavailable until the blob registration is visible on-chain.