Files
mintel.me/src/components/ContactForm/steps/ContentStep.tsx
2026-01-30 19:15:39 +01:00

185 lines
8.8 KiB
TypeScript

'use client';
import * as React from 'react';
import { FormState } from '../types';
import { Zap, AlertCircle, Minus, Plus, Settings2, BarChart3 } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { Reveal } from '../../Reveal';
interface ContentStepProps {
state: FormState;
updateState: (updates: Partial<FormState>) => void;
}
export function ContentStep({ state, updateState }: ContentStepProps) {
const toggleDontKnow = (id: string) => {
const current = state.dontKnows || [];
if (current.includes(id)) {
updateState({ dontKnows: current.filter(i => i !== id) });
} else {
updateState({ dontKnows: [...current, id] });
}
};
return (
<div className="space-y-16">
<Reveal width="100%" delay={0.1}>
<div className="flex flex-col md:flex-row items-center justify-between p-10 bg-white border border-slate-100 rounded-[3rem] gap-8">
<div className="max-w-2xl space-y-4">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-slate-50 rounded-2xl flex items-center justify-center text-black">
<Settings2 size={24} />
</div>
<h4 className="text-2xl font-bold text-slate-900">Inhalte selbst verwalten (CMS)</h4>
</div>
<p className="text-lg text-slate-500 leading-relaxed">
Ein CMS (Content Management System) ermöglicht es Ihnen, Texte, Bilder und Blogartikel selbst zu ändern, ohne programmieren zu müssen.
Ideal, wenn Sie Ihre Website aktuell halten möchten.
</p>
</div>
<div className="flex flex-col items-center md:items-end gap-6">
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
type="button"
onClick={() => toggleDontKnow('cms')}
className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${
state.dontKnows?.includes('cms') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'
}`}
>
Ich weiß es nicht
</motion.button>
<button
type="button"
onClick={() => updateState({ cmsSetup: !state.cmsSetup })}
className={`w-24 h-12 rounded-full transition-all duration-500 relative focus:outline-none ${state.cmsSetup ? 'bg-slate-900' : 'bg-slate-200'}`}
>
<motion.div
animate={{ x: state.cmsSetup ? 48 : 0 }}
transition={{ type: "spring", stiffness: 500, damping: 30 }}
className="absolute top-1.5 left-1.5 w-9 h-9 bg-white rounded-full"
/>
</button>
</div>
</div>
</Reveal>
<Reveal width="100%" delay={0.2}>
<div className="p-10 bg-slate-50 rounded-[3rem] border border-slate-100 space-y-10">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center text-black">
<BarChart3 size={24} />
</div>
<p className="text-xl font-bold text-slate-900">Wie oft ändern sich Ihre Inhalte?</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{[
{ id: 'low', label: 'Selten', desc: 'Wenige Male im Jahr.' },
{ id: 'medium', label: 'Regelmäßig', desc: 'Monatliche Updates.' },
{ id: 'high', label: 'Häufig', desc: 'Wöchentlich oder täglich.' },
].map((opt, index) => (
<motion.button
key={opt.id}
whileHover={{ y: -5 }}
whileTap={{ scale: 0.98 }}
type="button"
onClick={() => updateState({ expectedAdjustments: opt.id })}
className={`p-6 rounded-[2rem] border-2 text-left transition-all duration-300 focus:outline-none ${
state.expectedAdjustments === opt.id ? 'border-slate-900 bg-slate-900 text-white' : 'border-slate-200 bg-white hover:border-slate-400'
}`}
>
<p className={`font-bold text-lg ${state.expectedAdjustments === opt.id ? 'text-white' : 'text-slate-900'}`}>{opt.label}</p>
<p className={`text-sm mt-2 leading-relaxed ${state.expectedAdjustments === opt.id ? 'text-slate-200' : 'text-slate-500'}`}>{opt.desc}</p>
</motion.button>
))}
</div>
<AnimatePresence>
{state.expectedAdjustments === 'high' && !state.cmsSetup && (
<motion.div
initial={{ opacity: 0, height: 0, y: 20 }}
animate={{ opacity: 1, height: 'auto', y: 0 }}
exit={{ opacity: 0, height: 0, y: 20 }}
className="p-8 bg-amber-50 rounded-[2.5rem] border border-amber-100 flex gap-6 items-start"
>
<div className="w-12 h-12 bg-white rounded-xl flex items-center justify-center text-amber-600 shrink-0">
<AlertCircle size={24} />
</div>
<div className="space-y-2">
<p className="text-amber-900 text-xl font-bold">Empfehlung: CMS nutzen</p>
<p className="text-amber-800 text-base leading-relaxed max-w-3xl">
Bei täglichen oder wöchentlichen Änderungen sparen Sie mit einem CMS langfristig viel Geld, da Sie keine externen Entwickler für Inhalts-Updates benötigen.
</p>
</div>
</motion.div>
)}
</AnimatePresence>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-8">
<div className="p-8 bg-white rounded-[2.5rem] border border-slate-100 space-y-4">
<div className="flex items-center gap-3 text-slate-900 font-bold text-sm uppercase tracking-[0.2em]">
<Zap size={18} /> Vorteil CMS
</div>
<p className="text-base text-slate-500 leading-relaxed">
Volle Kontrolle über Ihre Inhalte und keine laufenden Kosten für kleine Textänderungen oder neue Blog-Beiträge.
</p>
</div>
<div className="p-8 bg-white rounded-[2.5rem] border border-slate-100 space-y-4">
<div className="flex items-center gap-3 text-slate-900 font-bold text-sm uppercase tracking-[0.2em]">
<AlertCircle size={18} /> Fokus Design
</div>
<p className="text-base text-slate-500 leading-relaxed">
Ohne CMS bleibt die technische Komplexität geringer und das Design ist maximal geschützt vor ungewollten Änderungen.
</p>
</div>
</div>
</div>
</Reveal>
<Reveal width="100%" delay={0.3}>
<div className="flex flex-col gap-8 p-10 bg-white border border-slate-100 rounded-[3rem]">
<div className="space-y-2">
<h4 className="text-2xl font-bold text-slate-900">Inhalte einpflegen</h4>
<p className="text-lg text-slate-500 leading-relaxed">
Wer kümmert sich um die erste Befüllung? Wenn ich das übernehmen soll, geben Sie hier die Anzahl der Datensätze (z.B. fertige Blogartikel oder Produkte) an.
Ansonsten übergeben wir Ihnen eine leere, aber einsatzbereite Struktur.
</p>
</div>
<div className="flex items-center gap-12 py-2">
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
type="button"
onClick={() => updateState({ newDatasets: Math.max(0, state.newDatasets - 1) })}
className="w-16 h-16 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center hover:border-slate-900 transition-colors focus:outline-none"
>
<Minus size={28} />
</motion.button>
<AnimatePresence mode="wait">
<motion.span
key={state.newDatasets}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
className="text-7xl font-bold w-20 text-center tabular-nums"
>
{state.newDatasets}
</motion.span>
</AnimatePresence>
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
type="button"
onClick={() => updateState({ newDatasets: state.newDatasets + 1 })}
className="w-16 h-16 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center hover:border-slate-900 transition-colors focus:outline-none"
>
<Plus size={28} />
</motion.button>
</div>
</div>
</Reveal>
</div>
);
}