Update marketing packages testimonials and demo
This commit is contained in:
@@ -23,6 +23,7 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
const locale = useLocale();
|
||||
const embedUrl = demoToken ? `/e/${demoToken}` : '/e/demo?demo=1';
|
||||
const [isDemoOpen, setIsDemoOpen] = React.useState(false);
|
||||
const demoOpenLabel = t('labels.demoOpenOverlay', locale === 'en' ? 'Open demo overlay' : 'Demo im Overlay öffnen');
|
||||
|
||||
const demo = t('demo_page', { returnObjects: true }) as {
|
||||
title: string;
|
||||
@@ -35,17 +36,6 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
};
|
||||
const demoFeatures = Array.isArray(demo.features) ? demo.features : [];
|
||||
const handleOpenDemo = (): void => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const isMobile = window.matchMedia('(max-width: 768px)').matches;
|
||||
|
||||
if (isMobile) {
|
||||
window.open(embedUrl, '_blank', 'noopener,noreferrer');
|
||||
return;
|
||||
}
|
||||
|
||||
setIsDemoOpen(true);
|
||||
};
|
||||
|
||||
@@ -84,18 +74,28 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
<div className="flex-1">
|
||||
{embedUrl ? (
|
||||
<>
|
||||
<div className="relative mx-auto w-full max-w-[300px] rounded-[2.5rem] border border-gray-200 bg-gray-900 px-3 pb-3 pt-4 shadow-2xl sm:max-w-[340px] md:max-w-[380px] dark:border-gray-700">
|
||||
<div className="relative mx-auto w-[min(92vw,calc(75dvh*10/14))] aspect-[10/14] rounded-[2.5rem] border border-gray-200 bg-gray-900 px-3 pb-3 pt-4 shadow-2xl dark:border-gray-700">
|
||||
<div
|
||||
className="absolute top-2 left-1/2 h-1.5 w-16 -translate-x-1/2 rounded-full bg-gray-300 dark:bg-gray-600"
|
||||
aria-hidden
|
||||
/>
|
||||
<iframe
|
||||
title="Demo der Fotospiel App"
|
||||
src={embedUrl}
|
||||
className="aspect-[9/19] w-full rounded-[1.75rem] border-0 bg-white shadow-inner dark:bg-gray-950"
|
||||
loading="lazy"
|
||||
sandbox="allow-scripts allow-same-origin allow-forms"
|
||||
/>
|
||||
<div className="h-full w-full overflow-hidden rounded-[1.75rem] bg-white shadow-inner dark:bg-gray-950">
|
||||
{isDemoOpen ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-2 bg-gradient-to-br from-pink-200 via-white to-white px-4 text-center dark:from-pink-900/40 dark:via-gray-950 dark:to-gray-950">
|
||||
<p className="text-xs uppercase tracking-[0.2em] text-pink-600/70 dark:text-pink-300/70">Live Demo</p>
|
||||
<p className="text-sm font-semibold text-gray-900 dark:text-gray-100">Demo läuft im Overlay</p>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-300">Schließe das Overlay, um hier weiterzumachen.</p>
|
||||
</div>
|
||||
) : (
|
||||
<iframe
|
||||
title="Demo der Fotospiel App"
|
||||
src={embedUrl}
|
||||
className="h-full w-full border-0 bg-white dark:bg-gray-950"
|
||||
loading="lazy"
|
||||
sandbox="allow-scripts allow-same-origin allow-forms"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex flex-col items-center gap-1 text-center">
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{demo.iframeNote}</p>
|
||||
@@ -105,7 +105,7 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
className="text-pink-600 hover:text-pink-700 dark:text-pink-300"
|
||||
onClick={handleOpenDemo}
|
||||
>
|
||||
{demo.openFull}
|
||||
{demoOpenLabel}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
@@ -174,8 +174,8 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
</div>
|
||||
</section>
|
||||
<Dialog open={isDemoOpen} onOpenChange={setIsDemoOpen}>
|
||||
<DialogContent className="w-[388px] max-w-[90vw] border-0 bg-transparent p-0 shadow-none">
|
||||
<div className="relative w-full rounded-[2.5rem] border border-gray-200 bg-gray-900 p-3 shadow-2xl dark:border-gray-700">
|
||||
<DialogContent className="flex items-center justify-center border-0 bg-transparent p-0 shadow-none">
|
||||
<div className="relative h-[75dvh] w-auto max-w-[92vw] aspect-[10/14] rounded-[2.5rem] border border-gray-200 bg-gray-900 p-3 shadow-2xl dark:border-gray-700">
|
||||
<div
|
||||
className="absolute top-2 left-1/2 h-1.5 w-16 -translate-x-1/2 rounded-full bg-gray-300 dark:bg-gray-600"
|
||||
aria-hidden
|
||||
@@ -183,7 +183,7 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
<iframe
|
||||
title="Demo der Fotospiel App"
|
||||
src={embedUrl}
|
||||
className="aspect-[9/16] w-full rounded-[1.75rem] border-0 bg-white shadow-inner dark:bg-gray-950"
|
||||
className="h-full w-full rounded-[1.75rem] border-0 bg-white shadow-inner dark:bg-gray-950"
|
||||
loading="lazy"
|
||||
sandbox="allow-scripts allow-same-origin allow-forms"
|
||||
/>
|
||||
|
||||
@@ -431,11 +431,33 @@ const Packages: React.FC<PackagesProps> = ({ endcustomerPackages, resellerPackag
|
||||
}, [orderedResellerPackages, highlightResellerId]);
|
||||
|
||||
|
||||
const testimonials = [
|
||||
{ name: tCommon('testimonials.anna.name'), text: t('packages.testimonials.anna'), rating: 5 },
|
||||
{ name: tCommon('testimonials.max.name'), text: t('packages.testimonials.max'), rating: 5 },
|
||||
{ name: tCommon('testimonials.lisa.name'), text: t('packages.testimonials.lisa'), rating: 5 },
|
||||
];
|
||||
const testimonialsByPackage = useMemo(() => {
|
||||
const raw = t('packages.testimonials', { returnObjects: true });
|
||||
|
||||
if (!raw || typeof raw !== 'object') {
|
||||
return {};
|
||||
}
|
||||
|
||||
return raw as Record<string, { name?: string; text?: string; rating?: number }[]>;
|
||||
}, [locale, t]);
|
||||
|
||||
const testimonials = useMemo(() => {
|
||||
if (!selectedPackage) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const entries = testimonialsByPackage[selectedPackage.slug] ?? testimonialsByPackage.default ?? [];
|
||||
|
||||
if (!Array.isArray(entries)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return entries.map((entry) => ({
|
||||
name: entry.name ?? '',
|
||||
text: entry.text ?? '',
|
||||
rating: entry.rating ?? 4,
|
||||
}));
|
||||
}, [selectedPackage, testimonialsByPackage]);
|
||||
|
||||
const renderDetailBody = (wrapperClass: string) => {
|
||||
if (!selectedPackage) {
|
||||
@@ -1104,7 +1126,7 @@ const PackageDetailGrid: React.FC<PackageDetailGridProps> = ({
|
||||
</div>
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
|
||||
{[
|
||||
{ title: t('packages.faq_free'), body: t('packages.faq_free_desc') },
|
||||
{ title: t('packages.faq_branding'), body: t('packages.faq_branding_desc') },
|
||||
{ title: t('packages.faq_upgrade'), body: t('packages.faq_upgrade_desc') },
|
||||
{ title: t('packages.faq_reseller'), body: t('packages.faq_reseller_desc') },
|
||||
{ title: t('packages.faq_payment'), body: t('packages.faq_payment_desc') },
|
||||
|
||||
Reference in New Issue
Block a user