chore: overhaul infrastructure and integrate @mintel packages
Some checks failed
🧪 CI (QA) / 🧪 Quality Assurance (push) Failing after 1m3s
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
This commit is contained in:
144
apps/web/src/components/ContactForm/steps/WebAppStep.tsx
Normal file
144
apps/web/src/components/ContactForm/steps/WebAppStep.tsx
Normal file
@@ -0,0 +1,144 @@
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import { FormState } from '../types';
|
||||
import { Users, Shield, Monitor, Smartphone, Globe, Lock } from 'lucide-react';
|
||||
|
||||
interface WebAppStepProps {
|
||||
state: FormState;
|
||||
updateState: (updates: Partial<FormState>) => void;
|
||||
}
|
||||
|
||||
export function WebAppStep({ state, updateState }: WebAppStepProps) {
|
||||
const toggleUserRole = (role: string) => {
|
||||
const current = state.userRoles || [];
|
||||
const next = current.includes(role)
|
||||
? current.filter(r => r !== role)
|
||||
: [...current, role];
|
||||
updateState({ userRoles: next });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
{/* Target Audience */}
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<h4 className="text-2xl font-bold text-slate-900 flex items-center gap-3">
|
||||
<Users size={24} className="text-black" /> Zielgruppe
|
||||
</h4>
|
||||
<span className="px-2 py-1 bg-slate-100 text-slate-500 text-[10px] font-bold uppercase tracking-wider rounded">Fokus</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{[
|
||||
{ id: 'internal', label: 'Internes Tool', desc: 'Für Mitarbeiter & Prozesse.' },
|
||||
{ id: 'external', label: 'Kunden-Portal', desc: 'Für Ihre Endnutzer (B2B/B2C).' },
|
||||
].map(opt => (
|
||||
<button
|
||||
key={opt.id}
|
||||
type="button"
|
||||
onClick={() => updateState({ targetAudience: opt.id })}
|
||||
className={`p-8 rounded-[2rem] border-2 text-left transition-all ${
|
||||
state.targetAudience === opt.id ? 'border-slate-900 bg-slate-900 text-white' : 'border-slate-100 bg-white hover:border-slate-200'
|
||||
}`}
|
||||
>
|
||||
<p className="text-xl font-bold">{opt.label}</p>
|
||||
<p className={`text-base mt-2 ${state.targetAudience === opt.id ? 'text-slate-200' : 'text-slate-500'}`}>{opt.desc}</p>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* User Roles */}
|
||||
<div className="space-y-6">
|
||||
<h4 className="text-2xl font-bold text-slate-900">Benutzerrollen</h4>
|
||||
<p className="text-lg text-slate-500">Wer wird das System nutzen?</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{['Administratoren', 'Manager', 'Standard-Nutzer', 'Gäste', 'Read-Only'].map(role => (
|
||||
<button
|
||||
key={role}
|
||||
type="button"
|
||||
onClick={() => toggleUserRole(role)}
|
||||
className={`px-8 py-4 rounded-full border-2 font-bold text-base transition-all ${
|
||||
(state.userRoles || []).includes(role) ? 'border-slate-900 bg-slate-900 text-white' : 'border-slate-100 bg-white hover:border-slate-200'
|
||||
}`}
|
||||
>
|
||||
{role}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Platform Type */}
|
||||
<div className="space-y-6">
|
||||
<h4 className="text-2xl font-bold text-slate-900 flex items-center gap-3">
|
||||
<Monitor size={24} className="text-black" /> Plattform-Fokus
|
||||
</h4>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{[
|
||||
{ id: 'desktop', label: 'Desktop First', icon: <Monitor size={24} /> },
|
||||
{ id: 'mobile', label: 'Mobile First', icon: <Smartphone size={24} /> },
|
||||
{ id: 'pwa', label: 'PWA (Installierbar)', icon: <Globe size={24} /> },
|
||||
].map(opt => (
|
||||
<button
|
||||
key={opt.id}
|
||||
type="button"
|
||||
onClick={() => updateState({ platformType: opt.id })}
|
||||
className={`p-8 rounded-[2rem] border-2 flex flex-col items-center gap-4 transition-all ${
|
||||
state.platformType === opt.id ? 'border-slate-900 bg-slate-900 text-white' : 'border-slate-100 bg-white hover:border-slate-200'
|
||||
}`}
|
||||
>
|
||||
<div className={state.platformType === opt.id ? 'text-white' : 'text-black'}>
|
||||
{opt.icon}
|
||||
</div>
|
||||
<span className="font-bold text-lg">{opt.label}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Data Sensitivity */}
|
||||
<div className="space-y-6">
|
||||
<h4 className="text-2xl font-bold text-slate-900 flex items-center gap-3">
|
||||
<Shield size={24} className="text-black" /> Datensicherheit
|
||||
</h4>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{[
|
||||
{ id: 'standard', label: 'Standard', desc: 'Normale Nutzerdaten & Profile.' },
|
||||
{ id: 'high', label: 'Sensibel', desc: 'Finanzdaten, Gesundheitsdaten oder DSGVO-kritisch.' },
|
||||
].map(opt => (
|
||||
<button
|
||||
key={opt.id}
|
||||
type="button"
|
||||
onClick={() => updateState({ dataSensitivity: opt.id })}
|
||||
className={`p-8 rounded-[2rem] border-2 text-left transition-all ${
|
||||
state.dataSensitivity === opt.id ? 'border-slate-900 bg-slate-900 text-white' : 'border-slate-100 bg-white hover:border-slate-200'
|
||||
}`}
|
||||
>
|
||||
<p className="text-xl font-bold">{opt.label}</p>
|
||||
<p className={`text-base mt-2 ${state.dataSensitivity === opt.id ? 'text-slate-200' : 'text-slate-500'}`}>{opt.desc}</p>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Authentication */}
|
||||
<div className="p-10 bg-slate-50 rounded-[3rem] border border-slate-100 space-y-6">
|
||||
<h4 className="text-2xl font-bold text-slate-900 flex items-center gap-3">
|
||||
<Lock size={24} className="text-black" /> Authentifizierung
|
||||
</h4>
|
||||
<p className="text-lg text-slate-500">Wie sollen sich Nutzer anmelden?</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{['E-Mail / Passwort', 'Social Login', 'SSO / SAML', '2FA / MFA', 'Magic Links'].map(method => (
|
||||
<div
|
||||
key={method}
|
||||
className="px-8 py-4 rounded-full border-2 border-white bg-white font-bold text-base text-slate-400"
|
||||
>
|
||||
{method}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-xs text-slate-400 italic">Details zur Authentifizierung besprechen wir im Erstgespräch.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user