@moontra/moonui-pro
Version:
Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components
142 lines (120 loc) • 3.75 kB
text/typescript
// Pro Access Hook
// Kullanıcının pro componentlere erişim durumunu kontrol eder
import React from 'react'
import { useSession } from 'next-auth/react'
import { useQuery } from '@tanstack/react-query'
import { getComponentAccess } from '@/lib/component-metadata'
interface UserSubscription {
userId: string
plan: 'free' | 'pro_monthly' | 'pro_annual' | 'pro_lifetime'
status: 'active' | 'expired' | 'cancelled' | 'trial'
expiresAt: Date | null // lifetime için null
createdAt: Date
updatedAt: Date
}
interface ProAccessStatus {
hasProAccess: boolean
subscription: UserSubscription | null | undefined
isLoading: boolean
error: Error | null
daysUntilExpiry: number | null
}
// Subscription durumunu API'den çek
async function fetchSubscriptionStatus(): Promise<UserSubscription | null> {
const response = await fetch('/api/user/subscription-status')
if (!response.ok) {
throw new Error('Subscription status fetch failed')
}
const data = await response.json()
return data.subscription
}
// Pro erişim durumunu hesapla
function calculateProAccess(subscription: UserSubscription | null | undefined): {
hasProAccess: boolean
daysUntilExpiry: number | null
} {
if (!subscription) {
return { hasProAccess: false, daysUntilExpiry: null }
}
// Lifetime üyelik
if (subscription.plan === 'pro_lifetime') {
return { hasProAccess: true, daysUntilExpiry: null }
}
// Aktif olmayan subscription
if (subscription.status !== 'active') {
return { hasProAccess: false, daysUntilExpiry: null }
}
// Süre kontrolü
if (subscription.expiresAt) {
const now = new Date()
const expiryDate = new Date(subscription.expiresAt)
const daysUntilExpiry = Math.ceil((expiryDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))
return {
hasProAccess: daysUntilExpiry > 0,
daysUntilExpiry: daysUntilExpiry > 0 ? daysUntilExpiry : 0
}
}
return { hasProAccess: false, daysUntilExpiry: null }
}
export function useProAccess(): ProAccessStatus {
const { data: session, status } = useSession()
const {
data: subscription,
isLoading,
error
} = useQuery({
queryKey: ['subscription-status', session?.user?.id],
queryFn: fetchSubscriptionStatus,
enabled: !!session?.user?.id && status === 'authenticated',
staleTime: 5 * 60 * 1000, // 5 dakika cache
refetchInterval: 10 * 60 * 1000, // 10 dakikada bir otomatik refresh
})
const { hasProAccess, daysUntilExpiry } = calculateProAccess(subscription)
return {
hasProAccess,
subscription,
isLoading: status === 'loading' || isLoading,
error: error as Error | null,
daysUntilExpiry
}
}
// Component erişim kontrolü için helper hook
export function useComponentAccess(componentId: string) {
const { hasProAccess, isLoading } = useProAccess()
const access = React.useMemo(() => {
return getComponentAccess(componentId, hasProAccess ? 'pro' : 'free')
}, [componentId, hasProAccess])
return {
...access,
isLoading,
canUse: access.access === 'unlocked',
isLocked: access.access === 'locked'
}
}
// Subscription durumu için utility functions
export function getSubscriptionDisplayName(plan: string): string {
switch (plan) {
case 'pro_monthly':
return 'Pro Monthly'
case 'pro_annual':
return 'Pro Annual'
case 'pro_lifetime':
return 'Pro Lifetime'
default:
return 'Free'
}
}
export function getSubscriptionColor(status: string): string {
switch (status) {
case 'active':
return 'green'
case 'trial':
return 'blue'
case 'expired':
return 'red'
case 'cancelled':
return 'gray'
default:
return 'gray'
}
}