diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 0a57fb17..845b5ffa 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -19,7 +19,8 @@
"Bash(cargo clean:*)",
"Bash(awk:*)",
"WebFetch(domain:connectrpc.com)",
- "Bash(git log:*)"
+ "Bash(git log:*)",
+ "Bash(bunx tsc:*)"
],
"deny": [],
"ask": []
diff --git a/app/components/home/HomeKit.tsx b/app/components/home/HomeKit.tsx
index 300e8bda..679f64dc 100644
--- a/app/components/home/HomeKit.tsx
+++ b/app/components/home/HomeKit.tsx
@@ -17,6 +17,7 @@ import DictionaryContent from './contents/DictionaryContent'
import NotesContent from './contents/NotesContent'
import SettingsContent from './contents/SettingsContent'
import AboutContent from './contents/AboutContent'
+import { SubscriptionStatusWidget } from './SubscriptionStatusWidget'
export default function HomeKit() {
const { navExpanded, currentPage, setCurrentPage } = useMainStore()
@@ -231,6 +232,8 @@ export default function HomeKit() {
/>
+
+
{/* Main Content */}
diff --git a/app/components/home/SubscriptionStatusWidget.tsx b/app/components/home/SubscriptionStatusWidget.tsx
new file mode 100644
index 00000000..5589325f
--- /dev/null
+++ b/app/components/home/SubscriptionStatusWidget.tsx
@@ -0,0 +1,121 @@
+import useBillingState, {
+ BillingState,
+ ProStatus,
+} from '@/app/hooks/useBillingState'
+import { useMainStore } from '@/app/store/useMainStore'
+
+interface SubscriptionStatusWidgetProps {
+ wordsUsed?: number
+ navExpanded?: boolean
+}
+
+const FREE_TIER_WORD_LIMIT = 5000
+
+export function SubscriptionStatusWidget({
+ wordsUsed = 1000,
+ navExpanded = true,
+}: SubscriptionStatusWidgetProps) {
+ const billingState = useBillingState()
+ const { setCurrentPage, setSettingsPage } = useMainStore()
+
+ const handleUpgradeClick = () => {
+ setCurrentPage('settings')
+ setSettingsPage('pricing-billing')
+ }
+
+ // Common styles
+ const cardClassName =
+ 'w-full bg-white rounded-2xl border-2 border-neutral-100 shadow-sm p-2 space-y-1.5'
+ const progressBarContainerClassName =
+ 'w-full h-1.5 bg-neutral-200 rounded-full overflow-hidden'
+ const progressBarFillClassName =
+ 'h-full transition-all duration-300 bg-gradient-to-r'
+ const buttonBaseClassName =
+ 'w-full text-white px-4 py-2.5 rounded-md text-sm font-semibold hover:bg-gray-800 cursor-pointer transition-colors mt-4'
+
+ // Hide widget when sidebar is collapsed
+ if (!navExpanded) {
+ return null
+ }
+
+ // Hide widget for active Pro subscribers
+ if (billingState.proStatus === ProStatus.ACTIVE_PRO) {
+ return null
+ }
+
+ // Show trial status if user is on free trial
+ if (billingState.proStatus === ProStatus.FREE_TRIAL) {
+ const daysUsed = billingState.trialDays - billingState.daysLeft
+ const trialDays = billingState.trialDays || 1
+ const trialPercentage = Math.min(100, (daysUsed / trialDays) * 100)
+
+ return (
+
+ {/* Header */}
+
Pro Trial Active
+
+ {/* Progress bar */}
+
+
+ {/* Days remaining */}
+
+ {billingState.daysLeft} day{billingState.daysLeft !== 1 ? 's' : ''}{' '}
+ left on Ito Pro
+
+
+ {/* Upgrade button */}
+
+
+ )
+ }
+
+ // Show free tier status (Ito Starter)
+ const totalWords = FREE_TIER_WORD_LIMIT
+ const usagePercentage = Math.min(100, (wordsUsed / totalWords) * 100)
+
+ return (
+
+ {/* Header */}
+
Your plan
+
Ito Starter
+
+ {/* Progress bar */}
+
+
+ {/* Usage text */}
+
+ You've used{' '}
+
+ {wordsUsed.toLocaleString()} of {totalWords.toLocaleString()}
+ {' '}
+ words this week
+
+
+ {/* Upgrade button */}
+
+
+ )
+}