Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Failing after 1m24s
Build & Deploy / 🏗️ Build (push) Failing after 4m3s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 5s
- Refined hero sections for About, Blog, Websites, and Case Studies for a bespoke industrial entry point. - Redesigned Marker component using layered SVG paths for an organic, hand-drawn highlighter effect. - Restored technical precision in ArchitectureVisualizer with refined line thickness. - Streamlined contact page by removing generic headers and prioritizing the configurator/gateway. - Updated technical references to reflect self-hosted Gitea infrastructure. - Cleaned up unused imports and addressed linting warnings across modified pages.
211 lines
7.0 KiB
TypeScript
211 lines
7.0 KiB
TypeScript
"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-lg font-bold text-slate-900 flex items-center gap-3">
|
|
<Users size={16} 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-xl 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-lg 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-lg font-bold text-slate-900 flex items-center gap-3">
|
|
<Monitor size={16} 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={16} />,
|
|
},
|
|
{
|
|
id: "mobile",
|
|
label: "Mobile First",
|
|
icon: <Smartphone size={16} />,
|
|
},
|
|
{
|
|
id: "pwa",
|
|
label: "PWA (Installierbar)",
|
|
icon: <Globe size={16} />,
|
|
},
|
|
].map((opt) => (
|
|
<button
|
|
key={opt.id}
|
|
type="button"
|
|
onClick={() => updateState({ platformType: opt.id })}
|
|
className={`p-8 rounded-xl 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-lg font-bold text-slate-900 flex items-center gap-3">
|
|
<Shield size={16} 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-xl 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-2xl border border-slate-100 space-y-6">
|
|
<h4 className="text-lg font-bold text-slate-900 flex items-center gap-3">
|
|
<Lock size={16} 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>
|
|
);
|
|
}
|