mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-28 07:17:42 +02:00
Move inactive projects out of active workspace: - bauntown (community website) - maerchenzauber (AI story generation) - memoro (voice memo app) - news (news aggregation) - nutriphi (nutrition tracking) - reader (reading app) - uload (URL shortener) - wisekeep (AI wisdom extraction) Update CLAUDE.md documentation: - Add presi to active projects - Document archived projects section - Update workspace configuration Archived apps can be re-activated by moving back to apps/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
75 lines
1.5 KiB
Svelte
75 lines
1.5 KiB
Svelte
<script lang="ts">
|
|
import { goto } from '$app/navigation';
|
|
|
|
export let priceType: 'monthly' | 'yearly' | 'lifetime' = 'monthly';
|
|
export let className = '';
|
|
export let size: 'sm' | 'md' | 'lg' = 'md';
|
|
|
|
let loading = false;
|
|
let error = '';
|
|
|
|
const priceDisplay = {
|
|
monthly: '4,99€/Monat',
|
|
yearly: '39,99€/Jahr',
|
|
lifetime: '129,99€ einmalig',
|
|
};
|
|
|
|
const sizeClasses = {
|
|
sm: 'btn-sm',
|
|
md: '',
|
|
lg: 'btn-lg',
|
|
};
|
|
|
|
async function handleUpgrade() {
|
|
loading = true;
|
|
error = '';
|
|
|
|
try {
|
|
const response = await fetch('/api/stripe/checkout', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ priceType }),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const data = await response.json();
|
|
if (response.status === 401) {
|
|
// Not logged in, redirect to login
|
|
goto('/login?redirect=/pricing');
|
|
return;
|
|
}
|
|
throw new Error(data.error || 'Checkout fehlgeschlagen');
|
|
}
|
|
|
|
const { url } = await response.json();
|
|
|
|
if (url) {
|
|
// Redirect to Stripe Checkout
|
|
window.location.href = url;
|
|
}
|
|
} catch (err: any) {
|
|
error = err.message;
|
|
loading = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<button
|
|
onclick={handleUpgrade}
|
|
disabled={loading}
|
|
class="btn btn-primary {sizeClasses[size]} {className}"
|
|
class:loading
|
|
>
|
|
{#if loading}
|
|
<span class="loading loading-spinner"></span>
|
|
Lädt...
|
|
{:else}
|
|
Upgrade für {priceDisplay[priceType]}
|
|
{/if}
|
|
</button>
|
|
|
|
{#if error}
|
|
<div class="text-error mt-2 text-sm">{error}</div>
|
|
{/if}
|