{detailModel.description}
@@ -121,7 +122,13 @@ export function ModelsVisual() {
- Permanently delete your ThinkEx account. Every workspace you own will also be deleted, - including all items and files inside them. This action cannot be undone. -
-{children}
; +} + +// Gain-framed on purpose: naming what Pro includes converts better than telling +// someone a limit was reached. +function UpgradeLink({ children }: { children: React.ReactNode }) { + return ( + ) => ({ + ...previous, + settings: "plan" as const, + })} + className="font-medium text-foreground underline underline-offset-4" + > + {children} + + ); +} + +function formatResetDate(resetsAt: number | null) { + if (!resetsAt) { + return null; + } + + const date = new Date(resetsAt); + + return Number.isNaN(date.getTime()) + ? null + : date.toLocaleDateString(undefined, { month: "long", day: "numeric" }); +} diff --git a/src/features/workspaces/components/ai-chat/AiChatModelPicker.tsx b/src/features/workspaces/components/ai-chat/AiChatModelPicker.tsx index bd03f0d30..64b9ebed4 100644 --- a/src/features/workspaces/components/ai-chat/AiChatModelPicker.tsx +++ b/src/features/workspaces/components/ai-chat/AiChatModelPicker.tsx @@ -1,6 +1,8 @@ +import { Link } from "@tanstack/react-router"; import { Check, ChevronUp, Waypoints } from "lucide-react"; import { useState } from "react"; +import { Badge } from "#/components/ui/badge"; import { Popover, PopoverContent, PopoverTrigger } from "#/components/ui/popover"; import { getWorkspaceAiChatModelById, @@ -10,6 +12,8 @@ import { type WorkspaceAiChatModelId, type WorkspaceAiChatModelLevel, } from "#/features/workspaces/ai/models"; +import { useIsProPlan } from "#/features/account/use-pro-plan"; +import { useWorkspaceAiTierBalances } from "#/features/workspaces/ai/use-workspace-ai-allowance"; import { ProviderLogo } from "#/features/workspaces/components/ai-chat/ProviderLogo"; import { WorkspaceToolbarTextButton } from "#/features/workspaces/components/WorkspaceToolbar"; import { cn } from "#/lib/utils"; @@ -35,6 +39,7 @@ export default function AiChatModelPicker({ modelId, onModelChange }: AiChatMode const selectedModel = getWorkspaceAiChatModelById(modelId); const detailModel = getWorkspaceAiChatModelById(previewId ?? modelId); + const premiumSpent = !useWorkspaceAiTierBalances().premium.hasBalance; // The "Auto" option lives outside the provider groups — it's ThinkEx's own // choice, not a provider's model. @@ -119,9 +124,14 @@ export default function AiChatModelPicker({ modelId, onModelChange }: AiChatMode )} > {model.name} - {isSelected ? ( -{model.description}
@@ -160,7 +178,38 @@ function ModelDetails({ model }: { model: WorkspaceAiChatModel }) {