Some checks failed
🧪 CI (QA) / 🧪 Quality Assurance (push) Failing after 1m3s
- Restructure to pnpm monorepo (site moved to apps/web) - Integrate @mintel/tsconfig, @mintel/eslint-config, @mintel/husky-config - Implement Docker service architecture (Varnish, Directus, Gatekeeper) - Setup environment-aware Gitea Actions deployment
151 lines
6.2 KiB
TypeScript
151 lines
6.2 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { FormState } from '../types';
|
|
import { Checkbox } from '../components/Checkbox';
|
|
import { Link2, Globe, Share2, Instagram, Linkedin, Facebook, Twitter, Youtube } from 'lucide-react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { Reveal } from '../../Reveal';
|
|
import { Input } from '../components/Input';
|
|
|
|
interface PresenceStepProps {
|
|
state: FormState;
|
|
updateState: (updates: Partial<FormState>) => void;
|
|
toggleItem: (list: string[], id: string) => string[];
|
|
}
|
|
|
|
export function PresenceStep({ state, updateState, toggleItem }: PresenceStepProps) {
|
|
const updateUrl = (id: string, url: string) => {
|
|
updateState({
|
|
socialMediaUrls: {
|
|
...state.socialMediaUrls,
|
|
[id]: url
|
|
}
|
|
});
|
|
};
|
|
|
|
const SOCIAL_PLATFORMS = [
|
|
{ id: 'instagram', label: 'Instagram', icon: Instagram },
|
|
{ id: 'linkedin', label: 'LinkedIn', icon: Linkedin },
|
|
{ id: 'facebook', label: 'Facebook', icon: Facebook },
|
|
{ id: 'twitter', label: 'Twitter / X', icon: Twitter },
|
|
{ id: 'youtube', label: 'YouTube', icon: Youtube },
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-16">
|
|
<Reveal width="100%" delay={0.1}>
|
|
<div className="space-y-8">
|
|
<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">
|
|
<Globe size={24} />
|
|
</div>
|
|
<h4 className="text-2xl font-bold text-slate-900">Bestehende Website</h4>
|
|
<span className="px-2 py-1 bg-slate-50 text-slate-400 text-[10px] font-bold uppercase tracking-wider rounded">Optional</span>
|
|
</div>
|
|
<Input
|
|
label="URL (falls vorhanden)"
|
|
type="url"
|
|
icon={Link2}
|
|
placeholder="https://www.beispiel.de"
|
|
value={state.existingWebsite}
|
|
onChange={(e) => updateState({ existingWebsite: e.target.value })}
|
|
/>
|
|
</div>
|
|
</Reveal>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
<Reveal width="100%" delay={0.2}>
|
|
<Input
|
|
label="Bestehende Domain"
|
|
placeholder="z.B. beispiel.de"
|
|
value={state.existingDomain}
|
|
onChange={(e) => updateState({ existingDomain: e.target.value })}
|
|
/>
|
|
</Reveal>
|
|
<Reveal width="100%" delay={0.2}>
|
|
<Input
|
|
label="Wunsch-Domain"
|
|
placeholder="z.B. neue-marke.de"
|
|
value={state.wishedDomain}
|
|
onChange={(e) => updateState({ wishedDomain: e.target.value })}
|
|
/>
|
|
</Reveal>
|
|
</div>
|
|
|
|
<Reveal width="100%" delay={0.3}>
|
|
<div className="space-y-10">
|
|
<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">
|
|
<Share2 size={24} />
|
|
</div>
|
|
<h4 className="text-2xl font-bold text-slate-900">Social Media Accounts</h4>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6">
|
|
{SOCIAL_PLATFORMS.map((platform) => {
|
|
const isSelected = state.socialMedia.includes(platform.id);
|
|
const Icon = platform.icon;
|
|
return (
|
|
<motion.button
|
|
key={platform.id}
|
|
whileHover={{ y: -8, scale: 1.02 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
type="button"
|
|
onClick={() => updateState({ socialMedia: toggleItem(state.socialMedia, platform.id) })}
|
|
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-2 transition-all duration-500 ${
|
|
isSelected ? 'border-slate-900 bg-slate-900 text-white shadow-2xl shadow-slate-400' : 'border-slate-100 bg-white text-slate-400 hover:border-slate-300 hover:shadow-xl'
|
|
}`}
|
|
>
|
|
<div className={`p-4 rounded-2xl transition-colors duration-500 ${isSelected ? 'bg-white/10 text-white' : 'bg-slate-50 text-slate-400'}`}>
|
|
<Icon size={32} />
|
|
</div>
|
|
<span className="font-bold text-base tracking-tight">{platform.label}</span>
|
|
</motion.button>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<AnimatePresence mode="popLayout">
|
|
{state.socialMedia.map((id) => {
|
|
const platform = SOCIAL_PLATFORMS.find(p => p.id === id);
|
|
if (!platform) return null;
|
|
return (
|
|
<motion.div
|
|
key={id}
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: 20 }}
|
|
layout
|
|
className="relative group"
|
|
>
|
|
<div className="absolute left-6 top-1/2 -translate-y-1/2 flex items-center gap-3 text-slate-400 group-focus-within:text-slate-900 transition-colors">
|
|
<span className="font-bold text-xs uppercase tracking-widest w-20">{platform.label}</span>
|
|
<div className="w-[1px] h-4 bg-slate-200" />
|
|
<Link2 size={18} />
|
|
</div>
|
|
<input
|
|
type="url"
|
|
placeholder={`https://${platform.id}.com/ihr-profil`}
|
|
value={state.socialMediaUrls[id] || ''}
|
|
onChange={(e) => updateUrl(id, e.target.value)}
|
|
className="w-full p-6 pl-40 bg-white border border-slate-100 rounded-[2rem] focus:outline-none focus:border-slate-900 transition-all duration-500 text-lg focus:shadow-xl"
|
|
/>
|
|
</motion.div>
|
|
);
|
|
})}
|
|
</AnimatePresence>
|
|
|
|
{state.socialMedia.length === 0 && (
|
|
<div className="p-12 border-2 border-dashed border-slate-100 rounded-[3rem] text-center">
|
|
<p className="text-slate-400 font-medium">Wählen Sie oben Ihre Kanäle aus, um die Links hinzuzufügen.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</Reveal>
|
|
</div>
|
|
);
|
|
}
|