feat: Polar license key integration and dashboard UI improvements

- Add license activation flow: server validates/activates keys via Polar SDK
- Auto-activate from Polar checkout redirect (checkout_id in URL)
- Gate dashboard behind license activation (redirect to /activate if no plan)
- Preserve redirect URL through login flow for post-purchase activation
- Show plan status badge in sidebar and overview page
- Add account section to settings (email, plan, license key)
- Add svelte-sonner toasts with custom black theme and iconify icons
- Improve validation messages across all forms
- Update API key prefix to droidclaw_
- Add cursor pointer globally for clickable elements
- Support Polar sandbox mode via POLAR_SANDBOX env flag
This commit is contained in:
Sanju Sivalingam
2026-02-18 22:11:37 +05:30
parent 5aace17096
commit b34088ceb7
28 changed files with 1555 additions and 87 deletions

View File

@@ -1,12 +1,38 @@
import { redirect } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { user as userTable } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = async ({ locals }) => {
export const load: LayoutServerLoad = async ({ locals, url }) => {
if (!locals.user) {
redirect(307, '/login');
redirect(307, `/login?redirect=${encodeURIComponent(url.pathname)}`);
}
// Check plan status (skip for the activate page itself)
if (!url.pathname.startsWith('/dashboard/activate')) {
const rows = await db
.select({ plan: userTable.plan, polarLicenseKey: userTable.polarLicenseKey })
.from(userTable)
.where(eq(userTable.id, locals.user.id))
.limit(1);
if (!rows[0]?.plan) {
redirect(307, '/dashboard/activate');
}
return {
user: locals.user,
sessionToken: locals.session?.token ?? '',
plan: rows[0].plan,
licenseKey: rows[0].polarLicenseKey
};
}
return {
user: locals.user,
sessionToken: locals.session?.token ?? ''
sessionToken: locals.session?.token ?? '',
plan: null,
licenseKey: null
};
};