Skip to content

Commit 414358c

Browse files
feat: Add ability to purchase provider coding plans (#3521)
1 parent cac6a06 commit 414358c

60 files changed

Lines changed: 31291 additions & 486 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.specs/coding-plans.md

Lines changed: 149 additions & 0 deletions
Large diffs are not rendered by default.

.specs/subscription-center.md

Lines changed: 132 additions & 87 deletions
Large diffs are not rendered by default.

apps/web/public/logos/minimax.svg

Lines changed: 1 addition & 0 deletions
Loading

apps/web/src/app/(app)/components/PersonalAppSidebar.tsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { Sidebar, SidebarContent, SidebarHeader } from '@/components/ui/sidebar';
44
import { useUser } from '@/hooks/useUser';
55
import { useKiloClawNavState } from '@/hooks/useKiloClaw';
6-
import { useEffect, useMemo, useState } from 'react';
6+
import { useState } from 'react';
77
import {
88
Code,
99
Coins,
@@ -197,6 +197,7 @@ export default function PersonalAppSidebar(props: React.ComponentProps<typeof Si
197197
title: string;
198198
icon: React.ElementType;
199199
url: string;
200+
badge?: string;
200201
className?: string;
201202
}> = [
202203
{
@@ -262,13 +263,16 @@ export default function PersonalAppSidebar(props: React.ComponentProps<typeof Si
262263
: 'unknown';
263264
const hasKiloClawInstance = kiloClawInstanceState === 'present';
264265
const isKiloClawPath = pathname === kiloClawBaseUrl || pathname.startsWith(kiloClawBaseUrl + '/');
265-
const [sidebarMenu, setSidebarMenu] = useState<'main' | 'kiloClaw'>(
266-
isKiloClawPath && hasKiloClawInstance ? 'kiloClaw' : 'main'
267-
);
268-
269-
useEffect(() => {
270-
setSidebarMenu(isKiloClawPath && hasKiloClawInstance ? 'kiloClaw' : 'main');
271-
}, [hasKiloClawInstance, isKiloClawPath]);
266+
const [sidebarMenuOverride, setSidebarMenuOverride] = useState<{
267+
pathname: string;
268+
menu: 'main' | 'kiloClaw';
269+
} | null>(null);
270+
const sidebarMenu =
271+
hasKiloClawInstance && sidebarMenuOverride?.pathname === pathname
272+
? sidebarMenuOverride.menu
273+
: isKiloClawPath && hasKiloClawInstance
274+
? 'kiloClaw'
275+
: 'main';
272276

273277
const kiloClawEntryItems: Array<{
274278
title: string;
@@ -282,7 +286,7 @@ export default function PersonalAppSidebar(props: React.ComponentProps<typeof Si
282286
{
283287
title: 'KiloClaw',
284288
icon: MessageSquare,
285-
onClick: () => setSidebarMenu('kiloClaw'),
289+
onClick: () => setSidebarMenuOverride({ pathname, menu: 'kiloClaw' }),
286290
isActive: isKiloClawPath,
287291
suffixIcon: ChevronRight,
288292
},
@@ -304,22 +308,18 @@ export default function PersonalAppSidebar(props: React.ComponentProps<typeof Si
304308
{
305309
title: 'Back',
306310
icon: ChevronLeft,
307-
onClick: () => setSidebarMenu('main'),
311+
onClick: () => setSidebarMenuOverride({ pathname, menu: 'main' }),
308312
},
309313
];
310314

311-
const allUrls = useMemo(
312-
() =>
313-
[
314-
kiloClawBaseUrl,
315-
...dashboardItems,
316-
...kiloClawItems,
317-
...cloudItems,
318-
...accountItems,
319-
...startItems,
320-
].map(i => (typeof i === 'string' ? i : i.url)),
321-
[kiloClawBaseUrl, dashboardItems, kiloClawItems, cloudItems, accountItems, startItems]
322-
);
315+
const allUrls = [
316+
kiloClawBaseUrl,
317+
...dashboardItems,
318+
...kiloClawItems,
319+
...cloudItems,
320+
...accountItems,
321+
...startItems,
322+
].map(i => (typeof i === 'string' ? i : i.url));
323323

324324
return (
325325
<Sidebar {...props}>
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import { PageContainer } from '@/components/layouts/PageContainer';
22
import { CodingPlanDetail } from '@/components/subscriptions/coding-plans/CodingPlanDetail';
33

4-
export default function CodingPlanSubscriptionPage() {
4+
export default async function CodingPlanSubscriptionPage({
5+
params,
6+
}: {
7+
params: Promise<{ subscriptionId: string }>;
8+
}) {
9+
const { subscriptionId } = await params;
10+
511
return (
612
<PageContainer>
7-
<CodingPlanDetail />
13+
<CodingPlanDetail key={subscriptionId} subscriptionId={subscriptionId} />
814
</PageContainer>
915
);
1016
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { PersonalSubscriptions } from '@/components/subscriptions/PersonalSubscriptions';
2+
import { CODING_PLANS_PURCHASE_ENABLED } from '@/lib/config.server';
23

34
export default function SubscriptionsPage() {
4-
return <PersonalSubscriptions />;
5+
return <PersonalSubscriptions codingPlansEnabled={CODING_PLANS_PURCHASE_ENABLED} />;
56
}

0 commit comments

Comments
 (0)