Final Feature 9c #10
86
frontend/src/components/TrialBanner.jsx
Normal file
86
frontend/src/components/TrialBanner.jsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export default function TrialBanner({ profile }) {
|
||||
const [daysLeft, setDaysLeft] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!profile?.trial_ends_at) {
|
||||
setDaysLeft(null)
|
||||
return
|
||||
}
|
||||
|
||||
const trialEnd = new Date(profile.trial_ends_at)
|
||||
const now = new Date()
|
||||
const diff = trialEnd - now
|
||||
const days = Math.ceil(diff / (1000 * 60 * 60 * 24))
|
||||
|
||||
setDaysLeft(days)
|
||||
}, [profile])
|
||||
|
||||
// No trial or trial ended
|
||||
if (daysLeft === null || daysLeft <= 0) return null
|
||||
|
||||
// Determine severity
|
||||
const isUrgent = daysLeft <= 3
|
||||
const isWarning = daysLeft <= 7
|
||||
|
||||
const bgColor = isUrgent ? '#FCEBEB' : isWarning ? '#FFF4E6' : 'var(--accent-light)'
|
||||
const borderColor = isUrgent ? '#D85A30' : isWarning ? '#F59E0B' : 'var(--accent)'
|
||||
const textColor = isUrgent ? '#D85A30' : isWarning ? '#D97706' : 'var(--accent-dark)'
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
background: bgColor,
|
||||
border: `2px solid ${borderColor}`,
|
||||
borderRadius: 12,
|
||||
padding: '16px 20px',
|
||||
marginBottom: 20,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
flexWrap: 'wrap',
|
||||
gap: 12
|
||||
}}>
|
||||
<div style={{flex: 1, minWidth: 200}}>
|
||||
<div style={{
|
||||
fontWeight: 700,
|
||||
fontSize: 15,
|
||||
color: textColor,
|
||||
marginBottom: 4
|
||||
}}>
|
||||
{isUrgent && '⚠️ '}
|
||||
Deine Trial endet {daysLeft === 1 ? 'morgen' : `in ${daysLeft} Tagen`}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: 13,
|
||||
color: 'var(--text2)',
|
||||
lineHeight: 1.4
|
||||
}}>
|
||||
{isUrgent
|
||||
? 'Upgrade jetzt um weiterhin alle Features nutzen zu können'
|
||||
: 'Wähle ein Abo um unbegrenzt Zugriff zu erhalten'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
to="/settings?tab=subscription"
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
borderRadius: 8,
|
||||
background: isUrgent ? '#D85A30' : 'var(--accent)',
|
||||
color: 'white',
|
||||
fontWeight: 600,
|
||||
fontSize: 14,
|
||||
textDecoration: 'none',
|
||||
whiteSpace: 'nowrap',
|
||||
border: 'none',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
{isUrgent ? 'Jetzt upgraden' : 'Abo wählen'}
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import {
|
|||
import { api } from '../utils/api'
|
||||
import { useProfile } from '../context/ProfileContext'
|
||||
import { getBfCategory } from '../utils/calc'
|
||||
import TrialBanner from '../components/TrialBanner'
|
||||
import { getInterpretation, getStatusColor, getStatusBg } from '../utils/interpret'
|
||||
import Markdown from '../utils/Markdown'
|
||||
import dayjs from 'dayjs'
|
||||
|
|
@ -315,6 +316,9 @@ export default function Dashboard() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Trial Banner */}
|
||||
<TrialBanner profile={activeProfile}/>
|
||||
|
||||
{!hasAnyData && (
|
||||
<div className="empty-state">
|
||||
<h3>Willkommen bei Mitai Jinkendo!</h3>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user