managarten/apps-archived/memoro/apps/landing/src/components/PricingToggle.astro
Till-JS 61d181fbc2 chore: archive inactive projects to apps-archived/
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>
2025-11-29 07:03:59 +01:00

108 lines
4 KiB
Text

---
interface Props {
monthlyText: string;
yearlyText: string;
}
const { monthlyText, yearlyText } = Astro.props;
---
<div class="mb-8 text-center">
<div class="inline-flex rounded-lg bg-background-cardHover p-1">
<button
id="monthly-toggle"
class="px-4 py-2 rounded-md bg-background-card shadow-sm text-sm font-medium text-text-primary transition-all duration-200"
data-billing="monthly"
>
{monthlyText}
</button>
<button
id="yearly-toggle"
class="px-4 py-2 rounded-md text-sm font-medium text-text-secondary hover:text-text-primary transition-all duration-200"
data-billing="yearly"
>
{yearlyText}
</button>
</div>
</div>
<script>
const monthlyToggle = document.getElementById('monthly-toggle');
const yearlyToggle = document.getElementById('yearly-toggle');
function updateBilling(billingType: 'monthly' | 'yearly') {
// Update toggle button styles
if (billingType === 'monthly') {
monthlyToggle?.classList.add('bg-background-card', 'shadow-sm', 'text-text-primary');
monthlyToggle?.classList.remove('text-text-secondary');
yearlyToggle?.classList.remove('bg-background-card', 'shadow-sm', 'text-text-primary');
yearlyToggle?.classList.add('text-text-secondary');
} else {
yearlyToggle?.classList.add('bg-background-card', 'shadow-sm', 'text-text-primary');
yearlyToggle?.classList.remove('text-text-secondary');
monthlyToggle?.classList.remove('bg-background-card', 'shadow-sm', 'text-text-primary');
monthlyToggle?.classList.add('text-text-secondary');
}
// Update all pricing elements
const priceElements = document.querySelectorAll('[data-price-monthly][data-price-yearly]');
priceElements.forEach((element) => {
const monthlyPrice = element.getAttribute('data-price-monthly');
const yearlyPrice = element.getAttribute('data-price-yearly');
const priceUnitElement = element.nextElementSibling;
const yearlyBreakdownElement = element
.closest('.price-container')
?.querySelector('.yearly-breakdown');
if (billingType === 'monthly') {
element.textContent =
monthlyPrice === '0'
? element.getAttribute('data-free-text') || 'Kostenlos'
: `${monthlyPrice}€`;
if (priceUnitElement?.classList.contains('price-unit')) {
priceUnitElement.textContent = '/ Monat';
}
yearlyBreakdownElement?.classList.add('hidden');
} else {
const yearlyPriceNum = parseFloat(yearlyPrice || '0');
element.textContent =
yearlyPrice === '0'
? element.getAttribute('data-free-text') || 'Kostenlos'
: `${yearlyPrice}€`;
if (priceUnitElement?.classList.contains('price-unit')) {
priceUnitElement.textContent = '/ Jahr';
}
yearlyBreakdownElement?.classList.remove('hidden');
// Update yearly breakdown text if it exists
if (yearlyBreakdownElement && monthlyPrice !== '0') {
const monthlyPriceNum = parseFloat(monthlyPrice || '0');
const monthlySavings = (monthlyPriceNum * 12 - yearlyPriceNum).toFixed(2);
const percentSavings = Math.round((monthlySavings / (monthlyPriceNum * 12)) * 100);
const isGerman = document.documentElement.lang === 'de';
yearlyBreakdownElement.textContent = isGerman
? `Spare ${monthlySavings}€ (${percentSavings}%)`
: `Save €${monthlySavings} (${percentSavings}%)`;
}
}
});
// Update comparison table prices
const comparisonPrices = document.querySelectorAll(
'[data-comparison-monthly][data-comparison-yearly]'
);
comparisonPrices.forEach((element) => {
const monthlyPrice = element.getAttribute('data-comparison-monthly');
const yearlyPrice = element.getAttribute('data-comparison-yearly');
if (billingType === 'monthly') {
element.textContent = monthlyPrice === '0' ? '✓' : `${monthlyPrice}€ / Monat`;
} else {
element.textContent = yearlyPrice === '0' ? '✓' : `${yearlyPrice}€ / Jahr`;
}
});
}
monthlyToggle?.addEventListener('click', () => updateBilling('monthly'));
yearlyToggle?.addEventListener('click', () => updateBilling('yearly'));
</script>